aboutsummaryrefslogtreecommitdiff
path: root/networking/udhcp/script.c
diff options
context:
space:
mode:
Diffstat (limited to 'networking/udhcp/script.c')
-rw-r--r--networking/udhcp/script.c37
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...) */
17static const uint8_t max_option_length[] = { 17static 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
33static 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 */
41static int sprint_nip(char *dest, const char *pre, const uint8_t *ip) 34static 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 */
61static char *alloc_fill_opts(uint8_t *option, const struct dhcp_option *type_p, const char *opt_name) 54static 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 */