Annotation of embedaddon/libnet/src/libnet_build_gre.c, revision 1.1.1.3

1.1       misho       1: /*
                      2:  *  libnet
                      3:  *  libnet_build_gre.c - GRE packet assembler
                      4:  *
                      5:  *  Copyright (c) 2003 Frédéric Raynal <pappy@security-labs.org>
                      6:  *  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  *
                     17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     18:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     19:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     20:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     21:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     22:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     23:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     25:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     26:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     27:  * SUCH DAMAGE.
                     28:  *
                     29:  */
                     30: 
1.1.1.3 ! misho      31: #include "common.h"
1.1       misho      32: 
                     33: /*
                     34:  * Overall packet
                     35:  *
                     36:  *  The entire encapsulated packet would then have the form:
                     37:  *
                     38:  *                  ---------------------------------
                     39:  *                  |                               |
                     40:  *                  |       Delivery Header         |
                     41:  *                  |                               |
                     42:  *                  ---------------------------------
                     43:  *                  |                               |
                     44:  *                  |       GRE Header              |
                     45:  *                  |                               |
                     46:  *                  ---------------------------------
                     47:  *                  |                               |
                     48:  *                  |       Payload packet          |
                     49:  *                  |                               |
                     50:  *                  ---------------------------------
                     51:  *
                     52:  * RFC 1701 defines a header. 
                     53:  * A new RFC (2784) has changed the header and proposed to remove the key 
                     54:  * and seqnum.
                     55:  * A newer RFC (2890) has changed the header proposed in RFC 2784 by putting
                     56:  * back key and seqnum.
                     57:  * These will be supported the day IETF'guys stop this mess !
                     58:  *
                     59:  *   FR
                     60:  */
                     61: 
                     62: 
                     63: /* 
                     64:  * Generic Routing Encapsulation (GRE) 
                     65:  * RFC 1701 http://www.faqs.org/rfcs/rfc1701.html
                     66:  *                                
                     67:  *
                     68:  * Packet header
                     69:  *
                     70:  *   The GRE packet header has the form:
                     71:  *
                     72:  *       0                   1                   2                   3
                     73:  *       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
                     74:  *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     75:  *      |C|R|K|S|s|Recur|  Flags  | Ver |         Protocol Type         |
                     76:  *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     77:  *      |      Checksum (optional)      |       Offset (optional)       |
                     78:  *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     79:  *      |                         Key (optional)                        |
                     80:  *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     81:  *      |                    Sequence Number (optional)                 |
                     82:  *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     83:  *      |                         Routing (optional)                    |
                     84:  *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     85:  *
                     86:  * Enhanced GRE header
                     87:  *
                     88:  *   See rfc 2637 for details. It is used for PPTP tunneling.
                     89:  * 
                     90:  *          0                   1                   2                   3
                     91:  *          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
                     92:  *         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     93:  *         |C|R|K|S|s|Recur|A| Flags | Ver |         Protocol Type         |
                     94:  *         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     95:  *         |    Key (HW) Payload Length    |       Key (LW) Call ID        |
                     96:  *         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     97:  *         |                  Sequence Number (Optional)                   |
                     98:  *         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     99:  *         |               Acknowledgment Number (Optional)                |
                    100:  *         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    101:  *      
                    102:  */
1.1.1.2   misho     103: #if 0
                    104: static void
                    105: __libnet_print_gre_flags_ver(uint16_t fv)
1.1       misho     106: {
                    107:     printf("version = %d (%d) -> ",
                    108:         fv & GRE_VERSION_MASK, libnet_getgre_length(fv));
                    109:     if (fv & GRE_CSUM)
                    110:     {
                    111:         printf("CSUM ");
                    112:     }
                    113:     if (fv & GRE_ROUTING)
                    114:     {
                    115:         printf("ROUTING ");
                    116:     }
                    117:     if (fv & GRE_KEY)
                    118:     {
                    119:         printf("KEY ");
                    120:     }
                    121:     if (fv & GRE_SEQ)
                    122:     {
                    123:         printf("SEQ ");
                    124:     }
                    125:     if (fv & GRE_ACK)
                    126:     {
                    127:         printf("ACK ");
                    128:     }
                    129:     printf("\n");
                    130: }
1.1.1.2   misho     131: #endif
1.1       misho     132: 
                    133: /* FIXME: what is the portability of the "((struct libnet_gre_hdr*)0)->" ? */
1.1.1.2   misho     134: uint32_t
                    135: libnet_getgre_length(uint16_t fv)
1.1       misho     136: {
                    137: 
1.1.1.2   misho     138:     uint32_t n = LIBNET_GRE_H;
1.1       misho     139:     /*
                    140:      * If either the Checksum Present bit or the Routing Present bit are
                    141:      * set, BOTH the Checksum and Offset fields are present in the GRE
                    142:      * packet.
                    143:      */
                    144: 
                    145:     if ((!(fv & GRE_VERSION_MASK) && (fv & (GRE_CSUM|GRE_ROUTING))) || /* v0 */
                    146:        (fv & GRE_VERSION_MASK) )                                      /* v1 */
                    147:     {
                    148:        n += sizeof( ((struct libnet_gre_hdr *)0)->gre_sum) + 
                    149:            sizeof( ((struct libnet_gre_hdr *)0)->gre_offset);
                    150:     }
                    151: 
                    152:     if ((!(fv & GRE_VERSION_MASK) && (fv & GRE_KEY)) ||                /* v0 */
                    153:        ( (fv & GRE_VERSION_MASK) && (fv & GRE_SEQ)) )                 /* v1 */
                    154:     {
                    155:        n += sizeof( ((struct libnet_gre_hdr *)0)->gre_key);
                    156:     }
                    157: 
                    158:     if ((!(fv & GRE_VERSION_MASK) && (fv & GRE_SEQ)) ||                /* v0 */
                    159:        ( (fv & GRE_VERSION_MASK) && (fv & GRE_ACK)) )                 /* v1 */
                    160:     {
                    161:        n += sizeof( ((struct libnet_gre_hdr *)0)->gre_seq );
                    162:     }
                    163: 
                    164:     return (n);
                    165: }
                    166: 
                    167: libnet_ptag_t
1.1.1.2   misho     168: libnet_build_gre(uint16_t fv, uint16_t type, uint16_t sum, 
                    169: uint16_t offset, uint32_t key, uint32_t seq, uint16_t len,
                    170: const uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
1.1       misho     171: {
1.1.1.2   misho     172:     uint32_t n;
1.1       misho     173:     libnet_pblock_t *p;
                    174:     struct libnet_gre_hdr gre_hdr;
                    175: 
                    176:     if (l == NULL)
                    177:     { 
                    178:         return (-1); 
                    179:     }
                    180: 
                    181:     n = libnet_getgre_length(fv) + payload_s;
                    182: 
                    183:     /*
                    184:      *  Find the existing protocol block if a ptag is specified, or create
                    185:      *  a new one.
                    186:      */
                    187:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_GRE_H);
                    188:     if (p == NULL)
                    189:     {
                    190:         return (-1);
                    191:     }
                    192: 
                    193:     gre_hdr.flags_ver = htons(fv);
                    194:     gre_hdr.type      = htons(type);
1.1.1.2   misho     195:     n = libnet_pblock_append(l, p, (uint8_t *)&gre_hdr, LIBNET_GRE_H);
1.1       misho     196:     if (n == -1)
                    197:     {
                    198:         /* err msg set in libnet_pblock_append() */
                    199:         goto bad; 
                    200:     }
                    201: 
                    202:     if ((!(fv & GRE_VERSION_MASK) && (fv & (GRE_CSUM|GRE_ROUTING))) || /* v0 */
                    203:        (fv & GRE_VERSION_MASK))                                       /* v1 */
                    204:     {
                    205:         sum = htons(sum);
1.1.1.2   misho     206:         n = libnet_pblock_append(l, p, (uint8_t*)&sum,
1.1       misho     207:                 sizeof(gre_hdr.gre_sum));
                    208:        if (n == -1)
                    209:        {
                    210:            /* err msg set in libnet_pblock_append() */
                    211:            goto bad;
                    212:        }
                    213:        offset = htons(offset);
1.1.1.2   misho     214:        n = libnet_pblock_append(l, p, (uint8_t*)&offset, 
1.1       misho     215:                 sizeof(gre_hdr.gre_offset));
                    216:        if (n == -1)
                    217:        {
                    218:            /* err msg set in libnet_pblock_append() */
                    219:            goto bad;
                    220:        }
                    221:     }
                    222: 
                    223:     if ((!(fv & GRE_VERSION_MASK) && (fv & GRE_KEY)) ||                /* v0 */
                    224:        ( (fv & GRE_VERSION_MASK) && (fv & GRE_SEQ)) )                 /* v1 */
                    225:     {
                    226:        key = htonl(key);
1.1.1.2   misho     227:        n = libnet_pblock_append(l, p, (uint8_t*)&key,
1.1       misho     228:                 sizeof(gre_hdr.gre_key));
                    229:        if (n == -1)
                    230:        {
                    231:            /* err msg set in libnet_pblock_append() */
                    232:            goto bad;
                    233:        }
                    234:     }
                    235: 
                    236:     if ((!(fv & GRE_VERSION_MASK) && (fv & GRE_SEQ)) ||                /* v0 */
                    237:        ( (fv & GRE_VERSION_MASK) && (fv & GRE_ACK)) )                 /* v1 */
                    238:     {
                    239:        seq = htonl(seq);
1.1.1.2   misho     240:        n = libnet_pblock_append(l, p, (uint8_t*)&seq, 
1.1       misho     241:                 sizeof(gre_hdr.gre_seq));
                    242:        if (n == -1)
                    243:        {
                    244:            /* err msg set in libnet_pblock_append() */
                    245:            goto bad;
                    246:        }
                    247:     }
                    248: 
1.1.1.2   misho     249:     /* boilerplate payload sanity check / append macro */
                    250:     LIBNET_DO_PAYLOAD(l, p);
1.1       misho     251: 
                    252:     if ( (fv & GRE_CSUM) && (!sum) )
                    253:     {
                    254:        libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
                    255:     }
                    256: 
                    257:     return (ptag ? ptag : libnet_pblock_update(l, p, len, LIBNET_PBLOCK_GRE_H));
                    258: 
                    259: bad:
                    260:     libnet_pblock_delete(l, p);
                    261:     return (-1);
                    262: }
                    263: 
                    264: libnet_ptag_t
1.1.1.2   misho     265: libnet_build_egre(uint16_t fv, uint16_t type, uint16_t sum, 
                    266: uint16_t offset, uint32_t key, uint32_t seq, uint16_t len,
                    267: const uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
1.1       misho     268: {
                    269:     return (libnet_build_gre(fv, type, sum, offset, key, seq, len, 
                    270:            payload, payload_s, l, ptag));
                    271: }
                    272: 
                    273: /*
                    274:  *    Routing (variable)
                    275:  *
                    276:  *      The Routing field is optional and is present only if the Routing
                    277:  *      Present bit is set to 1.
                    278:  *
                    279:  *      The Routing field is a list of Source Route Entries (SREs).  Each
                    280:  *      SRE has the form:
                    281:  *
                    282:  *    0                   1                   2                   3
                    283:  *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
                    284:  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    285:  *   |       Address Family          |  SRE Offset   |  SRE Length   |
                    286:  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    287:  *   |                        Routing Information ...
                    288:  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    289:  *
                    290:  */
                    291: libnet_ptag_t
1.1.1.2   misho     292: libnet_build_gre_sre(uint16_t af, uint8_t offset, uint8_t length, 
                    293: uint8_t *routing, const uint8_t *payload, uint32_t payload_s, libnet_t *l,
1.1       misho     294: libnet_ptag_t ptag)
                    295: {
1.1.1.2   misho     296:     uint32_t n;
1.1       misho     297:     libnet_pblock_t *p;
                    298:     struct libnet_gre_sre_hdr sre_hdr;
                    299: 
                    300:     if (l == NULL)
                    301:     { 
                    302:         return (-1); 
                    303:     }
                    304: 
                    305:     n = LIBNET_GRE_SRE_H + length + payload_s;
                    306: 
                    307:     /*
                    308:      *  Find the existing protocol block if a ptag is specified, or create
                    309:      *  a new one.
                    310:      */
                    311:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_GRE_SRE_H);
                    312:     if (p == NULL)
                    313:     {
                    314:         return (-1);
                    315:     }
                    316:     sre_hdr.af = htons(af);
                    317:     sre_hdr.sre_offset = offset;
                    318:     sre_hdr.sre_length = length;
1.1.1.2   misho     319:     n = libnet_pblock_append(l, p, (uint8_t *)&sre_hdr, LIBNET_GRE_SRE_H);
1.1       misho     320:     if (n == -1)
                    321:     {
                    322:         /* err msg set in libnet_pblock_append() */
                    323:         goto bad; 
                    324:     }
                    325: 
                    326:     if ((routing && !length) || (!routing && length))
                    327:     {
1.1.1.3 ! misho     328:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
        !           329:                  "%s(): routing inconsistency", __func__);
1.1       misho     330:         goto bad;
                    331:     }
                    332: 
                    333:     if (routing && length)
                    334:     {
                    335:         n = libnet_pblock_append(l, p, routing, length);
                    336:         if (n == -1)
                    337:         {
                    338:             /* err msg set in libnet_pblock_append() */
                    339:             goto bad;
                    340:         }
                    341:     }
                    342: 
1.1.1.2   misho     343:     /* boilerplate payload sanity check / append macro */
                    344:     LIBNET_DO_PAYLOAD(l, p);
1.1       misho     345: 
                    346:     return (ptag ? ptag : libnet_pblock_update(l, p, 0, 
                    347:            LIBNET_PBLOCK_GRE_SRE_H));
                    348: 
                    349: bad:
                    350:     libnet_pblock_delete(l, p);
                    351:     return (-1);
                    352: 
                    353: }
                    354: 
                    355: libnet_ptag_t
                    356: libnet_build_gre_last_sre(libnet_t *l, libnet_ptag_t ptag)
                    357: {
1.1.1.2   misho     358:     uint32_t n, zero = 0;
1.1       misho     359:     libnet_pblock_t *p;
                    360: 
                    361:     if (l == NULL)
                    362:     { 
                    363:         return (-1); 
                    364:     }
                    365: 
                    366:     n = LIBNET_GRE_SRE_H;
                    367: 
                    368:     /*
                    369:      *  Find the existing protocol block if a ptag is specified, or create
                    370:      *  a new one.
                    371:      */
                    372:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_GRE_H);
                    373:     if (p == NULL)
                    374:     {
                    375:         return (-1);
                    376:     }
                    377: 
1.1.1.2   misho     378:     n = libnet_pblock_append(l, p, (uint8_t *)&zero, LIBNET_GRE_SRE_H);
1.1       misho     379:     if (n == -1)
                    380:     {
                    381:         /* err msg set in libnet_pblock_append() */
                    382:         goto bad; 
                    383:     }
                    384: 
                    385:     return (ptag ? ptag : libnet_pblock_update(l, p, 0, 
                    386:            LIBNET_PBLOCK_GRE_SRE_H));
                    387: 
                    388: bad:
                    389:     libnet_pblock_delete(l, p);
                    390:     return (-1);
                    391: 
                    392: }
1.1.1.3 ! misho     393: 
        !           394: /**
        !           395:  * Local Variables:
        !           396:  *  indent-tabs-mode: nil
        !           397:  *  c-file-style: "stroustrup"
        !           398:  * End:
        !           399:  */

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