Indention of code
[netsniff-ng.git] / src / netdev.c
blobec8a71b890ff02cf71079b2ebcdace727696c3bf
1 /*
2 * Copyright (C) 2009, 2010 Daniel Borkmann <daniel@netsniff-ng.org> and
3 * Emmanuel Roullit <emmanuel@netsniff-ng.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or (at
8 * your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
20 #define _GNU_SOURCE
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <assert.h>
27 #include <errno.h>
29 #include <sys/ioctl.h>
30 #include <sys/socket.h>
32 #include <arpa/inet.h>
34 #include <netinet/in.h>
35 #include <netinet/ether.h>
36 #include <arpa/inet.h>
38 /* Kernel < 2.6.26 */
39 #include <linux/if.h>
40 #include <linux/socket.h>
41 #include <linux/types.h>
42 /* Kernel < 2.6.26 */
43 #include <linux/if_ether.h>
44 #include <linux/if_packet.h>
45 #include <linux/filter.h>
46 #include <linux/sockios.h>
47 #include <linux/ethtool.h>
48 #include <linux/wireless.h>
50 #include "xmalloc.h"
51 #include "strlcpy.h"
52 #include "macros.h"
53 #include "netdev.h"
54 #include "bpf.h"
56 #ifndef PACKET_LOSS
57 # define PACKET_LOSS 14
58 #endif
59 #define wop_entry(x, i) (wop_mode[(x) % (sizeof(wop_mode)/sizeof(wop_mode[0]))][(i)])
61 static const char *const wop_mode[][2] = {
62 {"auto", ""},
63 {"adhoc", "single cell net"},
64 {"infra", "multi cell net"},
65 {"master", "sync master or AP"},
66 {"repeat", "forwarder"},
67 {"second", "secondary master"},
68 {"monitor", "passive mode"},
69 {"mesh", "mesh net (IEEE 802.11s)"},
70 {"unknown", ""},
73 static inline void assert_dev_name(const char *dev)
75 assert(dev);
76 assert(strlen(dev) < IFNAMSIZ);
79 static int get_af_socket(int af)
81 int sock;
83 assert(af == AF_INET || af == AF_INET6);
85 sock = socket(af, SOCK_DGRAM, 0);
86 if (sock < 0) {
87 err("Fetch socket");
88 exit(EXIT_FAILURE);
91 return (sock);
94 /**
95 * get_pf_socket - Allocates a raw PF_PACKET socket
97 int get_pf_socket(void)
99 int sock = socket(PF_PACKET, SOCK_RAW, 0);
100 if (sock < 0) {
101 err("Allocation of pf socket");
102 exit(EXIT_FAILURE);
105 return (sock);
109 * get_wireless_bitrate - Returns wireless bitrate in Mb/s
110 * @ifname: device name
112 static int get_wireless_bitrate(const char *ifname)
114 int sock, ret;
115 struct iwreq iwr;
117 assert_dev_name(ifname);
119 memset(&iwr, 0, sizeof(iwr));
120 strlcpy(iwr.ifr_name, ifname, sizeof(iwr.ifr_name) - 1);
122 sock = get_af_socket(AF_INET);
124 ret = ioctl(sock, SIOCGIWRATE, &iwr);
125 if (ret) {
126 close(sock);
127 return 0;
130 close(sock);
131 return (iwr.u.bitrate.value / 1000000);
134 static int get_wireless_ssid(const char *ifname, char *ssid)
136 int ret, sock;
137 struct iwreq iwr;
139 assert(ifname);
140 assert(ssid);
142 sock = get_af_socket(AF_INET);
144 memset(&iwr, 0, sizeof(iwr));
145 strlcpy(iwr.ifr_name, ifname, sizeof(iwr.ifr_name) - 1);
147 iwr.u.essid.pointer = ssid;
148 iwr.u.essid.length = IW_ESSID_MAX_SIZE;
150 ret = ioctl(sock, SIOCGIWESSID, &iwr);
151 if (ret == 0)
152 ret = iwr.u.essid.length;
153 else {
154 close(sock);
155 return 0;
158 close(sock);
159 return ret;
162 static inline int adjust_dbm_level(int dbm_val)
164 if (dbm_val >= 64)
165 dbm_val -= 0x100;
166 return dbm_val;
169 static int dbm_to_mwatt(const int in)
171 /* From Jean Tourrilhes <jt@hpl.hp.com> (iwlib.c) */
172 int ip = in / 10;
173 int fp = in % 10;
174 int k;
176 double res = 1.0;
178 for (k = 0; k < ip; k++)
179 res *= 10;
180 for (k = 0; k < fp; k++)
181 res *= 1.25892541179; /* LOG10_MAGIC */
182 return ((int)res);
185 static int get_wireless_tx_power(const char *ifname)
187 int ret, sock;
188 struct iwreq iwr;
190 assert(ifname);
192 sock = get_af_socket(AF_INET);
194 memset(&iwr, 0, sizeof(iwr));
195 strlcpy(iwr.ifr_name, ifname, sizeof(iwr.ifr_name) - 1);
197 ret = ioctl(sock, SIOCGIWTXPOW, &iwr);
198 if (ret == 0)
199 ret = iwr.u.txpower.value;
200 else {
201 close(sock);
202 return 0;
205 close(sock);
206 return ret;
209 static int get_wireless_sigqual(const char *ifname, struct iw_statistics *stats)
211 int ret, sock;
212 struct iwreq iwr;
214 assert(ifname);
215 assert(stats);
217 sock = get_af_socket(AF_INET);
219 memset(&iwr, 0, sizeof(iwr));
221 strlcpy(iwr.ifr_name, ifname, sizeof(iwr.ifr_name) - 1);
222 iwr.u.data.pointer = (caddr_t) stats;
223 iwr.u.data.length = sizeof(*stats);
224 iwr.u.data.flags = 1;
226 ret = ioctl(sock, SIOCGIWSTATS, &iwr);
227 if (ret) {
228 close(sock);
229 return -EIO;
232 close(sock);
233 return ret;
236 static int get_wireless_rangemax_sigqual(const char *ifname)
238 int ret, sock;
239 struct iwreq iwr;
240 struct iw_range iwrange;
242 assert(ifname);
244 sock = get_af_socket(AF_INET);
246 memset(&iwr, 0, sizeof(iwr));
247 memset(&iwrange, 0, sizeof(iwrange));
249 strlcpy(iwr.ifr_name, ifname, sizeof(iwr.ifr_name) - 1);
250 iwr.u.data.pointer = (caddr_t) & iwrange;
251 iwr.u.data.length = sizeof(iwrange);
252 iwr.u.data.flags = 0;
254 ret = ioctl(sock, SIOCGIWRANGE, &iwr);
255 if (ret) {
256 close(sock);
257 return 0;
260 close(sock);
261 return iwrange.max_qual.qual;
265 * get_ethtool_bitrate - Returns non-wireless bitrate in Mb/s (via ethtool)
266 * @ifname: device name
268 static int get_ethtool_bitrate(const char *ifname)
270 int sock, ret;
271 struct ifreq ifr;
272 struct ethtool_cmd ecmd;
274 assert_dev_name(ifname);
276 memset(&ifr, 0, sizeof(ifr));
277 memset(&ecmd, 0, sizeof(ecmd));
278 ecmd.cmd = ETHTOOL_GSET;
280 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
282 sock = get_af_socket(AF_INET);
284 ifr.ifr_data = (char *)&ecmd;
286 ret = ioctl(sock, SIOCETHTOOL, &ifr);
287 if (ret) {
288 close(sock);
289 return 0;
292 switch (ecmd.speed) {
293 case SPEED_10:
294 case SPEED_100:
295 case SPEED_1000:
296 case SPEED_10000:
297 ret = ecmd.speed;
298 break;
299 default:
300 ret = 0;
301 break;
304 close(sock);
305 return ret;
309 * get_ethtool_drvinf - Returns driver info of ethtool supported dev
310 * @ifname: device name
312 static int get_ethtool_drvinf(const char *ifname, struct ethtool_drvinfo *di)
314 int sock, ret;
315 struct ifreq ifr;
316 struct ethtool_drvinfo __di;
318 assert(di);
319 assert_dev_name(ifname);
321 memset(&ifr, 0, sizeof(ifr));
322 memset(&__di, 0, sizeof(__di));
324 __di.cmd = ETHTOOL_GDRVINFO;
326 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
328 sock = get_af_socket(AF_INET);
330 ifr.ifr_data = (char *)&__di;
332 ret = ioctl(sock, SIOCETHTOOL, &ifr);
333 if (ret)
334 goto out_err;
336 memcpy(di, &__di, sizeof(*di));
338 out_err:
339 close(sock);
340 return ret;
344 * get_device_bitrate_generic - Returns bitrate in Mb/s
345 * @ifname: device name
347 int get_device_bitrate_generic(const char *ifname)
349 int speed_c, speed_w;
351 /* Probe for speed rates */
352 speed_c = get_ethtool_bitrate(ifname);
353 speed_w = get_wireless_bitrate(ifname);
355 return (speed_c == 0 ? speed_w : speed_c);
359 * get_device_bitrate_generic_cable - Returns bitrate in Mb/s
360 * @ifname: device name
362 int get_device_bitrate_generic_cable(const char *ifname)
364 return get_ethtool_bitrate(ifname);
368 * get_mtu - Get MTU of a device
369 * @sock: socket descriptor
370 * @ifname: device name
372 int get_mtu(const char *dev)
374 int sock;
375 struct ifreq ifr;
377 assert_dev_name(dev);
379 sock = get_af_socket(AF_INET);
381 memset(&ifr, 0, sizeof(ifr));
382 strlcpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name) - 1);
384 if (ioctl(sock, SIOCGIFMTU, &ifr) < 0) {
385 err("Doing iotcl(SIOCGIFMTU)");
386 return 0;
389 close(sock);
390 return (ifr.ifr_mtu);
393 static int get_nic_irq_number_proc(const char *dev)
395 /* Since fetching IRQ numbers from SIOCGIFMAP is deprecated and not
396 supported anymore, we need to grab them from procfs */
398 /* XXX Mhh... I think it would cleverer to read our
399 * info from /sys/class/net/eth0/device/irq
402 int ret = -1;
403 char *buffp;
404 char buff[128] = { 0 };
406 assert_dev_name(dev);
408 /* We exclude lo! */
409 if (!strncmp("lo", dev, strlen("lo")))
410 return -1;
412 FILE *fp = fopen("/proc/interrupts", "r");
413 if (!fp) {
414 err("Cannot open /proc/interrupts");
415 return -ENOENT;
418 memset(buff, 0, sizeof(buff));
420 while (fgets(buff, sizeof(buff), fp) != NULL) {
421 buff[sizeof(buff) - 1] = 0;
422 if (strstr(buff, dev) == NULL)
423 continue;
424 buffp = buff;
425 while (*buffp != ':') {
426 buffp++;
428 *buffp = 0;
429 ret = atoi(buff);
432 fclose(fp);
433 return ret;
436 int get_nic_irq_number(const char *dev)
438 return get_nic_irq_number_proc(dev);
441 int bind_nic_interrupts_to_cpu(int intr, int cpu)
443 int ret;
444 char buff[128] = { 0 };
445 char file[128] = { 0 };
447 /* XXX Mhh... I think it would cleverer to read our
448 * info from /sys/class/net/eth0/device/local_cpulist
451 /* Note: first CPU begins with CPU 0 */
452 if (intr < 0 || cpu < 0)
453 return -EINVAL;
455 /* smp_affinity starts counting with CPU 1, 2, ... */
456 cpu = cpu + 1;
458 sprintf(file, "/proc/irq/%d/smp_affinity", intr);
459 FILE *fp = fopen(file, "w");
460 if (!fp) {
461 err("Cannot open %s", file);
462 return -ENOENT;
465 sprintf(buff, "%d", cpu);
466 ret = fwrite(buff, sizeof(buff), 1, fp);
468 fclose(fp);
469 return (ret > 0 ? 0 : ret);
473 * get_nic_flags - Fetches device flags
474 * @dev: device name
476 short get_nic_flags(const char *dev)
478 int ret;
479 int sock;
480 struct ifreq ethreq;
482 assert_dev_name(dev);
484 sock = get_af_socket(AF_INET);
486 memset(&ethreq, 0, sizeof(ethreq));
487 strlcpy(ethreq.ifr_name, dev, sizeof(ethreq.ifr_name) - 1);
489 ret = ioctl(sock, SIOCGIFFLAGS, &ethreq);
490 if (ret < 0) {
491 err("ioctl: cannot determine dev number for %s",
492 ethreq.ifr_name);
493 close(sock);
494 exit(EXIT_FAILURE);
497 close(sock);
498 return (ethreq.ifr_flags);
502 * set_nic_flags - Set flags attached to a network device
503 * @dev: device name
504 * @mac: Flags to set
506 void set_nic_flags(const char *dev, const short nic_flags)
508 int ret;
509 int sock;
510 struct ifreq ethreq;
512 assert_dev_name(dev);
514 sock = get_af_socket(AF_INET);
516 memset(&ethreq, 0, sizeof(ethreq));
517 strlcpy(ethreq.ifr_name, dev, sizeof(ethreq.ifr_name) - 1);
518 ethreq.ifr_flags = nic_flags;
520 ret = ioctl(sock, SIOCSIFFLAGS, &ethreq);
521 if (ret < 0) {
522 err("ioctl: cannot determine dev number for %s",
523 ethreq.ifr_name);
524 close(sock);
525 exit(EXIT_FAILURE);
528 close(sock);
532 * get_nic_mac - Fetches device MAC address
533 * @dev: device name
534 * @mac: Output buffer
536 static int get_nic_mac(const char *dev, uint8_t * mac)
538 int ret;
539 int sock;
540 struct ifreq ifr;
542 assert_dev_name(dev);
543 assert(mac);
545 sock = get_af_socket(AF_INET);
547 memset(&ifr, 0, sizeof(ifr));
548 strlcpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name) - 1);
550 ret = ioctl(sock, SIOCGIFHWADDR, &ifr);
551 if (ret) {
552 err("Doing ioctl(SIOCGIFHWADDR)");
553 return (EINVAL);
556 close(sock);
557 memcpy(mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
559 return (0);
562 static char *get_nic_mac_str(const char *dev)
564 uint8_t mac[ETH_ALEN] = { 0 };
565 get_nic_mac(dev, mac);
566 return (ether_ntoa((const struct ether_addr *)mac));
569 static int get_interface_conf(struct ifconf *ifconf)
571 int sock;
573 assert(ifconf);
574 assert(ifconf->ifc_buf);
575 assert(ifconf->ifc_len);
577 sock = get_af_socket(AF_INET);
579 if (ioctl(sock, SIOCGIFCONF, ifconf) < 0) {
580 err("Doing ioctl(SIOCGIFCONF)");
581 exit(EXIT_FAILURE);
584 close(sock);
585 return (0);
588 static int get_interface_address(const char *dev, struct in_addr *in,
589 struct in6_addr *in6)
591 int sock;
593 struct ifreq ifr;
594 struct in_addr *tmp_in;
595 struct sockaddr *sa;
596 struct sockaddr_in6 *sa6;
598 assert(in);
599 assert(in6);
600 assert_dev_name(dev);
602 memset(in, 0, sizeof(*in));
603 memset(in6, 0, sizeof(*in6));
604 memset(&ifr, 0, sizeof(ifr));
606 strlcpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name) - 1);
608 sock = get_af_socket(AF_INET);
610 if (ioctl(sock, SIOCGIFADDR, &ifr) < 0) {
611 err("Doing ioctl(SIOCGIFADDR)");
612 close(sock);
613 return (0);
616 sa = (struct sockaddr *)&ifr.ifr_addr;
618 switch (sa->sa_family) {
619 case AF_INET:
620 tmp_in = &(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr);
621 memcpy(in, tmp_in, sizeof(*in));
622 break;
624 case AF_INET6:
625 sa6 = (struct sockaddr_in6 *)&ifr.ifr_addr;
626 memcpy(in6, &sa6->sin6_addr, sizeof(*in6));
627 break;
630 return (sa->sa_family);
634 * print_device_info - Prints infos of netdevs
636 void print_device_info(void)
638 int i = 0, ret = 0, speed = 0, txp = 0;
639 short nic_flags = 0;
641 char essid[IW_ESSID_MAX_SIZE] = { 0 };
642 char tmp_ip[INET6_ADDRSTRLEN] = { 0 };
644 struct ifreq *ifr_elem = NULL;
645 struct ifreq *ifr_buffer = NULL;
646 struct ifconf ifc = { 0 };
647 struct in_addr ipv4 = { 0 };
648 struct in6_addr ipv6 = IN6ADDR_ANY_INIT;
649 struct ethtool_drvinfo di = { 0 };
650 struct iw_statistics ws = { 0 };
652 size_t if_buffer_len = sizeof(*ifr_buffer) * MAX_NUMBER_OF_NICS;
654 ifr_buffer = xzmalloc(if_buffer_len);
656 ifc.ifc_len = if_buffer_len;
657 ifc.ifc_req = ifr_buffer;
659 get_interface_conf(&ifc);
661 info("Networking devs\n");
663 for (i = 0; i < (ifc.ifc_len / sizeof(*ifr_buffer)); i++) {
664 ifr_elem = &ifc.ifc_req[i];
667 * Fetch NIC addr
669 switch (get_interface_address(ifr_elem->ifr_name, &ipv4, &ipv6)) {
670 case AF_INET:
671 inet_ntop(AF_INET, (const void *)&ipv4, tmp_ip,
672 INET_ADDRSTRLEN);
673 break;
674 case AF_INET6:
675 inet_ntop(AF_INET6, (const void *)&ipv6, tmp_ip,
676 INET6_ADDRSTRLEN);
677 break;
681 * Basic info as name, HW addr, IP addr
683 info(" (%03d) %s%s%s => %s\n", i, colorize_start(bold),
684 ifr_elem->ifr_name, colorize_end(), tmp_ip);
685 info(" hw: %s\n", get_nic_mac_str(ifr_elem->ifr_name));
688 * Driver name (for non-wireless)
690 ret = get_ethtool_drvinf(ifr_elem->ifr_name, &di);
691 if (!ret) {
692 info(" driver: %s %s\n", di.driver, di.version);
696 * General device flags
698 nic_flags = get_nic_flags(ifr_elem->ifr_name);
699 info(" stat:%s%s%s%s\n",
700 (((nic_flags & IFF_UP) == IFF_UP) ? " up" : " not up"),
701 (((nic_flags & IFF_RUNNING) ==
702 IFF_RUNNING) ? " running" : ""),
703 (((nic_flags & IFF_LOOPBACK) ==
704 IFF_LOOPBACK) ? ", loops back" : ""),
705 (((nic_flags & IFF_POINTOPOINT) ==
706 IFF_POINTOPOINT) ? ", point-to-point link" : ""));
708 info(" mtu: %d Byte\n", get_mtu(ifr_elem->ifr_name));
709 info(" irq: %d\n",
710 get_nic_irq_number(ifr_elem->ifr_name));
713 * Device Bitrate
715 speed = get_device_bitrate_generic(ifr_elem->ifr_name);
716 if (speed) {
717 info(" bitrate: %d Mb/s\n", speed);
721 * Wireless information
723 /* XXX: a better way to test for a wireless dev!? */
724 if (get_wireless_bitrate(ifr_elem->ifr_name)) {
725 txp =
726 adjust_dbm_level(get_wireless_tx_power
727 (ifr_elem->ifr_name));
729 if (get_wireless_ssid(ifr_elem->ifr_name, essid) > 0)
730 info(" connected to ssid: %s\n", essid);
731 if (get_wireless_sigqual(ifr_elem->ifr_name, &ws) >= 0) {
732 info(" link quality: %d/%d\n",
733 ws.qual.qual,
734 get_wireless_rangemax_sigqual(ifr_elem->
735 ifr_name));
736 info(" signal level: %d dBm\n",
737 adjust_dbm_level(ws.qual.level));
738 info(" noise level: %d dBm\n",
739 adjust_dbm_level(ws.qual.noise));
740 info(" tx-power: %d dBm (%d mW)\n", txp,
741 dbm_to_mwatt(txp));
742 info(" operation mode: %s (%d) %s\n",
743 wop_entry(ws.status, 0), ws.status,
744 wop_entry(ws.status, 1));
745 info(" pkg discarded:\n");
746 info(" rx invalid nwid: %d\n",
747 ws.discard.nwid);
748 info(" rx invalid crypt: %d\n",
749 ws.discard.code);
750 info(" rx invalif frag: %d\n",
751 ws.discard.fragment);
752 info(" tx excessive retries: %d\n", ws.discard.retries);
753 info(" invalid misc reasons: %d\n", ws.discard.misc);
758 xfree(ifr_buffer);
762 * inject_kernel_bpf - Binds filter code to socket
763 * @sock: socket
764 * @bpf: Berkeley Packet Filter code
766 void inject_kernel_bpf(int sock, struct sock_fprog *bpf)
768 int ret;
770 assert(bpf);
772 ret = setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, bpf, sizeof(*bpf));
773 if (ret < 0) {
774 err("setsockopt: filter cannot be injected");
775 close(sock);
776 exit(EXIT_FAILURE);
781 * reset_kernel_bpf - Resets filter code from socket
782 * @sock: socket
784 void reset_kernel_bpf(int sock)
786 int ret;
787 int foo = 0;
789 ret = setsockopt(sock, SOL_SOCKET, SO_DETACH_FILTER, &foo, sizeof(foo));
790 if (ret < 0) {
791 err("setsockopt: cannot reset filter");
792 close(sock);
793 exit(EXIT_FAILURE);
798 * ethdev_to_ifindex - Translates device name into device number
799 * @dev: device name
801 int ethdev_to_ifindex(const char *dev)
803 int ret;
804 int sock;
805 struct ifreq ethreq;
807 assert(dev);
809 sock = get_af_socket(AF_INET);
811 memset(&ethreq, 0, sizeof(ethreq));
812 strlcpy(ethreq.ifr_name, dev, sizeof(ethreq.ifr_name) - 1);
814 ret = ioctl(sock, SIOCGIFINDEX, &ethreq);
815 if (ret < 0) {
816 err("ioctl: cannot determine dev number for %s",
817 ethreq.ifr_name);
818 close(sock);
819 exit(EXIT_FAILURE);
822 close(sock);
823 return (ethreq.ifr_ifindex);
827 * net_stat - Grabs and prints current socket statistics
828 * @sock: socket
830 void net_stat(int sock)
832 int ret;
833 struct tpacket_stats kstats;
834 socklen_t slen = sizeof(kstats);
836 memset(&kstats, 0, sizeof(kstats));
838 ret = getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &kstats, &slen);
839 if (ret > -1) {
840 info("\r%d frames incoming\n", kstats.tp_packets);
841 info("\r%d frames passed filter\n",
842 kstats.tp_packets - kstats.tp_drops);
843 info("\r%d frames failed filter (due to out of space)\n",
844 kstats.tp_drops);
849 * parse_rules - Parses a BPF rulefile
850 * @rulefile: path to rulefile
851 * @bpf: sock filter
852 * @len: len of bpf
854 int parse_rules(char *rulefile, struct sock_fprog *bpf)
856 int ret;
857 char buff[128] = { 0 };
859 struct sock_filter sf_single;
861 assert(bpf);
862 assert(rulefile);
864 FILE *fp = fopen(rulefile, "r");
865 if (!fp) {
866 err("Cannot read rulefile");
867 exit(EXIT_FAILURE);
870 memset(buff, 0, sizeof(buff));
872 info("Parsing rulefile %s\n", rulefile);
874 while (fgets(buff, sizeof(buff), fp) != NULL) {
875 /* We're using evil sscanf, so we have to assure
876 that we don't get into a buffer overflow ... */
877 buff[sizeof(buff) - 1] = 0;
879 /* A comment. Skip this line */
880 if (buff[0] != '{') {
881 continue;
884 memset(&sf_single, 0, sizeof(sf_single));
886 ret = sscanf(buff, "{ 0x%x, %d, %d, 0x%08x },",
887 (unsigned int *)((void *)&(sf_single.code)),
888 (int *)((void *)&(sf_single.jt)),
889 (int *)((void *)&(sf_single.jf)), &(sf_single.k));
890 if (ret != 4) {
891 /* No valid bpf opcode format or a syntax error */
892 return 0;
895 bpf->len++;
896 bpf->filter =
897 (struct sock_filter *)realloc(bpf->filter,
898 bpf->len * sizeof(sf_single));
900 memcpy(&bpf->filter[bpf->len - 1], &sf_single,
901 sizeof(sf_single));
903 memset(buff, 0, sizeof(buff));
906 fclose(fp);
908 /* bpf_validate() returns 0 on failiure */
909 return (bpf_validate(bpf));