Merge branch 'master' of git://github.com/borkmann/netsniff-ng
[netsniff-ng.git] / src / xsys.c
blob5c4a2a80a047db99155221de1626f2ee50914326
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, version 2.
7 */
9 #define _GNU_SOURCE
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <stdint.h>
13 #include <fcntl.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <errno.h>
17 #include <signal.h>
18 #include <arpa/inet.h>
19 #include <time.h>
20 #include <sched.h>
21 #include <limits.h>
22 #include <stdbool.h>
23 #include <sys/time.h>
24 #include <sys/socket.h>
25 #include <sys/ioctl.h>
26 #include <sys/resource.h>
27 #include <sys/epoll.h>
28 /* Kernel < 2.6.26 */
29 #include <linux/if.h>
30 #include <linux/socket.h>
31 #include <linux/types.h>
32 /* Kernel < 2.6.26 */
33 #include <linux/if_ether.h>
34 #include <linux/if_packet.h>
35 #include <linux/sockios.h>
36 #include <netinet/tcp.h>
37 #include <netinet/udp.h>
39 #include "die.h"
40 #include "xsys.h"
41 #include "xstring.h"
42 #include "ring.h"
43 #include "tprintf.h"
44 #include "built_in.h"
46 int af_socket(int af)
48 int sock;
50 if (unlikely(af != AF_INET && af != AF_INET6)) {
51 whine("Wrong AF socket type! Falling back to AF_INET\n");
52 af = AF_INET;
55 sock = socket(af, SOCK_DGRAM, 0);
56 if (unlikely(sock < 0))
57 panic("Creation AF socket failed!\n");
59 return sock;
62 int pf_socket(void)
64 int sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
65 if (unlikely(sock < 0))
66 panic("Creation of PF socket failed!\n");
68 return sock;
71 void set_udp_cork(int fd)
73 int state = 1;
74 setsockopt(fd, IPPROTO_UDP, UDP_CORK, &state, sizeof(state));
77 void set_udp_uncork(int fd)
79 int state = 0;
80 setsockopt(fd, IPPROTO_UDP, UDP_CORK, &state, sizeof(state));
83 void set_tcp_cork(int fd)
85 int state = 1;
86 setsockopt(fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
89 void set_tcp_uncork(int fd)
91 int state = 0;
92 setsockopt(fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
95 void set_sock_cork(int fd, int udp)
97 if (!!udp)
98 set_udp_cork(fd);
99 else
100 set_tcp_cork(fd);
103 void set_sock_uncork(int fd, int udp)
105 if (!!udp)
106 set_udp_uncork(fd);
107 else
108 set_tcp_uncork(fd);
111 int set_nonblocking(int fd)
113 int ret = fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK);
114 if (unlikely(ret < 0))
115 panic("Cannot fcntl!\n");
117 return 0;
120 int set_nonblocking_sloppy(int fd)
122 return fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK);
125 void set_socket_keepalive(int fd)
127 int one = 1;
128 setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one));
131 void set_tcp_nodelay(int fd)
133 int one = 1;
134 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
137 int set_ipv6_only(int fd)
139 int one = 1;
140 return setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
143 int set_reuseaddr(int fd)
145 int ret, one = 1;
147 ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof (one));
148 if (unlikely(ret < 0))
149 panic("Cannot reuse addr!\n");
151 return 0;
154 void set_mtu_disc_dont(int fd)
156 int mtu = IP_PMTUDISC_DONT;
157 setsockopt(fd, SOL_IP, IP_MTU_DISCOVER, &mtu, sizeof(mtu));
160 void set_epoll_descriptor(int fd_epoll, int action, int fd_toadd, int events)
162 int ret;
163 struct epoll_event ev;
165 memset(&ev, 0, sizeof(ev));
166 ev.events = events;
167 ev.data.fd = fd_toadd;
169 ret = epoll_ctl(fd_epoll, action, fd_toadd, &ev);
170 if (ret < 0)
171 panic("Cannot add socket for epoll!\n");
174 int set_epoll_descriptor2(int fd_epoll, int action, int fd_toadd, int events)
176 struct epoll_event ev;
178 memset(&ev, 0, sizeof(ev));
179 ev.events = events;
180 ev.data.fd = fd_toadd;
182 return epoll_ctl(fd_epoll, action, fd_toadd, &ev);
185 int wireless_bitrate(const char *ifname)
187 int sock, ret, rate_in_mbit;
188 struct iwreq iwr;
190 sock = af_socket(AF_INET);
192 memset(&iwr, 0, sizeof(iwr));
193 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
195 ret = ioctl(sock, SIOCGIWRATE, &iwr);
196 if (!ret)
197 rate_in_mbit = iwr.u.bitrate.value / 1000000;
198 else
199 rate_in_mbit = 0;
201 close(sock);
203 return rate_in_mbit;
206 int adjust_dbm_level(int dbm_val)
208 if (dbm_val >= 64)
209 dbm_val -= 0x100;
210 return dbm_val;
213 int wireless_sigqual(const char *ifname, struct iw_statistics *stats)
215 int ret, sock;
216 struct iwreq iwr;
218 sock = af_socket(AF_INET);
220 memset(&iwr, 0, sizeof(iwr));
221 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
223 iwr.u.data.pointer = (caddr_t) stats;
224 iwr.u.data.length = sizeof(*stats);
225 iwr.u.data.flags = 1;
227 ret = ioctl(sock, SIOCGIWSTATS, &iwr);
229 close(sock);
231 return ret;
234 int wireless_rangemax_sigqual(const char *ifname)
236 int ret, sock, sigqual;
237 struct iwreq iwr;
238 struct iw_range iwrange;
240 sock = af_socket(AF_INET);
242 memset(&iwrange, 0, sizeof(iwrange));
244 memset(&iwr, 0, sizeof(iwr));
245 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
247 iwr.u.data.pointer = (caddr_t) &iwrange;
248 iwr.u.data.length = sizeof(iwrange);
249 iwr.u.data.flags = 0;
251 ret = ioctl(sock, SIOCGIWRANGE, &iwr);
252 if (!ret)
253 sigqual = iwrange.max_qual.qual;
254 else
255 sigqual = 0;
257 close(sock);
259 return sigqual;
262 int ethtool_bitrate(const char *ifname)
264 int ret, sock, bitrate;
265 struct ifreq ifr;
266 struct ethtool_cmd ecmd;
268 sock = af_socket(AF_INET);
270 memset(&ecmd, 0, sizeof(ecmd));
272 memset(&ifr, 0, sizeof(ifr));
273 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
275 ecmd.cmd = ETHTOOL_GSET;
276 ifr.ifr_data = (char *) &ecmd;
278 ret = ioctl(sock, SIOCETHTOOL, &ifr);
279 if (ret) {
280 bitrate = 0;
281 goto out;
284 switch (ecmd.speed) {
285 case SPEED_10:
286 case SPEED_100:
287 case SPEED_1000:
288 case SPEED_10000:
289 bitrate = ecmd.speed;
290 break;
291 default:
292 bitrate = 0;
293 break;
295 out:
296 close(sock);
298 return bitrate;
301 int ethtool_drvinf(const char *ifname, struct ethtool_drvinfo *drvinf)
303 int ret, sock;
304 struct ifreq ifr;
306 sock = af_socket(AF_INET);
308 memset(drvinf, 0, sizeof(*drvinf));
310 memset(&ifr, 0, sizeof(ifr));
311 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
313 drvinf->cmd = ETHTOOL_GDRVINFO;
314 ifr.ifr_data = (char *) drvinf;
316 ret = ioctl(sock, SIOCETHTOOL, &ifr);
318 close(sock);
320 return ret;
323 int device_bitrate(const char *ifname)
325 int speed_c, speed_w;
327 speed_c = ethtool_bitrate(ifname);
328 speed_w = wireless_bitrate(ifname);
330 return (speed_c == 0 ? speed_w : speed_c);
333 int device_ifindex(const char *ifname)
335 int ret, sock, index;
336 struct ifreq ifr;
338 if (!strncmp("any", ifname, strlen("any")))
339 return 0;
341 sock = af_socket(AF_INET);
343 memset(&ifr, 0, sizeof(ifr));
344 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
346 ret = ioctl(sock, SIOCGIFINDEX, &ifr);
347 if (!ret)
348 index = ifr.ifr_ifindex;
349 else
350 index = -1;
352 close(sock);
354 return index;
357 int device_address(const char *ifname, int af, struct sockaddr_storage *ss)
359 int ret, sock;
360 struct ifreq ifr;
362 if (!ss)
363 return -EINVAL;
364 if (!strncmp("any", ifname, strlen("any")))
365 return -EINVAL;
367 sock = af_socket(af);
369 memset(&ifr, 0, sizeof(ifr));
370 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
372 ifr.ifr_addr.sa_family = af;
374 ret = ioctl(sock, SIOCGIFADDR, &ifr);
375 if (!ret)
376 memcpy(ss, &ifr.ifr_addr, sizeof(ifr.ifr_addr));
378 close(sock);
380 return ret;
383 int device_mtu(const char *ifname)
385 int ret, sock, mtu;
386 struct ifreq ifr;
388 sock = af_socket(AF_INET);
390 memset(&ifr, 0, sizeof(ifr));
391 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
393 ret = ioctl(sock, SIOCGIFMTU, &ifr);
394 if (!ret)
395 mtu = ifr.ifr_mtu;
396 else
397 mtu = 0;
399 close(sock);
401 return mtu;
404 short device_get_flags(const char *ifname)
406 /* Really, it's short! Look at struct ifreq */
407 short flags;
408 int ret, sock;
409 struct ifreq ifr;
411 sock = af_socket(AF_INET);
413 memset(&ifr, 0, sizeof(ifr));
414 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
416 ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
417 if (!ret)
418 flags = ifr.ifr_flags;
419 else
420 flags = 0;
422 close(sock);
424 return flags;
427 void device_set_flags(const char *ifname, const short flags)
429 int ret, sock;
430 struct ifreq ifr;
432 sock = af_socket(AF_INET);
434 memset(&ifr, 0, sizeof(ifr));
435 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
437 ifr.ifr_flags = flags;
439 ret = ioctl(sock, SIOCSIFFLAGS, &ifr);
440 if (ret < 0)
441 panic("Cannot set NIC flags!\n");
443 close(sock);
446 int device_irq_number(const char *ifname)
449 * Since fetching IRQ numbers from SIOCGIFMAP is deprecated and not
450 * supported anymore, we need to grab them from procfs
452 int irq = 0;
453 char *buffp;
454 char buff[512];
455 char sysname[512];
457 if (!strncmp("lo", ifname, strlen("lo")))
458 return 0;
460 FILE *fp = fopen("/proc/interrupts", "r");
461 if (!fp) {
462 whine("Cannot open /proc/interrupts!\n");
463 return -ENOENT;
466 memset(buff, 0, sizeof(buff));
467 while (fgets(buff, sizeof(buff), fp) != NULL) {
468 buff[sizeof(buff) - 1] = 0;
470 if (strstr(buff, ifname) == NULL)
471 continue;
473 buffp = buff;
474 while (*buffp != ':')
475 buffp++;
476 *buffp = 0;
477 irq = atoi(buff);
479 memset(buff, 0, sizeof(buff));
482 fclose(fp);
484 if (irq != 0)
485 return irq;
487 * Try sysfs as fallback. Probably wireless devices will be found
488 * here. We return silently if it fails ...
490 slprintf(sysname, sizeof(sysname), "/sys/class/net/%s/device/irq",
491 ifname);
493 fp = fopen(sysname, "r");
494 if (!fp)
495 return -ENOENT;
497 memset(buff, 0, sizeof(buff));
498 if(fgets(buff, sizeof(buff), fp) != NULL) {
499 buff[sizeof(buff) - 1] = 0;
500 irq = atoi(buff);
503 fclose(fp);
505 return irq;
508 int device_bind_irq_to_cpu(int irq, int cpu)
510 int ret;
511 char buff[256];
512 char file[256];
514 /* Note: first CPU begins with CPU 0 */
515 if (irq < 0 || cpu < 0)
516 return -EINVAL;
518 memset(file, 0, sizeof(file));
519 memset(buff, 0, sizeof(buff));
521 /* smp_affinity starts counting with CPU 1, 2, ... */
522 cpu = cpu + 1;
523 sprintf(file, "/proc/irq/%d/smp_affinity", irq);
525 FILE *fp = fopen(file, "w");
526 if (!fp) {
527 whine("Cannot open file %s!\n", file);
528 return -ENOENT;
531 sprintf(buff, "%d", cpu);
532 ret = fwrite(buff, sizeof(buff), 1, fp);
534 fclose(fp);
535 return (ret > 0 ? 0 : ret);
538 void sock_print_net_stats(int sock)
540 int ret;
541 struct tpacket_stats kstats;
543 socklen_t slen = sizeof(kstats);
545 memset(&kstats, 0, sizeof(kstats));
547 ret = getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &kstats, &slen);
548 if (ret > -1) {
549 printf("\r%12d frames incoming\n",
550 kstats.tp_packets);
551 printf("\r%12d frames passed filter\n",
552 kstats.tp_packets - kstats.tp_drops);
553 printf("\r%12d frames failed filter (out of space)\n",
554 kstats.tp_drops);
555 if (kstats.tp_packets > 0)
556 printf("\r%12.4f%% frame droprate\n", 1.f *
557 kstats.tp_drops / kstats.tp_packets * 100.f);
561 void register_signal(int signal, void (*handler)(int))
563 sigset_t block_mask;
564 struct sigaction saction;
566 sigfillset(&block_mask);
568 saction.sa_handler = handler;
569 saction.sa_mask = block_mask;
570 saction.sa_flags = SA_RESTART;
571 sigaction(signal, &saction, NULL);
574 void register_signal_f(int signal, void (*handler)(int), int flags)
576 sigset_t block_mask;
577 struct sigaction saction;
579 sigfillset(&block_mask);
581 saction.sa_handler = handler;
582 saction.sa_mask = block_mask;
583 saction.sa_flags = flags;
584 sigaction(signal, &saction, NULL);
587 int get_tty_size(void)
589 #ifdef TIOCGSIZE
590 struct ttysize ts = {0};
591 int ret = ioctl(0, TIOCGSIZE, &ts);
592 return (ret == 0 ? ts.ts_cols : DEFAULT_TTY_SIZE);
593 #elif defined(TIOCGWINSZ)
594 struct winsize ts;
595 memset(&ts, 0, sizeof(ts));
596 int ret = ioctl(0, TIOCGWINSZ, &ts);
597 return (ret == 0 ? ts.ws_col : DEFAULT_TTY_SIZE);
598 #else
599 return DEFAULT_TTY_SIZE;
600 #endif
603 void check_for_root_maybe_die(void)
605 if (geteuid() != 0 || geteuid() != getuid())
606 panic("Uhhuh, not root?!\n");
609 short enter_promiscuous_mode(char *ifname)
611 short ifflags;
613 if (!strncmp("any", ifname, strlen("any")))
614 return 0;
616 ifflags = device_get_flags(ifname);
617 device_set_flags(ifname, ifflags | IFF_PROMISC);
619 return ifflags;
622 void leave_promiscuous_mode(char *ifname, short oldflags)
624 if (!strncmp("any", ifname, strlen("any")))
625 return;
626 device_set_flags(ifname, oldflags);
629 int device_up(char *ifname)
631 if (!ifname)
632 return -EINVAL;
633 if (!strncmp("any", ifname, strlen("any")))
634 return 1;
635 return (device_get_flags(ifname) & IFF_UP) == IFF_UP;
638 int device_running(char *ifname)
640 if (!ifname)
641 return -EINVAL;
642 if (!strncmp("any", ifname, strlen("any")))
643 return 1;
644 return (device_get_flags(ifname) & IFF_RUNNING) == IFF_RUNNING;
647 int device_up_and_running(char *ifname)
649 if (!ifname)
650 return -EINVAL;
651 if (!strncmp("any", ifname, strlen("any")))
652 return 1;
653 return (device_get_flags(ifname) & (IFF_UP | IFF_RUNNING)) ==
654 (IFF_UP | IFF_RUNNING);
657 int poll_error_maybe_die(int sock, struct pollfd *pfd)
659 if ((pfd->revents & (POLLHUP | POLLRDHUP | POLLERR | POLLNVAL)) == 0)
660 return POLL_NEXT_PKT;
661 if (pfd->revents & (POLLHUP | POLLRDHUP))
662 panic("Hangup on socket occured!\n");
663 if (pfd->revents & POLLERR) {
664 int tmp;
665 errno = 0;
666 if (recv(sock, &tmp, sizeof(tmp), MSG_PEEK) >= 0)
667 return POLL_NEXT_PKT;
668 if (errno == ENETDOWN)
669 panic("Interface went down!\n");
670 return POLL_MOVE_OUT;
672 if (pfd->revents & POLLNVAL) {
673 whine("Invalid polling request on socket!\n");
674 return POLL_MOVE_OUT;
676 return POLL_NEXT_PKT;
679 static inline char *next_token(char *q, int sep)
681 if (q)
682 q = strchr(q, sep);
684 * glibc defines this as a macro and gcc throws a false
685 * positive ``logical ‘&&’ with non-zero constant will
686 * always evaluate as true'' in older versions. See:
687 * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36513
689 if (q)
690 q++;
691 return q;
694 int set_cpu_affinity(char *str, int inverted)
696 int ret, i, cpus;
697 char *p, *q;
698 cpu_set_t cpu_bitmask;
700 q = str;
702 cpus = get_number_cpus();
704 CPU_ZERO(&cpu_bitmask);
706 for (i = 0; inverted && i < cpus; ++i)
707 CPU_SET(i, &cpu_bitmask);
709 while (p = q, q = next_token(q, ','), p) {
710 unsigned int a; /* Beginning of range */
711 unsigned int b; /* End of range */
712 unsigned int s; /* Stride */
713 char *c1, *c2;
714 if (sscanf(p, "%u", &a) < 1)
715 return -EINVAL;
716 b = a;
717 s = 1;
718 c1 = next_token(p, '-');
719 c2 = next_token(p, ',');
720 if (c1 != NULL && (c2 == NULL || c1 < c2)) {
721 if (sscanf(c1, "%u", &b) < 1)
722 return -EINVAL;
723 c1 = next_token(c1, ':');
724 if (c1 != NULL && (c2 == NULL || c1 < c2))
725 if (sscanf(c1, "%u", &s) < 1)
726 return -EINVAL;
728 if (!(a <= b))
729 return -EINVAL;
730 while (a <= b) {
731 if (inverted)
732 CPU_CLR(a, &cpu_bitmask);
733 else
734 CPU_SET(a, &cpu_bitmask);
735 a += s;
738 ret = sched_setaffinity(getpid(), sizeof(cpu_bitmask),
739 &cpu_bitmask);
740 if (ret)
741 panic("Can't set this cpu affinity!\n");
742 return 0;
745 int set_proc_prio(int priority)
748 * setpriority() is clever, even if you put a nice value which
749 * is out of range it corrects it to the closest valid nice value
751 int ret = setpriority(PRIO_PROCESS, getpid(), priority);
752 if (ret)
753 panic("Can't set nice val to %i!\n", priority);
754 return 0;
757 int set_sched_status(int policy, int priority)
759 int ret, min_prio, max_prio;
760 struct sched_param sp;
762 max_prio = sched_get_priority_max(policy);
763 min_prio = sched_get_priority_min(policy);
765 if (max_prio == -1 || min_prio == -1)
766 whine("Cannot determine scheduler prio limits!\n");
767 else if (priority < min_prio)
768 priority = min_prio;
769 else if (priority > max_prio)
770 priority = max_prio;
772 memset(&sp, 0, sizeof(sp));
773 sp.sched_priority = priority;
775 ret = sched_setscheduler(getpid(), policy, &sp);
776 if (ret) {
777 whine("Cannot set scheduler policy!\n");
778 return -EINVAL;
781 ret = sched_setparam(getpid(), &sp);
782 if (ret) {
783 whine("Cannot set scheduler prio!\n");
784 return -EINVAL;
787 return 0;
790 int set_timeout(struct timeval *timeval, unsigned int msec)
792 if (msec == 0)
793 return -EINVAL;
795 timeval->tv_sec = 0;
796 timeval->tv_usec = 0;
798 if (msec < 1000) {
799 timeval->tv_usec = msec * 1000;
800 return 0;
803 timeval->tv_sec = (long) (msec / 1000);
804 timeval->tv_usec = (long) ((msec - (timeval->tv_sec * 1000)) * 1000);
806 return 0;