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>