Annotation of embedaddon/hping2/apd.c, revision 1.1.1.1
1.1 misho 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
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:
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:
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:
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:
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:
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:
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:
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
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 */
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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>