The following two source files comprise the Punch codebase. To preserve readability, we richly comment the code but do not display book-text inside the code. You can download the full source files from this book's companion Web site at http://www.wiley.com/compbooks/schiffman.
/* * $Id: punch.h,v 1.2 2002/03/24 20:06:38 route Exp $ * * Building Open Source Network Security Tools * punch.h - libnet example code * * Copyright (c) 2002 Mike D. Schiffman <mike@infonexus.com> * All rights reserved. * */ #include <libnet.h> /* * Simple way to subtract timeval based timers. Not every OS has this, * so we'll just define it here */ #define PTIMERSUB(tvp, uvp, vvp) do { (vvp)-> tv_sec = (tvp)-> tv_sec - (uvp)-> tv_sec; (vvp)-> tv_usec = (tvp)-> tv_usec - (uvp)->tv_usec; if ( (vvp)-> tv_usec < 0) { (vvp) -> tv_sec-; (vvp) -> tv_usec += 1000000; } } while (0) /* Check the OUI table for this one! */ u_char enet_src[6] = {0x00, 0x50, 0x58, 0x0d, 0x0d, 0x0d}; u_char enet_dst[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; void usage(char *); /* EOF */
/* * $Id: punch.c,v 1.2 2002/03/24 20:06:38 route Exp $ * * Building Open Source Network Security Tools * punch.c - libnet 1.1.0 example code * * Copyright (c) 2002 Mike D. Schiffman <mike@infonexus.com> * All rights reserved. * */ #include "./punch.h" int main(int argc, char **argv) { u_short sleep; libnet_t *1; char *payload; libnet_ptag_t t, udp; int c, fast, timer, build_ip; u_long src_ip, dst_ip; struct timeval r, s , e; struct libnet_stats ls; char dot = '.', bs = '\b'; libnet_plist_t plist, *plist_p; char errbuf[LIBNET_ERRBUF_SIZE]; u_short payload_s, bport, eport, cport; printf("Punch 1.0 [UDP packet shaping/blasting tool] \n"); /* * Power up libnet using the link-layer interface. We're going to * rely on libnet to find a device to use and 'errbuf' will hold * the error if something breaks. */ 1 = libnet_init( LIBNET_LINK, /* injection type */ NULL, /* network interface */ errbuf); /* errbuf */ if (l == NULL) { fprintf(stderr, "libnet_init() failed: %s", errbuf); exit(EXIT_FAILURE); } fast = 0; timer = 1; sleep = 0; src_ip = 0; dst_ip = 0; payload_s = 0; qpayload = NULL; plist_p = NULL; while ((c = getopt(argc, argv, "d:fs:s:p:P:")) != EOF) { switch (c) { case 'd': dst_ip = libnet_name2addr4(1, optarg, LIBNET_RESOLVE); if (dst_ip == -1) { fprintf(stderr, "Bad IP address %s\n", optarg); exit (EXIT_FAILURE); } break; case 'f': fast = 1; break; case 'S' : sleep = atoi(optarg); break; case 's': src_ip = libnet_name2addr4 (1, optarg, LIBNET_RESOLVE); if (src_ip == -1) { fprintf(stderr, "Bad IP address: %s\n", optarg); exit(EXIT_FAILURE); } break; case 'P': /* * Initialize the port list chain. Libnet's expecting * the port list to be specified in the format "x - y, * z" or some combination thereof. */ plist_p = &cplist; if (libnet_plist_chain_new(l, &plist_p, optarg) == -1) { fprintf(stderr, "Bad token: %s\n", libnet_geterror(1)); exit(EXIT_FAILURE); } break; case 'p': payload = optarg; payload_s = strlen(payload); break; default: usage(argv[0]); exit(EXIT_FAILURE); } } if (!src_ip || !dst_ip || !plist_p) { usage(argv[0]); exit(EXIT_FAILURE); } /* initialize these guys */ udp = t = LIBNET_PTAG_INITIALIZER; /* start the loop timer */ if (gettimeofday(&s, NULL) == -1) { fprintf(stderr, "Can't set timer\n"); timer = 0; } /* * Only the first time we run through the loop will we need to * build an IPv4 and an Ethernet header. */ build_ip = 1; /* * Start through the packet sending loop pulling out port list * numbers as we go. This will terminate when we run out of port * list pairs. */ for (; libnet_plist_chain_next_pair (plist_p, &bport, &eport); ) { while (!(bport > eport) && bport != 0) { cport = bport++; /* * Start our packet building process. Remember we have to * the packet in order as it will appear on the wire. We * go from highest protocol to lowest, so we start with * our UDP header (and any user supplied payload data). * Since we're going to be modifying this packet header * throughout the loop, we'll save the ptag 'udp' and * reuse it. */ udp = libnet_build_udp( 1025, /* source port */ cport, /* destination port */ LIBNET_UDP_H + payload_s, /* packet size */ 0, /* checksum */ payload, /* payload */ payload_s, /* payload size */ l, /* libnet context */ udp); /* ptag */ if (udp == -1) { fprintf(stderr, "Can't build UDP header (port %d): %s\n", cport, libnet_geterror(1)); goto bad; } /* * The first time through the loop we'll build an IPv4 and * an Ethernet header. Since we're not going to modify * either one of them again, we only need to do this once. */ if (build_ip) { build_ip = 0; /* * Build the IPv4 header. Note that we have to pass in * the ENTIRE IP packet length, including the IP header * itself. Previous versions of libnet would assume a * length of at least 20 bytes and would add to that * value whatever the app programmer passed in. Also * note the checksum of 0, which tells libnet to * compute the checksum before writing the packet to * the wire. The payload functionality isn't used here * since we havelibnet functionality to build our UDP * header. The ptag 't' is thrown away since we're not * going modify the IP header again. */ t = libnet_build_ipv4( /* total length */ LIBNET_IPV4_H + LIBNET_UDP_H + payload_s, 0, /* type of service */ 242, /* identification */ 0, /* fragmentation * / 64, /* time to live */ IPPROTO_UDP, /* protocol */ 0, /* checksum */ src_ip, /* source */ dst_ip, /* destination */ NULL, /* payload */ 0, /* payload size */ 1, /* libnet context */ 0); /* ptag */ if (t == -1) { fprintf(stderr, "Can't build IP header: %s\n", libnet_geterror(1)); goto bad; } /* * Build the Ethernet header and discard the ptag. */ t = libnet_build_ethernet( enet_dst, /* ethernet destination */ enet_src, /* ethernet source */ ETHERTYPE_IP, /* protocol type */ NULL, /* payload */ 0, /* payload size */ 1, /* libnet context */ 0); /* ptag */ if (t == -1) { fprintf(stderr, "Can't build ethernet header: %s\n", libnet_geterror(1)); goto bad; } } if (sleep) { /* even 1 usec makes a huge difference */ usleep(sleep); } if (fast) { /* this is needed to set up the screen properly */ write(STDERR_FILENO, &dot, 1); } /* * Write the packet to the wire. Libnet will handle the * checksum calculation here for IP (since we're at the * link-layer) and UDP. */ c = libnet_write(1); if (c == -1) { if (fast) { write(STDERR_FILENO, &dot, 1); } else { fprintf(stderr, "write error: %s\n", libnet_geterror(1)); } } else { if (fast) { write(STDERR_FILENO, &bs, 1); } else { fprintf(stderr, "wrote %d byte UDP packet to port %d\n", c, cport); } } } } if (timer) { if (gettimeofday(&e, NULL) == -1) { fprintf(stderr, "Can't set timer\n"); } else { PTIMERSUB(&e, &s, &r); fprintf(stderr, "\nTime spent in loop: %ld.%ld seconds \n", r.tv_sec, r.tv_usec); } } libnet_stats(1, &ls); printf("Packets sent: %ld\nPacket errors: %ld\nBytes written: %ld\n", ls.packets_sent, ls.packet_errors, ls.bytes_written); libnet_destroy(l); return (EXIT_SUCCESS); bad: libnet_destroy(l); return (EXIT_FAILURE); } void usage(char *name) { fprintf (stderr, "usage: %s:\n" "-s ip\t\tSource IP address\n" "-d ip\t\tDestination IP address\n" "-P port list\tUDP port list (x-y,z)\n" "[-f]\t\tFast mode, minimal screen output\n" "[-p payload]\tPayload\n" "[-S usec] \tMicrosecond pause between writing\n", name); } /* EOF */