Merge pull request #58 from electronjoe/a1cf780cccc4819eb360cda1e0e94e17935cb8c7
[netsniff-ng-old.git] / dissector_eth.c
blobf35264592e7ea0cb2393f753dc6977c7bd71afad
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 "protos.h"
12 #include "pkt_buff.h"
13 #include "dissector.h"
14 #include "dissector_eth.h"
15 #include "xmalloc.h"
17 struct hash_table eth_lay2;
18 struct hash_table eth_lay3;
20 static struct hash_table eth_ether_types;
21 static struct hash_table eth_ports_udp;
22 static struct hash_table eth_ports_tcp;
24 struct port {
25 unsigned int id;
26 char *port;
27 struct port *next;
30 #define __do_lookup_inline(id, struct_name, hash_ptr, struct_member) \
31 ({ \
32 struct struct_name *entry = lookup_hash(id, hash_ptr); \
34 while (entry && id != entry->id) \
35 entry = entry->next; \
37 (entry && id == entry->id ? entry->struct_member : 0); \
40 char *lookup_port_udp(unsigned int id)
42 return __do_lookup_inline(id, port, &eth_ports_udp, port);
45 char *lookup_port_tcp(unsigned int id)
47 return __do_lookup_inline(id, port, &eth_ports_tcp, port);
50 char *lookup_ether_type(unsigned int id)
52 return __do_lookup_inline(id, port, &eth_ether_types, port);
55 #ifdef __WITH_PROTOS
56 static inline void dissector_init_entry(int type)
58 dissector_set_print_type(&ethernet_ops, type);
61 static inline void dissector_init_exit(int type)
63 dissector_set_print_type(&none_ops, type);
66 static void dissector_init_layer_2(int type)
68 init_hash(&eth_lay2);
69 INSERT_HASH_PROTOS(arp_ops, eth_lay2);
70 INSERT_HASH_PROTOS(lldp_ops, eth_lay2);
71 INSERT_HASH_PROTOS(vlan_ops, eth_lay2);
72 INSERT_HASH_PROTOS(ipv4_ops, eth_lay2);
73 INSERT_HASH_PROTOS(ipv6_ops, eth_lay2);
74 INSERT_HASH_PROTOS(QinQ_ops, eth_lay2);
75 INSERT_HASH_PROTOS(mpls_uc_ops, eth_lay2);
76 for_each_hash_int(&eth_lay2, dissector_set_print_type, type);
79 static void dissector_init_layer_3(int type)
81 init_hash(&eth_lay3);
82 INSERT_HASH_PROTOS(icmpv4_ops, eth_lay3);
83 INSERT_HASH_PROTOS(icmpv6_ops, eth_lay3);
84 INSERT_HASH_PROTOS(igmp_ops, eth_lay3);
85 INSERT_HASH_PROTOS(ip_auth_ops, eth_lay3);
86 INSERT_HASH_PROTOS(ip_esp_ops, eth_lay3);
87 INSERT_HASH_PROTOS(ipv6_dest_opts_ops, eth_lay3);
88 INSERT_HASH_PROTOS(ipv6_fragm_ops, eth_lay3);
89 INSERT_HASH_PROTOS(ipv6_hop_by_hop_ops, eth_lay3);
90 INSERT_HASH_PROTOS(ipv6_in_ipv4_ops, eth_lay3);
91 INSERT_HASH_PROTOS(ipv6_mobility_ops, eth_lay3);
92 INSERT_HASH_PROTOS(ipv6_no_next_header_ops, eth_lay3);
93 INSERT_HASH_PROTOS(ipv6_routing_ops, eth_lay3);
94 INSERT_HASH_PROTOS(tcp_ops, eth_lay3);
95 INSERT_HASH_PROTOS(udp_ops, eth_lay3);
96 for_each_hash_int(&eth_lay3, dissector_set_print_type, type);
98 #else
99 static inline void dissector_init_entry(int type) {}
100 static inline void dissector_init_exit(int type) {}
101 static void dissector_init_layer_2(int type) {}
102 static void dissector_init_layer_3(int type) {}
103 #endif /* __WITH_PROTOS */
105 enum ports {
106 PORTS_UDP,
107 PORTS_TCP,
108 PORTS_ETHER,
111 static void dissector_init_ports(enum ports which)
113 FILE *fp;
114 char buff[128], *ptr, *file;
115 struct hash_table *table;
116 struct port *p;
117 void **pos;
119 switch (which) {
120 case PORTS_UDP:
121 file = "/etc/netsniff-ng/udp.conf";
122 table = &eth_ports_udp;
123 break;
124 case PORTS_TCP:
125 file = "/etc/netsniff-ng/tcp.conf";
126 table = &eth_ports_tcp;
127 break;
128 case PORTS_ETHER:
129 file = "/etc/netsniff-ng/ether.conf";
130 table = &eth_ether_types;
131 break;
132 default:
133 bug();
136 fp = fopen(file, "r");
137 if (!fp)
138 panic("No %s found!\n", file);
140 memset(buff, 0, sizeof(buff));
142 while (fgets(buff, sizeof(buff), fp) != NULL) {
143 buff[sizeof(buff) - 1] = 0;
144 ptr = buff;
146 p = xmalloc(sizeof(*p));
147 p->id = strtol(ptr, &ptr, 0);
149 if ((ptr = strstr(buff, ", ")))
150 ptr += strlen(", ");
151 ptr = strtrim_right(ptr, '\n');
152 ptr = strtrim_right(ptr, ' ');
154 p->port = xstrdup(ptr);
155 p->next = NULL;
157 pos = insert_hash(p->id, p, table);
158 if (pos) {
159 p->next = *pos;
160 *pos = p;
163 memset(buff, 0, sizeof(buff));
166 fclose(fp);
169 static int dissector_cleanup_ports(void *ptr)
171 struct port *tmp, *p = ptr;
173 if (!ptr)
174 return 0;
176 while ((tmp = p->next)) {
177 xfree(p->port);
178 xfree(p);
179 p = tmp;
182 xfree(p->port);
183 xfree(p);
185 return 0;
188 void dissector_init_ethernet(int fnttype)
190 dissector_init_entry(fnttype);
191 dissector_init_layer_2(fnttype);
192 dissector_init_layer_3(fnttype);
193 dissector_init_exit(fnttype);
195 #ifdef __WITH_PROTOS
196 dissector_init_oui();
197 #endif
198 dissector_init_ports(PORTS_UDP);
199 dissector_init_ports(PORTS_TCP);
200 dissector_init_ports(PORTS_ETHER);
203 void dissector_cleanup_ethernet(void)
205 free_hash(&eth_lay2);
206 free_hash(&eth_lay3);
208 for_each_hash(&eth_ether_types, dissector_cleanup_ports);
209 for_each_hash(&eth_ports_udp, dissector_cleanup_ports);
210 for_each_hash(&eth_ports_tcp, dissector_cleanup_ports);
212 free_hash(&eth_ether_types);
213 free_hash(&eth_ports_udp);
214 free_hash(&eth_ports_tcp);
216 #ifdef __WITH_PROTOS
217 dissector_cleanup_oui();
218 #endif