diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2019-05-16 11:18:49 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2019-05-16 11:18:49 +0200 |
| commit | a840884531df649aabc72debb2d6025dabe2abb3 (patch) | |
| tree | f953e5ac4ac2c7ae6535ac5569fb809cef9d929a | |
| parent | 9bf6780c2888805908d9485681dadffeab3414f7 (diff) | |
| download | busybox-w32-a840884531df649aabc72debb2d6025dabe2abb3.tar.gz busybox-w32-a840884531df649aabc72debb2d6025dabe2abb3.tar.bz2 busybox-w32-a840884531df649aabc72debb2d6025dabe2abb3.zip | |
udhcpd: support per-client hostnames in static leases
function old new delta
read_staticlease 222 299 +77
add_server_options 92 154 +62
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 139/0) Total: 139 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
| -rw-r--r-- | examples/udhcp/udhcpd.conf | 9 | ||||
| -rw-r--r-- | networking/udhcp/dhcpd.c | 72 | ||||
| -rw-r--r-- | networking/udhcp/dhcpd.h | 6 |
3 files changed, 71 insertions, 16 deletions
diff --git a/examples/udhcp/udhcpd.conf b/examples/udhcp/udhcpd.conf index bb8774e08..df1258aaf 100644 --- a/examples/udhcp/udhcpd.conf +++ b/examples/udhcp/udhcpd.conf | |||
| @@ -44,7 +44,7 @@ interface eth0 | |||
| 44 | #notify_file # default: no script | 44 | #notify_file # default: no script |
| 45 | #notify_file dumpleases # useful for debugging | 45 | #notify_file dumpleases # useful for debugging |
| 46 | 46 | ||
| 47 | # The following are bootp specific options | 47 | # The following are BOOTP specific options |
| 48 | # next server to use in bootstrap | 48 | # next server to use in bootstrap |
| 49 | #siaddr 192.168.0.22 # default: 0.0.0.0 (none) | 49 | #siaddr 192.168.0.22 # default: 0.0.0.0 (none) |
| 50 | # tftp server name | 50 | # tftp server name |
| @@ -52,9 +52,14 @@ interface eth0 | |||
| 52 | # tftp file to download (e.g. kernel image) | 52 | # tftp file to download (e.g. kernel image) |
| 53 | #boot_file /var/nfs_root # default: none | 53 | #boot_file /var/nfs_root # default: none |
| 54 | 54 | ||
| 55 | # NOTE: "boot_file FILE" and "opt bootfile FILE" are conceptually the same, | ||
| 56 | # but "boot_file" goes into BOOTP-defined fixed-size field in the packet, | ||
| 57 | # whereas "opt bootfile" goes into DHCP option 0x43. | ||
| 58 | # Same for "sname HOST" and "opt tftp HOST". | ||
| 59 | |||
| 55 | # Static leases map | 60 | # Static leases map |
| 56 | #static_lease 00:60:08:11:CE:4E 192.168.0.54 | 61 | #static_lease 00:60:08:11:CE:4E 192.168.0.54 |
| 57 | #static_lease 00:60:08:11:CE:3E 192.168.0.44 | 62 | #static_lease 00:60:08:11:CE:3E 192.168.0.44 optional_hostname |
| 58 | 63 | ||
| 59 | # The remainder of options are DHCP options and can be specified with the | 64 | # The remainder of options are DHCP options and can be specified with the |
| 60 | # keyword 'opt' or 'option'. If an option can take multiple items, such | 65 | # keyword 'opt' or 'option'. If an option can take multiple items, such |
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index bf44320a1..f231e4001 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c | |||
| @@ -48,14 +48,23 @@ | |||
| 48 | #define g_leases ((struct dyn_lease*)ptr_to_globals) | 48 | #define g_leases ((struct dyn_lease*)ptr_to_globals) |
| 49 | /* struct server_config_t server_config is in bb_common_bufsiz1 */ | 49 | /* struct server_config_t server_config is in bb_common_bufsiz1 */ |
| 50 | 50 | ||
| 51 | struct static_lease { | ||
| 52 | struct static_lease *next; | ||
| 53 | uint32_t nip; | ||
| 54 | uint8_t mac[6]; | ||
| 55 | uint8_t opt[1]; | ||
| 56 | }; | ||
| 57 | |||
| 51 | /* Takes the address of the pointer to the static_leases linked list, | 58 | /* Takes the address of the pointer to the static_leases linked list, |
| 52 | * address to a 6 byte mac address, | 59 | * address to a 6 byte mac address, |
| 53 | * 4 byte IP address */ | 60 | * 4 byte IP address */ |
| 54 | static void add_static_lease(struct static_lease **st_lease_pp, | 61 | static void add_static_lease(struct static_lease **st_lease_pp, |
| 55 | uint8_t *mac, | 62 | uint8_t *mac, |
| 56 | uint32_t nip) | 63 | uint32_t nip, |
| 64 | const char *opts) | ||
| 57 | { | 65 | { |
| 58 | struct static_lease *st_lease; | 66 | struct static_lease *st_lease; |
| 67 | unsigned optlen; | ||
| 59 | 68 | ||
| 60 | /* Find the tail of the list */ | 69 | /* Find the tail of the list */ |
| 61 | while ((st_lease = *st_lease_pp) != NULL) { | 70 | while ((st_lease = *st_lease_pp) != NULL) { |
| @@ -63,10 +72,17 @@ static void add_static_lease(struct static_lease **st_lease_pp, | |||
| 63 | } | 72 | } |
| 64 | 73 | ||
| 65 | /* Add new node */ | 74 | /* Add new node */ |
| 66 | *st_lease_pp = st_lease = xzalloc(sizeof(*st_lease)); | 75 | optlen = (opts ? 1+1+strnlen(opts, 120) : 0); |
| 76 | *st_lease_pp = st_lease = xzalloc(sizeof(*st_lease) + optlen); | ||
| 67 | memcpy(st_lease->mac, mac, 6); | 77 | memcpy(st_lease->mac, mac, 6); |
| 68 | st_lease->nip = nip; | 78 | st_lease->nip = nip; |
| 69 | /*st_lease->next = NULL;*/ | 79 | /*st_lease->next = NULL;*/ |
| 80 | if (optlen) { | ||
| 81 | st_lease->opt[OPT_CODE] = DHCP_HOST_NAME; | ||
| 82 | optlen -= 2; | ||
| 83 | st_lease->opt[OPT_LEN] = optlen; | ||
| 84 | memcpy(&st_lease->opt[OPT_DATA], opts, optlen); | ||
| 85 | } | ||
| 70 | } | 86 | } |
| 71 | 87 | ||
| 72 | /* Find static lease IP by mac */ | 88 | /* Find static lease IP by mac */ |
| @@ -344,6 +360,7 @@ static int FAST_FUNC read_staticlease(const char *const_line, void *arg) | |||
| 344 | char *line; | 360 | char *line; |
| 345 | char *mac_string; | 361 | char *mac_string; |
| 346 | char *ip_string; | 362 | char *ip_string; |
| 363 | char *opts; | ||
| 347 | struct ether_addr mac_bytes; /* it's "struct { uint8_t mac[6]; }" */ | 364 | struct ether_addr mac_bytes; /* it's "struct { uint8_t mac[6]; }" */ |
| 348 | uint32_t nip; | 365 | uint32_t nip; |
| 349 | 366 | ||
| @@ -358,7 +375,10 @@ static int FAST_FUNC read_staticlease(const char *const_line, void *arg) | |||
| 358 | if (!ip_string || !udhcp_str2nip(ip_string, &nip)) | 375 | if (!ip_string || !udhcp_str2nip(ip_string, &nip)) |
| 359 | return 0; | 376 | return 0; |
| 360 | 377 | ||
| 361 | add_static_lease(arg, (uint8_t*) &mac_bytes, nip); | 378 | opts = strtok_r(NULL, " \t", &line); |
| 379 | /* opts might be NULL, that's not an error */ | ||
| 380 | |||
| 381 | add_static_lease(arg, (uint8_t*) &mac_bytes, nip, opts); | ||
| 362 | 382 | ||
| 363 | log_static_leases(arg); | 383 | log_static_leases(arg); |
| 364 | 384 | ||
| @@ -626,14 +646,49 @@ static void init_packet(struct dhcp_packet *packet, struct dhcp_packet *oldpacke | |||
| 626 | */ | 646 | */ |
| 627 | static void add_server_options(struct dhcp_packet *packet) | 647 | static void add_server_options(struct dhcp_packet *packet) |
| 628 | { | 648 | { |
| 629 | struct option_set *curr = server_config.options; | 649 | struct option_set *config_opts; |
| 650 | uint8_t *client_hostname_opt; | ||
| 651 | |||
| 652 | client_hostname_opt = NULL; | ||
| 653 | if (packet->yiaddr) { /* if we aren't from send_inform()... */ | ||
| 654 | struct static_lease *st_lease = server_config.static_leases; | ||
| 655 | while (st_lease) { | ||
| 656 | if (st_lease->nip == packet->yiaddr) { | ||
| 657 | if (st_lease->opt[0] != 0) | ||
| 658 | client_hostname_opt = st_lease->opt; | ||
| 659 | break; | ||
| 660 | } | ||
| 661 | st_lease = st_lease->next; | ||
| 662 | } | ||
| 663 | } | ||
| 630 | 664 | ||
| 631 | while (curr) { | 665 | config_opts = server_config.options; |
| 632 | if (curr->data[OPT_CODE] != DHCP_LEASE_TIME) | 666 | while (config_opts) { |
| 633 | udhcp_add_binary_option(packet, curr->data); | 667 | if (config_opts->data[OPT_CODE] != DHCP_LEASE_TIME) { |
| 634 | curr = curr->next; | 668 | /* ^^^^ |
| 669 | * DHCP_LEASE_TIME is already filled, or in case of | ||
| 670 | * send_inform(), should not be filled at all. | ||
| 671 | */ | ||
| 672 | if (config_opts->data[OPT_CODE] != DHCP_HOST_NAME | ||
| 673 | || !client_hostname_opt | ||
| 674 | ) { | ||
| 675 | /* Why "!client_hostname_opt": | ||
| 676 | * add hostname only if client has no hostname | ||
| 677 | * on its static lease line. | ||
| 678 | * (Not that "opt hostname HOST" | ||
| 679 | * makes much sense in udhcpd.conf, | ||
| 680 | * that'd give all clients the same hostname, | ||
| 681 | * but it's a valid configuration). | ||
| 682 | */ | ||
| 683 | udhcp_add_binary_option(packet, config_opts->data); | ||
| 684 | } | ||
| 685 | } | ||
| 686 | config_opts = config_opts->next; | ||
| 635 | } | 687 | } |
| 636 | 688 | ||
| 689 | if (client_hostname_opt) | ||
| 690 | udhcp_add_binary_option(packet, client_hostname_opt); | ||
| 691 | |||
| 637 | packet->siaddr_nip = server_config.siaddr_nip; | 692 | packet->siaddr_nip = server_config.siaddr_nip; |
| 638 | 693 | ||
| 639 | if (server_config.sname) | 694 | if (server_config.sname) |
| @@ -753,7 +808,6 @@ static NOINLINE void send_ACK(struct dhcp_packet *oldpacket, uint32_t yiaddr) | |||
| 753 | 808 | ||
| 754 | lease_time_sec = select_lease_time(oldpacket); | 809 | lease_time_sec = select_lease_time(oldpacket); |
| 755 | udhcp_add_simple_option(&packet, DHCP_LEASE_TIME, htonl(lease_time_sec)); | 810 | udhcp_add_simple_option(&packet, DHCP_LEASE_TIME, htonl(lease_time_sec)); |
| 756 | |||
| 757 | add_server_options(&packet); | 811 | add_server_options(&packet); |
| 758 | 812 | ||
| 759 | addr.s_addr = yiaddr; | 813 | addr.s_addr = yiaddr; |
diff --git a/networking/udhcp/dhcpd.h b/networking/udhcp/dhcpd.h index b8f96b029..5c3bf5147 100644 --- a/networking/udhcp/dhcpd.h +++ b/networking/udhcp/dhcpd.h | |||
| @@ -15,11 +15,7 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | |||
| 15 | #define DHCPD_CONF_FILE "/etc/udhcpd.conf" | 15 | #define DHCPD_CONF_FILE "/etc/udhcpd.conf" |
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | struct static_lease { | 18 | struct static_lease; |
| 19 | struct static_lease *next; | ||
| 20 | uint32_t nip; | ||
| 21 | uint8_t mac[6]; | ||
| 22 | }; | ||
| 23 | 19 | ||
| 24 | struct server_config_t { | 20 | struct server_config_t { |
| 25 | char *interface; /* interface to use */ | 21 | char *interface; /* interface to use */ |
