summaryrefslogtreecommitdiff
path: root/networking
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2017-07-18 15:58:52 +0100
committerRon Yorston <rmy@pobox.com>2017-07-18 15:58:52 +0100
commitb680f05ad449505e3d914bebd4c8d83bf768c094 (patch)
treec08ded13d430b0e7e0104f2eb594fad190ce98a3 /networking
parent258200ff81d5a9da54dab35acf36213eff1e399b (diff)
parent513a2457b65894b10b9fd6aa8753fca59eced08c (diff)
downloadbusybox-w32-b680f05ad449505e3d914bebd4c8d83bf768c094.tar.gz
busybox-w32-b680f05ad449505e3d914bebd4c8d83bf768c094.tar.bz2
busybox-w32-b680f05ad449505e3d914bebd4c8d83bf768c094.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'networking')
-rw-r--r--networking/inetd.c20
-rw-r--r--networking/libiproute/iproute.c26
-rw-r--r--networking/libiproute/iprule.c73
-rw-r--r--networking/tls.c4
-rw-r--r--networking/tls_aes.c4
-rw-r--r--networking/tls_pstm.c2
-rw-r--r--networking/tls_pstm_montgomery_reduce.c2
-rw-r--r--networking/tls_pstm_mul_comba.c5
-rw-r--r--networking/tls_pstm_sqr_comba.c8
-rw-r--r--networking/udhcp/common.c27
-rw-r--r--networking/udhcp/common.h19
-rw-r--r--networking/udhcp/d6_common.h39
-rw-r--r--networking/udhcp/d6_dhcpc.c248
-rw-r--r--networking/udhcp/dhcpc.c4
-rw-r--r--networking/udhcp/dhcpc.h1
-rw-r--r--networking/udhcp/dhcpd.c8
-rw-r--r--networking/udhcp/packet.c2
17 files changed, 339 insertions, 153 deletions
diff --git a/networking/inetd.c b/networking/inetd.c
index 01e659f13..3bf157b70 100644
--- a/networking/inetd.c
+++ b/networking/inetd.c
@@ -227,7 +227,8 @@
227 227
228#if ENABLE_FEATURE_INETD_RPC 228#if ENABLE_FEATURE_INETD_RPC
229# if defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_RPC__) 229# if defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_RPC__)
230# error "You need to build uClibc with UCLIBC_HAS_RPC for NFS support" 230# warning "You probably need to build uClibc with UCLIBC_HAS_RPC for NFS support"
231 /* not #error, since user may be using e.g. libtirpc instead */
231# endif 232# endif
232# include <rpc/rpc.h> 233# include <rpc/rpc.h>
233# include <rpc/pmap_clnt.h> 234# include <rpc/pmap_clnt.h>
@@ -1513,8 +1514,11 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1513 } /* for (;;) */ 1514 } /* for (;;) */
1514} 1515}
1515 1516
1516#if !BB_MMU 1517#if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO \
1518 || ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD
1519# if !BB_MMU
1517static const char *const cat_args[] = { "cat", NULL }; 1520static const char *const cat_args[] = { "cat", NULL };
1521# endif
1518#endif 1522#endif
1519 1523
1520/* 1524/*
@@ -1525,14 +1529,14 @@ static const char *const cat_args[] = { "cat", NULL };
1525/* ARGSUSED */ 1529/* ARGSUSED */
1526static void FAST_FUNC echo_stream(int s, servtab_t *sep UNUSED_PARAM) 1530static void FAST_FUNC echo_stream(int s, servtab_t *sep UNUSED_PARAM)
1527{ 1531{
1528#if BB_MMU 1532# if BB_MMU
1529 while (1) { 1533 while (1) {
1530 ssize_t sz = safe_read(s, line, LINE_SIZE); 1534 ssize_t sz = safe_read(s, line, LINE_SIZE);
1531 if (sz <= 0) 1535 if (sz <= 0)
1532 break; 1536 break;
1533 xwrite(s, line, sz); 1537 xwrite(s, line, sz);
1534 } 1538 }
1535#else 1539# else
1536 /* We are after vfork here! */ 1540 /* We are after vfork here! */
1537 /* move network socket to stdin/stdout */ 1541 /* move network socket to stdin/stdout */
1538 xmove_fd(s, STDIN_FILENO); 1542 xmove_fd(s, STDIN_FILENO);
@@ -1542,7 +1546,7 @@ static void FAST_FUNC echo_stream(int s, servtab_t *sep UNUSED_PARAM)
1542 xopen(bb_dev_null, O_WRONLY); 1546 xopen(bb_dev_null, O_WRONLY);
1543 BB_EXECVP("cat", (char**)cat_args); 1547 BB_EXECVP("cat", (char**)cat_args);
1544 /* on failure we return to main, which does exit(EXIT_FAILURE) */ 1548 /* on failure we return to main, which does exit(EXIT_FAILURE) */
1545#endif 1549# endif
1546} 1550}
1547static void FAST_FUNC echo_dg(int s, servtab_t *sep) 1551static void FAST_FUNC echo_dg(int s, servtab_t *sep)
1548{ 1552{
@@ -1566,10 +1570,10 @@ static void FAST_FUNC echo_dg(int s, servtab_t *sep)
1566/* ARGSUSED */ 1570/* ARGSUSED */
1567static void FAST_FUNC discard_stream(int s, servtab_t *sep UNUSED_PARAM) 1571static void FAST_FUNC discard_stream(int s, servtab_t *sep UNUSED_PARAM)
1568{ 1572{
1569#if BB_MMU 1573# if BB_MMU
1570 while (safe_read(s, line, LINE_SIZE) > 0) 1574 while (safe_read(s, line, LINE_SIZE) > 0)
1571 continue; 1575 continue;
1572#else 1576# else
1573 /* We are after vfork here! */ 1577 /* We are after vfork here! */
1574 /* move network socket to stdin */ 1578 /* move network socket to stdin */
1575 xmove_fd(s, STDIN_FILENO); 1579 xmove_fd(s, STDIN_FILENO);
@@ -1580,7 +1584,7 @@ static void FAST_FUNC discard_stream(int s, servtab_t *sep UNUSED_PARAM)
1580 xdup2(STDOUT_FILENO, STDERR_FILENO); 1584 xdup2(STDOUT_FILENO, STDERR_FILENO);
1581 BB_EXECVP("cat", (char**)cat_args); 1585 BB_EXECVP("cat", (char**)cat_args);
1582 /* on failure we return to main, which does exit(EXIT_FAILURE) */ 1586 /* on failure we return to main, which does exit(EXIT_FAILURE) */
1583#endif 1587# endif
1584} 1588}
1585/* ARGSUSED */ 1589/* ARGSUSED */
1586static void FAST_FUNC discard_dg(int s, servtab_t *sep UNUSED_PARAM) 1590static void FAST_FUNC discard_dg(int s, servtab_t *sep UNUSED_PARAM)
diff --git a/networking/libiproute/iproute.c b/networking/libiproute/iproute.c
index cc3443a92..6a41b8331 100644
--- a/networking/libiproute/iproute.c
+++ b/networking/libiproute/iproute.c
@@ -28,7 +28,7 @@ struct filter_t {
28 int flushe; 28 int flushe;
29 struct rtnl_handle *rth; 29 struct rtnl_handle *rth;
30 //int protocol, protocolmask; - write-only fields?! 30 //int protocol, protocolmask; - write-only fields?!
31 //int scope, scopemask; - unused 31 int scope, scopemask;
32 //int type; - read-only 32 //int type; - read-only
33 //int typemask; - unused 33 //int typemask; - unused
34 //int tos, tosmask; - unused 34 //int tos, tosmask; - unused
@@ -120,6 +120,8 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
120 return 0; 120 return 0;
121 } 121 }
122 } 122 }
123 if ((G_filter.scope ^ r->rtm_scope) & G_filter.scopemask)
124 return 0;
123 if (G_filter.rdst.family 125 if (G_filter.rdst.family
124 && (r->rtm_family != G_filter.rdst.family || G_filter.rdst.bitlen > r->rtm_dst_len) 126 && (r->rtm_family != G_filter.rdst.family || G_filter.rdst.bitlen > r->rtm_dst_len)
125 ) { 127 ) {
@@ -270,7 +272,11 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
270 printf("table %s ", rtnl_rttable_n2a(tid)); 272 printf("table %s ", rtnl_rttable_n2a(tid));
271#endif 273#endif
272 274
273 /* Todo: parse & show "proto kernel", "scope link" here */ 275 /* Todo: parse & show "proto kernel" here */
276 if (!(r->rtm_flags & RTM_F_CLONED)) {
277 if ((r->rtm_scope != RT_SCOPE_UNIVERSE) && G_filter.scopemask != -1)
278 printf("scope %s ", rtnl_rtscope_n2a(r->rtm_scope));
279 }
274 280
275 if (tb[RTA_PREFSRC] && /*G_filter.rprefsrc.bitlen - always 0*/ 0 != host_len) { 281 if (tb[RTA_PREFSRC] && /*G_filter.rprefsrc.bitlen - always 0*/ 0 != host_len) {
276 /* Do not use format_host(). It is our local addr 282 /* Do not use format_host(). It is our local addr
@@ -761,10 +767,11 @@ static int iproute_list_or_flush(char **argv, int flush)
761 char *id = NULL; 767 char *id = NULL;
762 char *od = NULL; 768 char *od = NULL;
763 static const char keywords[] ALIGN1 = 769 static const char keywords[] ALIGN1 =
770 /* If you add stuff here, update iproute_full_usage */
764 /* "ip route list/flush" parameters: */ 771 /* "ip route list/flush" parameters: */
765 "protocol\0" "dev\0" "oif\0" "iif\0" 772 "protocol\0" "dev\0" "oif\0" "iif\0"
766 "via\0" "table\0" "cache\0" 773 "via\0" "table\0" "cache\0"
767 "from\0" "to\0" 774 "from\0" "to\0" "scope\0"
768 /* and possible further keywords */ 775 /* and possible further keywords */
769 "all\0" 776 "all\0"
770 "root\0" 777 "root\0"
@@ -775,7 +782,7 @@ static int iproute_list_or_flush(char **argv, int flush)
775 enum { 782 enum {
776 KW_proto, KW_dev, KW_oif, KW_iif, 783 KW_proto, KW_dev, KW_oif, KW_iif,
777 KW_via, KW_table, KW_cache, 784 KW_via, KW_table, KW_cache,
778 KW_from, KW_to, 785 KW_from, KW_to, KW_scope,
779 /* */ 786 /* */
780 KW_all, 787 KW_all,
781 KW_root, 788 KW_root,
@@ -834,6 +841,17 @@ static int iproute_list_or_flush(char **argv, int flush)
834 /* The command 'ip route flush cache' is used by OpenSWAN. 841 /* The command 'ip route flush cache' is used by OpenSWAN.
835 * Assuming it's a synonym for 'ip route flush table cache' */ 842 * Assuming it's a synonym for 'ip route flush table cache' */
836 G_filter.tb = -1; 843 G_filter.tb = -1;
844 } else if (arg == KW_scope) {
845 uint32_t scope;
846 NEXT_ARG();
847 G_filter.scopemask = -1;
848 if (rtnl_rtscope_a2n(&scope, *argv)) {
849 if (strcmp(*argv, "all") != 0)
850 invarg_1_to_2(*argv, "scope");
851 scope = RT_SCOPE_NOWHERE;
852 G_filter.scopemask = 0;
853 }
854 G_filter.scope = scope;
837 } else if (arg == KW_from) { 855 } else if (arg == KW_from) {
838 NEXT_ARG(); 856 NEXT_ARG();
839 parm = index_in_substrings(keywords, *argv); 857 parm = index_in_substrings(keywords, *argv);
diff --git a/networking/libiproute/iprule.c b/networking/libiproute/iprule.c
index 8f3f86286..1bb5e759e 100644
--- a/networking/libiproute/iprule.c
+++ b/networking/libiproute/iprule.c
@@ -17,25 +17,32 @@
17#include <netinet/ip.h> 17#include <netinet/ip.h>
18#include <arpa/inet.h> 18#include <arpa/inet.h>
19 19
20/* from <linux/fib_rules.h>: */
21#define FRA_SUPPRESS_IFGROUP 13
22#define FRA_SUPPRESS_PREFIXLEN 14
23
20#include "ip_common.h" /* #include "libbb.h" is inside */ 24#include "ip_common.h" /* #include "libbb.h" is inside */
21#include "rt_names.h" 25#include "rt_names.h"
22#include "utils.h" 26#include "utils.h"
23 27
24/* 28/* If you add stuff here, update iprule_full_usage */
25static void usage(void) __attribute__((noreturn)); 29static const char keywords[] ALIGN1 =
26 30 "from\0""to\0""preference\0""order\0""priority\0"
27static void usage(void) 31 "tos\0""fwmark\0""realms\0""table\0""lookup\0"
28{ 32 "suppress_prefixlength\0""suppress_ifgroup\0"
29 fprintf(stderr, "Usage: ip rule [ list | add | del ] SELECTOR ACTION\n"); 33 "dev\0""iif\0""nat\0""map-to\0""type\0""help\0"
30 fprintf(stderr, "SELECTOR := [ from PREFIX ] [ to PREFIX ] [ tos TOS ] [ fwmark FWMARK ]\n"); 34 ;
31 fprintf(stderr, " [ dev STRING ] [ pref NUMBER ]\n"); 35#define keyword_preference (keywords + sizeof("from") + sizeof("to"))
32 fprintf(stderr, "ACTION := [ table TABLE_ID ] [ nat ADDRESS ]\n"); 36#define keyword_fwmark (keyword_preference + sizeof("preference") + sizeof("order") + sizeof("priority") + sizeof("tos"))
33 fprintf(stderr, " [ prohibit | reject | unreachable ]\n"); 37#define keyword_realms (keyword_fwmark + sizeof("fwmark"))
34 fprintf(stderr, " [ realms [SRCREALM/]DSTREALM ]\n"); 38#define keyword_suppress_prefixlength (keyword_realms + sizeof("realms") + sizeof("table") + sizeof("lookup"))
35 fprintf(stderr, "TABLE_ID := [ local | main | default | NUMBER ]\n"); 39#define keyword_suppress_ifgroup (keyword_suppress_prefixlength + sizeof("suppress_prefixlength"))
36 exit(-1); 40enum {
37} 41 ARG_from = 1, ARG_to, ARG_preference, ARG_order, ARG_priority,
38*/ 42 ARG_tos, ARG_fwmark, ARG_realms, ARG_table, ARG_lookup,
43 ARG_suppress_prefixlength, ARG_suppress_ifgroup,
44 ARG_dev, ARG_iif, ARG_nat, ARG_map_to, ARG_type, ARG_help,
45};
39 46
40static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM, 47static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM,
41 struct nlmsghdr *n, void *arg UNUSED_PARAM) 48 struct nlmsghdr *n, void *arg UNUSED_PARAM)
@@ -119,6 +126,17 @@ static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM,
119 else if (r->rtm_table) 126 else if (r->rtm_table)
120 printf("lookup %s ", rtnl_rttable_n2a(r->rtm_table)); 127 printf("lookup %s ", rtnl_rttable_n2a(r->rtm_table));
121 128
129 if (tb[FRA_SUPPRESS_PREFIXLEN]) {
130 int pl = *(uint32_t*)RTA_DATA(tb[FRA_SUPPRESS_PREFIXLEN]);
131 if (pl != -1)
132 printf("%s %d ", keyword_suppress_prefixlength, pl);
133 }
134 if (tb[FRA_SUPPRESS_IFGROUP]) {
135 int grp = *(uint32_t*)RTA_DATA(tb[FRA_SUPPRESS_IFGROUP]);
136 if (grp != -1)
137 printf("%s %d ", keyword_suppress_ifgroup, grp);
138 }
139
122 if (tb[RTA_FLOW]) { 140 if (tb[RTA_FLOW]) {
123 uint32_t to = *(uint32_t*)RTA_DATA(tb[RTA_FLOW]); 141 uint32_t to = *(uint32_t*)RTA_DATA(tb[RTA_FLOW]);
124 uint32_t from = to>>16; 142 uint32_t from = to>>16;
@@ -174,15 +192,6 @@ static int iprule_list(char **argv)
174/* Return value becomes exitcode. It's okay to not return at all */ 192/* Return value becomes exitcode. It's okay to not return at all */
175static int iprule_modify(int cmd, char **argv) 193static int iprule_modify(int cmd, char **argv)
176{ 194{
177 static const char keywords[] ALIGN1 =
178 "from\0""to\0""preference\0""order\0""priority\0"
179 "tos\0""fwmark\0""realms\0""table\0""lookup\0""dev\0"
180 "iif\0""nat\0""map-to\0""type\0""help\0";
181 enum {
182 ARG_from = 1, ARG_to, ARG_preference, ARG_order, ARG_priority,
183 ARG_tos, ARG_fwmark, ARG_realms, ARG_table, ARG_lookup, ARG_dev,
184 ARG_iif, ARG_nat, ARG_map_to, ARG_type, ARG_help
185 };
186 bool table_ok = 0; 195 bool table_ok = 0;
187 struct rtnl_handle rth; 196 struct rtnl_handle rth;
188 struct { 197 struct {
@@ -232,7 +241,7 @@ static int iprule_modify(int cmd, char **argv)
232 ) { 241 ) {
233 uint32_t pref; 242 uint32_t pref;
234 NEXT_ARG(); 243 NEXT_ARG();
235 pref = get_u32(*argv, "preference"); 244 pref = get_u32(*argv, keyword_preference);
236 addattr32(&req.n, sizeof(req), RTA_PRIORITY, pref); 245 addattr32(&req.n, sizeof(req), RTA_PRIORITY, pref);
237 } else if (key == ARG_tos) { 246 } else if (key == ARG_tos) {
238 uint32_t tos; 247 uint32_t tos;
@@ -243,13 +252,13 @@ static int iprule_modify(int cmd, char **argv)
243 } else if (key == ARG_fwmark) { 252 } else if (key == ARG_fwmark) {
244 uint32_t fwmark; 253 uint32_t fwmark;
245 NEXT_ARG(); 254 NEXT_ARG();
246 fwmark = get_u32(*argv, "fwmark"); 255 fwmark = get_u32(*argv, keyword_fwmark);
247 addattr32(&req.n, sizeof(req), RTA_PROTOINFO, fwmark); 256 addattr32(&req.n, sizeof(req), RTA_PROTOINFO, fwmark);
248 } else if (key == ARG_realms) { 257 } else if (key == ARG_realms) {
249 uint32_t realm; 258 uint32_t realm;
250 NEXT_ARG(); 259 NEXT_ARG();
251 if (get_rt_realms(&realm, *argv)) 260 if (get_rt_realms(&realm, *argv))
252 invarg_1_to_2(*argv, "realms"); 261 invarg_1_to_2(*argv, keyword_realms);
253 addattr32(&req.n, sizeof(req), RTA_FLOW, realm); 262 addattr32(&req.n, sizeof(req), RTA_FLOW, realm);
254 } else if (key == ARG_table || 263 } else if (key == ARG_table ||
255 key == ARG_lookup 264 key == ARG_lookup
@@ -265,6 +274,16 @@ static int iprule_modify(int cmd, char **argv)
265 addattr32(&req.n, sizeof(req), RTA_TABLE, tid); 274 addattr32(&req.n, sizeof(req), RTA_TABLE, tid);
266 } 275 }
267 table_ok = 1; 276 table_ok = 1;
277 } else if (key == ARG_suppress_prefixlength) {
278 int prefix_length;
279 NEXT_ARG();
280 prefix_length = get_u32(*argv, keyword_suppress_prefixlength);
281 addattr32(&req.n, sizeof(req), FRA_SUPPRESS_PREFIXLEN, prefix_length);
282 } else if (key == ARG_suppress_ifgroup) {
283 int grp;
284 NEXT_ARG();
285 grp = get_u32(*argv, keyword_suppress_ifgroup);
286 addattr32(&req.n, sizeof(req), FRA_SUPPRESS_IFGROUP, grp);
268 } else if (key == ARG_dev || 287 } else if (key == ARG_dev ||
269 key == ARG_iif 288 key == ARG_iif
270 ) { 289 ) {
diff --git a/networking/tls.c b/networking/tls.c
index db518bf90..fd3cb0dba 100644
--- a/networking/tls.c
+++ b/networking/tls.c
@@ -1199,11 +1199,11 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni)
1199 }; 1199 };
1200 struct client_hello *record; 1200 struct client_hello *record;
1201 int len; 1201 int len;
1202 int sni_len = sni ? strnlen(sni, 127) : 0; 1202 int sni_len = sni ? strnlen(sni, 127 - 9) : 0;
1203 1203
1204 len = sizeof(*record); 1204 len = sizeof(*record);
1205 if (sni_len) 1205 if (sni_len)
1206 len += 11 + strlen(sni); 1206 len += 11 + sni_len;
1207 record = tls_get_outbuf(tls, len); 1207 record = tls_get_outbuf(tls, len);
1208 memset(record, 0, len); 1208 memset(record, 0, len);
1209 1209
diff --git a/networking/tls_aes.c b/networking/tls_aes.c
index 6992f1c90..c137442e9 100644
--- a/networking/tls_aes.c
+++ b/networking/tls_aes.c
@@ -40,10 +40,6 @@
40 */ 40 */
41#include "tls.h" 41#include "tls.h"
42 42
43/* TODO: grep for this and move to libbb */
44#define get_unaligned_be32(buf) ({ uint32_t v; move_from_unaligned32(v, buf); SWAP_BE32(v); })
45
46
47// The lookup-tables are marked const so they can be placed in read-only storage instead of RAM 43// The lookup-tables are marked const so they can be placed in read-only storage instead of RAM
48// The numbers below can be computed dynamically trading ROM for RAM - 44// The numbers below can be computed dynamically trading ROM for RAM -
49// This can be useful in (embedded) bootloader applications, where ROM is often limited. 45// This can be useful in (embedded) bootloader applications, where ROM is often limited.
diff --git a/networking/tls_pstm.c b/networking/tls_pstm.c
index bd5bae0b7..e12e6c9d4 100644
--- a/networking/tls_pstm.c
+++ b/networking/tls_pstm.c
@@ -2127,7 +2127,7 @@ int32 pstm_invmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c)
2127{ 2127{
2128 pstm_int x, y, u, v, B, D; 2128 pstm_int x, y, u, v, B, D;
2129 int32 res; 2129 int32 res;
2130 uint16 neg, sanity; 2130 int neg, sanity; //bbox: was uint16
2131 2131
2132 /* 2. [modified] b must be odd */ 2132 /* 2. [modified] b must be odd */
2133 if (pstm_iseven (b) == 1) { 2133 if (pstm_iseven (b) == 1) {
diff --git a/networking/tls_pstm_montgomery_reduce.c b/networking/tls_pstm_montgomery_reduce.c
index dc2fe0a48..3391755e1 100644
--- a/networking/tls_pstm_montgomery_reduce.c
+++ b/networking/tls_pstm_montgomery_reduce.c
@@ -345,7 +345,7 @@ int32 pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m,
345{ 345{
346 pstm_digit *c, *_c, *tmpm, mu; 346 pstm_digit *c, *_c, *tmpm, mu;
347 int32 oldused, x, y; 347 int32 oldused, x, y;
348 int16 pa; 348 int pa; //bbox: was int16
349 349
350 pa = m->used; 350 pa = m->used;
351 if (pa > a->alloc) { 351 if (pa > a->alloc) {
diff --git a/networking/tls_pstm_mul_comba.c b/networking/tls_pstm_mul_comba.c
index 47cbb9618..6ba152bc1 100644
--- a/networking/tls_pstm_mul_comba.c
+++ b/networking/tls_pstm_mul_comba.c
@@ -85,7 +85,8 @@ asm( \
85 "addl %%eax,%0 \n\t" \ 85 "addl %%eax,%0 \n\t" \
86 "adcl %%edx,%1 \n\t" \ 86 "adcl %%edx,%1 \n\t" \
87 "adcl $0,%2 \n\t" \ 87 "adcl $0,%2 \n\t" \
88 :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","%cc"); 88 :"=rm"(c0), "=rm"(c1), "=rm"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","%cc");
89 //bbox: ^^^ replaced "=r" with "=rm": %ebx is not available on shared build
89 90
90/******************************************************************************/ 91/******************************************************************************/
91#elif defined(PSTM_X86_64) 92#elif defined(PSTM_X86_64)
@@ -228,7 +229,7 @@ asm( \
228static int32 pstm_mul_comba_gen(psPool_t *pool, pstm_int *A, pstm_int *B, 229static int32 pstm_mul_comba_gen(psPool_t *pool, pstm_int *A, pstm_int *B,
229 pstm_int *C, pstm_digit *paD, uint32 paDlen) 230 pstm_int *C, pstm_digit *paD, uint32 paDlen)
230{ 231{
231 int16 paDfail, pa; 232 int paDfail, pa; //bbox: was int16
232 int32 ix, iy, iz, tx, ty; 233 int32 ix, iy, iz, tx, ty;
233 pstm_digit c0, c1, c2, *tmpx, *tmpy, *dst; 234 pstm_digit c0, c1, c2, *tmpx, *tmpy, *dst;
234 235
diff --git a/networking/tls_pstm_sqr_comba.c b/networking/tls_pstm_sqr_comba.c
index 36cb9ea97..d5c74d2f0 100644
--- a/networking/tls_pstm_sqr_comba.c
+++ b/networking/tls_pstm_sqr_comba.c
@@ -78,7 +78,8 @@ asm( \
78 "addl %%eax,%0 \n\t" \ 78 "addl %%eax,%0 \n\t" \
79 "adcl %%edx,%1 \n\t" \ 79 "adcl %%edx,%1 \n\t" \
80 "adcl $0,%2 \n\t" \ 80 "adcl $0,%2 \n\t" \
81 :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i) :"%eax","%edx","%cc"); 81 :"=rm"(c0), "=rm"(c1), "=rm"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i) :"%eax","%edx","%cc");
82 //bbox: ^^^ replaced "=r" with "=rm": %ebx is not available on shared build
82 83
83#define SQRADD2(i, j) \ 84#define SQRADD2(i, j) \
84asm( \ 85asm( \
@@ -90,7 +91,8 @@ asm( \
90 "addl %%eax,%0 \n\t" \ 91 "addl %%eax,%0 \n\t" \
91 "adcl %%edx,%1 \n\t" \ 92 "adcl %%edx,%1 \n\t" \
92 "adcl $0,%2 \n\t" \ 93 "adcl $0,%2 \n\t" \
93 :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","%cc"); 94 :"=rm"(c0), "=rm"(c1), "=rm"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","%cc");
95 //bbox: ^^^ replaced "=r" with "=rm": %ebx is not available on shared build
94 96
95#define SQRADDSC(i, j) \ 97#define SQRADDSC(i, j) \
96asm( \ 98asm( \
@@ -445,7 +447,7 @@ asm( \
445static int32 pstm_sqr_comba_gen(psPool_t *pool, pstm_int *A, pstm_int *B, 447static int32 pstm_sqr_comba_gen(psPool_t *pool, pstm_int *A, pstm_int *B,
446 pstm_digit *paD, uint32 paDlen) 448 pstm_digit *paD, uint32 paDlen)
447{ 449{
448 int16 paDfail, pa; 450 int paDfail, pa; //bbox: was int16
449 int32 ix, iz; 451 int32 ix, iz;
450 pstm_digit c0, c1, c2, *dst; 452 pstm_digit c0, c1, c2, *dst;
451#ifdef PSTM_ISO 453#ifdef PSTM_ISO
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c
index 420695a20..d3eea5def 100644
--- a/networking/udhcp/common.c
+++ b/networking/udhcp/common.c
@@ -14,6 +14,7 @@ const uint8_t MAC_BCAST_ADDR[6] ALIGN2 = {
14 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 14 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
15}; 15};
16 16
17#if ENABLE_UDHCPC || ENABLE_UDHCPD
17/* Supported options are easily added here. 18/* Supported options are easily added here.
18 * See RFC2132 for more options. 19 * See RFC2132 for more options.
19 * OPTION_REQ: these options are requested by udhcpc (unless -o). 20 * OPTION_REQ: these options are requested by udhcpc (unless -o).
@@ -136,6 +137,7 @@ const char dhcp_option_strings[] ALIGN1 =
136 "msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */ 137 "msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */
137 "wpad" "\0" /* DHCP_WPAD */ 138 "wpad" "\0" /* DHCP_WPAD */
138 ; 139 ;
140#endif
139 141
140/* Lengths of the option types in binary form. 142/* Lengths of the option types in binary form.
141 * Used by: 143 * Used by:
@@ -190,21 +192,26 @@ static void log_option(const char *pfx, const uint8_t *opt)
190# define log_option(pfx, opt) ((void)0) 192# define log_option(pfx, opt) ((void)0)
191#endif 193#endif
192 194
193unsigned FAST_FUNC udhcp_option_idx(const char *name) 195unsigned FAST_FUNC udhcp_option_idx(const char *name, const char *option_strings)
194{ 196{
195 int n = index_in_strings(dhcp_option_strings, name); 197 int n = index_in_strings(option_strings, name);
196 if (n >= 0) 198 if (n >= 0)
197 return n; 199 return n;
198 200
199 { 201 {
200 char buf[sizeof(dhcp_option_strings)]; 202 char *buf, *d;
201 char *d = buf; 203 const char *s;
202 const char *s = dhcp_option_strings; 204
203 while (s < dhcp_option_strings + sizeof(dhcp_option_strings) - 2) { 205 s = option_strings;
206 while (*s)
207 s += strlen(s) + 1;
208
209 d = buf = xzalloc(s - option_strings);
210 s = option_strings;
211 while (!(*s == '\0' && s[1] == '\0')) {
204 *d++ = (*s == '\0' ? ' ' : *s); 212 *d++ = (*s == '\0' ? ' ' : *s);
205 s++; 213 s++;
206 } 214 }
207 *d = '\0';
208 bb_error_msg_and_die("unknown option '%s', known options: %s", name, buf); 215 bb_error_msg_and_die("unknown option '%s', known options: %s", name, buf);
209 } 216 }
210} 217}
@@ -315,6 +322,7 @@ void FAST_FUNC udhcp_add_binary_option(struct dhcp_packet *packet, uint8_t *addo
315 optionptr[end + len] = DHCP_END; 322 optionptr[end + len] = DHCP_END;
316} 323}
317 324
325#if ENABLE_UDHCPC || ENABLE_UDHCPD
318/* Add an one to four byte option to a packet */ 326/* Add an one to four byte option to a packet */
319void FAST_FUNC udhcp_add_simple_option(struct dhcp_packet *packet, uint8_t code, uint32_t data) 327void FAST_FUNC udhcp_add_simple_option(struct dhcp_packet *packet, uint8_t code, uint32_t data)
320{ 328{
@@ -338,6 +346,7 @@ void FAST_FUNC udhcp_add_simple_option(struct dhcp_packet *packet, uint8_t code,
338 346
339 bb_error_msg("can't add option 0x%02x", code); 347 bb_error_msg("can't add option 0x%02x", code);
340} 348}
349#endif
341 350
342/* Find option 'code' in opt_list */ 351/* Find option 'code' in opt_list */
343struct option_set* FAST_FUNC udhcp_find_option(struct option_set *opt_list, uint8_t code) 352struct option_set* FAST_FUNC udhcp_find_option(struct option_set *opt_list, uint8_t code)
@@ -451,7 +460,7 @@ static NOINLINE void attach_option(
451 free(allocated); 460 free(allocated);
452} 461}
453 462
454int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg) 463int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg, const struct dhcp_optflag *optflags, const char *option_strings)
455{ 464{
456 struct option_set **opt_list = arg; 465 struct option_set **opt_list = arg;
457 char *opt, *val; 466 char *opt, *val;
@@ -478,7 +487,7 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg)
478 bin_optflag.code = optcode; 487 bin_optflag.code = optcode;
479 optflag = &bin_optflag; 488 optflag = &bin_optflag;
480 } else { 489 } else {
481 optflag = &dhcp_optflags[udhcp_option_idx(opt)]; 490 optflag = &optflags[udhcp_option_idx(opt, option_strings)];
482 } 491 }
483 492
484 retval = 0; 493 retval = 0;
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h
index ee12cf91b..a9c23a186 100644
--- a/networking/udhcp/common.h
+++ b/networking/udhcp/common.h
@@ -93,8 +93,10 @@ enum {
93 OPTION_BIN, 93 OPTION_BIN,
94 OPTION_STATIC_ROUTES, 94 OPTION_STATIC_ROUTES,
95 OPTION_6RD, 95 OPTION_6RD,
96#if ENABLE_FEATURE_UDHCP_RFC3397 96#if ENABLE_FEATURE_UDHCP_RFC3397 || ENABLE_FEATURE_UDHCPC6_RFC3646 || ENABLE_FEATURE_UDHCPC6_RFC4704
97 OPTION_DNS_STRING, /* RFC1035 compressed domain name list */ 97 OPTION_DNS_STRING, /* RFC1035 compressed domain name list */
98#endif
99#if ENABLE_FEATURE_UDHCP_RFC3397
98 OPTION_SIP_SERVERS, 100 OPTION_SIP_SERVERS,
99#endif 101#endif
100 102
@@ -189,17 +191,21 @@ struct option_set {
189 struct option_set *next; 191 struct option_set *next;
190}; 192};
191 193
194#if ENABLE_UDHCPC || ENABLE_UDHCPD
192extern const struct dhcp_optflag dhcp_optflags[]; 195extern const struct dhcp_optflag dhcp_optflags[];
193extern const char dhcp_option_strings[] ALIGN1; 196extern const char dhcp_option_strings[] ALIGN1;
197#endif
194extern const uint8_t dhcp_option_lengths[] ALIGN1; 198extern const uint8_t dhcp_option_lengths[] ALIGN1;
195 199
196unsigned FAST_FUNC udhcp_option_idx(const char *name); 200unsigned FAST_FUNC udhcp_option_idx(const char *name, const char *option_strings);
197 201
198uint8_t *udhcp_get_option(struct dhcp_packet *packet, int code) FAST_FUNC; 202uint8_t *udhcp_get_option(struct dhcp_packet *packet, int code) FAST_FUNC;
199int udhcp_end_option(uint8_t *optionptr) FAST_FUNC; 203int udhcp_end_option(uint8_t *optionptr) FAST_FUNC;
200void udhcp_add_binary_option(struct dhcp_packet *packet, uint8_t *addopt) FAST_FUNC; 204void udhcp_add_binary_option(struct dhcp_packet *packet, uint8_t *addopt) FAST_FUNC;
205#if ENABLE_UDHCPC || ENABLE_UDHCPD
201void udhcp_add_simple_option(struct dhcp_packet *packet, uint8_t code, uint32_t data) FAST_FUNC; 206void udhcp_add_simple_option(struct dhcp_packet *packet, uint8_t code, uint32_t data) FAST_FUNC;
202#if ENABLE_FEATURE_UDHCP_RFC3397 207#endif
208#if ENABLE_FEATURE_UDHCP_RFC3397 || ENABLE_FEATURE_UDHCPC6_RFC3646 || ENABLE_FEATURE_UDHCPC6_RFC4704
203char *dname_dec(const uint8_t *cstr, int clen, const char *pre) FAST_FUNC; 209char *dname_dec(const uint8_t *cstr, int clen, const char *pre) FAST_FUNC;
204uint8_t *dname_enc(const uint8_t *cstr, int clen, const char *src, int *retlen) FAST_FUNC; 210uint8_t *dname_enc(const uint8_t *cstr, int clen, const char *src, int *retlen) FAST_FUNC;
205#endif 211#endif
@@ -284,9 +290,14 @@ void udhcp_dump_packet(struct dhcp_packet *packet) FAST_FUNC;
284/* 2nd param is "uint32_t*" */ 290/* 2nd param is "uint32_t*" */
285int FAST_FUNC udhcp_str2nip(const char *str, void *arg); 291int FAST_FUNC udhcp_str2nip(const char *str, void *arg);
286/* 2nd param is "struct option_set**" */ 292/* 2nd param is "struct option_set**" */
287int FAST_FUNC udhcp_str2optset(const char *str, void *arg); 293int FAST_FUNC udhcp_str2optset(const char *str,
294 void *arg,
295 const struct dhcp_optflag *optflags,
296 const char *option_strings);
288 297
298#if ENABLE_UDHCPC || ENABLE_UDHCPD
289void udhcp_init_header(struct dhcp_packet *packet, char type) FAST_FUNC; 299void udhcp_init_header(struct dhcp_packet *packet, char type) FAST_FUNC;
300#endif
290 301
291int udhcp_recv_kernel_packet(struct dhcp_packet *packet, int fd) FAST_FUNC; 302int udhcp_recv_kernel_packet(struct dhcp_packet *packet, int fd) FAST_FUNC;
292 303
diff --git a/networking/udhcp/d6_common.h b/networking/udhcp/d6_common.h
index fcec8c15a..310550371 100644
--- a/networking/udhcp/d6_common.h
+++ b/networking/udhcp/d6_common.h
@@ -87,8 +87,47 @@ struct d6_option {
87#define D6_OPT_IA_PD 25 87#define D6_OPT_IA_PD 25
88#define D6_OPT_IAPREFIX 26 88#define D6_OPT_IAPREFIX 26
89 89
90/* RFC 4704 "The DHCPv6 Client FQDN Option"
91 * uint16 option-code OPTION_CLIENT_FQDN (39)
92 * uint16 option-len 1 + length of domain name
93 * uint8 flags
94 * char[] domain-name partial or fully qualified domain name
95 *
96 * Flags format is |MBZ|N|O|S|
97 * The "S" bit indicates whether the server SHOULD or SHOULD NOT perform
98 * the AAAA RR (FQDN-to-address) DNS updates. A client sets the bit to
99 * 0 to indicate that the server SHOULD NOT perform the updates and 1 to
100 * indicate that the server SHOULD perform the updates. The state of
101 * the bit in the reply from the server indicates the action to be taken
102 * by the server; if it is 1, the server has taken responsibility for
103 * AAAA RR updates for the FQDN.
104 * The "O" bit indicates whether the server has overridden the client's
105 * preference for the "S" bit. A client MUST set this bit to 0. A
106 * server MUST set this bit to 1 if the "S" bit in its reply to the
107 * client does not match the "S" bit received from the client.
108 * The "N" bit indicates whether the server SHOULD NOT perform any DNS
109 * updates. A client sets this bit to 0 to request that the server
110 * SHOULD perform updates (the PTR RR and possibly the AAAA RR based on
111 * the "S" bit) or to 1 to request that the server SHOULD NOT perform
112 * any DNS updates. A server sets the "N" bit to indicate whether the
113 * server SHALL (0) or SHALL NOT (1) perform DNS updates. If the "N"
114 * bit is 1, the "S" bit MUST be 0.
115 *
116 * If a client knows only part of its name, it MAY send a name that is not
117 * fully qualified, indicating that it knows part of the name but does not
118 * necessarily know the zone in which the name is to be embedded.
119 * To send a fully qualified domain name, the Domain Name field is set
120 * to the DNS-encoded domain name including the terminating zero-length
121 * label. To send a partial name, the Domain Name field is set to the
122 * DNS-encoded domain name without the terminating zero-length label.
123 * A client MAY also leave the Domain Name field empty if it desires the
124 * server to provide a name.
125 */
90#define D6_OPT_CLIENT_FQDN 39 126#define D6_OPT_CLIENT_FQDN 39
91 127
128#define D6_OPT_TZ_POSIX 41
129#define D6_OPT_TZ_NAME 42
130
92/*** Other shared functions ***/ 131/*** Other shared functions ***/
93 132
94struct client6_data_t { 133struct client6_data_t {
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c
index 18a104c61..f6d3fb98b 100644
--- a/networking/udhcp/d6_dhcpc.c
+++ b/networking/udhcp/d6_dhcpc.c
@@ -2,26 +2,49 @@
2/* 2/*
3 * DHCPv6 client. 3 * DHCPv6 client.
4 * 4 *
5 * 2011-11. 5 * WARNING: THIS CODE IS INCOMPLETE.
6 * WARNING: THIS CODE IS INCOMPLETE. IT IS NOWHERE NEAR
7 * TO BE READY FOR PRODUCTION USE.
8 * 6 *
9 * Copyright (C) 2011 Denys Vlasenko. 7 * Copyright (C) 2011-2017 Denys Vlasenko.
10 * 8 *
11 * Licensed under GPLv2, see file LICENSE in this source tree. 9 * Licensed under GPLv2, see file LICENSE in this source tree.
12 */ 10 */
13 11
14//config:config UDHCPC6 12//config:config UDHCPC6
15//config: bool "udhcpc6 (DHCPv6 client, NOT READY)" 13//config: bool "udhcpc6 (DHCPv6 client, EXPERIMENTAL)"
16//config: default n # not yet ready 14//config: default n # not yet ready
17//config: depends on FEATURE_IPV6 15//config: depends on FEATURE_IPV6
18//config: help 16//config: help
19//config: udhcpc6 is a DHCPv6 client 17//config: udhcpc6 is a DHCPv6 client
18//config:
19//config:config FEATURE_UDHCPC6_RFC3646
20//config: bool "Support RFC 3646 (DNS server and search list)"
21//config: default y
22//config: depends on UDHCPC6
23//config: help
24//config: List of DNS servers and domain search list can be requested with
25//config: "-O dns" and "-O search". If server gives these values,
26//config: they will be set in environment variables "dns" and "search".
27//config:
28//config:config FEATURE_UDHCPC6_RFC4704
29//config: bool "Support RFC 4704 (Client FQDN)"
30//config: default y
31//config: depends on UDHCPC6
32//config: help
33//config: You can request FQDN to be given by server using "-O fqdn".
34//config:
35//config:config FEATURE_UDHCPC6_RFC4833
36//config: bool "Support RFC 4833 (Timezones)"
37//config: default y
38//config: depends on UDHCPC6
39//config: help
40//config: You can request POSIX timezone with "-O tz" and timezone name
41//config: with "-O timezone".
20 42
21//applet:IF_UDHCPC6(APPLET(udhcpc6, BB_DIR_USR_BIN, BB_SUID_DROP)) 43//applet:IF_UDHCPC6(APPLET(udhcpc6, BB_DIR_USR_BIN, BB_SUID_DROP))
22 44
23//kbuild:lib-$(CONFIG_UDHCPC6) += d6_dhcpc.o d6_packet.o d6_socket.o common.o socket.o signalpipe.o 45//kbuild:lib-$(CONFIG_UDHCPC6) += d6_dhcpc.o d6_packet.o d6_socket.o common.o socket.o signalpipe.o
24 46//kbuild:lib-$(CONFIG_FEATURE_UDHCPC6_RFC3646) += domain_codec.o
47//kbuild:lib-$(CONFIG_FEATURE_UDHCPC6_RFC4704) += domain_codec.o
25 48
26#include <syslog.h> 49#include <syslog.h>
27/* Override ENABLE_FEATURE_PIDFILE - ifupdown needs our pidfile to always exist */ 50/* Override ENABLE_FEATURE_PIDFILE - ifupdown needs our pidfile to always exist */
@@ -37,6 +60,34 @@
37 60
38/* "struct client_config_t client_config" is in bb_common_bufsiz1 */ 61/* "struct client_config_t client_config" is in bb_common_bufsiz1 */
39 62
63static const struct dhcp_optflag d6_optflags[] = {
64#if ENABLE_FEATURE_UDHCPC6_RFC3646
65 { OPTION_6RD | OPTION_LIST | OPTION_REQ, D6_OPT_DNS_SERVERS },
66 { OPTION_DNS_STRING | OPTION_LIST | OPTION_REQ, D6_OPT_DOMAIN_LIST },
67#endif
68#if ENABLE_FEATURE_UDHCPC6_RFC4704
69 { OPTION_DNS_STRING, D6_OPT_CLIENT_FQDN },
70#endif
71#if ENABLE_FEATURE_UDHCPC6_RFC4833
72 { OPTION_STRING, D6_OPT_TZ_POSIX },
73 { OPTION_STRING, D6_OPT_TZ_NAME },
74#endif
75 { 0, 0 }
76};
77/* Must match d6_optflags[] order */
78static const char d6_option_strings[] ALIGN1 =
79#if ENABLE_FEATURE_UDHCPC6_RFC3646
80 "dns" "\0" /* D6_OPT_DNS_SERVERS */
81 "search" "\0" /* D6_OPT_DOMAIN_LIST */
82#endif
83#if ENABLE_FEATURE_UDHCPC6_RFC4704
84 "fqdn" "\0" /* D6_OPT_CLIENT_FQDN */
85#endif
86#if ENABLE_FEATURE_UDHCPC6_RFC4833
87 "tz" "\0" /* D6_OPT_TZ_POSIX */
88 "timezone" "\0" /* D6_OPT_TZ_NAME */
89#endif
90 "\0";
40 91
41#if ENABLE_LONG_OPTS 92#if ENABLE_LONG_OPTS
42static const char udhcpc6_longopts[] ALIGN1 = 93static const char udhcpc6_longopts[] ALIGN1 =
@@ -88,19 +139,17 @@ enum {
88 IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,) 139 IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,)
89}; 140};
90 141
91static const char opt_req[] = { 142#if ENABLE_FEATURE_UDHCPC6_RFC4704
92 (D6_OPT_ORO >> 8), (D6_OPT_ORO & 0xff),
93 0, 6,
94 (D6_OPT_DNS_SERVERS >> 8), (D6_OPT_DNS_SERVERS & 0xff),
95 (D6_OPT_DOMAIN_LIST >> 8), (D6_OPT_DOMAIN_LIST & 0xff),
96 (D6_OPT_CLIENT_FQDN >> 8), (D6_OPT_CLIENT_FQDN & 0xff)
97};
98
99static const char opt_fqdn_req[] = { 143static const char opt_fqdn_req[] = {
100 (D6_OPT_CLIENT_FQDN >> 8), (D6_OPT_CLIENT_FQDN & 0xff), 144 (D6_OPT_CLIENT_FQDN >> 8), (D6_OPT_CLIENT_FQDN & 0xff),
101 0, 2, 145 0, 2, /* optlen */
102 0, 0 146 0, /* flags: */
147 /* S=0: server SHOULD NOT perform AAAA RR updates */
148 /* O=0: client MUST set this bit to 0 */
149 /* N=0: server SHOULD perform updates (PTR RR only in our case, since S=0) */
150 0 /* empty DNS-encoded name */
103}; 151};
152#endif
104 153
105/*** Utility functions ***/ 154/*** Utility functions ***/
106 155
@@ -136,12 +185,6 @@ static void *d6_copy_option(uint8_t *option, uint8_t *option_end, unsigned code)
136 return xmemdup(opt, opt[3] + 4); 185 return xmemdup(opt, opt[3] + 4);
137} 186}
138 187
139static void *d6_store_blob(void *dst, const void *src, unsigned len)
140{
141 memcpy(dst, src, len);
142 return dst + len;
143}
144
145 188
146/*** Script execution code ***/ 189/*** Script execution code ***/
147 190
@@ -154,10 +197,12 @@ static char** new_env(void)
154/* put all the parameters into the environment */ 197/* put all the parameters into the environment */
155static void option_to_env(uint8_t *option, uint8_t *option_end) 198static void option_to_env(uint8_t *option, uint8_t *option_end)
156{ 199{
157 char *dlist, *ptr; 200#if ENABLE_FEATURE_UDHCPC6_RFC3646
201 int addrs, option_offset;
202#endif
158 /* "length minus 4" */ 203 /* "length minus 4" */
159 int len_m4 = option_end - option - 4; 204 int len_m4 = option_end - option - 4;
160 int olen, ooff; 205
161 while (len_m4 >= 0) { 206 while (len_m4 >= 0) {
162 uint32_t v32; 207 uint32_t v32;
163 char ipv6str[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")]; 208 char ipv6str[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
@@ -165,6 +210,10 @@ static void option_to_env(uint8_t *option, uint8_t *option_end)
165 if (option[0] != 0 || option[2] != 0) 210 if (option[0] != 0 || option[2] != 0)
166 break; 211 break;
167 212
213 /* Check if option-length exceeds size of option */
214 if (option[3] > len_m4)
215 break;
216
168 switch (option[1]) { 217 switch (option[1]) {
169 //case D6_OPT_CLIENTID: 218 //case D6_OPT_CLIENTID:
170 //case D6_OPT_SERVERID: 219 //case D6_OPT_SERVERID:
@@ -174,7 +223,7 @@ static void option_to_env(uint8_t *option, uint8_t *option_end)
174 break; 223 break;
175 //case D6_OPT_IA_TA: 224 //case D6_OPT_IA_TA:
176 case D6_OPT_IAADDR: 225 case D6_OPT_IAADDR:
177/* 0 1 2 3 226/* 0 1 2 3
178 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 227 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
179 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 228 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
180 * | OPTION_IAADDR | option-len | 229 * | OPTION_IAADDR | option-len |
@@ -235,51 +284,76 @@ static void option_to_env(uint8_t *option, uint8_t *option_end)
235 sprint_nip6(ipv6str, option + 4 + 4 + 1); 284 sprint_nip6(ipv6str, option + 4 + 4 + 1);
236 *new_env() = xasprintf("ipv6prefix=%s/%u", ipv6str, (unsigned)(option[4 + 4])); 285 *new_env() = xasprintf("ipv6prefix=%s/%u", ipv6str, (unsigned)(option[4 + 4]));
237 break; 286 break;
238 case D6_OPT_DNS_SERVERS: 287#if ENABLE_FEATURE_UDHCPC6_RFC3646
239 olen = ((option[2] << 8) | option[3]) / 16; 288 case D6_OPT_DNS_SERVERS: {
240 dlist = ptr = malloc (4 + olen * 40 - 1); 289 char *dlist;
241
242 memcpy (ptr, "dns=", 4);
243 ptr += 4;
244 ooff = 0;
245
246 while (olen--) {
247 sprint_nip6(ptr, option + 4 + ooff);
248 ptr += 39;
249 ooff += 16;
250 if (olen)
251 *ptr++ = ' ';
252 }
253 290
254 *new_env() = dlist; 291 /* Make sure payload-size is a multiple of 16 */
292 if ((option[3] & 0x0f) != 0)
293 break;
294
295 /* Get the number of addresses on the option */
296 addrs = option[3] >> 4;
297
298 /* Setup environment variable */
299 *new_env() = dlist = xmalloc(4 + addrs * 40 - 1);
300 dlist = stpcpy(dlist, "dns=");
301 option_offset = 0;
302
303 while (addrs--) {
304 sprint_nip6(dlist, option + 4 + option_offset);
305 dlist += 39;
306 option_offset += 16;
307 if (addrs)
308 *dlist++ = ' ';
309 }
255 310
256 break; 311 break;
257 case D6_OPT_DOMAIN_LIST: 312 }
313 case D6_OPT_DOMAIN_LIST: {
314 char *dlist;
315
258 dlist = dname_dec(option + 4, (option[2] << 8) | option[3], "search="); 316 dlist = dname_dec(option + 4, (option[2] << 8) | option[3], "search=");
259 if (!dlist) 317 if (!dlist)
260 break; 318 break;
261 *new_env() = dlist; 319 *new_env() = dlist;
262 break; 320 break;
263 case D6_OPT_CLIENT_FQDN: 321 }
264 // Work around broken ISC DHCPD6 322#endif
323#if ENABLE_FEATURE_UDHCPC6_RFC4704
324 case D6_OPT_CLIENT_FQDN: {
325 char *dlist;
326
327 if (option[3] == 0)
328 break;
329 /* Work around broken ISC DHCPD6.
330 * ISC DHCPD6 does not implement RFC 4704 correctly: It says the first
331 * byte of option-payload should contain flags where the bits 7-3 are
332 * reserved for future use and MUST be zero. Instead ISC DHCPD6 just
333 * writes the entire FQDN as string to option-payload. We assume a
334 * broken server here if any of the reserved bits are set.
335 */
265 if (option[4] & 0xf8) { 336 if (option[4] & 0xf8) {
266 olen = ((option[2] << 8) | option[3]); 337 *new_env() = xasprintf("fqdn=%.*s", (int)option[3], (char*)option + 4);
267 dlist = xmalloc(olen);
268//fixme:
269//- explain
270//- add len error check
271//- merge two allocs into one
272 memcpy(dlist, option + 4, olen);
273 *new_env() = xasprintf("fqdn=%s", dlist);
274 free(dlist);
275 break; 338 break;
276 } 339 }
277 dlist = dname_dec(option + 5, ((option[2] << 8) | option[3]) - 1, "fqdn="); 340 dlist = dname_dec(option + 5, (/*(option[2] << 8) |*/ option[3]) - 1, "fqdn=");
278 if (!dlist) 341 if (!dlist)
279 break; 342 break;
280 *new_env() = dlist; 343 *new_env() = dlist;
281 break; 344 break;
282 } 345 }
346#endif
347#if ENABLE_FEATURE_UDHCPC6_RFC4833
348 /* RFC 4833 Timezones */
349 case D6_OPT_TZ_POSIX:
350 *new_env() = xasprintf("tz=%.*s", (int)option[3], (char*)option + 4);
351 break;
352 case D6_OPT_TZ_NAME:
353 *new_env() = xasprintf("tz_name=%.*s", (int)option[3], (char*)option + 4);
354 break;
355#endif
356 }
283 len_m4 -= 4 + option[3]; 357 len_m4 -= 4 + option[3];
284 option += 4 + option[3]; 358 option += 4 + option[3];
285 } 359 }
@@ -346,22 +420,38 @@ static uint8_t *init_d6_packet(struct d6_packet *packet, char type, uint32_t xid
346 packet->d6_msg_type = type; 420 packet->d6_msg_type = type;
347 421
348 clientid = (void*)client_config.clientid; 422 clientid = (void*)client_config.clientid;
349 return d6_store_blob(packet->d6_options, clientid, clientid->len + 2+2); 423 return mempcpy(packet->d6_options, clientid, clientid->len + 2+2);
350} 424}
351 425
352static uint8_t *add_d6_client_options(uint8_t *ptr) 426static uint8_t *add_d6_client_options(uint8_t *ptr)
353{ 427{
354 return ptr; 428 uint8_t *start = ptr;
355 //uint8_t c; 429 unsigned option;
356 //int i, end, len; 430
431 ptr += 4;
432 for (option = 1; option < 256; option++) {
433 if (client_config.opt_mask[option >> 3] & (1 << (option & 7))) {
434 ptr[0] = (option >> 8);
435 ptr[1] = option;
436 ptr += 2;
437 }
438 }
357 439
358 /* Add a "param req" option with the list of options we'd like to have 440 if ((ptr - start - 4) != 0) {
359 * from stubborn DHCP servers. Pull the data from the struct in common.c. 441 start[0] = (D6_OPT_ORO >> 8);
360 * No bounds checking because it goes towards the head of the packet. */ 442 start[1] = D6_OPT_ORO;
361 //... 443 start[2] = ((ptr - start - 4) >> 8);
444 start[3] = (ptr - start - 4);
445 } else
446 ptr = start;
362 447
448#if ENABLE_FEATURE_UDHCPC6_RFC4704
449 ptr = mempcpy(ptr, &opt_fqdn_req, sizeof(opt_fqdn_req));
450#endif
363 /* Add -x options if any */ 451 /* Add -x options if any */
364 //... 452 //...
453
454 return ptr;
365} 455}
366 456
367static int d6_mcast_from_client_config_ifindex(struct d6_packet *packet, uint8_t *end) 457static int d6_mcast_from_client_config_ifindex(struct d6_packet *packet, uint8_t *end)
@@ -483,11 +573,7 @@ static NOINLINE int send_d6_discover(uint32_t xid, struct in6_addr *requested_ip
483 iaaddr->len = 16+4+4; 573 iaaddr->len = 16+4+4;
484 memcpy(iaaddr->data, requested_ipv6, 16); 574 memcpy(iaaddr->data, requested_ipv6, 16);
485 } 575 }
486 opt_ptr = d6_store_blob(opt_ptr, client6_data.ia_na, len); 576 opt_ptr = mempcpy(opt_ptr, client6_data.ia_na, len);
487
488 /* Request additional options */
489 opt_ptr = d6_store_blob(opt_ptr, &opt_req, sizeof(opt_req));
490 opt_ptr = d6_store_blob(opt_ptr, &opt_fqdn_req, sizeof(opt_fqdn_req));
491 577
492 /* Add options: 578 /* Add options:
493 * "param req" option according to -O, options specified with -x 579 * "param req" option according to -O, options specified with -x
@@ -538,13 +624,9 @@ static NOINLINE int send_d6_select(uint32_t xid)
538 opt_ptr = init_d6_packet(&packet, D6_MSG_REQUEST, xid); 624 opt_ptr = init_d6_packet(&packet, D6_MSG_REQUEST, xid);
539 625
540 /* server id */ 626 /* server id */
541 opt_ptr = d6_store_blob(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2); 627 opt_ptr = mempcpy(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2);
542 /* IA NA (contains requested IP) */ 628 /* IA NA (contains requested IP) */
543 opt_ptr = d6_store_blob(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2); 629 opt_ptr = mempcpy(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2);
544
545 /* Request additional options */
546 opt_ptr = d6_store_blob(opt_ptr, &opt_req, sizeof(opt_req));
547 opt_ptr = d6_store_blob(opt_ptr, &opt_fqdn_req, sizeof(opt_fqdn_req));
548 630
549 /* Add options: 631 /* Add options:
550 * "param req" option according to -O, options specified with -x 632 * "param req" option according to -O, options specified with -x
@@ -611,9 +693,9 @@ static NOINLINE int send_d6_renew(uint32_t xid, struct in6_addr *server_ipv6, st
611 opt_ptr = init_d6_packet(&packet, DHCPREQUEST, xid); 693 opt_ptr = init_d6_packet(&packet, DHCPREQUEST, xid);
612 694
613 /* server id */ 695 /* server id */
614 opt_ptr = d6_store_blob(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2); 696 opt_ptr = mempcpy(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2);
615 /* IA NA (contains requested IP) */ 697 /* IA NA (contains requested IP) */
616 opt_ptr = d6_store_blob(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2); 698 opt_ptr = mempcpy(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2);
617 699
618 /* Add options: 700 /* Add options:
619 * "param req" option according to -O, options specified with -x 701 * "param req" option according to -O, options specified with -x
@@ -640,9 +722,9 @@ static int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cu
640 /* Fill in: msg type, client id */ 722 /* Fill in: msg type, client id */
641 opt_ptr = init_d6_packet(&packet, D6_MSG_RELEASE, random_xid()); 723 opt_ptr = init_d6_packet(&packet, D6_MSG_RELEASE, random_xid());
642 /* server id */ 724 /* server id */
643 opt_ptr = d6_store_blob(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2); 725 opt_ptr = mempcpy(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2);
644 /* IA NA (contains our current IP) */ 726 /* IA NA (contains our current IP) */
645 opt_ptr = d6_store_blob(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2); 727 opt_ptr = mempcpy(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2);
646 728
647 bb_error_msg("sending %s", "release"); 729 bb_error_msg("sending %s", "release");
648 return d6_send_kernel_packet( 730 return d6_send_kernel_packet(
@@ -1051,20 +1133,18 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1051 char *optstr = llist_pop(&list_O); 1133 char *optstr = llist_pop(&list_O);
1052 unsigned n = bb_strtou(optstr, NULL, 0); 1134 unsigned n = bb_strtou(optstr, NULL, 0);
1053 if (errno || n > 254) { 1135 if (errno || n > 254) {
1054 n = udhcp_option_idx(optstr); 1136 n = udhcp_option_idx(optstr, d6_option_strings);
1055 n = dhcp_optflags[n].code; 1137 n = d6_optflags[n].code;
1056 } 1138 }
1057 client_config.opt_mask[n >> 3] |= 1 << (n & 7); 1139 client_config.opt_mask[n >> 3] |= 1 << (n & 7);
1058 } 1140 }
1059 if (!(opt & OPT_o)) { 1141 if (!(opt & OPT_o)) {
1060 /*
1061 unsigned i, n; 1142 unsigned i, n;
1062 for (i = 0; (n = dhcp_optflags[i].code) != 0; i++) { 1143 for (i = 0; (n = d6_optflags[i].code) != 0; i++) {
1063 if (dhcp_optflags[i].flags & OPTION_REQ) { 1144 if (d6_optflags[i].flags & OPTION_REQ) {
1064 client_config.opt_mask[n >> 3] |= 1 << (n & 7); 1145 client_config.opt_mask[n >> 3] |= 1 << (n & 7);
1065 } 1146 }
1066 } 1147 }
1067 */
1068 } 1148 }
1069 while (list_x) { 1149 while (list_x) {
1070 char *optstr = llist_pop(&list_x); 1150 char *optstr = llist_pop(&list_x);
@@ -1073,7 +1153,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1073 *colon = ' '; 1153 *colon = ' ';
1074 /* now it looks similar to udhcpd's config file line: 1154 /* now it looks similar to udhcpd's config file line:
1075 * "optname optval", using the common routine: */ 1155 * "optname optval", using the common routine: */
1076 udhcp_str2optset(optstr, &client_config.options); 1156 udhcp_str2optset(optstr, &client_config.options, d6_optflags, d6_option_strings);
1077 if (colon) 1157 if (colon)
1078 *colon = ':'; /* restore it for NOMMU reexec */ 1158 *colon = ':'; /* restore it for NOMMU reexec */
1079 } 1159 }
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index 6aa6731fb..1a66c610e 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -1346,7 +1346,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1346 char *optstr = llist_pop(&list_O); 1346 char *optstr = llist_pop(&list_O);
1347 unsigned n = bb_strtou(optstr, NULL, 0); 1347 unsigned n = bb_strtou(optstr, NULL, 0);
1348 if (errno || n > 254) { 1348 if (errno || n > 254) {
1349 n = udhcp_option_idx(optstr); 1349 n = udhcp_option_idx(optstr, dhcp_option_strings);
1350 n = dhcp_optflags[n].code; 1350 n = dhcp_optflags[n].code;
1351 } 1351 }
1352 client_config.opt_mask[n >> 3] |= 1 << (n & 7); 1352 client_config.opt_mask[n >> 3] |= 1 << (n & 7);
@@ -1366,7 +1366,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1366 *colon = ' '; 1366 *colon = ' ';
1367 /* now it looks similar to udhcpd's config file line: 1367 /* now it looks similar to udhcpd's config file line:
1368 * "optname optval", using the common routine: */ 1368 * "optname optval", using the common routine: */
1369 udhcp_str2optset(optstr, &client_config.options); 1369 udhcp_str2optset(optstr, &client_config.options, dhcp_optflags, dhcp_option_strings);
1370 if (colon) 1370 if (colon)
1371 *colon = ':'; /* restore it for NOMMU reexec */ 1371 *colon = ':'; /* restore it for NOMMU reexec */
1372 } 1372 }
diff --git a/networking/udhcp/dhcpc.h b/networking/udhcp/dhcpc.h
index 9f423a5b2..7fdbc9a6c 100644
--- a/networking/udhcp/dhcpc.h
+++ b/networking/udhcp/dhcpc.h
@@ -12,6 +12,7 @@ struct client_config_t {
12 IF_FEATURE_UDHCP_PORT(uint16_t port;) 12 IF_FEATURE_UDHCP_PORT(uint16_t port;)
13 int ifindex; /* Index number of the interface to use */ 13 int ifindex; /* Index number of the interface to use */
14 uint8_t opt_mask[256 / 8]; /* Bitmask of options to send (-O option) */ 14 uint8_t opt_mask[256 / 8]; /* Bitmask of options to send (-O option) */
15// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TODO: DHCPv6 has 16-bit option numbers
15 const char *interface; /* The name of the interface to use */ 16 const char *interface; /* The name of the interface to use */
16 char *pidfile; /* Optionally store the process ID */ 17 char *pidfile; /* Optionally store the process ID */
17 const char *script; /* User script to run at dhcp events */ 18 const char *script; /* User script to run at dhcp events */
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
index 5eff026bc..3a5fc2db7 100644
--- a/networking/udhcp/dhcpd.c
+++ b/networking/udhcp/dhcpd.c
@@ -361,6 +361,10 @@ static int FAST_FUNC read_staticlease(const char *const_line, void *arg)
361 return 1; 361 return 1;
362} 362}
363 363
364static int FAST_FUNC read_optset(const char *line, void *arg) {
365 return udhcp_str2optset(line, arg, dhcp_optflags, dhcp_option_strings);
366}
367
364struct config_keyword { 368struct config_keyword {
365 const char *keyword; 369 const char *keyword;
366 int (*handler)(const char *line, void *var) FAST_FUNC; 370 int (*handler)(const char *line, void *var) FAST_FUNC;
@@ -387,8 +391,8 @@ static const struct config_keyword keywords[] = {
387 {"pidfile" , read_str , OFS(pidfile ), "/var/run/udhcpd.pid"}, 391 {"pidfile" , read_str , OFS(pidfile ), "/var/run/udhcpd.pid"},
388 {"siaddr" , udhcp_str2nip , OFS(siaddr_nip ), "0.0.0.0"}, 392 {"siaddr" , udhcp_str2nip , OFS(siaddr_nip ), "0.0.0.0"},
389 /* keywords with no defaults must be last! */ 393 /* keywords with no defaults must be last! */
390 {"option" , udhcp_str2optset, OFS(options ), ""}, 394 {"option" , read_optset , OFS(options ), ""},
391 {"opt" , udhcp_str2optset, OFS(options ), ""}, 395 {"opt" , read_optset , OFS(options ), ""},
392 {"notify_file" , read_str , OFS(notify_file ), NULL}, 396 {"notify_file" , read_str , OFS(notify_file ), NULL},
393 {"sname" , read_str , OFS(sname ), NULL}, 397 {"sname" , read_str , OFS(sname ), NULL},
394 {"boot_file" , read_str , OFS(boot_file ), NULL}, 398 {"boot_file" , read_str , OFS(boot_file ), NULL},
diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c
index 0a31f2643..9e1b46d2f 100644
--- a/networking/udhcp/packet.c
+++ b/networking/udhcp/packet.c
@@ -12,6 +12,7 @@
12#include <netinet/if_ether.h> 12#include <netinet/if_ether.h>
13#include <netpacket/packet.h> 13#include <netpacket/packet.h>
14 14
15#if ENABLE_UDHCPC || ENABLE_UDHCPD
15void FAST_FUNC udhcp_init_header(struct dhcp_packet *packet, char type) 16void FAST_FUNC udhcp_init_header(struct dhcp_packet *packet, char type)
16{ 17{
17 memset(packet, 0, sizeof(*packet)); 18 memset(packet, 0, sizeof(*packet));
@@ -29,6 +30,7 @@ void FAST_FUNC udhcp_init_header(struct dhcp_packet *packet, char type)
29 packet->options[0] = DHCP_END; 30 packet->options[0] = DHCP_END;
30 udhcp_add_simple_option(packet, DHCP_MESSAGE_TYPE, type); 31 udhcp_add_simple_option(packet, DHCP_MESSAGE_TYPE, type);
31} 32}
33#endif
32 34
33#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2 35#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2
34void FAST_FUNC udhcp_dump_packet(struct dhcp_packet *packet) 36void FAST_FUNC udhcp_dump_packet(struct dhcp_packet *packet)