Annotation of embedaddon/libnet/sample/gre.c, revision 1.1.1.3

1.1       misho       1: /*
                      2:  *
                      3:  *  libnet 1.1
                      4:  *  Build a GRE packet
                      5:  *  To view: tcpdump -s 0 -n -X -vvv proto gre
                      6:  *
1.1.1.2   misho       7:  *  Copyright (c) 2003 Frédéric Raynal <pappy@security-labs.org>
1.1       misho       8:  *  All rights reserved.
                      9:  *
                     10:  *
                     11:  *  KNOWN BUG
                     12:  *    the encapsulated headers have wrong checksums. I guess this is due to
                     13:  *    the one pass libnet_pblock_coalesce() which is really to complicated :(
                     14:  *
                     15:  *
                     16:  *  Default packet:
                     17:  *   # ./gre -d 1.2.3.4                
                     18:  *   libnet 1.1 packet shaping: GRE 1701 [link]
                     19:  *   Wrote 78 byte GRE packet; check the wire.
                     20:  *
                     21:  *   18:58:12.112157 192.168.1.2 > 1.2.3.4: gre 198.35.123.50.1234 > 103.69.139.107.53: S [bad tcp cksum 698a!] 16843009:16843009(0) win 32767 (ttl 64, id 242, len 40, bad cksum 0!) (ttl 255, id 255, len 64)
                     22:  *   0x0000   4500 0040 00ff 0000 ff2f f4df c0a8 0102        E..@...../......
                     23:  *   0x0010   0102 0304 0000 0800 4500 0028 00f2 0000        ........E..(....
                     24:  *   0x0020   4006 0000 c623 7b32 6745 8b6b 04d2 0035        @....#{2gE.k...5
                     25:  *   0x0030   0101 0101 0202 0202 5002 7fff 6666 0000        ........P...ff..
                     26:  *
                     27:  *  Packet with a computed checksum 
                     28:  *   # ./gre -d 1.2.3.4 -c 0
                     29:  *   libnet 1.1 packet shaping: GRE 1701 [link]
                     30:  *   Wrote 82 byte GRE packet; check the wire.
                     31:  *   
                     32:  *   18:58:22.587513 192.168.1.2 > 1.2.3.4: gre [Cv0] C:7c62 198.35.123.50.1234 > 103.69.139.107.53: S [bad tcp cksum 698a!] 16843009:16843009(0) win 32767 (ttl 64, id 242, len 40, bad cksum 0!) (ttl 255, id 255, len 68)
                     33:  *   0x0000   4500 0044 00ff 0000 ff2f f4db c0a8 0102        E..D...../......
                     34:  *   0x0010   0102 0304 8000 0800 7c62 0000 4500 0028        ........|b..E..(
                     35:  *   0x0020   00f2 0000 4006 0000 c623 7b32 6745 8b6b        ....@....#{2gE.k
                     36:  *   0x0030   04d2 0035 0101 0101 0202 0202 5002 7fff        ...5........P...
                     37:  *   0x0040   6666 0000                                      ff..
                     38:  *
                     39:  *
                     40:  *  Packet with a forced checksum 
                     41:  *   # ./gre -d 1.2.3.4 -c 6666
                     42:  *   libnet 1.1 packet shaping: GRE 1701 [link]
                     43:  *   Wrote 68 byte GRE packet; check the wire.
                     44:  *   
                     45:  *   19:04:12.108080 192.168.1.2 > 1.2.3.4: gre [Cv0] C:1a0a 198.35.123.50.1234 > 103.69.139.107.53: S [bad tcp cksum 698a!] 16843009:16843009(0) win 32767 (ttl 64, id 242, len 40, bad cksum 0!) (ttl 255, id 255, len 68)
                     46:  *   0x0000   4500 0044 00ff 0000 ff2f f4db c0a8 0102        E..D...../......
                     47:  *   0x0010   0102 0304 8000 0800 1a0a 0000 4500 0028        ............E..(
                     48:  *   0x0020   00f2 0000 4006 0000 c623 7b32 6745 8b6b        ....@....#{2gE.k
                     49:  *   0x0030   04d2 0035 0101 0101 0202 0202 5002 7fff        ...5........P...
                     50:  *   0x0040   6666 0000                                      ff..
                     51:  *
                     52:  *
                     53:  * 
                     54:  *
                     55:  * Redistribution and use in source and binary forms, with or without
                     56:  * modification, are permitted provided that the following conditions
                     57:  * are met:
                     58:  * 1. Redistributions of source code must retain the above copyright
                     59:  *    notice, this list of conditions and the following disclaimer.
                     60:  * 2. Redistributions in binary form must reproduce the above copyright
                     61:  *    notice, this list of conditions and the following disclaimer in the
                     62:  *    documentation and/or other materials provided with the distribution.
                     63:  *
                     64:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     65:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     66:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     67:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     68:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     69:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     70:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     71:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     72:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     73:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     74:  * SUCH DAMAGE.
                     75:  *
                     76:  */
                     77: 
                     78: #if (HAVE_CONFIG_H)
                     79: #include "../include/config.h"
                     80: #endif
                     81: #include "./libnet_test.h"
                     82: 
                     83: 
                     84: void
                     85: usage(char *prog)
                     86: {
                     87:     fprintf(stderr, "Usage: %s\n", prog);
                     88:     fprintf(stderr, "\t IP options:  -d <dst ip> [-s src ip]\n");
                     89:     fprintf(stderr, "\t GRE options: [-v] set RFC 2637 mode (PPP in GRE) (default is RFC 1701 for IP in GRE)\n");
                     90:     fprintf(stderr, "\t\t RFC 1701 options (IP in GRE):\n");
                     91:     fprintf(stderr, "\t\t   [-c sum]  [-r routing] [-k key] [-n seqnum]\n");
                     92:     fprintf(stderr, "\t\t   IP in GRE options: [-S src ip]  [-D dst ip]\n");
                     93:     fprintf(stderr, "\t\t RFC 2637 options (PPP in GRE):\n");
                     94:     fprintf(stderr, "\t\t   [-a ack]\n");
                     95:     
                     96:     exit(1);
                     97: }
                     98: 
                     99: /*
                    100:  *                ---------------------------------
                    101:  *                |       Delivery Header         |
                    102:  *                ---------------------------------
                    103:  *                |       GRE Header              |
                    104:  *               ---------------------------------
                    105:  *                |       Payload packet          |
                    106:  *                ---------------------------------
                    107:  */
                    108: int
                    109: main(int argc, char *argv[])
                    110: {
                    111:     char c;
                    112:     libnet_t *l;
                    113:     char errbuf[LIBNET_ERRBUF_SIZE];
                    114:     u_long src_ip = 0, dst_ip = 0, gre_src_ip = 0, gre_dst_ip = 0;
                    115:     u_short checksum = 0, offset = 0;
                    116:     u_char *routing = NULL;
                    117:     u_long key = 0, seq = 0;
                    118:     u_short gre_flags = 0;
                    119:     u_long len;
                    120:     u_long size = 0;
                    121:     libnet_ptag_t t;
                    122: 
                    123:     printf("libnet 1.1 packet shaping: GRE [link]\n");
                    124:     
                    125:     /*
                    126:      *  Initialize the library.  Root priviledges are required.
                    127:      */
                    128:     l = libnet_init(
                    129:             LIBNET_LINK,                            /* injection type */
                    130:             NULL,                                   /* network interface */
                    131:             errbuf);                                /* error buffer */
                    132:   
                    133:     if (!l)
                    134:     {
                    135:         fprintf(stderr, "libnet_init: %s", errbuf);
                    136:         exit(EXIT_FAILURE);
                    137:     }
                    138: 
                    139:     /*
                    140:      * parse options
                    141:      */
                    142:     while ((c = getopt(argc, argv, "d:s:D:S:c:r:k:n:va:")) != EOF)
                    143:     {
                    144:         switch (c)
                    145:         {
                    146:            
                    147:             case 'd':
                    148:                 if ((dst_ip = libnet_name2addr4(l, optarg, LIBNET_RESOLVE)) == -1)
                    149:                 {
                    150:                     fprintf(stderr, "Bad destination IP address: %s\n", optarg);
                    151:                     exit(EXIT_FAILURE);
                    152:                 }
                    153:                 break;
                    154:             case 's':
                    155:                 if ((src_ip = libnet_name2addr4(l, optarg, LIBNET_RESOLVE)) == -1)
                    156:                 {
                    157:                     fprintf(stderr, "Bad source IP address: %s\n", optarg);
                    158:                     exit(EXIT_FAILURE);
                    159:                 }
                    160:                 break;
                    161:             case 'D':
                    162:                 if ((gre_dst_ip = libnet_name2addr4(l, optarg, LIBNET_RESOLVE)) == -1)
                    163:                 {
                    164:                     fprintf(stderr, "Bad destination IP address (GRE): %s\n", optarg);
                    165:                     exit(EXIT_FAILURE);
                    166:                 }
                    167:                 break;
                    168:             case 'S':
                    169:                 if ((gre_src_ip = libnet_name2addr4(l, optarg, LIBNET_RESOLVE)) == -1)
                    170:                 {
                    171:                     fprintf(stderr, "Bad source IP address (GRE): %s\n", optarg);
                    172:                     exit(EXIT_FAILURE);
                    173:                 }
                    174:                 break;
                    175:            case 'c':
                    176:                checksum = atoi(optarg);
                    177:                gre_flags|=GRE_CSUM;
                    178:                 break;
                    179:            case 'r':
1.1.1.3 ! misho     180:                routing = (u_char *)optarg;
1.1       misho     181:                gre_flags|=GRE_ROUTING;
                    182:                 break;
                    183:            case 'k':
                    184:                key = atoi(optarg);
                    185:                gre_flags|=GRE_KEY;
                    186:                 break;
                    187:            case 'n':
                    188:                seq = atoi(optarg);
                    189:                gre_flags|=GRE_SEQ;
                    190:                 break;
                    191:            case 'v':
                    192:                gre_flags|=(GRE_VERSION_1|GRE_KEY);
                    193:                break;
                    194:            case 'a':
                    195:                if (! (gre_flags & GRE_VERSION_1))
                    196:                    usage(argv[0]);
                    197:                seq = atoi(optarg);    /* seq in v0 is ack in v1 */
                    198:                gre_flags|=GRE_ACK;
                    199:                break;
                    200:             default:
                    201:                 exit(EXIT_FAILURE);
                    202:         }
                    203:     }
                    204: 
                    205:     /*
                    206:      * check options 
                    207:      */
                    208:     if (!dst_ip)
                    209:     {
                    210:        usage(argv[0]);
                    211:     }
                    212: 
                    213:     if (!src_ip)
                    214:     {
                    215:        src_ip = libnet_get_ipaddr4(l);
                    216:     }
                    217: 
                    218:     if (!gre_dst_ip)
                    219:     {
                    220:        gre_dst_ip = libnet_get_prand(LIBNET_PRu32);
                    221:     }
                    222: 
                    223:     if (!gre_src_ip)
                    224:     {
                    225:        gre_src_ip = libnet_get_prand(LIBNET_PRu32);
                    226:     }
                    227: 
                    228: 
                    229:     if ( (gre_flags & GRE_VERSION_MASK) == 0)
                    230:     {
                    231:        /*
                    232:         * Build a TCP/IP packet embedded in GRE message
                    233:         */
                    234:        size = LIBNET_TCP_H;
                    235:        t = libnet_build_tcp(
                    236:            1234,                                       /* source port */
                    237:            53,                                         /* destination port */
                    238:            0x01010101,                                 /* sequence number */
                    239:            0x02020202,                                 /* acknowledgement num */
                    240:            TH_SYN,                                     /* control flags */
                    241:            32767,                                      /* window size */
                    242:            0,                                          /* checksum */
                    243:            0,                                          /* urgent pointer */
                    244:            size,                                       /* TCP packet size */
                    245:            NULL,                                       /* payload */
                    246:            0,                                          /* payload size */
                    247:            l,                                          /* libnet handle */
                    248:            0);                                         /* libnet id */
                    249:        if (t == -1)
                    250:        {
                    251:            fprintf(stderr, "Can't build TCP header (GRE): %s\n", libnet_geterror(l));
                    252:            goto bad;
                    253:        }
                    254:        
                    255:        size += LIBNET_IPV4_H;
                    256:        t = libnet_build_ipv4(
                    257:            size,                                       /* length */
                    258:            0,                                          /* TOS */
                    259:            242,                                        /* IP ID */
                    260:            0,                                          /* IP Frag */
                    261:            64,                                         /* TTL */
                    262:            IPPROTO_TCP,                                /* protocol */
                    263:            0,                                          /* checksum */
                    264:            gre_src_ip,                                 /* source IP */
                    265:            gre_dst_ip,                                 /* destination IP */
                    266:            NULL,                                       /* payload */
                    267:            0,                                          /* payload size */
                    268:            l,                                          /* libnet handle */
                    269:            0);                                         /* libnet id */
                    270:        if (t == -1)
                    271:        {
                    272:            fprintf(stderr, "Can't build IP header (GRE): %s\n", libnet_geterror(l));
                    273:            goto bad;
                    274:        } 
                    275:     }
                    276: 
                    277:     if ( (gre_flags & GRE_VERSION_MASK) == 1)
                    278:     {
                    279:        offset = libnet_get_prand(LIBNET_PRu16);
                    280:        if (~gre_flags & GRE_ACK)
                    281:        {
                    282:            u_char ppp[4] = "\x00\x01"; /* PPP padding */
                    283:            checksum = 2; /* checksum is in fact payload_s in PPP/GRE (v1) */
                    284:            size = 2;
                    285:            gre_flags|=GRE_SEQ;
                    286:            key = libnet_get_prand(LIBNET_PRu32);
                    287: 
                    288:            /*
                    289:             * Build a PPP packet embedded in GRE message
                    290:             */
                    291:            t = libnet_build_data(
                    292:                ppp,
                    293:                checksum,
                    294:                l, 
                    295:                0
                    296:            );
                    297:            if (t == -1)
                    298:            {
                    299:                fprintf(stderr, "Can't build PPP header (GRE): %s\n", libnet_geterror(l));
                    300:                goto bad;
                    301:            }
                    302:        }
                    303:        gre_flags&=~(GRE_CSUM|GRE_ROUTING);
                    304:     }
                    305: 
                    306:     /*
                    307:      * Build the GRE message
                    308:      */
                    309:     if (gre_flags & GRE_ROUTING)
                    310:     {
                    311:        /* as packet are stacked, start by the last one, ie null sre */
                    312:        size += LIBNET_GRE_SRE_H;
                    313:        t = libnet_build_gre_last_sre(l, 0);
                    314:        if (t == -1)
                    315:        {
                    316:            fprintf(stderr, "Can't build GRE last SRE header: %s\n", libnet_geterror(l));
                    317:            goto bad;
                    318:        }
1.1.1.3 ! misho     319:        size += LIBNET_GRE_SRE_H + strlen((char *)routing);
1.1       misho     320:        t = libnet_build_gre_sre(
                    321:            GRE_IP,                                 /* address family */
                    322:            0,                                      /* offset */
1.1.1.3 ! misho     323:            strlen((char *)routing),                /* routing length */
1.1       misho     324:            routing,                                /* routing info */
                    325:            NULL,                                   /* payload */
                    326:            0,                                      /* payload size */
                    327:            l,                                      /* libnet handle */
                    328:            0);                                     /* libnet id */
                    329:        if (t == -1)
                    330:        {
                    331:            fprintf(stderr, "Can't build GRE last SRE header: %s\n", libnet_geterror(l));
                    332:            goto bad;
                    333:        }
                    334:     }
                    335: 
                    336:     len = libnet_getgre_length(gre_flags);
                    337:     size += len;
                    338:     t = libnet_build_gre(
                    339:         gre_flags,                                  /* flags & version */
                    340:         (gre_flags & GRE_VERSION_1 ? GRE_PPP : GRE_IP), /* type */
                    341:         checksum,                                   /* v0: checksum / v1: payload_s */
                    342:         offset,                                     /* v0: offset   / v1: callID    */
                    343:         key,                                        /* v0: key      / v1: seq bum   */
                    344:         seq,                                        /* v0: seq num  / v1: ack       */
                    345:        size,                                       /* length */
                    346:         NULL,                                       /* payload */
                    347:         0,                                          /* payload size */
                    348:         l,                                          /* libnet handle */
                    349:         0);                                         /* libnet id */
                    350:     if (t == -1)
                    351:     {
                    352:         fprintf(stderr, "Can't build GRE header: %s\n", libnet_geterror(l));
                    353:         goto bad;
                    354:     }
                    355: 
                    356:     
                    357:     /*
                    358:      * Build the "real" IP header
                    359:      */
                    360:     size+=LIBNET_IPV4_H;
                    361:     t = libnet_build_ipv4(
                    362:         size,                                       /* length */
                    363:         0,                                          /* TOS */
                    364:         255,                                        /* IP ID */
                    365:         0,                                          /* IP Frag */
                    366:         255,                                        /* TTL */
                    367:         IPPROTO_GRE,                                /* protocol */
                    368:         0,                                          /* checksum */
                    369:         src_ip,                                     /* source IP */
                    370:         dst_ip,                                     /* destination IP */
                    371:         NULL,                                       /* payload */
                    372:         0,                                          /* payload size */
                    373:         l,                                          /* libnet handle */
                    374:         0);                                         /* libnet id */
                    375:     if (t == -1)
                    376:     {
                    377:         fprintf(stderr, "Can't build IP header (GRE): %s\n", libnet_geterror(l));
                    378:         goto bad;
                    379:     } 
                    380: 
                    381:     t = libnet_autobuild_ethernet(
1.1.1.3 ! misho     382:             (uint8_t *)"11:11:11:11:11:11",         /* ethernet destination */
        !           383:             ETHERTYPE_IP,                           /* protocol type */
1.1       misho     384:             l);                                     /* libnet handle */
                    385:     if (t == -1)
                    386:     {
                    387:         fprintf(stderr, "Can't build ethernet header: %s\n",
                    388:                 libnet_geterror(l));
                    389:         goto bad;
                    390:     }
                    391:     /*
                    392:      *  Write it to the wire.
                    393:      */
                    394: 
                    395:     c = libnet_write(l);
                    396:     if (c == -1)
                    397:     {
                    398:         fprintf(stderr, "Write error: %s\n", libnet_geterror(l));
                    399:         goto bad;
                    400:     }
                    401:     else
                    402:     {
                    403:         fprintf(stderr, "Wrote %d byte GRE packet; check the wire.\n", c);
                    404:     }
                    405:     libnet_destroy(l);
                    406:     return (EXIT_SUCCESS);
                    407: bad:
                    408:     libnet_destroy(l);
                    409:     return (EXIT_FAILURE); 
                    410: }

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