---
 networking/udhcp/d6_dhcpc.c | 79 ++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 71 insertions(+), 8 deletions(-)

diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c
index 3c61292..d0f8593 100644
--- a/networking/udhcp/d6_dhcpc.c
+++ b/networking/udhcp/d6_dhcpc.c
@@ -125,6 +125,7 @@ static const char udhcpc6_longopts[] ALIGN1 =
        "request-option\0" Required_argument "O"
        "no-default-options\0" No_argument   "o"
        "foreground\0"     No_argument       "f"
+       "stateless\0"      No_argument       "l"
        USE_FOR_MMU(
        "background\0"     No_argument       "b"
        )
@@ -149,9 +150,10 @@ enum {
        OPT_o = 1 << 12,
        OPT_x = 1 << 13,
        OPT_f = 1 << 14,
-       OPT_d = 1 << 15,
+       OPT_l = 1 << 15,
+       OPT_d = 1 << 16,
 /* The rest has variable bit positions, need to be clever */
-       OPTBIT_d = 15,
+       OPTBIT_d = 16,
        USE_FOR_MMU(             OPTBIT_b,)
        ///IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,)
        IF_FEATURE_UDHCP_PORT(   OPTBIT_P,)
@@ -841,6 +843,45 @@ int send_d6_release(struct in6_addr *server_ipv6, struct 
in6_addr *our_cur_ipv6)
        );
 }
 
+/* RFC 3315 18.1.5. Creation and Transmission of Information-request Messages
+
+   The client uses an Information-request message to obtain
+   configuration information without having addresses assigned to it.
+
+   The client sets the "msg-type" field to INFORMATION-REQUEST.  The
+   client generates a transaction ID and inserts this value in the
+   "transaction-id" field.
+
+   The client SHOULD include a Client Identifier option to identify
+   itself to the server.  If the client does not include a Client
+   Identifier option, the server will not be able to return any client-
+   specific options to the client, or the server may choose not to
+   respond to the message at all.  The client MUST include a Client
+   Identifier option if the Information-Request message will be
+   authenticated.
+
+   The client MUST include an Option Request option (see section 22.7)
+   to indicate the options the client is interested in receiving.  The
+   client MAY include options with data values as hints to the server
+   about parameter values the client would like to have returned.
+*/
+
+/* NOINLINE: limit stack usage in caller */
+static NOINLINE int send_d6_info(uint32_t xid)
+{
+       struct d6_packet packet;
+       uint8_t *opt_ptr;
+       unsigned len;
+
+       /* Fill in: msg type, client id */
+       opt_ptr = init_d6_packet(&packet, D6_MSG_INFORMATION_REQUEST, xid);
+
+       opt_ptr = add_d6_client_options(opt_ptr);
+
+       bb_error_msg("sending %s", "info");
+       return d6_mcast_from_client_config_ifindex(&packet, opt_ptr);
+}
+
 /* Returns -1 on errors that are fatal for the socket, -2 for those that 
aren't */
 /* NOINLINE: limit stack usage in caller */
 static NOINLINE int d6_recv_raw_packet(struct in6_addr *peer_ipv6, struct 
d6_packet *d6_pkt, int fd)
@@ -1117,6 +1158,7 @@ static void client_background(void)
 //usage:     "\n       -T N            Pause between packets (default 3 
seconds)"
 //usage:     "\n       -A N            Wait N seconds (default 20) after 
failure"
 //usage:     "\n       -f              Run in foreground"
+//usage:     "\n       -l              Use stateless mode, only send 
informational request and dont request ip"
 //usage:       USE_FOR_MMU(
 //usage:     "\n       -b              Background if lease is not obtained"
 //usage:       )
@@ -1159,6 +1201,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
        int tryagain_timeout = 20;
        int discover_timeout = 3;
        int discover_retries = 3;
+       int stateless_timeout = 86400;
        struct in6_addr srv6_buf;
        struct in6_addr ipv6_buf;
        struct in6_addr *requested_ipv6;
@@ -1182,7 +1225,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
        /* Parse command line */
        opt = getopt32long(argv, "^"
                /* O,x: list; -T,-t,-A take numeric param */
-               "i:np:qRr:s:T:+t:+SA:+O:*ox:*fd"
+               "i:np:qRr:s:T:+t:+SA:+O:*ox:*fld"
                USE_FOR_MMU("b")
                ///IF_FEATURE_UDHCPC_ARPING("a")
                IF_FEATURE_UDHCP_PORT("P:")
@@ -1208,6 +1251,11 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
                        requested_ipv6 = &ipv6_buf;
                }
        }
+
+       if (opt & OPT_l) {
+               /* no ip request when stateless */
+               option_mask32 = option_mask32 & ~OPT_r;
+       }
 #if ENABLE_FEATURE_UDHCP_PORT
        if (opt & OPT_P) {
                CLIENT_PORT6 = xatou16(str_P);
@@ -1358,7 +1406,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
                                        if (packet_num == 0)
                                                xid = random_xid();
                                        /* multicast */
-                                       send_d6_discover(xid, requested_ipv6);
+                                       if(opt & OPT_l)
+                                               send_d6_info(xid);
+                                       else
+                                               send_d6_discover(xid, 
requested_ipv6);
                                        timeout = discover_timeout;
                                        packet_num++;
                                        continue;
@@ -1401,7 +1452,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
                                /* 1/2 lease passed, enter renewing state */
                                state = RENEWING;
                                client_config.first_secs = 0; /* make secs 
field count from 0 */
-                               change_listen_mode(LISTEN_KERNEL);
+                               if(opt & OPT_l)
+                                       change_listen_mode(LISTEN_RAW);
+                               else
+                                       change_listen_mode(LISTEN_KERNEL);
                                log1("entering renew state");
                                /* fall right through */
                        case RENEW_REQUESTED: /* manual (SIGUSR1) renew */
@@ -1417,7 +1471,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
                         * Anyway, it does recover by eventually failing through
                         * into INIT_SELECTING state.
                         */
-                                       send_d6_renew(xid, &srv6_buf, 
requested_ipv6);
+                                       if(opt & OPT_l)
+                                               send_d6_info(xid);
+                                       else
+                                               send_d6_renew(xid, &srv6_buf, 
requested_ipv6);
                                        timeout >>= 1;
                                        continue;
                                }
@@ -1431,8 +1488,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
                                /* Lease is *really* about to run out,
                                 * try to find DHCP server using broadcast */
                                if (timeout > 0) {
-                                       /* send a broadcast renew request */
-                                       send_d6_renew(xid, /*server_ipv6:*/ 
NULL, requested_ipv6);
+                                       if(opt & OPT_l)
+                                               send_d6_info(xid);
+                                       else /* send a broadcast renew request 
*/
+                                               send_d6_renew(xid, 
/*server_ipv6:*/ NULL, requested_ipv6);
                                        timeout >>= 1;
                                        continue;
                                }
@@ -1739,6 +1798,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
                                        prefix_timeout = address_timeout;
                                /* note: "int timeout" will not overflow even 
with 0xffffffff inputs here: */
                                timeout = (prefix_timeout < address_timeout ? 
prefix_timeout : address_timeout) / 2;
+
+                               if(opt & OPT_l) /* no lease timeout will be 
received, use stateless timeout */
+                                       timeout = stateless_timeout;
+
                                /* paranoia: must not be too small */
                                /* timeout > 60 - ensures at least one unicast 
renew attempt */
                                if (timeout < 61)
-- 
2.7.4

_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to