Annotation of embedaddon/hping2/getifname.c, revision 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>