xsys: included psched routines into xsys
[netsniff-ng.git] / src / xsys.c
blob46a01e2b7bec763c2172249e10133509176bf6a2
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 <sys/socket.h>
20 #include <sys/ioctl.h>
21 /* Kernel < 2.6.26 */
22 #include <linux/if.h>
23 #include <linux/socket.h>
24 #include <linux/types.h>
25 /* Kernel < 2.6.26 */
26 #include <linux/if_ether.h>
27 #include <linux/if_packet.h>
28 #include <linux/sockios.h>
29 #include <sched.h>
30 #include <sys/resource.h>
32 #include "die.h"
33 #include "xsys.h"
34 #include "strlcpy.h"
36 int af_socket(int af)
38 int sock;
39 if (af != AF_INET && af != AF_INET6) {
40 whine("Wrong AF socket type! Falling back to AF_INET\n");
41 af = AF_INET;
43 sock = socket(af, SOCK_DGRAM, 0);
44 if (sock < 0)
45 panic("Creation AF socket failed!\n");
46 return sock;
49 int af_raw_socket(int af, int proto)
51 int sock;
52 if (af != AF_INET && af != AF_INET6) {
53 whine("Wrong AF socket type! Falling back to AF_INET\n");
54 af = AF_INET;
56 sock = socket(af, SOCK_RAW, proto);
57 if (sock < 0)
58 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 (sock < 0)
66 panic("Creation of PF socket failed!\n");
67 return sock;
70 int set_nonblocking(int fd)
72 int ret = fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK);
73 if (ret < 0)
74 panic("Cannot fcntl!\n");
75 return 0;
78 int set_nonblocking_sloppy(int fd)
80 return fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK);
83 int set_reuseaddr(int fd)
85 int one = 1;
86 int ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof (one));
87 if (ret < 0)
88 panic("Cannot reuse addr!\n");
89 return 0;
92 int wireless_bitrate(const char *ifname)
94 int sock, ret, rate_in_mbit;
95 struct iwreq iwr;
96 sock = af_socket(AF_INET);
97 memset(&iwr, 0, sizeof(iwr));
98 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
99 ret = ioctl(sock, SIOCGIWRATE, &iwr);
100 if (!ret)
101 rate_in_mbit = iwr.u.bitrate.value / 1000000;
102 else
103 rate_in_mbit = 0;
104 close(sock);
105 return rate_in_mbit;
108 int wireless_essid(const char *ifname, char *essid)
110 int ret, sock, essid_len;
111 struct iwreq iwr;
112 sock = af_socket(AF_INET);
113 memset(&iwr, 0, sizeof(iwr));
114 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
115 iwr.u.essid.pointer = essid;
116 iwr.u.essid.length = IW_ESSID_MAX_SIZE;
117 ret = ioctl(sock, SIOCGIWESSID, &iwr);
118 if (!ret)
119 essid_len = iwr.u.essid.length;
120 else
121 essid_len = 0;
122 close(sock);
123 return essid_len;
126 int adjust_dbm_level(int dbm_val)
128 if (dbm_val >= 64)
129 dbm_val -= 0x100;
130 return dbm_val;
133 int dbm_to_mwatt(const int in)
135 /* From Jean Tourrilhes <jt@hpl.hp.com> (iwlib.c) */
136 int ip = in / 10;
137 int fp = in % 10;
138 int k;
139 double res = 1.0;
140 for (k = 0; k < ip; k++)
141 res *= 10;
142 for (k = 0; k < fp; k++)
143 res *= 1.25892541179; /* LOG10_MAGIC */
144 return (int) res;
147 int wireless_tx_power(const char *ifname)
149 int ret, sock, tx_power;
150 struct iwreq iwr;
152 sock = af_socket(AF_INET);
154 memset(&iwr, 0, sizeof(iwr));
155 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
157 ret = ioctl(sock, SIOCGIWTXPOW, &iwr);
158 if (!ret)
159 tx_power = iwr.u.txpower.value;
160 else
161 tx_power = 0;
163 close(sock);
164 return ret;
167 int wireless_sigqual(const char *ifname, struct iw_statistics *stats)
169 int ret, sock;
170 struct iwreq iwr;
171 sock = af_socket(AF_INET);
172 memset(&iwr, 0, sizeof(iwr));
173 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
174 iwr.u.data.pointer = (caddr_t) stats;
175 iwr.u.data.length = sizeof(*stats);
176 iwr.u.data.flags = 1;
177 ret = ioctl(sock, SIOCGIWSTATS, &iwr);
178 close(sock);
179 return ret;
182 int wireless_rangemax_sigqual(const char *ifname)
184 int ret, sock, sigqual;
185 struct iwreq iwr;
186 struct iw_range iwrange;
187 sock = af_socket(AF_INET);
188 memset(&iwrange, 0, sizeof(iwrange));
189 memset(&iwr, 0, sizeof(iwr));
190 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
191 iwr.u.data.pointer = (caddr_t) &iwrange;
192 iwr.u.data.length = sizeof(iwrange);
193 iwr.u.data.flags = 0;
194 ret = ioctl(sock, SIOCGIWRANGE, &iwr);
195 if (!ret)
196 sigqual = iwrange.max_qual.qual;
197 else
198 sigqual = 0;
199 close(sock);
200 return sigqual;
203 int ethtool_bitrate(const char *ifname)
205 int ret, sock, bitrate;
206 struct ifreq ifr;
207 struct ethtool_cmd ecmd;
208 sock = af_socket(AF_INET);
209 memset(&ecmd, 0, sizeof(ecmd));
210 memset(&ifr, 0, sizeof(ifr));
211 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
212 ecmd.cmd = ETHTOOL_GSET;
213 ifr.ifr_data = (char *) &ecmd;
214 ret = ioctl(sock, SIOCETHTOOL, &ifr);
215 if (ret) {
216 bitrate = 0;
217 goto out;
219 switch (ecmd.speed) {
220 case SPEED_10:
221 case SPEED_100:
222 case SPEED_1000:
223 case SPEED_10000:
224 bitrate = ecmd.speed;
225 break;
226 default:
227 bitrate = 0;
228 break;
230 out:
231 close(sock);
232 return bitrate;
235 int ethtool_drvinf(const char *ifname, struct ethtool_drvinfo *drvinf)
237 int ret, sock;
238 struct ifreq ifr;
239 sock = af_socket(AF_INET);
240 memset(drvinf, 0, sizeof(*drvinf));
241 memset(&ifr, 0, sizeof(ifr));
242 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
243 drvinf->cmd = ETHTOOL_GDRVINFO;
244 ifr.ifr_data = (char *) drvinf;
245 ret = ioctl(sock, SIOCETHTOOL, &ifr);
246 close(sock);
247 return ret;
250 int device_bitrate(const char *ifname)
252 int speed_c, speed_w;
253 /* Probe for speed rates */
254 speed_c = ethtool_bitrate(ifname);
255 speed_w = wireless_bitrate(ifname);
256 return (speed_c == 0 ? speed_w : speed_c);
259 int device_ifindex(const char *ifname)
261 int ret, sock, index;
262 struct ifreq ifr;
263 if (!strncmp("any", ifname, strlen("any")))
264 return 0;
265 sock = af_socket(AF_INET);
266 memset(&ifr, 0, sizeof(ifr));
267 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
268 ret = ioctl(sock, SIOCGIFINDEX, &ifr);
269 if (!ret)
270 index = ifr.ifr_ifindex;
271 else
272 index = -1;
273 close(sock);
274 return index;
277 int device_address(const char *ifname, int af, struct sockaddr_storage *ss)
279 int ret, sock;
280 struct ifreq ifr;
281 if (!ss)
282 return -EINVAL;
283 if (!strncmp("any", ifname, strlen("any")))
284 return -EINVAL;
285 sock = af_socket(af);
286 memset(&ifr, 0, sizeof(ifr));
287 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
288 ifr.ifr_addr.sa_family = af;
289 ret = ioctl(sock, SIOCGIFADDR, &ifr);
290 if (!ret)
291 memcpy(ss, &ifr.ifr_addr, sizeof(ifr.ifr_addr));
292 close(sock);
293 return ret;
296 int device_mtu(const char *ifname)
298 int ret, sock, mtu;
299 struct ifreq ifr;
300 sock = af_socket(AF_INET);
301 memset(&ifr, 0, sizeof(ifr));
302 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;
308 close(sock);
309 return mtu;
312 short device_get_flags(const char *ifname)
314 /* Really, it's short! Look at struct ifreq */
315 short flags;
316 int ret, sock;
317 struct ifreq ifr;
318 sock = af_socket(AF_INET);
319 memset(&ifr, 0, sizeof(ifr));
320 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
321 ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
322 if (!ret)
323 flags = ifr.ifr_flags;
324 else
325 flags = 0;
326 close(sock);
327 return flags;
330 void device_set_flags(const char *ifname, const short flags)
332 int ret, sock;
333 struct ifreq ifr;
334 sock = af_socket(AF_INET);
335 memset(&ifr, 0, sizeof(ifr));
336 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
337 ifr.ifr_flags = flags;
338 ret = ioctl(sock, SIOCSIFFLAGS, &ifr);
339 if (ret < 0)
340 panic("Cannot set NIC flags!\n");
341 close(sock);
344 int device_irq_number(const char *ifname)
347 * Since fetching IRQ numbers from SIOCGIFMAP is deprecated and not
348 * supported anymore, we need to grab them from procfs
350 int irq = 0;
351 char *buffp;
352 char buff[512];
353 char sysname[512];
354 if (!strncmp("lo", ifname, strlen("lo")))
355 return 0;
356 FILE *fp = fopen("/proc/interrupts", "r");
357 if (!fp) {
358 whine("Cannot open /proc/interrupts!\n");
359 return -ENOENT;
361 memset(buff, 0, sizeof(buff));
362 while (fgets(buff, sizeof(buff), fp) != NULL) {
363 buff[sizeof(buff) - 1] = 0;
364 if (strstr(buff, ifname) == NULL)
365 continue;
366 buffp = buff;
367 while (*buffp != ':')
368 buffp++;
369 *buffp = 0;
370 irq = atoi(buff);
371 memset(buff, 0, sizeof(buff));
373 fclose(fp);
374 if (irq != 0)
375 return irq;
377 * Try sysfs as fallback. Probably wireless devices will be found
378 * here. We return silently if it fails ...
380 slprintf(sysname, sizeof(sysname), "/sys/class/net/%s/device/irq",
381 ifname);
382 fp = fopen(sysname, "r");
383 if (!fp)
384 return -ENOENT;
385 memset(buff, 0, sizeof(buff));
386 if(fgets(buff, sizeof(buff), fp) != NULL) {
387 buff[sizeof(buff) - 1] = 0;
388 irq = atoi(buff);
390 fclose(fp);
391 return irq;
394 int device_bind_irq_to_cpu(int irq, int cpu)
396 int ret;
397 char buff[256];
398 char file[256];
399 /* Note: first CPU begins with CPU 0 */
400 if (irq < 0 || cpu < 0)
401 return -EINVAL;
402 memset(file, 0, sizeof(file));
403 memset(buff, 0, sizeof(buff));
404 /* smp_affinity starts counting with CPU 1, 2, ... */
405 cpu = cpu + 1;
406 sprintf(file, "/proc/irq/%d/smp_affinity", irq);
407 FILE *fp = fopen(file, "w");
408 if (!fp) {
409 whine("Cannot open file %s!\n", file);
410 return -ENOENT;
412 sprintf(buff, "%d", cpu);
413 ret = fwrite(buff, sizeof(buff), 1, fp);
414 fclose(fp);
415 return (ret > 0 ? 0 : ret);
418 void sock_print_net_stats(int sock)
420 int ret;
421 struct tpacket_stats kstats;
422 socklen_t slen = sizeof(kstats);
423 memset(&kstats, 0, sizeof(kstats));
424 ret = getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &kstats, &slen);
425 if (ret > -1) {
426 printf("\r%12d frames incoming\n",
427 kstats.tp_packets);
428 printf("\r%12d frames passed filter\n",
429 kstats.tp_packets - kstats.tp_drops);
430 printf("\r%12d frames failed filter (out of space)\n",
431 kstats.tp_drops);
432 if (kstats.tp_packets > 0)
433 printf("\r%12.4f%% frame droprate\n", 1.f *
434 kstats.tp_drops / kstats.tp_packets * 100.f);
438 void register_signal(int signal, void (*handler)(int))
440 sigset_t block_mask;
441 struct sigaction saction;
442 sigfillset(&block_mask);
443 saction.sa_handler = handler;
444 saction.sa_mask = block_mask;
445 saction.sa_flags = SA_RESTART;
446 sigaction(signal, &saction, NULL);
449 void register_signal_f(int signal, void (*handler)(int), int flags)
451 sigset_t block_mask;
452 struct sigaction saction;
453 sigfillset(&block_mask);
454 saction.sa_handler = handler;
455 saction.sa_mask = block_mask;
456 saction.sa_flags = flags;
457 sigaction(signal, &saction, NULL);
460 int get_tty_size(void)
462 #ifdef TIOCGSIZE
463 struct ttysize ts = {0};
464 int ret = ioctl(0, TIOCGSIZE, &ts);
465 return (ret == 0 ? ts.ts_cols : DEFAULT_TTY_SIZE);
466 #elif defined(TIOCGWINSZ)
467 struct winsize ts;
468 memset(&ts, 0, sizeof(ts));
469 int ret = ioctl(0, TIOCGWINSZ, &ts);
470 return (ret == 0 ? ts.ws_col : DEFAULT_TTY_SIZE);
471 #else
472 return DEFAULT_TTY_SIZE;
473 #endif
476 void check_for_root_maybe_die(void)
478 if (geteuid() != 0 || geteuid() != getuid())
479 panic("Uhhuh, not root?!\n");
482 short enter_promiscuous_mode(char *ifname)
484 if (!strncmp("any", ifname, strlen("any")))
485 return 0;
486 short ifflags = device_get_flags(ifname);
487 device_set_flags(ifname, ifflags | IFF_PROMISC);
488 return ifflags;
491 void leave_promiscuous_mode(char *ifname, short oldflags)
493 if (!strncmp("any", ifname, strlen("any")))
494 return;
495 device_set_flags(ifname, oldflags);
498 int device_up(char *ifname)
500 if (!ifname)
501 return -EINVAL;
502 if (!strncmp("any", ifname, strlen("any")))
503 return 1;
504 return (device_get_flags(ifname) & IFF_UP) == IFF_UP;
507 int device_running(char *ifname)
509 if (!ifname)
510 return -EINVAL;
511 if (!strncmp("any", ifname, strlen("any")))
512 return 1;
513 return (device_get_flags(ifname) & IFF_RUNNING) == IFF_RUNNING;
516 int device_up_and_running(char *ifname)
518 if (!ifname)
519 return -EINVAL;
520 if (!strncmp("any", ifname, strlen("any")))
521 return 1;
522 return (device_get_flags(ifname) & (IFF_UP | IFF_RUNNING)) ==
523 (IFF_UP | IFF_RUNNING);
526 int poll_error_maybe_die(int sock, struct pollfd *pfd)
528 if ((pfd->revents & (POLLHUP | POLLRDHUP | POLLERR | POLLNVAL)) == 0)
529 return POLL_NEXT_PKT;
530 if (pfd->revents & (POLLHUP | POLLRDHUP))
531 panic("Hangup on socket occured!\n");
532 if (pfd->revents & POLLERR) {
533 int tmp;
534 errno = 0;
535 /* recv is more specififc on the error */
536 if (recv(sock, &tmp, sizeof(tmp), MSG_PEEK) >= 0)
537 return POLL_NEXT_PKT;
538 if (errno == ENETDOWN)
539 panic("Interface went down!\n");
540 return POLL_MOVE_OUT;
542 if (pfd->revents & POLLNVAL) {
543 whine("Invalid polling request on socket!\n");
544 return POLL_MOVE_OUT;
546 return POLL_NEXT_PKT;
549 static inline const char *next_token(const char *q, int sep)
551 if (q)
552 q = strchr(q, sep);
553 if (q)
554 q++;
555 return (q);
558 int set_cpu_affinity(const char *str, int inverted)
560 int ret, i, cpus;
561 const char *p, *q;
562 cpu_set_t cpu_bitmask;
563 q = str;
564 cpus = get_number_cpus();
565 CPU_ZERO(&cpu_bitmask);
566 for (i = 0; inverted && i < cpus; ++i)
567 CPU_SET(i, &cpu_bitmask);
568 while (p = q, q = next_token(q, ','), p) {
569 unsigned int a; /* Beginning of range */
570 unsigned int b; /* End of range */
571 unsigned int s; /* Stride */
572 const char *c1, *c2;
573 if (sscanf(p, "%u", &a) < 1)
574 return -EINVAL;
575 b = a;
576 s = 1;
577 c1 = next_token(p, '-');
578 c2 = next_token(p, ',');
579 if (c1 != NULL && (c2 == NULL || c1 < c2)) {
580 if (sscanf(c1, "%u", &b) < 1)
581 return -EINVAL;
582 c1 = next_token(c1, ':');
583 if (c1 != NULL && (c2 == NULL || c1 < c2))
584 if (sscanf(c1, "%u", &s) < 1)
585 return -EINVAL;
587 if (!(a <= b))
588 return -EINVAL;
589 while (a <= b) {
590 if (inverted)
591 CPU_CLR(a, &cpu_bitmask);
592 else
593 CPU_SET(a, &cpu_bitmask);
594 a += s;
597 ret = sched_setaffinity(getpid(), sizeof(cpu_bitmask),
598 &cpu_bitmask);
599 if (ret)
600 panic("Can't set this cpu affinity!\n");
601 return 0;
604 char *get_cpu_affinity(char *cpu_string, size_t len)
606 int ret, i, cpu;
607 cpu_set_t cpu_bitmask;
608 if (len != get_number_cpus() + 1)
609 return NULL;
610 CPU_ZERO(&cpu_bitmask);
611 ret = sched_getaffinity(getpid(), sizeof(cpu_bitmask),
612 &cpu_bitmask);
613 if (ret) {
614 whine("Can't fetch cpu affinity!\n");
615 return NULL;
617 for (i = 0, cpu_string[len - 1] = 0; i < len - 1; ++i) {
618 cpu = CPU_ISSET(i, &cpu_bitmask);
619 cpu_string[i] = (cpu ? '1' : '0');
621 return cpu_string;
624 int set_proc_prio(int priority)
627 * setpriority() is clever, even if you put a nice value which
628 * is out of range it corrects it to the closest valid nice value
630 int ret = setpriority(PRIO_PROCESS, getpid(), priority);
631 if (ret)
632 panic("Can't set nice val to %i!\n", priority);
633 return 0;
636 int set_sched_status(int policy, int priority)
638 int ret, min_prio, max_prio;
639 struct sched_param sp;
640 max_prio = sched_get_priority_max(policy);
641 min_prio = sched_get_priority_min(policy);
642 if (max_prio == -1 || min_prio == -1)
643 whine("Cannot determine scheduler prio limits!\n");
644 else if (priority < min_prio)
645 priority = min_prio;
646 else if (priority > max_prio)
647 priority = max_prio;
648 memset(&sp, 0, sizeof(sp));
649 sp.sched_priority = priority;
650 ret = sched_setscheduler(getpid(), policy, &sp);
651 if (ret) {
652 whine("Cannot set scheduler policy!\n");
653 return -EINVAL;
655 ret = sched_setparam(getpid(), &sp);
656 if (ret) {
657 whine("Cannot set scheduler prio!\n");
658 return -EINVAL;
660 return 0;