diff options
Diffstat (limited to 'networking/udhcp/options.c')
-rw-r--r-- | networking/udhcp/options.c | 262 |
1 files changed, 0 insertions, 262 deletions
diff --git a/networking/udhcp/options.c b/networking/udhcp/options.c deleted file mode 100644 index af3c217e8..000000000 --- a/networking/udhcp/options.c +++ /dev/null | |||
@@ -1,262 +0,0 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * options.c -- DHCP server option packet tools | ||
4 | * Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001 | ||
5 | * | ||
6 | * Licensed under GPLv2, see file LICENSE in this tarball for details. | ||
7 | */ | ||
8 | |||
9 | #include "common.h" | ||
10 | |||
11 | |||
12 | /* Supported options are easily added here. | ||
13 | * See RFC2132 for more options. | ||
14 | * OPTION_REQ: these options are requested by udhcpc (unless -o). | ||
15 | */ | ||
16 | const struct dhcp_option dhcp_options[] = { | ||
17 | /* flags code */ | ||
18 | { OPTION_IP | OPTION_REQ, 0x01 }, /* DHCP_SUBNET */ | ||
19 | { OPTION_S32 , 0x02 }, /* DHCP_TIME_OFFSET */ | ||
20 | { OPTION_IP | OPTION_LIST | OPTION_REQ, 0x03 }, /* DHCP_ROUTER */ | ||
21 | // { OPTION_IP | OPTION_LIST , 0x04 }, /* DHCP_TIME_SERVER */ | ||
22 | // { OPTION_IP | OPTION_LIST , 0x05 }, /* DHCP_NAME_SERVER */ | ||
23 | { OPTION_IP | OPTION_LIST | OPTION_REQ, 0x06 }, /* DHCP_DNS_SERVER */ | ||
24 | // { OPTION_IP | OPTION_LIST , 0x07 }, /* DHCP_LOG_SERVER */ | ||
25 | // { OPTION_IP | OPTION_LIST , 0x08 }, /* DHCP_COOKIE_SERVER */ | ||
26 | { OPTION_IP | OPTION_LIST , 0x09 }, /* DHCP_LPR_SERVER */ | ||
27 | { OPTION_STRING | OPTION_REQ, 0x0c }, /* DHCP_HOST_NAME */ | ||
28 | { OPTION_U16 , 0x0d }, /* DHCP_BOOT_SIZE */ | ||
29 | { OPTION_STRING | OPTION_REQ, 0x0f }, /* DHCP_DOMAIN_NAME */ | ||
30 | { OPTION_IP , 0x10 }, /* DHCP_SWAP_SERVER */ | ||
31 | { OPTION_STRING , 0x11 }, /* DHCP_ROOT_PATH */ | ||
32 | { OPTION_U8 , 0x17 }, /* DHCP_IP_TTL */ | ||
33 | { OPTION_U16 , 0x1a }, /* DHCP_MTU */ | ||
34 | { OPTION_IP | OPTION_REQ, 0x1c }, /* DHCP_BROADCAST */ | ||
35 | { OPTION_STRING , 0x28 }, /* DHCP_NIS_DOMAIN */ | ||
36 | { OPTION_IP | OPTION_LIST , 0x29 }, /* DHCP_NIS_SERVER */ | ||
37 | { OPTION_IP | OPTION_LIST | OPTION_REQ, 0x2a }, /* DHCP_NTP_SERVER */ | ||
38 | { OPTION_IP | OPTION_LIST , 0x2c }, /* DHCP_WINS_SERVER */ | ||
39 | { OPTION_U32 , 0x33 }, /* DHCP_LEASE_TIME */ | ||
40 | { OPTION_IP , 0x36 }, /* DHCP_SERVER_ID */ | ||
41 | { OPTION_STRING , 0x38 }, /* DHCP_ERR_MESSAGE */ | ||
42 | //TODO: must be combined with 'sname' and 'file' handling: | ||
43 | { OPTION_STRING , 0x42 }, /* DHCP_TFTP_SERVER_NAME */ | ||
44 | { OPTION_STRING , 0x43 }, /* DHCP_BOOT_FILE */ | ||
45 | //TODO: not a string, but a set of LASCII strings: | ||
46 | // { OPTION_STRING , 0x4D }, /* DHCP_USER_CLASS */ | ||
47 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
48 | { OPTION_STR1035 | OPTION_LIST , 0x77 }, /* DHCP_DOMAIN_SEARCH */ | ||
49 | #endif | ||
50 | { OPTION_STATIC_ROUTES , 0x79 }, /* DHCP_STATIC_ROUTES */ | ||
51 | { OPTION_STRING , 0xfc }, /* DHCP_WPAD */ | ||
52 | |||
53 | /* Options below have no match in dhcp_option_strings[], | ||
54 | * are not passed to dhcpc scripts, and cannot be specified | ||
55 | * with "option XXX YYY" syntax in dhcpd config file. | ||
56 | * These entries are only used internally by udhcp[cd] | ||
57 | * to correctly encode options into packets. | ||
58 | */ | ||
59 | |||
60 | { OPTION_IP , 0x32 }, /* DHCP_REQUESTED_IP */ | ||
61 | { OPTION_U8 , 0x35 }, /* DHCP_MESSAGE_TYPE */ | ||
62 | { OPTION_U16 , 0x39 }, /* DHCP_MAX_SIZE */ | ||
63 | { OPTION_STRING , 0x3c }, /* DHCP_VENDOR */ | ||
64 | //FIXME: handling of this option is not exactly correct: | ||
65 | { OPTION_STRING , 0x3d }, /* DHCP_CLIENT_ID */ | ||
66 | { 0, 0 } /* zeroed terminating entry */ | ||
67 | }; | ||
68 | |||
69 | /* Used for converting options from incoming packets to env variables | ||
70 | * for udhcpc stript, and for setting options for udhcpd via | ||
71 | * "opt OPTION_NAME OPTION_VALUE" directives in udhcpd.conf file. | ||
72 | */ | ||
73 | /* Must match dhcp_options[] order */ | ||
74 | const char dhcp_option_strings[] ALIGN1 = | ||
75 | "subnet" "\0" /* DHCP_SUBNET */ | ||
76 | "timezone" "\0" /* DHCP_TIME_OFFSET */ | ||
77 | "router" "\0" /* DHCP_ROUTER */ | ||
78 | // "timesrv" "\0" /* DHCP_TIME_SERVER */ | ||
79 | // "namesrv" "\0" /* DHCP_NAME_SERVER */ | ||
80 | "dns" "\0" /* DHCP_DNS_SERVER */ | ||
81 | // "logsrv" "\0" /* DHCP_LOG_SERVER */ | ||
82 | // "cookiesrv" "\0" /* DHCP_COOKIE_SERVER */ | ||
83 | "lprsrv" "\0" /* DHCP_LPR_SERVER */ | ||
84 | "hostname" "\0" /* DHCP_HOST_NAME */ | ||
85 | "bootsize" "\0" /* DHCP_BOOT_SIZE */ | ||
86 | "domain" "\0" /* DHCP_DOMAIN_NAME */ | ||
87 | "swapsrv" "\0" /* DHCP_SWAP_SERVER */ | ||
88 | "rootpath" "\0" /* DHCP_ROOT_PATH */ | ||
89 | "ipttl" "\0" /* DHCP_IP_TTL */ | ||
90 | "mtu" "\0" /* DHCP_MTU */ | ||
91 | "broadcast" "\0" /* DHCP_BROADCAST */ | ||
92 | "nisdomain" "\0" /* DHCP_NIS_DOMAIN */ | ||
93 | "nissrv" "\0" /* DHCP_NIS_SERVER */ | ||
94 | "ntpsrv" "\0" /* DHCP_NTP_SERVER */ | ||
95 | "wins" "\0" /* DHCP_WINS_SERVER */ | ||
96 | "lease" "\0" /* DHCP_LEASE_TIME */ | ||
97 | "serverid" "\0" /* DHCP_SERVER_ID */ | ||
98 | "message" "\0" /* DHCP_ERR_MESSAGE */ | ||
99 | "tftp" "\0" /* DHCP_TFTP_SERVER_NAME */ | ||
100 | "bootfile" "\0" /* DHCP_BOOT_FILE */ | ||
101 | // "userclass" "\0" /* DHCP_USER_CLASS */ | ||
102 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
103 | "search" "\0" /* DHCP_DOMAIN_SEARCH */ | ||
104 | #endif | ||
105 | // "staticroutes" is only used to set udhcpc environment, it doesn't work | ||
106 | // in udhcpd.conf since OPTION_STATIC_ROUTES is not handled yet | ||
107 | // by "string->option" conversion code: | ||
108 | "staticroutes" "\0"/* DHCP_STATIC_ROUTES */ | ||
109 | "wpad" "\0" /* DHCP_WPAD */ | ||
110 | ; | ||
111 | |||
112 | /* Lengths of the different option types */ | ||
113 | const uint8_t dhcp_option_lengths[] ALIGN1 = { | ||
114 | [OPTION_IP] = 4, | ||
115 | [OPTION_IP_PAIR] = 8, | ||
116 | [OPTION_BOOLEAN] = 1, | ||
117 | [OPTION_STRING] = 1, | ||
118 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
119 | [OPTION_STR1035] = 1, | ||
120 | #endif | ||
121 | [OPTION_U8] = 1, | ||
122 | [OPTION_U16] = 2, | ||
123 | [OPTION_S16] = 2, | ||
124 | [OPTION_U32] = 4, | ||
125 | [OPTION_S32] = 4, | ||
126 | /* Just like OPTION_STRING, we use minimum length here */ | ||
127 | [OPTION_STATIC_ROUTES] = 5, | ||
128 | }; | ||
129 | |||
130 | |||
131 | #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2 | ||
132 | static void log_option(const char *pfx, const uint8_t *opt) | ||
133 | { | ||
134 | if (dhcp_verbose >= 2) { | ||
135 | char buf[256 * 2 + 2]; | ||
136 | *bin2hex(buf, (void*) (opt + OPT_DATA), opt[OPT_LEN]) = '\0'; | ||
137 | bb_info_msg("%s: 0x%02x %s", pfx, opt[OPT_CODE], buf); | ||
138 | } | ||
139 | } | ||
140 | #else | ||
141 | # define log_option(pfx, opt) ((void)0) | ||
142 | #endif | ||
143 | |||
144 | /* get an option with bounds checking (warning, result is not aligned). */ | ||
145 | uint8_t* FAST_FUNC udhcp_get_option(struct dhcp_packet *packet, int code) | ||
146 | { | ||
147 | uint8_t *optionptr; | ||
148 | int len; | ||
149 | int rem; | ||
150 | int overload = 0; | ||
151 | enum { | ||
152 | FILE_FIELD101 = FILE_FIELD * 0x101, | ||
153 | SNAME_FIELD101 = SNAME_FIELD * 0x101, | ||
154 | }; | ||
155 | |||
156 | /* option bytes: [code][len][data1][data2]..[dataLEN] */ | ||
157 | optionptr = packet->options; | ||
158 | rem = sizeof(packet->options); | ||
159 | while (1) { | ||
160 | if (rem <= 0) { | ||
161 | bb_error_msg("bad packet, malformed option field"); | ||
162 | return NULL; | ||
163 | } | ||
164 | if (optionptr[OPT_CODE] == DHCP_PADDING) { | ||
165 | rem--; | ||
166 | optionptr++; | ||
167 | continue; | ||
168 | } | ||
169 | if (optionptr[OPT_CODE] == DHCP_END) { | ||
170 | if ((overload & FILE_FIELD101) == FILE_FIELD) { | ||
171 | /* can use packet->file, and didn't look at it yet */ | ||
172 | overload |= FILE_FIELD101; /* "we looked at it" */ | ||
173 | optionptr = packet->file; | ||
174 | rem = sizeof(packet->file); | ||
175 | continue; | ||
176 | } | ||
177 | if ((overload & SNAME_FIELD101) == SNAME_FIELD) { | ||
178 | /* can use packet->sname, and didn't look at it yet */ | ||
179 | overload |= SNAME_FIELD101; /* "we looked at it" */ | ||
180 | optionptr = packet->sname; | ||
181 | rem = sizeof(packet->sname); | ||
182 | continue; | ||
183 | } | ||
184 | break; | ||
185 | } | ||
186 | len = 2 + optionptr[OPT_LEN]; | ||
187 | rem -= len; | ||
188 | if (rem < 0) | ||
189 | continue; /* complain and return NULL */ | ||
190 | |||
191 | if (optionptr[OPT_CODE] == code) { | ||
192 | log_option("Option found", optionptr); | ||
193 | return optionptr + OPT_DATA; | ||
194 | } | ||
195 | |||
196 | if (optionptr[OPT_CODE] == DHCP_OPTION_OVERLOAD) { | ||
197 | overload |= optionptr[OPT_DATA]; | ||
198 | /* fall through */ | ||
199 | } | ||
200 | optionptr += len; | ||
201 | } | ||
202 | |||
203 | /* log3 because udhcpc uses it a lot - very noisy */ | ||
204 | log3("Option 0x%02x not found", code); | ||
205 | return NULL; | ||
206 | } | ||
207 | |||
208 | /* return the position of the 'end' option (no bounds checking) */ | ||
209 | int FAST_FUNC udhcp_end_option(uint8_t *optionptr) | ||
210 | { | ||
211 | int i = 0; | ||
212 | |||
213 | while (optionptr[i] != DHCP_END) { | ||
214 | if (optionptr[i] != DHCP_PADDING) | ||
215 | i += optionptr[i + OPT_LEN] + OPT_DATA-1; | ||
216 | i++; | ||
217 | } | ||
218 | return i; | ||
219 | } | ||
220 | |||
221 | /* add an option string to the options */ | ||
222 | /* option bytes: [code][len][data1][data2]..[dataLEN] */ | ||
223 | void FAST_FUNC udhcp_add_option_string(uint8_t *optionptr, uint8_t *string) | ||
224 | { | ||
225 | unsigned len; | ||
226 | unsigned end = udhcp_end_option(optionptr); | ||
227 | |||
228 | /* end position + string length + option code/length + end option */ | ||
229 | if (end + string[OPT_LEN] + 2 + 1 >= DHCP_OPTIONS_BUFSIZE) { | ||
230 | bb_error_msg("option 0x%02x did not fit into the packet", | ||
231 | string[OPT_CODE]); | ||
232 | return; | ||
233 | } | ||
234 | log_option("Adding option", string); | ||
235 | len = OPT_DATA + string[OPT_LEN]; | ||
236 | memcpy(optionptr + end, string, len); | ||
237 | optionptr[end + len] = DHCP_END; | ||
238 | } | ||
239 | |||
240 | /* add a one to four byte option to a packet */ | ||
241 | void FAST_FUNC udhcp_add_simple_option(uint8_t *optionptr, uint8_t code, uint32_t data) | ||
242 | { | ||
243 | const struct dhcp_option *dh; | ||
244 | |||
245 | for (dh = dhcp_options; dh->code; dh++) { | ||
246 | if (dh->code == code) { | ||
247 | uint8_t option[6], len; | ||
248 | |||
249 | option[OPT_CODE] = code; | ||
250 | len = dhcp_option_lengths[dh->flags & OPTION_TYPE_MASK]; | ||
251 | option[OPT_LEN] = len; | ||
252 | if (BB_BIG_ENDIAN) | ||
253 | data <<= 8 * (4 - len); | ||
254 | /* Assignment is unaligned! */ | ||
255 | move_to_unaligned32(&option[OPT_DATA], data); | ||
256 | udhcp_add_option_string(optionptr, option); | ||
257 | return; | ||
258 | } | ||
259 | } | ||
260 | |||
261 | bb_error_msg("can't add option 0x%02x", code); | ||
262 | } | ||