cpus: break out cpu related functions from xutils
[netsniff-ng.git] / xutils.c
blob9b81feaeb822b05a3f5833ef610e181f9b334324
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2009, 2010 Daniel Borkmann.
4 * Copyright 2009, 2010 Emmanuel Roullit.
5 * Subject to the GPL, version 2.
6 */
8 #define _GNU_SOURCE
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 <stdarg.h>
17 #include <ctype.h>
18 #include <signal.h>
19 #include <arpa/inet.h>
20 #include <time.h>
21 #include <sched.h>
22 #include <limits.h>
23 #include <stdbool.h>
24 #include <netdb.h>
25 #include <ifaddrs.h>
26 #include <sys/time.h>
27 #include <sys/socket.h>
28 #include <sys/ioctl.h>
29 #include <sys/mman.h>
30 #include <sys/resource.h>
31 #include <sys/epoll.h>
32 #include <sys/syscall.h>
33 #include <asm/unistd.h>
34 #include <linux/if.h>
35 #include <linux/socket.h>
36 #include <linux/types.h>
37 #include <linux/if_ether.h>
38 #include <linux/if_packet.h>
39 #include <linux/sockios.h>
40 #include <netinet/tcp.h>
41 #include <netinet/udp.h>
43 #include "die.h"
44 #include "str.h"
45 #include "xutils.h"
46 #include "ring.h"
47 #include "built_in.h"
49 enum {
50 sock_rmem_max = 0,
51 sock_rmem_def,
52 sock_wmem_max,
53 sock_wmem_def,
56 #define SMEM_SUG_MAX 104857600
57 #define SMEM_SUG_DEF 4194304
59 static const char *const to_prio[] = {
60 "none",
61 "realtime",
62 "best-effort",
63 "idle",
66 static const char *const sock_mem[] = {
67 "/proc/sys/net/core/rmem_max",
68 "/proc/sys/net/core/rmem_default",
69 "/proc/sys/net/core/wmem_max",
70 "/proc/sys/net/core/wmem_default",
73 int af_socket(int af)
75 int sock;
77 if (unlikely(af != AF_INET && af != AF_INET6))
78 panic("Wrong AF socket type!\n");
80 sock = socket(af, SOCK_DGRAM, 0);
81 if (unlikely(sock < 0))
82 panic("Creation AF socket failed!\n");
84 return sock;
87 int pf_socket(void)
89 int sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
90 if (unlikely(sock < 0))
91 panic("Creation of PF socket failed!\n");
93 return sock;
96 void set_sock_prio(int fd, int prio)
98 int ret, val = prio;
100 ret = setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &val, sizeof(val));
101 if (unlikely(ret))
102 panic("Cannot set socket priority!\n");
105 void set_udp_cork(int fd)
107 int ret, state = 1;
109 ret = setsockopt(fd, IPPROTO_UDP, UDP_CORK, &state, sizeof(state));
110 if (unlikely(ret))
111 panic("Cannot cork UDP socket!\n");
114 void set_udp_uncork(int fd)
116 int ret, state = 0;
118 ret = setsockopt(fd, IPPROTO_UDP, UDP_CORK, &state, sizeof(state));
119 if (unlikely(ret))
120 panic("Cannot uncork UDP socket!\n");
123 void set_tcp_cork(int fd)
125 int ret, state = 1;
127 ret = setsockopt(fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
128 if (unlikely(ret))
129 panic("Cannot cork TCP socket!\n");
132 void set_tcp_uncork(int fd)
134 int ret, state = 0;
136 ret = setsockopt(fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
137 if (unlikely(ret))
138 panic("Cannot uncork TCP socket!\n");
141 void set_sock_cork(int fd, int udp)
143 if (!!udp)
144 set_udp_cork(fd);
145 else
146 set_tcp_cork(fd);
149 void set_sock_uncork(int fd, int udp)
151 if (!!udp)
152 set_udp_uncork(fd);
153 else
154 set_tcp_uncork(fd);
157 void set_nonblocking(int fd)
159 int ret = fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK);
160 if (unlikely(ret < 0))
161 panic("Cannot fcntl!\n");
164 int set_nonblocking_sloppy(int fd)
166 return fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK);
169 void set_socket_keepalive(int fd)
171 int ret, one = 1;
173 ret = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one));
174 if (unlikely(ret))
175 panic("Cannot set TCP keepalive!\n");
178 void set_tcp_nodelay(int fd)
180 int one = 1;
181 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
184 int set_ipv6_only(int fd)
186 int one = 1;
187 return setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
190 int set_reuseaddr(int fd)
192 int ret, one = 1;
194 ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
195 if (unlikely(ret < 0))
196 panic("Cannot reuse addr!\n");
198 return 0;
201 void set_mtu_disc_dont(int fd)
203 int mtu = IP_PMTUDISC_DONT, ret;
205 ret = setsockopt(fd, SOL_IP, IP_MTU_DISCOVER, &mtu, sizeof(mtu));
206 if (unlikely(ret))
207 panic("Cannot set MTU discovery options!\n");
210 void set_epoll_descriptor(int fd_epoll, int action, int fd_toadd, int events)
212 int ret;
213 struct epoll_event ev;
215 memset(&ev, 0, sizeof(ev));
216 ev.events = events;
217 ev.data.fd = fd_toadd;
219 ret = epoll_ctl(fd_epoll, action, fd_toadd, &ev);
220 if (ret < 0)
221 panic("Cannot add socket for epoll!\n");
224 int set_epoll_descriptor2(int fd_epoll, int action, int fd_toadd, int events)
226 struct epoll_event ev;
228 memset(&ev, 0, sizeof(ev));
229 ev.events = events;
230 ev.data.fd = fd_toadd;
232 return epoll_ctl(fd_epoll, action, fd_toadd, &ev);
235 u32 wireless_bitrate(const char *ifname)
237 int sock, ret, rate_in_mbit;
238 struct iwreq iwr;
240 sock = af_socket(AF_INET);
242 memset(&iwr, 0, sizeof(iwr));
243 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
245 ret = ioctl(sock, SIOCGIWRATE, &iwr);
246 if (!ret)
247 rate_in_mbit = iwr.u.bitrate.value / 1000000;
248 else
249 rate_in_mbit = 0;
251 close(sock);
253 return rate_in_mbit;
256 void drop_privileges(bool enforce, uid_t uid, gid_t gid)
258 if (enforce) {
259 if (uid == getuid())
260 panic("Uid cannot be the same as the current user!\n");
261 if (gid == getgid())
262 panic("Gid cannot be the same as the current user!\n");
264 if (setgid(gid) != 0)
265 panic("Unable to drop group privileges: %s!\n", strerror(errno));
266 if (setuid(uid) != 0)
267 panic("Unable to drop user privileges: %s!\n", strerror(errno));
270 int get_system_socket_mem(int which)
272 int fd, val = -1;
273 ssize_t ret;
274 const char *file = sock_mem[which];
275 char buff[64];
277 fd = open(file, O_RDONLY);
278 if (fd < 0)
279 return val;
281 ret = read(fd, buff, sizeof(buff));
282 if (ret > 0)
283 val = atoi(buff);
285 close(fd);
286 return val;
289 void set_system_socket_mem(int which, int val)
291 int fd;
292 const char *file = sock_mem[which];
293 ssize_t ret;
294 char buff[64];
296 fd = open(file, O_WRONLY);
297 if (fd < 0)
298 return;
300 memset(buff, 0, sizeof(buff));
301 slprintf(buff, sizeof(buff), "%d", val);
303 ret = write(fd, buff, strlen(buff));
304 ret = ret;
306 close(fd);
309 int wireless_sigqual(const char *ifname, struct iw_statistics *stats)
311 int ret, sock;
312 struct iwreq iwr;
314 sock = af_socket(AF_INET);
316 memset(&iwr, 0, sizeof(iwr));
317 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
319 iwr.u.data.pointer = (caddr_t) stats;
320 iwr.u.data.length = sizeof(*stats);
321 iwr.u.data.flags = 1;
323 ret = ioctl(sock, SIOCGIWSTATS, &iwr);
325 close(sock);
327 return ret;
330 int wireless_rangemax_sigqual(const char *ifname)
332 int ret, sock, sigqual;
333 struct iwreq iwr;
334 struct iw_range iwrange;
336 sock = af_socket(AF_INET);
338 memset(&iwrange, 0, sizeof(iwrange));
340 memset(&iwr, 0, sizeof(iwr));
341 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
343 iwr.u.data.pointer = (caddr_t) &iwrange;
344 iwr.u.data.length = sizeof(iwrange);
345 iwr.u.data.flags = 0;
347 ret = ioctl(sock, SIOCGIWRANGE, &iwr);
348 if (!ret)
349 sigqual = iwrange.max_qual.qual;
350 else
351 sigqual = 0;
353 close(sock);
355 return sigqual;
358 u32 ethtool_bitrate(const char *ifname)
360 int ret, sock, bitrate;
361 struct ifreq ifr;
362 struct ethtool_cmd ecmd;
364 sock = af_socket(AF_INET);
366 memset(&ecmd, 0, sizeof(ecmd));
368 memset(&ifr, 0, sizeof(ifr));
369 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
371 ecmd.cmd = ETHTOOL_GSET;
372 ifr.ifr_data = (char *) &ecmd;
374 ret = ioctl(sock, SIOCETHTOOL, &ifr);
375 if (ret) {
376 bitrate = 0;
377 goto out;
380 switch (ecmd.speed) {
381 case SPEED_10:
382 case SPEED_100:
383 case SPEED_1000:
384 case SPEED_2500:
385 case SPEED_10000:
386 bitrate = ecmd.speed;
387 break;
388 default:
389 bitrate = 0;
390 break;
392 out:
393 close(sock);
395 return bitrate;
398 int ethtool_link(const char *ifname)
400 int ret, sock;
401 struct ifreq ifr;
402 struct ethtool_value ecmd;
404 sock = af_socket(AF_INET);
406 memset(&ecmd, 0, sizeof(ecmd));
408 memset(&ifr, 0, sizeof(ifr));
409 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
411 ecmd.cmd = ETHTOOL_GLINK;
412 ifr.ifr_data = (char *) &ecmd;
414 ret = ioctl(sock, SIOCETHTOOL, &ifr);
415 if (ret)
416 ret = -EINVAL;
417 else
418 ret = !!ecmd.data;
420 close(sock);
421 return ret;
424 int ethtool_drvinf(const char *ifname, struct ethtool_drvinfo *drvinf)
426 int ret, sock;
427 struct ifreq ifr;
429 sock = af_socket(AF_INET);
431 memset(drvinf, 0, sizeof(*drvinf));
433 memset(&ifr, 0, sizeof(ifr));
434 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
436 drvinf->cmd = ETHTOOL_GDRVINFO;
437 ifr.ifr_data = (char *) drvinf;
439 ret = ioctl(sock, SIOCETHTOOL, &ifr);
441 close(sock);
443 return ret;
446 u32 device_bitrate(const char *ifname)
448 u32 speed_c, speed_w;
450 speed_c = ethtool_bitrate(ifname);
451 speed_w = wireless_bitrate(ifname);
453 return (speed_c == 0 ? speed_w : speed_c);
456 int device_ifindex(const char *ifname)
458 int ret, sock, index;
459 struct ifreq ifr;
461 if (!strncmp("any", ifname, strlen("any")))
462 return 0;
464 sock = af_socket(AF_INET);
466 memset(&ifr, 0, sizeof(ifr));
467 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
469 ret = ioctl(sock, SIOCGIFINDEX, &ifr);
470 if (!ret)
471 index = ifr.ifr_ifindex;
472 else
473 index = -1;
475 close(sock);
477 return index;
480 static int __device_address6(const char *ifname, struct sockaddr_storage *ss)
482 int ret, family, found = -EINVAL;
483 struct ifaddrs *ifaddr, *ifa;
485 ret = getifaddrs(&ifaddr);
486 if (ret < 0)
487 panic("Cannot get device addresses for IPv6!\n");
489 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
490 family = ifa->ifa_addr->sa_family;
491 if (family != AF_INET6)
492 continue;
493 if (strcmp(ifa->ifa_name, ifname))
494 continue;
496 memcpy(ss, ifa->ifa_addr, sizeof(*ss));
497 found = 0;
498 break;
501 freeifaddrs(ifaddr);
502 return found;
505 int device_address(const char *ifname, int af, struct sockaddr_storage *ss)
507 int ret, sock;
508 struct ifreq ifr;
510 if (!ss)
511 return -EINVAL;
512 if (!strncmp("any", ifname, strlen("any")))
513 return -EINVAL;
514 if (af == AF_INET6)
515 return __device_address6(ifname, ss);
517 sock = af_socket(af);
519 memset(&ifr, 0, sizeof(ifr));
520 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
522 ifr.ifr_addr.sa_family = af;
524 ret = ioctl(sock, SIOCGIFADDR, &ifr);
525 if (!ret)
526 memcpy(ss, &ifr.ifr_addr, sizeof(ifr.ifr_addr));
528 close(sock);
530 return ret;
533 int device_mtu(const char *ifname)
535 int ret, sock, mtu;
536 struct ifreq ifr;
538 sock = af_socket(AF_INET);
540 memset(&ifr, 0, sizeof(ifr));
541 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
543 ret = ioctl(sock, SIOCGIFMTU, &ifr);
544 if (!ret)
545 mtu = ifr.ifr_mtu;
546 else
547 mtu = 0;
549 close(sock);
551 return mtu;
554 short device_get_flags(const char *ifname)
556 /* Really, it's short! Look at struct ifreq */
557 short flags;
558 int ret, sock;
559 struct ifreq ifr;
561 sock = af_socket(AF_INET);
563 memset(&ifr, 0, sizeof(ifr));
564 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
566 ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
567 if (!ret)
568 flags = ifr.ifr_flags;
569 else
570 flags = 0;
572 close(sock);
574 return flags;
577 void device_set_flags(const char *ifname, const short flags)
579 int ret, sock;
580 struct ifreq ifr;
582 sock = af_socket(AF_INET);
584 memset(&ifr, 0, sizeof(ifr));
585 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
587 ifr.ifr_flags = flags;
589 ret = ioctl(sock, SIOCSIFFLAGS, &ifr);
590 if (ret < 0)
591 panic("Cannot set NIC flags!\n");
593 close(sock);
596 void register_signal(int signal, void (*handler)(int))
598 sigset_t block_mask;
599 struct sigaction saction;
601 sigfillset(&block_mask);
603 saction.sa_handler = handler;
604 saction.sa_mask = block_mask;
605 saction.sa_flags = SA_RESTART;
607 sigaction(signal, &saction, NULL);
610 void register_signal_f(int signal, void (*handler)(int), int flags)
612 sigset_t block_mask;
613 struct sigaction saction;
615 sigfillset(&block_mask);
617 saction.sa_handler = handler;
618 saction.sa_mask = block_mask;
619 saction.sa_flags = flags;
621 sigaction(signal, &saction, NULL);
624 short enter_promiscuous_mode(char *ifname)
626 short ifflags;
628 if (!strncmp("any", ifname, strlen("any")))
629 return 0;
631 ifflags = device_get_flags(ifname);
632 device_set_flags(ifname, ifflags | IFF_PROMISC);
634 return ifflags;
637 void leave_promiscuous_mode(char *ifname, short oldflags)
639 if (!strncmp("any", ifname, strlen("any")))
640 return;
642 device_set_flags(ifname, oldflags);
645 int device_up_and_running(char *ifname)
647 if (!ifname)
648 return -EINVAL;
649 if (!strncmp("any", ifname, strlen("any")))
650 return 1;
652 return (device_get_flags(ifname) & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING);
655 void cpu_affinity(int cpu)
657 int ret;
658 cpu_set_t cpu_bitmask;
660 CPU_ZERO(&cpu_bitmask);
661 CPU_SET(cpu, &cpu_bitmask);
663 ret = sched_setaffinity(getpid(), sizeof(cpu_bitmask),
664 &cpu_bitmask);
665 if (ret)
666 panic("Can't set this cpu affinity!\n");
669 int set_proc_prio(int priority)
671 int ret = setpriority(PRIO_PROCESS, getpid(), priority);
672 if (ret)
673 panic("Can't set nice val to %i!\n", priority);
675 return 0;
678 int set_sched_status(int policy, int priority)
680 int ret, min_prio, max_prio;
681 struct sched_param sp;
683 max_prio = sched_get_priority_max(policy);
684 min_prio = sched_get_priority_min(policy);
686 if (max_prio == -1 || min_prio == -1)
687 printf("Cannot determine scheduler prio limits!\n");
688 else if (priority < min_prio)
689 priority = min_prio;
690 else if (priority > max_prio)
691 priority = max_prio;
693 memset(&sp, 0, sizeof(sp));
694 sp.sched_priority = priority;
696 ret = sched_setscheduler(getpid(), policy, &sp);
697 if (ret) {
698 printf("Cannot set scheduler policy!\n");
699 return -EINVAL;
702 ret = sched_setparam(getpid(), &sp);
703 if (ret) {
704 printf("Cannot set scheduler prio!\n");
705 return -EINVAL;
708 return 0;
711 int get_default_sched_policy(void)
713 return SCHED_FIFO;
716 int get_default_sched_prio(void)
718 return sched_get_priority_max(get_default_sched_policy());
721 int get_default_proc_prio(void)
723 return -20;
726 void set_system_socket_memory(int *vals, size_t len)
728 bug_on(len != 4);
730 if ((vals[0] = get_system_socket_mem(sock_rmem_max)) < SMEM_SUG_MAX)
731 set_system_socket_mem(sock_rmem_max, SMEM_SUG_MAX);
732 if ((vals[1] = get_system_socket_mem(sock_rmem_def)) < SMEM_SUG_DEF)
733 set_system_socket_mem(sock_rmem_def, SMEM_SUG_DEF);
734 if ((vals[2] = get_system_socket_mem(sock_wmem_max)) < SMEM_SUG_MAX)
735 set_system_socket_mem(sock_wmem_max, SMEM_SUG_MAX);
736 if ((vals[3] = get_system_socket_mem(sock_wmem_def)) < SMEM_SUG_DEF)
737 set_system_socket_mem(sock_wmem_def, SMEM_SUG_DEF);
740 void reset_system_socket_memory(int *vals, size_t len)
742 bug_on(len != 4);
744 set_system_socket_mem(sock_rmem_max, vals[0]);
745 set_system_socket_mem(sock_rmem_def, vals[1]);
746 set_system_socket_mem(sock_wmem_max, vals[2]);
747 set_system_socket_mem(sock_wmem_def, vals[3]);
750 void set_itimer_interval_value(struct itimerval *itimer, unsigned long sec,
751 unsigned long usec)
753 itimer->it_interval.tv_sec = sec;
754 itimer->it_interval.tv_usec = usec;
756 itimer->it_value.tv_sec = sec;
757 itimer->it_value.tv_usec = usec;