Annotation of embedaddon/hping2/ars.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:  * TODO:
                      5:  * o Functions to add addresses and timestamps for some IP and TCP option
                      6:  * o IGMP support
                      7:  * o DNS support
                      8:  * o ARS add_build_layer() facility and Co., read the PROPOSAL file.
                      9:  */
                     10: 
                     11: /* $Id: ars.c,v 1.4 2003/07/28 09:00:54 njombart Exp $ */
                     12: 
                     13: #include <stdio.h>
                     14: #include <stdlib.h>
                     15: #include <assert.h>
                     16: #include <string.h>
                     17: #include <sys/types.h>
                     18: #include <netinet/in.h>
                     19: #include <arpa/inet.h>
                     20: #include <netdb.h>
                     21: #include <unistd.h>
                     22: #include "ars.h"
                     23: 
                     24: /* prototypes */
                     25: int ars_compiler_ip(struct ars_packet *pkt, int layer);
                     26: int ars_compiler_ipopt(struct ars_packet *pkt, int layer);
                     27: int ars_compiler_tcp(struct ars_packet *pkt, int layer);
                     28: int ars_compiler_tcpopt(struct ars_packet *pkt, int layer);
                     29: int ars_compiler_udp(struct ars_packet *pkt, int layer);
                     30: int ars_compiler_icmp(struct ars_packet *pkt, int layer);
                     31: int ars_compiler_abort(struct ars_packet *pkt, int layer) { return 0; }
                     32: 
                     33: /* Initialize a packets context:
                     34:  * must be called before to work with the packet's layers */
                     35: int ars_init(struct ars_packet *pkt)
                     36: {
                     37:        int j;
                     38: 
                     39:        pkt->p_error = NULL;
                     40:        pkt->p_layer_nr = 0;
                     41:        for (j = 0; j < ARS_MAX_LAYER; j++) {
                     42:                pkt->p_layer[j].l_size = 0;
                     43:                pkt->p_layer[j].l_flags = 0;
                     44:                pkt->p_layer[j].l_type = ARS_TYPE_NULL;
                     45:                pkt->p_layer[j].l_data = NULL;
                     46:                pkt->p_layer[j].l_packet = pkt;
                     47:        }
                     48:        for (j = 0; j < ARS_TYPE_SIZE; j++)
                     49:                pkt->p_default[j] = NULL;
                     50:        return -ARS_OK;
                     51: }
                     52: 
                     53: /* Destroy (free the allocated memory) a packet context */
                     54: int ars_destroy(struct ars_packet *pkt)
                     55: {
                     56:        int j;
                     57: 
                     58:        free(pkt->p_error);
                     59:        for (j = 0; j < ARS_MAX_LAYER; j++) {
                     60:                if (pkt->p_layer[j].l_type != ARS_TYPE_NULL &&
                     61:                    pkt->p_layer[j].l_data != NULL)
                     62:                        free(pkt->p_layer[j].l_data);
                     63:        }
                     64:        return ars_init(pkt); /* Re-initialize it */
                     65: }
                     66: 
                     67: /* THe out of memory message must be statically allocated */
                     68: char *ars_error_nomem = "Out of memory";
                     69: 
                     70: /* Set the error description */
                     71: int ars_set_error(struct ars_packet *pkt, char *error)
                     72: {
                     73:        if (pkt == NULL)
                     74:                return -ARS_OK;
                     75: 
                     76:        free(pkt->p_error); /* p_error is initialized to NULL */
                     77:        if ((pkt->p_error = strdup(error)) == NULL) {
                     78:                /* To put the error description for the -KO_NOMEM
                     79:                 * error we needs a statically allocated error message:
                     80:                 * Note that all other functions don't need to report
                     81:                 * a statically allocated error message for -KO_NOMEM
                     82:                 * it will be auto-selected if strdup() returns NULL */
                     83:                pkt->p_error = ars_error_nomem;
                     84:        }
                     85:        return -ARS_OK; /* report anyway success */
                     86: }
                     87: 
                     88: /* Set the default for a layer */
                     89: int ars_set_default(struct ars_packet *pkt, int layer_type, void *def)
                     90: {
                     91:        pkt->p_default[layer_type] = def;
                     92:        return -ARS_OK;
                     93: }
                     94: 
                     95: /* return nonzero if the packet is full */
                     96: int ars_nospace(struct ars_packet *pkt)
                     97: {
                     98:        return (pkt->p_layer_nr == ARS_MAX_LAYER);
                     99: }
                    100: 
                    101: /* Check if the layer number is valid */
                    102: int ars_valid_layer(int layer)
                    103: {
                    104:        if (layer < 0 || layer >= ARS_MAX_LAYER)
                    105:                return -ARS_INVALID;
                    106:        return -ARS_OK;
                    107: }
                    108: 
                    109: /* Add an a generic layer */
                    110: int ars_add_generic(struct ars_packet *pkt, size_t size, int type)
                    111: {
                    112:        int layer;
                    113: 
                    114:        if (ars_nospace(pkt)) {
                    115:                ars_set_error(pkt, "No space for the next layer");
                    116:                return -ARS_NOSPACE;
                    117:        }
                    118:        layer = pkt->p_layer_nr;
                    119:        /* You may want to create a 0 len layer and then realloc */
                    120:        if (size != 0) {
                    121:                pkt->p_layer[layer].l_data = malloc(size);
                    122:                if (pkt->p_layer[layer].l_data == NULL) {
                    123:                        ars_set_error(pkt, "Out of memory adding a new layer");
                    124:                        return -ARS_NOMEM;
                    125:                }
                    126:                memset(pkt->p_layer[layer].l_data, 0, size);
                    127:                /* Copy the default if any */
                    128:                if (pkt->p_default[type] != NULL) {
                    129:                        memcpy(pkt->p_layer[layer].l_data,
                    130:                               pkt->p_default[type], size);
                    131:                }
                    132:        }
                    133:        pkt->p_layer[layer].l_type = type;
                    134:        pkt->p_layer[layer].l_size = size;
                    135:        return -ARS_OK;
                    136: }
                    137: 
                    138: /* Add an IP layer */
                    139: void *ars_add_iphdr(struct ars_packet *pkt, int unused)
                    140: {
                    141:        int retval;
                    142: 
                    143:        retval = ars_add_generic(pkt, sizeof(struct ars_iphdr), ARS_TYPE_IP);
                    144:        if (retval != -ARS_OK)
                    145:                return NULL;
                    146:        pkt->p_layer_nr++;
                    147:        return pkt->p_layer[pkt->p_layer_nr-1].l_data;
                    148: }
                    149: 
                    150: /* Add on IP option */
                    151: void *ars_add_ipopt(struct ars_packet *pkt, int option)
                    152: {
                    153:        int retval;
                    154:        struct ars_ipopt *ipopt;
                    155:        int opt_len;
                    156: 
                    157:        switch(option) {
                    158:        case ARS_IPOPT_END:
                    159:        case ARS_IPOPT_NOOP:
                    160:                opt_len = 1;
                    161:                break;
                    162:        case ARS_IPOPT_SEC:
                    163:                opt_len = 11;
                    164:                break;
                    165:        case ARS_IPOPT_SID:
                    166:                opt_len = 4;
                    167:                break;
                    168:        case ARS_IPOPT_LSRR:
                    169:        case ARS_IPOPT_SSRR:
                    170:        case ARS_IPOPT_RR:
                    171:        case ARS_IPOPT_TIMESTAMP:
                    172:                /* We allocate the max (40 bytes) but the real layer size
                    173:                 * may be modified by ars_ipopt_set*() functions */
                    174:                opt_len = 40;
                    175:                break;
                    176:        default:
                    177:                return NULL; /* Unsupported option */
                    178:                break;
                    179:        }
                    180: 
                    181:        retval = ars_add_generic(pkt, opt_len, ARS_TYPE_IPOPT);
                    182:        if (retval != -ARS_OK)
                    183:                return NULL;
                    184:        ipopt = pkt->p_layer[pkt->p_layer_nr].l_data;
                    185:        pkt->p_layer_nr++;
                    186: 
                    187:        ipopt->kind = option;
                    188:        ipopt->len = opt_len; /* the default, can be modified inside switch() */
                    189:        /* Perform some special operation for some option */
                    190:        switch(option) {
                    191:        case ARS_IPOPT_LSRR: /* ars_ipopt_setls() will change some field */
                    192:        case ARS_IPOPT_SSRR: /* ars_ipopt_setss() will change some field */
                    193:        case ARS_IPOPT_RR:   /* ars_ipopt_setrr() will change some field */
                    194:                /* RFC 791 needs the roomlen - 3 octects, so the gateways
                    195:                 * can compare len and ptr to check for room.
                    196:                 * Try to break this to stress lame TCP/IP implementation */
                    197:                ipopt->len = opt_len - 2 - 3;
                    198:                ipopt->un.rr.ptr = 4;
                    199:                break;
                    200:        case ARS_IPOPT_TIMESTAMP:
                    201:                ipopt->un.tstamp.ptr = 5;
                    202:                ipopt->un.tstamp.flags = ARS_IPOPT_TS_TSONLY; /* default */
                    203:                break;
                    204:        }
                    205:        return ipopt;
                    206: }
                    207: 
                    208: /* Add a UDP layer */
                    209: void *ars_add_udphdr(struct ars_packet *pkt, int unused)
                    210: {
                    211:        int retval;
                    212: 
                    213:        retval = ars_add_generic(pkt, sizeof(struct ars_udphdr), ARS_TYPE_UDP);
                    214:        if (retval != -ARS_OK)
                    215:                return NULL;
                    216:        pkt->p_layer_nr++;
                    217:        return pkt->p_layer[pkt->p_layer_nr-1].l_data;
                    218: }
                    219: 
                    220: /* Add a TCP layer */
                    221: void *ars_add_tcphdr(struct ars_packet *pkt, int unused)
                    222: {
                    223:        int retval;
                    224: 
                    225:        retval = ars_add_generic(pkt, sizeof(struct ars_tcphdr), ARS_TYPE_TCP);
                    226:        if (retval != -ARS_OK)
                    227:                return NULL;
                    228:        pkt->p_layer_nr++;
                    229:        return pkt->p_layer[pkt->p_layer_nr-1].l_data;
                    230: }
                    231: 
                    232: /* Add TCP options */
                    233: void *ars_add_tcpopt(struct ars_packet *pkt, int option)
                    234: {
                    235:        int retval;
                    236:        struct ars_tcpopt *tcpopt;
                    237:        int opt_len;
                    238: 
                    239:        switch(option) {
                    240:        case ARS_TCPOPT_NOP:
                    241:        case ARS_TCPOPT_EOL:
                    242:                opt_len = 1;
                    243:                break;
                    244:        case ARS_TCPOPT_MAXSEG:
                    245:                opt_len = 4;
                    246:                break;
                    247:        case ARS_TCPOPT_WINDOW:
                    248:                opt_len = 3;
                    249:                break;
                    250:        case ARS_TCPOPT_SACK_PERM: /* ars_tcpopt_setsack() must change this */
                    251:        case ARS_TCPOPT_SACK:
                    252:                opt_len = 2;
                    253:                break;
                    254:        case ARS_TCPOPT_ECHOREQUEST:
                    255:        case ARS_TCPOPT_ECHOREPLY:
                    256:                opt_len = 6;
                    257:                break;
                    258:        case ARS_TCPOPT_TIMESTAMP:
                    259:                opt_len = 10;
                    260:                break;
                    261:        default:
                    262:                return NULL; /* Unsupported option */
                    263:                break;
                    264:        }
                    265: 
                    266:        retval = ars_add_generic(pkt, opt_len, ARS_TYPE_TCPOPT);
                    267:        if (retval != -ARS_OK)
                    268:                return NULL;
                    269:        tcpopt = pkt->p_layer[pkt->p_layer_nr].l_data;
                    270:        pkt->p_layer_nr++;
                    271: 
                    272:        tcpopt->kind = option;
                    273:        /* EOL and NOP lacks the len field */
                    274:        if (option != ARS_TCPOPT_EOL && option != ARS_TCPOPT_NOP)
                    275:                tcpopt->len = opt_len;
                    276: 
                    277:        /* Perform some special operation for the option */
                    278:        switch(option) {
                    279:        case ARS_TCPOPT_ECHOREQUEST:
                    280:        case ARS_TCPOPT_ECHOREPLY:
                    281:                memset(tcpopt->un.echo.info, 0, 4);
                    282:                break;
                    283:        case ARS_TCPOPT_TIMESTAMP:
                    284:                memset(tcpopt->un.timestamp.tsval, 0, 4);
                    285:                memset(tcpopt->un.timestamp.tsecr, 0, 4);
                    286:                break;
                    287:        }
                    288:        return tcpopt;
                    289: }
                    290: 
                    291: /* Add an ICMP layer */
                    292: void *ars_add_icmphdr(struct ars_packet *pkt, int unused)
                    293: {
                    294:        int retval;
                    295:        struct ars_icmphdr *icmp;
                    296: 
                    297:        retval = ars_add_generic(pkt, sizeof(struct ars_icmphdr),ARS_TYPE_ICMP);
                    298:        if (retval != -ARS_OK)
                    299:                return NULL;
                    300:        icmp = pkt->p_layer[pkt->p_layer_nr].l_data;
                    301:        pkt->p_layer_nr++;
                    302:        return (struct ars_icmphdr*) pkt->p_layer[pkt->p_layer_nr-1].l_data;
                    303: }
                    304: 
                    305: /* Add data, for IP-RAW, TCP, UDP, and so on */
                    306: void *ars_add_data(struct ars_packet *pkt, int size)
                    307: {
                    308:        int retval;
                    309:        void *boguspointer = "zzappt"; /* we can't return NULL for size == 0 */
                    310: 
                    311:        if (size < 0) {
                    312:                ars_set_error(pkt, "Tryed to add a DATA layer with size < 0");
                    313:                return NULL;
                    314:        }
                    315:        retval = ars_add_generic(pkt, size, ARS_TYPE_DATA);
                    316:        if (retval != -ARS_OK)
                    317:                return NULL;
                    318:        pkt->p_layer_nr++;
                    319:        if (size > 0)
                    320:                return pkt->p_layer[pkt->p_layer_nr-1].l_data;
                    321:        else
                    322:                return boguspointer;
                    323: }
                    324: 
                    325: /* Remove a layer */
                    326: int ars_remove_layer(struct ars_packet *pkt, int layer)
                    327: {
                    328:        if (layer == ARS_LAST_LAYER)
                    329:                layer = pkt->p_layer_nr -1;
                    330:        if (ars_valid_layer(layer) != -ARS_OK)
                    331:                return -ARS_INVALID;
                    332: 
                    333:        free(pkt->p_layer[layer].l_data); /* No problem if it's NULL */
                    334:        pkt->p_layer[layer].l_type = ARS_TYPE_NULL;
                    335:        pkt->p_layer[layer].l_size = 0;
                    336:        pkt->p_layer[layer].l_flags = 0;
                    337:        pkt->p_layer[layer].l_data = NULL;
                    338:        pkt->p_layer[layer].l_packet = pkt;
                    339:        return -ARS_OK;
                    340: }
                    341: 
                    342: /* Return the sum of the size of the specifed layer and of all the
                    343:  * following layers */
                    344: size_t ars_relative_size(struct ars_packet *pkt, int layer_nr)
                    345: {
                    346:        int j = layer_nr, rel_size = 0;
                    347: 
                    348:        while (j < ARS_MAX_LAYER && pkt->p_layer[j].l_type != ARS_TYPE_NULL) {
                    349:                rel_size += pkt->p_layer[j].l_size;
                    350:                j++;
                    351:        }
                    352:        return rel_size;
                    353: }
                    354: 
                    355: /* Just a short cut for ars_relative_size(), to get the total size */
                    356: size_t ars_packet_size(struct ars_packet *pkt)
                    357: {
                    358:        return ars_relative_size(pkt, 0);
                    359: }
                    360: 
                    361: /* from R. Stevens's Network Programming */
                    362: u_int16_t ars_cksum(void *vbuf, size_t nbytes)
                    363: {
                    364:        u_int16_t *buf = (u_int16_t*) vbuf;
                    365:        u_int32_t sum;
                    366:        u_int16_t oddbyte;
                    367: 
                    368:        sum = 0;
                    369:        while (nbytes > 1) {
                    370:                sum += *buf++;
                    371:                nbytes -= 2;
                    372:        }
                    373:        if (nbytes == 1) {
                    374:                oddbyte = 0;
                    375:                *((u_int16_t *) &oddbyte) = *(u_int8_t *) buf;
                    376:                sum += oddbyte;
                    377:        }
                    378:        sum = (sum >> 16) + (sum & 0xffff);
                    379:        sum += (sum >> 16);
                    380:        return (u_int16_t) ~sum;
                    381: }
                    382: 
                    383: /* Multiple buffers checksum facility */
                    384: u_int16_t ars_multi_cksum(struct mc_context *c, int op, void *vbuf,
                    385:                                                        size_t nbytes)
                    386: {
                    387:        u_int16_t *buf = (u_int16_t*) vbuf;
                    388:        u_int32_t sum;
                    389:        u_int16_t oddbyte;
                    390:        void *tmp;
                    391: 
                    392:        if (op == ARS_MC_INIT) {
                    393:                c->oddbyte_flag = 0;
                    394:                c->old = 0;
                    395:                return -ARS_OK;
                    396:        } else if (op == ARS_MC_UPDATE) {
                    397:                if (c->oddbyte_flag) {
                    398:                        u_int8_t *x = (u_int8_t*)&oddbyte;
                    399:                        oddbyte = 0;
                    400:                        *((u_int16_t *) &oddbyte) = c->oddbyte << 8;
                    401:                        *((u_int16_t *) &oddbyte) |= *(u_int8_t *) buf;
                    402:                        oddbyte = (x[0] << 8) | x[1]; /* fix endianess */
                    403:                        c->old += oddbyte;
                    404:                        nbytes--;
                    405:                        c->oddbyte_flag = 0;
                    406:                        /* We need to stay aligned -- bad slowdown, fix? */
                    407:                        tmp = alloca(nbytes);
                    408:                        memcpy(tmp, vbuf+1, nbytes);
                    409:                        buf = tmp;
                    410:                }
                    411:                sum = c->old;
                    412:                while (nbytes > 1) {
                    413:                        sum += *buf++;
                    414:                        nbytes -= 2;
                    415:                }
                    416:                c->old = sum;
                    417:                if (nbytes == 1) {
                    418:                        c->oddbyte = *(u_int8_t*) buf;
                    419:                        c->oddbyte_flag++;
                    420:                }
                    421:                return -ARS_OK;
                    422:        } else if (op == ARS_MC_FINAL) {
                    423:                sum = c->old;
                    424:                if (c->oddbyte_flag == 1) {
                    425:                        oddbyte = 0;
                    426:                        *((u_int16_t *) &oddbyte) = c->oddbyte;
                    427:                        sum += oddbyte;
                    428:                }
                    429:                sum = (sum >> 16) + (sum & 0xffff);
                    430:                sum += (sum >> 16);
                    431:                return (u_int16_t) ~sum;
                    432:        } else {
                    433:                assert("else reached in ars_multi_cksum()" == "");
                    434:        }
                    435:        return 0; /* unreached, here to prevent warnings */
                    436: }
                    437: 
                    438: /* The ARS compiler table is just a function pointers array:
                    439:  * For example to select the right function to compile an IP
                    440:  * layer use: ars_compiler[ARS_TYPE_IP](pkt, layer);
                    441:  * You can, of course, add your protocols and compilers:
                    442:  *
                    443:  * WARNING: take it syncronized with ars.h ARS_TYPE_* defines
                    444:  */
                    445: struct ars_layer_info ars_linfo[ARS_TYPE_SIZE] = {
                    446:        /* NAME                 COMPILER                ID *
                    447:         * ----                 --------                -- */
                    448:        { "NULL",               ars_compiler_abort,     0 },
                    449:        { "IP",                 ars_compiler_ip,        1 },
                    450:        { "IPOPT",              ars_compiler_ipopt,     2 },
                    451:        { "ICMP",               ars_compiler_icmp,      3 },
                    452:        { "UDP",                ars_compiler_udp,       4 },
                    453:        { "TCP",                ars_compiler_tcp,       5 },
                    454:        { "TCPOPT",             ars_compiler_tcpopt,    6 },
                    455:        { NULL, NULL, 7 },
                    456:        { NULL, NULL, 8 },
                    457:        { NULL, NULL, 9 },
                    458:        { NULL, NULL, 10 },
                    459:        { NULL, NULL, 11 },
                    460:        { NULL, NULL, 12 },
                    461:        { NULL, NULL, 13 },
                    462:        { NULL, NULL, 14 },
                    463:        { NULL, NULL, 15 },
                    464:        { NULL, NULL, 16 },
                    465:        { NULL, NULL, 17 },
                    466:        { NULL, NULL, 18 },
                    467:        { NULL, NULL, 19 },
                    468:        { NULL, NULL, 20 },
                    469:        { NULL, NULL, 21 },
                    470:        { NULL, NULL, 22 },
                    471:        { NULL, NULL, 23 },
                    472:        { NULL, NULL, 24 },
                    473:        { NULL, NULL, 25 },
                    474:        { NULL, NULL, 26 },
                    475:        { NULL, NULL, 27 },
                    476:        { NULL, NULL, 28 },
                    477:        { NULL, NULL, 29 },
                    478:        { NULL, NULL, 30 },
                    479:        { "DATA",               NULL,                   31 }
                    480: };
                    481: 
                    482: /* This function call the right compiler for all the layers of the packet:
                    483:  * A compiler just set the protocol fields like the checksum, len, and so on
                    484:  * accordly to the following layers.
                    485:  * Note that the layers are compiled from the last to the first, to ensure
                    486:  * that the checksum and other dependences are sane. */
                    487: int ars_compile(struct ars_packet *pkt)
                    488: {
                    489:        int j, err;
                    490: 
                    491:        for (j = pkt->p_layer_nr - 1; j >= 0; j--) {
                    492:                __D(printf("Compiling layer %d\n", j);)
                    493:                /* Skip NULL compilers */
                    494:                if (ars_linfo[pkt->p_layer[j].l_type].li_compiler != NULL) {
                    495:                        /* Call the compiler */
                    496:                        err = ars_linfo[pkt->p_layer[j].l_type].li_compiler(pkt, j);
                    497:                        if (err != -ARS_OK)
                    498:                                return err;
                    499:                }
                    500:        }
                    501:        return -ARS_OK;
                    502: }
                    503: 
                    504: /* The IP compiler: probably the more complex, but still simple */
                    505: int ars_compiler_ip(struct ars_packet *pkt, int layer)
                    506: {
                    507:        struct ars_iphdr *ip = pkt->p_layer[layer].l_data;
                    508:        int j = layer, err;
                    509:        int flags = pkt->p_layer[layer].l_flags;
                    510:        int ipoptlen = 0;
                    511:        struct mc_context mc; /* multi-buffer checksum context */
                    512: 
                    513:        /* IP version */
                    514:        if (ARS_DONTTAKE(flags, ARS_TAKE_IP_VERSION))
                    515:                ip->version = 4;
                    516:        /* IP header len */
                    517:        if (ARS_DONTTAKE(flags, ARS_TAKE_IP_HDRLEN)) {
                    518:                ip->ihl = (ARS_IPHDR_SIZE >> 2);
                    519:                /* Add IP options len */
                    520:                for (j = layer+1; j < ARS_MAX_LAYER; j++) {
                    521:                        if (pkt->p_layer[j].l_type != ARS_TYPE_IPOPT)
                    522:                                break;
                    523:                        ipoptlen += pkt->p_layer[j].l_size; 
                    524:                }
                    525:                ip->ihl += ipoptlen >> 2;
                    526:        }
                    527:        /* IP tot len */
                    528:        if (ARS_DONTTAKE(flags, ARS_TAKE_IP_TOTLEN))
                    529:                ip->tot_len = htons(ars_relative_size(pkt, layer));
                    530:        /* IP protocol field */
                    531:        if (ARS_DONTTAKE(flags, ARS_TAKE_IP_PROTOCOL)) {
                    532:                ip->protocol = ARS_IPPROTO_RAW; /* This is the default */
                    533:                while (j < ARS_MAX_LAYER) {
                    534:                        if (pkt->p_layer[j].l_type == ARS_TYPE_IPOPT) {
                    535:                                j++;
                    536:                                continue;
                    537:                        }
                    538:                        switch(pkt->p_layer[j].l_type) {
                    539:                        case ARS_TYPE_IP:
                    540:                                ip->protocol = ARS_IPPROTO_IPIP;
                    541:                                break;
                    542:                        case ARS_TYPE_ICMP:
                    543:                                ip->protocol = ARS_IPPROTO_ICMP;
                    544:                                break;
                    545:                        case ARS_TYPE_UDP:
                    546:                                ip->protocol = ARS_IPPROTO_UDP;
                    547:                                break;
                    548:                        case ARS_TYPE_TCP:
                    549:                                ip->protocol = ARS_IPPROTO_TCP;
                    550:                                break;
                    551:                        }
                    552:                        break;
                    553:                }
                    554:        }
                    555:        /* We always calculate the IP checksum, since the kernel
                    556:         * do it only for the first IP header in the datagram */
                    557:        if (ARS_DONTTAKE(flags, ARS_TAKE_IP_CKSUM)) {
                    558:                ip->check = 0;
                    559:                ars_multi_cksum(&mc, ARS_MC_INIT, NULL, 0);
                    560:                err = ars_multi_cksum(&mc, ARS_MC_UPDATE, ip, ARS_IPHDR_SIZE);
                    561:                if (err != -ARS_OK)
                    562:                        return err;
                    563:                for (j = layer+1; j < ARS_MAX_LAYER; j++) {
                    564:                        if (pkt->p_layer[j].l_type != ARS_TYPE_IPOPT)
                    565:                                break;
                    566:                        err = ars_multi_cksum(&mc, ARS_MC_UPDATE,
                    567:                                                pkt->p_layer[j].l_data,
                    568:                                                pkt->p_layer[j].l_size);
                    569:                        if  (err != -ARS_OK)
                    570:                                return err;
                    571:                }
                    572:                ip->check = ars_multi_cksum(&mc, ARS_MC_FINAL, NULL, 0);
                    573:        }
                    574:        return -ARS_OK;
                    575: }
                    576: 
                    577: /* The ip options compiler: do just option padding with NOP options */
                    578: int ars_compiler_ipopt(struct ars_packet *pkt, int layer)
                    579: {
                    580:        int j, opt_size;
                    581: 
                    582:        /* Padding is needed only in the last IP option */
                    583:        if (layer != ARS_MAX_LAYER-1 &&
                    584:            pkt->p_layer[layer+1].l_type == ARS_TYPE_IPOPT)
                    585:                return ARS_OK;
                    586: 
                    587:        /* Search the layer of the relative first TCP option */
                    588:        j = layer - 1; /* We know that 'layer' is a tcp option */
                    589:        while (j < ARS_MAX_LAYER && j >= 0 &&
                    590:               pkt->p_layer[j].l_type == ARS_TYPE_IPOPT)
                    591:                j--;
                    592:        j++;
                    593:        __D(printf("First IP OPTION layer is %d\n", j);)
                    594:        opt_size = ars_relative_size(pkt, j) - ars_relative_size(pkt, layer+1);
                    595:        __D(printf("IP OPTION size %d\n", opt_size);)
                    596:        if (opt_size % 4) {
                    597:                int padding = 4 - (opt_size % 4);
                    598:                unsigned char *t;
                    599:                int cur_size = pkt->p_layer[layer].l_size;
                    600: 
                    601:                __D(printf("IP OPTION at layer %d needs %d bytes "
                    602:                           "of padding\n", layer, padding);)
                    603:                t = realloc(pkt->p_layer[layer].l_data, cur_size + padding);
                    604:                if (t == NULL) {
                    605:                        ars_set_error(pkt, "Out of memory padding IP options");
                    606:                        return -ARS_NOMEM;
                    607:                }
                    608:                memset(t+cur_size, ARS_IPOPT_NOP, padding);
                    609:                pkt->p_layer[layer].l_size += padding;
                    610:        }
                    611:        return -ARS_OK;
                    612: }
                    613: 
                    614: /* Compute the UDP and TCP checksum using the pseudoheader.
                    615:  * Note that this functions automatically care about TCP/UDP data */
                    616: int ars_udptcp_cksum(struct ars_packet *pkt, int layer, u_int16_t *sum)
                    617: {
                    618:        struct ars_iphdr *ip;
                    619:        struct ars_pseudohdr pseudo;
                    620:        struct mc_context mc; /* multi-buffer checksum context */
                    621:        int j = layer - 1, err;
                    622: 
                    623:        /* search the first IP layer on the left:
                    624:         * it returns an error if between the IP and
                    625:         * the TCP layer there aren't just IPOPT layers:
                    626:         * even with malformed packets this does not
                    627:         * makes sense. */
                    628:        while (j > 0 && pkt->p_layer[j].l_type == ARS_TYPE_IPOPT)
                    629:                j--;
                    630:        if (pkt->p_layer[j].l_type != ARS_TYPE_IP) {
                    631:                ars_set_error(pkt, "TCP/UDP checksum requested, but IP header "
                    632:                                    "not found");
                    633:                return -ARS_INVALID;
                    634:        }
                    635:        ip = pkt->p_layer[j].l_data;
                    636:        memset(&pseudo, 0, sizeof(pseudo)); /* actually not needed */
                    637:        /* Copy the src and dst IP address */
                    638:        memcpy(&pseudo.saddr, &ip->saddr, 4);
                    639:        memcpy(&pseudo.daddr, &ip->daddr, 4);
                    640:        pseudo.protocol = (pkt->p_layer[layer].l_type == ARS_TYPE_TCP)
                    641:                ? ARS_IPPROTO_TCP : ARS_IPPROTO_UDP;
                    642:        pseudo.lenght = htons(ars_relative_size(pkt, layer));
                    643: 
                    644:        /* Finally do the checksum */
                    645:        ars_multi_cksum(&mc, ARS_MC_INIT, NULL, 0);
                    646:        err = ars_multi_cksum(&mc, ARS_MC_UPDATE, &pseudo, sizeof(pseudo));
                    647:        if (err != -ARS_OK)
                    648:                return err;
                    649:        for (j = layer; j < ARS_MAX_LAYER; j++) {
                    650:                if (pkt->p_layer[j].l_type == ARS_TYPE_NULL)
                    651:                        break;
                    652:                err = ars_multi_cksum(&mc, ARS_MC_UPDATE,
                    653:                                        pkt->p_layer[j].l_data,
                    654:                                        pkt->p_layer[j].l_size);
                    655:                if  (err != -ARS_OK)
                    656:                        return err;
                    657:        }
                    658:        *sum = ars_multi_cksum(&mc, ARS_MC_FINAL, NULL, 0);
                    659:        return -ARS_OK;
                    660: }
                    661: 
                    662: /* The tcp compiler */
                    663: int ars_compiler_tcp(struct ars_packet *pkt, int layer)
                    664: {
                    665:        struct ars_tcphdr *tcp = pkt->p_layer[layer].l_data;
                    666:        int j, err, tcpoptlen = 0;
                    667:        int flags = pkt->p_layer[layer].l_flags;
                    668: 
                    669:        if (ARS_DONTTAKE(flags, ARS_TAKE_TCP_HDRLEN)) {
                    670:                tcp->th_off = ARS_TCPHDR_SIZE >> 2;
                    671:                /* Add the len of the options */
                    672:                for (j = layer+1; j < ARS_MAX_LAYER; j++) {
                    673:                        if (pkt->p_layer[j].l_type != ARS_TYPE_TCPOPT)
                    674:                                break;
                    675:                        tcpoptlen += pkt->p_layer[j].l_size;
                    676:                }
                    677:                tcp->th_off += tcpoptlen >> 2;
                    678:        }
                    679:        if (ARS_DONTTAKE(flags, ARS_TAKE_TCP_CKSUM)) {
                    680:                tcp->th_sum = 0;
                    681:                err = ars_udptcp_cksum(pkt, layer, &tcp->th_sum);
                    682:                if (err != -ARS_OK)
                    683:                        return err;
                    684:        }
                    685:        return -ARS_OK;
                    686: }
                    687: 
                    688: /* The tcp options compiler: do just option padding with NOP options */
                    689: int ars_compiler_tcpopt(struct ars_packet *pkt, int layer)
                    690: {
                    691:        int j, opt_size;
                    692: 
                    693:        /* Padding is needed only in the last TCP option */
                    694:        if (layer != ARS_MAX_LAYER-1 &&
                    695:            pkt->p_layer[layer+1].l_type == ARS_TYPE_TCPOPT)
                    696:                return ARS_OK;
                    697: 
                    698:        /* Search the layer of the relative first TCP option */
                    699:        j = layer - 1; /* We know that 'layer' is a tcp option */
                    700:        while (j < ARS_MAX_LAYER && j >= 0 &&
                    701:               pkt->p_layer[j].l_type == ARS_TYPE_TCPOPT)
                    702:                j--;
                    703:        j++;
                    704:        __D(printf("First TCP OPTION layer is %d\n", j);)
                    705:        opt_size = ars_relative_size(pkt, j) - ars_relative_size(pkt, layer+1);
                    706:        __D(printf("TCP OPTION size %d\n", opt_size);)
                    707:        if (opt_size % 4) {
                    708:                int padding = 4 - (opt_size % 4);
                    709:                unsigned char *t;
                    710:                int cur_size = pkt->p_layer[layer].l_size;
                    711: 
                    712:                __D(printf("TCP OPTION at layer %d needs %d bytes "
                    713:                           "of padding\n", layer, padding);)
                    714:                t = realloc(pkt->p_layer[layer].l_data, cur_size + padding);
                    715:                if (t == NULL) {
                    716:                        ars_set_error(pkt, "Out of memory padding TCP options");
                    717:                        return -ARS_NOMEM;
                    718:                }
                    719:                memset(t+cur_size, ARS_TCPOPT_NOP, padding);
                    720:                pkt->p_layer[layer].l_size += padding;
                    721:        }
                    722:        return -ARS_OK;
                    723: }
                    724: 
                    725: /* The udp compiler, very simple */
                    726: int ars_compiler_udp(struct ars_packet *pkt, int layer)
                    727: {
                    728:        struct ars_udphdr *udp = pkt->p_layer[layer].l_data;
                    729:        int err;
                    730:        int flags = pkt->p_layer[layer].l_flags;
                    731: 
                    732:        if (ARS_DONTTAKE(flags, ARS_TAKE_UDP_LEN))
                    733:                udp->uh_ulen = htons(ars_relative_size(pkt, layer));
                    734: 
                    735:        if (ARS_DONTTAKE(flags, ARS_TAKE_UDP_CKSUM)) {
                    736:                udp->uh_sum = 0;
                    737:                err = ars_udptcp_cksum(pkt, layer, &udp->uh_sum);
                    738:                if (err != -ARS_OK)
                    739:                        return err;
                    740:        }
                    741:        return -ARS_OK;
                    742: }
                    743: 
                    744: /* The icmp compiler, just compute the checksum */
                    745: int ars_compiler_icmp(struct ars_packet *pkt, int layer)
                    746: {
                    747:        struct ars_icmphdr *icmp = pkt->p_layer[layer].l_data;
                    748:        struct mc_context mc; /* multi-buffer checksum context */
                    749:        int err, j;
                    750:        int flags = pkt->p_layer[layer].l_flags;
                    751: 
                    752:        if (ARS_DONTTAKE(flags, ARS_TAKE_ICMP_CKSUM)) {
                    753:                icmp->checksum = 0;
                    754:                ars_multi_cksum(&mc, ARS_MC_INIT, NULL, 0);
                    755:                for (j = layer; j < ARS_MAX_LAYER; j++) {
                    756:                        if (pkt->p_layer[j].l_type == ARS_TYPE_NULL)
                    757:                                break;
                    758:                        err = ars_multi_cksum(&mc, ARS_MC_UPDATE,
                    759:                                                pkt->p_layer[j].l_data,
                    760:                                                pkt->p_layer[j].l_size);
                    761:                        if  (err != -ARS_OK)
                    762:                                return err;
                    763:                }
                    764:                icmp->checksum = ars_multi_cksum(&mc, ARS_MC_FINAL, NULL, 0);
                    765:        }
                    766:        return -ARS_OK;
                    767: }
                    768: 
                    769: /* Open a raw socket, ready for IP header creation and broadcast addresses */
                    770: int ars_open_rawsocket(struct ars_packet *pkt)
                    771: {
                    772:        int s;
                    773:        const int one = 1;
                    774: 
                    775:        if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1) {
                    776:                ars_set_error(pkt, "Can't open the raw socket");
                    777:                return -ARS_ERROR;
                    778:        }
                    779:        if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char*)&one,
                    780:                sizeof(one)) == -1 ||
                    781:            setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char*)&one,
                    782:                sizeof(one)) == -1)
                    783:        {
                    784:                close(s);
                    785:                ars_set_error(pkt, "Can't set socket options");
                    786:                return -ARS_ERROR;
                    787:        }
                    788:        return s;
                    789: }
                    790: 
                    791: /* Create the packets using the layers. This function is often called
                    792:  * after the layers compilation. Note that since the packet created
                    793:  * is sane the strange-rawsocket-behaviour of some *BSD will not
                    794:  * be able to send this packet. Use the function ars_bsd_fix() to fix it.
                    795:  * WARNING: The packets returned is malloc()ated, free it */
                    796: int ars_build_packet(struct ars_packet *pkt, unsigned char **packet, size_t *size)
                    797: {
                    798:        size_t tot_size, offset = 0;
                    799:        int j = 0;
                    800: 
                    801:        if ((tot_size = ars_packet_size(pkt)) == 0) {
                    802:                ars_set_error(pkt, "Total size 0 building the packet");
                    803:                return -ARS_INVALID;
                    804:        }
                    805:        if ((*packet = malloc(tot_size)) == NULL) {
                    806:                ars_set_error(pkt, "Out of memory building the packet");
                    807:                return -ARS_NOMEM;
                    808:        }
                    809:        while (j < ARS_MAX_LAYER && pkt->p_layer[j].l_type != ARS_TYPE_NULL) {
                    810:                memcpy((*packet)+offset, pkt->p_layer[j].l_data,
                    811:                                         pkt->p_layer[j].l_size);
                    812:                offset += pkt->p_layer[j].l_size;
                    813:                j++;
                    814:        }
                    815:        *size = tot_size;
                    816:        return -ARS_OK;
                    817: }
                    818: 
                    819: /* FreeBSD and NetBSD have a strange raw socket layer :(
                    820:  * Call this function anyway to increase portability
                    821:  * since it does not perform any operation if the
                    822:  * system isn't FreeBSD or NetBSD. */
                    823: int ars_bsd_fix(struct ars_packet *pkt, unsigned char *packet, size_t size)
                    824: {
                    825:        struct ars_iphdr *ip;
                    826: 
                    827:        if (pkt->p_layer[0].l_type != ARS_TYPE_IP ||
                    828:            size < sizeof(struct ars_iphdr)) {
                    829:                ars_set_error(pkt, "BSD fix requested, but layer 0 not IP");
                    830:                return -ARS_INVALID;
                    831:        }
                    832:        ip = (struct ars_iphdr*) packet;
                    833: #if defined OSTYPE_FREEBSD || defined OSTYPE_NETBSD || defined OSTYPE_BSDI
                    834:        ip->tot_len = ntohs(ip->tot_len);
                    835:        ip->frag_off = ntohs(ip->frag_off);
                    836: #endif
                    837:        return -ARS_OK;
                    838: }
                    839: 
                    840: /* Set the flags for some layer: if layer == -1 the last layer will be used */
                    841: int ars_set_flags(struct ars_packet *pkt, int layer, int flags)
                    842: {
                    843:        if (layer == ARS_LAST_LAYER)
                    844:                layer = pkt->p_layer_nr - 1;
                    845:        if (layer < 0 || layer >= ARS_MAX_LAYER) {
                    846:                ars_set_error(pkt, "Invalid layer setting layer flags");
                    847:                return -ARS_INVALID;
                    848:        }
                    849:        pkt->p_layer[layer].l_flags = flags;
                    850:        return -ARS_OK;
                    851: }
                    852: 
                    853: /* Build, fix, and send the packet */
                    854: int ars_send(int s, struct ars_packet *pkt, struct sockaddr *sa, socklen_t slen)
                    855: {
                    856:        struct sockaddr_in sain;
                    857:        struct sockaddr *_sa = sa;
                    858:        unsigned char *packet;
                    859:        size_t size;
                    860:        int error;
                    861: 
                    862:        /* Perform the socket address completion if sa == NULL */
                    863:        if (sa == NULL) {
                    864:                struct ars_iphdr *ip;
                    865: 
                    866:                memset(&sain, 0, sizeof(sain));
                    867:                sain.sin_family = AF_INET;
                    868:                /* The first layer MUST be IP if the user requested
                    869:                 * the socket address completion */
                    870:                if (pkt->p_layer[0].l_type != ARS_TYPE_IP) {
                    871:                        ars_set_error(pkt, "socket address completion"
                    872:                                "requested, but layer 0 isn't IP");
                    873:                        return -ARS_ERROR;
                    874:                }
                    875:                ip = (struct ars_iphdr*) pkt->p_layer[0].l_data;
                    876:                memcpy(&sain.sin_addr.s_addr, &ip->daddr, 4);
                    877:                _sa = (struct sockaddr*) &sain;
                    878:                slen = sizeof(sain);
                    879:        }
                    880:        if ((error = ars_build_packet(pkt, &packet, &size)) != ARS_OK)
                    881:                return error;
                    882:        if ((error = ars_bsd_fix(pkt, packet, size)) != ARS_OK)
                    883:                return error;
                    884:        error = sendto(s, packet, size, 0, _sa, slen);
                    885:        free(packet);
                    886:        return (error != -1) ? -ARS_OK : -ARS_ERROR;
                    887: }
                    888: 
                    889: /* Resolve an hostname and write to 'dest' the IP */
                    890: int ars_resolve(struct ars_packet *pkt, u_int32_t *dest, char *hostname)
                    891: {
                    892:        struct sockaddr_in sa;
                    893: 
                    894:        if (inet_aton(hostname, &sa.sin_addr) == 0) {
                    895:                struct hostent *he;
                    896:                he = gethostbyname(hostname);
                    897:                if (he == NULL) {
                    898:                        ars_set_error(pkt, "Can't resolve the hostname");
                    899:                        return -ARS_ERROR;
                    900:                }
                    901:                sa.sin_addr.s_addr = ((struct in_addr*) he->h_addr)->s_addr;
                    902:        }
                    903:        memcpy(dest, &sa.sin_addr.s_addr, sizeof(u_int32_t));
                    904:        return -ARS_OK;
                    905: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>