From fe4e1fe75cab68428833b7402f863d0e2286427f Mon Sep 17 00:00:00 2001 From: Arseny Maslennikov Date: Mon, 11 Dec 2017 20:30:09 +0300 Subject: [PATCH] dhcp.c: Provide a DHCP vendor class identifier in requests --- dhcp.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/dhcp.c b/dhcp.c index be6805f..86e3a74 100644 --- a/dhcp.c +++ b/dhcp.c @@ -25,6 +25,7 @@ */ +#include #include #include #include @@ -38,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +51,7 @@ #include "frontend.h" #include "dhcp.h" +#include "version.h" typedef int bp_int32; @@ -68,6 +71,9 @@ typedef short bp_int16; #define DHCP_OPTION_SERVER 54 #define DHCP_OPTION_OPTIONREQ 55 #define DHCP_OPTION_MAXSIZE 57 +#define DHCP_OPTION_VENDORCLASS 60 + +#define DHCP_VENDOR_CLASS_ID_PREFIX "ALT-Propagator" #define BOOTP_CLIENT_PORT 68 #define BOOTP_SERVER_PORT 67 @@ -101,6 +107,34 @@ struct bootp_request { static const char vendor_cookie[] = { 99, 130, 83, 99, 255 }; +// This function's return value needs to be freed after use. +static char* get_vendor_class_id() { + // mimicking dhcpcd + char* ret; + struct utsname u; + unsigned int sz = sizeof(DHCP_VENDOR_CLASS_ID_PREFIX) + + sizeof(VERSION); + if (uname(&u) != 0) { + if ((ret = malloc(sz)) == NULL) { + log_perror("malloc"); + return ret; + } + sprintf(ret, "%s-%s", DHCP_VENDOR_CLASS_ID_PREFIX, VERSION); + } + else { + sz += sizeof(DHCP_VENDOR_CLASS_ID_PREFIX) + + strlen(u.sysname) + 1 + + strlen(u.release) + 1 + + strlen(u.machine) + 1; + if ((ret = malloc(sz)) == NULL) { + log_perror("malloc"); + return ret; + } + sprintf(ret, "%s-%s:%s-%s:%s", DHCP_VENDOR_CLASS_ID_PREFIX, VERSION, + u.sysname, u.release, u.machine); + } + return ret; +} static unsigned int verify_checksum(void * buf2, int length2) { @@ -523,6 +557,7 @@ enum return_type perform_dhcp(struct interface_info * intf) struct sockaddr_in broadcast_addr; struct bootp_request breq, bresp; unsigned char messageType; + char* vendorClass; unsigned int lease; short aShort; int num_options; @@ -565,6 +600,11 @@ enum return_type perform_dhcp(struct interface_info * intf) broadcast_addr.sin_port = htons(BOOTP_SERVER_PORT); /* bootp server */ memset(&broadcast_addr.sin_addr, 0xff, sizeof(broadcast_addr.sin_addr)); /* broadcast */ + vendorClass = get_vendor_class_id(); + add_vendor_code(&breq, DHCP_OPTION_VENDORCLASS, + strlen(vendorClass), + vendorClass); + log_message("DHCP: sending DISCOVER"); wait_message("Sending DHCP request..."); @@ -574,6 +614,7 @@ enum return_type perform_dhcp(struct interface_info * intf) if (i != 0) { stg1_info_message("No DHCP reply received."); close(s); + free(vendorClass); return RETURN_ERROR; } @@ -582,12 +623,16 @@ enum return_type perform_dhcp(struct interface_info * intf) if (get_vendor_code(&bresp, DHCP_OPTION_SERVER, &server_addr.sin_addr)) { close(s); log_message("DHCPOFFER didn't include server address"); + free(vendorClass); return RETURN_ERROR; } init_vendor_codes(&breq); messageType = DHCP_TYPE_REQUEST; add_vendor_code(&breq, DHCP_OPTION_TYPE, 1, &messageType); + add_vendor_code(&breq, DHCP_OPTION_VENDORCLASS, + strlen(vendorClass), + vendorClass); add_vendor_code(&breq, DHCP_OPTION_SERVER, 4, &server_addr.sin_addr); add_vendor_code(&breq, DHCP_OPTION_REQADDR, 4, &bresp.yiaddr); @@ -613,16 +658,19 @@ enum return_type perform_dhcp(struct interface_info * intf) if (i != 0) { close(s); + free(vendorClass); return RETURN_ERROR; } if (get_vendor_code(&bresp, DHCP_OPTION_LEASE, &lease)) { log_message("failed to get lease time\n"); + free(vendorClass); return RETURN_ERROR; } lease = ntohl(lease); close(s); + free(vendorClass); intf->netmask.s_addr = 0; intf->broadcast.s_addr = 0; -- 2.10.4