promisc: Constify `ifname' parameters to {enter,leave}_promiscuous_mode()
[netsniff-ng.git] / dissector_eth.c
blobb87c957a65056aac86cc5e1f3062228e66a8c4e8
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2009, 2010 Daniel Borkmann.
4 * Subject to the GPL, version 2.
5 */
7 #include <stdint.h>
9 #include "hash.h"
10 #include "oui.h"
11 #include "str.h"
12 #include "protos.h"
13 #include "pkt_buff.h"
14 #include "dissector.h"
15 #include "dissector_eth.h"
16 #include "xmalloc.h"
18 struct hash_table eth_lay2;
19 struct hash_table eth_lay3;
21 static struct hash_table eth_ether_types;
22 static struct hash_table eth_ports_udp;
23 static struct hash_table eth_ports_tcp;
25 struct port {
26 unsigned int id;
27 char *port;
28 struct port *next;
31 #define __do_lookup_inline(id, struct_name, hash_ptr, struct_member) \
32 ({ \
33 struct struct_name *entry = lookup_hash(id, hash_ptr); \
35 while (entry && id != entry->id) \
36 entry = entry->next; \
38 (entry && id == entry->id ? entry->struct_member : NULL); \
41 char *lookup_port_udp(unsigned int id)
43 return __do_lookup_inline(id, port, &eth_ports_udp, port);
46 char *lookup_port_tcp(unsigned int id)
48 return __do_lookup_inline(id, port, &eth_ports_tcp, port);
51 char *lookup_ether_type(unsigned int id)
53 return __do_lookup_inline(id, port, &eth_ether_types, port);
56 #ifdef HAVE_DISSECTOR_PROTOS
57 static inline void dissector_init_entry(int type)
59 dissector_set_print_type(&ethernet_ops, type);
62 static inline void dissector_init_exit(int type)
64 dissector_set_print_type(&none_ops, type);
67 static void dissector_init_layer_2(int type)
69 init_hash(&eth_lay2);
70 INSERT_HASH_PROTOS(arp_ops, eth_lay2);
71 INSERT_HASH_PROTOS(lldp_ops, eth_lay2);
72 INSERT_HASH_PROTOS(vlan_ops, eth_lay2);
73 INSERT_HASH_PROTOS(ipv4_ops, eth_lay2);
74 INSERT_HASH_PROTOS(ipv6_ops, eth_lay2);
75 INSERT_HASH_PROTOS(QinQ_ops, eth_lay2);
76 INSERT_HASH_PROTOS(mpls_uc_ops, eth_lay2);
77 for_each_hash_int(&eth_lay2, dissector_set_print_type, type);
80 static void dissector_init_layer_3(int type)
82 init_hash(&eth_lay3);
83 INSERT_HASH_PROTOS(icmpv4_ops, eth_lay3);
84 INSERT_HASH_PROTOS(icmpv6_ops, eth_lay3);
85 INSERT_HASH_PROTOS(igmp_ops, eth_lay3);
86 INSERT_HASH_PROTOS(ip_auth_ops, eth_lay3);
87 INSERT_HASH_PROTOS(ip_esp_ops, eth_lay3);
88 INSERT_HASH_PROTOS(ipv6_dest_opts_ops, eth_lay3);
89 INSERT_HASH_PROTOS(ipv6_fragm_ops, eth_lay3);
90 INSERT_HASH_PROTOS(ipv6_hop_by_hop_ops, eth_lay3);
91 INSERT_HASH_PROTOS(ipv6_in_ipv4_ops, eth_lay3);
92 INSERT_HASH_PROTOS(ipv6_mobility_ops, eth_lay3);
93 INSERT_HASH_PROTOS(ipv6_no_next_header_ops, eth_lay3);
94 INSERT_HASH_PROTOS(ipv6_routing_ops, eth_lay3);
95 INSERT_HASH_PROTOS(tcp_ops, eth_lay3);
96 INSERT_HASH_PROTOS(udp_ops, eth_lay3);
97 for_each_hash_int(&eth_lay3, dissector_set_print_type, type);
99 #else
100 static inline void dissector_init_entry(int type __maybe_unused) {}
101 static inline void dissector_init_exit(int type __maybe_unused) {}
102 static void dissector_init_layer_2(int type __maybe_unused) {}
103 static void dissector_init_layer_3(int type __maybe_unused) {}
104 #endif
106 enum ports {
107 PORTS_UDP,
108 PORTS_TCP,
109 PORTS_ETHER,
112 static void dissector_init_ports(enum ports which)
114 FILE *fp;
115 char buff[128], *ptr, *file, *end;
116 struct hash_table *table;
117 struct port *p;
118 void **pos;
120 switch (which) {
121 case PORTS_UDP:
122 file = PREFIX_STRING "/etc/netsniff-ng/udp.conf";
123 table = &eth_ports_udp;
124 break;
125 case PORTS_TCP:
126 file = PREFIX_STRING "/etc/netsniff-ng/tcp.conf";
127 table = &eth_ports_tcp;
128 break;
129 case PORTS_ETHER:
130 file = PREFIX_STRING "/etc/netsniff-ng/ether.conf";
131 table = &eth_ether_types;
132 break;
133 default:
134 bug();
137 fp = fopen(file, "r");
138 if (!fp)
139 panic("No %s found!\n", file);
141 memset(buff, 0, sizeof(buff));
143 while (fgets(buff, sizeof(buff), fp) != NULL) {
144 buff[sizeof(buff) - 1] = 0;
145 ptr = buff;
147 p = xmalloc(sizeof(*p));
148 p->id = strtol(ptr, &end, 0);
149 /* not a valid line, skip */
150 if (p->id == 0 && end == ptr) {
151 xfree(p);
152 continue;
155 ptr = strstr(buff, ", ");
156 /* likewise */
157 if (!ptr) {
158 xfree(p);
159 continue;
162 ptr += strlen(", ");
163 ptr = strtrim_right(ptr, '\n');
164 ptr = strtrim_right(ptr, ' ');
166 p->port = xstrdup(ptr);
167 p->next = NULL;
169 pos = insert_hash(p->id, p, table);
170 if (pos) {
171 p->next = *pos;
172 *pos = p;
175 memset(buff, 0, sizeof(buff));
178 fclose(fp);
181 static int dissector_cleanup_ports(void *ptr)
183 struct port *tmp, *p = ptr;
185 if (!ptr)
186 return 0;
188 while ((tmp = p->next)) {
189 xfree(p->port);
190 xfree(p);
191 p = tmp;
194 xfree(p->port);
195 xfree(p);
197 return 0;
200 void dissector_init_ethernet(int fnttype)
202 dissector_init_entry(fnttype);
203 dissector_init_layer_2(fnttype);
204 dissector_init_layer_3(fnttype);
205 dissector_init_exit(fnttype);
207 #ifdef __WITH_PROTOS
208 dissector_init_oui();
209 #endif
210 dissector_init_ports(PORTS_UDP);
211 dissector_init_ports(PORTS_TCP);
212 dissector_init_ports(PORTS_ETHER);
215 void dissector_cleanup_ethernet(void)
217 free_hash(&eth_lay2);
218 free_hash(&eth_lay3);
220 for_each_hash(&eth_ether_types, dissector_cleanup_ports);
221 for_each_hash(&eth_ports_udp, dissector_cleanup_ports);
222 for_each_hash(&eth_ports_tcp, dissector_cleanup_ports);
224 free_hash(&eth_ether_types);
225 free_hash(&eth_ports_udp);
226 free_hash(&eth_ports_tcp);
228 #ifdef __WITH_PROTOS
229 dissector_cleanup_oui();
230 #endif