diff options
Diffstat (limited to 'networking')
-rw-r--r-- | networking/udhcp/files.c | 86 |
1 files changed, 40 insertions, 46 deletions
diff --git a/networking/udhcp/files.c b/networking/udhcp/files.c index a23e886..968d8ed 100644 --- a/networking/udhcp/files.c +++ b/networking/udhcp/files.c @@ -21,7 +21,6 @@ static inline uint64_t hton64(uint64_t v) #endif #define ntoh64(v) hton64(v) - /* on these functions, make sure your datatype matches */ static int FAST_FUNC read_nip(const char *line, void *arg) { @@ -35,13 +34,11 @@ static int FAST_FUNC read_nip(const char *line, void *arg) return 1; } - static int FAST_FUNC read_mac(const char *line, void *arg) { return NULL == ether_aton_r(line, (struct ether_addr *)arg); } - static int FAST_FUNC read_str(const char *line, void *arg) { char **dest = arg; @@ -51,30 +48,27 @@ static int FAST_FUNC read_str(const char *line, void *arg) return 1; } - static int FAST_FUNC read_u32(const char *line, void *arg) { *(uint32_t*)arg = bb_strtou32(line, NULL, 10); return errno == 0; } - -static int FAST_FUNC read_yn(const char *line, void *arg) +static int read_yn(const char *line, void *arg) { char *dest = arg; - if (!strcasecmp("yes", line)) { + if (strcasecmp("yes", line) == 0) { *dest = 1; return 1; } - if (!strcasecmp("no", line)) { + if (strcasecmp("no", line) == 0) { *dest = 0; return 1; } return 0; } - /* find option 'code' in opt_list */ struct option_set* FAST_FUNC find_option(struct option_set *opt_list, uint8_t code) { @@ -86,29 +80,33 @@ struct option_set* FAST_FUNC find_option(struct option_set *opt_list, uint8_t co return NULL; } - /* add an option to the opt_list */ -static void attach_option(struct option_set **opt_list, - const struct dhcp_option *option, char *buffer, int length) +static NOINLINE void attach_option( + struct option_set **opt_list, + const struct dhcp_option *option, + char *buffer, + int length) { struct option_set *existing, *new, **curr; +#if ENABLE_FEATURE_UDHCP_RFC3397 + char *allocated = NULL; +#endif existing = find_option(*opt_list, option->code); if (!existing) { log2("Attaching option %02x to list", option->code); - #if ENABLE_FEATURE_UDHCP_RFC3397 - if ((option->flags & OPTION_TYPE_MASK) == OPTION_STR1035) + if ((option->flags & OPTION_TYPE_MASK) == OPTION_STR1035) { /* reuse buffer and length for RFC1035-formatted string */ - buffer = (char *)dname_enc(NULL, 0, buffer, &length); + allocated = buffer = (char *)dname_enc(NULL, 0, buffer, &length); + } #endif - /* make a new option */ new = xmalloc(sizeof(*new)); - new->data = xmalloc(length + 2); + new->data = xmalloc(length + OPT_DATA); new->data[OPT_CODE] = option->code; new->data[OPT_LEN] = length; - memcpy(new->data + 2, buffer, length); + memcpy(new->data + OPT_DATA, buffer, length); curr = opt_list; while (*curr && (*curr)->data[OPT_CODE] < option->code) @@ -116,44 +114,41 @@ static void attach_option(struct option_set **opt_list, new->next = *curr; *curr = new; -#if ENABLE_FEATURE_UDHCP_RFC3397 - if ((option->flags & OPTION_TYPE_MASK) == OPTION_STR1035 && buffer != NULL) - free(buffer); -#endif - return; + goto ret; } - /* add it to an existing option */ - log1("Attaching option %02x to existing member of list", option->code); if (option->flags & OPTION_LIST) { + unsigned old_len; + + /* add it to an existing option */ + log1("Attaching option %02x to existing member of list", option->code); + old_len = existing->data[OPT_LEN]; #if ENABLE_FEATURE_UDHCP_RFC3397 - if ((option->flags & OPTION_TYPE_MASK) == OPTION_STR1035) + if ((option->flags & OPTION_TYPE_MASK) == OPTION_STR1035) { /* reuse buffer and length for RFC1035-formatted string */ - buffer = (char *)dname_enc(existing->data + 2, - existing->data[OPT_LEN], buffer, &length); + allocated = buffer = (char *)dname_enc(existing->data + OPT_DATA, old_len, buffer, &length); + } #endif - if (existing->data[OPT_LEN] + length <= 255) { - existing->data = xrealloc(existing->data, - existing->data[OPT_LEN] + length + 3); + if (old_len + length < 255) { + /* actually 255 is ok too, but adding a space can overlow it */ + + existing->data = xrealloc(existing->data, OPT_DATA + 1 + old_len + length); if ((option->flags & OPTION_TYPE_MASK) == OPTION_STRING) { - /* ' ' can bring us to 256 - bad */ - if (existing->data[OPT_LEN] + length >= 255) - return; /* add space separator between STRING options in a list */ - existing->data[existing->data[OPT_LEN] + 2] = ' '; - existing->data[OPT_LEN]++; + existing->data[OPT_DATA + old_len] = ' '; + old_len++; } - memcpy(existing->data + existing->data[OPT_LEN] + 2, buffer, length); - existing->data[OPT_LEN] += length; + memcpy(existing->data + OPT_DATA + old_len, buffer, length); + existing->data[OPT_LEN] = old_len + length; } /* else, ignore the data, we could put this in a second option in the future */ + } /* else, ignore the new data */ + + ret: ; #if ENABLE_FEATURE_UDHCP_RFC3397 - if ((option->flags & OPTION_TYPE_MASK) == OPTION_STR1035 && buffer != NULL) - free(buffer); + free(allocated); #endif - } /* else, ignore the new data */ } - /* read a dhcp option and add it to opt_list */ static int FAST_FUNC read_opt(const char *const_line, void *arg) { @@ -166,7 +161,7 @@ static int FAST_FUNC read_opt(const char *const_line, void *arg) uint16_t *result_u16 = (uint16_t *) buffer; uint32_t *result_u32 = (uint32_t *) buffer; - /* Cheat, the only const line we'll actually get is "" */ + /* Cheat, the only *const* line possible is "" */ line = (char *) const_line; opt = strtok(line, " \t="); if (!opt) @@ -180,7 +175,8 @@ static int FAST_FUNC read_opt(const char *const_line, void *arg) retval = 0; do { val = strtok(NULL, ", \t"); - if (!val) break; + if (!val) + break; length = dhcp_option_lengths[option->flags & OPTION_TYPE_MASK]; retval = 0; opt = buffer; /* new meaning for variable opt */ @@ -337,7 +333,6 @@ void FAST_FUNC read_config(const char *file) server_config.end_ip = ntohl(server_config.end_ip); } - void FAST_FUNC write_leases(void) { int fd; @@ -385,7 +380,6 @@ void FAST_FUNC write_leases(void) } } - void FAST_FUNC read_leases(const char *file) { struct dyn_lease lease; |