Description of problem: When having dhcpv6 tests for rfc3315 in the host mode,we found that DUID cannot be kept consistent in some scenarios. Version-Release number of selected component (if applicable): kernel-2.6.18-43.el5 Software Environment: Testee(NUT): RHEL5 Kernel:2.6.18-43.el5 Tester(TN): FreeBSD6.2 v6eval-3.0.12.tar.gz TAHI package: DHCPv6_Self_Test_P2_1_0_7.tar.gz How reproducible: every time Steps to Reproduce: 1. Configure TAHI test environment. 2. Run the TAHI test suite 3. After the test completes, check for the results Actual results: DUID cannot be kept consistent. Expected results: DUID should be kept consistent. Additional info: please refer to http://focus.brisbane.redhat.com/~zwu/dhcp_client/20071030/DHCPv6_Self_Test_P2_1_0_7_client/rfc3315/index.html (1)17 Part B : DUID-LLT Consistency
This request was evaluated by Red Hat Product Management for inclusion in a Red Hat Enterprise Linux maintenance release. Product Management has requested further review of this request by Red Hat Engineering, for potential inclusion in a Red Hat Enterprise Linux Update release for currently deployed products. This request is not yet committed for inclusion in an Update release.
dhcp6c was saving the DUID when one was initially generated, but not any on received messages. I have patched the code so that the received DUID-LLT is saved to the DUID_FILE in /var/lib, which should maintain a consistent DUID across reboots. Attaching the patch to this bug report.
Created attachment 291437 [details] dhcpv6-1.0.4-bz377101.patch
Comment on attachment 291437 [details] dhcpv6-1.0.4-bz377101.patch >diff --git a/include/common.h b/include/common.h >index 3058596..ba1937c 100644 >--- a/include/common.h >+++ b/include/common.h >@@ -80,6 +80,8 @@ extern void dprintf __P((int, const char *, ...)); > #endif > > extern int get_duid __P((const char *, const char *, struct duid *)); >+extern int save_duid __P((const char *, const char *, struct duid *)); >+extern u_int16_t calculate_duid_len __P((const char *)); > extern void dhcp6_init_options __P((struct dhcp6_optinfo *)); > extern void dhcp6_clear_options __P((struct dhcp6_optinfo *)); > extern int dhcp6_copy_options __P((struct dhcp6_optinfo *, >diff --git a/src/common.c b/src/common.c >index 858ac70..913b0a1 100644 >--- a/src/common.c >+++ b/src/common.c >@@ -721,14 +721,7 @@ get_duid(const char *idfile, const char *ifname, > goto fail; > } > } else { >- int l; >- >- if ((l = gethwid(tmpbuf, sizeof(tmpbuf), ifname, &hwtype)) < 0) { >- dprintf(LOG_INFO, "%s" >- "failed to get a hardware address", FNAME); >- goto fail; >- } >- len = l + sizeof(struct dhcp6_duid_type1); >+ len = calculate_duid_len(ifname); > } > > memset(duid, 0, sizeof(*duid)); >@@ -763,29 +756,57 @@ get_duid(const char *idfile, const char *ifname, > duidstr(duid)); > } > >+ /* save DUID */ >+ if (save_duid(idfile, ifname, duid)) { >+ dprintf(LOG_DEBUG, "%s" "failed to save DUID: %s", FNAME, >+ duidstr(duid)); >+ goto fail; >+ } >+ >+ if (fp) >+ fclose(fp); >+ return (0); >+ >+fail: >+ if (fp) >+ fclose(fp); >+ if (duid->duid_id != NULL) { >+ duidfree(duid); >+ } >+ return (-1); >+} >+ >+int >+save_duid(const char *idfile, const char *ifname, struct duid *duid) >+{ >+ FILE *fp = NULL; >+ u_int16_t len = 0; >+ >+ /* calculate DUID length */ >+ len = calculate_duid_len(ifname); >+ > /* save the (new) ID to the file for next time */ > #ifdef LIBDHCP > if (libdhcp_control && (libdhcp_control->capability & DHCP_USE_LEASE_DATABASE)) > #endif >- if (!fp) { >- if ((fp = fopen(idfile, "w+")) == NULL) { >- dprintf(LOG_ERR, "%s" >- "failed to open DUID file for save", FNAME); >- goto fail; >- } >- if ((fwrite(&len, sizeof(len), 1, fp)) != 1) { >- dprintf(LOG_ERR, "%s" "failed to save DUID", FNAME); >- goto fail; >- } >- if ((fwrite(duid->duid_id, len, 1, fp)) != 1) { >- dprintf(LOG_ERR, "%s" "failed to save DUID", FNAME); >- goto fail; >- } >+ if ((fp = fopen(idfile, "w+")) == NULL) { >+ dprintf(LOG_ERR, "%s" >+ "failed to open DUID file for save", FNAME); >+ goto fail; >+ } > >- dprintf(LOG_DEBUG, "%s" "saved generated DUID to %s", FNAME, >- idfile); >+ if ((fwrite(&len, sizeof(len), 1, fp)) != 1) { >+ dprintf(LOG_ERR, "%s" "failed to save DUID", FNAME); >+ goto fail; > } > >+ if ((fwrite(duid->duid_id, len, 1, fp)) != 1) { >+ dprintf(LOG_ERR, "%s" "failed to save DUID", FNAME); >+ goto fail; >+ } >+ >+ dprintf(LOG_DEBUG, "%s" "saved generated DUID to %s", FNAME, idfile); >+ > if (fp) > fclose(fp); > return (0); >@@ -799,6 +820,24 @@ get_duid(const char *idfile, const char *ifname, > return (-1); > } > >+u_int16_t >+calculate_duid_len(const char *ifname) >+{ >+ int l; >+ u_int16_t ret = 0, hwtype; >+ struct dhcp6_duid_type1 *dp; /* we only support the type1 DUID */ >+ unsigned char tmpbuf[256]; /* DUID should be no more than 256 bytes */ >+ >+ if ((l = gethwid(tmpbuf, sizeof(tmpbuf), ifname, &hwtype)) < 0) { >+ dprintf(LOG_INFO, "%s" >+ "failed to get a hardware address", FNAME); >+ return 0; >+ } >+ >+ ret = l + sizeof(struct dhcp6_duid_type1); >+ return ret; >+} >+ > ssize_t > gethwid(buf, len, ifname, hwtypep) > unsigned char *buf; >diff --git a/src/dhcp6c.c b/src/dhcp6c.c >index 14e589e..255b161 100644 >--- a/src/dhcp6c.c >+++ b/src/dhcp6c.c >@@ -555,6 +555,7 @@ client6_ifinit(char *device) > memcpy(&client6_iaidaddr.client6_info.iaidinfo, &ifp->iaidinfo, > sizeof(client6_iaidaddr.client6_info.iaidinfo)); > duidcpy(&client6_iaidaddr.client6_info.clientid, &client_duid); >+ save_duid(DUID_FILE, device, &client_duid); > #ifdef LIBDHCP > if (libdhcp_control && (libdhcp_control->capability & DHCP_USE_LEASE_DATABASE)) { > #endif >@@ -1050,6 +1051,12 @@ client6_send(ev) > goto end; > } > >+ /* save DUID now for persistent DUID (e.g., if client reboots) */ >+ if (save_duid(DUID_FILE, device, &client_duid)) { >+ dprintf(LOG_ERR, "%s" "failed to save client ID", FNAME); >+ goto end; >+ } >+ > /* option request options */ > if (dhcp6_copy_list(&optinfo.reqopt_list, &ifp->reqopt_list)) { > dprintf(LOG_ERR, "%s" "failed to copy requested options",
Created attachment 291438 [details] dhcpv6-1.0.4-bz377101.patch
but the test cases FAIL on RHEL5.2 with dhcpv6-1.0.10 for more details, pls refer to http://focus.brisbane.redhat.com/~zwu/RHEL5.2-Server-20080212.0/20080220/DHCPv6_Self_Test_P2_1_0_8_client_1.0.10/rfc3315/17.html
In order to debug this problem, we need the test case for RHEL 5.2 with an exact reproducer, including output with verbose debugging messages from the DHCPV6 software. One way to do this would be to extract the commands that TAHI runs. The man pages for dhcp6s, dhcp6r, and dhcp6c all show how to generate verbose debug messages.
Fixed in dhcpv6-1.0.10-2.el5.
*** Bug 436870 has been marked as a duplicate of this bug. ***
When the NUT reboots, is the /var/lib/dhcpv6 directory getting cleared out before starting dhcp6c again? The DUID is recorded as /var/lib/dhcpv6/dhcp6c_duid, so the only way to keep it persistent is to make sure that file isn't removed. Any time it's removed, a new DUID will be generated by the client.
Adding yshao to the cc list as the manager of the disabled user zwu who reported this bug
*** This bug has been marked as a duplicate of 439526 ***
Is this still happening in RHEL 5.2 or the 5.2.z update? I'm pretty sure all of the instances where the DUID needs to be written out are in the code, but I may have missed one. Please let me know if it's working 5.2 or 5.2.z. Thanks.
Any updated info with regards to comment #21? Thanks.
OK, I think this is related to a similar problem that dhcp6c had earlier. We weren't saving the generated DUID in dhcp6c, so a call to save_duid() was added. I've added calls to save_duid() in dhcp6s in the same style as what we did in dhcp6c. This should solve the consistency between reboots problems. One thing that's confusing to me is that get_duid() will either read in the saved DUID or generate a new one, then it calls save_duid() to save it. However, that is what's happening now and the consistency is not there, so something must occur to the DUID during the course of the program running, so we need to save it again. If this patch doesn't fix things up, my suggestion will be to modify the signal handler in dhcp6s to call save_duid() before exiting to ensure we have the latest copy saved. The fix will be in dhcpv6-1.0.10-8.el5.
Are we ready to go or is the state still "needinfo"? If no additional information needed, I can approve for 5.2.z. Thanks
Testing. Trying to get rid of the NEED_INFO since its in MODIFIED state.
Fixed this in dhcpv6-1.0.10-10.el5. This one has taken me a while. I retraced everything today and finally figured out what was happening. I had been looking at the wrong place in the code the entire time. Once we have the client DUID, the server DUID LLT field is updated so they match. The rest of the DUID is left untouched. Watching the communication via wireshark, it looks like this will work for the test (I hope anyway). Attaching the patch so you can see. It ended up being pretty simple.
Created attachment 319707 [details] dhcpv6-1.0.10-duid_match_llt.patch
Great! Thanks David. llim->ryang: could you please run the test today and let us know the good news? :)
I just retested dhcpv6-1.0.10-10.el5 and with dhcpv6-1.0.10-11.el5 and the DUID LLT values match for the client and server. I did an information request and a normal IANA exchange and the LLT time value matched the entire time. The DUID also remained consistent through reboots. The MAC field of the DUID is different between the client and server, but that is how it should be, right? The server DUID should have the server MAC address and the client DUID should have the client MAC address, right? The DUID LLT should match between both of them. Please retest using dhcpv6-1.0.10-11.el5. I am showing the LLT TIME values are matched with both dhcpv6-1.0.10-10.el5 and dhcpv6-1.0.10-11.el5.
An advisory has been issued which should help the problem described in this bug report. This report is therefore being closed with a resolution of ERRATA. For more information on therefore solution and/or where to find the updated files, please follow the link below. You may reopen this bug report if the solution does not work for you. http://rhn.redhat.com/errata/RHBA-2009-0165.html