diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-03-22 14:29:13 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-03-22 14:29:13 +0100 |
commit | dde8bdcc5bd6f25157ca5364b2991c837f1ef364 (patch) | |
tree | d1947e02af92db440b8f8b9e16659ff8568d7e62 | |
parent | 8d1144565fd01576b72eac65ce4686405f98829e (diff) | |
download | busybox-w32-dde8bdcc5bd6f25157ca5364b2991c837f1ef364.tar.gz busybox-w32-dde8bdcc5bd6f25157ca5364b2991c837f1ef364.tar.bz2 busybox-w32-dde8bdcc5bd6f25157ca5364b2991c837f1ef364.zip |
udhcp: merge options.h into common.h, script.c into dhcpc.c
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | networking/udhcp/Kbuild | 2 | ||||
-rw-r--r-- | networking/udhcp/common.h | 182 | ||||
-rw-r--r-- | networking/udhcp/dhcpc.c | 370 | ||||
-rw-r--r-- | networking/udhcp/dhcpd.c | 23 | ||||
-rw-r--r-- | networking/udhcp/dhcprelay.c | 3 | ||||
-rw-r--r-- | networking/udhcp/domain_codec.c | 1 | ||||
-rw-r--r-- | networking/udhcp/files.c | 1 | ||||
-rw-r--r-- | networking/udhcp/options.c | 21 | ||||
-rw-r--r-- | networking/udhcp/options.h | 119 | ||||
-rw-r--r-- | networking/udhcp/packet.c | 7 | ||||
-rw-r--r-- | networking/udhcp/script.c | 283 |
11 files changed, 483 insertions, 529 deletions
diff --git a/networking/udhcp/Kbuild b/networking/udhcp/Kbuild index 693f6c873..c09f9aaf0 100644 --- a/networking/udhcp/Kbuild +++ b/networking/udhcp/Kbuild | |||
@@ -10,7 +10,7 @@ lib-y:= | |||
10 | lib-$(CONFIG_UDHCPC) += common.o options.o packet.o signalpipe.o socket.o | 10 | lib-$(CONFIG_UDHCPC) += common.o options.o packet.o signalpipe.o socket.o |
11 | lib-$(CONFIG_UDHCPD) += common.o options.o packet.o signalpipe.o socket.o | 11 | lib-$(CONFIG_UDHCPD) += common.o options.o packet.o signalpipe.o socket.o |
12 | 12 | ||
13 | lib-$(CONFIG_UDHCPC) += dhcpc.o script.o | 13 | lib-$(CONFIG_UDHCPC) += dhcpc.o |
14 | lib-$(CONFIG_UDHCPD) += dhcpd.o arpping.o files.o leases.o static_leases.o | 14 | lib-$(CONFIG_UDHCPD) += dhcpd.o arpping.o files.o leases.o static_leases.o |
15 | lib-$(CONFIG_DUMPLEASES) += dumpleases.o | 15 | lib-$(CONFIG_DUMPLEASES) += dumpleases.o |
16 | lib-$(CONFIG_DHCPRELAY) += dhcprelay.o | 16 | lib-$(CONFIG_DHCPRELAY) += dhcprelay.o |
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index d740ca56c..2ce67598d 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h | |||
@@ -15,17 +15,14 @@ | |||
15 | 15 | ||
16 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | 16 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN |
17 | 17 | ||
18 | #define DEFAULT_SCRIPT CONFIG_UDHCPC_DEFAULT_SCRIPT | ||
19 | |||
20 | extern const uint8_t MAC_BCAST_ADDR[6]; /* six all-ones */ | 18 | extern const uint8_t MAC_BCAST_ADDR[6]; /* six all-ones */ |
21 | 19 | ||
22 | /*** packet.h ***/ | 20 | |
21 | /*** DHCP packet ***/ | ||
23 | 22 | ||
24 | /* DHCP protocol. See RFC 2131 */ | 23 | /* DHCP protocol. See RFC 2131 */ |
25 | #define DHCP_MAGIC 0x63825363 | 24 | #define DHCP_MAGIC 0x63825363 |
26 | |||
27 | #define DHCP_OPTIONS_BUFSIZE 308 | 25 | #define DHCP_OPTIONS_BUFSIZE 308 |
28 | |||
29 | #define BOOTREQUEST 1 | 26 | #define BOOTREQUEST 1 |
30 | #define BOOTREPLY 2 | 27 | #define BOOTREPLY 2 |
31 | 28 | ||
@@ -67,6 +64,116 @@ struct BUG_bad_sizeof_struct_ip_udp_dhcp_packet { | |||
67 | [(sizeof(struct ip_udp_dhcp_packet) != 576 + CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS) ? -1 : 1]; | 64 | [(sizeof(struct ip_udp_dhcp_packet) != 576 + CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS) ? -1 : 1]; |
68 | }; | 65 | }; |
69 | 66 | ||
67 | |||
68 | /*** Options ***/ | ||
69 | |||
70 | enum { | ||
71 | OPTION_IP = 1, | ||
72 | OPTION_IP_PAIR, | ||
73 | OPTION_STRING, | ||
74 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
75 | OPTION_STR1035, /* RFC1035 compressed domain name list */ | ||
76 | #endif | ||
77 | OPTION_BOOLEAN, | ||
78 | OPTION_U8, | ||
79 | OPTION_U16, | ||
80 | OPTION_S16, | ||
81 | OPTION_U32, | ||
82 | OPTION_S32, | ||
83 | OPTION_STATIC_ROUTES, | ||
84 | |||
85 | OPTION_TYPE_MASK = 0x0f, | ||
86 | /* Client requests this option by default */ | ||
87 | OPTION_REQ = 0x10, | ||
88 | /* There can be a list of 1 or more of these */ | ||
89 | OPTION_LIST = 0x20, | ||
90 | }; | ||
91 | |||
92 | /* DHCP option codes (partial list). See RFC 2132 and | ||
93 | * http://www.iana.org/assignments/bootp-dhcp-parameters/ | ||
94 | * Commented out options are handled by common option machinery, | ||
95 | * uncommented ones have spacial cases (grep for them to see). | ||
96 | */ | ||
97 | #define DHCP_PADDING 0x00 | ||
98 | #define DHCP_SUBNET 0x01 | ||
99 | //#define DHCP_TIME_OFFSET 0x02 /* (localtime - UTC_time) in seconds. signed */ | ||
100 | //#define DHCP_ROUTER 0x03 | ||
101 | //#define DHCP_TIME_SERVER 0x04 /* RFC 868 time server (32-bit, 0 = 1.1.1900) */ | ||
102 | //#define DHCP_NAME_SERVER 0x05 /* IEN 116 _really_ ancient kind of NS */ | ||
103 | //#define DHCP_DNS_SERVER 0x06 | ||
104 | //#define DHCP_LOG_SERVER 0x07 /* port 704 UDP log (not syslog) | ||
105 | //#define DHCP_COOKIE_SERVER 0x08 /* "quote of the day" server */ | ||
106 | //#define DHCP_LPR_SERVER 0x09 | ||
107 | #define DHCP_HOST_NAME 0x0c /* either client informs server or server gives name to client */ | ||
108 | //#define DHCP_BOOT_SIZE 0x0d | ||
109 | //#define DHCP_DOMAIN_NAME 0x0f /* server gives domain suffix */ | ||
110 | //#define DHCP_SWAP_SERVER 0x10 | ||
111 | //#define DHCP_ROOT_PATH 0x11 | ||
112 | //#define DHCP_IP_TTL 0x17 | ||
113 | //#define DHCP_MTU 0x1a | ||
114 | //#define DHCP_BROADCAST 0x1c | ||
115 | //#define DHCP_NIS_DOMAIN 0x28 | ||
116 | //#define DHCP_NIS_SERVER 0x29 | ||
117 | //#define DHCP_NTP_SERVER 0x2a | ||
118 | //#define DHCP_WINS_SERVER 0x2c | ||
119 | #define DHCP_REQUESTED_IP 0x32 /* sent by client if specific IP is wanted */ | ||
120 | #define DHCP_LEASE_TIME 0x33 | ||
121 | #define DHCP_OPTION_OVERLOAD 0x34 | ||
122 | #define DHCP_MESSAGE_TYPE 0x35 | ||
123 | #define DHCP_SERVER_ID 0x36 /* by default server's IP */ | ||
124 | #define DHCP_PARAM_REQ 0x37 /* list of options client wants */ | ||
125 | //#define DHCP_ERR_MESSAGE 0x38 /* error message when sending NAK etc */ | ||
126 | #define DHCP_MAX_SIZE 0x39 | ||
127 | #define DHCP_VENDOR 0x3c /* client's vendor (a string) */ | ||
128 | #define DHCP_CLIENT_ID 0x3d /* by default client's MAC addr, but may be arbitrarily long */ | ||
129 | //#define DHCP_TFTP_SERVER_NAME 0x42 /* same as 'sname' field */ | ||
130 | //#define DHCP_BOOT_FILE 0x43 /* same as 'file' field */ | ||
131 | //#define DHCP_USER_CLASS 0x4d /* RFC 3004. set of LASCII strings. "I am a printer" etc */ | ||
132 | #define DHCP_FQDN 0x51 /* client asks to update DNS to map its FQDN to its new IP */ | ||
133 | //#define DHCP_DOMAIN_SEARCH 0x77 /* RFC 3397. set of ASCIZ string, DNS-style compressed */ | ||
134 | //#define DHCP_STATIC_ROUTES 0x79 /* RFC 3442. (mask,ip,router) tuples */ | ||
135 | //#define DHCP_WPAD 0xfc /* MSIE's Web Proxy Autodiscovery Protocol */ | ||
136 | #define DHCP_END 0xff | ||
137 | |||
138 | /* Offsets in option byte sequence */ | ||
139 | #define OPT_CODE 0 | ||
140 | #define OPT_LEN 1 | ||
141 | #define OPT_DATA 2 | ||
142 | /* Bits in "overload" option */ | ||
143 | #define OPTION_FIELD 0 | ||
144 | #define FILE_FIELD 1 | ||
145 | #define SNAME_FIELD 2 | ||
146 | |||
147 | /* DHCP_MESSAGE_TYPE values */ | ||
148 | #define DHCPDISCOVER 1 /* client -> server */ | ||
149 | #define DHCPOFFER 2 /* client <- server */ | ||
150 | #define DHCPREQUEST 3 /* client -> server */ | ||
151 | #define DHCPDECLINE 4 /* client -> server */ | ||
152 | #define DHCPACK 5 /* client <- server */ | ||
153 | #define DHCPNAK 6 /* client <- server */ | ||
154 | #define DHCPRELEASE 7 /* client -> server */ | ||
155 | #define DHCPINFORM 8 /* client -> server */ | ||
156 | #define DHCP_MINTYPE DHCPDISCOVER | ||
157 | #define DHCP_MAXTYPE DHCPINFORM | ||
158 | |||
159 | struct dhcp_option { | ||
160 | uint8_t flags; | ||
161 | uint8_t code; | ||
162 | }; | ||
163 | |||
164 | extern const struct dhcp_option dhcp_options[]; | ||
165 | extern const char dhcp_option_strings[]; | ||
166 | extern const uint8_t dhcp_option_lengths[]; | ||
167 | |||
168 | uint8_t *udhcp_get_option(struct dhcp_packet *packet, int code) FAST_FUNC; | ||
169 | int udhcp_end_option(uint8_t *optionptr) FAST_FUNC; | ||
170 | void udhcp_add_option_string(uint8_t *optionptr, uint8_t *string) FAST_FUNC; | ||
171 | void udhcp_add_simple_option(uint8_t *optionptr, uint8_t code, uint32_t data) FAST_FUNC; | ||
172 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
173 | char *dname_dec(const uint8_t *cstr, int clen, const char *pre) FAST_FUNC; | ||
174 | uint8_t *dname_enc(const uint8_t *cstr, int clen, const char *src, int *retlen) FAST_FUNC; | ||
175 | #endif | ||
176 | |||
70 | // RFC 2131 Table 5: Fields and options used by DHCP clients | 177 | // RFC 2131 Table 5: Fields and options used by DHCP clients |
71 | // | 178 | // |
72 | // Field DHCPDISCOVER DHCPREQUEST DHCPDECLINE, | 179 | // Field DHCPDISCOVER DHCPREQUEST DHCPDECLINE, |
@@ -132,6 +239,33 @@ struct BUG_bad_sizeof_struct_ip_udp_dhcp_packet { | |||
132 | // All others MAY MAY MUST NOT | 239 | // All others MAY MAY MUST NOT |
133 | 240 | ||
134 | 241 | ||
242 | /*** Logging ***/ | ||
243 | |||
244 | #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 | ||
245 | extern unsigned dhcp_verbose; | ||
246 | # define log1(...) do { if (dhcp_verbose >= 1) bb_info_msg(__VA_ARGS__); } while (0) | ||
247 | # if CONFIG_UDHCP_DEBUG >= 2 | ||
248 | void udhcp_dump_packet(struct dhcp_packet *packet) FAST_FUNC; | ||
249 | # define log2(...) do { if (dhcp_verbose >= 2) bb_info_msg(__VA_ARGS__); } while (0) | ||
250 | # else | ||
251 | # define udhcp_dump_packet(...) ((void)0) | ||
252 | # define log2(...) ((void)0) | ||
253 | # endif | ||
254 | # if CONFIG_UDHCP_DEBUG >= 3 | ||
255 | # define log3(...) do { if (dhcp_verbose >= 3) bb_info_msg(__VA_ARGS__); } while (0) | ||
256 | # else | ||
257 | # define log3(...) ((void)0) | ||
258 | # endif | ||
259 | #else | ||
260 | # define udhcp_dump_packet(...) ((void)0) | ||
261 | # define log1(...) ((void)0) | ||
262 | # define log2(...) ((void)0) | ||
263 | # define log3(...) ((void)0) | ||
264 | #endif | ||
265 | |||
266 | |||
267 | /*** Other shared functions ***/ | ||
268 | |||
135 | uint16_t udhcp_checksum(void *addr, int count) FAST_FUNC; | 269 | uint16_t udhcp_checksum(void *addr, int count) FAST_FUNC; |
136 | 270 | ||
137 | void udhcp_init_header(struct dhcp_packet *packet, char type) FAST_FUNC; | 271 | void udhcp_init_header(struct dhcp_packet *packet, char type) FAST_FUNC; |
@@ -147,24 +281,14 @@ int udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, | |||
147 | uint32_t source_ip, int source_port, | 281 | uint32_t source_ip, int source_port, |
148 | uint32_t dest_ip, int dest_port) FAST_FUNC; | 282 | uint32_t dest_ip, int dest_port) FAST_FUNC; |
149 | 283 | ||
150 | |||
151 | /**/ | ||
152 | |||
153 | void udhcp_run_script(struct dhcp_packet *packet, const char *name) FAST_FUNC; | ||
154 | |||
155 | // Still need to clean these up... | ||
156 | |||
157 | /* from options.h */ | ||
158 | #define get_option udhcp_get_option | ||
159 | #define end_option udhcp_end_option | ||
160 | #define add_option_string udhcp_add_option_string | ||
161 | #define add_simple_option udhcp_add_simple_option | ||
162 | |||
163 | void udhcp_sp_setup(void) FAST_FUNC; | 284 | void udhcp_sp_setup(void) FAST_FUNC; |
164 | int udhcp_sp_fd_set(fd_set *rfds, int extra_fd) FAST_FUNC; | 285 | int udhcp_sp_fd_set(fd_set *rfds, int extra_fd) FAST_FUNC; |
165 | int udhcp_sp_read(const fd_set *rfds) FAST_FUNC; | 286 | int udhcp_sp_read(const fd_set *rfds) FAST_FUNC; |
287 | |||
166 | int udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, uint8_t *mac) FAST_FUNC; | 288 | int udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, uint8_t *mac) FAST_FUNC; |
289 | |||
167 | int udhcp_listen_socket(/*uint32_t ip,*/ int port, const char *inf) FAST_FUNC; | 290 | int udhcp_listen_socket(/*uint32_t ip,*/ int port, const char *inf) FAST_FUNC; |
291 | |||
168 | /* Returns 1 if no reply received */ | 292 | /* Returns 1 if no reply received */ |
169 | int arpping(uint32_t test_nip, | 293 | int arpping(uint32_t test_nip, |
170 | const uint8_t *safe_mac, | 294 | const uint8_t *safe_mac, |
@@ -172,28 +296,6 @@ int arpping(uint32_t test_nip, | |||
172 | uint8_t *from_mac, | 296 | uint8_t *from_mac, |
173 | const char *interface) FAST_FUNC; | 297 | const char *interface) FAST_FUNC; |
174 | 298 | ||
175 | #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 | ||
176 | extern unsigned dhcp_verbose; | ||
177 | # define log1(...) do { if (dhcp_verbose >= 1) bb_info_msg(__VA_ARGS__); } while (0) | ||
178 | # if CONFIG_UDHCP_DEBUG >= 2 | ||
179 | void udhcp_dump_packet(struct dhcp_packet *packet) FAST_FUNC; | ||
180 | # define log2(...) do { if (dhcp_verbose >= 2) bb_info_msg(__VA_ARGS__); } while (0) | ||
181 | # else | ||
182 | # define udhcp_dump_packet(...) ((void)0) | ||
183 | # define log2(...) ((void)0) | ||
184 | # endif | ||
185 | # if CONFIG_UDHCP_DEBUG >= 3 | ||
186 | # define log3(...) do { if (dhcp_verbose >= 3) bb_info_msg(__VA_ARGS__); } while (0) | ||
187 | # else | ||
188 | # define log3(...) ((void)0) | ||
189 | # endif | ||
190 | #else | ||
191 | # define udhcp_dump_packet(...) ((void)0) | ||
192 | # define log1(...) ((void)0) | ||
193 | # define log2(...) ((void)0) | ||
194 | # define log3(...) ((void)0) | ||
195 | #endif | ||
196 | |||
197 | POP_SAVED_FUNCTION_VISIBILITY | 299 | POP_SAVED_FUNCTION_VISIBILITY |
198 | 300 | ||
199 | #endif | 301 | #endif |
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index e79feb7fe..758750907 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include "common.h" | 24 | #include "common.h" |
25 | #include "dhcpd.h" | 25 | #include "dhcpd.h" |
26 | #include "dhcpc.h" | 26 | #include "dhcpc.h" |
27 | #include "options.h" | ||
28 | 27 | ||
29 | #include <asm/types.h> | 28 | #include <asm/types.h> |
30 | #if (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1) || defined(_NEWLIB_VERSION) | 29 | #if (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1) || defined(_NEWLIB_VERSION) |
@@ -36,34 +35,278 @@ | |||
36 | #endif | 35 | #endif |
37 | #include <linux/filter.h> | 36 | #include <linux/filter.h> |
38 | 37 | ||
38 | /* struct client_config_t client_config is in bb_common_bufsiz1 */ | ||
39 | 39 | ||
40 | static int sockfd = -1; | ||
41 | 40 | ||
42 | #define LISTEN_NONE 0 | 41 | /*** Script execution code ***/ |
43 | #define LISTEN_KERNEL 1 | ||
44 | #define LISTEN_RAW 2 | ||
45 | static smallint listen_mode; | ||
46 | 42 | ||
47 | /* initial state: (re)start DHCP negotiation */ | 43 | /* get a rough idea of how long an option will be (rounding up...) */ |
48 | #define INIT_SELECTING 0 | 44 | static const uint8_t len_of_option_as_string[] = { |
49 | /* discover was sent, DHCPOFFER reply received */ | 45 | [OPTION_IP] = sizeof("255.255.255.255 "), |
50 | #define REQUESTING 1 | 46 | [OPTION_IP_PAIR] = sizeof("255.255.255.255 ") * 2, |
51 | /* select/renew was sent, DHCPACK reply received */ | 47 | [OPTION_STATIC_ROUTES]= sizeof("255.255.255.255/32 255.255.255.255 "), |
52 | #define BOUND 2 | 48 | [OPTION_STRING] = 1, |
53 | /* half of lease passed, want to renew it by sending unicast renew requests */ | 49 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
54 | #define RENEWING 3 | 50 | [OPTION_STR1035] = 1, |
55 | /* renew requests were not answered, lease is almost over, send broadcast renew */ | 51 | #endif |
56 | #define REBINDING 4 | 52 | [OPTION_BOOLEAN] = sizeof("yes "), |
57 | /* manually requested renew (SIGUSR1) */ | 53 | [OPTION_U8] = sizeof("255 "), |
58 | #define RENEW_REQUESTED 5 | 54 | [OPTION_U16] = sizeof("65535 "), |
59 | /* release, possibly manually requested (SIGUSR2) */ | 55 | [OPTION_S16] = sizeof("-32768 "), |
60 | #define RELEASED 6 | 56 | [OPTION_U32] = sizeof("4294967295 "), |
61 | static smallint state; | 57 | [OPTION_S32] = sizeof("-2147483684 "), |
58 | }; | ||
59 | |||
60 | /* note: ip is a pointer to an IP in network order, possibly misaliged */ | ||
61 | static int sprint_nip(char *dest, const char *pre, const uint8_t *ip) | ||
62 | { | ||
63 | return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]); | ||
64 | } | ||
62 | 65 | ||
63 | /* struct client_config_t client_config is in bb_common_bufsiz1 */ | 66 | /* really simple implementation, just count the bits */ |
67 | static int mton(uint32_t mask) | ||
68 | { | ||
69 | int i = 0; | ||
70 | mask = ntohl(mask); /* 111110000-like bit pattern */ | ||
71 | while (mask) { | ||
72 | i++; | ||
73 | mask <<= 1; | ||
74 | } | ||
75 | return i; | ||
76 | } | ||
77 | |||
78 | /* Create "opt_name=opt_value" string */ | ||
79 | static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_option *type_p, const char *opt_name) | ||
80 | { | ||
81 | unsigned upper_length; | ||
82 | int len, type, optlen; | ||
83 | uint16_t val_u16; | ||
84 | int16_t val_s16; | ||
85 | uint32_t val_u32; | ||
86 | int32_t val_s32; | ||
87 | char *dest, *ret; | ||
88 | |||
89 | /* option points to OPT_DATA, need to go back and get OPT_LEN */ | ||
90 | len = option[OPT_LEN - OPT_DATA]; | ||
91 | type = type_p->flags & OPTION_TYPE_MASK; | ||
92 | optlen = dhcp_option_lengths[type]; | ||
93 | upper_length = len_of_option_as_string[type] * (len / optlen); | ||
94 | |||
95 | dest = ret = xmalloc(upper_length + strlen(opt_name) + 2); | ||
96 | dest += sprintf(ret, "%s=", opt_name); | ||
97 | |||
98 | while (len >= optlen) { | ||
99 | switch (type) { | ||
100 | case OPTION_IP_PAIR: | ||
101 | dest += sprint_nip(dest, "", option); | ||
102 | *dest++ = '/'; | ||
103 | option += 4; | ||
104 | optlen = 4; | ||
105 | case OPTION_IP: | ||
106 | dest += sprint_nip(dest, "", option); | ||
107 | // TODO: it can be a list only if (type_p->flags & OPTION_LIST). | ||
108 | // Should we bail out/warn if we see multi-ip option which is | ||
109 | // not allowed to be such? For example, DHCP_BROADCAST... | ||
110 | break; | ||
111 | case OPTION_BOOLEAN: | ||
112 | dest += sprintf(dest, *option ? "yes" : "no"); | ||
113 | break; | ||
114 | case OPTION_U8: | ||
115 | dest += sprintf(dest, "%u", *option); | ||
116 | break; | ||
117 | case OPTION_U16: | ||
118 | move_from_unaligned16(val_u16, option); | ||
119 | dest += sprintf(dest, "%u", ntohs(val_u16)); | ||
120 | break; | ||
121 | case OPTION_S16: | ||
122 | move_from_unaligned16(val_s16, option); | ||
123 | dest += sprintf(dest, "%d", ntohs(val_s16)); | ||
124 | break; | ||
125 | case OPTION_U32: | ||
126 | move_from_unaligned32(val_u32, option); | ||
127 | dest += sprintf(dest, "%lu", (unsigned long) ntohl(val_u32)); | ||
128 | break; | ||
129 | case OPTION_S32: | ||
130 | move_from_unaligned32(val_s32, option); | ||
131 | dest += sprintf(dest, "%ld", (long) ntohl(val_s32)); | ||
132 | break; | ||
133 | case OPTION_STRING: | ||
134 | memcpy(dest, option, len); | ||
135 | dest[len] = '\0'; | ||
136 | return ret; /* Short circuit this case */ | ||
137 | case OPTION_STATIC_ROUTES: { | ||
138 | /* Option binary format: | ||
139 | * mask [one byte, 0..32] | ||
140 | * ip [big endian, 0..4 bytes depending on mask] | ||
141 | * router [big endian, 4 bytes] | ||
142 | * may be repeated | ||
143 | * | ||
144 | * We convert it to a string "IP/MASK ROUTER IP2/MASK2 ROUTER2" | ||
145 | */ | ||
146 | const char *pfx = ""; | ||
147 | |||
148 | while (len >= 1 + 4) { /* mask + 0-byte ip + router */ | ||
149 | uint32_t nip; | ||
150 | uint8_t *p; | ||
151 | unsigned mask; | ||
152 | int bytes; | ||
153 | |||
154 | mask = *option++; | ||
155 | if (mask > 32) | ||
156 | break; | ||
157 | len--; | ||
158 | |||
159 | nip = 0; | ||
160 | p = (void*) &nip; | ||
161 | bytes = (mask + 7) / 8; /* 0 -> 0, 1..8 -> 1, 9..16 -> 2 etc */ | ||
162 | while (--bytes >= 0) { | ||
163 | *p++ = *option++; | ||
164 | len--; | ||
165 | } | ||
166 | if (len < 4) | ||
167 | break; | ||
168 | |||
169 | /* print ip/mask */ | ||
170 | dest += sprint_nip(dest, pfx, (void*) &nip); | ||
171 | pfx = " "; | ||
172 | dest += sprintf(dest, "/%u ", mask); | ||
173 | /* print router */ | ||
174 | dest += sprint_nip(dest, "", option); | ||
175 | option += 4; | ||
176 | len -= 4; | ||
177 | } | ||
178 | |||
179 | return ret; | ||
180 | } | ||
181 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
182 | case OPTION_STR1035: | ||
183 | /* unpack option into dest; use ret for prefix (i.e., "optname=") */ | ||
184 | dest = dname_dec(option, len, ret); | ||
185 | if (dest) { | ||
186 | free(ret); | ||
187 | return dest; | ||
188 | } | ||
189 | /* error. return "optname=" string */ | ||
190 | return ret; | ||
191 | #endif | ||
192 | } | ||
193 | option += optlen; | ||
194 | len -= optlen; | ||
195 | if (len <= 0) | ||
196 | break; | ||
197 | *dest++ = ' '; | ||
198 | *dest = '\0'; | ||
199 | } | ||
200 | return ret; | ||
201 | } | ||
202 | |||
203 | /* put all the parameters into the environment */ | ||
204 | static char **fill_envp(struct dhcp_packet *packet) | ||
205 | { | ||
206 | int num_options = 0; | ||
207 | int i; | ||
208 | char **envp, **curr; | ||
209 | const char *opt_name; | ||
210 | uint8_t *temp; | ||
211 | uint8_t over = 0; | ||
212 | |||
213 | if (packet) { | ||
214 | for (i = 0; dhcp_options[i].code; i++) { | ||
215 | if (udhcp_get_option(packet, dhcp_options[i].code)) { | ||
216 | num_options++; | ||
217 | if (dhcp_options[i].code == DHCP_SUBNET) | ||
218 | num_options++; /* for mton */ | ||
219 | } | ||
220 | } | ||
221 | if (packet->siaddr_nip) | ||
222 | num_options++; | ||
223 | temp = udhcp_get_option(packet, DHCP_OPTION_OVERLOAD); | ||
224 | if (temp) | ||
225 | over = *temp; | ||
226 | if (!(over & FILE_FIELD) && packet->file[0]) | ||
227 | num_options++; | ||
228 | if (!(over & SNAME_FIELD) && packet->sname[0]) | ||
229 | num_options++; | ||
230 | } | ||
231 | |||
232 | curr = envp = xzalloc(sizeof(char *) * (num_options + 3)); | ||
233 | *curr = xasprintf("interface=%s", client_config.interface); | ||
234 | putenv(*curr++); | ||
235 | |||
236 | if (packet == NULL) | ||
237 | return envp; | ||
238 | |||
239 | *curr = xmalloc(sizeof("ip=255.255.255.255")); | ||
240 | sprint_nip(*curr, "ip=", (uint8_t *) &packet->yiaddr); | ||
241 | putenv(*curr++); | ||
242 | |||
243 | opt_name = dhcp_option_strings; | ||
244 | i = 0; | ||
245 | while (*opt_name) { | ||
246 | temp = udhcp_get_option(packet, dhcp_options[i].code); | ||
247 | if (!temp) | ||
248 | goto next; | ||
249 | *curr = xmalloc_optname_optval(temp, &dhcp_options[i], opt_name); | ||
250 | putenv(*curr++); | ||
251 | |||
252 | /* Fill in a subnet bits option for things like /24 */ | ||
253 | if (dhcp_options[i].code == DHCP_SUBNET) { | ||
254 | uint32_t subnet; | ||
255 | move_from_unaligned32(subnet, temp); | ||
256 | *curr = xasprintf("mask=%d", mton(subnet)); | ||
257 | putenv(*curr++); | ||
258 | } | ||
259 | next: | ||
260 | opt_name += strlen(opt_name) + 1; | ||
261 | i++; | ||
262 | } | ||
263 | if (packet->siaddr_nip) { | ||
264 | *curr = xmalloc(sizeof("siaddr=255.255.255.255")); | ||
265 | sprint_nip(*curr, "siaddr=", (uint8_t *) &packet->siaddr_nip); | ||
266 | putenv(*curr++); | ||
267 | } | ||
268 | if (!(over & FILE_FIELD) && packet->file[0]) { | ||
269 | /* watch out for invalid packets */ | ||
270 | *curr = xasprintf("boot_file=%."DHCP_PKT_FILE_LEN_STR"s", packet->file); | ||
271 | putenv(*curr++); | ||
272 | } | ||
273 | if (!(over & SNAME_FIELD) && packet->sname[0]) { | ||
274 | /* watch out for invalid packets */ | ||
275 | *curr = xasprintf("sname=%."DHCP_PKT_SNAME_LEN_STR"s", packet->sname); | ||
276 | putenv(*curr++); | ||
277 | } | ||
278 | return envp; | ||
279 | } | ||
280 | |||
281 | /* Call a script with a par file and env vars */ | ||
282 | static void udhcp_run_script(struct dhcp_packet *packet, const char *name) | ||
283 | { | ||
284 | char **envp, **curr; | ||
285 | char *argv[3]; | ||
286 | |||
287 | if (client_config.script == NULL) | ||
288 | return; | ||
289 | |||
290 | envp = fill_envp(packet); | ||
291 | |||
292 | /* call script */ | ||
293 | log1("Executing %s %s", client_config.script, name); | ||
294 | argv[0] = (char*) client_config.script; | ||
295 | argv[1] = (char*) name; | ||
296 | argv[2] = NULL; | ||
297 | spawn_and_wait(argv); | ||
298 | |||
299 | for (curr = envp; *curr; curr++) { | ||
300 | log2(" %s", *curr); | ||
301 | bb_unsetenv(*curr); | ||
302 | free(*curr); | ||
303 | } | ||
304 | free(envp); | ||
305 | } | ||
64 | 306 | ||
65 | 307 | ||
66 | /* Create a random xid */ | 308 | /*** Sending/receiving packets ***/ |
309 | |||
67 | static ALWAYS_INLINE uint32_t random_xid(void) | 310 | static ALWAYS_INLINE uint32_t random_xid(void) |
68 | { | 311 | { |
69 | return rand(); | 312 | return rand(); |
@@ -75,16 +318,16 @@ static void init_packet(struct dhcp_packet *packet, char type) | |||
75 | udhcp_init_header(packet, type); | 318 | udhcp_init_header(packet, type); |
76 | memcpy(packet->chaddr, client_config.client_mac, 6); | 319 | memcpy(packet->chaddr, client_config.client_mac, 6); |
77 | if (client_config.clientid) | 320 | if (client_config.clientid) |
78 | add_option_string(packet->options, client_config.clientid); | 321 | udhcp_add_option_string(packet->options, client_config.clientid); |
79 | if (client_config.hostname) | 322 | if (client_config.hostname) |
80 | add_option_string(packet->options, client_config.hostname); | 323 | udhcp_add_option_string(packet->options, client_config.hostname); |
81 | if (client_config.fqdn) | 324 | if (client_config.fqdn) |
82 | add_option_string(packet->options, client_config.fqdn); | 325 | udhcp_add_option_string(packet->options, client_config.fqdn); |
83 | if (type != DHCPDECLINE | 326 | if (type != DHCPDECLINE |
84 | && type != DHCPRELEASE | 327 | && type != DHCPRELEASE |
85 | && client_config.vendorclass | 328 | && client_config.vendorclass |
86 | ) { | 329 | ) { |
87 | add_option_string(packet->options, client_config.vendorclass); | 330 | udhcp_add_option_string(packet->options, client_config.vendorclass); |
88 | } | 331 | } |
89 | } | 332 | } |
90 | 333 | ||
@@ -94,7 +337,7 @@ static void init_packet(struct dhcp_packet *packet, char type) | |||
94 | static void add_param_req_option(struct dhcp_packet *packet) | 337 | static void add_param_req_option(struct dhcp_packet *packet) |
95 | { | 338 | { |
96 | uint8_t c; | 339 | uint8_t c; |
97 | int end = end_option(packet->options); | 340 | int end = udhcp_end_option(packet->options); |
98 | int i, len = 0; | 341 | int i, len = 0; |
99 | 342 | ||
100 | for (i = 0; (c = dhcp_options[i].code) != 0; i++) { | 343 | for (i = 0; (c = dhcp_options[i].code) != 0; i++) { |
@@ -148,10 +391,10 @@ static int send_discover(uint32_t xid, uint32_t requested) | |||
148 | init_packet(&packet, DHCPDISCOVER); | 391 | init_packet(&packet, DHCPDISCOVER); |
149 | packet.xid = xid; | 392 | packet.xid = xid; |
150 | if (requested) | 393 | if (requested) |
151 | add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); | 394 | udhcp_add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); |
152 | /* Explicitly saying that we want RFC-compliant packets helps | 395 | /* Explicitly saying that we want RFC-compliant packets helps |
153 | * some buggy DHCP servers to NOT send bigger packets */ | 396 | * some buggy DHCP servers to NOT send bigger packets */ |
154 | add_simple_option(packet.options, DHCP_MAX_SIZE, htons(576)); | 397 | udhcp_add_simple_option(packet.options, DHCP_MAX_SIZE, htons(576)); |
155 | add_param_req_option(&packet); | 398 | add_param_req_option(&packet); |
156 | 399 | ||
157 | bb_info_msg("Sending discover..."); | 400 | bb_info_msg("Sending discover..."); |
@@ -169,8 +412,8 @@ static int send_select(uint32_t xid, uint32_t server, uint32_t requested) | |||
169 | 412 | ||
170 | init_packet(&packet, DHCPREQUEST); | 413 | init_packet(&packet, DHCPREQUEST); |
171 | packet.xid = xid; | 414 | packet.xid = xid; |
172 | add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); | 415 | udhcp_add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); |
173 | add_simple_option(packet.options, DHCP_SERVER_ID, server); | 416 | udhcp_add_simple_option(packet.options, DHCP_SERVER_ID, server); |
174 | add_param_req_option(&packet); | 417 | add_param_req_option(&packet); |
175 | 418 | ||
176 | addr.s_addr = requested; | 419 | addr.s_addr = requested; |
@@ -204,8 +447,8 @@ static int send_decline(uint32_t xid, uint32_t server, uint32_t requested) | |||
204 | 447 | ||
205 | init_packet(&packet, DHCPDECLINE); | 448 | init_packet(&packet, DHCPDECLINE); |
206 | packet.xid = xid; | 449 | packet.xid = xid; |
207 | add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); | 450 | udhcp_add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); |
208 | add_simple_option(packet.options, DHCP_SERVER_ID, server); | 451 | udhcp_add_simple_option(packet.options, DHCP_SERVER_ID, server); |
209 | 452 | ||
210 | bb_info_msg("Sending decline..."); | 453 | bb_info_msg("Sending decline..."); |
211 | return raw_bcast_from_client_config_ifindex(&packet); | 454 | return raw_bcast_from_client_config_ifindex(&packet); |
@@ -221,7 +464,7 @@ static int send_release(uint32_t server, uint32_t ciaddr) | |||
221 | packet.xid = random_xid(); | 464 | packet.xid = random_xid(); |
222 | packet.ciaddr = ciaddr; | 465 | packet.ciaddr = ciaddr; |
223 | 466 | ||
224 | add_simple_option(packet.options, DHCP_SERVER_ID, server); | 467 | udhcp_add_simple_option(packet.options, DHCP_SERVER_ID, server); |
225 | 468 | ||
226 | bb_info_msg("Sending release..."); | 469 | bb_info_msg("Sending release..."); |
227 | return udhcp_send_kernel_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT); | 470 | return udhcp_send_kernel_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT); |
@@ -297,6 +540,32 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) | |||
297 | return bytes - (sizeof(packet.ip) + sizeof(packet.udp)); | 540 | return bytes - (sizeof(packet.ip) + sizeof(packet.udp)); |
298 | } | 541 | } |
299 | 542 | ||
543 | |||
544 | /*** Main ***/ | ||
545 | |||
546 | static int sockfd = -1; | ||
547 | |||
548 | #define LISTEN_NONE 0 | ||
549 | #define LISTEN_KERNEL 1 | ||
550 | #define LISTEN_RAW 2 | ||
551 | static smallint listen_mode; | ||
552 | |||
553 | /* initial state: (re)start DHCP negotiation */ | ||
554 | #define INIT_SELECTING 0 | ||
555 | /* discover was sent, DHCPOFFER reply received */ | ||
556 | #define REQUESTING 1 | ||
557 | /* select/renew was sent, DHCPACK reply received */ | ||
558 | #define BOUND 2 | ||
559 | /* half of lease passed, want to renew it by sending unicast renew requests */ | ||
560 | #define RENEWING 3 | ||
561 | /* renew requests were not answered, lease is almost over, send broadcast renew */ | ||
562 | #define REBINDING 4 | ||
563 | /* manually requested renew (SIGUSR1) */ | ||
564 | #define RENEW_REQUESTED 5 | ||
565 | /* release, possibly manually requested (SIGUSR2) */ | ||
566 | #define RELEASED 6 | ||
567 | static smallint state; | ||
568 | |||
300 | static int udhcp_raw_socket(int ifindex) | 569 | static int udhcp_raw_socket(int ifindex) |
301 | { | 570 | { |
302 | int fd; | 571 | int fd; |
@@ -368,7 +637,6 @@ static int udhcp_raw_socket(int ifindex) | |||
368 | return fd; | 637 | return fd; |
369 | } | 638 | } |
370 | 639 | ||
371 | /* just a little helper */ | ||
372 | static void change_listen_mode(int new_mode) | 640 | static void change_listen_mode(int new_mode) |
373 | { | 641 | { |
374 | log1("Entering listen mode: %s", | 642 | log1("Entering listen mode: %s", |
@@ -389,7 +657,6 @@ static void change_listen_mode(int new_mode) | |||
389 | /* else LISTEN_NONE: sockfd stays closed */ | 657 | /* else LISTEN_NONE: sockfd stays closed */ |
390 | } | 658 | } |
391 | 659 | ||
392 | /* perform a renew */ | ||
393 | static void perform_renew(void) | 660 | static void perform_renew(void) |
394 | { | 661 | { |
395 | bb_info_msg("Performing a DHCP renew"); | 662 | bb_info_msg("Performing a DHCP renew"); |
@@ -412,7 +679,6 @@ static void perform_renew(void) | |||
412 | } | 679 | } |
413 | } | 680 | } |
414 | 681 | ||
415 | /* perform a release */ | ||
416 | static void perform_release(uint32_t requested_ip, uint32_t server_addr) | 682 | static void perform_release(uint32_t requested_ip, uint32_t server_addr) |
417 | { | 683 | { |
418 | char buffer[sizeof("255.255.255.255")]; | 684 | char buffer[sizeof("255.255.255.255")]; |
@@ -434,16 +700,6 @@ static void perform_release(uint32_t requested_ip, uint32_t server_addr) | |||
434 | state = RELEASED; | 700 | state = RELEASED; |
435 | } | 701 | } |
436 | 702 | ||
437 | #if BB_MMU | ||
438 | static void client_background(void) | ||
439 | { | ||
440 | bb_daemonize(0); | ||
441 | logmode &= ~LOGMODE_STDIO; | ||
442 | /* rewrite pidfile, as our pid is different now */ | ||
443 | write_pidfile(client_config.pidfile); | ||
444 | } | ||
445 | #endif | ||
446 | |||
447 | static uint8_t* alloc_dhcp_option(int code, const char *str, int extra) | 703 | static uint8_t* alloc_dhcp_option(int code, const char *str, int extra) |
448 | { | 704 | { |
449 | uint8_t *storage; | 705 | uint8_t *storage; |
@@ -455,6 +711,16 @@ static uint8_t* alloc_dhcp_option(int code, const char *str, int extra) | |||
455 | return storage; | 711 | return storage; |
456 | } | 712 | } |
457 | 713 | ||
714 | #if BB_MMU | ||
715 | static void client_background(void) | ||
716 | { | ||
717 | bb_daemonize(0); | ||
718 | logmode &= ~LOGMODE_STDIO; | ||
719 | /* rewrite pidfile, as our pid is different now */ | ||
720 | write_pidfile(client_config.pidfile); | ||
721 | } | ||
722 | #endif | ||
723 | |||
458 | int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 724 | int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
459 | int udhcpc_main(int argc UNUSED_PARAM, char **argv) | 725 | int udhcpc_main(int argc UNUSED_PARAM, char **argv) |
460 | { | 726 | { |
@@ -541,7 +807,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
541 | IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;) | 807 | IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;) |
542 | IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;) | 808 | IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;) |
543 | client_config.interface = "eth0"; | 809 | client_config.interface = "eth0"; |
544 | client_config.script = DEFAULT_SCRIPT; | 810 | client_config.script = CONFIG_UDHCPC_DEFAULT_SCRIPT; |
545 | str_V = "udhcp "BB_VER; | 811 | str_V = "udhcp "BB_VER; |
546 | 812 | ||
547 | /* Parse command line */ | 813 | /* Parse command line */ |
@@ -861,7 +1127,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
861 | continue; | 1127 | continue; |
862 | } | 1128 | } |
863 | 1129 | ||
864 | message = get_option(&packet, DHCP_MESSAGE_TYPE); | 1130 | message = udhcp_get_option(&packet, DHCP_MESSAGE_TYPE); |
865 | if (message == NULL) { | 1131 | if (message == NULL) { |
866 | bb_error_msg("no message type option, ignoring packet"); | 1132 | bb_error_msg("no message type option, ignoring packet"); |
867 | continue; | 1133 | continue; |
@@ -872,7 +1138,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
872 | /* Must be a DHCPOFFER to one of our xid's */ | 1138 | /* Must be a DHCPOFFER to one of our xid's */ |
873 | if (*message == DHCPOFFER) { | 1139 | if (*message == DHCPOFFER) { |
874 | /* TODO: why we don't just fetch server's IP from IP header? */ | 1140 | /* TODO: why we don't just fetch server's IP from IP header? */ |
875 | temp = get_option(&packet, DHCP_SERVER_ID); | 1141 | temp = udhcp_get_option(&packet, DHCP_SERVER_ID); |
876 | if (!temp) { | 1142 | if (!temp) { |
877 | bb_error_msg("no server ID in message"); | 1143 | bb_error_msg("no server ID in message"); |
878 | continue; | 1144 | continue; |
@@ -895,7 +1161,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
895 | case RENEW_REQUESTED: | 1161 | case RENEW_REQUESTED: |
896 | case REBINDING: | 1162 | case REBINDING: |
897 | if (*message == DHCPACK) { | 1163 | if (*message == DHCPACK) { |
898 | temp = get_option(&packet, DHCP_LEASE_TIME); | 1164 | temp = udhcp_get_option(&packet, DHCP_LEASE_TIME); |
899 | if (!temp) { | 1165 | if (!temp) { |
900 | bb_error_msg("no lease time with ACK, using 1 hour lease"); | 1166 | bb_error_msg("no lease time with ACK, using 1 hour lease"); |
901 | lease_seconds = 60 * 60; | 1167 | lease_seconds = 60 * 60; |
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index d6e90cd03..93e06b237 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include "common.h" | 25 | #include "common.h" |
26 | #include "dhcpc.h" | 26 | #include "dhcpc.h" |
27 | #include "dhcpd.h" | 27 | #include "dhcpd.h" |
28 | #include "options.h" | ||
29 | 28 | ||
30 | 29 | ||
31 | /* Send a packet to a specific mac address and ip address by creating our own ip packet */ | 30 | /* Send a packet to a specific mac address and ip address by creating our own ip packet */ |
@@ -94,7 +93,7 @@ static void init_packet(struct dhcp_packet *packet, struct dhcp_packet *oldpacke | |||
94 | packet->flags = oldpacket->flags; | 93 | packet->flags = oldpacket->flags; |
95 | packet->gateway_nip = oldpacket->gateway_nip; | 94 | packet->gateway_nip = oldpacket->gateway_nip; |
96 | packet->ciaddr = oldpacket->ciaddr; | 95 | packet->ciaddr = oldpacket->ciaddr; |
97 | add_simple_option(packet->options, DHCP_SERVER_ID, server_config.server_nip); | 96 | udhcp_add_simple_option(packet->options, DHCP_SERVER_ID, server_config.server_nip); |
98 | } | 97 | } |
99 | 98 | ||
100 | /* Fill options field, siaddr_nip, and sname and boot_file fields. | 99 | /* Fill options field, siaddr_nip, and sname and boot_file fields. |
@@ -106,7 +105,7 @@ static void add_server_options(struct dhcp_packet *packet) | |||
106 | 105 | ||
107 | while (curr) { | 106 | while (curr) { |
108 | if (curr->data[OPT_CODE] != DHCP_LEASE_TIME) | 107 | if (curr->data[OPT_CODE] != DHCP_LEASE_TIME) |
109 | add_option_string(packet->options, curr->data); | 108 | udhcp_add_option_string(packet->options, curr->data); |
110 | curr = curr->next; | 109 | curr = curr->next; |
111 | } | 110 | } |
112 | 111 | ||
@@ -121,7 +120,7 @@ static void add_server_options(struct dhcp_packet *packet) | |||
121 | static uint32_t select_lease_time(struct dhcp_packet *packet) | 120 | static uint32_t select_lease_time(struct dhcp_packet *packet) |
122 | { | 121 | { |
123 | uint32_t lease_time_sec = server_config.max_lease_sec; | 122 | uint32_t lease_time_sec = server_config.max_lease_sec; |
124 | uint8_t *lease_time_opt = get_option(packet, DHCP_LEASE_TIME); | 123 | uint8_t *lease_time_opt = udhcp_get_option(packet, DHCP_LEASE_TIME); |
125 | if (lease_time_opt) { | 124 | if (lease_time_opt) { |
126 | move_from_unaligned32(lease_time_sec, lease_time_opt); | 125 | move_from_unaligned32(lease_time_sec, lease_time_opt); |
127 | lease_time_sec = ntohl(lease_time_sec); | 126 | lease_time_sec = ntohl(lease_time_sec); |
@@ -159,7 +158,7 @@ static void send_offer(struct dhcp_packet *oldpacket, uint32_t static_lease_nip, | |||
159 | packet.yiaddr = lease->lease_nip; | 158 | packet.yiaddr = lease->lease_nip; |
160 | } | 159 | } |
161 | /* Or: if client has requested an IP */ | 160 | /* Or: if client has requested an IP */ |
162 | else if ((req_ip_opt = get_option(oldpacket, DHCP_REQUESTED_IP)) != NULL | 161 | else if ((req_ip_opt = udhcp_get_option(oldpacket, DHCP_REQUESTED_IP)) != NULL |
163 | /* (read IP) */ | 162 | /* (read IP) */ |
164 | && (move_from_unaligned32(req_nip, req_ip_opt), 1) | 163 | && (move_from_unaligned32(req_nip, req_ip_opt), 1) |
165 | /* and the IP is in the lease range */ | 164 | /* and the IP is in the lease range */ |
@@ -182,7 +181,7 @@ static void send_offer(struct dhcp_packet *oldpacket, uint32_t static_lease_nip, | |||
182 | return; | 181 | return; |
183 | } | 182 | } |
184 | /* Reserve the IP for a short time hoping to get DHCPREQUEST soon */ | 183 | /* Reserve the IP for a short time hoping to get DHCPREQUEST soon */ |
185 | p_host_name = (const char*) get_option(oldpacket, DHCP_HOST_NAME); | 184 | p_host_name = (const char*) udhcp_get_option(oldpacket, DHCP_HOST_NAME); |
186 | lease = add_lease(packet.chaddr, packet.yiaddr, | 185 | lease = add_lease(packet.chaddr, packet.yiaddr, |
187 | server_config.offer_time, | 186 | server_config.offer_time, |
188 | p_host_name, | 187 | p_host_name, |
@@ -195,7 +194,7 @@ static void send_offer(struct dhcp_packet *oldpacket, uint32_t static_lease_nip, | |||
195 | } | 194 | } |
196 | 195 | ||
197 | lease_time_sec = select_lease_time(oldpacket); | 196 | lease_time_sec = select_lease_time(oldpacket); |
198 | add_simple_option(packet.options, DHCP_LEASE_TIME, htonl(lease_time_sec)); | 197 | udhcp_add_simple_option(packet.options, DHCP_LEASE_TIME, htonl(lease_time_sec)); |
199 | add_server_options(&packet); | 198 | add_server_options(&packet); |
200 | 199 | ||
201 | addr.s_addr = packet.yiaddr; | 200 | addr.s_addr = packet.yiaddr; |
@@ -225,7 +224,7 @@ static void send_ACK(struct dhcp_packet *oldpacket, uint32_t yiaddr) | |||
225 | packet.yiaddr = yiaddr; | 224 | packet.yiaddr = yiaddr; |
226 | 225 | ||
227 | lease_time_sec = select_lease_time(oldpacket); | 226 | lease_time_sec = select_lease_time(oldpacket); |
228 | add_simple_option(packet.options, DHCP_LEASE_TIME, htonl(lease_time_sec)); | 227 | udhcp_add_simple_option(packet.options, DHCP_LEASE_TIME, htonl(lease_time_sec)); |
229 | 228 | ||
230 | add_server_options(&packet); | 229 | add_server_options(&packet); |
231 | 230 | ||
@@ -233,7 +232,7 @@ static void send_ACK(struct dhcp_packet *oldpacket, uint32_t yiaddr) | |||
233 | bb_info_msg("Sending ACK to %s", inet_ntoa(addr)); | 232 | bb_info_msg("Sending ACK to %s", inet_ntoa(addr)); |
234 | send_packet(&packet, /*force_bcast:*/ 0); | 233 | send_packet(&packet, /*force_bcast:*/ 0); |
235 | 234 | ||
236 | p_host_name = (const char*) get_option(oldpacket, DHCP_HOST_NAME); | 235 | p_host_name = (const char*) udhcp_get_option(oldpacket, DHCP_HOST_NAME); |
237 | add_lease(packet.chaddr, packet.yiaddr, | 236 | add_lease(packet.chaddr, packet.yiaddr, |
238 | lease_time_sec, | 237 | lease_time_sec, |
239 | p_host_name, | 238 | p_host_name, |
@@ -422,7 +421,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
422 | bb_error_msg("not a REQUEST, ignoring packet"); | 421 | bb_error_msg("not a REQUEST, ignoring packet"); |
423 | continue; | 422 | continue; |
424 | } | 423 | } |
425 | state = get_option(&packet, DHCP_MESSAGE_TYPE); | 424 | state = udhcp_get_option(&packet, DHCP_MESSAGE_TYPE); |
426 | if (state == NULL || state[0] < DHCP_MINTYPE || state[0] > DHCP_MAXTYPE) { | 425 | if (state == NULL || state[0] < DHCP_MINTYPE || state[0] > DHCP_MAXTYPE) { |
427 | bb_error_msg("no or bad message type option, ignoring packet"); | 426 | bb_error_msg("no or bad message type option, ignoring packet"); |
428 | continue; | 427 | continue; |
@@ -441,7 +440,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
441 | } | 440 | } |
442 | 441 | ||
443 | /* Get REQUESTED_IP and SERVER_ID if present */ | 442 | /* Get REQUESTED_IP and SERVER_ID if present */ |
444 | server_id_opt = get_option(&packet, DHCP_SERVER_ID); | 443 | server_id_opt = udhcp_get_option(&packet, DHCP_SERVER_ID); |
445 | if (server_id_opt) { | 444 | if (server_id_opt) { |
446 | uint32_t server_id_net; | 445 | uint32_t server_id_net; |
447 | move_from_unaligned32(server_id_net, server_id_opt); | 446 | move_from_unaligned32(server_id_net, server_id_opt); |
@@ -451,7 +450,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
451 | continue; | 450 | continue; |
452 | } | 451 | } |
453 | } | 452 | } |
454 | requested_opt = get_option(&packet, DHCP_REQUESTED_IP); | 453 | requested_opt = udhcp_get_option(&packet, DHCP_REQUESTED_IP); |
455 | if (requested_opt) { | 454 | if (requested_opt) { |
456 | move_from_unaligned32(requested_nip, requested_opt); | 455 | move_from_unaligned32(requested_nip, requested_opt); |
457 | } | 456 | } |
diff --git a/networking/udhcp/dhcprelay.c b/networking/udhcp/dhcprelay.c index a7e715ff9..9f6ac699a 100644 --- a/networking/udhcp/dhcprelay.c +++ b/networking/udhcp/dhcprelay.c | |||
@@ -11,7 +11,6 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include "common.h" | 13 | #include "common.h" |
14 | #include "options.h" | ||
15 | 14 | ||
16 | #define SERVER_PORT 67 | 15 | #define SERVER_PORT 67 |
17 | #define SELECT_TIMEOUT 5 /* select timeout in sec. */ | 16 | #define SELECT_TIMEOUT 5 /* select timeout in sec. */ |
@@ -105,7 +104,7 @@ static int get_dhcp_packet_type(struct dhcp_packet *p) | |||
105 | if (p->op != BOOTREQUEST && p->op != BOOTREPLY) | 104 | if (p->op != BOOTREQUEST && p->op != BOOTREPLY) |
106 | return -1; | 105 | return -1; |
107 | /* get message type option */ | 106 | /* get message type option */ |
108 | op = get_option(p, DHCP_MESSAGE_TYPE); | 107 | op = udhcp_get_option(p, DHCP_MESSAGE_TYPE); |
109 | if (op != NULL) | 108 | if (op != NULL) |
110 | return op[0]; | 109 | return op[0]; |
111 | return -1; | 110 | return -1; |
diff --git a/networking/udhcp/domain_codec.c b/networking/udhcp/domain_codec.c index 45354e727..c00b4ed88 100644 --- a/networking/udhcp/domain_codec.c +++ b/networking/udhcp/domain_codec.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 10 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
11 | 11 | ||
12 | #include "common.h" | 12 | #include "common.h" |
13 | #include "options.h" | ||
14 | 13 | ||
15 | #define NS_MAXDNAME 1025 /* max domain name length */ | 14 | #define NS_MAXDNAME 1025 /* max domain name length */ |
16 | #define NS_MAXCDNAME 255 /* max compressed domain name length */ | 15 | #define NS_MAXCDNAME 255 /* max compressed domain name length */ |
diff --git a/networking/udhcp/files.c b/networking/udhcp/files.c index 62f4a388f..a23e8862c 100644 --- a/networking/udhcp/files.c +++ b/networking/udhcp/files.c | |||
@@ -10,7 +10,6 @@ | |||
10 | 10 | ||
11 | #include "common.h" | 11 | #include "common.h" |
12 | #include "dhcpd.h" | 12 | #include "dhcpd.h" |
13 | #include "options.h" | ||
14 | 13 | ||
15 | #if BB_LITTLE_ENDIAN | 14 | #if BB_LITTLE_ENDIAN |
16 | static inline uint64_t hton64(uint64_t v) | 15 | static inline uint64_t hton64(uint64_t v) |
diff --git a/networking/udhcp/options.c b/networking/udhcp/options.c index 29a264047..b4d2d2de3 100644 --- a/networking/udhcp/options.c +++ b/networking/udhcp/options.c | |||
@@ -7,8 +7,6 @@ | |||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include "common.h" | 9 | #include "common.h" |
10 | #include "dhcpd.h" | ||
11 | #include "options.h" | ||
12 | 10 | ||
13 | 11 | ||
14 | /* Supported options are easily added here. | 12 | /* Supported options are easily added here. |
@@ -111,7 +109,6 @@ const char dhcp_option_strings[] ALIGN1 = | |||
111 | "wpad" "\0" /* DHCP_WPAD */ | 109 | "wpad" "\0" /* DHCP_WPAD */ |
112 | ; | 110 | ; |
113 | 111 | ||
114 | |||
115 | /* Lengths of the different option types */ | 112 | /* Lengths of the different option types */ |
116 | const uint8_t dhcp_option_lengths[] ALIGN1 = { | 113 | const uint8_t dhcp_option_lengths[] ALIGN1 = { |
117 | [OPTION_IP] = 4, | 114 | [OPTION_IP] = 4, |
@@ -144,9 +141,8 @@ static void log_option(const char *pfx, const uint8_t *opt) | |||
144 | # define log_option(pfx, opt) ((void)0) | 141 | # define log_option(pfx, opt) ((void)0) |
145 | #endif | 142 | #endif |
146 | 143 | ||
147 | |||
148 | /* get an option with bounds checking (warning, result is not aligned). */ | 144 | /* get an option with bounds checking (warning, result is not aligned). */ |
149 | uint8_t* FAST_FUNC get_option(struct dhcp_packet *packet, int code) | 145 | uint8_t* FAST_FUNC udhcp_get_option(struct dhcp_packet *packet, int code) |
150 | { | 146 | { |
151 | uint8_t *optionptr; | 147 | uint8_t *optionptr; |
152 | int len; | 148 | int len; |
@@ -162,7 +158,7 @@ uint8_t* FAST_FUNC get_option(struct dhcp_packet *packet, int code) | |||
162 | rem = sizeof(packet->options); | 158 | rem = sizeof(packet->options); |
163 | while (1) { | 159 | while (1) { |
164 | if (rem <= 0) { | 160 | if (rem <= 0) { |
165 | bb_error_msg("bogus packet, malformed option field"); | 161 | bb_error_msg("bad packet, malformed option field"); |
166 | return NULL; | 162 | return NULL; |
167 | } | 163 | } |
168 | if (optionptr[OPT_CODE] == DHCP_PADDING) { | 164 | if (optionptr[OPT_CODE] == DHCP_PADDING) { |
@@ -209,9 +205,8 @@ uint8_t* FAST_FUNC get_option(struct dhcp_packet *packet, int code) | |||
209 | return NULL; | 205 | return NULL; |
210 | } | 206 | } |
211 | 207 | ||
212 | |||
213 | /* return the position of the 'end' option (no bounds checking) */ | 208 | /* return the position of the 'end' option (no bounds checking) */ |
214 | int FAST_FUNC end_option(uint8_t *optionptr) | 209 | int FAST_FUNC udhcp_end_option(uint8_t *optionptr) |
215 | { | 210 | { |
216 | int i = 0; | 211 | int i = 0; |
217 | 212 | ||
@@ -223,12 +218,11 @@ int FAST_FUNC end_option(uint8_t *optionptr) | |||
223 | return i; | 218 | return i; |
224 | } | 219 | } |
225 | 220 | ||
226 | |||
227 | /* add an option string to the options */ | 221 | /* add an option string to the options */ |
228 | /* option bytes: [code][len][data1][data2]..[dataLEN] */ | 222 | /* option bytes: [code][len][data1][data2]..[dataLEN] */ |
229 | void FAST_FUNC add_option_string(uint8_t *optionptr, uint8_t *string) | 223 | void FAST_FUNC udhcp_add_option_string(uint8_t *optionptr, uint8_t *string) |
230 | { | 224 | { |
231 | int end = end_option(optionptr); | 225 | int end = udhcp_end_option(optionptr); |
232 | 226 | ||
233 | /* end position + string length + option code/length + end option */ | 227 | /* end position + string length + option code/length + end option */ |
234 | if (end + string[OPT_LEN] + 2 + 1 >= DHCP_OPTIONS_BUFSIZE) { | 228 | if (end + string[OPT_LEN] + 2 + 1 >= DHCP_OPTIONS_BUFSIZE) { |
@@ -241,9 +235,8 @@ void FAST_FUNC add_option_string(uint8_t *optionptr, uint8_t *string) | |||
241 | optionptr[end + string[OPT_LEN] + 2] = DHCP_END; | 235 | optionptr[end + string[OPT_LEN] + 2] = DHCP_END; |
242 | } | 236 | } |
243 | 237 | ||
244 | |||
245 | /* add a one to four byte option to a packet */ | 238 | /* add a one to four byte option to a packet */ |
246 | void FAST_FUNC add_simple_option(uint8_t *optionptr, uint8_t code, uint32_t data) | 239 | void FAST_FUNC udhcp_add_simple_option(uint8_t *optionptr, uint8_t code, uint32_t data) |
247 | { | 240 | { |
248 | const struct dhcp_option *dh; | 241 | const struct dhcp_option *dh; |
249 | 242 | ||
@@ -258,7 +251,7 @@ void FAST_FUNC add_simple_option(uint8_t *optionptr, uint8_t code, uint32_t data | |||
258 | data <<= 8 * (4 - len); | 251 | data <<= 8 * (4 - len); |
259 | /* Assignment is unaligned! */ | 252 | /* Assignment is unaligned! */ |
260 | move_to_unaligned32(&option[OPT_DATA], data); | 253 | move_to_unaligned32(&option[OPT_DATA], data); |
261 | add_option_string(optionptr, option); | 254 | udhcp_add_option_string(optionptr, option); |
262 | return; | 255 | return; |
263 | } | 256 | } |
264 | } | 257 | } |
diff --git a/networking/udhcp/options.h b/networking/udhcp/options.h deleted file mode 100644 index 3ca4dc42d..000000000 --- a/networking/udhcp/options.h +++ /dev/null | |||
@@ -1,119 +0,0 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* options.h */ | ||
3 | #ifndef UDHCP_OPTIONS_H | ||
4 | #define UDHCP_OPTIONS_H 1 | ||
5 | |||
6 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | ||
7 | |||
8 | |||
9 | enum { | ||
10 | OPTION_IP = 1, | ||
11 | OPTION_IP_PAIR, | ||
12 | OPTION_STRING, | ||
13 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
14 | OPTION_STR1035, /* RFC1035 compressed domain name list */ | ||
15 | #endif | ||
16 | OPTION_BOOLEAN, | ||
17 | OPTION_U8, | ||
18 | OPTION_U16, | ||
19 | OPTION_S16, | ||
20 | OPTION_U32, | ||
21 | OPTION_S32, | ||
22 | OPTION_STATIC_ROUTES, | ||
23 | |||
24 | OPTION_TYPE_MASK = 0x0f, | ||
25 | /* Client requests this option by default */ | ||
26 | OPTION_REQ = 0x10, | ||
27 | /* There can be a list of 1 or more of these */ | ||
28 | OPTION_LIST = 0x20, | ||
29 | }; | ||
30 | |||
31 | /* DHCP option codes (partial list). See RFC 2132 and | ||
32 | * http://www.iana.org/assignments/bootp-dhcp-parameters/ | ||
33 | * Commented out options are handled by common option machinery, | ||
34 | * uncommented ones have spacial cases (grep for them to see). | ||
35 | */ | ||
36 | #define DHCP_PADDING 0x00 | ||
37 | #define DHCP_SUBNET 0x01 | ||
38 | //#define DHCP_TIME_OFFSET 0x02 /* (localtime - UTC_time) in seconds. signed */ | ||
39 | //#define DHCP_ROUTER 0x03 | ||
40 | //#define DHCP_TIME_SERVER 0x04 /* RFC 868 time server (32-bit, 0 = 1.1.1900) */ | ||
41 | //#define DHCP_NAME_SERVER 0x05 /* IEN 116 _really_ ancient kind of NS */ | ||
42 | //#define DHCP_DNS_SERVER 0x06 | ||
43 | //#define DHCP_LOG_SERVER 0x07 /* port 704 UDP log (not syslog) | ||
44 | //#define DHCP_COOKIE_SERVER 0x08 /* "quote of the day" server */ | ||
45 | //#define DHCP_LPR_SERVER 0x09 | ||
46 | #define DHCP_HOST_NAME 0x0c /* either client informs server or server gives name to client */ | ||
47 | //#define DHCP_BOOT_SIZE 0x0d | ||
48 | //#define DHCP_DOMAIN_NAME 0x0f /* server gives domain suffix */ | ||
49 | //#define DHCP_SWAP_SERVER 0x10 | ||
50 | //#define DHCP_ROOT_PATH 0x11 | ||
51 | //#define DHCP_IP_TTL 0x17 | ||
52 | //#define DHCP_MTU 0x1a | ||
53 | //#define DHCP_BROADCAST 0x1c | ||
54 | //#define DHCP_NIS_DOMAIN 0x28 | ||
55 | //#define DHCP_NIS_SERVER 0x29 | ||
56 | //#define DHCP_NTP_SERVER 0x2a | ||
57 | //#define DHCP_WINS_SERVER 0x2c | ||
58 | #define DHCP_REQUESTED_IP 0x32 /* sent by client if specific IP is wanted */ | ||
59 | #define DHCP_LEASE_TIME 0x33 | ||
60 | #define DHCP_OPTION_OVERLOAD 0x34 | ||
61 | #define DHCP_MESSAGE_TYPE 0x35 | ||
62 | #define DHCP_SERVER_ID 0x36 /* by default server's IP */ | ||
63 | #define DHCP_PARAM_REQ 0x37 /* list of options client wants */ | ||
64 | //#define DHCP_ERR_MESSAGE 0x38 /* error message when sending NAK etc */ | ||
65 | #define DHCP_MAX_SIZE 0x39 | ||
66 | #define DHCP_VENDOR 0x3c /* client's vendor (a string) */ | ||
67 | #define DHCP_CLIENT_ID 0x3d /* by default client's MAC addr, but may be arbitrarily long */ | ||
68 | //#define DHCP_TFTP_SERVER_NAME 0x42 /* same as 'sname' field */ | ||
69 | //#define DHCP_BOOT_FILE 0x43 /* same as 'file' field */ | ||
70 | //#define DHCP_USER_CLASS 0x4d /* RFC 3004. set of LASCII strings. "I am a printer" etc */ | ||
71 | #define DHCP_FQDN 0x51 /* client asks to update DNS to map its FQDN to its new IP */ | ||
72 | //#define DHCP_DOMAIN_SEARCH 0x77 /* RFC 3397. set of ASCIZ string, DNS-style compressed */ | ||
73 | //#define DHCP_STATIC_ROUTES 0x79 /* RFC 3442. (mask,ip,router) tuples */ | ||
74 | //#define DHCP_WPAD 0xfc /* MSIE's Web Proxy Autodiscovery Protocol */ | ||
75 | #define DHCP_END 0xff | ||
76 | |||
77 | /* Offsets in option byte sequence */ | ||
78 | #define OPT_CODE 0 | ||
79 | #define OPT_LEN 1 | ||
80 | #define OPT_DATA 2 | ||
81 | /* Bits in "overload" option */ | ||
82 | #define OPTION_FIELD 0 | ||
83 | #define FILE_FIELD 1 | ||
84 | #define SNAME_FIELD 2 | ||
85 | |||
86 | /* DHCP_MESSAGE_TYPE values */ | ||
87 | #define DHCPDISCOVER 1 /* client -> server */ | ||
88 | #define DHCPOFFER 2 /* client <- server */ | ||
89 | #define DHCPREQUEST 3 /* client -> server */ | ||
90 | #define DHCPDECLINE 4 /* client -> server */ | ||
91 | #define DHCPACK 5 /* client <- server */ | ||
92 | #define DHCPNAK 6 /* client <- server */ | ||
93 | #define DHCPRELEASE 7 /* client -> server */ | ||
94 | #define DHCPINFORM 8 /* client -> server */ | ||
95 | #define DHCP_MINTYPE DHCPDISCOVER | ||
96 | #define DHCP_MAXTYPE DHCPINFORM | ||
97 | |||
98 | |||
99 | struct dhcp_option { | ||
100 | uint8_t flags; | ||
101 | uint8_t code; | ||
102 | }; | ||
103 | |||
104 | extern const struct dhcp_option dhcp_options[]; | ||
105 | extern const char dhcp_option_strings[]; | ||
106 | extern const uint8_t dhcp_option_lengths[]; | ||
107 | |||
108 | uint8_t *get_option(struct dhcp_packet *packet, int code) FAST_FUNC; | ||
109 | int end_option(uint8_t *optionptr) FAST_FUNC; | ||
110 | void add_option_string(uint8_t *optionptr, uint8_t *string) FAST_FUNC; | ||
111 | void add_simple_option(uint8_t *optionptr, uint8_t code, uint32_t data) FAST_FUNC; | ||
112 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
113 | char *dname_dec(const uint8_t *cstr, int clen, const char *pre) FAST_FUNC; | ||
114 | uint8_t *dname_enc(const uint8_t *cstr, int clen, const char *src, int *retlen) FAST_FUNC; | ||
115 | #endif | ||
116 | |||
117 | POP_SAVED_FUNCTION_VISIBILITY | ||
118 | |||
119 | #endif | ||
diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c index 84d83098c..03d5e1fc8 100644 --- a/networking/udhcp/packet.c +++ b/networking/udhcp/packet.c | |||
@@ -17,7 +17,6 @@ | |||
17 | 17 | ||
18 | #include "common.h" | 18 | #include "common.h" |
19 | #include "dhcpd.h" | 19 | #include "dhcpd.h" |
20 | #include "options.h" | ||
21 | 20 | ||
22 | void FAST_FUNC udhcp_init_header(struct dhcp_packet *packet, char type) | 21 | void FAST_FUNC udhcp_init_header(struct dhcp_packet *packet, char type) |
23 | { | 22 | { |
@@ -34,7 +33,7 @@ void FAST_FUNC udhcp_init_header(struct dhcp_packet *packet, char type) | |||
34 | packet->cookie = htonl(DHCP_MAGIC); | 33 | packet->cookie = htonl(DHCP_MAGIC); |
35 | if (DHCP_END != 0) | 34 | if (DHCP_END != 0) |
36 | packet->options[0] = DHCP_END; | 35 | packet->options[0] = DHCP_END; |
37 | add_simple_option(packet->options, DHCP_MESSAGE_TYPE, type); | 36 | udhcp_add_simple_option(packet->options, DHCP_MESSAGE_TYPE, type); |
38 | } | 37 | } |
39 | 38 | ||
40 | #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2 | 39 | #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2 |
@@ -105,7 +104,7 @@ int FAST_FUNC udhcp_recv_kernel_packet(struct dhcp_packet *packet, int fd) | |||
105 | udhcp_dump_packet(packet); | 104 | udhcp_dump_packet(packet); |
106 | 105 | ||
107 | if (packet->op == BOOTREQUEST) { | 106 | if (packet->op == BOOTREQUEST) { |
108 | vendor = get_option(packet, DHCP_VENDOR); | 107 | vendor = udhcp_get_option(packet, DHCP_VENDOR); |
109 | if (vendor) { | 108 | if (vendor) { |
110 | #if 0 | 109 | #if 0 |
111 | static const char broken_vendors[][8] = { | 110 | static const char broken_vendors[][8] = { |
@@ -221,7 +220,7 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, | |||
221 | 220 | ||
222 | /* Currently we send full-sized DHCP packets (zero padded). | 221 | /* Currently we send full-sized DHCP packets (zero padded). |
223 | * If you need to change this: last byte of the packet is | 222 | * If you need to change this: last byte of the packet is |
224 | * packet.data.options[end_option(packet.data.options)] | 223 | * packet.data.options[udhcp_end_option(packet.data.options)] |
225 | */ | 224 | */ |
226 | udhcp_dump_packet(dhcp_pkt); | 225 | udhcp_dump_packet(dhcp_pkt); |
227 | result = sendto(fd, &packet, IP_UPD_DHCP_SIZE, 0, | 226 | result = sendto(fd, &packet, IP_UPD_DHCP_SIZE, 0, |
diff --git a/networking/udhcp/script.c b/networking/udhcp/script.c deleted file mode 100644 index 400fd2b9b..000000000 --- a/networking/udhcp/script.c +++ /dev/null | |||
@@ -1,283 +0,0 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* script.c | ||
3 | * | ||
4 | * Functions to call the DHCP client notification scripts | ||
5 | * | ||
6 | * Russ Dill <Russ.Dill@asu.edu> July 2001 | ||
7 | * | ||
8 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | ||
9 | */ | ||
10 | |||
11 | #include "common.h" | ||
12 | #include "dhcpc.h" | ||
13 | #include "options.h" | ||
14 | |||
15 | |||
16 | /* get a rough idea of how long an option will be (rounding up...) */ | ||
17 | static const uint8_t len_of_option_as_string[] = { | ||
18 | [OPTION_IP] = sizeof("255.255.255.255 "), | ||
19 | [OPTION_IP_PAIR] = sizeof("255.255.255.255 ") * 2, | ||
20 | [OPTION_STATIC_ROUTES]= sizeof("255.255.255.255/32 255.255.255.255 "), | ||
21 | [OPTION_STRING] = 1, | ||
22 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
23 | [OPTION_STR1035] = 1, | ||
24 | #endif | ||
25 | [OPTION_BOOLEAN] = sizeof("yes "), | ||
26 | [OPTION_U8] = sizeof("255 "), | ||
27 | [OPTION_U16] = sizeof("65535 "), | ||
28 | [OPTION_S16] = sizeof("-32768 "), | ||
29 | [OPTION_U32] = sizeof("4294967295 "), | ||
30 | [OPTION_S32] = sizeof("-2147483684 "), | ||
31 | }; | ||
32 | |||
33 | |||
34 | /* note: ip is a pointer to an IP in network order, possibly misaliged */ | ||
35 | static int sprint_nip(char *dest, const char *pre, const uint8_t *ip) | ||
36 | { | ||
37 | return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]); | ||
38 | } | ||
39 | |||
40 | |||
41 | /* really simple implementation, just count the bits */ | ||
42 | static int mton(uint32_t mask) | ||
43 | { | ||
44 | int i = 0; | ||
45 | mask = ntohl(mask); /* 111110000-like bit pattern */ | ||
46 | while (mask) { | ||
47 | i++; | ||
48 | mask <<= 1; | ||
49 | } | ||
50 | return i; | ||
51 | } | ||
52 | |||
53 | |||
54 | /* Create "opt_name=opt_value" string */ | ||
55 | static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_option *type_p, const char *opt_name) | ||
56 | { | ||
57 | unsigned upper_length; | ||
58 | int len, type, optlen; | ||
59 | uint16_t val_u16; | ||
60 | int16_t val_s16; | ||
61 | uint32_t val_u32; | ||
62 | int32_t val_s32; | ||
63 | char *dest, *ret; | ||
64 | |||
65 | /* option points to OPT_DATA, need to go back and get OPT_LEN */ | ||
66 | len = option[OPT_LEN - OPT_DATA]; | ||
67 | type = type_p->flags & OPTION_TYPE_MASK; | ||
68 | optlen = dhcp_option_lengths[type]; | ||
69 | upper_length = len_of_option_as_string[type] * (len / optlen); | ||
70 | |||
71 | dest = ret = xmalloc(upper_length + strlen(opt_name) + 2); | ||
72 | dest += sprintf(ret, "%s=", opt_name); | ||
73 | |||
74 | while (len >= optlen) { | ||
75 | switch (type) { | ||
76 | case OPTION_IP_PAIR: | ||
77 | dest += sprint_nip(dest, "", option); | ||
78 | *dest++ = '/'; | ||
79 | option += 4; | ||
80 | optlen = 4; | ||
81 | case OPTION_IP: | ||
82 | dest += sprint_nip(dest, "", option); | ||
83 | // TODO: it can be a list only if (type_p->flags & OPTION_LIST). | ||
84 | // Should we bail out/warn if we see multi-ip option which is | ||
85 | // not allowed to be such? For example, DHCP_BROADCAST... | ||
86 | break; | ||
87 | case OPTION_BOOLEAN: | ||
88 | dest += sprintf(dest, *option ? "yes" : "no"); | ||
89 | break; | ||
90 | case OPTION_U8: | ||
91 | dest += sprintf(dest, "%u", *option); | ||
92 | break; | ||
93 | case OPTION_U16: | ||
94 | move_from_unaligned16(val_u16, option); | ||
95 | dest += sprintf(dest, "%u", ntohs(val_u16)); | ||
96 | break; | ||
97 | case OPTION_S16: | ||
98 | move_from_unaligned16(val_s16, option); | ||
99 | dest += sprintf(dest, "%d", ntohs(val_s16)); | ||
100 | break; | ||
101 | case OPTION_U32: | ||
102 | move_from_unaligned32(val_u32, option); | ||
103 | dest += sprintf(dest, "%lu", (unsigned long) ntohl(val_u32)); | ||
104 | break; | ||
105 | case OPTION_S32: | ||
106 | move_from_unaligned32(val_s32, option); | ||
107 | dest += sprintf(dest, "%ld", (long) ntohl(val_s32)); | ||
108 | break; | ||
109 | case OPTION_STRING: | ||
110 | memcpy(dest, option, len); | ||
111 | dest[len] = '\0'; | ||
112 | return ret; /* Short circuit this case */ | ||
113 | case OPTION_STATIC_ROUTES: { | ||
114 | /* Option binary format: | ||
115 | * mask [one byte, 0..32] | ||
116 | * ip [big endian, 0..4 bytes depending on mask] | ||
117 | * router [big endian, 4 bytes] | ||
118 | * may be repeated | ||
119 | * | ||
120 | * We convert it to a string "IP/MASK ROUTER IP2/MASK2 ROUTER2" | ||
121 | */ | ||
122 | const char *pfx = ""; | ||
123 | |||
124 | while (len >= 1 + 4) { /* mask + 0-byte ip + router */ | ||
125 | uint32_t nip; | ||
126 | uint8_t *p; | ||
127 | unsigned mask; | ||
128 | int bytes; | ||
129 | |||
130 | mask = *option++; | ||
131 | if (mask > 32) | ||
132 | break; | ||
133 | len--; | ||
134 | |||
135 | nip = 0; | ||
136 | p = (void*) &nip; | ||
137 | bytes = (mask + 7) / 8; /* 0 -> 0, 1..8 -> 1, 9..16 -> 2 etc */ | ||
138 | while (--bytes >= 0) { | ||
139 | *p++ = *option++; | ||
140 | len--; | ||
141 | } | ||
142 | if (len < 4) | ||
143 | break; | ||
144 | |||
145 | /* print ip/mask */ | ||
146 | dest += sprint_nip(dest, pfx, (void*) &nip); | ||
147 | pfx = " "; | ||
148 | dest += sprintf(dest, "/%u ", mask); | ||
149 | /* print router */ | ||
150 | dest += sprint_nip(dest, "", option); | ||
151 | option += 4; | ||
152 | len -= 4; | ||
153 | } | ||
154 | |||
155 | return ret; | ||
156 | } | ||
157 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
158 | case OPTION_STR1035: | ||
159 | /* unpack option into dest; use ret for prefix (i.e., "optname=") */ | ||
160 | dest = dname_dec(option, len, ret); | ||
161 | if (dest) { | ||
162 | free(ret); | ||
163 | return dest; | ||
164 | } | ||
165 | /* error. return "optname=" string */ | ||
166 | return ret; | ||
167 | #endif | ||
168 | } | ||
169 | option += optlen; | ||
170 | len -= optlen; | ||
171 | if (len <= 0) | ||
172 | break; | ||
173 | *dest++ = ' '; | ||
174 | *dest = '\0'; | ||
175 | } | ||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | |||
180 | /* put all the parameters into the environment */ | ||
181 | static char **fill_envp(struct dhcp_packet *packet) | ||
182 | { | ||
183 | int num_options = 0; | ||
184 | int i; | ||
185 | char **envp, **curr; | ||
186 | const char *opt_name; | ||
187 | uint8_t *temp; | ||
188 | uint8_t over = 0; | ||
189 | |||
190 | if (packet) { | ||
191 | for (i = 0; dhcp_options[i].code; i++) { | ||
192 | if (get_option(packet, dhcp_options[i].code)) { | ||
193 | num_options++; | ||
194 | if (dhcp_options[i].code == DHCP_SUBNET) | ||
195 | num_options++; /* for mton */ | ||
196 | } | ||
197 | } | ||
198 | if (packet->siaddr_nip) | ||
199 | num_options++; | ||
200 | temp = get_option(packet, DHCP_OPTION_OVERLOAD); | ||
201 | if (temp) | ||
202 | over = *temp; | ||
203 | if (!(over & FILE_FIELD) && packet->file[0]) | ||
204 | num_options++; | ||
205 | if (!(over & SNAME_FIELD) && packet->sname[0]) | ||
206 | num_options++; | ||
207 | } | ||
208 | |||
209 | curr = envp = xzalloc(sizeof(char *) * (num_options + 3)); | ||
210 | *curr = xasprintf("interface=%s", client_config.interface); | ||
211 | putenv(*curr++); | ||
212 | |||
213 | if (packet == NULL) | ||
214 | return envp; | ||
215 | |||
216 | *curr = xmalloc(sizeof("ip=255.255.255.255")); | ||
217 | sprint_nip(*curr, "ip=", (uint8_t *) &packet->yiaddr); | ||
218 | putenv(*curr++); | ||
219 | |||
220 | opt_name = dhcp_option_strings; | ||
221 | i = 0; | ||
222 | while (*opt_name) { | ||
223 | temp = get_option(packet, dhcp_options[i].code); | ||
224 | if (!temp) | ||
225 | goto next; | ||
226 | *curr = xmalloc_optname_optval(temp, &dhcp_options[i], opt_name); | ||
227 | putenv(*curr++); | ||
228 | |||
229 | /* Fill in a subnet bits option for things like /24 */ | ||
230 | if (dhcp_options[i].code == DHCP_SUBNET) { | ||
231 | uint32_t subnet; | ||
232 | move_from_unaligned32(subnet, temp); | ||
233 | *curr = xasprintf("mask=%d", mton(subnet)); | ||
234 | putenv(*curr++); | ||
235 | } | ||
236 | next: | ||
237 | opt_name += strlen(opt_name) + 1; | ||
238 | i++; | ||
239 | } | ||
240 | if (packet->siaddr_nip) { | ||
241 | *curr = xmalloc(sizeof("siaddr=255.255.255.255")); | ||
242 | sprint_nip(*curr, "siaddr=", (uint8_t *) &packet->siaddr_nip); | ||
243 | putenv(*curr++); | ||
244 | } | ||
245 | if (!(over & FILE_FIELD) && packet->file[0]) { | ||
246 | /* watch out for invalid packets */ | ||
247 | *curr = xasprintf("boot_file=%."DHCP_PKT_FILE_LEN_STR"s", packet->file); | ||
248 | putenv(*curr++); | ||
249 | } | ||
250 | if (!(over & SNAME_FIELD) && packet->sname[0]) { | ||
251 | /* watch out for invalid packets */ | ||
252 | *curr = xasprintf("sname=%."DHCP_PKT_SNAME_LEN_STR"s", packet->sname); | ||
253 | putenv(*curr++); | ||
254 | } | ||
255 | return envp; | ||
256 | } | ||
257 | |||
258 | |||
259 | /* Call a script with a par file and env vars */ | ||
260 | void FAST_FUNC udhcp_run_script(struct dhcp_packet *packet, const char *name) | ||
261 | { | ||
262 | char **envp, **curr; | ||
263 | char *argv[3]; | ||
264 | |||
265 | if (client_config.script == NULL) | ||
266 | return; | ||
267 | |||
268 | envp = fill_envp(packet); | ||
269 | |||
270 | /* call script */ | ||
271 | log1("Executing %s %s", client_config.script, name); | ||
272 | argv[0] = (char*) client_config.script; | ||
273 | argv[1] = (char*) name; | ||
274 | argv[2] = NULL; | ||
275 | spawn_and_wait(argv); | ||
276 | |||
277 | for (curr = envp; *curr; curr++) { | ||
278 | log2(" %s", *curr); | ||
279 | bb_unsetenv(*curr); | ||
280 | free(*curr); | ||
281 | } | ||
282 | free(envp); | ||
283 | } | ||