improving dissector_fuzz
[netsniff-ng.git] / src / dissector_eth.c
blob2ddaf0c285f51fb0df06297ab92959ded3f66fa6
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2009, 2010 Daniel Borkmann.
5 * Subject to the GPL, version 2.
6 */
8 #include <stdint.h>
10 #include "hash.h"
11 #include "protos.h"
12 #include "pkt_buff.h"
13 #include "dissector.h"
14 #include "dissector_eth.h"
15 #include "xmalloc.h"
16 #include "xstring.h"
18 struct hash_table eth_lay2;
19 struct hash_table eth_lay3;
20 struct hash_table eth_lay4;
22 static struct hash_table eth_ether_types;
23 static struct hash_table eth_ports_udp;
24 static struct hash_table eth_ports_tcp;
25 static struct hash_table eth_oui;
27 struct vendor_id {
28 unsigned int id;
29 char *vendor;
30 struct vendor_id *next;
33 struct port_tcp {
34 unsigned int id;
35 char *port;
36 struct port_tcp *next;
39 struct port_udp {
40 unsigned int id;
41 char *port;
42 struct port_udp *next;
45 struct ether_type {
46 unsigned int id;
47 char *type;
48 struct ether_type *next;
51 /* Note: this macro only applies to the lookup_* functions here in this file,
52 * mainly to remove redundand code. */
53 #define __do_lookup_inline(id, struct_name, hash_ptr, struct_member) \
54 ({ \
55 struct struct_name *entry = lookup_hash(id, hash_ptr); \
56 while (entry && id != entry->id) \
57 entry = entry->next; \
58 (entry && id == entry->id ? entry->struct_member : "Unknown");\
61 char *lookup_vendor(unsigned int id)
63 return __do_lookup_inline(id, vendor_id, &eth_oui, vendor);
66 char *lookup_port_udp(unsigned int id)
68 return __do_lookup_inline(id, port_udp, &eth_ports_udp, port);
71 char *lookup_port_tcp(unsigned int id)
73 return __do_lookup_inline(id, port_tcp, &eth_ports_tcp, port);
76 char *lookup_ether_type(unsigned int id)
78 return __do_lookup_inline(id, ether_type, &eth_ether_types, type);
81 static inline void dissector_init_entry(int type)
83 dissector_set_print_type(&ethernet_ops, type);
86 static inline void dissector_init_exit(int type)
88 dissector_set_print_type(&none_ops, type);
91 static void dissector_init_layer_2(int type)
93 init_hash(&eth_lay2);
94 INSERT_HASH_PROTOS(arp_ops, eth_lay2);
95 INSERT_HASH_PROTOS(vlan_ops, eth_lay2);
96 INSERT_HASH_PROTOS(ipv4_ops, eth_lay2);
97 INSERT_HASH_PROTOS(ipv6_ops, eth_lay2);
98 for_each_hash_int(&eth_lay2, dissector_set_print_type, type);
101 static void dissector_init_layer_3(int type)
103 init_hash(&eth_lay3);
104 INSERT_HASH_PROTOS(igmp_ops, eth_lay3);
105 INSERT_HASH_PROTOS(ipv6_routing_ops, eth_lay3);
106 INSERT_HASH_PROTOS(ipv6_no_next_header_ops, eth_lay3);
107 for_each_hash_int(&eth_lay3, dissector_set_print_type, type);
110 static void dissector_init_layer_4(int type)
112 init_hash(&eth_lay4);
113 for_each_hash_int(&eth_lay4, dissector_set_print_type, type);
116 static void dissector_init_oui(void)
118 FILE *fp;
119 char buff[512], *ptr;
120 struct vendor_id *ven;
121 void **pos;
122 fp = fopen("/etc/netsniff-ng/oui.conf", "r");
123 if (!fp)
124 panic("No /etc/netsniff-ng/oui.conf found!\n");
125 memset(buff, 0, sizeof(buff));
126 while (fgets(buff, sizeof(buff), fp) != NULL) {
127 buff[sizeof(buff) - 1] = 0;
128 ven = xmalloc(sizeof(*ven));
129 ptr = buff;
130 ptr = skips(ptr);
131 ptr = getuint(ptr, &ven->id);
132 ptr = skips(ptr);
133 ptr = skipchar(ptr, ',');
134 ptr = skips(ptr);
135 ptr = strtrim_right(ptr, '\n');
136 ptr = strtrim_right(ptr, ' ');
137 ven->vendor = xstrdup(ptr);
138 ven->next = NULL;
139 pos = insert_hash(ven->id, ven, &eth_oui);
140 if (pos) {
141 ven->next = *pos;
142 *pos = ven;
144 memset(buff, 0, sizeof(buff));
146 fclose(fp);
149 static int dissector_cleanup_oui(void *ptr)
151 struct vendor_id *tmp, *v = ptr;
152 if (!ptr)
153 return 0;
154 while ((tmp = v->next)) {
155 xfree(v->vendor);
156 xfree(v);
157 v = tmp;
159 xfree(v->vendor);
160 xfree(v);
161 return 0;
164 static void dissector_init_ports_udp(void)
166 FILE *fp;
167 char buff[512], *ptr;
168 struct port_udp *pudp;
169 void **pos;
170 fp = fopen("/etc/netsniff-ng/udp.conf", "r");
171 if (!fp)
172 panic("No /etc/netsniff-ng/udp.conf found!\n");
173 memset(buff, 0, sizeof(buff));
174 while (fgets(buff, sizeof(buff), fp) != NULL) {
175 buff[sizeof(buff) - 1] = 0;
176 pudp = xmalloc(sizeof(*pudp));
177 ptr = buff;
178 ptr = skips(ptr);
179 ptr = getuint(ptr, &pudp->id);
180 ptr = skips(ptr);
181 ptr = skipchar(ptr, ',');
182 ptr = skips(ptr);
183 ptr = strtrim_right(ptr, '\n');
184 ptr = strtrim_right(ptr, ' ');
185 pudp->port = xstrdup(ptr);
186 pudp->next = NULL;
187 pos = insert_hash(pudp->id, pudp, &eth_ports_udp);
188 if (pos) {
189 pudp->next = *pos;
190 *pos = pudp;
192 memset(buff, 0, sizeof(buff));
194 fclose(fp);
197 static int dissector_cleanup_ports_udp(void *ptr)
199 struct port_udp *tmp, *p = ptr;
200 if (!ptr)
201 return 0;
202 while ((tmp = p->next)) {
203 xfree(p->port);
204 xfree(p);
205 p = tmp;
207 xfree(p->port);
208 xfree(p);
209 return 0;
212 static void dissector_init_ports_tcp(void)
214 FILE *fp;
215 char buff[512], *ptr;
216 struct port_tcp *ptcp;
217 void **pos;
218 fp = fopen("/etc/netsniff-ng/tcp.conf", "r");
219 if (!fp)
220 panic("No /etc/netsniff-ng/tcp.conf found!\n");
221 memset(buff, 0, sizeof(buff));
222 while (fgets(buff, sizeof(buff), fp) != NULL) {
223 buff[sizeof(buff) - 1] = 0;
224 ptcp = xmalloc(sizeof(*ptcp));
225 ptr = buff;
226 ptr = skips(ptr);
227 ptr = getuint(ptr, &ptcp->id);
228 ptr = skips(ptr);
229 ptr = skipchar(ptr, ',');
230 ptr = skips(ptr);
231 ptr = strtrim_right(ptr, '\n');
232 ptr = strtrim_right(ptr, ' ');
233 ptcp->port = xstrdup(ptr);
234 ptcp->next = NULL;
235 pos = insert_hash(ptcp->id, ptcp, &eth_ports_tcp);
236 if (pos) {
237 ptcp->next = *pos;
238 *pos = ptcp;
240 memset(buff, 0, sizeof(buff));
242 fclose(fp);
245 static int dissector_cleanup_ports_tcp(void *ptr)
247 struct port_tcp *tmp, *p = ptr;
248 if (!ptr)
249 return 0;
250 while ((tmp = p->next)) {
251 xfree(p->port);
252 xfree(p);
253 p = tmp;
255 xfree(p->port);
256 xfree(p);
257 return 0;
260 static void dissector_init_ether_types(void)
262 FILE *fp;
263 char buff[512], *ptr;
264 struct ether_type *et;
265 void **pos;
266 fp = fopen("/etc/netsniff-ng/ether.conf", "r");
267 if (!fp)
268 panic("No /etc/netsniff-ng/ether.conf found!\n");
269 memset(buff, 0, sizeof(buff));
270 while (fgets(buff, sizeof(buff), fp) != NULL) {
271 buff[sizeof(buff) - 1] = 0;
272 et = xmalloc(sizeof(*et));
273 ptr = buff;
274 ptr = skips(ptr);
275 ptr = getuint(ptr, &et->id);
276 ptr = skips(ptr);
277 ptr = skipchar(ptr, ',');
278 ptr = skips(ptr);
279 ptr = strtrim_right(ptr, '\n');
280 ptr = strtrim_right(ptr, ' ');
281 et->type = xstrdup(ptr);
282 et->next = NULL;
283 pos = insert_hash(et->id, et, &eth_ether_types);
284 if (pos) {
285 et->next = *pos;
286 *pos = et;
288 memset(buff, 0, sizeof(buff));
290 fclose(fp);
293 static int dissector_cleanup_ether_types(void *ptr)
295 struct ether_type *tmp, *p = ptr;
296 if (!ptr)
297 return 0;
298 while ((tmp = p->next)) {
299 xfree(p->type);
300 xfree(p);
301 p = tmp;
303 xfree(p->type);
304 xfree(p);
305 return 0;
308 void dissector_init_ethernet(int fnttype)
310 dissector_init_entry(fnttype);
311 dissector_init_layer_2(fnttype);
312 dissector_init_layer_3(fnttype);
313 dissector_init_layer_4(fnttype);
314 dissector_init_exit(fnttype);
315 dissector_init_oui();
316 dissector_init_ports_udp();
317 dissector_init_ports_tcp();
318 dissector_init_ether_types();
321 void dissector_cleanup_ethernet(void)
323 free_hash(&eth_lay2);
324 free_hash(&eth_lay3);
325 free_hash(&eth_lay4);
326 for_each_hash(&eth_ether_types, dissector_cleanup_ether_types);
327 free_hash(&eth_ether_types);
328 for_each_hash(&eth_ports_udp, dissector_cleanup_ports_udp);
329 free_hash(&eth_ports_udp);
330 for_each_hash(&eth_ports_tcp, dissector_cleanup_ports_tcp);
331 free_hash(&eth_ports_tcp);
332 for_each_hash(&eth_oui, dissector_cleanup_oui);
333 free_hash(&eth_oui);