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>