ring: built_in: fix if cacheline_aligned is not defined
[netsniff-ng.git] / src / xsys.c
blob476a000349061d2e4d6be7f942f4b4e97a9cb63d
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 <assert.h>
22 #include <limits.h>
23 #include <stdbool.h>
24 #include <sys/time.h>
25 #include <sys/socket.h>
26 #include <sys/ioctl.h>
27 #include <sys/resource.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>
37 #include "die.h"
38 #include "xsys.h"
39 #include "xstring.h"
40 #include "built_in.h"
42 int af_socket(int af)
44 int sock;
45 if (unlikely(af != AF_INET && af != AF_INET6)) {
46 whine("Wrong AF socket type! Falling back to AF_INET\n");
47 af = AF_INET;
49 sock = socket(af, SOCK_DGRAM, 0);
50 if (unlikely(sock < 0))
51 panic("Creation AF socket failed!\n");
52 return sock;
55 int af_raw_socket(int af, int proto)
57 int sock;
58 if (unlikely(af != AF_INET && af != AF_INET6)) {
59 whine("Wrong AF socket type! Falling back to AF_INET\n");
60 af = AF_INET;
62 sock = socket(af, SOCK_RAW, proto);
63 if (unlikely(sock < 0))
64 panic("Creation AF socket failed!\n");
65 return sock;
68 int pf_socket(void)
70 int sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
71 if (unlikely(sock < 0))
72 panic("Creation of PF socket failed!\n");
73 return sock;
76 int set_nonblocking(int fd)
78 int ret = fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK);
79 if (unlikely(ret < 0))
80 panic("Cannot fcntl!\n");
81 return 0;
84 int set_nonblocking_sloppy(int fd)
86 return fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK);
89 int set_reuseaddr(int fd)
91 int ret, one = 1;
92 ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof (one));
93 if (unlikely(ret < 0))
94 panic("Cannot reuse addr!\n");
95 return 0;
98 int wireless_bitrate(const char *ifname)
100 int sock, ret, rate_in_mbit;
101 struct iwreq iwr;
102 sock = af_socket(AF_INET);
103 memset(&iwr, 0, sizeof(iwr));
104 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
105 ret = ioctl(sock, SIOCGIWRATE, &iwr);
106 if (!ret)
107 rate_in_mbit = iwr.u.bitrate.value / 1000000;
108 else
109 rate_in_mbit = 0;
110 close(sock);
111 return rate_in_mbit;
114 int adjust_dbm_level(int dbm_val)
116 if (dbm_val >= 64)
117 dbm_val -= 0x100;
118 return dbm_val;
121 int wireless_sigqual(const char *ifname, struct iw_statistics *stats)
123 int ret, sock;
124 struct iwreq iwr;
125 sock = af_socket(AF_INET);
126 memset(&iwr, 0, sizeof(iwr));
127 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
128 iwr.u.data.pointer = (caddr_t) stats;
129 iwr.u.data.length = sizeof(*stats);
130 iwr.u.data.flags = 1;
131 ret = ioctl(sock, SIOCGIWSTATS, &iwr);
132 close(sock);
133 return ret;
136 int wireless_rangemax_sigqual(const char *ifname)
138 int ret, sock, sigqual;
139 struct iwreq iwr;
140 struct iw_range iwrange;
141 sock = af_socket(AF_INET);
142 memset(&iwrange, 0, sizeof(iwrange));
143 memset(&iwr, 0, sizeof(iwr));
144 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
145 iwr.u.data.pointer = (caddr_t) &iwrange;
146 iwr.u.data.length = sizeof(iwrange);
147 iwr.u.data.flags = 0;
148 ret = ioctl(sock, SIOCGIWRANGE, &iwr);
149 if (!ret)
150 sigqual = iwrange.max_qual.qual;
151 else
152 sigqual = 0;
153 close(sock);
154 return sigqual;
157 int ethtool_bitrate(const char *ifname)
159 int ret, sock, bitrate;
160 struct ifreq ifr;
161 struct ethtool_cmd ecmd;
162 sock = af_socket(AF_INET);
163 memset(&ecmd, 0, sizeof(ecmd));
164 memset(&ifr, 0, sizeof(ifr));
165 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
166 ecmd.cmd = ETHTOOL_GSET;
167 ifr.ifr_data = (char *) &ecmd;
168 ret = ioctl(sock, SIOCETHTOOL, &ifr);
169 if (ret) {
170 bitrate = 0;
171 goto out;
173 switch (ecmd.speed) {
174 case SPEED_10:
175 case SPEED_100:
176 case SPEED_1000:
177 case SPEED_10000:
178 bitrate = ecmd.speed;
179 break;
180 default:
181 bitrate = 0;
182 break;
184 out:
185 close(sock);
186 return bitrate;
189 int ethtool_drvinf(const char *ifname, struct ethtool_drvinfo *drvinf)
191 int ret, sock;
192 struct ifreq ifr;
193 sock = af_socket(AF_INET);
194 memset(drvinf, 0, sizeof(*drvinf));
195 memset(&ifr, 0, sizeof(ifr));
196 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
197 drvinf->cmd = ETHTOOL_GDRVINFO;
198 ifr.ifr_data = (char *) drvinf;
199 ret = ioctl(sock, SIOCETHTOOL, &ifr);
200 close(sock);
201 return ret;
204 int device_bitrate(const char *ifname)
206 int speed_c, speed_w;
207 speed_c = ethtool_bitrate(ifname);
208 speed_w = wireless_bitrate(ifname);
209 return (speed_c == 0 ? speed_w : speed_c);
212 int device_ifindex(const char *ifname)
214 int ret, sock, index;
215 struct ifreq ifr;
216 if (!strncmp("any", ifname, strlen("any")))
217 return 0;
218 sock = af_socket(AF_INET);
219 memset(&ifr, 0, sizeof(ifr));
220 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
221 ret = ioctl(sock, SIOCGIFINDEX, &ifr);
222 if (!ret)
223 index = ifr.ifr_ifindex;
224 else
225 index = -1;
226 close(sock);
227 return index;
230 int device_address(const char *ifname, int af, struct sockaddr_storage *ss)
232 int ret, sock;
233 struct ifreq ifr;
234 if (!ss)
235 return -EINVAL;
236 if (!strncmp("any", ifname, strlen("any")))
237 return -EINVAL;
238 sock = af_socket(af);
239 memset(&ifr, 0, sizeof(ifr));
240 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
241 ifr.ifr_addr.sa_family = af;
242 ret = ioctl(sock, SIOCGIFADDR, &ifr);
243 if (!ret)
244 memcpy(ss, &ifr.ifr_addr, sizeof(ifr.ifr_addr));
245 close(sock);
246 return ret;
249 int device_mtu(const char *ifname)
251 int ret, sock, mtu;
252 struct ifreq ifr;
253 sock = af_socket(AF_INET);
254 memset(&ifr, 0, sizeof(ifr));
255 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
256 ret = ioctl(sock, SIOCGIFMTU, &ifr);
257 if (!ret)
258 mtu = ifr.ifr_mtu;
259 else
260 mtu = 0;
261 close(sock);
262 return mtu;
265 short device_get_flags(const char *ifname)
267 /* Really, it's short! Look at struct ifreq */
268 short flags;
269 int ret, sock;
270 struct ifreq ifr;
271 sock = af_socket(AF_INET);
272 memset(&ifr, 0, sizeof(ifr));
273 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
274 ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
275 if (!ret)
276 flags = ifr.ifr_flags;
277 else
278 flags = 0;
279 close(sock);
280 return flags;
283 void device_set_flags(const char *ifname, const short flags)
285 int ret, sock;
286 struct ifreq ifr;
287 sock = af_socket(AF_INET);
288 memset(&ifr, 0, sizeof(ifr));
289 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
290 ifr.ifr_flags = flags;
291 ret = ioctl(sock, SIOCSIFFLAGS, &ifr);
292 if (ret < 0)
293 panic("Cannot set NIC flags!\n");
294 close(sock);
297 int device_irq_number(const char *ifname)
300 * Since fetching IRQ numbers from SIOCGIFMAP is deprecated and not
301 * supported anymore, we need to grab them from procfs
303 int irq = 0;
304 char *buffp;
305 char buff[512];
306 char sysname[512];
307 if (!strncmp("lo", ifname, strlen("lo")))
308 return 0;
309 FILE *fp = fopen("/proc/interrupts", "r");
310 if (!fp) {
311 whine("Cannot open /proc/interrupts!\n");
312 return -ENOENT;
314 memset(buff, 0, sizeof(buff));
315 while (fgets(buff, sizeof(buff), fp) != NULL) {
316 buff[sizeof(buff) - 1] = 0;
317 if (strstr(buff, ifname) == NULL)
318 continue;
319 buffp = buff;
320 while (*buffp != ':')
321 buffp++;
322 *buffp = 0;
323 irq = atoi(buff);
324 memset(buff, 0, sizeof(buff));
326 fclose(fp);
327 if (irq != 0)
328 return irq;
330 * Try sysfs as fallback. Probably wireless devices will be found
331 * here. We return silently if it fails ...
333 slprintf(sysname, sizeof(sysname), "/sys/class/net/%s/device/irq",
334 ifname);
335 fp = fopen(sysname, "r");
336 if (!fp)
337 return -ENOENT;
338 memset(buff, 0, sizeof(buff));
339 if(fgets(buff, sizeof(buff), fp) != NULL) {
340 buff[sizeof(buff) - 1] = 0;
341 irq = atoi(buff);
343 fclose(fp);
344 return irq;
347 int device_bind_irq_to_cpu(int irq, int cpu)
349 int ret;
350 char buff[256];
351 char file[256];
352 /* Note: first CPU begins with CPU 0 */
353 if (irq < 0 || cpu < 0)
354 return -EINVAL;
355 memset(file, 0, sizeof(file));
356 memset(buff, 0, sizeof(buff));
357 /* smp_affinity starts counting with CPU 1, 2, ... */
358 cpu = cpu + 1;
359 sprintf(file, "/proc/irq/%d/smp_affinity", irq);
360 FILE *fp = fopen(file, "w");
361 if (!fp) {
362 whine("Cannot open file %s!\n", file);
363 return -ENOENT;
365 sprintf(buff, "%d", cpu);
366 ret = fwrite(buff, sizeof(buff), 1, fp);
367 fclose(fp);
368 return (ret > 0 ? 0 : ret);
371 void sock_print_net_stats(int sock)
373 int ret;
374 struct tpacket_stats kstats;
375 socklen_t slen = sizeof(kstats);
376 memset(&kstats, 0, sizeof(kstats));
377 ret = getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &kstats, &slen);
378 if (ret > -1) {
379 printf("\r%12d frames incoming\n",
380 kstats.tp_packets);
381 printf("\r%12d frames passed filter\n",
382 kstats.tp_packets - kstats.tp_drops);
383 printf("\r%12d frames failed filter (out of space)\n",
384 kstats.tp_drops);
385 if (kstats.tp_packets > 0)
386 printf("\r%12.4f%% frame droprate\n", 1.f *
387 kstats.tp_drops / kstats.tp_packets * 100.f);
391 void register_signal(int signal, void (*handler)(int))
393 sigset_t block_mask;
394 struct sigaction saction;
395 sigfillset(&block_mask);
396 saction.sa_handler = handler;
397 saction.sa_mask = block_mask;
398 saction.sa_flags = SA_RESTART;
399 sigaction(signal, &saction, NULL);
402 void register_signal_f(int signal, void (*handler)(int), int flags)
404 sigset_t block_mask;
405 struct sigaction saction;
406 sigfillset(&block_mask);
407 saction.sa_handler = handler;
408 saction.sa_mask = block_mask;
409 saction.sa_flags = flags;
410 sigaction(signal, &saction, NULL);
413 int get_tty_size(void)
415 #ifdef TIOCGSIZE
416 struct ttysize ts = {0};
417 int ret = ioctl(0, TIOCGSIZE, &ts);
418 return (ret == 0 ? ts.ts_cols : DEFAULT_TTY_SIZE);
419 #elif defined(TIOCGWINSZ)
420 struct winsize ts;
421 memset(&ts, 0, sizeof(ts));
422 int ret = ioctl(0, TIOCGWINSZ, &ts);
423 return (ret == 0 ? ts.ws_col : DEFAULT_TTY_SIZE);
424 #else
425 return DEFAULT_TTY_SIZE;
426 #endif
429 void check_for_root_maybe_die(void)
431 if (geteuid() != 0 || geteuid() != getuid())
432 panic("Uhhuh, not root?!\n");
435 short enter_promiscuous_mode(char *ifname)
437 if (!strncmp("any", ifname, strlen("any")))
438 return 0;
439 short ifflags = device_get_flags(ifname);
440 device_set_flags(ifname, ifflags | IFF_PROMISC);
441 return ifflags;
444 void leave_promiscuous_mode(char *ifname, short oldflags)
446 if (!strncmp("any", ifname, strlen("any")))
447 return;
448 device_set_flags(ifname, oldflags);
451 int device_up(char *ifname)
453 if (!ifname)
454 return -EINVAL;
455 if (!strncmp("any", ifname, strlen("any")))
456 return 1;
457 return (device_get_flags(ifname) & IFF_UP) == IFF_UP;
460 int device_running(char *ifname)
462 if (!ifname)
463 return -EINVAL;
464 if (!strncmp("any", ifname, strlen("any")))
465 return 1;
466 return (device_get_flags(ifname) & IFF_RUNNING) == IFF_RUNNING;
469 int device_up_and_running(char *ifname)
471 if (!ifname)
472 return -EINVAL;
473 if (!strncmp("any", ifname, strlen("any")))
474 return 1;
475 return (device_get_flags(ifname) & (IFF_UP | IFF_RUNNING)) ==
476 (IFF_UP | IFF_RUNNING);
479 int poll_error_maybe_die(int sock, struct pollfd *pfd)
481 if ((pfd->revents & (POLLHUP | POLLRDHUP | POLLERR | POLLNVAL)) == 0)
482 return POLL_NEXT_PKT;
483 if (pfd->revents & (POLLHUP | POLLRDHUP))
484 panic("Hangup on socket occured!\n");
485 if (pfd->revents & POLLERR) {
486 int tmp;
487 errno = 0;
488 if (recv(sock, &tmp, sizeof(tmp), MSG_PEEK) >= 0)
489 return POLL_NEXT_PKT;
490 if (errno == ENETDOWN)
491 panic("Interface went down!\n");
492 return POLL_MOVE_OUT;
494 if (pfd->revents & POLLNVAL) {
495 whine("Invalid polling request on socket!\n");
496 return POLL_MOVE_OUT;
498 return POLL_NEXT_PKT;
501 static inline char *next_token(char *q, int sep)
503 if (q)
504 q = strchr(q, sep);
506 * glibc defines this as a macro and gcc throws a false
507 * positive ``logical ‘&&’ with non-zero constant will
508 * always evaluate as true'' in older versions. See:
509 * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36513
511 if (q)
512 q++;
513 return q;
516 int set_cpu_affinity(char *str, int inverted)
518 int ret, i, cpus;
519 char *p, *q;
520 cpu_set_t cpu_bitmask;
521 q = str;
522 cpus = get_number_cpus();
523 CPU_ZERO(&cpu_bitmask);
524 for (i = 0; inverted && i < cpus; ++i)
525 CPU_SET(i, &cpu_bitmask);
526 while (p = q, q = next_token(q, ','), p) {
527 unsigned int a; /* Beginning of range */
528 unsigned int b; /* End of range */
529 unsigned int s; /* Stride */
530 char *c1, *c2;
531 if (sscanf(p, "%u", &a) < 1)
532 return -EINVAL;
533 b = a;
534 s = 1;
535 c1 = next_token(p, '-');
536 c2 = next_token(p, ',');
537 if (c1 != NULL && (c2 == NULL || c1 < c2)) {
538 if (sscanf(c1, "%u", &b) < 1)
539 return -EINVAL;
540 c1 = next_token(c1, ':');
541 if (c1 != NULL && (c2 == NULL || c1 < c2))
542 if (sscanf(c1, "%u", &s) < 1)
543 return -EINVAL;
545 if (!(a <= b))
546 return -EINVAL;
547 while (a <= b) {
548 if (inverted)
549 CPU_CLR(a, &cpu_bitmask);
550 else
551 CPU_SET(a, &cpu_bitmask);
552 a += s;
555 ret = sched_setaffinity(getpid(), sizeof(cpu_bitmask),
556 &cpu_bitmask);
557 if (ret)
558 panic("Can't set this cpu affinity!\n");
559 return 0;
562 char *get_cpu_affinity(char *cpu_string, size_t len)
564 int ret, i, cpu;
565 cpu_set_t cpu_bitmask;
566 if (len != get_number_cpus() + 1)
567 return NULL;
568 CPU_ZERO(&cpu_bitmask);
569 ret = sched_getaffinity(getpid(), sizeof(cpu_bitmask),
570 &cpu_bitmask);
571 if (ret) {
572 whine("Can't fetch cpu affinity!\n");
573 return NULL;
575 for (i = 0, cpu_string[len - 1] = 0; i < len - 1; ++i) {
576 cpu = CPU_ISSET(i, &cpu_bitmask);
577 cpu_string[i] = (cpu ? '1' : '0');
579 return cpu_string;
582 int set_proc_prio(int priority)
585 * setpriority() is clever, even if you put a nice value which
586 * is out of range it corrects it to the closest valid nice value
588 int ret = setpriority(PRIO_PROCESS, getpid(), priority);
589 if (ret)
590 panic("Can't set nice val to %i!\n", priority);
591 return 0;
594 int set_sched_status(int policy, int priority)
596 int ret, min_prio, max_prio;
597 struct sched_param sp;
598 max_prio = sched_get_priority_max(policy);
599 min_prio = sched_get_priority_min(policy);
600 if (max_prio == -1 || min_prio == -1)
601 whine("Cannot determine scheduler prio limits!\n");
602 else if (priority < min_prio)
603 priority = min_prio;
604 else if (priority > max_prio)
605 priority = max_prio;
606 memset(&sp, 0, sizeof(sp));
607 sp.sched_priority = priority;
608 ret = sched_setscheduler(getpid(), policy, &sp);
609 if (ret) {
610 whine("Cannot set scheduler policy!\n");
611 return -EINVAL;
613 ret = sched_setparam(getpid(), &sp);
614 if (ret) {
615 whine("Cannot set scheduler prio!\n");
616 return -EINVAL;
618 return 0;
621 int set_timeout(struct timeval *timeval, unsigned int msec)
623 if (msec == 0)
624 return -EINVAL;
625 timeval->tv_sec = 0;
626 timeval->tv_usec = 0;
627 if (msec < 1000) {
628 timeval->tv_usec = msec * 1000;
629 return 0;
631 timeval->tv_sec = (long) (msec / 1000);
632 timeval->tv_usec = (long) ((msec - (timeval->tv_sec * 1000)) * 1000);
633 return 0;