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>