diff options
Diffstat (limited to 'staging/lookupdev.c')
-rw-r--r-- | staging/lookupdev.c | 357 |
1 files changed, 357 insertions, 0 deletions
diff --git a/staging/lookupdev.c b/staging/lookupdev.c new file mode 100644 index 0000000..dfca239 --- /dev/null +++ b/staging/lookupdev.c @@ -0,0 +1,357 @@ +/* + * Mausezahn - A fast versatile traffic generator + * Copyright (C) 2008-2010 Herbert Haas + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License version 2 as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see http://www.gnu.org/licenses/gpl-2.0.html + * +*/ + + + + +#include "mz.h" +#include "mops.h" + +#include <netpacket/packet.h> +#include <netinet/ether.h> + + +// PURPOSE: Find usable network devices +// +// NOTE: +// +// 1. Ignores devices without IP address +// 2. Ignores loopback (etc) +// +// RETURN VALUES: +// +// 0 if usable device found (device_list[] and tx.device set) +// 1 if no usable device found +// +int lookupdev() +{ + // char *tx.device is global, see as.h + + char + ipaddress[IPADDRSIZE+1], + errbuf[PCAP_ERRBUF_SIZE]; + + pcap_if_t + *alldevs, + *index = NULL; + + pcap_addr_t *pcap_addr; + + int i=0; + + + // FIRST get a list of all available devices + // + if (pcap_findalldevs(&alldevs, errbuf) == -1) + { + fprintf(stderr," mz: %s\n",errbuf); + return 1; + } + + index = (pcap_if_t *) alldevs; + + while (index) + { + if (index->addresses) + { + pcap_addr = index->addresses; + while(pcap_addr) + { + if (pcap_addr->addr && (pcap_addr->addr->sa_family==AF_INET)) + { + if (inet_ntop(pcap_addr->addr->sa_family, + (void *)&pcap_addr->addr->sa_data[2], + ipaddress, + IPADDRSIZE)) + { + if (verbose) + { + fprintf(stderr," mz: device %s got assigned %s ", + index->name, ipaddress); + } + + if (strncmp(ipaddress, "127", 3)==0) + { + if (verbose) fprintf(stderr, "(loopback)\n"); + strncpy(device_list[i].dev, index->name, 9); + strncpy(device_list[i].ip_str, ipaddress, IPADDRSIZE); + device_list[i].phy=0; + get_if_addr(index->name, device_list[i].ip, device_list[i].mac); + get_if_addr(index->name, device_list[i].ip_mops, device_list[i].mac_mops); + i++; + } + else if (strncmp(ipaddress, "169.254", 7)==0) + { + if (verbose) fprintf(stderr, "but IGNORED (cause: host-scope address)\n"); + } + else // FOUND VALID INTERFACE + { + if (verbose) fprintf(stderr, "and is a possible candidate.\n"); + strncpy(device_list[i].dev, index->name, 9); + strncpy(device_list[i].ip_str, ipaddress, IPADDRSIZE); + device_list[i].phy=1; + get_if_addr(index->name, device_list[i].ip, device_list[i].mac); + get_if_addr(index->name, device_list[i].ip_mops, device_list[i].mac_mops); + i++; + } + + // Select only interfaces with IP addresses + // but avoid those that start with 127 or 169.254 + // Put the remaining on a list. If this list has more than one entry + // ask the user which interface to listen to. + } + else + { + return 1; + } + } + pcap_addr = pcap_addr->next; + } // closes while(pcap_addr) + } + index = index->next; + } // closes while (index) + + device_list_entries = i; + + /* + if (verbose) + { + for (i=0; i<device_list_entries; i++) + { + fprintf(stderr, " mz: Found device %s with IP %s\n", device_list[i].dev, device_list[i].ip_str); + } + } + */ + + // No device found: + if (device_list_entries==0) return 1; + + // Else device found: + // initialize tx.device with first entry of the device_list + strncpy (tx.device, device_list[0].dev, 16); + + return 0; +} + + + + + + + + +// Determines ip and mac address of specified interface 'ifname' +// Caller must provide an unsigned char ip[4], mac[6] +// +int get_if_addr (char *ifname, u_int8_t *ip, u_int8_t *mac) +{ + int fd, i; + struct ifreq ifr; + struct sockaddr_in saddr; + u_int8_t *x; + + ifr.ifr_addr.sa_family = AF_INET; + strncpy(ifr.ifr_name, ifname , IFNAMSIZ-1); + + // we must open a socket to get the addresses + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd == -1) return 1; + + // get mac + ioctl(fd, SIOCGIFHWADDR, &ifr); + for (i=0; i<6; i++) mac[i]= (u_int8_t) ifr.ifr_hwaddr.sa_data[i]; + + // get IP + ioctl(fd, SIOCGIFADDR, &ifr); + saddr=*((struct sockaddr_in *)(&(ifr.ifr_addr))); + x = (u_int8_t*)&saddr.sin_addr; + ip[0]=*x; ip[1]=*(x+1); ip[2]=*(x+2); ip[3]=*(x+3); + + close(fd); + + + return 0; +} + + + + +// For a given device name, find out the following parameters: +// +// - MTU +// - Network +// - Mask +// - Default GW (IP) +// - Default GW (MAC) +// - Open packet socket (if not already done) +// +int get_dev_params (char *name) +{ + FILE *fd; + + char f[10][16], line[256]; + int in=0, nw=1, gw=2, mk=7; // default columns in /proc/net/route for interface, network, gateway, and mask. + unsigned int tmp[4], net[4]={0,0,0,0}, dgw[4], mask[4]={0,0,0,0}; + int i=0, flag=0, nw_found=0, gw_found=0, devind=0, dev_found=0; + + struct ifreq si; + struct sockaddr_ll psock; + int ps, index, mtu; + struct arp_table_struct *cur; + // 1. Check if device is already present in our device_list + + for (i=0; i<device_list_entries; i++) { + if (strncmp(device_list[i].dev, name, 16)==0) { + devind=i; + dev_found=1; + break; + } + } + if (dev_found==0) return 1; // ERROR: device name not found !!!! + + + + // 2. find network, gateway, and mask + + fd = fopen("/proc/net/route", "r"); + while (fgets(line, 255, fd)!=NULL) { + 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]); + if (!flag) { // find columns (we do NOT assume that the order of columns is the same everywhere) + for (i=0; i<10; i++) { + if (strncasecmp(f[i],"iface", 16)==0) in=i; + if (strncasecmp(f[i],"destination", 16)==0) nw=i; + if (strncasecmp(f[i],"gateway", 16)==0) gw=i; + if (strncasecmp(f[i],"mask", 16)==0) mk=i; + } + flag=1; + } + + if (strncmp(f[in], name, 16)==0) { // interface found + // Determine network + if ((strncmp(f[nw],"00000000",8)!=0) && (strncmp(f[gw],"00000000",8)==0)) { + // ignore 169.254 and 127 networks + sscanf(f[nw],"%02x%02x%02x%02x",&tmp[3], &tmp[2], &tmp[1], &tmp[0]); + if ((tmp[0]!=127) && (tmp[0]!=169)) { + nw_found=1; + net[0]=tmp[0]; + net[1]=tmp[1]; + net[2]=tmp[2]; + net[3]=tmp[3]; + // also get mask for that network + sscanf(f[mk],"%02x%02x%02x%02x",&tmp[3], &tmp[2], &tmp[1], &tmp[0]); + mask[0]=tmp[0]; + mask[1]=tmp[1]; + mask[2]=tmp[2]; + mask[3]=tmp[3]; + } + } + // Determine gateway + if ((strncmp(f[nw],"00000000",8)==0) && (strncmp(f[gw],"00000000",8)!=0)) { + sscanf(f[gw],"%02x%02x%02x%02x",&dgw[3], &dgw[2], &dgw[1], &dgw[0]); + gw_found=1; + } + } + } + + fclose(fd); + + + // 3. Get device index, determine MTU, + // and bind socket to device for later TX and RX + + // if socket is already open, then close and re-open it! + if (device_list[devind].ps>=0) { + close(device_list[devind].ps); + device_list[devind].ps=-1; + } + + if (device_list[devind].ps<0) { + ps = socket (PF_PACKET, SOCK_RAW, htons(ETH_P_IP)); //ETH_P_ALL, ETH_P_802_3); + if (ps<0) { + fprintf(stderr, " Warning: [lookupdev.c get_dev_params()] Cannot open socket!\n"); + return 1; + } + + // Get device index + strncpy(si.ifr_name, name, IFNAMSIZ); + if (ioctl(ps, SIOCGIFINDEX, &si)==-1) { + perror("ioctl"); + close(ps); + return 1; + } + index=si.ifr_ifindex; + + // Get MTU + if (ioctl(ps, SIOCGIFMTU, &si)==-1) { + perror("ioctl"); + close(ps); + return 1; + } + mtu = si.ifr_mtu; + + // ***** bind socket for later TX and RX **** + psock.sll_family = AF_PACKET; // evident + // psock.sll_protocol = 0; // unsigned short - Physical layer protocol + psock.sll_ifindex = index; // int - Interface number + psock.sll_hatype = 0; // unsigned short - Header type //ARPHRD_ETHER + psock.sll_pkttype = 0; // unsigned char - Packet type + psock.sll_halen = 6; // unsigned char - Length of address + bind(ps, (const struct sockaddr *) &psock, sizeof(psock)); // <= !!! + device_list[devind].ps = ps; // Note that close(ps) must be done upon termination + } + + // Get MAC of default gateway + service_arp(name, device_list[devind].ip_gw, device_list[devind].mac_gw); + + usleep(200); // this is a VERY short delay but it usually works in today's LANs + cur=device_list[devind].arp_table; + while(cur!=NULL) { + if ((cur->sip[0]==dgw[0]) && + (cur->sip[1]==dgw[1]) && + (cur->sip[2]==dgw[2]) && + (cur->sip[3]==dgw[3])) { // entry found! + for (i=0; i<6; i++) { + device_list[devind].mac_gw[i] = cur->smac[i]; + } + } + cur=cur->next; + } + + // FINALLY: Copy findings in device_list + + if (device_list[devind].phy) { + for (i=0; i<4; i++) { + device_list[devind].net[i] = net[i]; + device_list[devind].mask[i] = mask[i]; + device_list[devind].ip_gw[i] = dgw[i]; + } + } + else { + for (i=0; i<4; i++) { + device_list[devind].net[i] = 0; + device_list[devind].mask[i] = 0; + device_list[devind].ip_gw[i] = 0; + } + } + + device_list[devind].index = index; + device_list[devind].mtu = mtu; + + return 0; +} + |