dev: mark paths likely/unlikely
[netsniff-ng.git] / staging / lookupdev.c
blobdfca239e90a8272189ad75ce3702ace5d4d54b7e
1 /*
2 * Mausezahn - A fast versatile traffic generator
3 * Copyright (C) 2008-2010 Herbert Haas
4 *
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License version 2 as published by the
7 * Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12 * details.
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, see http://www.gnu.org/licenses/gpl-2.0.html
22 #include "mz.h"
23 #include "mops.h"
25 #include <netpacket/packet.h>
26 #include <netinet/ether.h>
29 // PURPOSE: Find usable network devices
30 //
31 // NOTE:
32 //
33 // 1. Ignores devices without IP address
34 // 2. Ignores loopback (etc)
35 //
36 // RETURN VALUES:
37 //
38 // 0 if usable device found (device_list[] and tx.device set)
39 // 1 if no usable device found
40 //
41 int lookupdev()
43 // char *tx.device is global, see as.h
45 char
46 ipaddress[IPADDRSIZE+1],
47 errbuf[PCAP_ERRBUF_SIZE];
49 pcap_if_t
50 *alldevs,
51 *index = NULL;
53 pcap_addr_t *pcap_addr;
55 int i=0;
58 // FIRST get a list of all available devices
59 //
60 if (pcap_findalldevs(&alldevs, errbuf) == -1)
62 fprintf(stderr," mz: %s\n",errbuf);
63 return 1;
66 index = (pcap_if_t *) alldevs;
68 while (index)
70 if (index->addresses)
72 pcap_addr = index->addresses;
73 while(pcap_addr)
75 if (pcap_addr->addr && (pcap_addr->addr->sa_family==AF_INET))
77 if (inet_ntop(pcap_addr->addr->sa_family,
78 (void *)&pcap_addr->addr->sa_data[2],
79 ipaddress,
80 IPADDRSIZE))
82 if (verbose)
84 fprintf(stderr," mz: device %s got assigned %s ",
85 index->name, ipaddress);
88 if (strncmp(ipaddress, "127", 3)==0)
90 if (verbose) fprintf(stderr, "(loopback)\n");
91 strncpy(device_list[i].dev, index->name, 9);
92 strncpy(device_list[i].ip_str, ipaddress, IPADDRSIZE);
93 device_list[i].phy=0;
94 get_if_addr(index->name, device_list[i].ip, device_list[i].mac);
95 get_if_addr(index->name, device_list[i].ip_mops, device_list[i].mac_mops);
96 i++;
98 else if (strncmp(ipaddress, "169.254", 7)==0)
100 if (verbose) fprintf(stderr, "but IGNORED (cause: host-scope address)\n");
102 else // FOUND VALID INTERFACE
104 if (verbose) fprintf(stderr, "and is a possible candidate.\n");
105 strncpy(device_list[i].dev, index->name, 9);
106 strncpy(device_list[i].ip_str, ipaddress, IPADDRSIZE);
107 device_list[i].phy=1;
108 get_if_addr(index->name, device_list[i].ip, device_list[i].mac);
109 get_if_addr(index->name, device_list[i].ip_mops, device_list[i].mac_mops);
110 i++;
113 // Select only interfaces with IP addresses
114 // but avoid those that start with 127 or 169.254
115 // Put the remaining on a list. If this list has more than one entry
116 // ask the user which interface to listen to.
118 else
120 return 1;
123 pcap_addr = pcap_addr->next;
124 } // closes while(pcap_addr)
126 index = index->next;
127 } // closes while (index)
129 device_list_entries = i;
132 if (verbose)
134 for (i=0; i<device_list_entries; i++)
136 fprintf(stderr, " mz: Found device %s with IP %s\n", device_list[i].dev, device_list[i].ip_str);
141 // No device found:
142 if (device_list_entries==0) return 1;
144 // Else device found:
145 // initialize tx.device with first entry of the device_list
146 strncpy (tx.device, device_list[0].dev, 16);
148 return 0;
158 // Determines ip and mac address of specified interface 'ifname'
159 // Caller must provide an unsigned char ip[4], mac[6]
161 int get_if_addr (char *ifname, u_int8_t *ip, u_int8_t *mac)
163 int fd, i;
164 struct ifreq ifr;
165 struct sockaddr_in saddr;
166 u_int8_t *x;
168 ifr.ifr_addr.sa_family = AF_INET;
169 strncpy(ifr.ifr_name, ifname , IFNAMSIZ-1);
171 // we must open a socket to get the addresses
172 fd = socket(AF_INET, SOCK_DGRAM, 0);
173 if (fd == -1) return 1;
175 // get mac
176 ioctl(fd, SIOCGIFHWADDR, &ifr);
177 for (i=0; i<6; i++) mac[i]= (u_int8_t) ifr.ifr_hwaddr.sa_data[i];
179 // get IP
180 ioctl(fd, SIOCGIFADDR, &ifr);
181 saddr=*((struct sockaddr_in *)(&(ifr.ifr_addr)));
182 x = (u_int8_t*)&saddr.sin_addr;
183 ip[0]=*x; ip[1]=*(x+1); ip[2]=*(x+2); ip[3]=*(x+3);
185 close(fd);
188 return 0;
194 // For a given device name, find out the following parameters:
196 // - MTU
197 // - Network
198 // - Mask
199 // - Default GW (IP)
200 // - Default GW (MAC)
201 // - Open packet socket (if not already done)
203 int get_dev_params (char *name)
205 FILE *fd;
207 char f[10][16], line[256];
208 int in=0, nw=1, gw=2, mk=7; // default columns in /proc/net/route for interface, network, gateway, and mask.
209 unsigned int tmp[4], net[4]={0,0,0,0}, dgw[4], mask[4]={0,0,0,0};
210 int i=0, flag=0, nw_found=0, gw_found=0, devind=0, dev_found=0;
212 struct ifreq si;
213 struct sockaddr_ll psock;
214 int ps, index, mtu;
215 struct arp_table_struct *cur;
216 // 1. Check if device is already present in our device_list
218 for (i=0; i<device_list_entries; i++) {
219 if (strncmp(device_list[i].dev, name, 16)==0) {
220 devind=i;
221 dev_found=1;
222 break;
225 if (dev_found==0) return 1; // ERROR: device name not found !!!!
229 // 2. find network, gateway, and mask
231 fd = fopen("/proc/net/route", "r");
232 while (fgets(line, 255, fd)!=NULL) {
233 sscanf(line, " %s %s %s %s %s %s %s %s %s %s", f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]);
234 if (!flag) { // find columns (we do NOT assume that the order of columns is the same everywhere)
235 for (i=0; i<10; i++) {
236 if (strncasecmp(f[i],"iface", 16)==0) in=i;
237 if (strncasecmp(f[i],"destination", 16)==0) nw=i;
238 if (strncasecmp(f[i],"gateway", 16)==0) gw=i;
239 if (strncasecmp(f[i],"mask", 16)==0) mk=i;
241 flag=1;
244 if (strncmp(f[in], name, 16)==0) { // interface found
245 // Determine network
246 if ((strncmp(f[nw],"00000000",8)!=0) && (strncmp(f[gw],"00000000",8)==0)) {
247 // ignore 169.254 and 127 networks
248 sscanf(f[nw],"%02x%02x%02x%02x",&tmp[3], &tmp[2], &tmp[1], &tmp[0]);
249 if ((tmp[0]!=127) && (tmp[0]!=169)) {
250 nw_found=1;
251 net[0]=tmp[0];
252 net[1]=tmp[1];
253 net[2]=tmp[2];
254 net[3]=tmp[3];
255 // also get mask for that network
256 sscanf(f[mk],"%02x%02x%02x%02x",&tmp[3], &tmp[2], &tmp[1], &tmp[0]);
257 mask[0]=tmp[0];
258 mask[1]=tmp[1];
259 mask[2]=tmp[2];
260 mask[3]=tmp[3];
263 // Determine gateway
264 if ((strncmp(f[nw],"00000000",8)==0) && (strncmp(f[gw],"00000000",8)!=0)) {
265 sscanf(f[gw],"%02x%02x%02x%02x",&dgw[3], &dgw[2], &dgw[1], &dgw[0]);
266 gw_found=1;
271 fclose(fd);
274 // 3. Get device index, determine MTU,
275 // and bind socket to device for later TX and RX
277 // if socket is already open, then close and re-open it!
278 if (device_list[devind].ps>=0) {
279 close(device_list[devind].ps);
280 device_list[devind].ps=-1;
283 if (device_list[devind].ps<0) {
284 ps = socket (PF_PACKET, SOCK_RAW, htons(ETH_P_IP)); //ETH_P_ALL, ETH_P_802_3);
285 if (ps<0) {
286 fprintf(stderr, " Warning: [lookupdev.c get_dev_params()] Cannot open socket!\n");
287 return 1;
290 // Get device index
291 strncpy(si.ifr_name, name, IFNAMSIZ);
292 if (ioctl(ps, SIOCGIFINDEX, &si)==-1) {
293 perror("ioctl");
294 close(ps);
295 return 1;
297 index=si.ifr_ifindex;
299 // Get MTU
300 if (ioctl(ps, SIOCGIFMTU, &si)==-1) {
301 perror("ioctl");
302 close(ps);
303 return 1;
305 mtu = si.ifr_mtu;
307 // ***** bind socket for later TX and RX ****
308 psock.sll_family = AF_PACKET; // evident
309 // psock.sll_protocol = 0; // unsigned short - Physical layer protocol
310 psock.sll_ifindex = index; // int - Interface number
311 psock.sll_hatype = 0; // unsigned short - Header type //ARPHRD_ETHER
312 psock.sll_pkttype = 0; // unsigned char - Packet type
313 psock.sll_halen = 6; // unsigned char - Length of address
314 bind(ps, (const struct sockaddr *) &psock, sizeof(psock)); // <= !!!
315 device_list[devind].ps = ps; // Note that close(ps) must be done upon termination
318 // Get MAC of default gateway
319 service_arp(name, device_list[devind].ip_gw, device_list[devind].mac_gw);
321 usleep(200); // this is a VERY short delay but it usually works in today's LANs
322 cur=device_list[devind].arp_table;
323 while(cur!=NULL) {
324 if ((cur->sip[0]==dgw[0]) &&
325 (cur->sip[1]==dgw[1]) &&
326 (cur->sip[2]==dgw[2]) &&
327 (cur->sip[3]==dgw[3])) { // entry found!
328 for (i=0; i<6; i++) {
329 device_list[devind].mac_gw[i] = cur->smac[i];
332 cur=cur->next;
335 // FINALLY: Copy findings in device_list
337 if (device_list[devind].phy) {
338 for (i=0; i<4; i++) {
339 device_list[devind].net[i] = net[i];
340 device_list[devind].mask[i] = mask[i];
341 device_list[devind].ip_gw[i] = dgw[i];
344 else {
345 for (i=0; i<4; i++) {
346 device_list[devind].net[i] = 0;
347 device_list[devind].mask[i] = 0;
348 device_list[devind].ip_gw[i] = 0;
352 device_list[devind].index = index;
353 device_list[devind].mtu = mtu;
355 return 0;