File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / hping2 / getifname.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:11:37 2012 UTC (12 years, 4 months ago) by misho
Branches: hping2, MAIN
CVS tags: v2_0_0rc3p7, v2_0_0rc3p5, v2_0_0rc3p4, v2_0_0rc3p0, v2_0_0rc3, HEAD
hping2

    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>