Annotation of embedaddon/hping2/apd.c, revision 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>