File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / hping2 / apd.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:11:37 2012 UTC (12 years, 3 months ago) by misho
Branches: hping2, MAIN
CVS tags: v2_0_0rc3p7, v2_0_0rc3p5, v2_0_0rc3p4, v2_0_0rc3p0, v2_0_0rc3, HEAD
hping2

    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>