1 #include "config.h"
2 #include <libtrace.h>
3 #include <err.h>
4 #include <time.h>
5 #include "libpacketdump.h"
6 #include "lt_bswap.h"
7 #include <stdio.h>
8 #include <netdb.h>
9 #include <stdlib.h>
10 #include <getopt.h>
11 #include <unistd.h>
12 #include <sys/socket.h>
13 
14 #ifdef HAVE_NETINET_ETHER
15 #  include <netinet/ether.h>
16 #endif
17 
18 
19 #ifdef HAVE_INTTYPES_H
20 #  include <inttypes.h>
21 #else
22 #  error "Can't find inttypes.h"
23 #endif
24 
25 #ifdef HAVE_LIMITS_H
26 #  include <limits.h>
27 #endif
28 
29 #ifdef HAVE_SYS_LIMITS_H
30 #  include <sys/limits.h>
31 #endif
32 
33 #ifdef HAVE_SYS_TYPES_H
34 #  include <sys/types.h>
35 #endif
36 #include <net/if.h>
37 #include <netinet/in.h>
38 #include <stdio.h>
39 
40 #include <net/if_arp.h>
41 #ifdef HAVE_NETINET_IF_ETHER_H
42 #  include <netinet/if_ether.h>
43 #endif
44 #include <dlfcn.h>
45 #include <map>
46 #include <string>
47 #include <ctype.h>
48 #include "libpacketdump.h"
49 extern "C"{
50 #include "grammar.h"
51 }
52 
53 enum decode_style_t {
54     DECODE_NORMAL,
55     DECODE_PARSER
56 };
57 
58 typedef void (*decode_norm_t)(uint16_t type,const char *packet,int len);
59 typedef void (*decode_parser_t)(uint16_t type,const char *packet,int len, element_t* el);
60 
61 typedef union decode_funcs {
62     decode_norm_t decode_n;
63     decode_parser_t decode_p;
64 } decode_funcs_t;
65 
66 typedef struct decoder {
67     enum decode_style_t style;
68     decode_funcs_t *func;
69     element_t *el; // make a union of structs with all args in it for all funcs?
70 } decode_t;
71 
72 
73 static std::map<std::string,std::map<uint16_t,decode_t> > decoders;
74 
75 #define WIDTH 16
76 
77 #ifndef DIRNAME
78 #define DIRNAME "./"
79 #warning "No DIRNAME set!"
80 #endif
81 
formatted_hexdump(const char * packet,int len)82 static void formatted_hexdump(const char *packet, int len) {
83 	int i;
84 
85 	for(i=0;i<len; /* Nothing */ ) {
86 		int j;
87 		printf("\n ");
88 		for(j=0;j<WIDTH;j++) {
89 			if (i+j<len)
90 				printf(" %02x",(unsigned char)packet[i+j]);
91 			else
92 				printf("   ");
93 		}
94 		printf("    ");
95 		for(j=0;j<WIDTH;j++) {
96 			if (i+j<len)
97 				if (isprint((unsigned char)packet[i+j]))
98 					printf("%c",(unsigned char)packet[i+j]);
99 				else
100 					printf(".");
101 			else
102 				printf("   ");
103 		}
104 		if (i+WIDTH>len)
105 			break;
106 		else
107 			i+=WIDTH;
108 	}
109 	printf("\n");
110 }
111 
trace_hexdump_packet(struct libtrace_packet_t * packet)112 void trace_hexdump_packet(struct libtrace_packet_t *packet) {
113 
114 	libtrace_linktype_t linktype;
115 	uint32_t length;
116 	const char *pkt_ptr = (char *)trace_get_packet_buffer(packet, &linktype, NULL);
117 
118 	time_t sec = (time_t)trace_get_seconds(packet);
119 
120 	length = trace_get_capture_length(packet);
121 
122 	if (pkt_ptr == NULL || length == 0) {
123 		printf(" [No packet payload]\n");
124 		return;
125 	}
126 
127 	printf("\n%s",ctime(&sec));
128 	printf(" Capture: Packet Length: %i/%i Direction Value: %i\n",
129 			(int)length,
130 			(int)trace_get_wire_length(packet),
131 			(int)trace_get_direction(packet));
132 
133 
134 	formatted_hexdump(pkt_ptr, (int)length);
135 	return;
136 }
137 
trace_dump_packet(struct libtrace_packet_t * packet)138 void trace_dump_packet(struct libtrace_packet_t *packet)
139 {
140 	time_t sec = (time_t)trace_get_seconds(packet);
141 	libtrace_linktype_t linktype;
142 	uint32_t length;
143 	const char *link=(char *)trace_get_packet_buffer(packet,&linktype,NULL);
144 
145 	length = trace_get_capture_length(packet);
146 
147 	printf("\n%s",ctime(&sec));
148 	printf(" Capture: Packet Length: %i/%i Direction Value: %i\n",
149 			(int)length,
150 			(int)trace_get_wire_length(packet),
151 			(int)trace_get_direction(packet));
152 	if (!link)
153 		printf(" [No link layer available]\n");
154 	else
155 		decode_next(link,length, "link",
156 			linktype);
157 }
158 
generic_decode(uint16_t type,const char * packet,int len)159 static void generic_decode(uint16_t type,const char *packet, int len) {
160 	printf(" Unknown Protocol: %i",type);
161 
162 	formatted_hexdump(packet, len);
163 }
164 
open_so_decoder(const char * name,int type)165 static void *open_so_decoder(const char *name,int type)
166 {
167 	char path[1024];
168 	void *hdl;
169 	/* Only check LIBPKTDUMPDIR if we're not setuid.  Not bulletproof, but hopefully anyone who
170 	 * sets uid == euid will also clear the environment (eg sudo).
171 	 */
172 	if (getuid() == geteuid() && getenv("LIBPKTDUMPDIR")) {
173 		snprintf(path,sizeof(path),"%s/%s_%i.so",getenv("LIBPKTDUMPDIR"),name,type);
174 		hdl = dlopen(path,RTLD_LAZY);
175 		if (hdl)
176 			return hdl;
177 	}
178 	/* If the variable isn't set, *or* if we don't find anything, try the system location. */
179 	snprintf(path,sizeof(path),DIRNAME "/%s_%i.so",name,type);
180 	hdl = dlopen(path,RTLD_LAZY);
181 	if (hdl)
182 		return hdl;
183 
184 	return hdl;
185 }
186 
open_protocol_decoder(const char * name,int type)187 static void *open_protocol_decoder(const char *name, int type)
188 {
189 	char path[1024];
190 	void *hdl;
191 	/* Only check LIBPKTDUMPDIR if we're not setuid.  Not bulletproof, but hopefully anyone who
192 	 * sets uid == euid will also clear the environment (eg sudo).
193 	 */
194 	if (getuid() == geteuid() && getenv("LIBPKTDUMPDIR")) {
195 		snprintf(path,sizeof(path),"%s/%s_%i.protocol",getenv("LIBPKTDUMPDIR"),name,type);
196 		hdl = parse_protocol_file(path);
197 		if (hdl)
198 			return hdl;
199 	}
200 	/* Try the system directory */
201 	snprintf(path,sizeof(path),DIRNAME "/%s_%i.protocol",
202 		name,type);
203 	hdl = parse_protocol_file(path);
204 
205 	if (!hdl)
206 		return hdl;
207 
208 	return hdl;
209 }
210 
decode_next(const char * packet,int len,const char * proto_name,int type)211 void decode_next(const char *packet,int len,const char *proto_name,int type)
212 {
213 	std::string sname(proto_name);
214 
215 	// if we haven't worked out how to decode this type yet, load the
216 	// appropriate files to do so
217 	if (decoders[sname].find(type)==decoders[sname].end()) {
218 		void *hdl;
219 		decode_funcs_t *func = new decode_funcs_t;
220 		decode_t dec;
221 
222 		/* Try and find a .so to handle this protocol */
223 		hdl = open_so_decoder(sname.c_str(),type);
224 		if (hdl) {
225 			void *s=dlsym(hdl,"decode");
226 			if (s) {
227 				// use the shared library
228 				func->decode_n = (decode_norm_t)s;
229 				dec.style = DECODE_NORMAL;
230 				dec.el = NULL;
231 			}
232 			else {
233 				dlclose(hdl);
234 				hdl = NULL;
235 			}
236 		}
237 
238 		/* We didn't successfully open the .so, try finding a .protocol that we can use */
239 		if (!hdl) {
240 			hdl = open_protocol_decoder(sname.c_str(),type);
241 			if (hdl) {
242 				// use the protocol file
243 				func->decode_p = decode_protocol_file;
244 				dec.style = DECODE_PARSER;
245 				dec.el = (element_t*)hdl;
246 			}
247 		}
248 
249 		/* No matches found, fall back to the generic decoder. */
250 		/* TODO: We should have a variety of fallback decoders based on the protocol. */
251 		if(!hdl)
252 		{
253 			// no protocol file either, use a generic one
254 			func->decode_n = generic_decode;
255 			dec.style = DECODE_NORMAL;
256 			dec.el = NULL;
257 		}
258 
259 		dec.func = func;
260 		decoders[sname][type] = dec;
261 	}
262 
263 	/* TODO: Instead of haxing this here, we should provide a series of generic_decode's
264 	 * and let the code above deal with it.
265 	 */
266 	if (decoders[sname][type].func->decode_n == generic_decode) {
267 		/* We can't decode a link, so lets skip that and see if libtrace
268 		 * knows how to find us the ip header
269 		 */
270 
271 		/* Also, don't try to skip if the linktype is not valid,
272 		 * because libtrace will just assert fail and that's never
273 		 * good */
274 		if (sname=="link" && type != -1) {
275 			uint16_t newtype;
276 			uint32_t newlen=len;
277 			const char *network=(const char*)trace_get_payload_from_link((void*)packet,
278 					(libtrace_linktype_t)type,
279 					&newtype,&newlen);
280 			if (network) {
281 				printf("skipping unknown link header of type %i to network type %i\n",type,newtype);
282 				/* Should hex dump this too. */
283 				decode_next(network,newlen,"eth",newtype);
284 				return;
285 			}
286 		}
287 		else {
288 			printf("unknown protocol %s/%i\n",sname.c_str(),type);
289 		}
290 	}
291 
292 	// decode using the appropriate function
293 	switch(decoders[sname][type].style)
294 	{
295 		case DECODE_NORMAL:
296 			decoders[sname][type].func->decode_n(type,packet,len);
297 			break;
298 
299 		case DECODE_PARSER:
300 			decoders[sname][type].func->decode_p(type,packet,len,
301 				decoders[sname][type].el);
302 			break;
303 
304 	};
305 }
306 
307