update on index.html
[netsniff-ng.git] / src / netdev.c
blob7816acda3af892774d413fcff2e4ebbc568cdcaf
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2009, 2010 Daniel Borkmann.
5 * Copyright 2009, 2010 Emmanuel Roullit.
6 * Subject to the GPL.
7 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <stdint.h>
12 #include <fcntl.h>
13 #include <string.h>
14 #include <unistd.h>
15 #include <errno.h>
16 #include <sys/socket.h>
17 /* Kernel < 2.6.26 */
18 #include <linux/if.h>
19 #include <linux/socket.h>
20 #include <linux/types.h>
21 /* Kernel < 2.6.26 */
22 #include <linux/if_ether.h>
23 #include <linux/if_packet.h>
24 #include <linux/sockios.h>
26 #include "netdev.h"
27 #include "die.h"
28 #include "strlcpy.h"
30 int af_socket(int af)
32 if (af != AF_INET && af != AF_INET6) {
33 whine("Wrong AF socket type! Falling back to AF_INET\n");
34 af = AF_INET;
37 int sock = socket(af, SOCK_DGRAM, 0);
38 if (sock < 0)
39 error_and_die(EXIT_FAILURE, "Creation AF socket failed!\n");
40 return sock;
43 int pf_socket(void)
45 int sock = socket(PF_PACKET, SOCK_RAW, 0);
46 if (sock < 0)
47 error_and_die(EXIT_FAILURE, "Creation of PF socket failed!\n");
48 return sock;
51 int set_nonblocking(int fd)
53 int ret = fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK);
54 if (ret < 0)
55 panic("Cannot fcntl!\n");
56 return 0;
59 int set_reuseaddr(int fd)
61 int one = 1;
62 int ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof (one));
63 if (ret < 0)
64 panic("Cannot reuse addr!\n");
65 return 0;
68 int wireless_bitrate(const char *ifname)
70 int sock, ret, rate_in_mbit;
71 struct iwreq iwr;
73 sock = af_socket(AF_INET);
75 memset(&iwr, 0, sizeof(iwr));
76 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
78 ret = ioctl(sock, SIOCGIWRATE, &iwr);
79 if (!ret)
80 rate_in_mbit = iwr.u.bitrate.value / 1000000;
81 else
82 rate_in_mbit = 0;
84 close(sock);
85 return rate_in_mbit;
88 int wireless_essid(const char *ifname, char *essid)
90 int ret, sock, essid_len;
91 struct iwreq iwr;
93 sock = af_socket(AF_INET);
95 memset(&iwr, 0, sizeof(iwr));
96 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
98 iwr.u.essid.pointer = essid;
99 iwr.u.essid.length = IW_ESSID_MAX_SIZE;
101 ret = ioctl(sock, SIOCGIWESSID, &iwr);
102 if (!ret)
103 essid_len = iwr.u.essid.length;
104 else
105 essid_len = 0;
107 close(sock);
108 return essid_len;
111 int adjust_dbm_level(int dbm_val)
113 if (dbm_val >= 64)
114 dbm_val -= 0x100;
115 return dbm_val;
118 int dbm_to_mwatt(const int in)
120 /* From Jean Tourrilhes <jt@hpl.hp.com> (iwlib.c) */
121 int ip = in / 10;
122 int fp = in % 10;
123 int k;
125 double res = 1.0;
127 for (k = 0; k < ip; k++)
128 res *= 10;
129 for (k = 0; k < fp; k++)
130 res *= 1.25892541179; /* LOG10_MAGIC */
132 return (int) res;
135 int wireless_tx_power(const char *ifname)
137 int ret, sock, tx_power;
138 struct iwreq iwr;
140 sock = af_socket(AF_INET);
142 memset(&iwr, 0, sizeof(iwr));
143 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
145 ret = ioctl(sock, SIOCGIWTXPOW, &iwr);
146 if (!ret)
147 tx_power = iwr.u.txpower.value;
148 else
149 tx_power = 0;
151 close(sock);
152 return ret;
155 int wireless_sigqual(const char *ifname, struct iw_statistics *stats)
157 int ret, sock;
158 struct iwreq iwr;
160 sock = af_socket(AF_INET);
162 memset(&iwr, 0, sizeof(iwr));
163 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
165 iwr.u.data.pointer = (caddr_t) stats;
166 iwr.u.data.length = sizeof(*stats);
167 iwr.u.data.flags = 1;
169 ret = ioctl(sock, SIOCGIWSTATS, &iwr);
171 close(sock);
172 return ret;
175 int wireless_rangemax_sigqual(const char *ifname)
177 int ret, sock, sigqual;
178 struct iwreq iwr;
179 struct iw_range iwrange;
181 sock = af_socket(AF_INET);
183 memset(&iwrange, 0, sizeof(iwrange));
184 memset(&iwr, 0, sizeof(iwr));
185 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
187 iwr.u.data.pointer = (caddr_t) &iwrange;
188 iwr.u.data.length = sizeof(iwrange);
189 iwr.u.data.flags = 0;
191 ret = ioctl(sock, SIOCGIWRANGE, &iwr);
192 if (!ret)
193 sigqual = iwrange.max_qual.qual;
194 else
195 sigqual = 0;
197 close(sock);
198 return sigqual;
201 int ethtool_bitrate(const char *ifname)
203 int ret, sock, bitrate;
204 struct ifreq ifr;
205 struct ethtool_cmd ecmd;
207 sock = af_socket(AF_INET);
209 memset(&ecmd, 0, sizeof(ecmd));
210 memset(&ifr, 0, sizeof(ifr));
211 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
213 ecmd.cmd = ETHTOOL_GSET;
214 ifr.ifr_data = (char *) &ecmd;
216 ret = ioctl(sock, SIOCETHTOOL, &ifr);
217 if (ret) {
218 bitrate = 0;
219 goto out;
222 switch (ecmd.speed) {
223 case SPEED_10:
224 case SPEED_100:
225 case SPEED_1000:
226 case SPEED_10000:
227 bitrate = ecmd.speed;
228 break;
229 default:
230 bitrate = 0;
231 break;
234 out:
235 close(sock);
236 return bitrate;
239 int ethtool_drvinf(const char *ifname, struct ethtool_drvinfo *drvinf)
241 int ret, sock;
242 struct ifreq ifr;
244 sock = af_socket(AF_INET);
246 memset(drvinf, 0, sizeof(*drvinf));
247 memset(&ifr, 0, sizeof(ifr));
248 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
250 drvinf->cmd = ETHTOOL_GDRVINFO;
251 ifr.ifr_data = (char *) drvinf;
253 ret = ioctl(sock, SIOCETHTOOL, &ifr);
255 close(sock);
256 return ret;
259 int device_bitrate(const char *ifname)
261 int speed_c, speed_w;
263 /* Probe for speed rates */
264 speed_c = ethtool_bitrate(ifname);
265 speed_w = wireless_bitrate(ifname);
267 return (speed_c == 0 ? speed_w : speed_c);
270 int device_ifindex(const char *ifname)
272 int ret, sock, index;
273 struct ifreq ifr;
275 if (!strncmp("any", ifname, strlen("any")))
276 return 0;
278 sock = af_socket(AF_INET);
280 memset(&ifr, 0, sizeof(ifr));
281 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
283 ret = ioctl(sock, SIOCGIFINDEX, &ifr);
284 if (!ret)
285 index = ifr.ifr_ifindex;
286 else
287 index = -1;
289 close(sock);
290 return index;
293 int device_mtu(const char *ifname)
295 int ret, sock, mtu;
296 struct ifreq ifr;
298 sock = af_socket(AF_INET);
300 memset(&ifr, 0, sizeof(ifr));
301 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
303 ret = ioctl(sock, SIOCGIFMTU, &ifr);
304 if (!ret)
305 mtu = ifr.ifr_mtu;
306 else
307 mtu = 0;
309 close(sock);
310 return mtu;
313 short device_get_flags(const char *ifname)
315 /* Really, it's short! Look at struct ifreq */
316 short flags;
317 int ret, sock;
318 struct ifreq ifr;
320 sock = af_socket(AF_INET);
322 memset(&ifr, 0, sizeof(ifr));
323 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
325 ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
326 if (!ret)
327 flags = ifr.ifr_flags;
328 else
329 flags = 0;
331 close(sock);
332 return flags;
335 void device_set_flags(const char *ifname, const short flags)
337 int ret, sock;
338 struct ifreq ifr;
340 sock = af_socket(AF_INET);
342 memset(&ifr, 0, sizeof(ifr));
343 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
345 ifr.ifr_flags = flags;
347 ret = ioctl(sock, SIOCSIFFLAGS, &ifr);
348 if (ret < 0)
349 error_and_die(EXIT_FAILURE, "Cannot set NIC flags!\n");
351 close(sock);
354 int device_irq_number(const char *ifname)
357 * Since fetching IRQ numbers from SIOCGIFMAP is deprecated and not
358 * supported anymore, we need to grab them from procfs
361 int irq = 0;
362 char *buffp;
363 char buff[512];
364 char sysname[512];
366 /* We exclude lo! */
367 if (!strncmp("lo", ifname, strlen("lo")))
368 return 0;
370 /* Try /proc/interrupts */
371 FILE *fp = fopen("/proc/interrupts", "r");
372 if (!fp) {
373 whine("Cannot open /proc/interrupts!\n");
374 return -ENOENT;
377 memset(buff, 0, sizeof(buff));
379 while (fgets(buff, sizeof(buff), fp) != NULL) {
380 buff[sizeof(buff) - 1] = 0;
382 if (strstr(buff, ifname) == NULL)
383 continue;
385 buffp = buff;
386 while (*buffp != ':')
387 buffp++;
389 *buffp = 0;
390 irq = atoi(buff);
392 memset(buff, 0, sizeof(buff));
395 fclose(fp);
396 if (irq != 0)
397 return irq;
400 * Try sysfs as fallback. Probably wireless devices will be found
401 * here. We return silently if it fails ...
403 snprintf(sysname, sizeof(sysname), "/sys/class/net/%s/device/irq",
404 ifname);
406 fp = fopen(sysname, "r");
407 if (!fp)
408 return -ENOENT;
410 memset(buff, 0, sizeof(buff));
411 if(fgets(buff, sizeof(buff), fp) != NULL) {
412 buff[sizeof(buff) - 1] = 0;
413 irq = atoi(buff);
416 fclose(fp);
417 return irq;
420 int device_bind_irq_to_cpu(int irq, int cpu)
422 int ret;
423 char buff[256];
424 char file[256];
426 /* Note: first CPU begins with CPU 0 */
427 if (irq < 0 || cpu < 0)
428 return -EINVAL;
430 memset(file, 0, sizeof(file));
431 memset(buff, 0, sizeof(buff));
433 /* smp_affinity starts counting with CPU 1, 2, ... */
434 cpu = cpu + 1;
436 sprintf(file, "/proc/irq/%d/smp_affinity", irq);
438 FILE *fp = fopen(file, "w");
439 if (!fp) {
440 whine("Cannot open file %s!\n", file);
441 return -ENOENT;
444 sprintf(buff, "%d", cpu);
445 ret = fwrite(buff, sizeof(buff), 1, fp);
447 fclose(fp);
448 return (ret > 0 ? 0 : ret);
451 void sock_print_net_stats(int sock)
453 int ret;
454 struct tpacket_stats kstats;
455 socklen_t slen = sizeof(kstats);
457 memset(&kstats, 0, sizeof(kstats));
459 ret = getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &kstats, &slen);
460 if (ret > -1) {
461 printf("\r%3d frames incoming\n",
462 kstats.tp_packets);
463 printf("\r%3d frames passed filter\n",
464 kstats.tp_packets - kstats.tp_drops);
465 printf("\r%3d frames failed filter (out of space)\n",
466 kstats.tp_drops);