Add Broadcom / Netgear changes from RAXE 1.0.0.48
[project/bcm63xx/u-boot.git] / net / nmrp.c
diff --git a/net/nmrp.c b/net/nmrp.c
new file mode 100755 (executable)
index 0000000..3e603fd
--- /dev/null
@@ -0,0 +1,592 @@
+/*
+ *     Copyright (C) 2008 Delta Networks Inc.
+ */
+#include <common.h>
+#include <command.h>
+#include <net.h>
+//#include "tftp.h"
+#include "bootp.h"
+#include "nmrp.h"
+#include <dni_common.h>
+
+typedef void nmrp_thand_f(void);
+ulong NmrpOuripaddr;
+ulong NmrpOuripSubnetMask;
+ulong NmrpFwOption;
+int NmrpFwUPOption = 0;
+int NmrpSTUPOption = 0;
+int NmrpStringTableUpdateCount = 0;
+int NmrpStringTableUpdateIndex = 0;
+int NmrpState = 0;
+ulong Nmrp_active_start=0;
+static ulong NmrpBlock;
+static ulong NmrpLastBlock = 0;
+int Nmrp_Listen_TimeoutCount = 0;
+int Nmrp_REQ_TimeoutCount = 0;
+static ulong NmrptimeStart;
+static ulong NmrptimeDelta;
+static nmrp_thand_f *NmrptimeHandler;
+static uchar Nmrpproto;
+static int Nmrp_Closing_TimeoutCount = 0;
+struct in_addr NmrpClientIP;
+uchar NmrpClientEther[6] = { 0, 0, 0, 0, 0, 0 };
+uchar NmrpServerEther[6] = { 0, 0, 0, 0, 0, 0 };
+static u16 NmrpDevRegionOption = 0;
+static uchar NmrpFirmwareFilename[FIRMWARE_FILENAME_LEN] = FIRMWARE_FILENAME;
+static u32 NmrpStringTableBitmask = 0;
+static uchar NmrpStringTableFilename[STRING_TABLE_FILENAME_LEN] = {0};
+static int NmrpStringTableUpdateList[STRING_TABLE_NUMBER_MAX] = {0};
+ulong NmrpAliveTimerStart = 0;
+ulong NmrpAliveTimerBase = 0;
+int NmrpAliveTimerTimeout = NMRP_TIMEOUT_ACTIVE;
+int NmrpAliveWaitACK = 0;
+
+static void Nmrp_Listen_Timeout(void);
+void NmrpSend(void);
+
+void NmrpStart(void);
+
+void NmrpSetTimeout(unchar, ulong, nmrp_thand_f *);
+
+void Nmrp_Led_Flashing_Timeout();
+
+extern void board_reset_default();
+
+static int MyNetSetEther(volatile uchar * xet, uchar * addr, uint prot)
+{
+       struct ethernet_hdr *et = (struct ethernet_hdr *) xet;
+       ushort myvlanid;
+       myvlanid = ntohs(net_our_vlan);
+       if (myvlanid == (ushort) - 1)
+               myvlanid = VLAN_NONE;
+       memcpy(et->et_dest, addr, 6);
+    eth_env_get_enetaddr("ethaddr", net_server_ethaddr);
+       memcpy(et->et_src, net_server_ethaddr, 6);
+       if ((myvlanid & VLAN_IDMASK) == VLAN_NONE) {
+               et->et_protlen = htons(prot);
+               return ETHER_HDR_SIZE;
+       } else {
+               struct vlan_ethernet_hdr *vet =
+                               (struct vlan_ethernet_hdr *) xet;
+               vet->vet_vlan_type = htons(PROT_VLAN);
+               vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK));
+               vet->vet_type = htons(prot);
+               return VLAN_ETHER_HDR_SIZE;
+       }
+
+       return ETHER_HDR_SIZE;
+}
+
+static void Nmrp_Conf_Timeout(void)
+{
+       if (++Nmrp_REQ_TimeoutCount > NMRP_MAX_RETRY_CONF) {
+               puts("\n retry conf count exceeded;\n");
+               Nmrp_REQ_TimeoutCount = 0;
+               NmrpStart();
+       } else {
+               puts("T");
+               NmrpSetTimeout(NMRP_CODE_CONF_ACK,
+                              (NMRP_TIMEOUT_REQ * CONFIG_SYS_HZ) / 2,
+                              Nmrp_Conf_Timeout);
+               NmrpSend();
+       }
+}
+
+void Nmrp_Closing_Timeout()
+{
+
+       if (++Nmrp_Closing_TimeoutCount > NMRP_MAX_RETRY_CLOSE) {
+               puts("\n close retry count exceed;stay idle and blink\n");
+               Nmrp_Closing_TimeoutCount = 0;
+               //board_reset_default(); toso Silver
+
+               puts("\nNMRP is complete. Please switch OFF power.\n");
+
+               Nmrp_Led_Flashing_Timeout();
+               /* Unreachable */
+
+               ctrlc();
+               console_assign(stdout, "nulldev");
+               console_assign(stderr, "nulldev");
+               NmrpState = STATE_CLOSED;
+               net_set_state(NETLOOP_SUCCESS);
+       } else {
+               puts("T");
+               NmrpSetTimeout(NMRP_CODE_CLOSE_ACK,
+                              (CONFIG_SYS_HZ * NMRP_TIMEOUT_REQ) / 2,
+                              Nmrp_Closing_Timeout);
+               NmrpSend();
+       }
+}
+
+#define LED_REG_IN_OUT         0xff800500
+#define LED_TEST_MASK          0x08000000
+#define LED_AL_AH_REG          0xff800528
+
+void board_test_led(int status)
+{
+       volatile uint32_t *cled_al_ah_reg = (void *)(LED_AL_AH_REG);
+       volatile uint32_t *cled_in_out_reg = (void *)(LED_REG_IN_OUT);
+       uint32_t val32;
+
+       val32 = *cled_in_out_reg;
+       val32 |= LED_TEST_MASK;
+       *cled_in_out_reg = val32;
+
+       val32 = *cled_al_ah_reg;
+    if( status == 0 )
+           val32 &= ~LED_TEST_MASK;
+    else
+           val32 |= LED_TEST_MASK;
+       *cled_al_ah_reg = val32;
+}
+
+void Nmrp_Led_Flashing_Timeout()
+{
+       static int NmrpLedCount = 0;
+       while (1) {
+               NmrpLedCount++;
+               if ((NmrpLedCount % 2) == 1) {
+                       board_test_led(0);
+                       udelay(500000);
+               } else {
+                       board_test_led(1);
+                       udelay(500000);
+               }
+       }
+       /* Unreachable */
+
+       /*press ctl+c, turn on test led,then normally boot*/
+       board_test_led(0);
+}
+
+extern void NmrpSend(void)
+{
+       volatile u8 *pkt;
+       volatile u8 *xp;
+       int len = 0;
+       int eth_len = 0;
+       pkt = (u8 *) net_tx_packet;
+       pkt += MyNetSetEther(pkt, NmrpServerEther, PROT_NMRP);
+       eth_len = pkt - net_tx_packet;
+
+       switch (NmrpState) {
+       case STATE_LISTENING:
+               xp = pkt;
+               *((u16 *) pkt) = 0;
+               pkt += 2;
+               *((u8 *) pkt) = (NMRP_CODE_CONF_REQ);
+               pkt++;
+               *((u8 *) pkt) = 0;
+               pkt++;
+               *((u16 *) pkt) = htons(6);
+               pkt += 2;
+
+               len = pkt - xp;
+
+               (void)net_send_packet((u8 *) net_tx_packet, eth_len + len);
+               net_set_timeout_handler((NMRP_TIMEOUT_REQ * CONFIG_SYS_HZ) / 2,
+                             Nmrp_Conf_Timeout);
+               NmrpSetTimeout(NMRP_CODE_CONF_ACK,
+                              (NMRP_TIMEOUT_REQ * CONFIG_SYS_HZ) / 2,
+                              Nmrp_Conf_Timeout);
+               break;
+       case STATE_CONFIGING:
+               xp = pkt;
+               *((u16 *) pkt) = 0;
+               pkt += 2;
+               *((u8 *) pkt) = (NMRP_CODE_TFTP_UL_REQ);
+               pkt++;
+               *((u8 *) pkt) = 0;
+               pkt++;
+               /* Recv ST-UP option, upgrade string table.
+                * add FILE-NAME option to TFTP-UL-REQ
+                * value of FILE-NAME would like "string table 01"*/
+               if (NmrpSTUPOption == 1) {
+                       /* Append the total length to packet
+                        * NMRP_HEADER_LEN for the length of "Reserved", "Code", "Identifier", "Length"
+                        * STRING_TABLE_FILENAME_OPT_LEN for the length of "Options". */
+                       *((u16 *) pkt) = htons((NMRP_HEADER_LEN + STRING_TABLE_FILENAME_OPT_LEN));
+                       pkt += 2;
+
+                       /* Append NMRP option type FILE-NAME */
+                       *((u16 *) pkt) = htons(NMRP_OPT_FILE_NAME);
+                       pkt += 2;
+
+                       /* Append the total length of NMRP option FILE-NAME */
+                       *((u16 *) pkt) = htons(STRING_TABLE_FILENAME_OPT_LEN);
+                       pkt += 2;
+
+                       /* Append the string table filename to FILE-NAME option value */
+                       int i;
+                       sprintf(NmrpStringTableFilename, "%s%02d", STRING_TABLE_FILENAME_PREFIX,\
+                               NmrpStringTableUpdateList[NmrpStringTableUpdateIndex]);
+                       for (i = 0; i < STRING_TABLE_FILENAME_LEN; i++) {
+                               *((u8 *) pkt) = NmrpStringTableFilename[i];
+                               pkt++;
+                       }
+                       printf("\nReq %s\n", NmrpStringTableFilename);
+               /* No string table updates, or all string table updates finished.
+                * And received FW-UP option, upgrading firmware,
+                * add FILE-NAME option to TFTP-UL-REQ */
+               } else {
+                       /* Append the total length to packet
+                        * NMRP_HEADER_LEN for the length of "Reserved", "Code", "Identifier", "Length"
+                        * STRING_TABLE_FILENAME_OPT_LEN for the length of "Options". */
+                       *((u16 *) pkt) = htons((NMRP_HEADER_LEN + FIRMWARE_FILENAME_OPT_LEN));
+                       pkt += 2;
+
+                       /* Append NMRP option type FILE-NAME */
+                       *((u16 *) pkt) = htons(NMRP_OPT_FILE_NAME);
+                       pkt += 2;
+
+                       /* Append the total length of NMRP option FILE-NAME for firmware*/
+                       *((u16 *) pkt) = htons(FIRMWARE_FILENAME_OPT_LEN);
+                       pkt += 2;
+
+                       /* Append the firmware filename to FILE-NAME option value */
+                       sprintf(NmrpFirmwareFilename, "%s\n", FIRMWARE_FILENAME);
+                       int i;
+                       for (i = 0; i < FIRMWARE_FILENAME_LEN; i++) {
+                               *((u8 *) pkt) = NmrpFirmwareFilename[i];
+                               pkt++;
+                       }
+               }
+               len = pkt - xp;
+               (void)net_send_packet((u8 *) net_tx_packet, eth_len + len);
+               int update_table_num = NmrpStringTableUpdateList[NmrpStringTableUpdateIndex];
+               if (NmrpSTUPOption == 1)
+                       UpgradeStringTableFromNmrpServer(update_table_num);
+               else
+                       UpgradeFirmwareFromNmrpServer();
+               break;
+       case STATE_TFTPUPLOADING:
+               printf("TFTP upload done\n");
+               NmrpAliveTimerStart = get_timer(0);
+               NmrpAliveTimerBase = NMRP_TIMEOUT_ACTIVE / 4;
+               NmrpState = STATE_KEEP_ALIVE;
+               break;
+       case STATE_KEEP_ALIVE:
+               printf("NMRP Send Keep alive REQ\n");
+               //workaround_ipq40xx_gmac_nmrp_hang_action();
+               xp = pkt;
+               *((u16 *) pkt) = 0;
+               pkt += 2;
+               *((u8 *) pkt) = (NMRP_CODE_KEEP_ALIVE_REQ);
+               pkt++;
+               *((u8 *) pkt) = 0;
+               pkt++;
+               *((u16 *) pkt) = htons(6);
+               pkt += 2;
+               len = pkt - xp;
+               (void)net_send_packet((u8 *) net_tx_packet, eth_len + len);
+               NmrpAliveWaitACK = 1;
+               break;
+       case STATE_CLOSING:
+               printf("NMRP Send Closing REQ\n");
+               //workaround_qca8337_gmac_nmrp_hang_action();
+               //workaround_ipq40xx_gmac_nmrp_hang_action();
+               eth_halt();
+        mdelay(1000);
+               eth_init();
+        mdelay(500);
+               xp = pkt;
+               *((u16 *) pkt) = 0;
+               pkt += 2;
+               *((u8 *) pkt) = (NMRP_CODE_CLOSE_REQ);
+               pkt++;
+               *((u8 *) pkt) = 0;
+               pkt++;
+               *((u16 *) pkt) = htons(6);
+               pkt += 2;
+               len = pkt - xp;
+               NmrpSetTimeout(NMRP_CODE_CLOSE_ACK, (1 * CONFIG_SYS_HZ),
+                              Nmrp_Closing_Timeout);
+               (void)net_send_packet((u8 *) net_tx_packet, eth_len + len);
+               break;
+
+       case STATE_CLOSED:
+               run_command("sdk restoredefault", 0); //board_reset_default();
+#if defined(CONFIG_HW29765352P32P4000P512P2X2P2X2P4X4) || \
+       defined(CONFIG_HW29765352P0P4096P512P2X2P2X2P4X4) || \
+       defined(CONFIG_HW29765515P0P4096P512P2X2P2X2P2X2)
+               char runcmd[256];
+               printf ("boot_partition_set 1\n");
+               snprintf(runcmd, sizeof(runcmd), "boot_partition_set 1");
+               run_command(runcmd, 0);
+#endif
+               NmrptimeHandler=NULL;
+               puts("\nNMRP is complete. Please switch OFF power.\n");
+
+               Nmrp_Led_Flashing_Timeout();
+               /* Unreachable */
+
+               ctrlc();
+               console_assign(stdout, "nulldev");
+               console_assign(stderr, "nulldev");
+               net_set_state(NETLOOP_SUCCESS);
+               break;
+       default:
+               break;
+
+       }
+
+}
+
+static void Nmrp_Listen_Timeout(void)
+{
+       if (++Nmrp_Listen_TimeoutCount > NMRP_TIMEOUT_LISTEN) {
+               puts("\nRetry count exceeded; boot the image as usual\n");
+               Nmrp_Listen_TimeoutCount = 0;
+               ResetBootup_usual();
+       } else {
+               puts("T");
+               net_set_timeout_handler(CONFIG_SYS_HZ, Nmrp_Listen_Timeout);
+       }
+}
+
+static NMRP_PARSED_OPT *Nmrp_Parse(uchar * pkt, ushort optType)
+{
+       NMRP_PARSED_MSG *msg = (NMRP_PARSED_MSG *) pkt;
+       NMRP_PARSED_OPT *opt, *optEnd;
+       optEnd = &msg->options[msg->numOptions];
+       for (opt = msg->options; opt != optEnd; opt++)
+               if (opt->type == ntohs(optType))
+                       break;
+       return msg->numOptions == 0 ? NULL : (opt == optEnd ? NULL : opt);
+}
+
+void NmrpSetTimeout(unchar proto, ulong iv, nmrp_thand_f * f)
+{
+       if (iv == 0) {
+               NmrptimeHandler = (nmrp_thand_f *) 0;
+               Nmrpproto = 0;
+       } else {
+
+               NmrptimeHandler = f;
+               NmrptimeStart = get_timer(0);
+               NmrptimeDelta = iv;
+               Nmrpproto = proto;
+       }
+}
+/*
+  Function to parse the NMRP options inside packet.
+  If all options are parsed correctly, it returns 0.
+ */
+static int Nmrp_Parse_Opts(uchar *pkt, NMRP_PARSED_MSG *nmrp_parsed)
+{
+       nmrp_t *nmrphdr= (nmrp_t*) pkt;
+       NMRP_OPT *nmrp_opt;
+       int remain_len, opt_index = 0;
+
+       nmrp_parsed->reserved = nmrphdr->reserved;
+       nmrp_parsed->code     = nmrphdr->code;
+       nmrp_parsed->id       = nmrphdr->id;
+       nmrp_parsed->length   = nmrphdr->length;
+
+       remain_len = ntohs(nmrphdr->length) - NMRP_HDR_LEN;
+
+       nmrp_opt = &nmrphdr->opt;
+       while (remain_len > 0){
+               memcpy(&nmrp_parsed->options[opt_index], nmrp_opt, ntohs(nmrp_opt->len));
+               remain_len -= ntohs(nmrp_opt->len);
+               nmrp_opt = ((uchar *)nmrp_opt) + ntohs(nmrp_opt->len);
+               opt_index++;
+       }
+       nmrp_parsed->numOptions=opt_index;
+       return remain_len;
+}
+
+void string_table_bitmask_check()
+{
+       int update_bit;
+
+       /* find string tables need to be update, begin with smallest bit */
+       for (update_bit = 0; update_bit < STRING_TABLE_BITMASK_LEN; update_bit++) {
+               if ((NmrpStringTableBitmask & (1 << update_bit)) != 0) {
+                       //if bit 0 is set, update ST 1, ... etc
+                       NmrpStringTableUpdateList[NmrpStringTableUpdateCount] = update_bit + 1;
+                       NmrpStringTableUpdateCount++;
+               }
+       }
+}
+
+void set_region(u16 RegionOption)
+{
+       uchar region[8];
+       sprintf(region, "%04x", RegionOption);
+       env_set("region", region);
+       run_command("saveenv", 0);
+}
+
+void NmrpHandler(uchar * pkt, unsigned dest, struct in_addr src_ip, unsigned src,
+                 unsigned type)
+{
+       nmrp_t *nmrphdr= (nmrp_t*) pkt;
+       uchar proto;
+       unchar *xp = pkt;
+       int fwUpgrade;
+       NMRP_PARSED_MSG nmrp_parsed;
+       NMRP_PARSED_OPT *opt;
+       proto = nmrphdr->code;
+       if (type!=PROT_NMRP)
+               return;
+
+       /* check for timeout,and run the timeout handler
+          if we have one
+        */
+
+       if (NmrptimeHandler && ((get_timer(0) - NmrptimeStart) > NmrptimeDelta)
+           && (proto != Nmrpproto)) {
+               nmrp_thand_f *x;
+               x = NmrptimeHandler;
+               NmrptimeHandler = (nmrp_thand_f *) 0;
+               (*x) ();
+       }
+
+       /*
+          Check if Reserved field is zero. Per the specification, the reserved
+          must be all zero in a valid NMRP packet.
+        */
+       if (nmrphdr->reserved != 0){
+               return;
+       }
+       memset(&nmrp_parsed, 0, sizeof(NMRP_PARSED_MSG));
+
+       /*
+          Parse the options inside the packet and save it into nmrp_parsed for
+          future reference.
+        */
+       if (Nmrp_Parse_Opts(pkt, &nmrp_parsed) != 0){
+               /* Some wrong inside the packet, just discard it */
+               return;
+       }
+
+       NmrpBlock = proto;
+
+       // ignore same packet
+       if (NmrpBlock == NmrpLastBlock)
+               return;
+       NmrpLastBlock = NmrpBlock;
+
+       switch (proto) {
+       case NMRP_CODE_ADVERTISE:       /*listening state * */
+               if (NmrpState == 0) {
+                       /*
+                          Check if we get the MAGIC-NO option and the content is match
+                          with the MAGICNO.
+                        */
+                       if ((opt = Nmrp_Parse(&nmrp_parsed, NMRP_OPT_MAGIC_NO)) != NULL){
+                               int opt_hdr_len = sizeof(opt->type) + sizeof(opt->len);
+                               if (memcmp(opt->value.magicno, MAGICNO, ntohs(opt->len) - opt_hdr_len) == 0){
+                                       NmrpState = STATE_LISTENING;
+                                       board_test_led(0);
+                                       printf("\nNMRP CONFIGING");
+                                       NmrpSend();
+                               }
+                       }
+               }
+               break;
+       case NMRP_CODE_CONF_ACK:
+               if (NmrpState == STATE_LISTENING) {
+                       /*
+                          If there is no DEV-IP option inside the packet, it must be
+                          something wrong in the packet, so just ignore this packet
+                          without any action taken.
+                        */
+                       if ((opt = Nmrp_Parse(&nmrp_parsed, NMRP_OPT_DEV_IP)) != NULL){
+                               memcpy(NetOurTftpIP, opt->value.ip.addr,IP_ADDR_LEN);
+                               /* Do we need the subnet mask? */
+                               memcpy(&NmrpOuripSubnetMask, opt->value.ip.mask,IP_ADDR_LEN);
+                               /*
+                                  FW-UP option is optional for CONF-ACK and it has no effect no
+                                  matter what is the content of this option, so we just skip the
+                                  process of this option for now, and will add it back when
+                                  this option is defined as mandatory.
+                                  The process for FW-UP would be similar as the action taken for
+                                  DEV-IP and MAGIC-NO.
+                                */
+
+                               /*When NMRP Client get CONF-ACK with DEV-REGION option*/
+                               if ((opt = Nmrp_Parse(&nmrp_parsed, NMRP_OPT_DEV_REGION)) != NULL) {
+                                       /* Save DEV-REGION value to board */
+                                       printf("Get DEV-REGION option, value:0x%04x\n", opt->value.region);
+                                       NmrpDevRegionOption = ntohs(opt->value.region);
+                                       printf("Write Region Number 0x%04x to board\n", NmrpDevRegionOption);
+                                       set_region(NmrpDevRegionOption);
+                               }
+                               /*Check if NMRP Client get CONF-ACK with FW-UP option*/
+                               if ((opt = Nmrp_Parse(&nmrp_parsed, NMRP_OPT_FW_UP)) != NULL) {
+                                       printf("\nRecv FW-UP option\n");
+                                       NmrpFwUPOption = 1;
+                               } else {
+                                       printf("\nNo FW-UP option\n");
+                                       NmrpFwUPOption = 0;
+                               }
+
+                               /*When NMRP Client get CONF-ACK with ST-UP option*/
+                               if ((opt = Nmrp_Parse(&nmrp_parsed, NMRP_OPT_ST_UP)) != NULL) {
+                                       printf("\nRecv ST-UP option\n");
+                                       NmrpSTUPOption = 1;
+                                       /* Reset string tables' update related variables. */
+                                       NmrpStringTableUpdateCount = 0;
+                                       NmrpStringTableUpdateIndex = 0;
+                                       memset(NmrpStringTableUpdateList, 0,\
+                                               sizeof(NmrpStringTableUpdateList));
+
+                                       /* Save from network byte-order to host byte-order. */
+                                       NmrpStringTableBitmask = ntohl(opt->value.string_table_bitmask);
+
+                                       string_table_bitmask_check();
+                                       printf("\nTotal %d String Table need updating\n",\
+                                               NmrpStringTableUpdateCount);
+                               } else {
+                                       printf("\nNo ST-UP option\n");
+                                       NmrpSTUPOption = 0;
+                               }
+                               if (NmrpFwUPOption == 0 && NmrpSTUPOption == 0) {
+                                       NmrpState = STATE_CLOSING;
+                                       printf("\nNo firmware update, nor string table update\n");
+                                       NmrpSend();
+                               } else {
+                                       NmrpState = STATE_CONFIGING;
+                                       printf("\nNMRP WAITING FOR UPLOAD FIRMWARE or STRING TABLES!\n");
+                                       NmrpSend();
+                               }
+                       }else
+                               break;
+               }
+               break;
+       case NMRP_CODE_KEEP_ALIVE_ACK:
+               if (NmrpState == STATE_KEEP_ALIVE) {
+                       if (NmrpAliveWaitACK == 1) {
+                               NmrpAliveTimerBase += NMRP_TIMEOUT_ACTIVE / 4;
+                               NmrpAliveWaitACK = 0;
+                       }
+               }
+               break;
+       case NMRP_CODE_CLOSE_ACK:
+               if (NmrpState == STATE_CLOSING) {
+                       NmrpState = STATE_CLOSED;
+                       printf("\nNMRP CLOSED");
+                       NmrpSend();
+               }
+               break;
+       default:
+               break;
+       }
+
+}
+
+void NmrpStart(void)
+{
+       printf("\n Client starts...[Listening] for ADVERTISE...");
+
+       net_set_timeout_handler(CONFIG_SYS_HZ / 10, Nmrp_Listen_Timeout);
+       net_set_udp_handler(NmrpHandler);
+
+       NmrpState = 0;
+       Nmrp_Listen_TimeoutCount = 0;
+       memset(NmrpClientEther, 0, 6);
+       NmrpClientIP.s_addr = 0;
+}