1 /* Copyright (C) 2000,2001 Salvatore Sanfilippo <antirez@invece.org>
2  * See the LICENSE file for more information.
3  *
4  * ARS Packet Description System.
5  *
6  * Please, prefix all the function with ars_d_ */
7 
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <sys/types.h>
12 #include <netinet/in.h>
13 #include <sys/stat.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include "ars.h"
17 
18 #define ARS_MAX_TSIZE	1024
ars_d_parser(char * t,char * next,size_t size)19 char *ars_d_parser(char *t, char *next, size_t size)
20 {
21 	int i = 0;
22 
23 	if (size == 0 || next == NULL || *t == '\0')
24 		return NULL;
25 	size--; /* space for nul term */
26 	while (1) {
27 		/* no space for the next char */
28 		if (i == size) {
29 			next[i] = '\0';
30 			return t;
31 		}
32 		switch(*t) {
33 		case '\0':
34 		case '{':
35 		case '}':
36 		case ',':
37 		case '=':
38 		case '+':
39 			if (i == 0) {
40 				next[i] = *t;
41 				next[i+1] = '\0';
42 				return t+1;
43 			} else {
44 				next[i] = '\0';
45 				return t;
46 			}
47 		default:
48 			next[i++] = *t++;
49 			break;
50 		}
51 	}
52 	return NULL; /* unreached */
53 }
54 
55 /* states */
56 #define ARS_G_LAYER		0
57 #define ARS_G_FIELD		1
58 #define ARS_G_VALUE		2
59 #define ARS_G_OBRACE_OR_PLUS	3
60 #define ARS_G_CBRACE		4
61 #define ARS_G_COMMA_OR_CBRACE	5
62 #define ARS_G_LEN_OR_PLUS	6
63 #define ARS_G_PLUS		7
64 #define ARS_G_EQUAL		8
65 
66 struct ars_d_keyword_info {
67 	char *ki_keyword;
68 	int ki_opt;
69 	void *(*ki_add) (struct ars_packet *pkt, int opt);
70 	int (*ki_set) (struct ars_packet *pkt, int layer, char *f, char *v);
71 };
72 
73 #define ARS_DKINFO_SIZE		64
74 
75 #define BOGUS_SET_F(x) \
76   int (x)(struct ars_packet *pkt, int layer, char *f, char *v) { return 0; }
77 
78 int ars_d_set_ip(struct ars_packet *pkt, int layer, char *f, char *v);
79 int ars_d_set_udp(struct ars_packet *pkt, int layer, char *f, char *v);
80 int ars_d_set_tcp(struct ars_packet *pkt, int layer, char *f, char *v);
81 int ars_d_set_icmp(struct ars_packet *pkt, int layer, char *f, char *v);
82 int ars_d_set_data(struct ars_packet *pkt, int layer, char *f, char *v);
83 BOGUS_SET_F(ars_d_set_ipopt_sec)
84 BOGUS_SET_F(ars_d_set_ipopt_sid)
85 BOGUS_SET_F(ars_d_set_ipopt_lsrr)
86 BOGUS_SET_F(ars_d_set_ipopt_ssrr)
87 BOGUS_SET_F(ars_d_set_ipopt_rr)
88 BOGUS_SET_F(ars_d_set_ipopt_ts)
89 BOGUS_SET_F(ars_d_set_tcpopt_mss)
90 BOGUS_SET_F(ars_d_set_tcpopt_wscale)
91 BOGUS_SET_F(ars_d_set_tcpopt_sackperm)
92 BOGUS_SET_F(ars_d_set_tcpopt_sack)
93 BOGUS_SET_F(ars_d_set_tcpopt_echo)
94 BOGUS_SET_F(ars_d_set_tcpopt_echoreply)
95 BOGUS_SET_F(ars_d_set_tcpopt_ts)
96 
97 struct ars_d_keyword_info ars_dkinfo[ARS_DKINFO_SIZE] = {
98 	/* KEYWORD	OPT		ADD function	SET function *
99 	 * --------------------------------------------------------- */
100 	{"ip",		0,		ars_add_iphdr,	ars_d_set_ip},
101 	{"ipopt.eol",	ARS_IPOPT_EOL,	ars_add_ipopt,	NULL},
102 	{"ipopt.nop",	ARS_IPOPT_NOP,	ars_add_ipopt,	NULL},
103 	{"ipopt.sec",	ARS_IPOPT_SEC,	ars_add_ipopt,	ars_d_set_ipopt_sec},
104 	{"ipopt.sid",	ARS_IPOPT_SID,	ars_add_ipopt,	ars_d_set_ipopt_sid},
105 	{"ipopt.lsrr",	ARS_IPOPT_LSRR,	ars_add_ipopt,	ars_d_set_ipopt_lsrr},
106 	{"ipopt.ssrr",	ARS_IPOPT_SSRR,	ars_add_ipopt,	ars_d_set_ipopt_ssrr},
107 	{"ipopt.rr",	ARS_IPOPT_RR,	ars_add_ipopt,	ars_d_set_ipopt_rr},
108 	{"ipopt.ts",	ARS_IPOPT_TIMESTAMP, ars_add_ipopt, ars_d_set_ipopt_ts},
109 	{"udp",		0,		ars_add_udphdr,	ars_d_set_udp},
110 	{"tcp",		0,		ars_add_tcphdr,	ars_d_set_tcp},
111 	{"tcpopt.end",	ARS_TCPOPT_EOL,	ars_add_tcpopt,	NULL},
112 	{"tcpopt.nop",	ARS_TCPOPT_NOP,	ars_add_tcpopt,	NULL},
113 	{"tcpopt.mss",	ARS_TCPOPT_MAXSEG, ars_add_tcpopt, ars_d_set_tcpopt_mss},
114 	{"tcpopt.wscale", ARS_TCPOPT_WINDOW, ars_add_tcpopt, ars_d_set_tcpopt_wscale},
115 	{"tcpopt.sackperm", ARS_TCPOPT_SACK_PERM, ars_add_tcpopt, ars_d_set_tcpopt_sackperm},
116 	{"tcpopt.sack", ARS_TCPOPT_SACK, ars_add_tcpopt, ars_d_set_tcpopt_sack},
117 	{"tcpopt.echo", ARS_TCPOPT_ECHOREQUEST, ars_add_tcpopt, ars_d_set_tcpopt_echo},
118 	{"tcpopt.echoreply", ARS_TCPOPT_ECHOREPLY, ars_add_tcpopt, ars_d_set_tcpopt_echoreply},
119 	{"tcpopt.ts",	ARS_TCPOPT_TIMESTAMP, ars_add_tcpopt, ars_d_set_tcpopt_ts},
120 	{"icmp",	0,		ars_add_icmphdr, ars_d_set_icmp},
121 	{"data",	0,		ars_add_data,	ars_d_set_data},
122 	{NULL, 0, NULL, NULL} /* nul term */
123 };
124 
ars_get_keyword_by_name(char * name)125 struct ars_d_keyword_info *ars_get_keyword_by_name(char *name)
126 {
127 	struct ars_d_keyword_info *k = ars_dkinfo;
128 
129 	while (k->ki_keyword) {
130 		if (strcasecmp(k->ki_keyword, name) == 0)
131 			return k;
132 		k++;
133 	}
134 	return NULL;
135 }
136 
ars_d_setlayer_size(struct ars_packet * pkt,int layer,char * size)137 int ars_d_setlayer_size(struct ars_packet *pkt, int layer, char *size)
138 {
139 	size_t newsize;
140 
141 	if (layer == ARS_LAST_LAYER)
142 		layer = pkt->p_layer_nr - 1;
143 	if (ars_valid_layer(layer) != -ARS_OK)
144 		return -ARS_INVALID;
145 
146 	newsize = ars_atou(size);
147 	if (newsize < 1 || newsize > pkt->p_layer[layer].l_size) {
148 		ars_set_error(pkt, "Invalid layer size in description");
149 		return -ARS_INVALID;
150 	}
151 	pkt->p_layer[layer].l_size = newsize;
152 
153 	__D(printf("Setting the layer to size %s\n", size);)
154 	return -ARS_OK;
155 }
156 
ars_d_set_ip(struct ars_packet * pkt,int layer,char * f,char * v)157 int ars_d_set_ip(struct ars_packet *pkt, int layer, char *f, char *v)
158 {
159 	struct ars_iphdr *ip;
160 
161 	if (layer == ARS_LAST_LAYER)
162 		layer = pkt->p_layer_nr - 1;
163 	if (ars_valid_layer(layer) != -ARS_OK)
164 		return -ARS_INVALID;
165 
166 	ip = pkt->p_layer[layer].l_data;
167 
168 	if (strcasecmp(f, "saddr") == 0) {
169 		return ars_resolve(pkt, &ip->saddr, v);
170 	} else if (strcasecmp(f, "daddr") == 0) {
171 		return ars_resolve(pkt, &ip->daddr, v);
172 	} else if (strcasecmp(f, "ihl") == 0) {
173 		ip->ihl = ars_atou(v);
174 		pkt->p_layer[layer].l_flags |= ARS_TAKE_IP_HDRLEN;
175 	} else if (strcasecmp(f, "ver") == 0) {
176 		ip->version = ars_atou(v);
177 		pkt->p_layer[layer].l_flags |= ARS_TAKE_IP_VERSION;
178 	} else if (strcasecmp(f, "tos") == 0) {
179 		ip->tos = ars_atou(v);
180 	} else if (strcasecmp(f, "totlen") == 0) {
181 		ip->tot_len = htons(ars_atou(v));
182 		pkt->p_layer[layer].l_flags |= ARS_TAKE_IP_TOTLEN;
183 	} else if (strcasecmp(f, "id") == 0) {
184 		ip->id = htons(ars_atou(v));
185 	} else if (strcasecmp(f, "fragoff") == 0) {
186 		ip->frag_off = ip->frag_off & 0xE000;
187 		ip->frag_off = htons(ars_atou(v) >> 3);
188 	} else if (strcasecmp(f, "mf") == 0) {
189 		if (ars_atou(v) == 0)
190 			ip->frag_off &= htons(~ARS_IP_MF);
191 		else
192 			ip->frag_off |= htons(ARS_IP_MF);
193 	} else if (strcasecmp(f, "df") == 0) {
194 		if (ars_atou(v) == 0)
195 			ip->frag_off &= htons(~ARS_IP_DF);
196 		else
197 			ip->frag_off |= htons(ARS_IP_DF);
198 	} else if (strcasecmp(f, "rf") == 0) {
199 		if (ars_atou(v) == 0)
200 			ip->frag_off &= htons((u_int16_t)~ARS_IP_RF);
201 		else
202 			ip->frag_off |= htons(ARS_IP_RF);
203 	} else if (strcasecmp(f, "ttl") == 0) {
204 		ip->ttl = ars_atou(v);
205 	} else if (strcasecmp(f, "proto") == 0) {
206 		ip->protocol = ars_atou(v);
207 		pkt->p_layer[layer].l_flags |= ARS_TAKE_IP_PROTOCOL;
208 	} else if (strcasecmp(f, "cksum") == 0) {
209 		ip->check = htons(ars_atou(v));
210 		pkt->p_layer[layer].l_flags |= ARS_TAKE_IP_CKSUM;
211 	} else {
212 		ars_set_error(pkt, "Invalid field for IP layer");
213 		return -ARS_INVALID;
214 	}
215 	return -ARS_OK;
216 }
217 
ars_d_set_udp(struct ars_packet * pkt,int layer,char * f,char * v)218 int ars_d_set_udp(struct ars_packet *pkt, int layer, char *f, char *v)
219 {
220 	struct ars_udphdr *udp;
221 
222 	if (layer == ARS_LAST_LAYER)
223 		layer = pkt->p_layer_nr - 1;
224 	if (ars_valid_layer(layer) != -ARS_OK)
225 		return -ARS_INVALID;
226 
227 	udp = pkt->p_layer[layer].l_data;
228 
229 	if (strcasecmp(f, "sport") == 0) {
230 		udp->uh_sport = htons(ars_atou(v));
231 	} else if (strcasecmp(f, "dport") == 0) {
232 		udp->uh_dport = htons(ars_atou(v));
233 	} else if (strcasecmp(f, "len") == 0) {
234 		udp->uh_ulen = htons(ars_atou(v));
235 		pkt->p_layer[layer].l_flags |= ARS_TAKE_UDP_LEN;
236 	} else if (strcasecmp(f, "cksum") == 0) {
237 		udp->uh_sum = htons(ars_atou(v));
238 		pkt->p_layer[layer].l_flags |= ARS_TAKE_UDP_CKSUM;
239 	} else {
240 		ars_set_error(pkt, "Invalid field for UDP layer");
241 		return -ARS_INVALID;
242 	}
243 	return -ARS_OK;
244 }
245 
ars_d_set_tcp(struct ars_packet * pkt,int layer,char * f,char * v)246 int ars_d_set_tcp(struct ars_packet *pkt, int layer, char *f, char *v)
247 {
248 	struct ars_tcphdr *tcp;
249 
250 	if (layer == ARS_LAST_LAYER)
251 		layer = pkt->p_layer_nr - 1;
252 	if (ars_valid_layer(layer) != -ARS_OK)
253 		return -ARS_INVALID;
254 
255 	tcp = pkt->p_layer[layer].l_data;
256 
257 	if (strcasecmp(f, "sport") == 0) {
258 		tcp->th_sport = htons(ars_atou(v));
259 	} else if (strcasecmp(f, "dport") == 0) {
260 		tcp->th_dport = htons(ars_atou(v));
261 	} else if (strcasecmp(f, "seq") == 0) {
262 		tcp->th_seq = htonl(ars_atou(v));
263 	} else if (strcasecmp(f, "ack") == 0) {
264 		tcp->th_ack = htonl(ars_atou(v));
265 	} else if (strcasecmp(f, "x2") == 0) {
266 		tcp->th_x2 = ars_atou(v);
267 	} else if (strcasecmp(f, "off") == 0) {
268 		tcp->th_off = ars_atou(v);
269 		pkt->p_layer[layer].l_flags |= ARS_TAKE_TCP_HDRLEN;
270 	} else if (strcasecmp(f, "flags") == 0) {
271 		tcp->th_flags = 0;
272 		if (strchr(v, 'f') || strchr(v, 'F'))
273 			tcp->th_flags |= ARS_TCP_TH_FIN;
274 		if (strchr(v, 's') || strchr(v, 'S'))
275 			tcp->th_flags |= ARS_TCP_TH_SYN;
276 		if (strchr(v, 'r') || strchr(v, 'R'))
277 			tcp->th_flags |= ARS_TCP_TH_RST;
278 		if (strchr(v, 'p') || strchr(v, 'P'))
279 			tcp->th_flags |= ARS_TCP_TH_PUSH;
280 		if (strchr(v, 'a') || strchr(v, 'A'))
281 			tcp->th_flags |= ARS_TCP_TH_ACK;
282 		if (strchr(v, 'u') || strchr(v, 'U'))
283 			tcp->th_flags |= ARS_TCP_TH_URG;
284 		if (strchr(v, 'x') || strchr(v, 'X'))
285 			tcp->th_flags |= ARS_TCP_TH_X;
286 		if (strchr(v, 'y') || strchr(v, 'Y'))
287 			tcp->th_flags |= ARS_TCP_TH_Y;
288 	} else if (strcasecmp(f, "win") == 0) {
289 		tcp->th_win = htons(ars_atou(v));
290 	} else if (strcasecmp(f, "cksum") == 0) {
291 		tcp->th_sum = htons(ars_atou(v));
292 		pkt->p_layer[layer].l_flags |= ARS_TAKE_TCP_CKSUM;
293 	} else if (strcasecmp(f, "urp") == 0) {
294 		tcp->th_urp = htons(ars_atou(v));
295 	} else {
296 		ars_set_error(pkt, "Invalid field for TCP layer");
297 		return -ARS_INVALID;
298 	}
299 	return -ARS_OK;
300 }
301 
ars_d_set_icmp(struct ars_packet * pkt,int layer,char * f,char * v)302 int ars_d_set_icmp(struct ars_packet *pkt, int layer, char *f, char *v)
303 {
304 	struct ars_icmphdr *icmp;
305 
306 	if (layer == ARS_LAST_LAYER)
307 		layer = pkt->p_layer_nr - 1;
308 	if (ars_valid_layer(layer) != -ARS_OK)
309 		return -ARS_INVALID;
310 
311 	icmp = pkt->p_layer[layer].l_data;
312 
313 	if (strcasecmp(f, "type") == 0) {
314 		icmp->type = ars_atou(v);
315 	} else if (strcasecmp(f, "code") == 0) {
316 		icmp->code = ars_atou(v);
317 	} else if (strcasecmp(f, "cksum") == 0) {
318 		icmp->checksum = htons(ars_atou(v));
319 		pkt->p_layer[layer].l_flags |= ARS_TAKE_ICMP_CKSUM;
320 	} else if (strcasecmp(f, "id") == 0) {
321 		icmp->un.echo.id = htons(ars_atou(v));
322 	} else if (strcasecmp(f, "seq") == 0) {
323 		icmp->un.echo.sequence = htons(ars_atou(v));
324 	} else if (strcasecmp(f, "gw") == 0) {
325 		return ars_resolve(pkt, &icmp->un.gateway, v);
326 	} else {
327 		ars_set_error(pkt, "Invalid field for ICMP layer");
328 		return -ARS_INVALID;
329 	}
330 	return -ARS_OK;
331 }
332 
ars_push_data(struct ars_packet * pkt,int layer,void * data,size_t size)333 int ars_push_data(struct ars_packet *pkt, int layer, void *data, size_t size)
334 {
335 	char *p;
336 	int old_size;
337 
338 	if (layer == ARS_LAST_LAYER)
339 		layer = pkt->p_layer_nr - 1;
340 	if (ars_valid_layer(layer) != -ARS_OK)
341 		return -ARS_INVALID;
342 
343 	old_size = pkt->p_layer[layer].l_size;
344 	p = realloc(pkt->p_layer[layer].l_data, old_size + size);
345 	if (p == NULL)
346 		return -ARS_NOMEM;
347 	memcpy(p+old_size, data, size);
348 	pkt->p_layer[layer].l_data = p;
349 	pkt->p_layer[layer].l_size += size;
350 	return ARS_OK;
351 }
352 
353 #define ARS_DATA_BUF_SIZE 4096
ars_d_set_data(struct ars_packet * pkt,int layer,char * f,char * v)354 int ars_d_set_data(struct ars_packet *pkt, int layer, char *f, char *v)
355 {
356 	if (layer == ARS_LAST_LAYER)
357 		layer = pkt->p_layer_nr - 1;
358 	if (ars_valid_layer(layer) != -ARS_OK)
359 		return -ARS_INVALID;
360 
361 	if (strcasecmp(f, "file") == 0) {
362 		int fd, n_read;
363 		unsigned char buffer[ARS_DATA_BUF_SIZE];
364 
365 		if ((fd = open(v, O_RDONLY)) == -1) {
366 			ars_set_error(pkt, "Can't open the DATA file");
367 			return -ARS_ERROR;
368 		}
369 		if ((n_read = read(fd, buffer, ARS_DATA_BUF_SIZE)) == -1) {
370 			close(fd);
371 			ars_set_error(pkt, "Can't read DATA from file");
372 			return -ARS_ERROR;
373 		}
374 		close(fd);
375 		if (n_read == 0)
376 			return -ARS_OK;
377 		return ars_push_data(pkt, layer, buffer, n_read);
378 	} else if (strcasecmp(f, "str") == 0) {
379 		return ars_push_data(pkt, layer, v, strlen(v));
380 	} else {
381 		ars_set_error(pkt, "Invalid field for DATA layer");
382 		return -ARS_INVALID;
383 	}
384 	return -ARS_OK;
385 }
386 
387 /* A Finite state machine to build the packet using the description */
ars_d_build(struct ars_packet * pkt,char * t)388 int ars_d_build(struct ars_packet *pkt, char *t)
389 {
390 	struct ars_d_keyword_info *k = NULL;
391 	char next[ARS_MAX_TSIZE];
392 	char field[ARS_MAX_TSIZE];
393 	int state = ARS_G_LAYER;
394 	int error;
395 	void *p;
396 
397 	while ((t = ars_d_parser(t, next, ARS_MAX_TSIZE)) != NULL) {
398 		switch(state) {
399 		case ARS_G_LAYER:
400 			k = ars_get_keyword_by_name(next);
401 			if (k == NULL) {
402 				ars_set_error(pkt, "Unknown keyword");
403 				return -ARS_INVALID;
404 			}
405 			__D(printf("Adding a new layer (%s)\n", next);)
406 			p = k->ki_add(pkt, k->ki_opt);
407 			if (p == NULL)
408 				return -ARS_INVALID;
409 			state = ARS_G_OBRACE_OR_PLUS;
410 			break;
411 		case ARS_G_FIELD:
412 			strncpy(field, next, ARS_MAX_TSIZE);
413 			state = ARS_G_EQUAL;
414 			break;
415 		case ARS_G_VALUE:
416 			if (k->ki_set == NULL) {
417 				ars_set_error(pkt, "Field specified for"
418 					"a layer that doesn't support fields");
419 				return -ARS_INVALID;
420 			}
421 			error = k->ki_set(pkt, ARS_LAST_LAYER, field, next);
422 			if (error != -ARS_OK)
423 				return error;
424 			state = ARS_G_COMMA_OR_CBRACE;
425 			break;
426 		case ARS_G_OBRACE_OR_PLUS:
427 			if (next[0] == '{' && next[1] == '\0') {
428 				state = ARS_G_FIELD;
429 				break;
430 			} else if (next[0] == '+' && next[1] == '\0') {
431 				state = ARS_G_LAYER;
432 				break;
433 			} else {
434 				ars_set_error(pkt, "Missing brace or plus");
435 				return -ARS_INVALID;
436 			}
437 			break;
438 		case ARS_G_CBRACE:
439 			if (next[0] != '}' || next[1] != '\0') {
440 				ars_set_error(pkt, "Missing closed brace");
441 				return -ARS_INVALID;
442 			}
443 			state = ARS_G_LEN_OR_PLUS;
444 			break;
445 		case ARS_G_COMMA_OR_CBRACE:
446 			if (next[0] == '}' && next[1] == '\0') {
447 				state = ARS_G_LEN_OR_PLUS;
448 				break;
449 			} else if (next[0] == ',' && next[1] == '\0') {
450 				state = ARS_G_FIELD;
451 				break;
452 			} else {
453 				ars_set_error(pkt, "Missing brace or comma");
454 				return -ARS_INVALID;
455 			}
456 			break;
457 		case ARS_G_LEN_OR_PLUS:
458 			if (next[0] == '+' && next[1] == '\0') {
459 				state = ARS_G_LAYER;
460 				break;
461 			}
462 			error = ars_d_setlayer_size(pkt, ARS_LAST_LAYER, next);
463 			if (error != -ARS_OK)
464 				return error;
465 			state = ARS_G_PLUS;
466 			break;
467 		case ARS_G_PLUS:
468 			if (next[0] != '+' || next[1] != '\0') {
469 				ars_set_error(pkt, "Missing plus");
470 				return -ARS_INVALID;
471 			}
472 			state = ARS_G_LAYER;
473 			break;
474 		case ARS_G_EQUAL:
475 			if (next[0] != '=' || next[1] != '\0') {
476 				ars_set_error(pkt, "Missing equal");
477 				return -ARS_INVALID;
478 			}
479 			state = ARS_G_VALUE;
480 			break;
481 		}
482 	}
483 	if (state != ARS_G_LEN_OR_PLUS && state != ARS_G_PLUS &&
484 	    state != ARS_G_OBRACE_OR_PLUS) {
485 		ars_set_error(pkt, "Packet description truncated");
486 		return -ARS_INVALID;
487 	}
488 	return -ARS_OK;
489 }
490