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>