xsys: renamed netdev.c/h to xsys.c/h to further reduce other files
[netsniff-ng.git] / src / xsys.c
blob59f319a5d3c1e0163eb0c4dccd4e7572b388ecd0
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 <arpa/inet.h>
17 #include <sys/socket.h>
18 #include <sys/ioctl.h>
19 /* Kernel < 2.6.26 */
20 #include <linux/if.h>
21 #include <linux/socket.h>
22 #include <linux/types.h>
23 /* Kernel < 2.6.26 */
24 #include <linux/if_ether.h>
25 #include <linux/if_packet.h>
26 #include <linux/sockios.h>
28 #include "die.h"
29 #include "xsys.h"
30 #include "strlcpy.h"
32 int af_socket(int af)
34 int sock;
35 if (af != AF_INET && af != AF_INET6) {
36 whine("Wrong AF socket type! Falling back to AF_INET\n");
37 af = AF_INET;
39 sock = socket(af, SOCK_DGRAM, 0);
40 if (sock < 0)
41 panic("Creation AF socket failed!\n");
42 return sock;
45 int af_raw_socket(int af, int proto)
47 int sock;
48 if (af != AF_INET && af != AF_INET6) {
49 whine("Wrong AF socket type! Falling back to AF_INET\n");
50 af = AF_INET;
52 sock = socket(af, SOCK_RAW, proto);
53 if (sock < 0)
54 panic("Creation AF socket failed!\n");
55 return sock;
58 int pf_socket(void)
60 int sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
61 if (sock < 0)
62 panic("Creation of PF socket failed!\n");
63 return sock;
66 int set_nonblocking(int fd)
68 int ret = fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK);
69 if (ret < 0)
70 panic("Cannot fcntl!\n");
71 return 0;
74 int set_nonblocking_sloppy(int fd)
76 return fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK);
79 int set_reuseaddr(int fd)
81 int one = 1;
82 int ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof (one));
83 if (ret < 0)
84 panic("Cannot reuse addr!\n");
85 return 0;
88 int wireless_bitrate(const char *ifname)
90 int sock, ret, rate_in_mbit;
91 struct iwreq iwr;
92 sock = af_socket(AF_INET);
93 memset(&iwr, 0, sizeof(iwr));
94 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
95 ret = ioctl(sock, SIOCGIWRATE, &iwr);
96 if (!ret)
97 rate_in_mbit = iwr.u.bitrate.value / 1000000;
98 else
99 rate_in_mbit = 0;
100 close(sock);
101 return rate_in_mbit;
104 int wireless_essid(const char *ifname, char *essid)
106 int ret, sock, essid_len;
107 struct iwreq iwr;
108 sock = af_socket(AF_INET);
109 memset(&iwr, 0, sizeof(iwr));
110 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
111 iwr.u.essid.pointer = essid;
112 iwr.u.essid.length = IW_ESSID_MAX_SIZE;
113 ret = ioctl(sock, SIOCGIWESSID, &iwr);
114 if (!ret)
115 essid_len = iwr.u.essid.length;
116 else
117 essid_len = 0;
118 close(sock);
119 return essid_len;
122 int adjust_dbm_level(int dbm_val)
124 if (dbm_val >= 64)
125 dbm_val -= 0x100;
126 return dbm_val;
129 int dbm_to_mwatt(const int in)
131 /* From Jean Tourrilhes <jt@hpl.hp.com> (iwlib.c) */
132 int ip = in / 10;
133 int fp = in % 10;
134 int k;
135 double res = 1.0;
136 for (k = 0; k < ip; k++)
137 res *= 10;
138 for (k = 0; k < fp; k++)
139 res *= 1.25892541179; /* LOG10_MAGIC */
140 return (int) res;
143 int wireless_tx_power(const char *ifname)
145 int ret, sock, tx_power;
146 struct iwreq iwr;
148 sock = af_socket(AF_INET);
150 memset(&iwr, 0, sizeof(iwr));
151 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
153 ret = ioctl(sock, SIOCGIWTXPOW, &iwr);
154 if (!ret)
155 tx_power = iwr.u.txpower.value;
156 else
157 tx_power = 0;
159 close(sock);
160 return ret;
163 int wireless_sigqual(const char *ifname, struct iw_statistics *stats)
165 int ret, sock;
166 struct iwreq iwr;
167 sock = af_socket(AF_INET);
168 memset(&iwr, 0, sizeof(iwr));
169 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
170 iwr.u.data.pointer = (caddr_t) stats;
171 iwr.u.data.length = sizeof(*stats);
172 iwr.u.data.flags = 1;
173 ret = ioctl(sock, SIOCGIWSTATS, &iwr);
174 close(sock);
175 return ret;
178 int wireless_rangemax_sigqual(const char *ifname)
180 int ret, sock, sigqual;
181 struct iwreq iwr;
182 struct iw_range iwrange;
183 sock = af_socket(AF_INET);
184 memset(&iwrange, 0, sizeof(iwrange));
185 memset(&iwr, 0, sizeof(iwr));
186 strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
187 iwr.u.data.pointer = (caddr_t) &iwrange;
188 iwr.u.data.length = sizeof(iwrange);
189 iwr.u.data.flags = 0;
190 ret = ioctl(sock, SIOCGIWRANGE, &iwr);
191 if (!ret)
192 sigqual = iwrange.max_qual.qual;
193 else
194 sigqual = 0;
195 close(sock);
196 return sigqual;
199 int ethtool_bitrate(const char *ifname)
201 int ret, sock, bitrate;
202 struct ifreq ifr;
203 struct ethtool_cmd ecmd;
204 sock = af_socket(AF_INET);
205 memset(&ecmd, 0, sizeof(ecmd));
206 memset(&ifr, 0, sizeof(ifr));
207 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
208 ecmd.cmd = ETHTOOL_GSET;
209 ifr.ifr_data = (char *) &ecmd;
210 ret = ioctl(sock, SIOCETHTOOL, &ifr);
211 if (ret) {
212 bitrate = 0;
213 goto out;
215 switch (ecmd.speed) {
216 case SPEED_10:
217 case SPEED_100:
218 case SPEED_1000:
219 case SPEED_10000:
220 bitrate = ecmd.speed;
221 break;
222 default:
223 bitrate = 0;
224 break;
226 out:
227 close(sock);
228 return bitrate;
231 int ethtool_drvinf(const char *ifname, struct ethtool_drvinfo *drvinf)
233 int ret, sock;
234 struct ifreq ifr;
235 sock = af_socket(AF_INET);
236 memset(drvinf, 0, sizeof(*drvinf));
237 memset(&ifr, 0, sizeof(ifr));
238 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
239 drvinf->cmd = ETHTOOL_GDRVINFO;
240 ifr.ifr_data = (char *) drvinf;
241 ret = ioctl(sock, SIOCETHTOOL, &ifr);
242 close(sock);
243 return ret;
246 int device_bitrate(const char *ifname)
248 int speed_c, speed_w;
249 /* Probe for speed rates */
250 speed_c = ethtool_bitrate(ifname);
251 speed_w = wireless_bitrate(ifname);
252 return (speed_c == 0 ? speed_w : speed_c);
255 int device_ifindex(const char *ifname)
257 int ret, sock, index;
258 struct ifreq ifr;
259 if (!strncmp("any", ifname, strlen("any")))
260 return 0;
261 sock = af_socket(AF_INET);
262 memset(&ifr, 0, sizeof(ifr));
263 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
264 ret = ioctl(sock, SIOCGIFINDEX, &ifr);
265 if (!ret)
266 index = ifr.ifr_ifindex;
267 else
268 index = -1;
269 close(sock);
270 return index;
273 int device_address(const char *ifname, int af, struct sockaddr_storage *ss)
275 int ret, sock;
276 struct ifreq ifr;
277 if (!ss)
278 return -EINVAL;
279 if (!strncmp("any", ifname, strlen("any")))
280 return -EINVAL;
281 sock = af_socket(af);
282 memset(&ifr, 0, sizeof(ifr));
283 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
284 ifr.ifr_addr.sa_family = af;
285 ret = ioctl(sock, SIOCGIFADDR, &ifr);
286 if (!ret)
287 memcpy(ss, &ifr.ifr_addr, sizeof(ifr.ifr_addr));
288 close(sock);
289 return ret;
292 int device_mtu(const char *ifname)
294 int ret, sock, mtu;
295 struct ifreq ifr;
296 sock = af_socket(AF_INET);
297 memset(&ifr, 0, sizeof(ifr));
298 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
299 ret = ioctl(sock, SIOCGIFMTU, &ifr);
300 if (!ret)
301 mtu = ifr.ifr_mtu;
302 else
303 mtu = 0;
304 close(sock);
305 return mtu;
308 short device_get_flags(const char *ifname)
310 /* Really, it's short! Look at struct ifreq */
311 short flags;
312 int ret, sock;
313 struct ifreq ifr;
314 sock = af_socket(AF_INET);
315 memset(&ifr, 0, sizeof(ifr));
316 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
317 ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
318 if (!ret)
319 flags = ifr.ifr_flags;
320 else
321 flags = 0;
322 close(sock);
323 return flags;
326 void device_set_flags(const char *ifname, const short flags)
328 int ret, sock;
329 struct ifreq ifr;
330 sock = af_socket(AF_INET);
331 memset(&ifr, 0, sizeof(ifr));
332 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
333 ifr.ifr_flags = flags;
334 ret = ioctl(sock, SIOCSIFFLAGS, &ifr);
335 if (ret < 0)
336 panic("Cannot set NIC flags!\n");
337 close(sock);
340 int device_irq_number(const char *ifname)
343 * Since fetching IRQ numbers from SIOCGIFMAP is deprecated and not
344 * supported anymore, we need to grab them from procfs
346 int irq = 0;
347 char *buffp;
348 char buff[512];
349 char sysname[512];
350 if (!strncmp("lo", ifname, strlen("lo")))
351 return 0;
352 FILE *fp = fopen("/proc/interrupts", "r");
353 if (!fp) {
354 whine("Cannot open /proc/interrupts!\n");
355 return -ENOENT;
357 memset(buff, 0, sizeof(buff));
358 while (fgets(buff, sizeof(buff), fp) != NULL) {
359 buff[sizeof(buff) - 1] = 0;
360 if (strstr(buff, ifname) == NULL)
361 continue;
362 buffp = buff;
363 while (*buffp != ':')
364 buffp++;
365 *buffp = 0;
366 irq = atoi(buff);
367 memset(buff, 0, sizeof(buff));
369 fclose(fp);
370 if (irq != 0)
371 return irq;
373 * Try sysfs as fallback. Probably wireless devices will be found
374 * here. We return silently if it fails ...
376 slprintf(sysname, sizeof(sysname), "/sys/class/net/%s/device/irq",
377 ifname);
378 fp = fopen(sysname, "r");
379 if (!fp)
380 return -ENOENT;
381 memset(buff, 0, sizeof(buff));
382 if(fgets(buff, sizeof(buff), fp) != NULL) {
383 buff[sizeof(buff) - 1] = 0;
384 irq = atoi(buff);
386 fclose(fp);
387 return irq;
390 int device_bind_irq_to_cpu(int irq, int cpu)
392 int ret;
393 char buff[256];
394 char file[256];
395 /* Note: first CPU begins with CPU 0 */
396 if (irq < 0 || cpu < 0)
397 return -EINVAL;
398 memset(file, 0, sizeof(file));
399 memset(buff, 0, sizeof(buff));
400 /* smp_affinity starts counting with CPU 1, 2, ... */
401 cpu = cpu + 1;
402 sprintf(file, "/proc/irq/%d/smp_affinity", irq);
403 FILE *fp = fopen(file, "w");
404 if (!fp) {
405 whine("Cannot open file %s!\n", file);
406 return -ENOENT;
408 sprintf(buff, "%d", cpu);
409 ret = fwrite(buff, sizeof(buff), 1, fp);
410 fclose(fp);
411 return (ret > 0 ? 0 : ret);
414 void sock_print_net_stats(int sock)
416 int ret;
417 struct tpacket_stats kstats;
418 socklen_t slen = sizeof(kstats);
419 memset(&kstats, 0, sizeof(kstats));
420 ret = getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &kstats, &slen);
421 if (ret > -1) {
422 printf("\r%12d frames incoming\n",
423 kstats.tp_packets);
424 printf("\r%12d frames passed filter\n",
425 kstats.tp_packets - kstats.tp_drops);
426 printf("\r%12d frames failed filter (out of space)\n",
427 kstats.tp_drops);
428 if (kstats.tp_packets > 0)
429 printf("\r%12.4f%% frame droprate\n", 1.f *
430 kstats.tp_drops / kstats.tp_packets * 100.f);