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 /* $Id: apd.c,v 1.3 2003/09/07 11:21:18 antirez Exp $ */
9
10 #include <stdio.h>
11 #include <string.h>
12 #include <stdlib.h>
13 #include <sys/types.h>
14 #include <netinet/in.h>
15 #include <sys/stat.h>
16 #include <fcntl.h>
17 #include <unistd.h>
18 #include <ctype.h>
19 #include "ars.h"
20 #include "hstring.h"
21 #include "hex.h"
22
23 /* FIXME: parsing should use dynamic buffers to use less memory.
24 * For now we support MTU up to 3000 */
25 #define ARS_MAX_TSIZE (3000*4)
ars_d_parser(char * t,char * next,size_t size)26 char *ars_d_parser(char *t, char *next, size_t size)
27 {
28 int i = 0;
29
30 if (size == 0 || next == NULL || *t == '\0')
31 return NULL;
32 size--; /* space for nul term */
33 while (1) {
34 /* no space for the next char */
35 if (i == size) {
36 next[i] = '\0';
37 return t;
38 }
39 switch(*t) {
40 case '\0':
41 case '(':
42 case ')':
43 case ',':
44 case '=':
45 case '+':
46 if (i == 0) {
47 next[i] = *t;
48 next[i+1] = '\0';
49 return t+1;
50 } else {
51 next[i] = '\0';
52 return t;
53 }
54 default:
55 next[i++] = *t++;
56 break;
57 }
58 }
59 return NULL; /* unreached */
60 }
61
62 /* states */
63 #define ARS_G_LAYER 0
64 #define ARS_G_FIELD_OR_CBRACE 1
65 #define ARS_G_VALUE 2
66 #define ARS_G_OBRACE_OR_PLUS 3
67 #define ARS_G_CBRACE 4
68 #define ARS_G_COMMA_OR_CBRACE 5
69 #define ARS_G_LEN_OR_PLUS 6
70 #define ARS_G_PLUS 7
71 #define ARS_G_EQUAL 8
72
73 struct ars_d_keyword_info {
74 char *ki_keyword;
75 int ki_opt;
76 void *(*ki_add) (struct ars_packet *pkt, int opt);
77 int (*ki_set) (struct ars_packet *pkt, int layer, char *f, char *v);
78 };
79
80 #define ARS_DKINFO_SIZE 64
81
82 /* If the user specify a layer number of -1 with *set functions, the
83 * last layer is selected */
84 #define ARS_DEF_LAYER \
85 do { \
86 if (layer == ARS_LAST_LAYER) \
87 layer = pkt->p_layer_nr - 1; \
88 if (ars_valid_layer(layer) != -ARS_OK) \
89 return -ARS_INVALID; \
90 } while(0)
91
92 #define BOGUS_SET_F(x) \
93 int (x)(struct ars_packet *pkt, int layer, char *f, char *v) { return 0; }
94
95 int ars_d_set_ip(struct ars_packet *pkt, int layer, char *f, char *v);
96 int ars_d_set_udp(struct ars_packet *pkt, int layer, char *f, char *v);
97 int ars_d_set_tcp(struct ars_packet *pkt, int layer, char *f, char *v);
98 int ars_d_set_icmp(struct ars_packet *pkt, int layer, char *f, char *v);
99 int ars_d_set_data(struct ars_packet *pkt, int layer, char *f, char *v);
100 int ars_d_set_ipopt_rr(struct ars_packet *pkt, int layer, char *f, char *v);
101 int ars_d_set_ipopt_ts(struct ars_packet *pkt, int layer, char *f, char *v);
102 int ars_d_set_ipopt_sid(struct ars_packet *pkt, int layer, char *f, char *v);
103 int ars_d_set_ipopt_sec(struct ars_packet *pkt, int layer, char *f, char *v);
104 int ars_d_set_ipopt_dumb(struct ars_packet *pkt, int layer, char *f, char *v);
105 int ars_d_set_tcpopt_mss(struct ars_packet *pkt, int layer, char *f, char *v);
106 int ars_d_set_tcpopt_wscale(struct ars_packet *pkt, int layer, char *f, char *v);
107 int ars_d_set_tcpopt_sack(struct ars_packet *pkt, int layer, char *f, char *v);
108 int ars_d_set_tcpopt_echo(struct ars_packet *pkt, int layer, char *f, char *v);
109 int ars_d_set_tcpopt_dumb(struct ars_packet *pkt, int layer, char *f, char *v);
110 int ars_d_set_igrp(struct ars_packet *pkt, int layer, char *f, char *v);
111 int ars_d_set_igrpentry(struct ars_packet *pkt, int layer, char *f, char *v);
112 BOGUS_SET_F(ars_d_set_tcpopt_ts)
113
114 struct ars_d_keyword_info ars_dkinfo[ARS_DKINFO_SIZE] = {
115 /* KEYWORD OPT ADD function SET function *
116 * --------------------------------------------------------- */
117 {"ip", 0, ars_add_iphdr, ars_d_set_ip},
118 {"ip.eol", ARS_IPOPT_EOL, ars_add_ipopt, ars_d_set_ipopt_dumb},
119 {"ip.nop", ARS_IPOPT_NOP, ars_add_ipopt, ars_d_set_ipopt_dumb},
120 {"ip.sec", ARS_IPOPT_SEC, ars_add_ipopt, ars_d_set_ipopt_sec},
121 {"ip.sid", ARS_IPOPT_SID, ars_add_ipopt, ars_d_set_ipopt_sid},
122 {"ip.lsrr", ARS_IPOPT_LSRR, ars_add_ipopt, ars_d_set_ipopt_rr},
123 {"ip.ssrr", ARS_IPOPT_SSRR, ars_add_ipopt, ars_d_set_ipopt_rr},
124 {"ip.rr", ARS_IPOPT_RR, ars_add_ipopt, ars_d_set_ipopt_rr},
125 {"ip.ts", ARS_IPOPT_TIMESTAMP, ars_add_ipopt, ars_d_set_ipopt_ts},
126 {"udp", 0, ars_add_udphdr, ars_d_set_udp},
127 {"tcp", 0, ars_add_tcphdr, ars_d_set_tcp},
128 {"tcp.eol", ARS_TCPOPT_EOL, ars_add_tcpopt, ars_d_set_tcpopt_dumb},
129 {"tcp.nop", ARS_TCPOPT_NOP, ars_add_tcpopt, ars_d_set_tcpopt_dumb},
130 {"tcp.mss", ARS_TCPOPT_MAXSEG, ars_add_tcpopt, ars_d_set_tcpopt_mss},
131 {"tcp.wscale", ARS_TCPOPT_WINDOW, ars_add_tcpopt, ars_d_set_tcpopt_wscale},
132 {"tcp.sackperm", ARS_TCPOPT_SACK_PERM, ars_add_tcpopt, ars_d_set_tcpopt_dumb},
133 {"tcp.sack", ARS_TCPOPT_SACK, ars_add_tcpopt, ars_d_set_tcpopt_sack},
134 {"tcp.echo", ARS_TCPOPT_ECHOREQUEST, ars_add_tcpopt, ars_d_set_tcpopt_echo},
135 {"tcp.echoreply", ARS_TCPOPT_ECHOREPLY, ars_add_tcpopt, ars_d_set_tcpopt_echo},
136 {"tcp.ts", ARS_TCPOPT_TIMESTAMP, ars_add_tcpopt, ars_d_set_tcpopt_ts},
137 {"icmp", 0, ars_add_icmphdr, ars_d_set_icmp},
138 {"igrp", 0, ars_add_igrphdr, ars_d_set_igrp},
139 {"igrp.entry", 0, ars_add_igrpentry, ars_d_set_igrpentry},
140 {"data", 0, ars_add_data, ars_d_set_data},
141 {NULL, 0, NULL, NULL} /* nul term */
142 };
143
ars_get_keyword_by_name(char * name)144 struct ars_d_keyword_info *ars_get_keyword_by_name(char *name)
145 {
146 struct ars_d_keyword_info *k = ars_dkinfo;
147
148 while (k->ki_keyword) {
149 if (strcasecmp(k->ki_keyword, name) == 0)
150 return k;
151 k++;
152 }
153 return NULL;
154 }
155
ars_d_setlayer_size(struct ars_packet * pkt,int layer,char * size)156 int ars_d_setlayer_size(struct ars_packet *pkt, int layer, char *size)
157 {
158 size_t newsize;
159
160 ARS_DEF_LAYER;
161 newsize = ars_atou(size);
162 if (newsize < 1 || newsize > pkt->p_layer[layer].l_size) {
163 ars_set_error(pkt, "Invalid layer size in description");
164 return -ARS_INVALID;
165 }
166 pkt->p_layer[layer].l_size = newsize;
167
168 __D(printf("Setting the layer to size %s\n", size);)
169 return -ARS_OK;
170 }
171
ars_d_set_ip(struct ars_packet * pkt,int layer,char * f,char * v)172 int ars_d_set_ip(struct ars_packet *pkt, int layer, char *f, char *v)
173 {
174 struct ars_iphdr *ip;
175
176 ARS_DEF_LAYER;
177 ip = pkt->p_layer[layer].l_data;
178
179 if (strcasecmp(f, "saddr") == 0) {
180 return ars_resolve(pkt, &ip->saddr, v);
181 } else if (strcasecmp(f, "daddr") == 0) {
182 return ars_resolve(pkt, &ip->daddr, v);
183 } else if (strcasecmp(f, "ihl") == 0) {
184 ip->ihl = ars_atou(v);
185 pkt->p_layer[layer].l_flags |= ARS_TAKE_IP_HDRLEN;
186 } else if (strcasecmp(f, "ver") == 0) {
187 ip->version = ars_atou(v);
188 pkt->p_layer[layer].l_flags |= ARS_TAKE_IP_VERSION;
189 } else if (strcasecmp(f, "tos") == 0) {
190 ip->tos = ars_atou(v);
191 } else if (strcasecmp(f, "totlen") == 0) {
192 ip->tot_len = htons(ars_atou(v));
193 pkt->p_layer[layer].l_flags |= ARS_TAKE_IP_TOTLEN;
194 } else if (strcasecmp(f, "id") == 0) {
195 ip->id = htons(ars_atou(v));
196 } else if (strcasecmp(f, "fragoff") == 0) {
197 ip->frag_off = ip->frag_off & 0xE000;
198 ip->frag_off |= htons(ars_atou(v) >> 3);
199 } else if (strcasecmp(f, "mf") == 0) {
200 if (ars_atou(v) == 0)
201 ip->frag_off &= htons(~ARS_IP_MF);
202 else
203 ip->frag_off |= htons(ARS_IP_MF);
204 } else if (strcasecmp(f, "df") == 0) {
205 if (ars_atou(v) == 0)
206 ip->frag_off &= htons(~ARS_IP_DF);
207 else
208 ip->frag_off |= htons(ARS_IP_DF);
209 } else if (strcasecmp(f, "rf") == 0) {
210 if (ars_atou(v) == 0)
211 ip->frag_off &= htons((u_int16_t)~ARS_IP_RF);
212 else
213 ip->frag_off |= htons(ARS_IP_RF);
214 } else if (strcasecmp(f, "ttl") == 0) {
215 ip->ttl = ars_atou(v);
216 } else if (strcasecmp(f, "proto") == 0) {
217 if (!strcasecmp(v, "icmp")) {
218 ip->protocol = ARS_IPPROTO_ICMP;
219 } else if (!strcasecmp(v, "udp")) {
220 ip->protocol = ARS_IPPROTO_UDP;
221 } else if (!strcasecmp(v, "tcp")) {
222 ip->protocol = ARS_IPPROTO_TCP;
223 } else {
224 ip->protocol = ars_atou(v);
225 }
226 pkt->p_layer[layer].l_flags |= ARS_TAKE_IP_PROTOCOL;
227 } else if (strcasecmp(f, "cksum") == 0) {
228 ip->check = htons(ars_atou(v));
229 pkt->p_layer[layer].l_flags |= ARS_TAKE_IP_CKSUM;
230 } else {
231 ars_set_error(pkt, "Invalid field for IP layer: '%s'", f);
232 return -ARS_INVALID;
233 }
234 return -ARS_OK;
235 }
236
237 /* Note: for all the variable-length ip options the allocated layer data
238 * length is always as big as possible (40 bytes), so set_ipopt_rr() and
239 * other similar functions don't need to check if there is enough room.
240 * Of course functions shoult still check to not overflow over the 40
241 * bytes, but this makes very little sense. */
242 #define IPOPTRR_MAX_ENTRIES 9
ars_d_set_ipopt_rr(struct ars_packet * pkt,int layer,char * f,char * v)243 int ars_d_set_ipopt_rr(struct ars_packet *pkt, int layer, char *f, char *v)
244 {
245 struct ars_ipopt *ipopt;
246
247 ARS_DEF_LAYER;
248 ipopt = pkt->p_layer[layer].l_data;
249
250 if (strcasecmp(f, "optlen") == 0) {
251 ipopt->len = ars_atou(v);
252 } else if (strcasecmp(f, "ptr") == 0) {
253 ipopt->un.rr.ptr = ars_atou(v);
254 pkt->p_layer[layer].l_flags |= ARS_TAKE_IPOPT_PTR;
255 } else if (strcasecmp(f, "data") == 0) {
256 char *addrv[IPOPTRR_MAX_ENTRIES];
257 int vlen = strlen(v), num, i;
258 char *vcopy = alloca(vlen+1);
259 unsigned char *data = pkt->p_layer[layer].l_data;
260
261 memcpy(vcopy, v, vlen+1);
262 num = strftok("/", vcopy, addrv, IPOPTRR_MAX_ENTRIES);
263 for (i = 0; i < num; i++) {
264 __u32 addr;
265 int err;
266
267 err = ars_resolve(pkt, &addr, addrv[i]);
268 if (err != -ARS_OK)
269 return err;
270 memcpy(data+3+(i*4), &addr, 4);
271 }
272 if (ARS_DONTTAKE(pkt->p_layer[layer].l_flags,
273 ARS_TAKE_IPOPT_PTR))
274 {
275 /* For the record route option the default ptr
276 * is at the end of the specified entries */
277 if (ipopt->kind == ARS_IPOPT_RR) {
278 ipopt->un.rr.ptr = 4+(num*4);
279 } else {
280 /* For SSRR and LSRR is set at the start
281 * if not otherwise specified. */
282 ipopt->un.rr.ptr = 4;
283 }
284 }
285 } else {
286 ars_set_error(pkt, "Invalid field for IP.RR layer: '%s'", f);
287 return -ARS_INVALID;
288 }
289
290 return -ARS_OK;
291 }
292
293 #define IPOPTTS_MAX_ENTRIES 9
ars_d_set_ipopt_ts(struct ars_packet * pkt,int layer,char * f,char * v)294 int ars_d_set_ipopt_ts(struct ars_packet *pkt, int layer, char *f, char *v)
295 {
296 struct ars_ipopt *ipopt;
297 int flags, overflow;
298
299 ARS_DEF_LAYER;
300 ipopt = pkt->p_layer[layer].l_data;
301 overflow = (ipopt->un.ts.flags & 0xF0) >> 4;
302 flags = ipopt->un.ts.flags & 0xF;
303
304 if (strcasecmp(f, "optlen") == 0) {
305 ipopt->len = ars_atou(v);
306 } else if (strcasecmp(f, "ptr") == 0) {
307 ipopt->un.rr.ptr = ars_atou(v);
308 pkt->p_layer[layer].l_flags |= ARS_TAKE_IPOPT_PTR;
309 } else if (strcasecmp(f, "flags") == 0) {
310 if (strisnum(v)) {
311 flags = ars_atou(v) & 0xF;
312 } else {
313 if (!strcasecmp(v, "tsonly"))
314 flags = ARS_IPOPT_TS_TSONLY;
315 else if (!strcasecmp(v, "tsandaddr"))
316 flags = ARS_IPOPT_TS_TSANDADDR;
317 else if (!strcasecmp(v, "prespec"))
318 flags = ARS_IPOPT_TS_PRESPEC;
319 else {
320 ars_set_error(pkt, "Invalid symbol for ip.ts flags: '%s' (use: tsonly, tsandaddr, prespec or a numerical value)", v);
321 return -ARS_INVALID;
322 }
323 }
324 ipopt->un.ts.flags = ((overflow&0xF)<<4)|(flags&0xF);
325 } else if (strcasecmp(f, "overflow") == 0) {
326 overflow = ars_atou(v) & 0xF;
327 ipopt->un.ts.flags = ((overflow&0xF)<<4)|(flags&0xF);
328 } else if (strcasecmp(f, "data") == 0) {
329 char *addrv[IPOPTTS_MAX_ENTRIES];
330 int vlen = strlen(v), num, i;
331 char *vcopy = alloca(vlen+1);
332 unsigned char *data = pkt->p_layer[layer].l_data;
333
334 memcpy(vcopy, v, vlen+1);
335 num = strftok("/", vcopy, addrv, IPOPTTS_MAX_ENTRIES);
336 for (i = 0; i < num; i++) {
337 __u32 addr, ts;
338 int err;
339 char *p;
340
341 p = strchr(addrv[i], '@');
342 if (p) {
343 if (flags == ARS_IPOPT_TS_TSONLY) {
344 ars_set_error(pkt, "Gateway specified but ip.ts flags set to 'tsonly'. (Try flags=tsandaddr,data=...)");
345 return -ARS_INVALID;
346 }
347 *p = '\0';
348 p++;
349 err = ars_resolve(pkt, &addr, p);
350 if (err != -ARS_OK)
351 return err;
352 ts = ars_atou(addrv[i]);
353 ts = htonl(ts);
354 if (i < 4) {
355 memcpy(data+4+(i*8), &addr, 4);
356 memcpy(data+8+(i*8), &ts, 4);
357 };
358 } else {
359 if (flags == ARS_IPOPT_TS_TSANDADDR ||
360 flags == ARS_IPOPT_TS_PRESPEC) {
361 ars_set_error(pkt, "Gateway not specified in data for ip.ts, but flags set to 'tsandaddr' or 'prespec'. (Try flags=tsonly)");
362 return -ARS_INVALID;
363 }
364 ts = ars_atou(addrv[i]);
365 ts = htonl(ts);
366 memcpy(data+4+(i*4), &ts, 4);
367 }
368 }
369 if (ARS_DONTTAKE(pkt->p_layer[layer].l_flags,
370 ARS_TAKE_IPOPT_PTR))
371 {
372 if (flags == ARS_IPOPT_TS_TSANDADDR ||
373 flags == ARS_IPOPT_TS_PRESPEC) {
374 ipopt->un.rr.ptr = 5+(num*8);
375 } else {
376 ipopt->un.rr.ptr = 5+(num*4);
377 }
378 }
379 } else {
380 ars_set_error(pkt, "Invalid field for IP.TS layer: '%s'", f);
381 return -ARS_INVALID;
382 }
383
384 return -ARS_OK;
385 }
386
ars_d_set_ipopt_sid(struct ars_packet * pkt,int layer,char * f,char * v)387 int ars_d_set_ipopt_sid(struct ars_packet *pkt, int layer, char *f, char *v)
388 {
389 struct ars_ipopt *ipopt;
390
391 ARS_DEF_LAYER;
392 ipopt = pkt->p_layer[layer].l_data;
393 if (strcasecmp(f, "optlen") == 0) {
394 ipopt->len = ars_atou(v);
395 } else if (strcasecmp(f, "sid") == 0) {
396 ipopt->un.sid.id = ars_atou(v);
397 } else {
398 ars_set_error(pkt, "Invalid field for IP.SID layer: '%s'", f);
399 return -ARS_INVALID;
400 }
401 return -ARS_OK;
402 }
403
ars_d_set_ipopt_sec(struct ars_packet * pkt,int layer,char * f,char * v)404 int ars_d_set_ipopt_sec(struct ars_packet *pkt, int layer, char *f, char *v)
405 {
406 struct ars_ipopt *ipopt;
407
408 ARS_DEF_LAYER;
409 ipopt = pkt->p_layer[layer].l_data;
410 if (strcasecmp(f, "optlen") == 0) {
411 ipopt->len = ars_atou(v);
412 } else if (strcasecmp(f, "seclev") == 0) {
413 ipopt->un.sec.s = ars_atou(v);
414 } else if (strcasecmp(f, "comp") == 0) {
415 ipopt->un.sec.c = ars_atou(v);
416 } else if (strcasecmp(f, "hrest") == 0) {
417 if (strlen(v) != 4) {
418 ars_set_error(pkt, "Invalid ip.sec hrest field value of '%s'(should be four hex digits, like this: ...,hrest=252A,...)", v);
419 return -ARS_INVALID;
420 }
421 if (hextobin(&ipopt->un.sec.h, v, 4)) {
422 ars_set_error(pkt, "Invalid hex value for ip.sec hex: '%s'", v);
423 return -ARS_INVALID;
424 }
425 } else if (strcasecmp(f, "tcc") == 0) {
426 if (strlen(v) != 6) {
427 ars_set_error(pkt, "Invalid ip.sec tcc field value of '%s'(should be six hex digits, like this: ...,tcc=252A27,...)", v);
428 return -ARS_INVALID;
429 }
430 if (hextobin(&ipopt->un.sec.h, v, 6)) {
431 ars_set_error(pkt, "Invalid hex value for ip.sec hex: '%s'", v);
432 return -ARS_INVALID;
433 }
434 } else {
435 ars_set_error(pkt, "Invalid field for IP.SEC layer: '%s'", f);
436 return -ARS_INVALID;
437 }
438
439 return -ARS_OK;
440 }
441
ars_d_set_ipopt_dumb(struct ars_packet * pkt,int layer,char * f,char * v)442 int ars_d_set_ipopt_dumb(struct ars_packet *pkt, int layer, char *f, char *v)
443 {
444 struct ars_ipopt *ipopt;
445
446 ARS_DEF_LAYER;
447 ipopt = pkt->p_layer[layer].l_data;
448 if (strcasecmp(f, "optlen") == 0) {
449 ipopt->len = ars_atou(v);
450 } else {
451 ars_set_error(pkt, "Invalid field for IP.? layer: '%s'", f);
452 return -ARS_INVALID;
453 }
454 return -ARS_OK;
455 }
456
ars_d_set_udp(struct ars_packet * pkt,int layer,char * f,char * v)457 int ars_d_set_udp(struct ars_packet *pkt, int layer, char *f, char *v)
458 {
459 struct ars_udphdr *udp;
460
461 ARS_DEF_LAYER;
462 udp = pkt->p_layer[layer].l_data;
463
464 if (strcasecmp(f, "sport") == 0) {
465 udp->uh_sport = htons(ars_atou(v));
466 } else if (strcasecmp(f, "dport") == 0) {
467 udp->uh_dport = htons(ars_atou(v));
468 } else if (strcasecmp(f, "len") == 0) {
469 udp->uh_ulen = htons(ars_atou(v));
470 pkt->p_layer[layer].l_flags |= ARS_TAKE_UDP_LEN;
471 } else if (strcasecmp(f, "cksum") == 0) {
472 udp->uh_sum = htons(ars_atou(v));
473 pkt->p_layer[layer].l_flags |= ARS_TAKE_UDP_CKSUM;
474 } else {
475 ars_set_error(pkt, "Invalid field for UDP layer: '%s'", f);
476 return -ARS_INVALID;
477 }
478 return -ARS_OK;
479 }
480
ars_d_set_tcp(struct ars_packet * pkt,int layer,char * f,char * v)481 int ars_d_set_tcp(struct ars_packet *pkt, int layer, char *f, char *v)
482 {
483 struct ars_tcphdr *tcp;
484
485 ARS_DEF_LAYER;
486 tcp = pkt->p_layer[layer].l_data;
487
488 if (strcasecmp(f, "sport") == 0) {
489 tcp->th_sport = htons(ars_atou(v));
490 } else if (strcasecmp(f, "dport") == 0) {
491 tcp->th_dport = htons(ars_atou(v));
492 } else if (strcasecmp(f, "seq") == 0) {
493 tcp->th_seq = htonl(ars_atou(v));
494 } else if (strcasecmp(f, "ack") == 0) {
495 tcp->th_ack = htonl(ars_atou(v));
496 } else if (strcasecmp(f, "x2") == 0) {
497 tcp->th_x2 = ars_atou(v);
498 } else if (strcasecmp(f, "off") == 0) {
499 tcp->th_off = ars_atou(v);
500 pkt->p_layer[layer].l_flags |= ARS_TAKE_TCP_HDRLEN;
501 } else if (strcasecmp(f, "flags") == 0) {
502 tcp->th_flags = 0;
503 if (strchr(v, 'f') || strchr(v, 'F'))
504 tcp->th_flags |= ARS_TCP_TH_FIN;
505 if (strchr(v, 's') || strchr(v, 'S'))
506 tcp->th_flags |= ARS_TCP_TH_SYN;
507 if (strchr(v, 'r') || strchr(v, 'R'))
508 tcp->th_flags |= ARS_TCP_TH_RST;
509 if (strchr(v, 'p') || strchr(v, 'P'))
510 tcp->th_flags |= ARS_TCP_TH_PUSH;
511 if (strchr(v, 'a') || strchr(v, 'A'))
512 tcp->th_flags |= ARS_TCP_TH_ACK;
513 if (strchr(v, 'u') || strchr(v, 'U'))
514 tcp->th_flags |= ARS_TCP_TH_URG;
515 if (strchr(v, 'x') || strchr(v, 'X'))
516 tcp->th_flags |= ARS_TCP_TH_X;
517 if (strchr(v, 'y') || strchr(v, 'Y'))
518 tcp->th_flags |= ARS_TCP_TH_Y;
519 } else if (strcasecmp(f, "win") == 0) {
520 tcp->th_win = htons(ars_atou(v));
521 } else if (strcasecmp(f, "cksum") == 0) {
522 tcp->th_sum = htons(ars_atou(v));
523 pkt->p_layer[layer].l_flags |= ARS_TAKE_TCP_CKSUM;
524 } else if (strcasecmp(f, "urp") == 0) {
525 tcp->th_urp = htons(ars_atou(v));
526 } else {
527 ars_set_error(pkt, "Invalid field for TCP layer: '%s'", f);
528 return -ARS_INVALID;
529 }
530 return -ARS_OK;
531 }
532
ars_d_set_tcpopt_mss(struct ars_packet * pkt,int layer,char * f,char * v)533 int ars_d_set_tcpopt_mss(struct ars_packet *pkt, int layer, char *f, char *v)
534 {
535 struct ars_tcpopt *tcpopt;
536
537 ARS_DEF_LAYER;
538 tcpopt = pkt->p_layer[layer].l_data;
539 if (strcasecmp(f, "optlen") == 0) {
540 tcpopt->len = ars_atou(v);
541 } else if (strcasecmp(f, "size") == 0) {
542 tcpopt->un.mss.size = htons(ars_atou(v));
543 } else {
544 ars_set_error(pkt, "Invalid field for TCP.MSS layer: '%s'", f);
545 return -ARS_INVALID;
546 }
547 return -ARS_OK;
548 }
549
ars_d_set_tcpopt_wscale(struct ars_packet * pkt,int layer,char * f,char * v)550 int ars_d_set_tcpopt_wscale(struct ars_packet *pkt, int layer, char *f, char *v)
551 {
552 struct ars_tcpopt *tcpopt;
553
554 ARS_DEF_LAYER;
555 tcpopt = pkt->p_layer[layer].l_data;
556 if (strcasecmp(f, "optlen") == 0) {
557 tcpopt->len = ars_atou(v);
558 } else if (strcasecmp(f, "shift") == 0) {
559 tcpopt->un.win.shift = htons(ars_atou(v));
560 } else {
561 ars_set_error(pkt, "Invalid field for TCP.WSCALE layer: '%s'", f);
562 return -ARS_INVALID;
563 }
564 return -ARS_OK;
565 }
566
567 #define TCPOPTSACK_MAX_ENTRIES 4
ars_d_set_tcpopt_sack(struct ars_packet * pkt,int layer,char * f,char * v)568 int ars_d_set_tcpopt_sack(struct ars_packet *pkt, int layer, char *f, char *v)
569 {
570 struct ars_tcpopt *tcpopt;
571
572 ARS_DEF_LAYER;
573 tcpopt = pkt->p_layer[layer].l_data;
574 if (strcasecmp(f, "optlen") == 0) {
575 tcpopt->len = ars_atou(v);
576 } else if (strcasecmp(f, "blocks") == 0) {
577 char *bv[TCPOPTSACK_MAX_ENTRIES];
578 int vlen = strlen(v), num, i;
579 char *vcopy = alloca(vlen+1);
580 unsigned char *data = pkt->p_layer[layer].l_data;
581
582 memcpy(vcopy, v, vlen+1);
583 num = strftok("/", vcopy, bv, TCPOPTSACK_MAX_ENTRIES);
584 for (i = 0; i < num; i++) {
585 char *p;
586 __u32 s_origin, s_len;
587
588 p = strchr(bv[i], '-');
589 if (!p) {
590 ars_set_error(pkt, "Invalid syntax for tcp.sack blocks: '%s' (try ...tcp.sack(blocks=123342-10/12653-50/0-0/0-0)... )");
591 return -ARS_INVALID;
592 }
593 *p = '\0';
594 p++;
595 s_origin = htonl(ars_atou(bv[i]));
596 s_len = htonl(ars_atou(p));
597 memcpy(data+2+(i*8), &s_origin, 4);
598 memcpy(data+6+(i*8), &s_len, 4);
599 }
600 } else {
601 ars_set_error(pkt, "Invalid field for TCP.SACK layer: '%s'", f);
602 return -ARS_INVALID;
603 }
604 return -ARS_OK;
605 }
606
ars_d_set_tcpopt_dumb(struct ars_packet * pkt,int layer,char * f,char * v)607 int ars_d_set_tcpopt_dumb(struct ars_packet *pkt, int layer, char *f, char *v)
608 {
609 struct ars_tcpopt *tcpopt;
610
611 ARS_DEF_LAYER;
612 tcpopt = pkt->p_layer[layer].l_data;
613 if (strcasecmp(f, "optlen") == 0) {
614 tcpopt->len = ars_atou(v);
615 } else {
616 ars_set_error(pkt, "Invalid field for TCP.? layer: '%s'", f);
617 return -ARS_INVALID;
618 }
619 return -ARS_OK;
620 }
621
ars_d_set_tcpopt_echo(struct ars_packet * pkt,int layer,char * f,char * v)622 int ars_d_set_tcpopt_echo(struct ars_packet *pkt, int layer, char *f, char *v)
623 {
624 struct ars_tcpopt *tcpopt;
625
626 ARS_DEF_LAYER;
627 tcpopt = pkt->p_layer[layer].l_data;
628 if (strcasecmp(f, "optlen") == 0) {
629 tcpopt->len = ars_atou(v);
630 } else if (strcasecmp(f, "info") == 0) {
631 u_int32_t info = htonl(ars_atou(v));
632 memcpy(tcpopt->un.echo.info, &info, 4);
633 } else {
634 ars_set_error(pkt, "Invalid field for TCP.ECHO layer: '%s'", f);
635 return -ARS_INVALID;
636 }
637 return -ARS_OK;
638 }
639
ars_d_set_icmp(struct ars_packet * pkt,int layer,char * f,char * v)640 int ars_d_set_icmp(struct ars_packet *pkt, int layer, char *f, char *v)
641 {
642 struct ars_icmphdr *icmp;
643
644 ARS_DEF_LAYER;
645 icmp = pkt->p_layer[layer].l_data;
646
647 if (strcasecmp(f, "type") == 0) {
648 icmp->type = ars_atou(v);
649 } else if (strcasecmp(f, "code") == 0) {
650 icmp->code = ars_atou(v);
651 } else if (strcasecmp(f, "cksum") == 0) {
652 icmp->checksum = htons(ars_atou(v));
653 pkt->p_layer[layer].l_flags |= ARS_TAKE_ICMP_CKSUM;
654 } else if (strcasecmp(f, "id") == 0) {
655 icmp->un.echo.id = htons(ars_atou(v));
656 } else if (strcasecmp(f, "seq") == 0) {
657 icmp->un.echo.sequence = htons(ars_atou(v));
658 } else if (strcasecmp(f, "gw") == 0) {
659 return ars_resolve(pkt, &icmp->un.gateway, v);
660 } else if (strcasecmp(f, "unused") == 0) {
661 icmp->un.gateway = htonl(ars_atou(v));
662 } else {
663 ars_set_error(pkt, "Invalid field for ICMP layer: '%s'", f);
664 return -ARS_INVALID;
665 }
666 return -ARS_OK;
667 }
668
ars_d_set_igrp(struct ars_packet * pkt,int layer,char * f,char * v)669 int ars_d_set_igrp(struct ars_packet *pkt, int layer, char *f, char *v)
670 {
671 struct ars_igrphdr *igrp;
672
673 ARS_DEF_LAYER;
674 igrp = pkt->p_layer[layer].l_data;
675
676 if (strcasecmp(f, "version") == 0) {
677 igrp->version = ars_atou(v);
678 } else if (strcasecmp(f, "opcode") == 0) {
679 if (strcasecmp(v, "update") == 0)
680 igrp->opcode = ARS_IGRP_OPCODE_UPDATE;
681 else if (strcasecmp(v, "request") == 0)
682 igrp->opcode = ARS_IGRP_OPCODE_REQUEST;
683 else
684 igrp->opcode = ars_atou(v);
685 } else if (strcasecmp(f, "cksum") == 0) {
686 igrp->checksum = htons(ars_atou(v));
687 pkt->p_layer[layer].l_flags |= ARS_TAKE_IGRP_CKSUM;
688 } else if (strcasecmp(f, "edition") == 0) {
689 igrp->edition = ars_atou(v);
690 } else if (strcasecmp(f, "autosys") == 0) {
691 igrp->autosys = htons(ars_atou(v));
692 } else if (strcasecmp(f, "interior") == 0) {
693 igrp->interior = htons(ars_atou(v));
694 } else if (strcasecmp(f, "system") == 0) {
695 igrp->system= htons(ars_atou(v));
696 } else if (strcasecmp(f, "exterior") == 0) {
697 igrp->exterior = htons(ars_atou(v));
698 } else {
699 ars_set_error(pkt, "Invalid field for IGRP layer: '%s'", f);
700 return -ARS_INVALID;
701 }
702 return -ARS_OK;
703 }
704
igrp_set_dest(unsigned char * d,char * v)705 static int igrp_set_dest(unsigned char *d, char *v)
706 {
707 int l = strlen(v);
708 char *vcopy = alloca(l+1);
709 char *f0, *f1, *f2;
710
711 memcpy(vcopy, v, l+1);
712 f0 = vcopy;
713 if ((f1 = strchr(f0, '.')) == NULL)
714 return 1;
715 *f1++ = '\0';
716 if ((f2 = strchr(f1, '.')) == NULL)
717 return 1;
718 *f2++ = '\0';
719 if (!strisnum(f0) || !strisnum(f1) || !strisnum(f2))
720 return 1;
721 d[0] = ars_atou(f0);
722 d[1] = ars_atou(f1);
723 d[2] = ars_atou(f2);
724 return 0;
725 }
726
igrp_set_uint24(void * d,char * v)727 static void igrp_set_uint24(void *d, char *v)
728 {
729 __u32 t;
730 unsigned char *x;
731
732 t = htonl(ars_atou(v));
733 x = (unsigned char*) &t;
734 memcpy(d, x+1, 3);
735 }
736
ars_d_set_igrpentry(struct ars_packet * pkt,int layer,char * f,char * v)737 int ars_d_set_igrpentry(struct ars_packet *pkt, int layer, char *f, char *v)
738 {
739 struct ars_igrpentry *entry;
740
741 ARS_DEF_LAYER;
742 entry = pkt->p_layer[layer].l_data;
743
744 if (strcasecmp(f, "dest") == 0) {
745 if (igrp_set_dest(entry->destination, v)) {
746 ars_set_error(pkt, "Invalid IGRP entry 'dest' field value: '%s'\n", v);
747 return -ARS_INVALID;
748 }
749 } else if (strcasecmp(f, "delay") == 0) {
750 igrp_set_uint24(entry->delay, v);
751 } else if (strcasecmp(f, "bandwidth") == 0) {
752 igrp_set_uint24(entry->bandwidth, v);
753 } else if (strcasecmp(f, "mtu") == 0) {
754 __u16 mtu = htons(ars_atou(v));
755 memcpy(entry->mtu, &mtu, 2);
756 } else if (strcasecmp(f, "reliability") == 0) {
757 entry->reliability = ars_atou(v);
758 } else if (strcasecmp(f, "load") == 0) {
759 entry->load = ars_atou(v);
760 } else if (strcasecmp(f, "hopcount") == 0) {
761 entry->hopcount = ars_atou(v);
762 } else {
763 ars_set_error(pkt, "Invalid field for IGRP.ENTRY layer: '%s'", f);
764 return -ARS_INVALID;
765 }
766 return -ARS_OK;
767 }
768
ars_push_data(struct ars_packet * pkt,int layer,void * data,size_t size)769 int ars_push_data(struct ars_packet *pkt, int layer, void *data, size_t size)
770 {
771 char *p;
772 int old_size;
773
774 ARS_DEF_LAYER;
775 old_size = pkt->p_layer[layer].l_size;
776 p = realloc(pkt->p_layer[layer].l_data, old_size + size);
777 if (p == NULL)
778 return -ARS_NOMEM;
779 memcpy(p+old_size, data, size);
780 pkt->p_layer[layer].l_data = p;
781 pkt->p_layer[layer].l_size += size;
782 return ARS_OK;
783 }
784
785 static int hextab[256];
786 static int hextab_initialized = 0;
787 static char *hexdig = "0123456789abcdef";
788
ars_decode_hex(struct ars_packet * pkt,char * s,int * blen)789 static char *ars_decode_hex(struct ars_packet *pkt, char *s, int *blen)
790 {
791 int len = strlen(s), i;
792 unsigned char *d, *saved;
793
794 if (len%2) {
795 ars_set_error(pkt, "Odd length of 'hex' data");
796 return NULL;
797 }
798 *blen = len/2;
799 if (!hextab_initialized) {
800 memset(hextab, 255, 255);
801 for (i = 0; i < 16; i++)
802 hextab[(int)hexdig[i]] = i;
803 }
804 if ((d = malloc(*blen)) == NULL) {
805 ars_set_error(pkt, "Out of memory decoding 'hex' data");
806 return NULL;
807 }
808 saved = d;
809 while(*s) {
810 int x0, x1;
811
812 x0 = hextab[tolower(*s)];
813 x1 = hextab[tolower(*(s+1))];
814 if (x0 == 255 || x1 == 255) {
815 ars_set_error(pkt, "Wrong byte for 'hex' data: '%c%c'",
816 *s, *(s+1));
817 free(saved);
818 return NULL;
819 }
820 *d++ = (x0 << 4) | x1;
821 s += 2;
822 }
823 return saved;
824 }
825
ars_decode_string(struct ars_packet * pkt,char * s,int * blen)826 static char *ars_decode_string(struct ars_packet *pkt, char *s, int *blen)
827 {
828 int l = strlen(s), i;
829 int bl = 0;
830 unsigned char *d, *saved;
831
832 if (!hextab_initialized) {
833 memset(hextab, -1, 255);
834 for (i = 0; i < 16; i++)
835 hextab[(int)hexdig[i]] = i;
836 }
837 if ((d = malloc(l)) == NULL) {
838 ars_set_error(pkt, "Out of memory decoding 'str' data");
839 return NULL;
840 }
841 saved = d;
842 while(*s) {
843 if (*s == '\\' && *(s+1) && *(s+2)) {
844 *d++ = (hextab[(int)*(s+1)] << 4) + hextab[(int)*(s+2)];
845 s += 3;
846 } else {
847 *d++ = *s++;
848 }
849 bl++;
850 }
851 *blen = bl;
852 return saved;
853 }
854
855 #define ARS_DATA_BUF_SIZE 4096
ars_d_set_data(struct ars_packet * pkt,int layer,char * f,char * v)856 int ars_d_set_data(struct ars_packet *pkt, int layer, char *f, char *v)
857 {
858 ARS_DEF_LAYER;
859 if (strcasecmp(f, "file") == 0) {
860 int fd, n_read;
861 unsigned char buffer[ARS_DATA_BUF_SIZE];
862
863 if ((fd = open(v, O_RDONLY)) == -1) {
864 ars_set_error(pkt, "Can't open the DATA file '%s': %s",
865 v, strerror(errno));
866 return -ARS_ERROR;
867 }
868 if ((n_read = read(fd, buffer, ARS_DATA_BUF_SIZE)) == -1) {
869 close(fd);
870 ars_set_error(pkt, "Can't read DATA from file: %s", strerror(errno));
871 return -ARS_ERROR;
872 }
873 close(fd);
874 if (n_read == 0)
875 return -ARS_OK;
876 return ars_push_data(pkt, layer, buffer, n_read);
877 } else if (strcasecmp(f, "str") == 0) {
878 char *binary;
879 int err, blen;
880
881 binary = ars_decode_string(pkt, v, &blen);
882 if (binary == NULL)
883 return -ARS_ERROR;
884 err = ars_push_data(pkt, layer, binary, blen);
885 free(binary);
886 return err;
887 } else if (strcasecmp(f, "hex") == 0) {
888 char *binary;
889 int err, blen;
890
891 binary = ars_decode_hex(pkt, v, &blen);
892 if (binary == NULL)
893 return -ARS_ERROR;
894 err = ars_push_data(pkt, layer, binary, blen);
895 free(binary);
896 } else if (strcasecmp(f, "uint32") == 0) {
897 int err;
898 __u32 t, nt;
899 t = ars_atou(v);
900 nt = htonl(t);
901 err = ars_push_data(pkt, layer, (char*)&nt, 4);
902 return err;
903 } else if (strcasecmp(f, "uint24") == 0) {
904 int err;
905 __u32 t, nt;
906 unsigned char *x = (unsigned char*) &nt;
907 t = ars_atou(v);
908 nt = htonl(t);
909 err = ars_push_data(pkt, layer, x+1, 3);
910 return err;
911 } else if (strcasecmp(f, "uint16") == 0) {
912 int err;
913 __u16 t, nt;
914 t = ars_atou(v);
915 nt = htons(t);
916 err = ars_push_data(pkt, layer, (char*)&nt, 2);
917 return err;
918 } else if (strcasecmp(f, "uint8") == 0) {
919 int err;
920 __u8 t;
921 t = ars_atou(v);
922 err = ars_push_data(pkt, layer, (char*)&t, 1);
923 return err;
924 } else {
925 ars_set_error(pkt, "Invalid field for DATA layer: '%s'", f);
926 return -ARS_INVALID;
927 }
928 return -ARS_OK;
929 }
930
931 /* A Finite state machine to build the packet using the description */
ars_d_build(struct ars_packet * pkt,char * t)932 int ars_d_build(struct ars_packet *pkt, char *t)
933 {
934 struct ars_d_keyword_info *k = NULL;
935 char next[ARS_MAX_TSIZE];
936 char field[ARS_MAX_TSIZE];
937 int state = ARS_G_LAYER;
938 int error;
939 void *p;
940
941 while ((t = ars_d_parser(t, next, ARS_MAX_TSIZE)) != NULL) {
942 switch(state) {
943 case ARS_G_LAYER:
944 k = ars_get_keyword_by_name(next);
945 if (k == NULL) {
946 ars_set_error(pkt, "Unknown keyword: '%s'", next);
947 return -ARS_INVALID;
948 }
949 __D(printf("Adding a new layer (%s)\n", next);)
950 p = k->ki_add(pkt, k->ki_opt);
951 if (p == NULL)
952 return -ARS_INVALID;
953 state = ARS_G_OBRACE_OR_PLUS;
954 break;
955 case ARS_G_FIELD_OR_CBRACE:
956 if (next[0] == ')' && next[1] == '\0') {
957 state = ARS_G_LEN_OR_PLUS;
958 } else {
959 strncpy(field, next, ARS_MAX_TSIZE);
960 state = ARS_G_EQUAL;
961 }
962 break;
963 case ARS_G_VALUE:
964 if (k->ki_set == NULL) {
965 ars_set_error(pkt, "Field specified for"
966 "a layer that doesn't support fields");
967 return -ARS_INVALID;
968 }
969 error = k->ki_set(pkt, ARS_LAST_LAYER, field, next);
970 if (error != -ARS_OK)
971 return error;
972 state = ARS_G_COMMA_OR_CBRACE;
973 break;
974 case ARS_G_OBRACE_OR_PLUS:
975 if (next[0] == '(' && next[1] == '\0') {
976 state = ARS_G_FIELD_OR_CBRACE;
977 break;
978 } else if (next[0] == '+' && next[1] == '\0') {
979 state = ARS_G_LAYER;
980 break;
981 } else {
982 ars_set_error(pkt, "Missing brace or plus");
983 return -ARS_INVALID;
984 }
985 break;
986 case ARS_G_CBRACE:
987 if (next[0] != ')' || next[1] != '\0') {
988 ars_set_error(pkt, "Missing closed brace");
989 return -ARS_INVALID;
990 }
991 state = ARS_G_LEN_OR_PLUS;
992 break;
993 case ARS_G_COMMA_OR_CBRACE:
994 if (next[0] == ')' && next[1] == '\0') {
995 state = ARS_G_LEN_OR_PLUS;
996 break;
997 } else if (next[0] == ',' && next[1] == '\0') {
998 state = ARS_G_FIELD_OR_CBRACE;
999 break;
1000 } else {
1001 ars_set_error(pkt, "Missing brace or comma");
1002 return -ARS_INVALID;
1003 }
1004 break;
1005 case ARS_G_LEN_OR_PLUS:
1006 if (next[0] == '+' && next[1] == '\0') {
1007 state = ARS_G_LAYER;
1008 break;
1009 }
1010 error = ars_d_setlayer_size(pkt, ARS_LAST_LAYER, next);
1011 if (error != -ARS_OK)
1012 return error;
1013 state = ARS_G_PLUS;
1014 break;
1015 case ARS_G_PLUS:
1016 if (next[0] != '+' || next[1] != '\0') {
1017 ars_set_error(pkt, "Missing plus");
1018 return -ARS_INVALID;
1019 }
1020 state = ARS_G_LAYER;
1021 break;
1022 case ARS_G_EQUAL:
1023 if (next[0] != '=' || next[1] != '\0') {
1024 ars_set_error(pkt, "Missing equal");
1025 return -ARS_INVALID;
1026 }
1027 state = ARS_G_VALUE;
1028 break;
1029 }
1030 }
1031 if (state != ARS_G_LEN_OR_PLUS && state != ARS_G_PLUS &&
1032 state != ARS_G_OBRACE_OR_PLUS) {
1033 ars_set_error(pkt, "Packet description truncated");
1034 return -ARS_INVALID;
1035 }
1036 return -ARS_OK;
1037 }
1038