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.c99
1 files changed, 39 insertions, 60 deletions
diff --git a/networking/udhcp/script.c b/networking/udhcp/script.c
index 1c6f1bd33..2eb4459dd 100644
--- a/networking/udhcp/script.c
+++ b/networking/udhcp/script.c
@@ -37,8 +37,6 @@
37#include "options.h" 37#include "options.h"
38#include "debug.h" 38#include "debug.h"
39 39
40#include "config.h"
41
42/* get a rough idea of how long an option will be (rounding up...) */ 40/* get a rough idea of how long an option will be (rounding up...) */
43static int max_option_length[] = { 41static int max_option_length[] = {
44 [OPTION_IP] = sizeof("255.255.255.255 "), 42 [OPTION_IP] = sizeof("255.255.255.255 "),
@@ -60,41 +58,22 @@ static int upper_length(int length, struct dhcp_option *option)
60} 58}
61 59
62 60
63static int sprintip(char *dest, char *pre, unsigned char *ip) { 61static int sprintip(char *dest, char *pre, unsigned char *ip)
64 return sprintf(dest, "%s%d.%d.%d.%d ", pre, ip[0], ip[1], ip[2], ip[3]);
65}
66
67#ifdef CONFIG_FEATURE_UDHCPC_IP
68/* convert a netmask (255.255.255.0) into the length (24) */
69static int inet_ntom (const char *src, short *dst)
70{ 62{
71 in_addr_t mask, num; 63 return sprintf(dest, "%s%d.%d.%d.%d", pre, ip[0], ip[1], ip[2], ip[3]);
72 64}
73 mask = ntohl(*(unsigned int *)src);
74
75 for (num = mask; num & 1; num >>= 1);
76
77 if (num != 0 && mask != 0)
78 {
79 for (num = ~mask; num & 1; num >>= 1);
80 if (num)
81 return 0;
82 }
83
84 for (num = 0; mask; mask <<= 1)
85 num++;
86 65
87 *dst = num;
88 66
89 return 1; 67/* really simple implementation, just count the bits */
68static int mton(struct in_addr *mask)
69{
70 int i;
71 /* note: mask will always be in network byte order, so
72 * there are no endian issues */
73 for (i = 31; i >= 0 && !((mask->s_addr >> i) & 1); i--);
74 return i + 1;
90} 75}
91 76
92static int sprintprefix(char *dest, char *pre, unsigned char *ip) {
93 short sdest = 0;
94 inet_ntom(ip, &sdest);
95 return sprintf(dest, "%s%hd ", pre, sdest);
96}
97#endif
98 77
99/* Fill dest with the text of option 'option'. */ 78/* Fill dest with the text of option 'option'. */
100static void fill_options(char *dest, unsigned char *option, struct dhcp_option *type_p) 79static void fill_options(char *dest, unsigned char *option, struct dhcp_option *type_p)
@@ -117,41 +96,30 @@ static void fill_options(char *dest, unsigned char *option, struct dhcp_option *
117 *(dest++) = '/'; 96 *(dest++) = '/';
118 option += 4; 97 option += 4;
119 optlen = 4; 98 optlen = 4;
120#ifndef CONFIG_FEATURE_UDHCPC_IP
121 case OPTION_IP: /* Works regardless of host byte order. */ 99 case OPTION_IP: /* Works regardless of host byte order. */
122#endif
123 dest += sprintip(dest, "", option); 100 dest += sprintip(dest, "", option);
124 break; 101 break;
125#ifdef CONFIG_FEATURE_UDHCPC_IP
126 case OPTION_IP: /* Works regardless of host byte order. */
127 if (type_p->flags & OPTION_PREFIX) {
128 dest += sprintprefix(dest, "", option);
129 } else {
130 dest += sprintip(dest, "", option);
131 }
132 break;
133#endif
134 case OPTION_BOOLEAN: 102 case OPTION_BOOLEAN:
135 dest += sprintf(dest, *option ? "yes " : "no "); 103 dest += sprintf(dest, *option ? "yes" : "no");
136 break; 104 break;
137 case OPTION_U8: 105 case OPTION_U8:
138 dest += sprintf(dest, "%u ", *option); 106 dest += sprintf(dest, "%u", *option);
139 break; 107 break;
140 case OPTION_U16: 108 case OPTION_U16:
141 memcpy(&val_u16, option, 2); 109 memcpy(&val_u16, option, 2);
142 dest += sprintf(dest, "%u ", ntohs(val_u16)); 110 dest += sprintf(dest, "%u", ntohs(val_u16));
143 break; 111 break;
144 case OPTION_S16: 112 case OPTION_S16:
145 memcpy(&val_s16, option, 2); 113 memcpy(&val_s16, option, 2);
146 dest += sprintf(dest, "%d ", ntohs(val_s16)); 114 dest += sprintf(dest, "%d", ntohs(val_s16));
147 break; 115 break;
148 case OPTION_U32: 116 case OPTION_U32:
149 memcpy(&val_u32, option, 4); 117 memcpy(&val_u32, option, 4);
150 dest += sprintf(dest, "%lu ", (unsigned long) ntohl(val_u32)); 118 dest += sprintf(dest, "%lu", (unsigned long) ntohl(val_u32));
151 break; 119 break;
152 case OPTION_S32: 120 case OPTION_S32:
153 memcpy(&val_s32, option, 4); 121 memcpy(&val_s32, option, 4);
154 dest += sprintf(dest, "%ld ", (long) ntohl(val_s32)); 122 dest += sprintf(dest, "%ld", (long) ntohl(val_s32));
155 break; 123 break;
156 case OPTION_STRING: 124 case OPTION_STRING:
157 memcpy(dest, option, len); 125 memcpy(dest, option, len);
@@ -161,6 +129,7 @@ static void fill_options(char *dest, unsigned char *option, struct dhcp_option *
161 option += optlen; 129 option += optlen;
162 len -= optlen; 130 len -= optlen;
163 if (len <= 0) break; 131 if (len <= 0) break;
132 dest += sprintf(dest, " ");
164 } 133 }
165} 134}
166 135
@@ -186,6 +155,7 @@ static char **fill_envp(struct dhcpMessage *packet)
186 int i, j; 155 int i, j;
187 char **envp; 156 char **envp;
188 unsigned char *temp; 157 unsigned char *temp;
158 struct in_addr subnet;
189 char over = 0; 159 char over = 0;
190 160
191 if (packet == NULL) 161 if (packet == NULL)
@@ -202,23 +172,32 @@ static char **fill_envp(struct dhcpMessage *packet)
202 } 172 }
203 173
204 envp = xmalloc((num_options + 5) * sizeof(char *)); 174 envp = xmalloc((num_options + 5) * sizeof(char *));
205 envp[0] = xmalloc(sizeof("interface=") + strlen(client_config.interface)); 175 j = 0;
176 envp[j++] = xmalloc(sizeof("interface=") + strlen(client_config.interface));
206 sprintf(envp[0], "interface=%s", client_config.interface); 177 sprintf(envp[0], "interface=%s", client_config.interface);
207 envp[1] = find_env("PATH", "PATH=/bin:/usr/bin:/sbin:/usr/sbin"); 178 envp[j++] = find_env("PATH", "PATH=/bin:/usr/bin:/sbin:/usr/sbin");
208 envp[2] = find_env("HOME", "HOME=/"); 179 envp[j++] = find_env("HOME", "HOME=/");
209 180
210 if (packet == NULL) { 181 if (packet == NULL) {
211 envp[3] = NULL; 182 envp[j++] = NULL;
212 return envp; 183 return envp;
213 } 184 }
214 185
215 envp[3] = xmalloc(sizeof("ip=255.255.255.255")); 186 envp[j] = xmalloc(sizeof("ip=255.255.255.255"));
216 sprintip(envp[3], "ip=", (unsigned char *) &packet->yiaddr); 187 sprintip(envp[j++], "ip=", (unsigned char *) &packet->yiaddr);
217 for (i = 0, j = 4; options[i].code; i++) { 188
218 if ((temp = get_option(packet, options[i].code))) { 189
219 envp[j] = xmalloc(upper_length(temp[OPT_LEN - 2], &options[i]) + strlen(options[i].name) + 2); 190 for (i = 0; options[i].code; i++) {
220 fill_options(envp[j], temp, &options[i]); 191 if (!(temp = get_option(packet, options[i].code)))
221 j++; 192 continue;
193 envp[j] = xmalloc(upper_length(temp[OPT_LEN - 2], &options[i]) + strlen(options[i].name) + 2);
194 fill_options(envp[j++], temp, &options[i]);
195
196 /* Fill in a subnet bits option for things like /24 */
197 if (options[i].code == DHCP_SUBNET) {
198 envp[j] = xmalloc(sizeof("mask=32"));
199 memcpy(&subnet, temp, 4);
200 sprintf(envp[j++], "mask=%d", mton(&subnet));
222 } 201 }
223 } 202 }
224 if (packet->siaddr) { 203 if (packet->siaddr) {