proc: move out process specific management functions
[netsniff-ng.git] / xutils.c
blobe07ce9e5d591fe05a1e01661adc69ea953add3e2
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 int get_system_socket_mem(int which)
206 int fd, val = -1;
207 ssize_t ret;
208 const char *file = sock_mem[which];
209 char buff[64];
211 fd = open(file, O_RDONLY);
212 if (fd < 0)
213 return val;
215 ret = read(fd, buff, sizeof(buff));
216 if (ret > 0)
217 val = atoi(buff);
219 close(fd);
220 return val;
223 void set_system_socket_mem(int which, int val)
225 int fd;
226 const char *file = sock_mem[which];
227 ssize_t ret;
228 char buff[64];
230 fd = open(file, O_WRONLY);
231 if (fd < 0)
232 return;
234 memset(buff, 0, sizeof(buff));
235 slprintf(buff, sizeof(buff), "%d", val);
237 ret = write(fd, buff, strlen(buff));
238 ret = ret;
240 close(fd);
243 int wireless_sigqual(const char *ifname, struct iw_statistics *stats)
245 int ret, sock;
246 struct iwreq iwr;
248 sock = af_socket(AF_INET);
250 memset(&iwr, 0, sizeof(iwr));
251 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
253 iwr.u.data.pointer = (caddr_t) stats;
254 iwr.u.data.length = sizeof(*stats);
255 iwr.u.data.flags = 1;
257 ret = ioctl(sock, SIOCGIWSTATS, &iwr);
259 close(sock);
261 return ret;
264 int wireless_rangemax_sigqual(const char *ifname)
266 int ret, sock, sigqual;
267 struct iwreq iwr;
268 struct iw_range iwrange;
270 sock = af_socket(AF_INET);
272 memset(&iwrange, 0, sizeof(iwrange));
274 memset(&iwr, 0, sizeof(iwr));
275 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
277 iwr.u.data.pointer = (caddr_t) &iwrange;
278 iwr.u.data.length = sizeof(iwrange);
279 iwr.u.data.flags = 0;
281 ret = ioctl(sock, SIOCGIWRANGE, &iwr);
282 if (!ret)
283 sigqual = iwrange.max_qual.qual;
284 else
285 sigqual = 0;
287 close(sock);
289 return sigqual;
292 u32 ethtool_bitrate(const char *ifname)
294 int ret, sock, bitrate;
295 struct ifreq ifr;
296 struct ethtool_cmd ecmd;
298 sock = af_socket(AF_INET);
300 memset(&ecmd, 0, sizeof(ecmd));
302 memset(&ifr, 0, sizeof(ifr));
303 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
305 ecmd.cmd = ETHTOOL_GSET;
306 ifr.ifr_data = (char *) &ecmd;
308 ret = ioctl(sock, SIOCETHTOOL, &ifr);
309 if (ret) {
310 bitrate = 0;
311 goto out;
314 switch (ecmd.speed) {
315 case SPEED_10:
316 case SPEED_100:
317 case SPEED_1000:
318 case SPEED_2500:
319 case SPEED_10000:
320 bitrate = ecmd.speed;
321 break;
322 default:
323 bitrate = 0;
324 break;
326 out:
327 close(sock);
329 return bitrate;
332 int ethtool_link(const char *ifname)
334 int ret, sock;
335 struct ifreq ifr;
336 struct ethtool_value ecmd;
338 sock = af_socket(AF_INET);
340 memset(&ecmd, 0, sizeof(ecmd));
342 memset(&ifr, 0, sizeof(ifr));
343 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
345 ecmd.cmd = ETHTOOL_GLINK;
346 ifr.ifr_data = (char *) &ecmd;
348 ret = ioctl(sock, SIOCETHTOOL, &ifr);
349 if (ret)
350 ret = -EINVAL;
351 else
352 ret = !!ecmd.data;
354 close(sock);
355 return ret;
358 int ethtool_drvinf(const char *ifname, struct ethtool_drvinfo *drvinf)
360 int ret, sock;
361 struct ifreq ifr;
363 sock = af_socket(AF_INET);
365 memset(drvinf, 0, sizeof(*drvinf));
367 memset(&ifr, 0, sizeof(ifr));
368 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
370 drvinf->cmd = ETHTOOL_GDRVINFO;
371 ifr.ifr_data = (char *) drvinf;
373 ret = ioctl(sock, SIOCETHTOOL, &ifr);
375 close(sock);
377 return ret;
380 void register_signal(int signal, void (*handler)(int))
382 sigset_t block_mask;
383 struct sigaction saction;
385 sigfillset(&block_mask);
387 saction.sa_handler = handler;
388 saction.sa_mask = block_mask;
389 saction.sa_flags = SA_RESTART;
391 sigaction(signal, &saction, NULL);
394 void register_signal_f(int signal, void (*handler)(int), int flags)
396 sigset_t block_mask;
397 struct sigaction saction;
399 sigfillset(&block_mask);
401 saction.sa_handler = handler;
402 saction.sa_mask = block_mask;
403 saction.sa_flags = flags;
405 sigaction(signal, &saction, NULL);
408 void set_system_socket_memory(int *vals, size_t len)
410 bug_on(len != 4);
412 if ((vals[0] = get_system_socket_mem(sock_rmem_max)) < SMEM_SUG_MAX)
413 set_system_socket_mem(sock_rmem_max, SMEM_SUG_MAX);
414 if ((vals[1] = get_system_socket_mem(sock_rmem_def)) < SMEM_SUG_DEF)
415 set_system_socket_mem(sock_rmem_def, SMEM_SUG_DEF);
416 if ((vals[2] = get_system_socket_mem(sock_wmem_max)) < SMEM_SUG_MAX)
417 set_system_socket_mem(sock_wmem_max, SMEM_SUG_MAX);
418 if ((vals[3] = get_system_socket_mem(sock_wmem_def)) < SMEM_SUG_DEF)
419 set_system_socket_mem(sock_wmem_def, SMEM_SUG_DEF);
422 void reset_system_socket_memory(int *vals, size_t len)
424 bug_on(len != 4);
426 set_system_socket_mem(sock_rmem_max, vals[0]);
427 set_system_socket_mem(sock_rmem_def, vals[1]);
428 set_system_socket_mem(sock_wmem_max, vals[2]);
429 set_system_socket_mem(sock_wmem_def, vals[3]);
432 void set_itimer_interval_value(struct itimerval *itimer, unsigned long sec,
433 unsigned long usec)
435 itimer->it_interval.tv_sec = sec;
436 itimer->it_interval.tv_usec = usec;
438 itimer->it_value.tv_sec = sec;
439 itimer->it_value.tv_usec = usec;