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.c59
1 files changed, 25 insertions, 34 deletions
diff --git a/networking/udhcp/script.c b/networking/udhcp/script.c
index 48ff8e07e..41b680d6b 100644
--- a/networking/udhcp/script.c
+++ b/networking/udhcp/script.c
@@ -28,17 +28,15 @@
28#include <arpa/inet.h> 28#include <arpa/inet.h>
29#include <sys/types.h> 29#include <sys/types.h>
30#include <sys/wait.h> 30#include <sys/wait.h>
31#include <errno.h>
32 31
33#include "options.h" 32#include "options.h"
34#include "dhcpd.h" 33#include "dhcpd.h"
35#include "dhcpc.h" 34#include "dhcpc.h"
36#include "packet.h"
37#include "options.h" 35#include "options.h"
38#include "debug.h" 36#include "common.h"
39 37
40/* get a rough idea of how long an option will be (rounding up...) */ 38/* get a rough idea of how long an option will be (rounding up...) */
41static int max_option_length[] = { 39static const int max_option_length[] = {
42 [OPTION_IP] = sizeof("255.255.255.255 "), 40 [OPTION_IP] = sizeof("255.255.255.255 "),
43 [OPTION_IP_PAIR] = sizeof("255.255.255.255 ") * 2, 41 [OPTION_IP_PAIR] = sizeof("255.255.255.255 ") * 2,
44 [OPTION_STRING] = 1, 42 [OPTION_STRING] = 1,
@@ -51,16 +49,21 @@ static int max_option_length[] = {
51}; 49};
52 50
53 51
54static int upper_length(int length, struct dhcp_option *option) 52static inline int upper_length(int length, int opt_index)
55{ 53{
56 return max_option_length[option->flags & TYPE_MASK] * 54 return max_option_length[opt_index] *
57 (length / option_lengths[option->flags & TYPE_MASK]); 55 (length / option_lengths[opt_index]);
58} 56}
59 57
60 58
61static int sprintip(char *dest, char *pre, unsigned char *ip) 59static int sprintip(char *dest, unsigned char *ip)
62{ 60{
63 return sprintf(dest, "%s%d.%d.%d.%d", pre, ip[0], ip[1], ip[2], ip[3]); 61 return sprintf(dest, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
62}
63
64static void asprintip(char **dest, char *pre, unsigned char *ip)
65{
66 asprintf(dest, "%s%d.%d.%d.%d", pre, ip[0], ip[1], ip[2], ip[3]);
64} 67}
65 68
66 69
@@ -93,12 +96,12 @@ static void fill_options(char *dest, unsigned char *option, struct dhcp_option *
93 for(;;) { 96 for(;;) {
94 switch (type) { 97 switch (type) {
95 case OPTION_IP_PAIR: 98 case OPTION_IP_PAIR:
96 dest += sprintip(dest, "", option); 99 dest += sprintip(dest, option);
97 *(dest++) = '/'; 100 *(dest++) = '/';
98 option += 4; 101 option += 4;
99 optlen = 4; 102 optlen = 4;
100 case OPTION_IP: /* Works regardless of host byte order. */ 103 case OPTION_IP: /* Works regardless of host byte order. */
101 dest += sprintip(dest, "", option); 104 dest += sprintip(dest, option);
102 break; 105 break;
103 case OPTION_BOOLEAN: 106 case OPTION_BOOLEAN:
104 dest += sprintf(dest, *option ? "yes" : "no"); 107 dest += sprintf(dest, *option ? "yes" : "no");
@@ -137,15 +140,10 @@ static void fill_options(char *dest, unsigned char *option, struct dhcp_option *
137 140
138static char *find_env(const char *prefix, char *defaultstr) 141static char *find_env(const char *prefix, char *defaultstr)
139{ 142{
140 extern char **environ; 143 char *ptr;
141 char **ptr;
142 const int len = strlen(prefix);
143 144
144 for (ptr = environ; *ptr != NULL; ptr++) { 145 ptr = getenv(prefix);
145 if (strncmp(prefix, *ptr, len) == 0) 146 return ptr ? ptr : defaultstr;
146 return *ptr;
147 }
148 return defaultstr;
149} 147}
150 148
151 149
@@ -174,8 +172,7 @@ static char **fill_envp(struct dhcpMessage *packet)
174 172
175 envp = xmalloc((num_options + 5) * sizeof(char *)); 173 envp = xmalloc((num_options + 5) * sizeof(char *));
176 j = 0; 174 j = 0;
177 envp[j++] = xmalloc(sizeof("interface=") + strlen(client_config.interface)); 175 asprintf(&envp[j++], "interface=%s", client_config.interface);
178 sprintf(envp[0], "interface=%s", client_config.interface);
179 envp[j++] = find_env("PATH", "PATH=/bin:/usr/bin:/sbin:/usr/sbin"); 176 envp[j++] = find_env("PATH", "PATH=/bin:/usr/bin:/sbin:/usr/sbin");
180 envp[j++] = find_env("HOME", "HOME=/"); 177 envp[j++] = find_env("HOME", "HOME=/");
181 178
@@ -184,38 +181,33 @@ static char **fill_envp(struct dhcpMessage *packet)
184 return envp; 181 return envp;
185 } 182 }
186 183
187 envp[j] = xmalloc(sizeof("ip=255.255.255.255")); 184 asprintip(&envp[j++], "ip=", (unsigned char *) &packet->yiaddr);
188 sprintip(envp[j++], "ip=", (unsigned char *) &packet->yiaddr);
189 185
190 186
191 for (i = 0; options[i].code; i++) { 187 for (i = 0; options[i].code; i++) {
192 if (!(temp = get_option(packet, options[i].code))) 188 if (!(temp = get_option(packet, options[i].code)))
193 continue; 189 continue;
194 envp[j] = xmalloc(upper_length(temp[OPT_LEN - 2], &options[i]) + strlen(options[i].name) + 2); 190 envp[j] = xmalloc(upper_length(temp[OPT_LEN - 2], options[i].flags & TYPE_MASK) + strlen(options[i].name) + 2);
195 fill_options(envp[j++], temp, &options[i]); 191 fill_options(envp[j++], temp, &options[i]);
196 192
197 /* Fill in a subnet bits option for things like /24 */ 193 /* Fill in a subnet bits option for things like /24 */
198 if (options[i].code == DHCP_SUBNET) { 194 if (options[i].code == DHCP_SUBNET) {
199 envp[j] = xmalloc(sizeof("mask=32"));
200 memcpy(&subnet, temp, 4); 195 memcpy(&subnet, temp, 4);
201 sprintf(envp[j++], "mask=%d", mton(&subnet)); 196 asprintf(&envp[j++], "mask=%d", mton(&subnet));
202 } 197 }
203 } 198 }
204 if (packet->siaddr) { 199 if (packet->siaddr) {
205 envp[j] = xmalloc(sizeof("siaddr=255.255.255.255")); 200 asprintip(&envp[j++], "siaddr=", (unsigned char *) &packet->siaddr);
206 sprintip(envp[j++], "siaddr=", (unsigned char *) &packet->siaddr);
207 } 201 }
208 if (!(over & FILE_FIELD) && packet->file[0]) { 202 if (!(over & FILE_FIELD) && packet->file[0]) {
209 /* watch out for invalid packets */ 203 /* watch out for invalid packets */
210 packet->file[sizeof(packet->file) - 1] = '\0'; 204 packet->file[sizeof(packet->file) - 1] = '\0';
211 envp[j] = xmalloc(sizeof("boot_file=") + strlen(packet->file)); 205 asprintf(&envp[j++], "boot_file=%s", packet->file);
212 sprintf(envp[j++], "boot_file=%s", packet->file);
213 } 206 }
214 if (!(over & SNAME_FIELD) && packet->sname[0]) { 207 if (!(over & SNAME_FIELD) && packet->sname[0]) {
215 /* watch out for invalid packets */ 208 /* watch out for invalid packets */
216 packet->sname[sizeof(packet->sname) - 1] = '\0'; 209 packet->sname[sizeof(packet->sname) - 1] = '\0';
217 envp[j] = xmalloc(sizeof("sname=") + strlen(packet->sname)); 210 asprintf(&envp[j++], "sname=%s", packet->sname);
218 sprintf(envp[j++], "sname=%s", packet->sname);
219 } 211 }
220 envp[j] = NULL; 212 envp[j] = NULL;
221 return envp; 213 return envp;
@@ -245,8 +237,7 @@ void run_script(struct dhcpMessage *packet, const char *name)
245 DEBUG(LOG_INFO, "execle'ing %s", client_config.script); 237 DEBUG(LOG_INFO, "execle'ing %s", client_config.script);
246 execle(client_config.script, client_config.script, 238 execle(client_config.script, client_config.script,
247 name, NULL, envp); 239 name, NULL, envp);
248 LOG(LOG_ERR, "script %s failed: %s", 240 LOG(LOG_ERR, "script %s failed: %m", client_config.script);
249 client_config.script, strerror(errno));
250 exit(1); 241 exit(1);
251 } 242 }
252} 243}