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

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:  */
                    110: 
                    111: static inline void
                    112: __libnet_print_gre_flags_ver(u_int16_t fv)
                    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: }
                    138: 
                    139: 
                    140: /* FIXME: what is the portability of the "((struct libnet_gre_hdr*)0)->" ? */
                    141: inline u_int32_t
                    142: libnet_getgre_length(u_int16_t fv)
                    143: {
                    144: 
                    145:     u_int32_t n = LIBNET_GRE_H;
                    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
                    175: libnet_build_gre(u_int16_t fv, u_int16_t type, u_int16_t sum, 
                    176: u_int16_t offset, u_int32_t key, u_int32_t seq, u_int16_t len,
                    177: u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
                    178: {
                    179:     u_int32_t n;
                    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);
                    202:     n = libnet_pblock_append(l, p, (u_int8_t *)&gre_hdr, LIBNET_GRE_H);
                    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);
                    213:         n = libnet_pblock_append(l, p, (u_int8_t*)&sum,
                    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);
                    221:        n = libnet_pblock_append(l, p, (u_int8_t*)&offset, 
                    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);
                    234:        n = libnet_pblock_append(l, p, (u_int8_t*)&key,
                    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);
                    247:        n = libnet_pblock_append(l, p, (u_int8_t*)&seq, 
                    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: 
                    256:     if ((payload && !payload_s) || (!payload && payload_s))
                    257:     {
                    258:         sprintf(l->err_buf, "%s(): payload inconsistency\n", __func__);
                    259:         goto bad;
                    260:     }
                    261: 
                    262:     if (payload && payload_s)
                    263:     {
                    264:         n = libnet_pblock_append(l, p, payload, payload_s);
                    265:         if (n == -1)
                    266:         {
                    267:             /* err msg set in libnet_pblock_append() */
                    268:             goto bad;
                    269:         }
                    270:     }
                    271: 
                    272:     if ( (fv & GRE_CSUM) && (!sum) )
                    273:     {
                    274:        libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
                    275:     }
                    276: 
                    277:     return (ptag ? ptag : libnet_pblock_update(l, p, len, LIBNET_PBLOCK_GRE_H));
                    278: 
                    279: bad:
                    280:     libnet_pblock_delete(l, p);
                    281:     return (-1);
                    282: }
                    283: 
                    284: libnet_ptag_t
                    285: libnet_build_egre(u_int16_t fv, u_int16_t type, u_int16_t sum, 
                    286: u_int16_t offset, u_int32_t key, u_int32_t seq, u_int16_t len,
                    287: u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
                    288: {
                    289:     return (libnet_build_gre(fv, type, sum, offset, key, seq, len, 
                    290:            payload, payload_s, l, ptag));
                    291: }
                    292: 
                    293: /*
                    294:  *    Routing (variable)
                    295:  *
                    296:  *      The Routing field is optional and is present only if the Routing
                    297:  *      Present bit is set to 1.
                    298:  *
                    299:  *      The Routing field is a list of Source Route Entries (SREs).  Each
                    300:  *      SRE has the form:
                    301:  *
                    302:  *    0                   1                   2                   3
                    303:  *    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
                    304:  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    305:  *   |       Address Family          |  SRE Offset   |  SRE Length   |
                    306:  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    307:  *   |                        Routing Information ...
                    308:  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    309:  *
                    310:  */
                    311: libnet_ptag_t
                    312: libnet_build_gre_sre(u_int16_t af, u_int8_t offset, u_int8_t length, 
                    313: u_int8_t *routing, u_int8_t *payload, u_int32_t payload_s, libnet_t *l,
                    314: libnet_ptag_t ptag)
                    315: {
                    316:     u_int32_t n;
                    317:     libnet_pblock_t *p;
                    318:     struct libnet_gre_sre_hdr sre_hdr;
                    319: 
                    320:     if (l == NULL)
                    321:     { 
                    322:         return (-1); 
                    323:     }
                    324: 
                    325:     n = LIBNET_GRE_SRE_H + length + payload_s;
                    326: 
                    327:     /*
                    328:      *  Find the existing protocol block if a ptag is specified, or create
                    329:      *  a new one.
                    330:      */
                    331:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_GRE_SRE_H);
                    332:     if (p == NULL)
                    333:     {
                    334:         return (-1);
                    335:     }
                    336:     sre_hdr.af = htons(af);
                    337:     sre_hdr.sre_offset = offset;
                    338:     sre_hdr.sre_length = length;
                    339:     n = libnet_pblock_append(l, p, (u_int8_t *)&sre_hdr, LIBNET_GRE_SRE_H);
                    340:     if (n == -1)
                    341:     {
                    342:         /* err msg set in libnet_pblock_append() */
                    343:         goto bad; 
                    344:     }
                    345: 
                    346:     if ((routing && !length) || (!routing && length))
                    347:     {
                    348:         sprintf(l->err_buf, "%s(): routing inconsistency\n", __func__);
                    349:         goto bad;
                    350:     }
                    351: 
                    352:     if (routing && length)
                    353:     {
                    354:         n = libnet_pblock_append(l, p, routing, length);
                    355:         if (n == -1)
                    356:         {
                    357:             /* err msg set in libnet_pblock_append() */
                    358:             goto bad;
                    359:         }
                    360:     }
                    361: 
                    362:     if ((payload && !payload_s) || (!payload && payload_s))
                    363:     {
                    364:         sprintf(l->err_buf, "%s(): payload inconsistency\n", __func__);
                    365:         goto bad;
                    366:     }
                    367: 
                    368:     if (payload && payload_s)
                    369:     {
                    370:         n = libnet_pblock_append(l, p, payload, payload_s);
                    371:         if (n == -1)
                    372:         {
                    373:             /* err msg set in libnet_pblock_append() */
                    374:             goto bad;
                    375:         }
                    376:     }
                    377: 
                    378:     return (ptag ? ptag : libnet_pblock_update(l, p, 0, 
                    379:            LIBNET_PBLOCK_GRE_SRE_H));
                    380: 
                    381: bad:
                    382:     libnet_pblock_delete(l, p);
                    383:     return (-1);
                    384: 
                    385: }
                    386: 
                    387: libnet_ptag_t
                    388: libnet_build_gre_last_sre(libnet_t *l, libnet_ptag_t ptag)
                    389: {
                    390:     u_int32_t n, zero = 0;
                    391:     libnet_pblock_t *p;
                    392: 
                    393:     if (l == NULL)
                    394:     { 
                    395:         return (-1); 
                    396:     }
                    397: 
                    398:     n = LIBNET_GRE_SRE_H;
                    399: 
                    400:     /*
                    401:      *  Find the existing protocol block if a ptag is specified, or create
                    402:      *  a new one.
                    403:      */
                    404:     p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_GRE_H);
                    405:     if (p == NULL)
                    406:     {
                    407:         return (-1);
                    408:     }
                    409: 
                    410:     n = libnet_pblock_append(l, p, (u_int8_t *)&zero, LIBNET_GRE_SRE_H);
                    411:     if (n == -1)
                    412:     {
                    413:         /* err msg set in libnet_pblock_append() */
                    414:         goto bad; 
                    415:     }
                    416: 
                    417:     return (ptag ? ptag : libnet_pblock_update(l, p, 0, 
                    418:            LIBNET_PBLOCK_GRE_SRE_H));
                    419: 
                    420: bad:
                    421:     libnet_pblock_delete(l, p);
                    422:     return (-1);
                    423: 
                    424: }
                    425: 
                    426: 
                    427: /* EOF */

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