diff options
Diffstat (limited to 'libnet/sample/dhcp_discover.c')
-rw-r--r-- | libnet/sample/dhcp_discover.c | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/libnet/sample/dhcp_discover.c b/libnet/sample/dhcp_discover.c new file mode 100644 index 0000000..60710b1 --- /dev/null +++ b/libnet/sample/dhcp_discover.c @@ -0,0 +1,257 @@ +/* + * $Id: dhcp_discover.c,v 1.3 2004/01/03 20:31:01 mike Exp $ + * + * libnet 1.1 + * Build a DHCP discover packet + * To view: /usr/sbin/tcpdump -vvvvven -s 4096 'port 67 or port 68' + * + * Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#if (HAVE_CONFIG_H) +#include "../include/config.h" +#endif +#include "./libnet_test.h" +#ifdef __WIN32__ +#include "../include/win32/getopt.h" +#endif + +void +usage(char *prog) +{ + fprintf(stderr, "Usage: %s interface\n", prog); + exit(1); +} + + +int +main(int argc, char *argv[]) +{ + char *intf; + u_long src_ip, options_len, orig_len; + int i; + + libnet_t *l; + libnet_ptag_t t; + libnet_ptag_t ip; + libnet_ptag_t udp; + libnet_ptag_t dhcp; + struct libnet_ether_addr *ethaddr; + struct libnet_stats ls; + + char errbuf[LIBNET_ERRBUF_SIZE]; + + u_char options_req[] = { LIBNET_DHCP_SUBNETMASK , LIBNET_DHCP_BROADCASTADDR , LIBNET_DHCP_TIMEOFFSET , LIBNET_DHCP_ROUTER , LIBNET_DHCP_DOMAINNAME , LIBNET_DHCP_DNS , LIBNET_DHCP_HOSTNAME }; + u_char *options; + u_char enet_dst[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + u_char *tmp; + + // have to specify interface + if (argc != 2) + usage(argv[0]); + intf = argv[1]; + + l = libnet_init( + LIBNET_LINK, // injection type + intf, // network interface + errbuf); // errbuf + if (!l) + { + fprintf(stderr, "libnet_init: %s", errbuf); + exit(EXIT_FAILURE); + } + else { + src_ip = libnet_get_ipaddr4(l);; + + if ((ethaddr = libnet_get_hwaddr(l)) == NULL) + { + fprintf(stderr, "libnet_get_hwaddr: %s\n", libnet_geterror(l)); + exit(EXIT_FAILURE); + } + + printf("ip addr : %s\n", libnet_addr2name4(src_ip, LIBNET_DONT_RESOLVE)); + printf("eth addr : "); + for (i = 0; i < 6; i++) { + printf("%2.2x", ethaddr->ether_addr_octet[i]); + if (i != 5) { + printf(":"); + } + } + printf("\n"); + + + // build options packet + i = 0; + options_len = 3; // update total payload size + + // we are a discover packet + options = malloc(3); + options[i++] = LIBNET_DHCP_MESSAGETYPE; // type + options[i++] = 1; // len + options[i++] = LIBNET_DHCP_MSGDISCOVER; // data + + orig_len = options_len; + options_len += sizeof(options_req) + 2; // update total payload size + + // workaround for realloc on old machines + // options = realloc(options, options_len); // resize options buffer + tmp = malloc(options_len); + memcpy(tmp, options, orig_len); + free(options); + options = tmp; + + // we are going to request some parameters + options[i++] = LIBNET_DHCP_PARAMREQUEST; // type + options[i++] = sizeof(options_req); // len + memcpy(options + i, options_req, sizeof(options_req)); // data + i += sizeof(options_req); + + // if we have an ip already, let's request it. + if (src_ip) + { + orig_len = options_len; + options_len += 2 + sizeof(src_ip); + + // workaround for realloc on old machines + // options = realloc(options, options_len); + tmp = malloc(options_len); + memcpy(tmp, options, orig_len); + free(options); + options = tmp; + + options[i++] = LIBNET_DHCP_DISCOVERADDR; // type + options[i++] = sizeof(src_ip); // len + memcpy(options + i, (char *)&src_ip, sizeof(src_ip));// data + i += sizeof(src_ip); + } + + // end our options packet + // workaround for realloc on old machines + // options = realloc(options, options_len); // resize options buffer + orig_len = options_len; + options_len += 1; + tmp = malloc(options_len); + memcpy(tmp, options, orig_len); + free(options); + options = tmp; + options[i++] = LIBNET_DHCP_END; + + + // make sure we are at least the minimum length, if not fill + // this could go in libnet, but we will leave it in the app for now + if (options_len + LIBNET_DHCPV4_H < LIBNET_BOOTP_MIN_LEN) + { + orig_len = options_len; + options_len = LIBNET_BOOTP_MIN_LEN - LIBNET_DHCPV4_H; + + // workaround for realloc on old machines + // options = realloc(options, options_len); + tmp = malloc(options_len); + memcpy(tmp, options, orig_len); + free(options); + options = tmp; + + memset(options + i, 0, options_len - i); + } + + // the goodies are here + dhcp = libnet_build_dhcpv4( + LIBNET_DHCP_REQUEST, // opcode + 1, // hardware type + 6, // hardware address length + 0, // hop count + 0xdeadbeef, // transaction id + 0, // seconds since bootstrap + 0x8000, // flags + 0, // client ip + 0, // your ip + 0, // server ip + 0, // gateway ip + ethaddr->ether_addr_octet, // client hardware addr + NULL, // server host name + NULL, // boot file + options, // dhcp options stuck in payload since it is dynamic + options_len, // length of options + l, // libnet handle + 0); // libnet id + + // wrap it + udp = libnet_build_udp( + 68, // source port + 67, // destination port + LIBNET_UDP_H + LIBNET_DHCPV4_H + options_len, // packet size + 0, // checksum + NULL, // payload + 0, // payload size + l, // libnet handle + 0); // libnet id + + // hook me up with some ipv4 + ip = libnet_build_ipv4( + LIBNET_IPV4_H + LIBNET_UDP_H + LIBNET_DHCPV4_H + + options_len, // length + 0x10, // TOS + 0, // IP ID + 0, // IP Frag + 16, // TTL + IPPROTO_UDP, // protocol + 0, // checksum + src_ip, // src ip + inet_addr("255.255.255.255"), // destination ip + NULL, // payload + 0, // payload size + l, // libnet handle + 0); // libnet id + + // we can just autobuild since we arent doing anything tricky + t = libnet_autobuild_ethernet( + enet_dst, // ethernet destination + ETHERTYPE_IP, // protocol type + l); // libnet handle + + // write to the wire + if (libnet_write(l) == -1) + { + fprintf(stderr, " %s: libnet_write: %s\n", argv[0], + strerror(errno)); + exit(EXIT_FAILURE); + } + + // fill and print stats + libnet_stats(l, &ls); + fprintf(stderr, "Packets sent: %lld\n" + "Packet errors: %lld\n" + "Bytes written: %lld\n", + ls.packets_sent, ls.packet_errors, ls.bytes_written); + libnet_destroy(l); + + // free mem + free(options); + + exit(0); + } + exit(0); +} |