From bd8ffe3f035bff5efeb8197aa5d4f3a5bb803c08 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Wed, 8 Jan 2014 13:34:53 -0500 Subject: [PATCH] better handling and checking of received packets --- dhtest.c | 1 - functions.c | 169 +++++++++++++++++++++++++++++++++------------------- headers.h | 3 - 3 files changed, 109 insertions(+), 64 deletions(-) diff --git a/dhtest.c b/dhtest.c index a6ac92f..bb7070d 100644 --- a/dhtest.c +++ b/dhtest.c @@ -55,7 +55,6 @@ char *server_addr = "255.255.255.255"; struct dhcpv4_hdr *dhcph_g = { 0 }; -u_int8_t *dhopt_pointer_g = { 0 }; u_int8_t verbose = 0; u_int8_t dhcp_release_flag = 0; u_int8_t padding_flag = 0; diff --git a/functions.c b/functions.c index 24f1092..854c0a3 100644 --- a/functions.c +++ b/functions.c @@ -23,6 +23,7 @@ struct iphdr *iph_g = { 0 }; struct udphdr *uh_g = { 0 }; static struct arp_hdr *arp_hg; static struct icmp_hdr *icmp_hg; +static unsigned char *dhopt_pointer_g; /* DHCP packet, option buffer and size of option buffer */ static unsigned char dhcp_packet_send[1518]; @@ -35,6 +36,15 @@ static u_char arp_icmp_packet[1514] = { 0 }; static u_char arp_icmp_reply[1514] = { 0 }; static u_int16_t icmp_len = 0; static int have_set_promisc; +static unsigned int lease_time; + + + + +static void read_options(int len); +static int check_packet(int pkt_type, int len); +static int map_all_layer_ptr(int pkt_type); + /* @@ -264,7 +274,7 @@ int recv_packet(int pkt_type) if (ret < 0) return timeout_rv; - chk_pkt_state = check_packet(pkt_type); + chk_pkt_state = check_packet(pkt_type, ret); switch (chk_pkt_state) { case DHCP_OFFR_RCVD: @@ -627,8 +637,6 @@ int build_packet(int pkt_type) { bzero(arp_icmp_reply, sizeof(arp_icmp_reply)); if(pkt_type == ARP_SEND) { - map_all_layer_ptr(ARP_MAP); - struct vlan_eth_hdr *vhdr = (struct vlan_eth_hdr *)arp_icmp_reply; memcpy(vhdr->vlan_dhost, vlan_hg->vlan_shost, ETHER_ADDR_LEN); memcpy(vhdr->vlan_shost, dhmac, ETHER_ADDR_LEN); @@ -648,8 +656,6 @@ int build_packet(int pkt_type) memcpy(arph->target_mac, arp_hg->sender_mac, ETHER_ADDR_LEN); memcpy(arph->target_ip, arp_hg->sender_ip, IP_ADDR_LEN); } else if(ICMP_SEND) { - map_all_layer_ptr(ICMP_MAP); - struct vlan_eth_hdr *vhdr = (struct vlan_eth_hdr *)arp_icmp_reply; memcpy(vhdr->vlan_dhost, vlan_hg->vlan_shost, ETHER_ADDR_LEN); memcpy(vhdr->vlan_shost, dhmac, ETHER_ADDR_LEN); @@ -691,54 +697,84 @@ int build_packet(int pkt_type) * Checks whether received packet is DHCP offer/ACK/NACK/ARP/ICMP * and retunrs the received packet type */ -int check_packet(int pkt_type) +static int check_packet(int pkt_type, int len) { + int ret; + + if (len < 40) + return UNKNOWN_PACKET; + if(pkt_type == DHCP_MSGOFFER || pkt_type == DHCP_MSGACK) { - map_all_layer_ptr(pkt_type); + if (map_all_layer_ptr(pkt_type)) + return UNKNOWN_PACKET; + if (vlan) { if (ntohs(vlan_hg->vlan_priority_c_vid) != vlan || ntohs(vlan_hg->vlan_tpi) != ETHERTYPE_VLAN) return UNKNOWN_PACKET; } + if (dhopt_pointer_g > dhcp_packet_recv + len) + return UNKNOWN_PACKET; + if (iph_g->protocol != 17 || uh_g->source != htons(port) || uh_g->dest != htons(port + 1)) return UNKNOWN_PACKET; if (htonl(dhcph_g->dhcp_xid) != dhcp_xid) return UNKNOWN_PACKET; if(*(dhopt_pointer_g + 2) == DHCP_MSGOFFER) - return DHCP_OFFR_RCVD; - if(*(dhopt_pointer_g + 2) == DHCP_MSGACK) - return DHCP_ACK_RCVD; - if(*(dhopt_pointer_g + 2) == DHCP_MSGNACK) - return DHCP_NAK_RCVD; + ret = DHCP_OFFR_RCVD; + else if(*(dhopt_pointer_g + 2) == DHCP_MSGACK) + ret = DHCP_ACK_RCVD; + else if(*(dhopt_pointer_g + 2) == DHCP_MSGNACK) + ret = DHCP_NAK_RCVD; + else + return UNKNOWN_PACKET; - return UNKNOWN_PACKET; + read_options(len); + + return ret; } else if(pkt_type == ARP_ICMP_RCV) { - map_all_layer_ptr(ARP_MAP); - if(!vlan) { + if (map_all_layer_ptr(ARP_MAP)) + return UNKNOWN_PACKET; - if((ntohs(arp_hg->ar_op)) == ARPOP_REQUEST && htonl(ip_address) == arp_hg->target_ip32) { - return ARP_RCVD; - } - } else if(vlan && ntohs(vlan) == vlan_hg->vlan_priority_c_vid) { - if((ntohs(arp_hg->ar_op)) == ARPOP_REQUEST && htonl(ip_address) == arp_hg->target_ip32) { - if (!quiet) - printf("Arp request received\n"); - return ARP_RCVD; - } - } - map_all_layer_ptr(ICMP_MAP); - if(!vlan) { - if((ntohs(vlan_hg->vlan_tpi)) == ETHERTYPE_IP && iph_g->protocol == 1 && ip_address == ntohl(iph_g->daddr) && icmp_hg->icmp_type == ICMP_ECHO) { - return ICMP_RCVD; - } - } else if(vlan && ntohs(vlan) == vlan_hg->vlan_priority_c_vid) { - if((ntohs(vlan_hg->vlan_len)) == ETHERTYPE_IP && iph_g->protocol == 1 && ip_address == ntohl(iph_g->daddr) && icmp_hg->icmp_type == ICMP_ECHO) { - return ICMP_RCVD; - } + if(!vlan && vlan_hg->vlan_tpi != htons(ETHERTYPE_ARP)) + goto not_arp; + if (vlan && (ntohs(vlan_hg->vlan_priority_c_vid) != vlan + || vlan_hg->vlan_len != htons(ETHERTYPE_ARP))) + goto not_arp; + + if ((unsigned char *) arp_hg + sizeof(*arp_hg) > arp_icmp_packet + len) + return UNKNOWN_PACKET; + + if((ntohs(arp_hg->ar_op)) == ARPOP_REQUEST && htonl(ip_address) == arp_hg->target_ip32) { + if (!quiet) + printf("Arp request received\n"); + return ARP_RCVD; } return UNKNOWN_PACKET; + +not_arp: + if (map_all_layer_ptr(ICMP_MAP)) + return UNKNOWN_PACKET; + + if(!vlan && vlan_hg->vlan_tpi != htons(ETHERTYPE_IP)) + goto not_icmp; + if (vlan && (ntohs(vlan_hg->vlan_priority_c_vid) != vlan + || vlan_hg->vlan_len != htons(ETHERTYPE_IP))) + goto not_icmp; + + if ((unsigned char *) icmp_hg + sizeof(*icmp_hg) > arp_icmp_packet + len) + return -1; + + if (iph_g->protocol != 1) + goto not_icmp; + + if(ip_address == ntohl(iph_g->daddr) && icmp_hg->icmp_type == ICMP_ECHO) + return ICMP_RCVD; + +not_icmp: + return UNKNOWN_PACKET; } return 0; } @@ -749,17 +785,31 @@ int check_packet(int pkt_type) */ int set_serv_id_opt50() { - map_all_layer_ptr(DHCP_MSGOFFER); - option50_ip = dhcph_g->dhcp_yip; - while(*(dhopt_pointer_g) != DHCP_END) { - if(*(dhopt_pointer_g) == DHCP_SERVIDENT) { - memcpy(&server_id, (u_int32_t *)(dhopt_pointer_g + 2), 4); + return 0; +} + +static void read_options(int len) { + unsigned char *p = dhopt_pointer_g, + *end = dhcp_packet_recv + len; + + while(*(p) != DHCP_END && p < end) { + if ((p + *(p + 1) + 2) > end) + break; + + switch(*(p)) { + case DHCP_SERVIDENT: + server_id = *(u_int32_t *)(p + 2); + break; + + case DHCP_LEASETIME: + lease_time = ntohl(*(u_int32_t *)(p + 2)); + break; } - dhopt_pointer_g = dhopt_pointer_g + *(dhopt_pointer_g + 1) + 2; + + p = p + *(p + 1) + 2; } - return 0; } /* @@ -768,9 +818,9 @@ int set_serv_id_opt50() int print_dhinfo(int pkt_type) { u_int16_t tmp; - if(pkt_type == DHCP_MSGOFFER) { - map_all_layer_ptr(DHCP_MSGOFFER); + unsigned char *p; + if(pkt_type == DHCP_MSGOFFER) { printf("\nDHCP offer details\n"); printf("----------------------------------------------------------\n"); printf("DHCP offered IP from server - %s\n", get_ip_str(dhcph_g->dhcp_yip)); @@ -780,8 +830,6 @@ int print_dhinfo(int pkt_type) printf("DHCP Relay agent IP - %s\n", get_ip_str(dhcph_g->dhcp_gip)); } } else if( pkt_type == DHCP_MSGACK) { - map_all_layer_ptr(DHCP_MSGACK); - printf("\nDHCP ack details\n"); printf("----------------------------------------------------------\n"); printf("DHCP offered IP from server - %s\n", get_ip_str(dhcph_g->dhcp_yip)); @@ -792,52 +840,53 @@ int print_dhinfo(int pkt_type) } } - while(*(dhopt_pointer_g) != DHCP_END) { + p = dhopt_pointer_g; + while(*(p) != DHCP_END) { - switch(*(dhopt_pointer_g)) { + switch(*(p)) { case DHCP_SERVIDENT: - printf("DHCP server - %s\n", get_ip_str(*(u_int32_t *)(dhopt_pointer_g + 2))); + printf("DHCP server - %s\n", get_ip_str(*(u_int32_t *)(p + 2))); break; case DHCP_LEASETIME: printf("Lease time - %d Days %d Hours %d Minutes\n", \ - (ntohl(*(u_int32_t *)(dhopt_pointer_g + 2))) / (3600 * 24), \ - ((ntohl(*(u_int32_t *)(dhopt_pointer_g + 2))) % (3600 * 24)) / 3600, \ - (((ntohl(*(u_int32_t *)(dhopt_pointer_g + 2))) % (3600 * 24)) % 3600) / 60); + (ntohl(*(u_int32_t *)(p + 2))) / (3600 * 24), \ + ((ntohl(*(u_int32_t *)(p + 2))) % (3600 * 24)) / 3600, \ + (((ntohl(*(u_int32_t *)(p + 2))) % (3600 * 24)) % 3600) / 60); break; case DHCP_SUBNETMASK: - printf("Subnet mask - %s\n", get_ip_str(*(u_int32_t *)(dhopt_pointer_g + 2))); + printf("Subnet mask - %s\n", get_ip_str(*(u_int32_t *)(p + 2))); break; case DHCP_ROUTER: - for(tmp = 0; tmp < (*(dhopt_pointer_g + 1) / 4); tmp++) { - printf("Router/gateway - %s\n", get_ip_str(*(u_int32_t *)(dhopt_pointer_g + 2 + (tmp * 4)))); + for(tmp = 0; tmp < (*(p + 1) / 4); tmp++) { + printf("Router/gateway - %s\n", get_ip_str(*(u_int32_t *)(p + 2 + (tmp * 4)))); } break; case DHCP_DNS: - for(tmp = 0; tmp < ((*(dhopt_pointer_g + 1)) / 4); tmp++) { - printf("DNS server - %s\n", get_ip_str(*(u_int32_t *)(dhopt_pointer_g + 2 + (tmp * 4)))); + for(tmp = 0; tmp < ((*(p + 1)) / 4); tmp++) { + printf("DNS server - %s\n", get_ip_str(*(u_int32_t *)(p + 2 + (tmp * 4)))); } break; case DHCP_FQDN: { /* Minus 3 beacause 3 bytes are used to flags, rcode1 and rcode2 */ - u_int32_t size = (u_int32_t)*(dhopt_pointer_g + 1) - 3; + u_int32_t size = (u_int32_t)*(p + 1) - 3; /* Plus 2 to add string terminator */ u_char fqdn_client_name[size + 1]; /* Plus 5 to reach the beginning of the string */ - memcpy(fqdn_client_name, dhopt_pointer_g + 5, size); + memcpy(fqdn_client_name, p + 5, size); fqdn_client_name[size] = '\0'; printf("FQDN Client name - %s\n", fqdn_client_name); } } - dhopt_pointer_g = dhopt_pointer_g + *(dhopt_pointer_g + 1) + 2; + p = p + *(p + 1) + 2; } printf("----------------------------------------------------------\n\n"); @@ -847,7 +896,7 @@ int print_dhinfo(int pkt_type) /* * Function maps all pointers on OFFER/ACK/ARP/ICMP packet */ -int map_all_layer_ptr(int pkt_type) +static int map_all_layer_ptr(int pkt_type) { switch (pkt_type) { case DHCP_MSGOFFER: diff --git a/headers.h b/headers.h index 7ad552e..e678066 100644 --- a/headers.h +++ b/headers.h @@ -39,8 +39,6 @@ int build_optioneof(void); /* End of option */ int build_dhpacket(int pkt_type); /* Build DHCP disc, req packets */ int build_packet(int pkt_type); /* Builds ARP and ICMP reply packets */ int print_buff(u_int8_t *buff, int size);/* Debug routine */ -int map_all_layer_ptr(int pkt_type); /* maps all layer pointer on DHCP packet */ -int check_packet(int pkt_type); /* Checks the packet for DHCP offer & ack */ int print_dhinfo(int pkt_type); /* Prints DHCP offer & ack informations */ int log_dhinfo(void); /* Logs DHCP IP info to log file */ int get_dhinfo(void); /* Reads log file for mac, ip, serv_ip info */ @@ -331,7 +329,6 @@ extern char *giaddr; extern char *server_addr; extern struct dhcpv4_hdr *dhcph_g; -extern u_int8_t *dhopt_pointer_g; extern u_char dhmac[ETHER_ADDR_LEN]; extern u_char dmac[ETHER_ADDR_LEN];