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