summaryrefslogtreecommitdiff
path: root/libnet/sample/dhcp_discover.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnet/sample/dhcp_discover.c')
-rw-r--r--libnet/sample/dhcp_discover.c257
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);
+}