Add -W option for enabling workaround for buggy AP that handle broadcast flag incorrectly 06/226506/2 tizen_5.5_tv
authorNishant Chaprana <n.chaprana@samsung.com>
Tue, 3 Mar 2020 05:19:23 +0000 (10:49 +0530)
committerNishant Chaprana <n.chaprana@samsung.com>
Tue, 3 Mar 2020 07:05:55 +0000 (12:35 +0530)
Some routers/AP handle the DHCP broadcast flag incorrectly.
This means that some AP discard the DHCP packet if broadcast
flag is present and some discard it if broadcast flag is missing.

The workaround is to first send DISCOVER packet in INIT state without
broadcast flag. If there is a timeout we send the second packet with
broadcast flag set. In a case of second timeout the next DISCOVER will
not set broadcast flag etc.

In REBOOTING state the REQUEST packet will not set the broadcast flag.
If we do not get a reply, we switch to INIT state anyway which will
set the broadcast flag.

Change-Id: I0e7903f6569b7a6666516671311e49f82f1a8479
Signed-off-by: Nishant Chaprana <n.chaprana@samsung.com>
toys/pending/dhcp.c

index 9dad00a..61d9e98 100644 (file)
@@ -4,13 +4,13 @@
  * Copyright 2013 Kyungwan Han <asura321@gmail.com>
  *
  * Not in SUSv4.
-USE_DHCP(NEWTOY(dhcp, "V:H:F:x*r:O*A#<0T#<0t#<0s:p:i:SBRCaovqnbf", TOYFLAG_SBIN|TOYFLAG_ROOTONLY))
+USE_DHCP(NEWTOY(dhcp, "V:H:F:x*r:O*A#<0T#<0t#<0s:p:i:SBRCaovqnbfW", TOYFLAG_SBIN|TOYFLAG_ROOTONLY))
 
 config DHCP
   bool "dhcp"
   default n
   help
-   usage: dhcp [-fbnqvoCRB] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]
+   usage: dhcp [-fbnqvoCRBW] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]
                [-H HOSTNAME] [-V VENDOR] [-x OPT:VAL] [-O OPT]
 
         Configure network dynamicaly using DHCP.
@@ -38,6 +38,7 @@ config DHCP
       -V VENDOR Vendor identifier (default 'toybox VERSION')
       -C Don't send MAC as client identifier
       -v Verbose
+      -W Workarround for buggy APs when DHCPDISCOVER/DHCPREQUEST set/unset BOOTP broadcast flag
 
       Signals:
       USR1  Renew current lease
@@ -82,7 +83,8 @@ GLOBALS(
 #define STATE_RENEW_REQUESTED 5
 #define STATE_RELEASED        6
 
-#define BOOTP_BROADCAST   0x8000
+#define BOOTP_BROADCAST_ON    0x8000
+#define BOOTP_BROADCAST_OFF   0x0000
 #define DHCP_MAGIC        0x63825363
 
 #define DHCP_REQUEST          1
@@ -198,6 +200,7 @@ struct fd_pair { int rd; int wr; };
 static uint32_t xid;
 static dhcpc_state_t *state;
 static struct fd_pair sigfd;
+static int broadcast_flag;
 uint8_t bmacaddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  int set = 1;
 uint8_t infomode = LOG_CONSOLE;
@@ -1006,7 +1009,10 @@ static int dhcpc_sendmsg(int msgtype)
   // Handle the message specific settings
   switch (msgtype) {
   case DHCPDISCOVER: // Broadcast DISCOVER message to all servers
-    state->pdhcp.flags = htons(BOOTP_BROADCAST); //  Broadcast bit.
+    if ((flag_chk(FLAG_W) && !broadcast_flag))
+      state->pdhcp.flags = htons(BOOTP_BROADCAST_OFF); //  Broadcast bit unset.
+    else
+      state->pdhcp.flags = htons(BOOTP_BROADCAST_ON); //  Broadcast bit set.
     if (flag_chk(FLAG_r)) {
       inet_aton(TT.req_ip, &rqsd);
       pend = dhcpc_addreqipaddr(&rqsd, pend);
@@ -1020,7 +1026,10 @@ static int dhcpc_sendmsg(int msgtype)
     if (flag_chk(FLAG_x)) pend = set_xopt(pend);
     break;
   case DHCPREQUEST: // Send REQUEST message to the server that sent the *first* OFFER
-    state->pdhcp.flags = htons(BOOTP_BROADCAST); //  Broadcast bit.
+    if ((flag_chk(FLAG_W) && !broadcast_flag) && server != INADDR_BROADCAST)
+      state->pdhcp.flags = htons(BOOTP_BROADCAST_OFF); //  Broadcast bit unset.
+    else
+      state->pdhcp.flags = htons(BOOTP_BROADCAST_ON); //  Broadcast bit set.
     if (state->status == STATE_RENEWING) memcpy(&state->pdhcp.ciaddr, &state->ipaddr.s_addr, 4);
     pend = dhcpc_addmaxsize(pend, htons(sizeof(dhcp_raw_t)));
     rqsd.s_addr = htonl(server);
@@ -1339,6 +1348,7 @@ void dhcp_main(void)
           if (!packets) xid = getxid();
           run_script(NULL, "deconfig");
           infomsg(infomode, "Sending discover...");
+          broadcast_flag = (broadcast_flag + 1) % 2;
           dhcpc_sendmsg(DHCPDISCOVER);
           server = 0;
           timeout = flag_get(FLAG_T, TT.timeout, 3);