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

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: 
                     31: #if (HAVE_CONFIG_H)
                     32: #include "../include/config.h"
                     33: #endif
                     34: #if (!(_WIN32) || (__CYGWIN__)) 
                     35: #include "../include/libnet.h"
                     36: #else
                     37: #include "../include/win32/libnet.h"
                     38: #endif
                     39: 
                     40: /*
                     41:  * Overall packet
                     42:  *
                     43:  *  The entire encapsulated packet would then have the form:
                     44:  *
                     45:  *                  ---------------------------------
                     46:  *                  |                               |
                     47:  *                  |       Delivery Header         |
                     48:  *                  |                               |
                     49:  *                  ---------------------------------
                     50:  *                  |                               |
                     51:  *                  |       GRE Header              |
                     52:  *                  |                               |
                     53:  *                  ---------------------------------
                     54:  *                  |                               |
                     55:  *                  |       Payload packet          |
                     56:  *                  |                               |
                     57:  *                  ---------------------------------
                     58:  *
                     59:  * RFC 1701 defines a header. 
                     60:  * A new RFC (2784) has changed the header and proposed to remove the key 
                     61:  * and seqnum.
                     62:  * A newer RFC (2890) has changed the header proposed in RFC 2784 by putting
                     63:  * back key and seqnum.
                     64:  * These will be supported the day IETF'guys stop this mess !
                     65:  *
                     66:  *   FR
                     67:  */
                     68: 
                     69: 
                     70: /* 
                     71:  * Generic Routing Encapsulation (GRE) 
                     72:  * RFC 1701 http://www.faqs.org/rfcs/rfc1701.html
                     73:  *                                
                     74:  *
                     75:  * Packet header
                     76:  *
                     77:  *   The GRE packet header has the form:
                     78:  *
                     79:  *       0                   1                   2                   3
                     80:  *       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
                     81:  *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     82:  *      |C|R|K|S|s|Recur|  Flags  | Ver |         Protocol Type         |
                     83:  *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     84:  *      |      Checksum (optional)      |       Offset (optional)       |
                     85:  *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     86:  *      |                         Key (optional)                        |
                     87:  *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     88:  *      |                    Sequence Number (optional)                 |
                     89:  *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     90:  *      |                         Routing (optional)                    |
                     91:  *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     92:  *
                     93:  * Enhanced GRE header
                     94:  *
                     95:  *   See rfc 2637 for details. It is used for PPTP tunneling.
                     96:  * 
                     97:  *          0                   1                   2                   3
                     98:  *          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
                     99:  *         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    100:  *         |C|R|K|S|s|Recur|A| Flags | Ver |         Protocol Type         |
                    101:  *         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    102:  *         |    Key (HW) Payload Length    |       Key (LW) Call ID        |
                    103:  *         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    104:  *         |                  Sequence Number (Optional)                   |
                    105:  *         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    106:  *         |               Acknowledgment Number (Optional)                |
                    107:  *         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    108:  *      
                    109:  */
1.1.1.2 ! misho     110: #if 0
        !           111: static void
        !           112: __libnet_print_gre_flags_ver(uint16_t fv)
1.1       misho     113: {
                    114:     printf("version = %d (%d) -> ",
                    115:         fv & GRE_VERSION_MASK, libnet_getgre_length(fv));
                    116:     if (fv & GRE_CSUM)
                    117:     {
                    118:         printf("CSUM ");
                    119:     }
                    120:     if (fv & GRE_ROUTING)
                    121:     {
                    122:         printf("ROUTING ");
                    123:     }
                    124:     if (fv & GRE_KEY)
                    125:     {
                    126:         printf("KEY ");
                    127:     }
                    128:     if (fv & GRE_SEQ)
                    129:     {
                    130:         printf("SEQ ");
                    131:     }
                    132:     if (fv & GRE_ACK)
                    133:     {
                    134:         printf("ACK ");
                    135:     }
                    136:     printf("\n");
                    137: }
1.1.1.2 ! misho     138: #endif
1.1       misho     139: 
                    140: /* FIXME: what is the portability of the "((struct libnet_gre_hdr*)0)->" ? */
1.1.1.2 ! misho     141: uint32_t
        !           142: libnet_getgre_length(uint16_t fv)
1.1       misho     143: {
                    144: 
1.1.1.2 ! misho     145:     uint32_t n = LIBNET_GRE_H;
1.1       misho     146:     /*
                    147:      * If either the Checksum Present bit or the Routing Present bit are
                    148:      * set, BOTH the Checksum and Offset fields are present in the GRE
                    149:      * packet.
                    150:      */
                    151: 
                    152:     if ((!(fv & GRE_VERSION_MASK) && (fv & (GRE_CSUM|GRE_ROUTING))) || /* v0 */
                    153:        (fv & GRE_VERSION_MASK) )                                      /* v1 */
                    154:     {
                    155:        n += sizeof( ((struct libnet_gre_hdr *)0)->gre_sum) + 
                    156:            sizeof( ((struct libnet_gre_hdr *)0)->gre_offset);
                    157:     }
                    158: 
                    159:     if ((!(fv & GRE_VERSION_MASK) && (fv & GRE_KEY)) ||                /* v0 */
                    160:        ( (fv & GRE_VERSION_MASK) && (fv & GRE_SEQ)) )                 /* v1 */
                    161:     {
                    162:        n += sizeof( ((struct libnet_gre_hdr *)0)->gre_key);
                    163:     }
                    164: 
                    165:     if ((!(fv & GRE_VERSION_MASK) && (fv & GRE_SEQ)) ||                /* v0 */
                    166:        ( (fv & GRE_VERSION_MASK) && (fv & GRE_ACK)) )                 /* v1 */
                    167:     {
                    168:        n += sizeof( ((struct libnet_gre_hdr *)0)->gre_seq );
                    169:     }
                    170: 
                    171:     return (n);
                    172: }
                    173: 
                    174: libnet_ptag_t
1.1.1.2 ! misho     175: libnet_build_gre(uint16_t fv, uint16_t type, uint16_t sum, 
        !           176: uint16_t offset, uint32_t key, uint32_t seq, uint16_t len,
        !           177: const uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
1.1       misho     178: {
1.1.1.2 ! misho     179:     uint32_t n;
1.1       misho     180:     libnet_pblock_t *p;
                    181:     struct libnet_gre_hdr gre_hdr;
                    182: 
                    183:     if (l == NULL)
                    184:     { 
                    185:         return (-1); 
                    186:     }
                    187: 
                    188:     n = libnet_getgre_length(fv) + payload_s;
                    189: 
                    190:     /*
                    191:      *  Find the existing protocol block if a ptag is specified, or create
                    192:      *  a new one.
                    193:      */
                    194:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_GRE_H);
                    195:     if (p == NULL)
                    196:     {
                    197:         return (-1);
                    198:     }
                    199: 
                    200:     gre_hdr.flags_ver = htons(fv);
                    201:     gre_hdr.type      = htons(type);
1.1.1.2 ! misho     202:     n = libnet_pblock_append(l, p, (uint8_t *)&gre_hdr, LIBNET_GRE_H);
1.1       misho     203:     if (n == -1)
                    204:     {
                    205:         /* err msg set in libnet_pblock_append() */
                    206:         goto bad; 
                    207:     }
                    208: 
                    209:     if ((!(fv & GRE_VERSION_MASK) && (fv & (GRE_CSUM|GRE_ROUTING))) || /* v0 */
                    210:        (fv & GRE_VERSION_MASK))                                       /* v1 */
                    211:     {
                    212:         sum = htons(sum);
1.1.1.2 ! misho     213:         n = libnet_pblock_append(l, p, (uint8_t*)&sum,
1.1       misho     214:                 sizeof(gre_hdr.gre_sum));
                    215:        if (n == -1)
                    216:        {
                    217:            /* err msg set in libnet_pblock_append() */
                    218:            goto bad;
                    219:        }
                    220:        offset = htons(offset);
1.1.1.2 ! misho     221:        n = libnet_pblock_append(l, p, (uint8_t*)&offset, 
1.1       misho     222:                 sizeof(gre_hdr.gre_offset));
                    223:        if (n == -1)
                    224:        {
                    225:            /* err msg set in libnet_pblock_append() */
                    226:            goto bad;
                    227:        }
                    228:     }
                    229: 
                    230:     if ((!(fv & GRE_VERSION_MASK) && (fv & GRE_KEY)) ||                /* v0 */
                    231:        ( (fv & GRE_VERSION_MASK) && (fv & GRE_SEQ)) )                 /* v1 */
                    232:     {
                    233:        key = htonl(key);
1.1.1.2 ! misho     234:        n = libnet_pblock_append(l, p, (uint8_t*)&key,
1.1       misho     235:                 sizeof(gre_hdr.gre_key));
                    236:        if (n == -1)
                    237:        {
                    238:            /* err msg set in libnet_pblock_append() */
                    239:            goto bad;
                    240:        }
                    241:     }
                    242: 
                    243:     if ((!(fv & GRE_VERSION_MASK) && (fv & GRE_SEQ)) ||                /* v0 */
                    244:        ( (fv & GRE_VERSION_MASK) && (fv & GRE_ACK)) )                 /* v1 */
                    245:     {
                    246:        seq = htonl(seq);
1.1.1.2 ! misho     247:        n = libnet_pblock_append(l, p, (uint8_t*)&seq, 
1.1       misho     248:                 sizeof(gre_hdr.gre_seq));
                    249:        if (n == -1)
                    250:        {
                    251:            /* err msg set in libnet_pblock_append() */
                    252:            goto bad;
                    253:        }
                    254:     }
                    255: 
1.1.1.2 ! misho     256:     /* boilerplate payload sanity check / append macro */
        !           257:     LIBNET_DO_PAYLOAD(l, p);
1.1       misho     258: 
                    259:     if ( (fv & GRE_CSUM) && (!sum) )
                    260:     {
                    261:        libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
                    262:     }
                    263: 
                    264:     return (ptag ? ptag : libnet_pblock_update(l, p, len, LIBNET_PBLOCK_GRE_H));
                    265: 
                    266: bad:
                    267:     libnet_pblock_delete(l, p);
                    268:     return (-1);
                    269: }
                    270: 
                    271: libnet_ptag_t
1.1.1.2 ! misho     272: libnet_build_egre(uint16_t fv, uint16_t type, uint16_t sum, 
        !           273: uint16_t offset, uint32_t key, uint32_t seq, uint16_t len,
        !           274: const uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
1.1       misho     275: {
                    276:     return (libnet_build_gre(fv, type, sum, offset, key, seq, len, 
                    277:            payload, payload_s, l, ptag));
                    278: }
                    279: 
                    280: /*
                    281:  *    Routing (variable)
                    282:  *
                    283:  *      The Routing field is optional and is present only if the Routing
                    284:  *      Present bit is set to 1.
                    285:  *
                    286:  *      The Routing field is a list of Source Route Entries (SREs).  Each
                    287:  *      SRE has the form:
                    288:  *
                    289:  *    0                   1                   2                   3
                    290:  *    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
                    291:  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    292:  *   |       Address Family          |  SRE Offset   |  SRE Length   |
                    293:  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    294:  *   |                        Routing Information ...
                    295:  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    296:  *
                    297:  */
                    298: libnet_ptag_t
1.1.1.2 ! misho     299: libnet_build_gre_sre(uint16_t af, uint8_t offset, uint8_t length, 
        !           300: uint8_t *routing, const uint8_t *payload, uint32_t payload_s, libnet_t *l,
1.1       misho     301: libnet_ptag_t ptag)
                    302: {
1.1.1.2 ! misho     303:     uint32_t n;
1.1       misho     304:     libnet_pblock_t *p;
                    305:     struct libnet_gre_sre_hdr sre_hdr;
                    306: 
                    307:     if (l == NULL)
                    308:     { 
                    309:         return (-1); 
                    310:     }
                    311: 
                    312:     n = LIBNET_GRE_SRE_H + length + payload_s;
                    313: 
                    314:     /*
                    315:      *  Find the existing protocol block if a ptag is specified, or create
                    316:      *  a new one.
                    317:      */
                    318:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_GRE_SRE_H);
                    319:     if (p == NULL)
                    320:     {
                    321:         return (-1);
                    322:     }
                    323:     sre_hdr.af = htons(af);
                    324:     sre_hdr.sre_offset = offset;
                    325:     sre_hdr.sre_length = length;
1.1.1.2 ! misho     326:     n = libnet_pblock_append(l, p, (uint8_t *)&sre_hdr, LIBNET_GRE_SRE_H);
1.1       misho     327:     if (n == -1)
                    328:     {
                    329:         /* err msg set in libnet_pblock_append() */
                    330:         goto bad; 
                    331:     }
                    332: 
                    333:     if ((routing && !length) || (!routing && length))
                    334:     {
                    335:         sprintf(l->err_buf, "%s(): routing inconsistency\n", __func__);
                    336:         goto bad;
                    337:     }
                    338: 
                    339:     if (routing && length)
                    340:     {
                    341:         n = libnet_pblock_append(l, p, routing, length);
                    342:         if (n == -1)
                    343:         {
                    344:             /* err msg set in libnet_pblock_append() */
                    345:             goto bad;
                    346:         }
                    347:     }
                    348: 
1.1.1.2 ! misho     349:     /* boilerplate payload sanity check / append macro */
        !           350:     LIBNET_DO_PAYLOAD(l, p);
1.1       misho     351: 
                    352:     return (ptag ? ptag : libnet_pblock_update(l, p, 0, 
                    353:            LIBNET_PBLOCK_GRE_SRE_H));
                    354: 
                    355: bad:
                    356:     libnet_pblock_delete(l, p);
                    357:     return (-1);
                    358: 
                    359: }
                    360: 
                    361: libnet_ptag_t
                    362: libnet_build_gre_last_sre(libnet_t *l, libnet_ptag_t ptag)
                    363: {
1.1.1.2 ! misho     364:     uint32_t n, zero = 0;
1.1       misho     365:     libnet_pblock_t *p;
                    366: 
                    367:     if (l == NULL)
                    368:     { 
                    369:         return (-1); 
                    370:     }
                    371: 
                    372:     n = LIBNET_GRE_SRE_H;
                    373: 
                    374:     /*
                    375:      *  Find the existing protocol block if a ptag is specified, or create
                    376:      *  a new one.
                    377:      */
                    378:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_GRE_H);
                    379:     if (p == NULL)
                    380:     {
                    381:         return (-1);
                    382:     }
                    383: 
1.1.1.2 ! misho     384:     n = libnet_pblock_append(l, p, (uint8_t *)&zero, LIBNET_GRE_SRE_H);
1.1       misho     385:     if (n == -1)
                    386:     {
                    387:         /* err msg set in libnet_pblock_append() */
                    388:         goto bad; 
                    389:     }
                    390: 
                    391:     return (ptag ? ptag : libnet_pblock_update(l, p, 0, 
                    392:            LIBNET_PBLOCK_GRE_SRE_H));
                    393: 
                    394: bad:
                    395:     libnet_pblock_delete(l, p);
                    396:     return (-1);
                    397: 
                    398: }
                    399: /* EOF */

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