diff options
-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 a23e8862c..968d8ed79 100644 --- a/networking/udhcp/files.c +++ b/networking/udhcp/files.c | |||
@@ -21,7 +21,6 @@ static inline uint64_t hton64(uint64_t v) | |||
21 | #endif | 21 | #endif |
22 | #define ntoh64(v) hton64(v) | 22 | #define ntoh64(v) hton64(v) |
23 | 23 | ||
24 | |||
25 | /* on these functions, make sure your datatype matches */ | 24 | /* on these functions, make sure your datatype matches */ |
26 | static int FAST_FUNC read_nip(const char *line, void *arg) | 25 | static int FAST_FUNC read_nip(const char *line, void *arg) |
27 | { | 26 | { |
@@ -35,13 +34,11 @@ static int FAST_FUNC read_nip(const char *line, void *arg) | |||
35 | return 1; | 34 | return 1; |
36 | } | 35 | } |
37 | 36 | ||
38 | |||
39 | static int FAST_FUNC read_mac(const char *line, void *arg) | 37 | static int FAST_FUNC read_mac(const char *line, void *arg) |
40 | { | 38 | { |
41 | return NULL == ether_aton_r(line, (struct ether_addr *)arg); | 39 | return NULL == ether_aton_r(line, (struct ether_addr *)arg); |
42 | } | 40 | } |
43 | 41 | ||
44 | |||
45 | static int FAST_FUNC read_str(const char *line, void *arg) | 42 | static int FAST_FUNC read_str(const char *line, void *arg) |
46 | { | 43 | { |
47 | char **dest = arg; | 44 | char **dest = arg; |
@@ -51,30 +48,27 @@ static int FAST_FUNC read_str(const char *line, void *arg) | |||
51 | return 1; | 48 | return 1; |
52 | } | 49 | } |
53 | 50 | ||
54 | |||
55 | static int FAST_FUNC read_u32(const char *line, void *arg) | 51 | static int FAST_FUNC read_u32(const char *line, void *arg) |
56 | { | 52 | { |
57 | *(uint32_t*)arg = bb_strtou32(line, NULL, 10); | 53 | *(uint32_t*)arg = bb_strtou32(line, NULL, 10); |
58 | return errno == 0; | 54 | return errno == 0; |
59 | } | 55 | } |
60 | 56 | ||
61 | 57 | static int read_yn(const char *line, void *arg) | |
62 | static int FAST_FUNC read_yn(const char *line, void *arg) | ||
63 | { | 58 | { |
64 | char *dest = arg; | 59 | char *dest = arg; |
65 | 60 | ||
66 | if (!strcasecmp("yes", line)) { | 61 | if (strcasecmp("yes", line) == 0) { |
67 | *dest = 1; | 62 | *dest = 1; |
68 | return 1; | 63 | return 1; |
69 | } | 64 | } |
70 | if (!strcasecmp("no", line)) { | 65 | if (strcasecmp("no", line) == 0) { |
71 | *dest = 0; | 66 | *dest = 0; |
72 | return 1; | 67 | return 1; |
73 | } | 68 | } |
74 | return 0; | 69 | return 0; |
75 | } | 70 | } |
76 | 71 | ||
77 | |||
78 | /* find option 'code' in opt_list */ | 72 | /* find option 'code' in opt_list */ |
79 | struct option_set* FAST_FUNC find_option(struct option_set *opt_list, uint8_t code) | 73 | struct option_set* FAST_FUNC find_option(struct option_set *opt_list, uint8_t code) |
80 | { | 74 | { |
@@ -86,29 +80,33 @@ struct option_set* FAST_FUNC find_option(struct option_set *opt_list, uint8_t co | |||
86 | return NULL; | 80 | return NULL; |
87 | } | 81 | } |
88 | 82 | ||
89 | |||
90 | /* add an option to the opt_list */ | 83 | /* add an option to the opt_list */ |
91 | static void attach_option(struct option_set **opt_list, | 84 | static NOINLINE void attach_option( |
92 | const struct dhcp_option *option, char *buffer, int length) | 85 | struct option_set **opt_list, |
86 | const struct dhcp_option *option, | ||
87 | char *buffer, | ||
88 | int length) | ||
93 | { | 89 | { |
94 | struct option_set *existing, *new, **curr; | 90 | struct option_set *existing, *new, **curr; |
91 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
92 | char *allocated = NULL; | ||
93 | #endif | ||
95 | 94 | ||
96 | existing = find_option(*opt_list, option->code); | 95 | existing = find_option(*opt_list, option->code); |
97 | if (!existing) { | 96 | if (!existing) { |
98 | log2("Attaching option %02x to list", option->code); | 97 | log2("Attaching option %02x to list", option->code); |
99 | |||
100 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 98 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
101 | if ((option->flags & OPTION_TYPE_MASK) == OPTION_STR1035) | 99 | if ((option->flags & OPTION_TYPE_MASK) == OPTION_STR1035) { |
102 | /* reuse buffer and length for RFC1035-formatted string */ | 100 | /* reuse buffer and length for RFC1035-formatted string */ |
103 | buffer = (char *)dname_enc(NULL, 0, buffer, &length); | 101 | allocated = buffer = (char *)dname_enc(NULL, 0, buffer, &length); |
102 | } | ||
104 | #endif | 103 | #endif |
105 | |||
106 | /* make a new option */ | 104 | /* make a new option */ |
107 | new = xmalloc(sizeof(*new)); | 105 | new = xmalloc(sizeof(*new)); |
108 | new->data = xmalloc(length + 2); | 106 | new->data = xmalloc(length + OPT_DATA); |
109 | new->data[OPT_CODE] = option->code; | 107 | new->data[OPT_CODE] = option->code; |
110 | new->data[OPT_LEN] = length; | 108 | new->data[OPT_LEN] = length; |
111 | memcpy(new->data + 2, buffer, length); | 109 | memcpy(new->data + OPT_DATA, buffer, length); |
112 | 110 | ||
113 | curr = opt_list; | 111 | curr = opt_list; |
114 | while (*curr && (*curr)->data[OPT_CODE] < option->code) | 112 | while (*curr && (*curr)->data[OPT_CODE] < option->code) |
@@ -116,44 +114,41 @@ static void attach_option(struct option_set **opt_list, | |||
116 | 114 | ||
117 | new->next = *curr; | 115 | new->next = *curr; |
118 | *curr = new; | 116 | *curr = new; |
119 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 117 | goto ret; |
120 | if ((option->flags & OPTION_TYPE_MASK) == OPTION_STR1035 && buffer != NULL) | ||
121 | free(buffer); | ||
122 | #endif | ||
123 | return; | ||
124 | } | 118 | } |
125 | 119 | ||
126 | /* add it to an existing option */ | ||
127 | log1("Attaching option %02x to existing member of list", option->code); | ||
128 | if (option->flags & OPTION_LIST) { | 120 | if (option->flags & OPTION_LIST) { |
121 | unsigned old_len; | ||
122 | |||
123 | /* add it to an existing option */ | ||
124 | log1("Attaching option %02x to existing member of list", option->code); | ||
125 | old_len = existing->data[OPT_LEN]; | ||
129 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 126 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
130 | if ((option->flags & OPTION_TYPE_MASK) == OPTION_STR1035) | 127 | if ((option->flags & OPTION_TYPE_MASK) == OPTION_STR1035) { |
131 | /* reuse buffer and length for RFC1035-formatted string */ | 128 | /* reuse buffer and length for RFC1035-formatted string */ |
132 | buffer = (char *)dname_enc(existing->data + 2, | 129 | allocated = buffer = (char *)dname_enc(existing->data + OPT_DATA, old_len, buffer, &length); |
133 | existing->data[OPT_LEN], buffer, &length); | 130 | } |
134 | #endif | 131 | #endif |
135 | if (existing->data[OPT_LEN] + length <= 255) { | 132 | if (old_len + length < 255) { |
136 | existing->data = xrealloc(existing->data, | 133 | /* actually 255 is ok too, but adding a space can overlow it */ |
137 | existing->data[OPT_LEN] + length + 3); | 134 | |
135 | existing->data = xrealloc(existing->data, OPT_DATA + 1 + old_len + length); | ||
138 | if ((option->flags & OPTION_TYPE_MASK) == OPTION_STRING) { | 136 | if ((option->flags & OPTION_TYPE_MASK) == OPTION_STRING) { |
139 | /* ' ' can bring us to 256 - bad */ | ||
140 | if (existing->data[OPT_LEN] + length >= 255) | ||
141 | return; | ||
142 | /* add space separator between STRING options in a list */ | 137 | /* add space separator between STRING options in a list */ |
143 | existing->data[existing->data[OPT_LEN] + 2] = ' '; | 138 | existing->data[OPT_DATA + old_len] = ' '; |
144 | existing->data[OPT_LEN]++; | 139 | old_len++; |
145 | } | 140 | } |
146 | memcpy(existing->data + existing->data[OPT_LEN] + 2, buffer, length); | 141 | memcpy(existing->data + OPT_DATA + old_len, buffer, length); |
147 | existing->data[OPT_LEN] += length; | 142 | existing->data[OPT_LEN] = old_len + length; |
148 | } /* else, ignore the data, we could put this in a second option in the future */ | 143 | } /* else, ignore the data, we could put this in a second option in the future */ |
144 | } /* else, ignore the new data */ | ||
145 | |||
146 | ret: ; | ||
149 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 147 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
150 | if ((option->flags & OPTION_TYPE_MASK) == OPTION_STR1035 && buffer != NULL) | 148 | free(allocated); |
151 | free(buffer); | ||
152 | #endif | 149 | #endif |
153 | } /* else, ignore the new data */ | ||
154 | } | 150 | } |
155 | 151 | ||
156 | |||
157 | /* read a dhcp option and add it to opt_list */ | 152 | /* read a dhcp option and add it to opt_list */ |
158 | static int FAST_FUNC read_opt(const char *const_line, void *arg) | 153 | static int FAST_FUNC read_opt(const char *const_line, void *arg) |
159 | { | 154 | { |
@@ -166,7 +161,7 @@ static int FAST_FUNC read_opt(const char *const_line, void *arg) | |||
166 | uint16_t *result_u16 = (uint16_t *) buffer; | 161 | uint16_t *result_u16 = (uint16_t *) buffer; |
167 | uint32_t *result_u32 = (uint32_t *) buffer; | 162 | uint32_t *result_u32 = (uint32_t *) buffer; |
168 | 163 | ||
169 | /* Cheat, the only const line we'll actually get is "" */ | 164 | /* Cheat, the only *const* line possible is "" */ |
170 | line = (char *) const_line; | 165 | line = (char *) const_line; |
171 | opt = strtok(line, " \t="); | 166 | opt = strtok(line, " \t="); |
172 | if (!opt) | 167 | if (!opt) |
@@ -180,7 +175,8 @@ static int FAST_FUNC read_opt(const char *const_line, void *arg) | |||
180 | retval = 0; | 175 | retval = 0; |
181 | do { | 176 | do { |
182 | val = strtok(NULL, ", \t"); | 177 | val = strtok(NULL, ", \t"); |
183 | if (!val) break; | 178 | if (!val) |
179 | break; | ||
184 | length = dhcp_option_lengths[option->flags & OPTION_TYPE_MASK]; | 180 | length = dhcp_option_lengths[option->flags & OPTION_TYPE_MASK]; |
185 | retval = 0; | 181 | retval = 0; |
186 | opt = buffer; /* new meaning for variable opt */ | 182 | opt = buffer; /* new meaning for variable opt */ |
@@ -337,7 +333,6 @@ void FAST_FUNC read_config(const char *file) | |||
337 | server_config.end_ip = ntohl(server_config.end_ip); | 333 | server_config.end_ip = ntohl(server_config.end_ip); |
338 | } | 334 | } |
339 | 335 | ||
340 | |||
341 | void FAST_FUNC write_leases(void) | 336 | void FAST_FUNC write_leases(void) |
342 | { | 337 | { |
343 | int fd; | 338 | int fd; |
@@ -385,7 +380,6 @@ void FAST_FUNC write_leases(void) | |||
385 | } | 380 | } |
386 | } | 381 | } |
387 | 382 | ||
388 | |||
389 | void FAST_FUNC read_leases(const char *file) | 383 | void FAST_FUNC read_leases(const char *file) |
390 | { | 384 | { |
391 | struct dyn_lease lease; | 385 | struct dyn_lease lease; |