File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libnet / src / libnet_build_gre.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Sep 27 11:11:38 2023 UTC (9 months, 1 week ago) by misho
Branches: libnet, MAIN
CVS tags: v1_2p1, HEAD
Version 1.2p1

    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: #include "common.h"
   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:  */
  103: #if 0
  104: static void
  105: __libnet_print_gre_flags_ver(uint16_t fv)
  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: }
  131: #endif
  132: 
  133: /* FIXME: what is the portability of the "((struct libnet_gre_hdr*)0)->" ? */
  134: uint32_t
  135: libnet_getgre_length(uint16_t fv)
  136: {
  137: 
  138:     uint32_t n = LIBNET_GRE_H;
  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
  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)
  171: {
  172:     uint32_t n;
  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);
  195:     n = libnet_pblock_append(l, p, (uint8_t *)&gre_hdr, LIBNET_GRE_H);
  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);
  206:         n = libnet_pblock_append(l, p, (uint8_t*)&sum,
  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);
  214: 	n = libnet_pblock_append(l, p, (uint8_t*)&offset, 
  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);
  227: 	n = libnet_pblock_append(l, p, (uint8_t*)&key,
  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);
  240: 	n = libnet_pblock_append(l, p, (uint8_t*)&seq, 
  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: 
  249:     /* boilerplate payload sanity check / append macro */
  250:     LIBNET_DO_PAYLOAD(l, p);
  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
  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)
  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
  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,
  294: libnet_ptag_t ptag)
  295: {
  296:     uint32_t n;
  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;
  319:     n = libnet_pblock_append(l, p, (uint8_t *)&sre_hdr, LIBNET_GRE_SRE_H);
  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:     {
  328:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  329:                  "%s(): routing inconsistency", __func__);
  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: 
  343:     /* boilerplate payload sanity check / append macro */
  344:     LIBNET_DO_PAYLOAD(l, p);
  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: {
  358:     uint32_t n, zero = 0;
  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: 
  378:     n = libnet_pblock_append(l, p, (uint8_t *)&zero, LIBNET_GRE_SRE_H);
  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: }
  393: 
  394: /**
  395:  * Local Variables:
  396:  *  indent-tabs-mode: nil
  397:  *  c-file-style: "stroustrup"
  398:  * End:
  399:  */

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