From 3ea888363486647e70682effdd3fd2ada85417b2 Mon Sep 17 00:00:00 2001 From: Christian Giese Date: Fri, 23 Apr 2021 20:38:36 +0200 Subject: [PATCH] Initial DHCP encode/decode draft --- src/bbl_protocols.c | 182 +++++++++++++++++++++++++++++++++++++++++++- src/bbl_protocols.h | 145 +++++++++++++++++++++++++++++++++++ 2 files changed, 326 insertions(+), 1 deletion(-) diff --git a/src/bbl_protocols.c b/src/bbl_protocols.c index 5d8c0fcf..6f715227 100644 --- a/src/bbl_protocols.c +++ b/src/bbl_protocols.c @@ -184,6 +184,90 @@ encode_dhcpv6(uint8_t *buf, uint16_t *len, return PROTOCOL_SUCCESS; } +/* + * encode_dhcp + */ +protocol_error_t +encode_dhcp(uint8_t *buf, uint16_t *len, + bbl_dhcp_t *dhcp) { + + if(!dhcp->header) return ENCODE_ERROR; + + uint8_t *option_len; + + memcpy(buf, dhcp->header, sizeof(struct dhcp_header)); + BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t)); + + *buf = DHCPV4_OPTION_DHCP_MESSAGE_TYPE; + BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t)); + *buf = 1; + BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t)); + *buf = dhcp->type; + BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t)); + + if(dhcp->parameter_request_list) { + *buf = DHCPV4_OPTION_PARAM_REQUEST_LIST; + BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t)); + option_len = buf; /* option len */ + *option_len = 0; + BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t)); + if(dhcp->option_netmask) { + *option_len = *option_len+1; + *buf = DHCPV4_OPTION_SUBNET_MASK; + BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t)); + } + if(dhcp->option_router) { + *option_len = *option_len+1; + *buf = DHCPV4_OPTION_ROUTER; + BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t)); + } + if(dhcp->option_dns1 || dhcp->option_dns2) { + *option_len = *option_len+1; + *buf = DHCPV4_OPTION_DNS_SERVER; + BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t)); + } + if(dhcp->option_domain_name) { + *option_len = *option_len+1; + *buf = DHCPV4_OPTION_DOMAIN_NAME; + BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t)); + } + } + if(dhcp->client_identifier) { + *buf = DHCPV4_OPTION_CLIENT_IDENTIFIER; + BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t)); + *buf = dhcp->client_identifier_len; + BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t)); + memcpy(buf, dhcp->client_identifier, dhcp->client_identifier_len); + BUMP_WRITE_BUFFER(buf, len, dhcp->client_identifier_len); + } + if(dhcp->server_identifier) { + *buf = DHCPV4_OPTION_SERVER_IDENTIFIER; + BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t)); + *buf = dhcp->server_identifier_len; + BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t)); + memcpy(buf, dhcp->server_identifier, dhcp->server_identifier_len); + BUMP_WRITE_BUFFER(buf, len, dhcp->server_identifier_len); + } + if(dhcp->option_address) { + *buf = DHCPV4_OPTION_REQUESTED_IP_ADDRESS; + BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t)); + *buf = 4; + BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t)); + *(uint32_t*)buf = dhcp->address; + BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t)); + } + + *buf = DHCPV4_OPTION_END; + BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t)); + + /* This is optional ... */ + while(*len % 8) { + *buf = DHCPV4_OPTION_PAD; + BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t)); + } + return PROTOCOL_SUCCESS; +} + /* * encode_bbl */ @@ -1432,7 +1516,7 @@ decode_dhcpv6(uint8_t *buf, uint16_t len, return DECODE_ERROR; } - /* Init IPv4 header */ + /* Init DHCPv6 structure */ dhcpv6 = (bbl_dhcpv6_t*)sp; BUMP_BUFFER(sp, sp_len, sizeof(bbl_dhcpv6_t)); memset(dhcpv6, 0x0, sizeof(bbl_dhcpv6_t)); @@ -1488,6 +1572,102 @@ decode_dhcpv6(uint8_t *buf, uint16_t len, return ret_val; } +/* + * decode_dhcp + */ +protocol_error_t +decode_dhcp(uint8_t *buf, uint16_t len, + uint8_t *sp, uint16_t sp_len, + bbl_dhcp_t **_dhcp) { + + protocol_error_t ret_val = PROTOCOL_SUCCESS; + + bbl_dhcp_t *dhcp; + + uint8_t option; + uint8_t option_len; + + if(len < sizeof(struct dhcp_header) || sp_len < sizeof(bbl_dhcp_t)) { + return DECODE_ERROR; + } + + /* Init DHCP structure */ + dhcp = (bbl_dhcp_t*)sp; BUMP_BUFFER(sp, sp_len, sizeof(bbl_dhcp_t)); + memset(dhcp, 0x0, sizeof(bbl_dhcp_t)); + + dhcp->header = (struct dhcp_header*)buf; + BUMP_BUFFER(buf, len, sizeof(struct dhcp_header)); + + while(len >= 2) { + option = *buf; + BUMP_BUFFER(buf, len, sizeof(uint8_t)); + if(option == DHCPV4_OPTION_PAD) { + continue; + } + option_len = *buf; + BUMP_BUFFER(buf, len, sizeof(uint16_t)); + if(option_len > len) { + return DECODE_ERROR; + } + switch(option) { + case DHCPV4_OPTION_END: + option_len = len; + break; + case DHCPV4_OPTION_DHCP_MESSAGE_TYPE: + if(option_len != 1) { + return DECODE_ERROR; + } + dhcp->type = *buf; + break; + case DHCPV4_OPTION_SUBNET_MASK: + if(option_len != 4) { + return DECODE_ERROR; + } + dhcp->netmask = *(uint32_t*)buf; + dhcp->option_netmask = true; + break; + case DHCPV4_OPTION_ROUTER: + if(option_len < 4) { + return DECODE_ERROR; + } + dhcp->router = *(uint32_t*)buf; + dhcp->option_router = true; + break; + case DHCPV4_OPTION_DNS_SERVER: + if(option_len < 4) { + return DECODE_ERROR; + } + dhcp->dns1 = *(uint32_t*)buf; + dhcp->option_dns1 = true; + if(option_len >=8) { + dhcp->dns2 = *(uint32_t*)(buf+4); + dhcp->option_dns2 = true; + } + break; + case DHCPV4_OPTION_HOST_NAME: + dhcp->host_name = (char*)buf; + dhcp->host_name_len = option_len; + break; + case DHCPV4_OPTION_DOMAIN_NAME: + dhcp->domain_name = (char*)buf; + dhcp->domain_name_len = option_len; + break; + case DHCPV4_OPTION_INTERFACE_MTU: + if(option_len != 2) { + return DECODE_ERROR; + } + dhcp->mtu = be16toh(*(uint16_t*)buf); + dhcp->option_mtu = true; + break; + default: + break; + } + BUMP_BUFFER(buf, len, option_len); + } + *_dhcp = dhcp; + return ret_val; +} + /* * decode_bbl */ diff --git a/src/bbl_protocols.h b/src/bbl_protocols.h index 39b068ff..d97963e6 100644 --- a/src/bbl_protocols.h +++ b/src/bbl_protocols.h @@ -297,6 +297,99 @@ typedef enum dhcpv6_option_code_ { DHCPV6_OPTION_MAX, } dhcpv6_option_code; +typedef enum dhcp_message_type_ { + DHCPV4_MESSAGE_DISCOVER = 1, + DHCPV4_MESSAGE_OFFER = 2, + DHCPV4_MESSAGE_REQUEST = 3, + DHCPV4_MESSAGE_DECLINE = 4, + DHCPV4_MESSAGE_ACK = 5, + DHCPV4_MESSAGE_NAK = 6, + DHCPV4_MESSAGE_RELEASE = 7, + DHCPV4_MESSAGE_INFORM = 8, + DHCPV4_MESSAGE_MAX +} dhcp_message_type; + +typedef enum dhcp_option_code_ { + DHCPV4_OPTION_PAD = 0, + DHCPV4_OPTION_SUBNET_MASK = 1, + DHCPV4_OPTION_TIME_OFFSET = 2, + DHCPV4_OPTION_ROUTER = 3, + DHCPV4_OPTION_TIME_SERVER = 4, + DHCPV4_OPTION_NAME_SERVER = 5, + DHCPV4_OPTION_DNS_SERVER = 6, + DHCPV4_OPTION_LOG_SERVER = 7, + DHCPV4_OPTION_COOKIE_SERVER = 8, + DHCPV4_OPTION_LPR_SERVER = 9, + DHCPV4_OPTION_IMPRESS_SERVER = 10, + DHCPV4_OPTION_RESOURCE_LOCATION_SERVER = 11, + DHCPV4_OPTION_HOST_NAME = 12, + DHCPV4_OPTION_BOOT_FILE_SIZE = 13, + DHCPV4_OPTION_MERIT_DUMP_FILE = 14, + DHCPV4_OPTION_DOMAIN_NAME = 15, + DHCPV4_OPTION_SWAP_SERVER = 16, + DHCPV4_OPTION_ROOT_PATH = 17, + DHCPV4_OPTION_EXTENSIONS_PATH = 18, + DHCPV4_OPTION_IP_FORWARDING = 19, + DHCPV4_OPTION_NON_LOCAL_SOURCE_ROUTING = 20, + DHCPV4_OPTION_POLICY_FILTER = 21, + DHCPV4_OPTION_MAX_DATAGRAM_REASSEMBLY_SIZE = 22, + DHCPV4_OPTION_DEFAULT_IP_TTL = 23, + DHCPV4_OPTION_PATH_MTU_AGING_TIMEOUT = 24, + DHCPV4_OPTION_PATH_MTU_PLATEAU_TABLE = 25, + DHCPV4_OPTION_INTERFACE_MTU = 26, + DHCPV4_OPTION_ALL_SUBNETS_ARE_LOCAL = 27, + DHCPV4_OPTION_BROADCAST_ADDRESS = 28, + DHCPV4_OPTION_PERFORM_MASK_DISCOVERY = 29, + DHCPV4_OPTION_MASK_SUPPLIER = 30, + DHCPV4_OPTION_PERFORM_ROUTER_DISCOVERY = 31, + DHCPV4_OPTION_ROUTER_SOLICITATION_ADDRESS = 32, + DHCPV4_OPTION_STATIC_ROUTE = 33, + DHCPV4_OPTION_TRAILER_ENCAPSULATION = 34, + DHCPV4_OPTION_ARP_CACHE_TIMEOUT = 35, + DHCPV4_OPTION_ETHERNET_ENCAPSULATION = 36, + DHCPV4_OPTION_TCP_DEFAULT_TTL = 37, + DHCPV4_OPTION_TCP_KEEPALIVE_INTERVAL = 38, + DHCPV4_OPTION_TCP_KEEPALIVE_GARBAGE = 39, + DHCPV4_OPTION_NIS_DOMAIN = 40, + DHCPV4_OPTION_NIS_SERVER = 41, + DHCPV4_OPTION_NTP_SERVER = 42, + DHCPV4_OPTION_VENDOR_SPECIFIC_INFO = 43, + DHCPV4_OPTION_NETBIOS_NBNS_SERVER = 44, + DHCPV4_OPTION_NETBIOS_NBDD_SERVER = 45, + DHCPV4_OPTION_NETBIOS_NODE_TYPE = 46, + DHCPV4_OPTION_NETBIOS_SCOPE = 47, + DHCPV4_OPTION_X11_FONT_SERVER = 48, + DHCPV4_OPTION_X11_DISPLAY_MANAGER = 49, + DHCPV4_OPTION_REQUESTED_IP_ADDRESS = 50, + DHCPV4_OPTION_IP_ADDRESS_LEASE_TIME = 51, + DHCPV4_OPTION_OPTION_OVERLOAD = 52, + DHCPV4_OPTION_DHCP_MESSAGE_TYPE = 53, + DHCPV4_OPTION_SERVER_IDENTIFIER = 54, + DHCPV4_OPTION_PARAM_REQUEST_LIST = 55, + DHCPV4_OPTION_MESSAGE = 56, + DHCPV4_OPTION_MAX_DHCP_MESSAGE_SIZE = 57, + DHCPV4_OPTION_RENEWAL_TIME_VALUE = 58, + DHCPV4_OPTION_REBINDING_TIME_VALUE = 59, + DHCPV4_OPTION_VENDOR_CLASS_IDENTIFIER = 60, + DHCPV4_OPTION_CLIENT_IDENTIFIER = 61, + DHCPV4_OPTION_NISP_DOMAIN = 64, + DHCPV4_OPTION_NISP_SERVER = 65, + DHCPV4_OPTION_TFTP_SERVER_NAME = 66, + DHCPV4_OPTION_BOOTFILE_NAME = 67, + DHCPV4_OPTION_MOBILE_IP_HOME_AGENT = 68, + DHCPV4_OPTION_SMTP_SERVER = 69, + DHCPV4_OPTION_POP3_SERVER = 70, + DHCPV4_OPTION_NNTP_SERVER = 71, + DHCPV4_OPTION_DEFAULT_WWW_SERVER = 72, + DHCPV4_OPTION_DEFAULT_FINGER_SERVER = 73, + DHCPV4_OPTION_DEFAULT_IRC_SERVER = 74, + DHCPV4_OPTION_STREETTALK_SERVER = 75, + DHCPV4_OPTION_STDA_SERVER = 76, + DHCPV4_OPTION_RAPID_COMMIT = 80, + DHCPV4_OPTION_CAPTIVE_PORTAL = 160, + DHCPV4_OPTION_END = 255 +} dhcp_option_code; + typedef enum access_line_codes_ { // broadband forum tr101 ACCESS_LINE_ACI = 0x01, // Agent Circuit ID @@ -575,6 +668,58 @@ typedef struct bbl_dhcpv6_ { ipv6addr_t *dns2; } bbl_dhcpv6_t; +struct dhcp_header { + uint8_t op; + uint8_t htype; + uint8_t hlen; + uint8_t hops; + uint32_t xid; + uint16_t secs; + uint16_t flags; + uint32_t ciaddr; + uint32_t yiaddr; + uint32_t siaddr; + uint32_t giaddr; + char chaddr[16]; + char sname[64]; + char file[128]; + uint32_t magic_cookie; +} __attribute__ ((__packed__)); + +typedef struct bbl_dhcp_ { + const struct dhcp_header *header; + uint8_t type; + + uint8_t *server_identifier; + uint8_t server_identifier_len; + uint8_t *client_identifier; + uint8_t client_identifier_len; + + uint32_t lease_time; + uint32_t address; + uint32_t netmask; + uint32_t dns1; + uint32_t dns2; + uint32_t router; + uint16_t mtu; + char *host_name; + uint8_t host_name_len; + char *domain_name; + uint8_t domain_name_len; + + bool parameter_request_list; + bool option_lease_time; + bool option_address; + bool option_netmask; + bool option_dns1; + bool option_dns2; + bool option_router; + bool option_mtu; + bool option_host_name; + bool option_domain_name; + +} bbl_dhcp_t; + typedef struct bbl_l2tp_ { bool with_length; // L Bit bool with_sequence; // S Bit