Annotation of embedaddon/libnet/src/libnet_build_gre.c, revision 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>