Annotation of embedaddon/hping2/getifname.c, revision 1.1.1.1

1.1       misho       1: /* getifname.c -- network interface handling
                      2:  * Copyright(C) 1999,2000,2001 Salvatore Sanfilippo <antirez@invece.org>
                      3:  * Copyright(C) 2001 by Nicolas Jombart <Nicolas.Jombart@hsc.fr>
                      4:  * This code is under the GPL license */
                      5: 
                      6: /* BSD support thanks to Nicolas Jombart <Nicolas.Jombart@hsc.fr> */
                      7: 
                      8: #include <stdio.h>             /* perror */
                      9: #include <stdlib.h>
                     10: #include <string.h>
                     11: #include <sys/ioctl.h>
                     12: #include <sys/types.h>
                     13: #include <sys/socket.h>
                     14: #include <netinet/in.h>                /* struct sockaddr_in */
                     15: #include <arpa/inet.h>         /* inet_ntoa */
                     16: #include <net/if.h>
                     17: #include <unistd.h>            /* close */
                     18: 
                     19: #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || \
                     20:     defined(__bsdi__) || defined(__APPLE__)
                     21: #include <stdlib.h>
                     22: #include <ifaddrs.h>
                     23: #include <net/route.h>
                     24: #endif /* defined(__*BSD__) */
                     25: 
                     26: #include "hping2.h"
                     27: #include "globals.h"
                     28: 
                     29: #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && \
                     30:     !defined(__linux__) && !defined(__sun__) && !defined(__bsdi__) && \
                     31:     !defined(__APPLE__)
                     32: #error Sorry, interface code not implemented.
                     33: #endif
                     34: 
                     35: #ifdef __sun__
                     36: #include <sys/sockio.h>
                     37: #include <net/route.h>
                     38: #include <net/if_dl.h>
                     39: #endif
                     40: 
                     41: static int get_output_if(struct sockaddr_in *dest, struct sockaddr_in *ifip);
                     42: 
                     43: #if (defined OSTYPE_LINUX) || (defined __sun__)
                     44: int get_if_name(void)
                     45: {
                     46:        int fd;
                     47:        struct ifconf   ifc;
                     48:        struct ifreq    ibuf[16],
                     49:                        ifr,
                     50:                        *ifrp,
                     51:                        *ifend;
                     52:        struct sockaddr_in sa;
                     53:        struct sockaddr_in output_if_addr;
                     54:        int known_output_if = 0;
                     55: 
                     56:        /* Try to get the output interface address according to
                     57:         * the OS routing table */
                     58:        if (ifname[0] == '\0') {
                     59:                if (get_output_if(&remote, &output_if_addr) == 0) {
                     60:                        known_output_if = 1;
                     61:                        if (opt_debug)
                     62:                                printf("DEBUG: Output interface address: %s\n",
                     63:                                        inet_ntoa(sa.sin_addr));
                     64:                } else {
                     65:                        fprintf(stderr, "Warning: Unable to guess the output "
                     66:                                        "interface\n");
                     67:                }
                     68:        }
                     69: 
                     70:        if ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
                     71:                perror("[get_if_name] socket(AF_INET, SOCK_DGRAM, 0)");
                     72:                return -1;
                     73:        }
                     74: 
                     75:        memset(ibuf, 0, sizeof(struct ifreq)*16);
                     76:        ifc.ifc_len = sizeof ibuf;
                     77:        ifc.ifc_buf = (caddr_t) ibuf;
                     78: 
                     79:        /* gets interfaces list */
                     80:        if ( ioctl(fd, SIOCGIFCONF, (char*)&ifc) == -1 ||
                     81:             ifc.ifc_len < sizeof(struct ifreq)         ) {
                     82:                perror("[get_if_name] ioctl(SIOCGIFCONF)");
                     83:                close(fd);
                     84:                return -1;
                     85:        }
                     86: 
                     87:        /* ifrp points to buffer and ifend points to buffer's end */
                     88:        ifrp = ibuf;
                     89:        ifend = (struct ifreq*) ((char*)ibuf + ifc.ifc_len);
                     90: 
                     91:        for (; ifrp < ifend; ifrp++) {
                     92:                strlcpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name));
                     93: 
                     94:                if ( ioctl(fd, SIOCGIFFLAGS, (char*)&ifr) == -1) {
                     95:                        if (opt_debug)
                     96:                                perror("DEBUG: [get_if_name] ioctl(SIOCGIFFLAGS)");
                     97:                        continue;
                     98:                }
                     99: 
                    100:                if (opt_debug)
                    101:                        printf("DEBUG: if %s: ", ifr.ifr_name);
                    102: 
                    103:                /* Down interface? */
                    104:                if ( !(ifr.ifr_flags & IFF_UP) )
                    105:                {
                    106:                        if (opt_debug)
                    107:                                printf("DOWN\n");
                    108:                        continue;
                    109:                }
                    110: 
                    111:                if (known_output_if) {
                    112:                        /* Get the interface address */
                    113:                        if (ioctl(fd, SIOCGIFADDR, (char*)&ifr) == -1) {
                    114:                                perror("[get_if_name] ioctl(SIOCGIFADDR)");
                    115:                                continue;
                    116:                        }
                    117:                        /* Copy it */
                    118:                        memcpy(&sa, &ifr.ifr_addr,
                    119:                                sizeof(struct sockaddr_in));
                    120:                        /* Check if it is what we are locking for */
                    121:                        if (sa.sin_addr.s_addr !=
                    122:                            output_if_addr.sin_addr.s_addr) {
                    123:                                if (opt_debug)
                    124:                                        printf("The address doesn't match\n");
                    125:                                continue;
                    126:                        }
                    127:                } else if (ifname[0] != '\0' && !strstr(ifr.ifr_name, ifname)) {
                    128:                        if (opt_debug)
                    129:                                printf("Don't Match (but seems to be UP)\n");
                    130:                        continue;
                    131:                }
                    132: 
                    133:                if (opt_debug)
                    134:                        printf("OK\n");
                    135: 
                    136:                /* interface found, save if name */
                    137:                strlcpy(ifname, ifr.ifr_name, 1024);
                    138: 
                    139:                /* get if address */
                    140:                if ( ioctl(fd, SIOCGIFADDR, (char*)&ifr) == -1) {
                    141:                        perror("DEBUG: [get_if_name] ioctl(SIOCGIFADDR)");
                    142:                        exit(1);
                    143:                }
                    144: 
                    145:                /* save if address */
                    146:                memcpy(&sa, &ifr.ifr_addr,
                    147:                        sizeof(struct sockaddr_in));
                    148:                strlcpy(ifstraddr, inet_ntoa(sa.sin_addr), 1024);
                    149: 
                    150:                /* get if mtu */
                    151:                if ( ioctl(fd, SIOCGIFMTU, (char*)&ifr) == -1) {
                    152:                        perror("Warning: [get_if_name] ioctl(SIOCGIFMTU)");
                    153:                        fprintf(stderr, "Using a fixed MTU of 1500\n");
                    154:                        h_if_mtu = 1500;
                    155:                }
                    156:                else
                    157:                {
                    158: #ifdef __sun__
                    159:                        /* somehow solaris is braidamaged in wrt ifr_mtu */
                    160:                        h_if_mtu = ifr.ifr_metric;
                    161: #else
                    162:                        h_if_mtu = ifr.ifr_mtu;
                    163: #endif
                    164:                }
                    165:                close(fd);
                    166:                return 0;
                    167:        }
                    168:        /* interface not found, use 'lo' */
                    169:        strlcpy(ifname, "lo", 1024);
                    170:        strlcpy(ifstraddr, "127.0.0.1", 1024);
                    171:        h_if_mtu = 1500;
                    172: 
                    173:        close(fd);
                    174:        return 0;
                    175: }
                    176: 
                    177: #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
                    178:       defined(__bsdi__) || defined(__APPLE__)
                    179: 
                    180: /* return interface informations :
                    181:    - from the specified (-I) interface
                    182:    - from the routing table
                    183:    - or at least from the first UP interface found
                    184: */
                    185: int get_if_name(void)
                    186: {
                    187:        /* variable declarations */
                    188:        struct ifaddrs          *ifap, *ifa;
                    189:        char                    current_if_name[24];
                    190:        char                    saved_ifname[24];
                    191:        struct sockaddr_in      output_if_addr;
                    192: #ifdef __NetBSD__
                    193:        int s;
                    194:        struct ifreq ifr;
                    195: #endif  /* __NetBSD__ */
                    196: 
                    197:        if (getifaddrs(&ifap) < 0)
                    198:                perror("getifaddrs");
                    199: 
                    200:        saved_ifname[0] = 0;
                    201: 
                    202:        /* lookup desired interface */
                    203:        if(ifname[0] == 0) {
                    204:                /* find gateway interface from kernel */
                    205:                 if (get_output_if(&remote, &output_if_addr) == 0) {
                    206:                         if (opt_debug)
                    207:                                 printf("DEBUG: Output interface address: %s\n",
                    208:                                         inet_ntoa(output_if_addr.sin_addr));
                    209:                        /* Put something in saved_ifname in order to tell
                    210:                           that the output adress is known */
                    211:                        saved_ifname[0] = 'X'; saved_ifname[1] = 0;
                    212:                 } else {
                    213:                         fprintf(stderr, "Warning: Unable to guess the output "
                    214:                                         "interface\n");
                    215:                 }
                    216:        }
                    217:        else {
                    218:                /* use the forced interface name */
                    219:                strlcpy(saved_ifname,ifname,24);
                    220:        }
                    221: 
                    222:        /* get interface information */
                    223:         for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
                    224: 
                    225:                if (opt_debug) printf("\n DEBUG: if %s: ", ifa->ifa_name);
                    226: 
                    227:                /* print if the data structure is null or not */
                    228:                if (ifa->ifa_data) {
                    229:                        if(opt_debug) printf("DEBUG: (struct DATA) "); }
                    230:                else
                    231:                        if(opt_debug) printf("DEBUG: (struct DATA is NULL) ");
                    232: 
                    233:                if (!(ifa->ifa_flags & IFF_UP)) {       /* if down */
                    234:                        if (opt_debug)
                    235:                                printf("DEBUG: DOWN");
                    236:                        continue; 
                    237:                }
                    238: 
                    239:                if ((ifa->ifa_flags & IFF_LOOPBACK)&&
                    240:                    (strncmp(saved_ifname,"lo0",3))) {  /* if loopback */
                    241:                        if (opt_debug)
                    242:                                printf("DEBUG: LOOPBACK, SKIPPED");
                    243:                        continue;
                    244:                }
                    245: 
                    246:                if (ifa->ifa_addr->sa_family == AF_LINK) {
                    247:                        if (opt_debug)
                    248:                                printf("DEBUG: AF_LINK ");
                    249:                        strlcpy(ifname,ifa->ifa_name,1024);
                    250:                        strlcpy(current_if_name,ifa->ifa_name,24);
                    251: 
                    252: /* I don't know why NetBSD behavior is not the same */
                    253: #ifdef __NetBSD__
                    254:                        memset( &ifr, 0, sizeof(ifr));
                    255:                        strlcpy(ifr.ifr_name, ifa->ifa_name, sizeof(ifr.ifr_name));
                    256:                        if( sizeof(ifr.ifr_addr) >= ifa->ifa_addr->sa_len )
                    257:                                memcpy(&ifr.ifr_addr, ifa->ifa_addr, 
                    258:                                       ifa->ifa_addr->sa_len);
                    259:                        if( (s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
                    260:                                perror("[get_if_name] socket");
                    261:                                return -1;
                    262:                        }
                    263:                        if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0) h_if_mtu = 0;
                    264:                        else h_if_mtu = ifr.ifr_mtu;
                    265:                        close(s);
                    266: #else
                    267:                        if( ifa->ifa_data )
                    268:                                h_if_mtu = ((struct if_data *)ifa->ifa_data)->ifi_mtu;
                    269:                        else {
                    270:                                h_if_mtu = 1500;
                    271:                                fprintf(stderr, "Warning: fixing MTU to 1500 !\n");
                    272:                         }
                    273: #endif /* __NetBSD__ */
                    274:                        continue;
                    275:                }
                    276: 
                    277:                if (ifa->ifa_addr->sa_family == AF_INET6) {
                    278:                        if (opt_debug)
                    279:                                printf("AF_INET6 ");
                    280:                        continue;
                    281:                }
                    282: 
                    283:                if (ifa->ifa_addr->sa_family == AF_INET) {
                    284:                        if (opt_debug)
                    285:                                printf("AF_INET ");
                    286: 
                    287:                        if(strncmp(ifa->ifa_name,current_if_name,24))
                    288:                                continue; /* error */
                    289: 
                    290:                        if(opt_debug) printf("OK\n");
                    291: 
                    292:                        strlcpy(ifname,ifa->ifa_name,1024);
                    293:                        strlcpy(ifstraddr,
                    294:                                inet_ntoa(((struct sockaddr_in *)ifa->ifa_addr)->sin_addr),
                    295:                                          1024);
                    296:                        
                    297:                        if( (saved_ifname[0] == 0) ||
                    298:                             (!strncmp(ifa->ifa_name, saved_ifname, 24)) || 
                    299:                            (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr ==
                    300:                               output_if_addr.sin_addr.s_addr) )
                    301:                                break; /* asked if found or first UP interface */
                    302:                }
                    303: 
                    304:                /* interface not found, use hardcoded 'lo' */
                    305:                strlcpy(ifname, "lo0", 1024);
                    306:                strlcpy(ifstraddr, "127.0.0.1", 1024);
                    307:                h_if_mtu = 1500;
                    308:        }
                    309: 
                    310:        freeifaddrs(ifap);
                    311:        return 0;
                    312: }
                    313: 
                    314: #endif /* __*BSD__ */
                    315: 
                    316: /* Try to obtain the IP address of the output interface according
                    317:  * to the OS routing table. Derived from R.Stevens */
                    318: int get_output_if(struct sockaddr_in *dest, struct sockaddr_in *ifip)
                    319: {
                    320:        int sock_rt, len, on=1;
                    321:        struct sockaddr_in iface_out;
                    322:  
                    323:        memset(&iface_out, 0, sizeof(iface_out));
                    324:        sock_rt = socket(AF_INET, SOCK_DGRAM, 0 );
                    325: 
                    326:        dest->sin_port = htons(11111);
                    327:        if (setsockopt(sock_rt, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on))
                    328:             == -1) {
                    329:                if (opt_debug)
                    330:                        perror("DEBUG: [get_output_if] setsockopt(SOL_SOCKET, "
                    331:                               "SO_BROADCAST");
                    332:                close(sock_rt);
                    333:                return -1;
                    334:        }
                    335:   
                    336:        if (connect(sock_rt, (struct sockaddr*)dest, sizeof(struct sockaddr_in))
                    337:            == -1 ) {
                    338:                if (opt_debug)
                    339:                        perror("DEBUG: [get_output_if] connect");
                    340:                close(sock_rt);
                    341:                return -1;
                    342:        }
                    343: 
                    344:        len = sizeof(iface_out);
                    345:        if (getsockname(sock_rt, (struct sockaddr *)&iface_out, &len) == -1 ) {
                    346:                if (opt_debug)
                    347:                        perror("DEBUG: [get_output_if] getsockname");
                    348:                close(sock_rt);
                    349:                return -1;
                    350:        }
                    351:        close(sock_rt);
                    352:        if (iface_out.sin_addr.s_addr == 0)
                    353:                return 1;
                    354:        memcpy(ifip, &iface_out, sizeof(struct sockaddr_in));
                    355:         return 0;
                    356: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>