Changeset 4138


Ignore:
Timestamp:
Dec 13, 2007, 12:55:48 AM (14 years ago)
Author:
charles
Message:

try merging joshe's BSD implementation of tr_getDefaultRoute() into libnatpmp's getgateway()

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/third-party/libnatpmp/getgateway.c

    r4101 r4138  
    1414 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    1515 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
     16
    1617#include <stdio.h>
     18#include <stdlib.h>
     19#include <string.h>
    1720#include <ctype.h>
    1821#include <netinet/in.h>
    1922#include <sys/param.h>
    20 #if defined(BSD) || defined(__APPLE__)
    21 #include <stdlib.h>
    22 #include <sys/sysctl.h>
    23 #include <sys/socket.h>
    24 #include <net/route.h>
    25 #endif
    2623#include "getgateway.h"
    2724
     
    6360#if defined(BSD) || defined(__APPLE__)
    6461
    65 #define ROUNDUP(a) \
    66         ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
    67 
    68 int getdefaultgateway(in_addr_t * addr)
    69 {
    70         int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET,
    71                      NET_RT_DUMP, 0, 0/*tableid*/};
    72         size_t l;
    73         char * buf, * p;
    74         struct rt_msghdr * rt;
    75         struct sockaddr * sa;
    76         struct sockaddr * sa_tab[RTAX_MAX];
    77         int i;
    78         int r = -1;
    79         if(sysctl(mib, sizeof(mib)/sizeof(int), 0, &l, 0, 0) < 0) {
    80                 return -1;
    81         }
    82         if(l>0) {
    83                 buf = malloc(l);
    84                 if(sysctl(mib, sizeof(mib)/sizeof(int), buf, &l, 0, 0) < 0) {
    85                         return -1;
    86                 }
    87                 for(p=buf; p<buf+l; p+=rt->rtm_msglen) {
    88                         rt = (struct rt_msghdr *)p;
    89                         sa = (struct sockaddr *)(rt + 1);
    90                         for(i=0; i<RTAX_MAX; i++) {
    91                                 if(rt->rtm_addrs & (1 << i)) {
    92                                         sa_tab[i] = sa;
    93                                         sa = (struct sockaddr *)((char *)sa + ROUNDUP(sa->sa_len));
    94                                 } else {
    95                                         sa_tab[i] = NULL;
    96                                 }
    97                         }
    98                         if( ((rt->rtm_addrs & (RTA_DST|RTA_GATEWAY)) == (RTA_DST|RTA_GATEWAY))
    99               && sa_tab[RTAX_DST]->sa_family == AF_INET
    100               && sa_tab[RTAX_GATEWAY]->sa_family == AF_INET) {
    101                                 if(((struct sockaddr_in *)sa_tab[RTAX_DST])->sin_addr.s_addr == 0) {
    102                                         *addr = ((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr;
    103                                         r = 0;
    104                                 }
    105                         }
    106                 }
    107                 free(buf);
    108         }
    109         return r;
    110 }
     62#include <errno.h>
     63#include <stdlib.h>
     64#include <sys/types.h>
     65#include <sys/socket.h>
     66#include <netinet/in.h>
     67#include <arpa/inet.h>
     68#include <netinet/in.h> /* struct in_addr */
     69#include <sys/sysctl.h>
     70#include <net/route.h>
     71
     72#ifndef SA_SIZE
     73#define ROUNDUP( a, size ) \
     74    ( ( (a) & ( (size) - 1 ) ) ? ( 1 + ( (a) | ( (size) - 1 ) ) ) : (a) )
     75#define SA_SIZE( sap ) \
     76    ( sap->sa_len ? ROUNDUP( (sap)->sa_len, sizeof( u_long ) ) : \
     77                    sizeof( u_long ) )
     78#endif /* !SA_SIZE */
     79#define NEXT_SA( sap ) \
     80    (struct sockaddr *) ( (caddr_t) (sap) + ( SA_SIZE( (sap) ) ) )
     81
     82static uint8_t *
     83getroute( int * buflen )
     84{
     85    int     mib[6];
     86    size_t  len;
     87    uint8_t * buf;
     88
     89    mib[0] = CTL_NET;
     90    mib[1] = PF_ROUTE;
     91    mib[2] = 0;
     92    mib[3] = AF_INET;
     93    mib[4] = NET_RT_FLAGS;
     94    mib[5] = RTF_GATEWAY;
     95
     96    if( sysctl( mib, 6, NULL, &len, NULL, 0 ) )
     97    {
     98        if( ENOENT != errno )
     99        {
     100            fprintf(stderr, "sysctl net.route.0.inet.flags.gateway failed (%s)",
     101                    strerror( errno ) );
     102        }
     103        *buflen = 0;
     104        return NULL;
     105    }
     106
     107    buf = malloc( len );
     108    if( NULL == buf )
     109    {
     110        *buflen = 0;
     111        return NULL;
     112    }
     113
     114    if( sysctl( mib, 6, buf, &len, NULL, 0 ) )
     115    {
     116        fprintf(stderr, "sysctl net.route.0.inet.flags.gateway failed (%s)",
     117                strerror( errno ) );
     118        free( buf );
     119        *buflen = 0;
     120        return NULL;
     121    }
     122
     123    *buflen = len;
     124
     125    return buf;
     126}
     127
     128static int
     129parseroutes( uint8_t * buf, int len, struct in_addr * addr )
     130{
     131    uint8_t            * end;
     132    struct rt_msghdr   * rtm;
     133    struct sockaddr    * sa;
     134    struct sockaddr_in * sin;
     135    int                  ii;
     136    struct in_addr       dest, gw;
     137
     138    end = buf + len;
     139    while( end > buf + sizeof( *rtm ) )
     140    {
     141        rtm = (struct rt_msghdr *) buf;
     142        buf += rtm->rtm_msglen;
     143        if( end >= buf )
     144        {
     145            dest.s_addr = INADDR_NONE;
     146            gw.s_addr   = INADDR_NONE;
     147            sa = (struct sockaddr *) ( rtm + 1 );
     148
     149            for( ii = 0; ii < RTAX_MAX && (uint8_t *) sa < buf; ii++ )
     150            {
     151                if( buf < (uint8_t *) NEXT_SA( sa ) )
     152                {
     153                    break;
     154                }
     155
     156                if( rtm->rtm_addrs & ( 1 << ii ) )
     157                {
     158                    if( AF_INET == sa->sa_family )
     159                    {
     160                        sin = (struct sockaddr_in *) sa;
     161                        switch( ii )
     162                        {
     163                            case RTAX_DST:
     164                                dest = sin->sin_addr;
     165                                break;
     166                            case RTAX_GATEWAY:
     167                                gw = sin->sin_addr;
     168                                break;
     169                        }
     170                    }
     171                    sa = NEXT_SA( sa );
     172                }
     173            }
     174
     175            if( INADDR_ANY == dest.s_addr && INADDR_NONE != gw.s_addr )
     176            {
     177                *addr = gw;
     178                return 0;
     179            }
     180        }
     181    }
     182
     183    return 1;
     184}
     185
     186int
     187getdefaultgateway( struct in_addr * addr )
     188{
     189    uint8_t * buf;
     190    int len;
     191
     192    buf = getroute( &len );
     193    if( NULL == buf )
     194    {
     195        fprintf(stderr, "failed to get default route (BSD)" );
     196        return 1;
     197    }
     198
     199    len = parseroutes( buf, len, addr );
     200    free( buf );
     201
     202    return len;
     203}
     204
    111205#endif
Note: See TracChangeset for help on using the changeset viewer.