/*
* $Id: dhcp_discover.c,v 1.1.1.1 2012/02/21 22:14:23 misho 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);
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>