diff options
Diffstat (limited to 'networking/udhcp/script.c')
-rw-r--r-- | networking/udhcp/script.c | 37 |
1 files changed, 19 insertions, 18 deletions
diff --git a/networking/udhcp/script.c b/networking/udhcp/script.c index 7ebef3553..94dabf4d1 100644 --- a/networking/udhcp/script.c +++ b/networking/udhcp/script.c | |||
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | 15 | ||
16 | /* get a rough idea of how long an option will be (rounding up...) */ | 16 | /* get a rough idea of how long an option will be (rounding up...) */ |
17 | static const uint8_t max_option_length[] = { | 17 | static const uint8_t len_of_option_as_string[] = { |
18 | [OPTION_IP] = sizeof("255.255.255.255 "), | 18 | [OPTION_IP] = sizeof("255.255.255.255 "), |
19 | [OPTION_IP_PAIR] = sizeof("255.255.255.255 ") * 2, | 19 | [OPTION_IP_PAIR] = sizeof("255.255.255.255 ") * 2, |
20 | [OPTION_STRING] = 1, | 20 | [OPTION_STRING] = 1, |
@@ -30,17 +30,10 @@ static const uint8_t max_option_length[] = { | |||
30 | }; | 30 | }; |
31 | 31 | ||
32 | 32 | ||
33 | static inline int upper_length(int length, int opt_index) | ||
34 | { | ||
35 | return max_option_length[opt_index] * | ||
36 | (length / dhcp_option_lengths[opt_index]); | ||
37 | } | ||
38 | |||
39 | |||
40 | /* note: ip is a pointer to an IP in network order, possibly misaliged */ | 33 | /* note: ip is a pointer to an IP in network order, possibly misaliged */ |
41 | static int sprint_nip(char *dest, const char *pre, const uint8_t *ip) | 34 | static int sprint_nip(char *dest, const char *pre, const uint8_t *ip) |
42 | { | 35 | { |
43 | return sprintf(dest, "%s%d.%d.%d.%d", pre, ip[0], ip[1], ip[2], ip[3]); | 36 | return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]); |
44 | } | 37 | } |
45 | 38 | ||
46 | 39 | ||
@@ -57,9 +50,10 @@ static int mton(uint32_t mask) | |||
57 | } | 50 | } |
58 | 51 | ||
59 | 52 | ||
60 | /* Allocate and fill with the text of option 'option'. */ | 53 | /* Create "opt_name=opt_value" string */ |
61 | static char *alloc_fill_opts(uint8_t *option, const struct dhcp_option *type_p, const char *opt_name) | 54 | static char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_option *type_p, const char *opt_name) |
62 | { | 55 | { |
56 | unsigned upper_length; | ||
63 | int len, type, optlen; | 57 | int len, type, optlen; |
64 | uint16_t val_u16; | 58 | uint16_t val_u16; |
65 | int16_t val_s16; | 59 | int16_t val_s16; |
@@ -67,14 +61,16 @@ static char *alloc_fill_opts(uint8_t *option, const struct dhcp_option *type_p, | |||
67 | int32_t val_s32; | 61 | int32_t val_s32; |
68 | char *dest, *ret; | 62 | char *dest, *ret; |
69 | 63 | ||
70 | len = option[OPT_LEN - 2]; | 64 | /* option points to OPT_DATA, need to go back and get OPT_LEN */ |
65 | len = option[OPT_LEN - OPT_DATA]; | ||
71 | type = type_p->flags & TYPE_MASK; | 66 | type = type_p->flags & TYPE_MASK; |
72 | optlen = dhcp_option_lengths[type]; | 67 | optlen = dhcp_option_lengths[type]; |
68 | upper_length = len_of_option_as_string[type] * (len / optlen); | ||
73 | 69 | ||
74 | dest = ret = xmalloc(upper_length(len, type) + strlen(opt_name) + 2); | 70 | dest = ret = xmalloc(upper_length + strlen(opt_name) + 2); |
75 | dest += sprintf(ret, "%s=", opt_name); | 71 | dest += sprintf(ret, "%s=", opt_name); |
76 | 72 | ||
77 | for (;;) { | 73 | while (len >= optlen) { |
78 | switch (type) { | 74 | switch (type) { |
79 | case OPTION_IP_PAIR: | 75 | case OPTION_IP_PAIR: |
80 | dest += sprint_nip(dest, "", option); | 76 | dest += sprint_nip(dest, "", option); |
@@ -114,15 +110,20 @@ static char *alloc_fill_opts(uint8_t *option, const struct dhcp_option *type_p, | |||
114 | case OPTION_STR1035: | 110 | case OPTION_STR1035: |
115 | /* unpack option into dest; use ret for prefix (i.e., "optname=") */ | 111 | /* unpack option into dest; use ret for prefix (i.e., "optname=") */ |
116 | dest = dname_dec(option, len, ret); | 112 | dest = dname_dec(option, len, ret); |
117 | free(ret); | 113 | if (dest) { |
118 | return dest; | 114 | free(ret); |
115 | return dest; | ||
116 | } | ||
117 | /* error. return "optname=" string */ | ||
118 | return ret; | ||
119 | #endif | 119 | #endif |
120 | } | 120 | } |
121 | option += optlen; | 121 | option += optlen; |
122 | len -= optlen; | 122 | len -= optlen; |
123 | if (len <= 0) | 123 | if (len <= 0) |
124 | break; | 124 | break; |
125 | dest += sprintf(dest, " "); | 125 | *dest++ = ' '; |
126 | *dest = '\0'; | ||
126 | } | 127 | } |
127 | return ret; | 128 | return ret; |
128 | } | 129 | } |
@@ -174,7 +175,7 @@ static char **fill_envp(struct dhcp_packet *packet) | |||
174 | temp = get_option(packet, dhcp_options[i].code); | 175 | temp = get_option(packet, dhcp_options[i].code); |
175 | if (!temp) | 176 | if (!temp) |
176 | goto next; | 177 | goto next; |
177 | *curr = alloc_fill_opts(temp, &dhcp_options[i], opt_name); | 178 | *curr = xmalloc_optname_optval(temp, &dhcp_options[i], opt_name); |
178 | putenv(*curr++); | 179 | putenv(*curr++); |
179 | 180 | ||
180 | /* Fill in a subnet bits option for things like /24 */ | 181 | /* Fill in a subnet bits option for things like /24 */ |