X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flibsystemd-network%2Fsd-dhcp-lease.c;h=2ec45ca949b01c89ea888599b9d818aa5dddba69;hp=648e6e2159b9f45a11ef775cc4a9613b0a148e10;hb=e140ae58f1c10bbd75ef94afc07d07b82323b506;hpb=109731eb250705e055b98b844d7c0dfb74bcf728 diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c index 648e6e215..2ec45ca94 100644 --- a/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/libsystemd-network/sd-dhcp-lease.c @@ -36,6 +36,7 @@ #include "dhcp-lease-internal.h" #include "sd-dhcp-lease.h" #include "sd-dhcp-client.h" +#include "network-internal.h" int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) { assert_return(lease, -EINVAL); @@ -126,7 +127,10 @@ int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, struct in_addr *addr) { assert_return(lease, -EINVAL); assert_return(addr, -EINVAL); - addr->s_addr = lease->router; + if (lease->router != INADDR_ANY) + addr->s_addr = lease->router; + else + return -ENOENT; return 0; } @@ -170,119 +174,168 @@ sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) { free(lease->hostname); free(lease->domainname); free(lease->dns); + free(lease->ntp); free(lease); } return NULL; } +static void lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, uint32_t min) { + be32_t val; + + assert(option); + assert(ret); + + if (len == 4) { + memcpy(&val, option, 4); + *ret = be32toh(val); + + if (*ret < min) + *ret = min; + } +} + +static void lease_parse_u16(const uint8_t *option, size_t len, uint16_t *ret, uint16_t min) { + be16_t val; + + assert(option); + assert(ret); + + if (len == 2) { + memcpy(&val, option, 2); + *ret = be16toh(val); + + if (*ret < min) + *ret = min; + } +} + +static void lease_parse_be32(const uint8_t *option, size_t len, be32_t *ret) { + assert(option); + assert(ret); + + if (len == 4) + memcpy(ret, option, 4); +} + +static int lease_parse_string(const uint8_t *option, size_t len, char **ret) { + assert(option); + assert(ret); + + if (len >= 1) { + char *string; + + string = strndup((const char *)option, len); + if (!string) + return -errno; + + free(*ret); + *ret = string; + } + + return 0; +} + +static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size) { + assert(option); + assert(ret); + assert(ret_size); + + if (len && !(len % 4)) { + size_t size; + struct in_addr *addresses; + + size = len / 4; + + addresses = newdup(struct in_addr, option, size); + if (!addresses) + return -ENOMEM; + + free(*ret); + *ret = addresses; + *ret_size = size; + } + + return 0; +} + int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option, void *user_data) { sd_dhcp_lease *lease = user_data; - be32_t val; + int r; + + assert(lease); switch(code) { case DHCP_OPTION_IP_ADDRESS_LEASE_TIME: - if (len == 4) { - memcpy(&val, option, 4); - lease->lifetime = be32toh(val); - } + lease_parse_u32(option, len, &lease->lifetime, 1); break; case DHCP_OPTION_SERVER_IDENTIFIER: - if (len >= 4) - memcpy(&lease->server_address, option, 4); + lease_parse_be32(option, len, &lease->server_address); break; case DHCP_OPTION_SUBNET_MASK: - if (len >= 4) - memcpy(&lease->subnet_mask, option, 4); + lease_parse_be32(option, len, &lease->subnet_mask); break; case DHCP_OPTION_ROUTER: - if (len >= 4) - memcpy(&lease->router, option, 4); + lease_parse_be32(option, len, &lease->router); break; case DHCP_OPTION_DOMAIN_NAME_SERVER: - if (len && !(len % 4)) { - lease->dns_size = len / 4; - - free(lease->dns); - lease->dns = newdup(struct in_addr, option, lease->dns_size); - if (!lease->dns) - return -ENOMEM; - } + r = lease_parse_in_addrs(option, len, &lease->dns, &lease->dns_size); + if (r < 0) + return r; break; case DHCP_OPTION_NTP_SERVER: - if (len && !(len % 4)) { - lease->ntp_size = len / 4; - - free(lease->ntp); - lease->ntp = newdup(struct in_addr, option, lease->ntp_size); - if (!lease->ntp) - return -ENOMEM; - } + r = lease_parse_in_addrs(option, len, &lease->ntp, &lease->ntp_size); + if (r < 0) + return r; break; case DHCP_OPTION_INTERFACE_MTU: - if (len >= 2) { - be16_t mtu; - - memcpy(&mtu, option, 2); - lease->mtu = be16toh(mtu); - - if (lease->mtu < 68) - lease->mtu = 0; - } + lease_parse_u16(option, len, &lease->mtu, 68); break; case DHCP_OPTION_DOMAIN_NAME: - if (len >= 1) { - free(lease->domainname); - lease->domainname = strndup((const char *)option, len); - } + r = lease_parse_string(option, len, &lease->domainname); + if (r < 0) + return r; break; case DHCP_OPTION_HOST_NAME: - if (len >= 1) { - free(lease->hostname); - lease->hostname = strndup((const char *)option, len); - } + r = lease_parse_string(option, len, &lease->hostname); + if (r < 0) + return r; break; case DHCP_OPTION_ROOT_PATH: - if (len >= 1) { - free(lease->root_path); - lease->root_path = strndup((const char *)option, len); - } + r = lease_parse_string(option, len, &lease->root_path); + if (r < 0) + return r; break; case DHCP_OPTION_RENEWAL_T1_TIME: - if (len == 4) { - memcpy(&val, option, 4); - lease->t1 = be32toh(val); - } + lease_parse_u32(option, len, &lease->t1, 1); break; case DHCP_OPTION_REBINDING_T2_TIME: - if (len == 4) { - memcpy(&val, option, 4); - lease->t2 = be32toh(val); - } + lease_parse_u32(option, len, &lease->t2, 1); break; } @@ -297,51 +350,13 @@ int dhcp_lease_new(sd_dhcp_lease **ret) { if (!lease) return -ENOMEM; + lease->router = INADDR_ANY; lease->n_ref = REFCNT_INIT; *ret = lease; return 0; } -static void serialize_addresses(FILE *f, const char *key, struct in_addr *addresses, size_t size) { - unsigned i; - - assert(key); - assert(addresses); - assert(size); - - fputs("DNS=", f); - - for (i = 0; i < size; i++) - fprintf(f, "%s%s", inet_ntoa(addresses[i]), - (i < (size - 1)) ? " ": ""); - - fputs("\n", f); -} - -static int deserialize_addresses(struct in_addr **addresses, size_t *size, const char *string) { - char *word, *state; - size_t len; - - FOREACH_WORD(word, len, string, state) { - struct in_addr *new_addresses; - int r; - - new_addresses = realloc(*addresses, (*size + 1) * sizeof(struct in_addr)); - if (!new_addresses) - return -ENOMEM; - - r = inet_aton(word, &(new_addresses[*size])); - if (r < 0) - continue; - - *addresses = new_addresses; - (*size)++; - } - - return 0; -} - int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) { _cleanup_free_ char *temp_path = NULL; _cleanup_fclose_ FILE *f = NULL; @@ -369,18 +384,16 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) { "# This is private data. Do not parse.\n" "ADDRESS=%s\n", inet_ntoa(address)); - r = sd_dhcp_lease_get_router(lease, &address); - if (r < 0) - goto finish; - - fprintf(f, "ROUTER=%s\n", inet_ntoa(address)); - r = sd_dhcp_lease_get_netmask(lease, &address); if (r < 0) goto finish; fprintf(f, "NETMASK=%s\n", inet_ntoa(address)); + r = sd_dhcp_lease_get_router(lease, &address); + if (r >= 0) + fprintf(f, "ROUTER=%s\n", inet_ntoa(address)); + r = sd_dhcp_lease_get_server_identifier(lease, &address); if (r >= 0) fprintf(f, "SERVER_ADDRESS=%s\n", @@ -396,11 +409,11 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) { r = sd_dhcp_lease_get_dns(lease, &addresses, &addresses_size); if (r >= 0) - serialize_addresses(f, "DNS", addresses, addresses_size); + serialize_in_addrs(f, "DNS", addresses, addresses_size); r = sd_dhcp_lease_get_ntp(lease, &addresses, &addresses_size); if (r >= 0) - serialize_addresses(f, "NTP", addresses, addresses_size); + serialize_in_addrs(f, "NTP", addresses, addresses_size); r = sd_dhcp_lease_get_domainname(lease, &string); if (r >= 0) @@ -473,11 +486,13 @@ int dhcp_lease_load(const char *lease_file, sd_dhcp_lease **ret) { lease->address = addr.s_addr; - r = inet_pton(AF_INET, router, &addr); - if (r < 0) - return r; + if (router) { + r = inet_pton(AF_INET, router, &addr); + if (r < 0) + return r; - lease->router = addr.s_addr; + lease->router = addr.s_addr; + } r = inet_pton(AF_INET, netmask, &addr); if (r < 0) @@ -502,13 +517,13 @@ int dhcp_lease_load(const char *lease_file, sd_dhcp_lease **ret) { } if (dns) { - r = deserialize_addresses(&lease->dns, &lease->dns_size, dns); + r = deserialize_in_addrs(&lease->dns, &lease->dns_size, dns); if (r < 0) return r; } if (ntp) { - r = deserialize_addresses(&lease->ntp, &lease->ntp_size, dns); + r = deserialize_in_addrs(&lease->ntp, &lease->ntp_size, dns); if (r < 0) return r; }