[package] update busybox to 1.18.4, patch from Peter Wagner
[openwrt.git] / package / busybox / patches / 244-udhcpc_add_6rd_option.patch
1 diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c
2 index 0a60261..eaf2b4b 100644
3 --- a/networking/udhcp/common.c
4 +++ b/networking/udhcp/common.c
5 @@ -56,6 +56,8 @@ const struct dhcp_optflag dhcp_optflags[] = {
6  #endif
7         { OPTION_STATIC_ROUTES                    , 0x79 }, /* DHCP_STATIC_ROUTES */
8         { OPTION_STATIC_ROUTES                    , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */
9 +       { OPTION_6RD                              , 0xd4 }, /* DHCP_6RD (RFC)     */
10 +       { OPTION_6RD                              , 0x96 }, /* DHCP_6RD (Comcast) */
11         { OPTION_STRING                           , 0xfc }, /* DHCP_WPAD          */
12  
13         /* Options below have no match in dhcp_option_strings[],
14 @@ -118,6 +120,8 @@ const char dhcp_option_strings[] ALIGN1 =
15  // doesn't work in udhcpd.conf since OPTION_STATIC_ROUTES
16  // is not handled yet by "string->option" conversion code:
17         "staticroutes" "\0"/* DHCP_STATIC_ROUTES  */
18 +       "ip6rd" "\0"       /* DHCP_6RD (RFC)      */
19 +       "ip6rd" "\0"       /* DHCP_6RD (Comcast)  */
20         "msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */
21         "wpad" "\0"        /* DHCP_WPAD           */
22         ;
23 @@ -146,6 +150,7 @@ const uint8_t dhcp_option_lengths[] ALIGN1 = {
24         [OPTION_S32] =     4,
25         /* Just like OPTION_STRING, we use minimum length here */
26         [OPTION_STATIC_ROUTES] = 5,
27 +       [OPTION_6RD]           = 22,
28  };
29  
30  
31 diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h
32 index f8f18ff..56cd8b0 100644
33 --- a/networking/udhcp/common.h
34 +++ b/networking/udhcp/common.h
35 @@ -88,6 +88,7 @@ enum {
36         OPTION_S32,
37         OPTION_BIN,
38         OPTION_STATIC_ROUTES,
39 +       OPTION_6RD,
40  #if ENABLE_FEATURE_UDHCP_RFC3397
41         OPTION_DNS_STRING,  /* RFC1035 compressed domain name list */
42         OPTION_SIP_SERVERS,
43 diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
44 index 78aabed..993326f 100644
45 --- a/networking/udhcp/dhcpc.c
46 +++ b/networking/udhcp/dhcpc.c
47 @@ -45,6 +45,7 @@ static const uint8_t len_of_option_as_string[] = {
48         [OPTION_IP              ] = sizeof("255.255.255.255 "),
49         [OPTION_IP_PAIR         ] = sizeof("255.255.255.255 ") * 2,
50         [OPTION_STATIC_ROUTES   ] = sizeof("255.255.255.255/32 255.255.255.255 "),
51 +       [OPTION_6RD             ] = sizeof("32 128 FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF 255.255.255.255 "),
52         [OPTION_STRING          ] = 1,
53  #if ENABLE_FEATURE_UDHCP_RFC3397
54         [OPTION_DNS_STRING      ] = 1, /* unused */
55 @@ -68,6 +69,23 @@ static int sprint_nip(char *dest, const char *pre, const uint8_t *ip)
56         return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]);
57  }
58  
59 +static int sprint_nip6(char *dest, const char *pre, const uint8_t *ip)
60 +{
61 +       int len = 0;
62 +       int off;
63 +       uint16_t word;
64 +
65 +       len += sprintf(dest, "%s", pre);
66 +
67 +       for (off = 0; off < 16; off += 2)
68 +       {
69 +               move_from_unaligned16(word, &ip[off]);
70 +               len += sprintf(dest+len, "%s%04X", off ? ":" : "", htons(word));
71 +       }
72 +
73 +       return len;
74 +}
75 +
76  /* really simple implementation, just count the bits */
77  static int mton(uint32_t mask)
78  {
79 @@ -177,6 +195,70 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_
80  
81                         return ret;
82                 }
83 +               case OPTION_6RD: {
84 +                       /* Option binary format:
85 +                        *  0                   1                   2                   3
86 +                        *  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
87 +                        *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
88 +                        *  |  OPTION_6RD   | option-length |  IPv4MaskLen  |  6rdPrefixLen |
89 +                        *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
90 +                        *  |                                                               |
91 +                        *  |                           6rdPrefix                           |
92 +                        *  |                          (16 octets)                          |
93 +                        *  |                                                               |
94 +                        *  |                                                               |
95 +                        *  |                                                               |
96 +                        *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
97 +                        *  |                     6rdBRIPv4Address(es)                      |
98 +                        *  .                                                               .
99 +                        *  .                                                               .
100 +                        *  .                                                               .
101 +                        *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
102 +                        *
103 +                        * We convert it to a string "IPv4MaskLen 6rdPrefixLen 6rdPrefix 6rdBRIPv4Address"
104 +                        */
105 +
106 +                       /* Sanity check: ensure that our length is at least 22 bytes, that
107 +                        * IPv4MaskLen is <= 32, 6rdPrefixLen <= 128 and that the sum of
108 +                        * (32 - IPv4MaskLen) + 6rdPrefixLen is less than or equal to 128.
109 +                        * If any of these requirements is not fulfilled, return with empty
110 +                        * value.
111 +                        */
112 +                       if ((len >= 22) && (*option <= 32) && (*(option+1) <= 128) &&
113 +                           (((32 - *option) + *(option+1)) <= 128))
114 +                       {
115 +                               /* IPv4MaskLen */
116 +                               dest += sprintf(dest, "%u ", *option++);
117 +                               len--;
118 +
119 +                               /* 6rdPrefixLen */
120 +                               dest += sprintf(dest, "%u ", *option++);
121 +                               len--;
122 +
123 +                               /* 6rdPrefix */
124 +                               dest += sprint_nip6(dest, "", option);
125 +                               option += 16;
126 +                               len -= 16;
127 +
128 +                               /* 6rdBRIPv4Addresses */
129 +                               while (len >= 4)
130 +                               {
131 +                                       dest += sprint_nip(dest, " ", option);
132 +                                       option += 4;
133 +                                       len -= 4;
134 +
135 +                                       /* the code to determine the option size fails to work with
136 +                                        * lengths that are not a multiple of the minimum length,
137 +                                        * adding all advertised 6rdBRIPv4Addresses here would
138 +                                        * overflow the destination buffer, therefore skip the rest
139 +                                        * for now
140 +                                        */
141 +                                       break;
142 +                               }
143 +                       }
144 +
145 +                       return ret;
146 +               }
147  #if ENABLE_FEATURE_UDHCP_RFC3397
148                 case OPTION_DNS_STRING:
149                         /* unpack option into dest; use ret for prefix (i.e., "optname=") */