xsys: removed signals.h and put stuff into xsys
[netsniff-ng.git] / src / xsys.c
blob3c8b7a06bb95abc1efc9df126f0787357b1dd1f8
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 #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 <signal.h>
17 #include <arpa/inet.h>
18 #include <sys/socket.h>
19 #include <sys/ioctl.h>
20 /* Kernel < 2.6.26 */
21 #include <linux/if.h>
22 #include <linux/socket.h>
23 #include <linux/types.h>
24 /* Kernel < 2.6.26 */
25 #include <linux/if_ether.h>
26 #include <linux/if_packet.h>
27 #include <linux/sockios.h>
29 #include "die.h"
30 #include "xsys.h"
31 #include "strlcpy.h"
33 int af_socket(int af)
35 int sock;
36 if (af != AF_INET && af != AF_INET6) {
37 whine("Wrong AF socket type! Falling back to AF_INET\n");
38 af = AF_INET;
40 sock = socket(af, SOCK_DGRAM, 0);
41 if (sock < 0)
42 panic("Creation AF socket failed!\n");
43 return sock;
46 int af_raw_socket(int af, int proto)
48 int sock;
49 if (af != AF_INET && af != AF_INET6) {
50 whine("Wrong AF socket type! Falling back to AF_INET\n");
51 af = AF_INET;
53 sock = socket(af, SOCK_RAW, proto);
54 if (sock < 0)
55 panic("Creation AF socket failed!\n");
56 return sock;
59 int pf_socket(void)
61 int sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
62 if (sock < 0)
63 panic("Creation of PF socket failed!\n");
64 return sock;
67 int set_nonblocking(int fd)
69 int ret = fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK);
70 if (ret < 0)
71 panic("Cannot fcntl!\n");
72 return 0;
75 int set_nonblocking_sloppy(int fd)
77 return fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK);
80 int set_reuseaddr(int fd)
82 int one = 1;
83 int ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof (one));
84 if (ret < 0)
85 panic("Cannot reuse addr!\n");
86 return 0;
89 int wireless_bitrate(const char *ifname)
91 int sock, ret, rate_in_mbit;
92 struct iwreq iwr;
93 sock = af_socket(AF_INET);
94 memset(&iwr, 0, sizeof(iwr));
95 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
96 ret = ioctl(sock, SIOCGIWRATE, &iwr);
97 if (!ret)
98 rate_in_mbit = iwr.u.bitrate.value / 1000000;
99 else
100 rate_in_mbit = 0;
101 close(sock);
102 return rate_in_mbit;
105 int wireless_essid(const char *ifname, char *essid)
107 int ret, sock, essid_len;
108 struct iwreq iwr;
109 sock = af_socket(AF_INET);
110 memset(&iwr, 0, sizeof(iwr));
111 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
112 iwr.u.essid.pointer = essid;
113 iwr.u.essid.length = IW_ESSID_MAX_SIZE;
114 ret = ioctl(sock, SIOCGIWESSID, &iwr);
115 if (!ret)
116 essid_len = iwr.u.essid.length;
117 else
118 essid_len = 0;
119 close(sock);
120 return essid_len;
123 int adjust_dbm_level(int dbm_val)
125 if (dbm_val >= 64)
126 dbm_val -= 0x100;
127 return dbm_val;
130 int dbm_to_mwatt(const int in)
132 /* From Jean Tourrilhes <jt@hpl.hp.com> (iwlib.c) */
133 int ip = in / 10;
134 int fp = in % 10;
135 int k;
136 double res = 1.0;
137 for (k = 0; k < ip; k++)
138 res *= 10;
139 for (k = 0; k < fp; k++)
140 res *= 1.25892541179; /* LOG10_MAGIC */
141 return (int) res;
144 int wireless_tx_power(const char *ifname)
146 int ret, sock, tx_power;
147 struct iwreq iwr;
149 sock = af_socket(AF_INET);
151 memset(&iwr, 0, sizeof(iwr));
152 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
154 ret = ioctl(sock, SIOCGIWTXPOW, &iwr);
155 if (!ret)
156 tx_power = iwr.u.txpower.value;
157 else
158 tx_power = 0;
160 close(sock);
161 return ret;
164 int wireless_sigqual(const char *ifname, struct iw_statistics *stats)
166 int ret, sock;
167 struct iwreq iwr;
168 sock = af_socket(AF_INET);
169 memset(&iwr, 0, sizeof(iwr));
170 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
171 iwr.u.data.pointer = (caddr_t) stats;
172 iwr.u.data.length = sizeof(*stats);
173 iwr.u.data.flags = 1;
174 ret = ioctl(sock, SIOCGIWSTATS, &iwr);
175 close(sock);
176 return ret;
179 int wireless_rangemax_sigqual(const char *ifname)
181 int ret, sock, sigqual;
182 struct iwreq iwr;
183 struct iw_range iwrange;
184 sock = af_socket(AF_INET);
185 memset(&iwrange, 0, sizeof(iwrange));
186 memset(&iwr, 0, sizeof(iwr));
187 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
188 iwr.u.data.pointer = (caddr_t) &iwrange;
189 iwr.u.data.length = sizeof(iwrange);
190 iwr.u.data.flags = 0;
191 ret = ioctl(sock, SIOCGIWRANGE, &iwr);
192 if (!ret)
193 sigqual = iwrange.max_qual.qual;
194 else
195 sigqual = 0;
196 close(sock);
197 return sigqual;
200 int ethtool_bitrate(const char *ifname)
202 int ret, sock, bitrate;
203 struct ifreq ifr;
204 struct ethtool_cmd ecmd;
205 sock = af_socket(AF_INET);
206 memset(&ecmd, 0, sizeof(ecmd));
207 memset(&ifr, 0, sizeof(ifr));
208 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
209 ecmd.cmd = ETHTOOL_GSET;
210 ifr.ifr_data = (char *) &ecmd;
211 ret = ioctl(sock, SIOCETHTOOL, &ifr);
212 if (ret) {
213 bitrate = 0;
214 goto out;
216 switch (ecmd.speed) {
217 case SPEED_10:
218 case SPEED_100:
219 case SPEED_1000:
220 case SPEED_10000:
221 bitrate = ecmd.speed;
222 break;
223 default:
224 bitrate = 0;
225 break;
227 out:
228 close(sock);
229 return bitrate;
232 int ethtool_drvinf(const char *ifname, struct ethtool_drvinfo *drvinf)
234 int ret, sock;
235 struct ifreq ifr;
236 sock = af_socket(AF_INET);
237 memset(drvinf, 0, sizeof(*drvinf));
238 memset(&ifr, 0, sizeof(ifr));
239 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
240 drvinf->cmd = ETHTOOL_GDRVINFO;
241 ifr.ifr_data = (char *) drvinf;
242 ret = ioctl(sock, SIOCETHTOOL, &ifr);
243 close(sock);
244 return ret;
247 int device_bitrate(const char *ifname)
249 int speed_c, speed_w;
250 /* Probe for speed rates */
251 speed_c = ethtool_bitrate(ifname);
252 speed_w = wireless_bitrate(ifname);
253 return (speed_c == 0 ? speed_w : speed_c);
256 int device_ifindex(const char *ifname)
258 int ret, sock, index;
259 struct ifreq ifr;
260 if (!strncmp("any", ifname, strlen("any")))
261 return 0;
262 sock = af_socket(AF_INET);
263 memset(&ifr, 0, sizeof(ifr));
264 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
265 ret = ioctl(sock, SIOCGIFINDEX, &ifr);
266 if (!ret)
267 index = ifr.ifr_ifindex;
268 else
269 index = -1;
270 close(sock);
271 return index;
274 int device_address(const char *ifname, int af, struct sockaddr_storage *ss)
276 int ret, sock;
277 struct ifreq ifr;
278 if (!ss)
279 return -EINVAL;
280 if (!strncmp("any", ifname, strlen("any")))
281 return -EINVAL;
282 sock = af_socket(af);
283 memset(&ifr, 0, sizeof(ifr));
284 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
285 ifr.ifr_addr.sa_family = af;
286 ret = ioctl(sock, SIOCGIFADDR, &ifr);
287 if (!ret)
288 memcpy(ss, &ifr.ifr_addr, sizeof(ifr.ifr_addr));
289 close(sock);
290 return ret;
293 int device_mtu(const char *ifname)
295 int ret, sock, mtu;
296 struct ifreq ifr;
297 sock = af_socket(AF_INET);
298 memset(&ifr, 0, sizeof(ifr));
299 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
300 ret = ioctl(sock, SIOCGIFMTU, &ifr);
301 if (!ret)
302 mtu = ifr.ifr_mtu;
303 else
304 mtu = 0;
305 close(sock);
306 return mtu;
309 short device_get_flags(const char *ifname)
311 /* Really, it's short! Look at struct ifreq */
312 short flags;
313 int ret, sock;
314 struct ifreq ifr;
315 sock = af_socket(AF_INET);
316 memset(&ifr, 0, sizeof(ifr));
317 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
318 ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
319 if (!ret)
320 flags = ifr.ifr_flags;
321 else
322 flags = 0;
323 close(sock);
324 return flags;
327 void device_set_flags(const char *ifname, const short flags)
329 int ret, sock;
330 struct ifreq ifr;
331 sock = af_socket(AF_INET);
332 memset(&ifr, 0, sizeof(ifr));
333 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
334 ifr.ifr_flags = flags;
335 ret = ioctl(sock, SIOCSIFFLAGS, &ifr);
336 if (ret < 0)
337 panic("Cannot set NIC flags!\n");
338 close(sock);
341 int device_irq_number(const char *ifname)
344 * Since fetching IRQ numbers from SIOCGIFMAP is deprecated and not
345 * supported anymore, we need to grab them from procfs
347 int irq = 0;
348 char *buffp;
349 char buff[512];
350 char sysname[512];
351 if (!strncmp("lo", ifname, strlen("lo")))
352 return 0;
353 FILE *fp = fopen("/proc/interrupts", "r");
354 if (!fp) {
355 whine("Cannot open /proc/interrupts!\n");
356 return -ENOENT;
358 memset(buff, 0, sizeof(buff));
359 while (fgets(buff, sizeof(buff), fp) != NULL) {
360 buff[sizeof(buff) - 1] = 0;
361 if (strstr(buff, ifname) == NULL)
362 continue;
363 buffp = buff;
364 while (*buffp != ':')
365 buffp++;
366 *buffp = 0;
367 irq = atoi(buff);
368 memset(buff, 0, sizeof(buff));
370 fclose(fp);
371 if (irq != 0)
372 return irq;
374 * Try sysfs as fallback. Probably wireless devices will be found
375 * here. We return silently if it fails ...
377 slprintf(sysname, sizeof(sysname), "/sys/class/net/%s/device/irq",
378 ifname);
379 fp = fopen(sysname, "r");
380 if (!fp)
381 return -ENOENT;
382 memset(buff, 0, sizeof(buff));
383 if(fgets(buff, sizeof(buff), fp) != NULL) {
384 buff[sizeof(buff) - 1] = 0;
385 irq = atoi(buff);
387 fclose(fp);
388 return irq;
391 int device_bind_irq_to_cpu(int irq, int cpu)
393 int ret;
394 char buff[256];
395 char file[256];
396 /* Note: first CPU begins with CPU 0 */
397 if (irq < 0 || cpu < 0)
398 return -EINVAL;
399 memset(file, 0, sizeof(file));
400 memset(buff, 0, sizeof(buff));
401 /* smp_affinity starts counting with CPU 1, 2, ... */
402 cpu = cpu + 1;
403 sprintf(file, "/proc/irq/%d/smp_affinity", irq);
404 FILE *fp = fopen(file, "w");
405 if (!fp) {
406 whine("Cannot open file %s!\n", file);
407 return -ENOENT;
409 sprintf(buff, "%d", cpu);
410 ret = fwrite(buff, sizeof(buff), 1, fp);
411 fclose(fp);
412 return (ret > 0 ? 0 : ret);
415 void sock_print_net_stats(int sock)
417 int ret;
418 struct tpacket_stats kstats;
419 socklen_t slen = sizeof(kstats);
420 memset(&kstats, 0, sizeof(kstats));
421 ret = getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &kstats, &slen);
422 if (ret > -1) {
423 printf("\r%12d frames incoming\n",
424 kstats.tp_packets);
425 printf("\r%12d frames passed filter\n",
426 kstats.tp_packets - kstats.tp_drops);
427 printf("\r%12d frames failed filter (out of space)\n",
428 kstats.tp_drops);
429 if (kstats.tp_packets > 0)
430 printf("\r%12.4f%% frame droprate\n", 1.f *
431 kstats.tp_drops / kstats.tp_packets * 100.f);
435 void register_signal(int signal, void (*handler)(int))
437 sigset_t block_mask;
438 struct sigaction saction;
439 sigfillset(&block_mask);
440 saction.sa_handler = handler;
441 saction.sa_mask = block_mask;
442 saction.sa_flags = SA_RESTART;
443 sigaction(signal, &saction, NULL);
446 void register_signal_f(int signal, void (*handler)(int), int flags)
448 sigset_t block_mask;
449 struct sigaction saction;
450 sigfillset(&block_mask);
451 saction.sa_handler = handler;
452 saction.sa_mask = block_mask;
453 saction.sa_flags = flags;
454 sigaction(signal, &saction, NULL);