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 | } | ||
