From 4cf0f07fad038db7e057a06e04f34a2a5b040cb0 Mon Sep 17 00:00:00 2001 From: Nikita Date: Sat, 16 Jan 2021 01:29:26 +0300 Subject: [PATCH] initial commit --- BSDmakefile | 7 + Makefile | 4 + dhcp-client | Bin 0 -> 51176 bytes dhcp-client.c | 515 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 526 insertions(+) create mode 100644 BSDmakefile create mode 100644 Makefile create mode 100755 dhcp-client create mode 100644 dhcp-client.c diff --git a/BSDmakefile b/BSDmakefile new file mode 100644 index 00000000..43adbdda --- /dev/null +++ b/BSDmakefile @@ -0,0 +1,7 @@ +SRCS= dhcp-client.c +PROG= dhcp-client +LDADD= -lpcap +WARNS?= 3 +MAN= + +.include diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..d225ce98 --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +LDLIBS = -lpcap + +dhcp-client: dhcp-client.c + diff --git a/dhcp-client b/dhcp-client new file mode 100755 index 0000000000000000000000000000000000000000..50bc0f0e152633e34e17be80ab30294741207356 GIT binary patch literal 51176 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 literal 0 HcmV?d00001 diff --git a/dhcp-client.c b/dhcp-client.c new file mode 100644 index 00000000..394145e1 --- /dev/null +++ b/dhcp-client.c @@ -0,0 +1,515 @@ +#include +#include +#include +#include +#include +#ifndef __linux__ +#include +#endif +#include +#include + +#define __FAVOR_BSD +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +typedef u_int32_t ip4_t; + +#define DHCP_CHADDR_LEN 16 +#define DHCP_SNAME_LEN 64 +#define DHCP_FILE_LEN 128 + +/* + * http://www.tcpipguide.com/free/t_DHCPMessageFormat.htm + */ +typedef struct dhcp +{ + u_int8_t opcode; + u_int8_t htype; + u_int8_t hlen; + u_int8_t hops; + u_int32_t xid; + u_int16_t secs; + u_int16_t flags; + ip4_t ciaddr; + ip4_t yiaddr; + ip4_t siaddr; + ip4_t giaddr; + u_int8_t chaddr[DHCP_CHADDR_LEN]; + char bp_sname[DHCP_SNAME_LEN]; + char bp_file[DHCP_FILE_LEN]; + uint32_t magic_cookie; + u_int8_t bp_options[0]; +} dhcp_t; + +#define DHCP_BOOTREQUEST 1 +#define DHCP_BOOTREPLY 2 + +#define DHCP_HARDWARE_TYPE_10_EHTHERNET 1 + +#define MESSAGE_TYPE_PAD 0 +#define MESSAGE_TYPE_REQ_SUBNET_MASK 1 +#define MESSAGE_TYPE_ROUTER 3 +#define MESSAGE_TYPE_DNS 6 +#define MESSAGE_TYPE_DOMAIN_NAME 15 +#define MESSAGE_TYPE_REQ_IP 50 +#define MESSAGE_TYPE_DHCP 53 +#define MESSAGE_TYPE_SERVER_IP 54 +#define MESSAGE_TYPE_PARAMETER_REQ_LIST 55 +#define MESSAGE_TYPE_END 255 + +#define DHCP_OPTION_DISCOVER 1 +#define DHCP_OPTION_OFFER 2 +#define DHCP_OPTION_REQUEST 3 +#define DHCP_OPTION_PACK 4 + +typedef enum { + VERBOSE_LEVEL_NONE, + VERBOSE_LEVEL_ERROR, + VERBOSE_LEVEL_INFO, + VERBOSE_LEVEL_DEBUG, +}verbose_level_t; + +#define PRINT(verbose_level, fmt, args...) \ +do{ \ + if( verbose_level <= program_verbose_level ) { \ + if ( verbose_level == VERBOSE_LEVEL_DEBUG ) { \ + printf("%s:%d:%s::", __FILE__, __LINE__, __FUNCTION__); \ + } \ + printf(fmt, ##args); \ + printf("\n"); \ + } \ +}while(0) + +#define DHCP_SERVER_PORT 67 +#define DHCP_CLIENT_PORT 68 + +#define DHCP_MAGIC_COOKIE 0x63825363 + +verbose_level_t program_verbose_level = VERBOSE_LEVEL_DEBUG; +pcap_t *pcap_handle; +u_int32_t ip; +dhcp_t *prev_dhcp; + +/* + * Print the Given ethernet packet in hexa format - Just for debugging + */ +static void +print_packet(const u_int8_t *data, int len) +{ + int i; + + for (i = 0; i < len; i++) + { + if (i % 0x10 == 0) + printf("\n %04x :: ", i); + printf("%02x ", data[i]); + } + PRINT(VERBOSE_LEVEL_INFO, "\n"); +} + +/* + * Get MAC address of given link(dev_name) + */ +static int +get_mac_address(char *dev_name, u_int8_t *mac) +{ +#ifdef __linux__ + struct ifreq s; + int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); + int result; + + strcpy(s.ifr_name, dev_name); + result = ioctl(fd, SIOCGIFHWADDR, &s); + close(fd); + if (result != 0) + return -1; + + memcpy((void *)mac, s.ifr_addr.sa_data, 6); + return 0; +#else + struct ifaddrs *ifap, *p; + + if (getifaddrs(&ifap) != 0) + return -1; + + for (p = ifap; p; p = p->ifa_next) + { + /* Check the device name */ + if ((strcmp(p->ifa_name, dev_name) == 0) && + (p->ifa_addr->sa_family == AF_LINK)) + { + struct sockaddr_dl* sdp; + + sdp = (struct sockaddr_dl*) p->ifa_addr; + memcpy((void *)mac, sdp->sdl_data + sdp->sdl_nlen, 6); + break; + } + } + freeifaddrs(ifap); +#endif + + return 0; +} + +/* + * Return checksum for the given data. + * Copied from FreeBSD + */ +static unsigned short +in_cksum(unsigned short *addr, int len) +{ + register int sum = 0; + u_short answer = 0; + register u_short *w = addr; + register int nleft = len; + /* + * Our algorithm is simple, using a 32 bit accumulator (sum), we add + * sequential 16 bit words to it, and at the end, fold back all the + * carry bits from the top 16 bits into the lower 16 bits. + */ + while (nleft > 1) + { + sum += *w++; + nleft -= 2; + } + /* mop up an odd byte, if necessary */ + if (nleft == 1) + { + *(u_char *)(&answer) = *(u_char *) w; + sum += answer; + } + /* add back carry outs from top 16 bits to low 16 bits */ + sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ + sum += (sum >> 16); /* add carry */ + answer = ~sum; /* truncate to 16 bits */ + return (answer); +} + +/* + * This function will be called for any incoming DHCP responses + */ +static void +dhcp_input(dhcp_t *dhcp) +{ + if (dhcp->opcode != DHCP_OPTION_OFFER ) + return; + + /* Get the IP address given by the server */ + ip = ntohl(dhcp->yiaddr); + prev_dhcp = dhcp; + + /* We are done - lets break the loop */ + pcap_breakloop(pcap_handle); +} + +/* + * UDP packet handler + */ +static void +udp_input(struct udphdr * udp_packet) +{ + /* Check if there is a response from DHCP server by checking the source Port */ + if (ntohs(udp_packet->uh_sport) == DHCP_SERVER_PORT) + dhcp_input((dhcp_t *)((char *)udp_packet + sizeof(struct udphdr))); +} + +/* + * IP Packet handler + */ +static void +ip_input(struct ip * ip_packet) +{ + /* Care only about UDP - since DHCP sits over UDP */ + if (ip_packet->ip_p == IPPROTO_UDP) + udp_input((struct udphdr *)((char *)ip_packet + sizeof(struct ip))); +} + +/* + * Ethernet packet handler + */ +static void +ether_input(u_char *args, const struct pcap_pkthdr *header, const u_char *frame) +{ + struct ether_header *eframe = (struct ether_header *)frame; + + PRINT(VERBOSE_LEVEL_DEBUG, "Received a frame with length of [%d]", header->len); + + if (program_verbose_level == VERBOSE_LEVEL_DEBUG) + print_packet(frame, header->len); + + if (htons(eframe->ether_type) == ETHERTYPE_IP) + ip_input((struct ip *)(frame + sizeof(struct ether_header))); +} + +/* + * Ethernet output handler - Fills appropriate bytes in ethernet header + */ +static void +ether_output(u_char *frame, u_int8_t *mac, int len) +{ + int result; + struct ether_header *eframe = (struct ether_header *)frame; + + memcpy(eframe->ether_shost, mac, ETHER_ADDR_LEN); + memset(eframe->ether_dhost, -1, ETHER_ADDR_LEN); + eframe->ether_type = htons(ETHERTYPE_IP); + + len = len + sizeof(struct ether_header); + + /* Send the packet on wire */ + result = pcap_inject(pcap_handle, frame, len); + PRINT(VERBOSE_LEVEL_DEBUG, "Send %d bytes\n", result); + if (result <= 0) + pcap_perror(pcap_handle, "ERROR:"); +} + +/* + * IP Output handler - Fills appropriate bytes in IP header + */ +static void +ip_output(struct ip *ip_header, int *len) +{ + *len += sizeof(struct ip); + + ip_header->ip_hl = 5; + ip_header->ip_v = IPVERSION; + ip_header->ip_tos = 0x10; + ip_header->ip_len = htons(*len); + ip_header->ip_id = htons(0xffff); + ip_header->ip_off = 0; + ip_header->ip_ttl = 16; + ip_header->ip_p = IPPROTO_UDP; + ip_header->ip_sum = 0; + ip_header->ip_src.s_addr = 0; + ip_header->ip_dst.s_addr = 0xFFFFFFFF; + + ip_header->ip_sum = in_cksum((unsigned short *) ip_header, sizeof(struct ip)); +} + +/* + * UDP output - Fills appropriate bytes in UDP header + */ +static void +udp_output(struct udphdr *udp_header, int *len) +{ + if (*len & 1) + *len += 1; + *len += sizeof(struct udphdr); + + udp_header->uh_sport = htons(DHCP_CLIENT_PORT); + udp_header->uh_dport = htons(DHCP_SERVER_PORT); + udp_header->uh_ulen = htons(*len); + udp_header->uh_sum = 0; +} + +/* + * DHCP output - Just fills DHCP_BOOTREQUEST + */ +static void +dhcp_output(dhcp_t *dhcp, u_int8_t *mac, int *len) +{ + *len += sizeof(dhcp_t); + memset(dhcp, 0, sizeof(dhcp_t)); + + dhcp->opcode = DHCP_BOOTREQUEST; + dhcp->htype = DHCP_HARDWARE_TYPE_10_EHTHERNET; + dhcp->hlen = 6; + memcpy(dhcp->chaddr, mac, DHCP_CHADDR_LEN); + + dhcp->magic_cookie = htonl(DHCP_MAGIC_COOKIE); +} + +/* + * Adds DHCP option to the bytestream + */ +static int +fill_dhcp_option(u_int8_t *packet, u_int8_t code, u_int8_t *data, u_int8_t len) +{ + packet[0] = code; + packet[1] = len; + memcpy(&packet[2], data, len); + + return len + (sizeof(u_int8_t) * 2); +} + +/* + * Fill DHCP options + */ +static int +fill_dhcp_discovery_options(dhcp_t *dhcp) +{ + int len = 0; + u_int32_t req_ip; + u_int8_t parameter_req_list[] = {MESSAGE_TYPE_REQ_SUBNET_MASK, MESSAGE_TYPE_ROUTER, MESSAGE_TYPE_DNS, MESSAGE_TYPE_DOMAIN_NAME}; + u_int8_t option; + + option = DHCP_OPTION_DISCOVER; + len += fill_dhcp_option(&dhcp->bp_options[len], MESSAGE_TYPE_DHCP, &option, sizeof(option)); + req_ip = htonl(0xc0a8010a); + len += fill_dhcp_option(&dhcp->bp_options[len], MESSAGE_TYPE_REQ_IP, (u_int8_t *)&req_ip, sizeof(req_ip)); + len += fill_dhcp_option(&dhcp->bp_options[len], MESSAGE_TYPE_PARAMETER_REQ_LIST, (u_int8_t *)¶meter_req_list, sizeof(parameter_req_list)); + option = 0; + len += fill_dhcp_option(&dhcp->bp_options[len], MESSAGE_TYPE_END, &option, sizeof(option)); + + return len; +} + +/* + * Fill DHCP request options + */ +static int +fill_dhcp_request_options(dhcp_t *dhcp) +{ + int len = 0; + u_int32_t req_ip; + u_int32_t server_ip; + u_int8_t option; + + option = DHCP_OPTION_REQUEST; + len += fill_dhcp_option(&dhcp->bp_options[len], MESSAGE_TYPE_DHCP, &option, sizeof(option)); + req_ip = htonl(prev_dhcp->yiaddr); + req_ip = ((req_ip>>24)&0xff) | // move byte 3 to byte 0 + ((req_ip<<8)&0xff0000) | // move byte 1 to byte 2 + ((req_ip>>8)&0xff00) | // move byte 2 to byte 1 + ((req_ip<<24)&0xff000000); // byte 0 to byte 3 + len += fill_dhcp_option(&dhcp->bp_options[len], MESSAGE_TYPE_REQ_IP, (u_int8_t *)&req_ip, sizeof(req_ip)); + int first_byte = 5; + server_ip = prev_dhcp->bp_options[first_byte+3]<<24 | + prev_dhcp->bp_options[first_byte+2]<<16 | + prev_dhcp->bp_options[first_byte+1]<<8 | + prev_dhcp->bp_options[first_byte]; + len += fill_dhcp_option(&dhcp->bp_options[len], MESSAGE_TYPE_SERVER_IP, (u_int8_t *)&server_ip, sizeof(server_ip)); + option = 0; + + return len; +} + +/* + * Send DHCP DISCOVERY packet + */ +static int +dhcp_discovery(u_int8_t *mac) +{ + int len = 0; + u_char packet[4096]; + struct udphdr *udp_header; + struct ip *ip_header; + dhcp_t *dhcp; + + PRINT(VERBOSE_LEVEL_INFO, "Sending DHCP_DISCOVERY"); + + ip_header = (struct ip *)(packet + sizeof(struct ether_header)); + udp_header = (struct udphdr *)(((char *)ip_header) + sizeof(struct ip)); + dhcp = (dhcp_t *)(((char *)udp_header) + sizeof(struct udphdr)); + + len = fill_dhcp_discovery_options(dhcp); + dhcp_output(dhcp, mac, &len); + udp_output(udp_header, &len); + ip_output(ip_header, &len); + ether_output(packet, mac, len); + + return 0; +} + +/* + * Send DHCP REQUEST packet + */ +static int +dhcp_request(u_int8_t *mac) +{ + int len = 0; + u_char packet[4096]; + struct udphdr *udp_header; + struct ip *ip_header; + dhcp_t *dhcp; + + PRINT(VERBOSE_LEVEL_INFO, "Sending DHCP_REQUEST"); + + ip_header = (struct ip *)(packet + sizeof(struct ether_header)); + udp_header = (struct udphdr *)(((char *)ip_header) + sizeof(struct ip)); + dhcp = (dhcp_t *)(((char *)udp_header) + sizeof(struct udphdr)); + + len = fill_dhcp_request_options(dhcp); + dhcp_output(dhcp, mac, &len); + udp_output(udp_header, &len); + ip_output(ip_header, &len); + ether_output(packet, mac, len); + + return 0; +} + +int +main(int argc, char *argv[]) +{ + int result; + char errbuf[PCAP_ERRBUF_SIZE]; + char *dev; + u_int8_t mac[6]; + + dev = pcap_lookupdev(errbuf); + if (dev == NULL) { + fprintf(stderr, "Couldn't find default device: %s\n", errbuf); + return(2); + } + printf("Device: %s\n", dev); + + /* Get the MAC address of the interface */ + result = get_mac_address(dev, mac); + if (result != 0) + { + PRINT(VERBOSE_LEVEL_ERROR, "Unable to get MAC address for %s", dev); + return -1; + } + PRINT(VERBOSE_LEVEL_INFO, "%s MAC : %02X:%02X:%02X:%02X:%02X:%02X", + dev, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + /* Open the device and get pcap handle for it */ + pcap_handle = pcap_open_live(dev, BUFSIZ, 0, 10, errbuf); + if (pcap_handle == NULL) + { + PRINT(VERBOSE_LEVEL_ERROR, "Couldn't open device %s: %s", dev, errbuf); + return -1; + } + + /* Send DHCP DISCOVERY packet */ + result = dhcp_discovery(mac); + if (result) + { + PRINT(VERBOSE_LEVEL_ERROR, "Couldn't send DHCP DISCOVERY on device %s: %s", dev, errbuf); + goto done; + } + + ip = 0; + PRINT(VERBOSE_LEVEL_INFO, "Waiting for DHCP_OFFER"); + /* Listen till the DHCP OFFER comes */ + pcap_loop(pcap_handle, -1, ether_input, NULL); + printf("Suggested IP %u.%u.%u.%u\n", ip >> 24, ((ip << 8) >> 24), (ip << 16) >> 24, (ip << 24) >> 24); + + result = dhcp_request(mac); + if (result) + { + PRINT(VERBOSE_LEVEL_ERROR, "Couldn't send DHCP REQUEST on device %s: %s", dev, errbuf); + goto done; + } + + ip = 0; + PRINT(VERBOSE_LEVEL_INFO, "Waiting for DHCP_ACK"); + /* Listen till the DHCP ACK comes */ + pcap_loop(pcap_handle, -1, ether_input, NULL); + printf("Got IP %u.%u.%u.%u\n", ip >> 24, ((ip << 8) >> 24), (ip << 16) >> 24, (ip << 24) >> 24); + +done: + pcap_close(pcap_handle); + + return result; +} +