rnd: break out prng from xutils
[netsniff-ng.git] / xutils.c
blobe3e7f6f3ea876ad471e8d1750025432cb00b3ff2
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_nonblocking(int fd)
107 int ret = fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK);
108 if (unlikely(ret < 0))
109 panic("Cannot fcntl!\n");
112 int set_nonblocking_sloppy(int fd)
114 return fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK);
117 void set_socket_keepalive(int fd)
119 int ret, one = 1;
121 ret = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one));
122 if (unlikely(ret))
123 panic("Cannot set TCP keepalive!\n");
126 void set_tcp_nodelay(int fd)
128 int one = 1;
129 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
132 int set_ipv6_only(int fd)
134 int one = 1;
135 return setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
138 int set_reuseaddr(int fd)
140 int ret, one = 1;
142 ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
143 if (unlikely(ret < 0))
144 panic("Cannot reuse addr!\n");
146 return 0;
149 void set_mtu_disc_dont(int fd)
151 int mtu = IP_PMTUDISC_DONT, ret;
153 ret = setsockopt(fd, SOL_IP, IP_MTU_DISCOVER, &mtu, sizeof(mtu));
154 if (unlikely(ret))
155 panic("Cannot set MTU discovery options!\n");
158 void set_epoll_descriptor(int fd_epoll, int action, int fd_toadd, int events)
160 int ret;
161 struct epoll_event ev;
163 memset(&ev, 0, sizeof(ev));
164 ev.events = events;
165 ev.data.fd = fd_toadd;
167 ret = epoll_ctl(fd_epoll, action, fd_toadd, &ev);
168 if (ret < 0)
169 panic("Cannot add socket for epoll!\n");
172 int set_epoll_descriptor2(int fd_epoll, int action, int fd_toadd, int events)
174 struct epoll_event ev;
176 memset(&ev, 0, sizeof(ev));
177 ev.events = events;
178 ev.data.fd = fd_toadd;
180 return epoll_ctl(fd_epoll, action, fd_toadd, &ev);
183 u32 wireless_bitrate(const char *ifname)
185 int sock, ret, rate_in_mbit;
186 struct iwreq iwr;
188 sock = af_socket(AF_INET);
190 memset(&iwr, 0, sizeof(iwr));
191 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
193 ret = ioctl(sock, SIOCGIWRATE, &iwr);
194 if (!ret)
195 rate_in_mbit = iwr.u.bitrate.value / 1000000;
196 else
197 rate_in_mbit = 0;
199 close(sock);
201 return rate_in_mbit;
204 void drop_privileges(bool enforce, uid_t uid, gid_t gid)
206 if (enforce) {
207 if (uid == getuid())
208 panic("Uid cannot be the same as the current user!\n");
209 if (gid == getgid())
210 panic("Gid cannot be the same as the current user!\n");
212 if (setgid(gid) != 0)
213 panic("Unable to drop group privileges: %s!\n", strerror(errno));
214 if (setuid(uid) != 0)
215 panic("Unable to drop user privileges: %s!\n", strerror(errno));
218 int get_system_socket_mem(int which)
220 int fd, val = -1;
221 ssize_t ret;
222 const char *file = sock_mem[which];
223 char buff[64];
225 fd = open(file, O_RDONLY);
226 if (fd < 0)
227 return val;
229 ret = read(fd, buff, sizeof(buff));
230 if (ret > 0)
231 val = atoi(buff);
233 close(fd);
234 return val;
237 void set_system_socket_mem(int which, int val)
239 int fd;
240 const char *file = sock_mem[which];
241 ssize_t ret;
242 char buff[64];
244 fd = open(file, O_WRONLY);
245 if (fd < 0)
246 return;
248 memset(buff, 0, sizeof(buff));
249 slprintf(buff, sizeof(buff), "%d", val);
251 ret = write(fd, buff, strlen(buff));
252 ret = ret;
254 close(fd);
257 int wireless_sigqual(const char *ifname, struct iw_statistics *stats)
259 int ret, sock;
260 struct iwreq iwr;
262 sock = af_socket(AF_INET);
264 memset(&iwr, 0, sizeof(iwr));
265 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
267 iwr.u.data.pointer = (caddr_t) stats;
268 iwr.u.data.length = sizeof(*stats);
269 iwr.u.data.flags = 1;
271 ret = ioctl(sock, SIOCGIWSTATS, &iwr);
273 close(sock);
275 return ret;
278 int wireless_rangemax_sigqual(const char *ifname)
280 int ret, sock, sigqual;
281 struct iwreq iwr;
282 struct iw_range iwrange;
284 sock = af_socket(AF_INET);
286 memset(&iwrange, 0, sizeof(iwrange));
288 memset(&iwr, 0, sizeof(iwr));
289 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
291 iwr.u.data.pointer = (caddr_t) &iwrange;
292 iwr.u.data.length = sizeof(iwrange);
293 iwr.u.data.flags = 0;
295 ret = ioctl(sock, SIOCGIWRANGE, &iwr);
296 if (!ret)
297 sigqual = iwrange.max_qual.qual;
298 else
299 sigqual = 0;
301 close(sock);
303 return sigqual;
306 u32 ethtool_bitrate(const char *ifname)
308 int ret, sock, bitrate;
309 struct ifreq ifr;
310 struct ethtool_cmd ecmd;
312 sock = af_socket(AF_INET);
314 memset(&ecmd, 0, sizeof(ecmd));
316 memset(&ifr, 0, sizeof(ifr));
317 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
319 ecmd.cmd = ETHTOOL_GSET;
320 ifr.ifr_data = (char *) &ecmd;
322 ret = ioctl(sock, SIOCETHTOOL, &ifr);
323 if (ret) {
324 bitrate = 0;
325 goto out;
328 switch (ecmd.speed) {
329 case SPEED_10:
330 case SPEED_100:
331 case SPEED_1000:
332 case SPEED_2500:
333 case SPEED_10000:
334 bitrate = ecmd.speed;
335 break;
336 default:
337 bitrate = 0;
338 break;
340 out:
341 close(sock);
343 return bitrate;
346 int ethtool_link(const char *ifname)
348 int ret, sock;
349 struct ifreq ifr;
350 struct ethtool_value ecmd;
352 sock = af_socket(AF_INET);
354 memset(&ecmd, 0, sizeof(ecmd));
356 memset(&ifr, 0, sizeof(ifr));
357 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
359 ecmd.cmd = ETHTOOL_GLINK;
360 ifr.ifr_data = (char *) &ecmd;
362 ret = ioctl(sock, SIOCETHTOOL, &ifr);
363 if (ret)
364 ret = -EINVAL;
365 else
366 ret = !!ecmd.data;
368 close(sock);
369 return ret;
372 int ethtool_drvinf(const char *ifname, struct ethtool_drvinfo *drvinf)
374 int ret, sock;
375 struct ifreq ifr;
377 sock = af_socket(AF_INET);
379 memset(drvinf, 0, sizeof(*drvinf));
381 memset(&ifr, 0, sizeof(ifr));
382 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
384 drvinf->cmd = ETHTOOL_GDRVINFO;
385 ifr.ifr_data = (char *) drvinf;
387 ret = ioctl(sock, SIOCETHTOOL, &ifr);
389 close(sock);
391 return ret;
394 u32 device_bitrate(const char *ifname)
396 u32 speed_c, speed_w;
398 speed_c = ethtool_bitrate(ifname);
399 speed_w = wireless_bitrate(ifname);
401 return (speed_c == 0 ? speed_w : speed_c);
404 int device_ifindex(const char *ifname)
406 int ret, sock, index;
407 struct ifreq ifr;
409 if (!strncmp("any", ifname, strlen("any")))
410 return 0;
412 sock = af_socket(AF_INET);
414 memset(&ifr, 0, sizeof(ifr));
415 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
417 ret = ioctl(sock, SIOCGIFINDEX, &ifr);
418 if (!ret)
419 index = ifr.ifr_ifindex;
420 else
421 index = -1;
423 close(sock);
425 return index;
428 static int __device_address6(const char *ifname, struct sockaddr_storage *ss)
430 int ret, family, found = -EINVAL;
431 struct ifaddrs *ifaddr, *ifa;
433 ret = getifaddrs(&ifaddr);
434 if (ret < 0)
435 panic("Cannot get device addresses for IPv6!\n");
437 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
438 family = ifa->ifa_addr->sa_family;
439 if (family != AF_INET6)
440 continue;
441 if (strcmp(ifa->ifa_name, ifname))
442 continue;
444 memcpy(ss, ifa->ifa_addr, sizeof(*ss));
445 found = 0;
446 break;
449 freeifaddrs(ifaddr);
450 return found;
453 int device_address(const char *ifname, int af, struct sockaddr_storage *ss)
455 int ret, sock;
456 struct ifreq ifr;
458 if (!ss)
459 return -EINVAL;
460 if (!strncmp("any", ifname, strlen("any")))
461 return -EINVAL;
462 if (af == AF_INET6)
463 return __device_address6(ifname, ss);
465 sock = af_socket(af);
467 memset(&ifr, 0, sizeof(ifr));
468 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
470 ifr.ifr_addr.sa_family = af;
472 ret = ioctl(sock, SIOCGIFADDR, &ifr);
473 if (!ret)
474 memcpy(ss, &ifr.ifr_addr, sizeof(ifr.ifr_addr));
476 close(sock);
478 return ret;
481 int device_mtu(const char *ifname)
483 int ret, sock, mtu;
484 struct ifreq ifr;
486 sock = af_socket(AF_INET);
488 memset(&ifr, 0, sizeof(ifr));
489 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
491 ret = ioctl(sock, SIOCGIFMTU, &ifr);
492 if (!ret)
493 mtu = ifr.ifr_mtu;
494 else
495 mtu = 0;
497 close(sock);
499 return mtu;
502 short device_get_flags(const char *ifname)
504 /* Really, it's short! Look at struct ifreq */
505 short flags;
506 int ret, sock;
507 struct ifreq ifr;
509 sock = af_socket(AF_INET);
511 memset(&ifr, 0, sizeof(ifr));
512 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
514 ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
515 if (!ret)
516 flags = ifr.ifr_flags;
517 else
518 flags = 0;
520 close(sock);
522 return flags;
525 void device_set_flags(const char *ifname, const short flags)
527 int ret, sock;
528 struct ifreq ifr;
530 sock = af_socket(AF_INET);
532 memset(&ifr, 0, sizeof(ifr));
533 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
535 ifr.ifr_flags = flags;
537 ret = ioctl(sock, SIOCSIFFLAGS, &ifr);
538 if (ret < 0)
539 panic("Cannot set NIC flags!\n");
541 close(sock);
544 void register_signal(int signal, void (*handler)(int))
546 sigset_t block_mask;
547 struct sigaction saction;
549 sigfillset(&block_mask);
551 saction.sa_handler = handler;
552 saction.sa_mask = block_mask;
553 saction.sa_flags = SA_RESTART;
555 sigaction(signal, &saction, NULL);
558 void register_signal_f(int signal, void (*handler)(int), int flags)
560 sigset_t block_mask;
561 struct sigaction saction;
563 sigfillset(&block_mask);
565 saction.sa_handler = handler;
566 saction.sa_mask = block_mask;
567 saction.sa_flags = flags;
569 sigaction(signal, &saction, NULL);
572 short enter_promiscuous_mode(char *ifname)
574 short ifflags;
576 if (!strncmp("any", ifname, strlen("any")))
577 return 0;
579 ifflags = device_get_flags(ifname);
580 device_set_flags(ifname, ifflags | IFF_PROMISC);
582 return ifflags;
585 void leave_promiscuous_mode(char *ifname, short oldflags)
587 if (!strncmp("any", ifname, strlen("any")))
588 return;
590 device_set_flags(ifname, oldflags);
593 int device_up_and_running(char *ifname)
595 if (!ifname)
596 return -EINVAL;
597 if (!strncmp("any", ifname, strlen("any")))
598 return 1;
600 return (device_get_flags(ifname) & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING);
603 void cpu_affinity(int cpu)
605 int ret;
606 cpu_set_t cpu_bitmask;
608 CPU_ZERO(&cpu_bitmask);
609 CPU_SET(cpu, &cpu_bitmask);
611 ret = sched_setaffinity(getpid(), sizeof(cpu_bitmask),
612 &cpu_bitmask);
613 if (ret)
614 panic("Can't set this cpu affinity!\n");
617 int set_proc_prio(int priority)
619 int ret = setpriority(PRIO_PROCESS, getpid(), priority);
620 if (ret)
621 panic("Can't set nice val to %i!\n", priority);
623 return 0;
626 int set_sched_status(int policy, int priority)
628 int ret, min_prio, max_prio;
629 struct sched_param sp;
631 max_prio = sched_get_priority_max(policy);
632 min_prio = sched_get_priority_min(policy);
634 if (max_prio == -1 || min_prio == -1)
635 printf("Cannot determine scheduler prio limits!\n");
636 else if (priority < min_prio)
637 priority = min_prio;
638 else if (priority > max_prio)
639 priority = max_prio;
641 memset(&sp, 0, sizeof(sp));
642 sp.sched_priority = priority;
644 ret = sched_setscheduler(getpid(), policy, &sp);
645 if (ret) {
646 printf("Cannot set scheduler policy!\n");
647 return -EINVAL;
650 ret = sched_setparam(getpid(), &sp);
651 if (ret) {
652 printf("Cannot set scheduler prio!\n");
653 return -EINVAL;
656 return 0;
659 int get_default_sched_policy(void)
661 return SCHED_FIFO;
664 int get_default_sched_prio(void)
666 return sched_get_priority_max(get_default_sched_policy());
669 int get_default_proc_prio(void)
671 return -20;
674 void set_system_socket_memory(int *vals, size_t len)
676 bug_on(len != 4);
678 if ((vals[0] = get_system_socket_mem(sock_rmem_max)) < SMEM_SUG_MAX)
679 set_system_socket_mem(sock_rmem_max, SMEM_SUG_MAX);
680 if ((vals[1] = get_system_socket_mem(sock_rmem_def)) < SMEM_SUG_DEF)
681 set_system_socket_mem(sock_rmem_def, SMEM_SUG_DEF);
682 if ((vals[2] = get_system_socket_mem(sock_wmem_max)) < SMEM_SUG_MAX)
683 set_system_socket_mem(sock_wmem_max, SMEM_SUG_MAX);
684 if ((vals[3] = get_system_socket_mem(sock_wmem_def)) < SMEM_SUG_DEF)
685 set_system_socket_mem(sock_wmem_def, SMEM_SUG_DEF);
688 void reset_system_socket_memory(int *vals, size_t len)
690 bug_on(len != 4);
692 set_system_socket_mem(sock_rmem_max, vals[0]);
693 set_system_socket_mem(sock_rmem_def, vals[1]);
694 set_system_socket_mem(sock_wmem_max, vals[2]);
695 set_system_socket_mem(sock_wmem_def, vals[3]);
698 void set_itimer_interval_value(struct itimerval *itimer, unsigned long sec,
699 unsigned long usec)
701 itimer->it_interval.tv_sec = sec;
702 itimer->it_interval.tv_usec = usec;
704 itimer->it_value.tv_sec = sec;
705 itimer->it_value.tv_usec = usec;