size_t get_duid(unsigned char *duid, const struct interface *ifp) { FILE *f; int x = 0; size_t len = 0; char *line; /* If we already have a DUID then use it as it's never supposed * to change once we have one even if the interfaces do */ if ((f = fopen(DUID, "r"))) { while ((line = get_line(f))) { len = hwaddr_aton(NULL, line); if (len && len <= DUID_LEN) { hwaddr_aton(duid, line); break; } len = 0; } fclose(f); if (len) return len; } else { if (errno != ENOENT) { syslog(LOG_ERR, "error reading DUID: %s: %m", DUID); return make_duid(duid, ifp, DUID_LL); } } /* No file? OK, lets make one based on our interface */ if (!(f = fopen(DUID, "w"))) { syslog(LOG_ERR, "error writing DUID: %s: %m", DUID); return make_duid(duid, ifp, DUID_LL); } len = make_duid(duid, ifp, DUID_LLT); x = fprintf(f, "%s\n", hwaddr_ntoa(duid, len)); fclose(f); /* Failed to write the duid? scrub it, we cannot use it */ if (x < 1) { syslog(LOG_ERR, "error writing DUID: %s: %m", DUID); unlink(DUID); return make_duid(duid, ifp, DUID_LL); } return len; }
void handle_hwaddr(const char *ifname, const uint8_t *hwaddr, size_t hwlen) { struct interface *ifp; ifp = find_interface(ifname); if (ifp == NULL) return; if (hwlen > sizeof(ifp->hwaddr)) { errno = ENOBUFS; syslog(LOG_ERR, "%s: %s: %m", ifp->name, __func__); return; } if (ifp->hwlen == hwlen && memcmp(ifp->hwaddr, hwaddr, hwlen) == 0) return; syslog(LOG_INFO, "%s: new hardware address: %s", ifp->name, hwaddr_ntoa(hwaddr, hwlen)); ifp->hwlen = hwlen; memcpy(ifp->hwaddr, hwaddr, hwlen); }
interface_t *read_interface (const char *ifname, int metric) { int s; struct ifreq ifr; interface_t *iface; unsigned char hwaddr[16]; int hwlen = 0; sa_family_t family; #ifndef __linux__ struct ifaddrs *ifap; struct ifaddrs *p; #endif if (! ifname) return NULL; memset (hwaddr, sizeof (hwaddr), 0); #ifndef __linux__ if (getifaddrs (&ifap) != 0) return NULL; for (p = ifap; p; p = p->ifa_next) { union { struct sockaddr *sa; struct sockaddr_dl *sdl; } us; if (strcmp (p->ifa_name, ifname) != 0) continue; us.sa = p->ifa_addr; if (p->ifa_addr->sa_family != AF_LINK || (us.sdl->sdl_type != IFT_ETHER)) /* && us.sdl->sdl_type != IFT_ISO88025)) */ { logger (LOG_ERR, "interface is not Ethernet"); freeifaddrs (ifap); return NULL; } memcpy (hwaddr, us.sdl->sdl_data + us.sdl->sdl_nlen, ETHER_ADDR_LEN); family = ARPHRD_ETHER; hwlen = ETHER_ADDR_LEN; break; } freeifaddrs (ifap); if (!p) { logger (LOG_ERR, "could not find interface %s", ifname); return NULL; } #endif memset (&ifr, 0, sizeof (struct ifreq)); strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); if ((s = socket (AF_INET, SOCK_DGRAM, 0)) < 0) { logger (LOG_ERR, "socket: %s", strerror (errno)); return NULL; } #ifdef __linux__ /* Do something with the metric parameter to satisfy the compiler warning */ metric = 0; strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); if (ioctl (s, SIOCGIFHWADDR, &ifr) <0) { logger (LOG_ERR, "ioctl SIOCGIFHWADDR: %s", strerror (errno)); close (s); return NULL; } switch (ifr.ifr_hwaddr.sa_family) { case ARPHRD_ETHER: case ARPHRD_IEEE802: hwlen = ETHER_ADDR_LEN; break; case ARPHRD_IEEE1394: hwlen = EUI64_ADDR_LEN; case ARPHRD_INFINIBAND: hwlen = INFINIBAND_ADDR_LEN; break; default: logger (LOG_ERR, "interface is not Ethernet, FireWire, InfiniBand or Token Ring"); close (s); return NULL; } memcpy (hwaddr, ifr.ifr_hwaddr.sa_data, hwlen); family = ifr.ifr_hwaddr.sa_family; #else ifr.ifr_metric = metric; strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); if (ioctl (s, SIOCSIFMETRIC, &ifr) < 0) { logger (LOG_ERR, "ioctl SIOCSIFMETRIC: %s", strerror (errno)); close (s); return NULL; } #endif strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) { logger (LOG_ERR, "ioctl SIOCGIFFLAGS: %s", strerror (errno)); close (s); return NULL; } ifr.ifr_flags |= IFF_UP | IFF_RUNNING; strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0) { logger (LOG_ERR, "ioctl SIOCSIFFLAGS: %s", strerror (errno)); close (s); return NULL; } close (s); iface = xmalloc (sizeof (interface_t)); memset (iface, 0, sizeof (interface_t)); strncpy (iface->name, ifname, IF_NAMESIZE); snprintf (iface->infofile, PATH_MAX, INFOFILE, ifname); memcpy (&iface->hwaddr, hwaddr, hwlen); iface->hwlen = hwlen; iface->family = family; iface->arpable = ! (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)); logger (LOG_INFO, "hardware address = %s", hwaddr_ntoa (iface->hwaddr, iface->hwlen)); /* 0 is a valid fd, so init to -1 */ iface->fd = -1; return iface; }
static int write_info(const interface_t *iface, const dhcp_t *dhcp, const options_t *options) { FILE *f; route_t *route; address_t *address; logger (LOG_DEBUG, "writing %s", iface->infofile); if ((f = fopen (iface->infofile, "w")) == NULL) { logger (LOG_ERR, "fopen `%s': %s", iface->infofile, strerror (errno)); return -1; } fprintf (f, "IPADDR='%s'\n", inet_ntoa (dhcp->address)); fprintf (f, "NETMASK='%s'\n", inet_ntoa (dhcp->netmask)); fprintf (f, "BROADCAST='%s'\n", inet_ntoa (dhcp->broadcast)); if (dhcp->mtu > 0) fprintf (f, "MTU='%d'\n", dhcp->mtu); if (dhcp->routes) { fprintf (f, "ROUTES='"); for (route = dhcp->routes; route; route = route->next) { fprintf (f, "%s", inet_ntoa (route->destination)); fprintf (f, ",%s", inet_ntoa (route->netmask)); fprintf (f, ",%s", inet_ntoa (route->gateway)); if (route->next) fprintf (f, " "); } fprintf (f, "'\n"); } if (dhcp->hostname) fprintf (f, "HOSTNAME='%s'\n", cleanmetas (dhcp->hostname)); if (dhcp->dnsdomain) fprintf (f, "DNSDOMAIN='%s'\n", cleanmetas (dhcp->dnsdomain)); if (dhcp->dnssearch) fprintf (f, "DNSSEARCH='%s'\n", cleanmetas (dhcp->dnssearch)); if (dhcp->dnsservers) { fprintf (f, "DNSSERVERS='"); for (address = dhcp->dnsservers; address; address = address->next) { fprintf (f, "%s", inet_ntoa (address->address)); if (address->next) fprintf (f, " "); } fprintf (f, "'\n"); } if (dhcp->fqdn) { fprintf (f, "FQDNFLAGS='%u'\n", dhcp->fqdn->flags); fprintf (f, "FQDNRCODE1='%u'\n", dhcp->fqdn->r1); fprintf (f, "FQDNRCODE2='%u'\n", dhcp->fqdn->r2); fprintf (f, "FQDNHOSTNAME='%s'\n", dhcp->fqdn->name); } if (dhcp->ntpservers) { fprintf (f, "NTPSERVERS='"); for (address = dhcp->ntpservers; address; address = address->next) { fprintf (f, "%s", inet_ntoa (address->address)); if (address->next) fprintf (f, " "); } fprintf (f, "'\n"); } if (dhcp->nisdomain) fprintf (f, "NISDOMAIN='%s'\n", cleanmetas (dhcp->nisdomain)); if (dhcp->nisservers) { fprintf (f, "NISSERVERS='"); for (address = dhcp->nisservers; address; address = address->next) { fprintf (f, "%s", inet_ntoa (address->address)); if (address->next) fprintf (f, " "); } fprintf (f, "'\n"); } if (dhcp->rootpath) fprintf (f, "ROOTPATH='%s'\n", cleanmetas (dhcp->rootpath)); fprintf (f, "DHCPSID='%s'\n", inet_ntoa (dhcp->serveraddress)); fprintf (f, "DHCPSNAME='%s'\n", cleanmetas (dhcp->servername)); fprintf (f, "LEASETIME='%u'\n", dhcp->leasetime); fprintf (f, "RENEWALTIME='%u'\n", dhcp->renewaltime); fprintf (f, "REBINDTIME='%u'\n", dhcp->rebindtime); fprintf (f, "INTERFACE='%s'\n", iface->name); fprintf (f, "CLASSID='%s'\n", cleanmetas (options->classid)); if (options->clientid[0]) fprintf (f, "CLIENTID='%s'\n", cleanmetas (options->clientid)); else fprintf (f, "CLIENTID='%s'\n", hwaddr_ntoa (iface->hwaddr, iface->hwlen)); fprintf (f, "DHCPCHADDR='%s'\n", hwaddr_ntoa (iface->hwaddr, iface->hwlen)); fclose (f); return 0; }
int arp_claim (interface_t *iface, struct in_addr address) { struct arphdr *reply = NULL; long timeout = 0; unsigned char *buffer; int retval = -1; int nprobes = 0; int nclaims = 0; struct in_addr null_address; if (! iface->arpable) { logger (LOG_DEBUG, "interface `%s' is not ARPable", iface->name); return (0); } logger (LOG_INFO, "checking %s is available on attached networks", inet_ntoa (address)); if (! open_socket (iface, true)) return (0); memset (&null_address, 0, sizeof (null_address)); buffer = xmalloc (sizeof (char *) * iface->buffer_length); /* Our ARP packets are always smaller - hopefully */ reply = xmalloc (IP_MIN_FRAME_LENGTH); while (1) { struct timeval tv; int bufpos = -1; int buflen = sizeof (char *) * iface->buffer_length; fd_set rset; int bytes; int s; tv.tv_sec = 0; tv.tv_usec = timeout; FD_ZERO (&rset); FD_SET (iface->fd, &rset); errno = 0; if ((s = select (FD_SETSIZE, &rset, NULL, NULL, &tv)) == -1) { if (errno != EINTR) logger (LOG_ERR, "select: `%s'", strerror (errno)); break; } else if (s == 0) { /* Timed out */ if (nprobes < NPROBES) { nprobes ++; timeout = PROBE_INTERVAL; logger (LOG_DEBUG, "sending ARP probe #%d", nprobes); send_arp (iface, ARPOP_REQUEST, null_address, NULL, address); } else if (nclaims < NCLAIMS) { nclaims ++; timeout = CLAIM_INTERVAL; logger (LOG_DEBUG, "sending ARP claim #%d", nclaims); send_arp (iface, ARPOP_REQUEST, address, iface->hwaddr, address); } else { /* No replies, so done */ retval = 0; break; } } if (! FD_ISSET (iface->fd, &rset)) continue; memset (buffer, 0, buflen); while (bufpos != 0) { union { unsigned char *c; struct in_addr *a; } rp; union { unsigned char *c; struct ether_addr *a; } rh; memset (reply, 0, IP_MIN_FRAME_LENGTH); if ((bytes = get_packet (iface, (unsigned char *) reply, buffer, &buflen, &bufpos)) == -1) break; /* Only these types are recognised */ if (reply->ar_op != htons (ARPOP_REPLY)) continue; /* Protocol must be IP. */ if (reply->ar_pro != htons (ETHERTYPE_IP)) continue; if (reply->ar_pln != sizeof (struct in_addr)) continue; if ((unsigned) bytes < sizeof (reply) + 2 * (4 + reply->ar_hln)) continue; rp.c = (unsigned char *) ar_spa (reply); rh.c = (unsigned char *) ar_sha (reply); /* Ensure the ARP reply is for the address we asked for */ if (rp.a->s_addr != address.s_addr) continue; /* Some systems send a reply back from our hwaddress - weird */ if (reply->ar_hln == iface->hwlen && memcmp (rh.c, iface->hwaddr, iface->hwlen) == 0) continue; logger (LOG_ERR, "ARPOP_REPLY received from %s (%s)", inet_ntoa (*rp.a), hwaddr_ntoa (rh.c, reply->ar_hln)); retval = -1; goto eexit; } } eexit: close (iface->fd); iface->fd = -1; free (buffer); free (reply); return (retval); }
interface_t *read_interface (const char *ifname, int metric) { int s; struct ifreq ifr; interface_t *iface = NULL; unsigned char *hwaddr = NULL; int hwlen = 0; sa_family_t family = 0; unsigned short mtu; #ifdef __linux__ char *p; #endif if (! ifname) return NULL; memset (&ifr, 0, sizeof (struct ifreq)); strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); if ((s = socket (AF_INET, SOCK_DGRAM, 0)) == -1) { logger (LOG_ERR, "socket: %s", strerror (errno)); return NULL; } #ifdef __linux__ /* Do something with the metric parameter to satisfy the compiler warning */ metric = 0; strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); if (ioctl (s, SIOCGIFHWADDR, &ifr) == -1) { logger (LOG_ERR, "ioctl SIOCGIFHWADDR: %s", strerror (errno)); goto exit; } switch (ifr.ifr_hwaddr.sa_family) { case ARPHRD_ETHER: case ARPHRD_IEEE802: hwlen = ETHER_ADDR_LEN; break; case ARPHRD_IEEE1394: hwlen = EUI64_ADDR_LEN; case ARPHRD_INFINIBAND: hwlen = INFINIBAND_ADDR_LEN; break; default: logger (LOG_ERR, "interface is not Ethernet, FireWire, InfiniBand or Token Ring"); goto exit; } hwaddr = xmalloc (sizeof (unsigned char) * HWADDR_LEN); memcpy (hwaddr, ifr.ifr_hwaddr.sa_data, hwlen); family = ifr.ifr_hwaddr.sa_family; #else ifr.ifr_metric = metric; strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); if (ioctl (s, SIOCSIFMETRIC, &ifr) == -1) { logger (LOG_ERR, "ioctl SIOCSIFMETRIC: %s", strerror (errno)); goto exit; } hwaddr = xmalloc (sizeof (unsigned char) * HWADDR_LEN); if (_do_interface (ifname, hwaddr, &hwlen, NULL, false, false) != 1) { logger (LOG_ERR, "could not find interface %s", ifname); goto exit; } family = ARPHRD_ETHER; #endif strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); if (ioctl (s, SIOCGIFMTU, &ifr) == -1) { logger (LOG_ERR, "ioctl SIOCGIFMTU: %s", strerror (errno)); goto exit; } if (ifr.ifr_mtu < MTU_MIN) { logger (LOG_DEBUG, "MTU of %d is too low, setting to %d", ifr.ifr_mtu, MTU_MIN); ifr.ifr_mtu = MTU_MIN; strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); if (ioctl (s, SIOCSIFMTU, &ifr) == -1) { logger (LOG_ERR, "ioctl SIOCSIFMTU,: %s", strerror (errno)); goto exit; } } mtu = ifr.ifr_mtu; strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); #ifdef __linux__ /* We can only bring the real interface up */ if ((p = strchr (ifr.ifr_name, ':'))) *p = '\0'; #endif if (ioctl (s, SIOCGIFFLAGS, &ifr) == -1) { logger (LOG_ERR, "ioctl SIOCGIFFLAGS: %s", strerror (errno)); goto exit; } if (! (ifr.ifr_flags & IFF_UP) || ! (ifr.ifr_flags & IFF_RUNNING)) { ifr.ifr_flags |= IFF_UP | IFF_RUNNING; if (ioctl (s, SIOCSIFFLAGS, &ifr) == -1) { logger (LOG_ERR, "ioctl SIOCSIFFLAGS: %s", strerror (errno)); goto exit; } } iface = xmalloc (sizeof (interface_t)); memset (iface, 0, sizeof (interface_t)); strlcpy (iface->name, ifname, IF_NAMESIZE); #ifdef ENABLE_INFO snprintf (iface->infofile, PATH_MAX, INFOFILE, ifname); #endif memcpy (&iface->hwaddr, hwaddr, hwlen); iface->hwlen = hwlen; iface->family = family; iface->arpable = ! (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)); iface->mtu = iface->previous_mtu = mtu; logger (LOG_INFO, "hardware address = %s", hwaddr_ntoa (iface->hwaddr, iface->hwlen)); /* 0 is a valid fd, so init to -1 */ iface->fd = -1; exit: close (s); free (hwaddr); return iface; }
bool write_info(const interface_t *iface, const dhcp_t *dhcp, const options_t *options, bool overwrite) { FILE *f; route_t *route; address_t *address; struct stat sb; if (options->test) f = stdout; else { if (! overwrite && stat (iface->infofile, &sb) == 0) return (true); logger (LOG_DEBUG, "writing %s", iface->infofile); if ((f = fopen (iface->infofile, "w")) == NULL) { logger (LOG_ERR, "fopen `%s': %s", iface->infofile, strerror (errno)); return (false); } } if (dhcp->address.s_addr) { fprintf (f, "IPADDR='%s'\n", inet_ntoa (dhcp->address)); fprintf (f, "NETMASK='%s'\n", inet_ntoa (dhcp->netmask)); fprintf (f, "BROADCAST='%s'\n", inet_ntoa (dhcp->broadcast)); } if (dhcp->mtu > 0) fprintf (f, "MTU='%d'\n", dhcp->mtu); if (dhcp->routes) { bool doneone = false; fprintf (f, "ROUTES='"); for (route = dhcp->routes; route; route = route->next) { if (route->destination.s_addr != 0) { if (doneone) fprintf (f, " "); fprintf (f, "%s", inet_ntoa (route->destination)); fprintf (f, ",%s", inet_ntoa (route->netmask)); fprintf (f, ",%s", inet_ntoa (route->gateway)); doneone = true; } } fprintf (f, "'\n"); doneone = false; fprintf (f, "GATEWAYS='"); for (route = dhcp->routes; route; route = route->next) { if (route->destination.s_addr == 0) { if (doneone) fprintf (f, " "); fprintf (f, "%s", inet_ntoa (route->gateway)); doneone = true; } } fprintf (f, "'\n"); } if (dhcp->hostname) fprintf (f, "HOSTNAME='%s'\n", cleanmetas (dhcp->hostname)); if (dhcp->dnsdomain) fprintf (f, "DNSDOMAIN='%s'\n", cleanmetas (dhcp->dnsdomain)); if (dhcp->dnssearch) fprintf (f, "DNSSEARCH='%s'\n", cleanmetas (dhcp->dnssearch)); if (dhcp->dnsservers) { fprintf (f, "DNSSERVERS='"); for (address = dhcp->dnsservers; address; address = address->next) { fprintf (f, "%s", inet_ntoa (address->address)); if (address->next) fprintf (f, " "); } fprintf (f, "'\n"); } if (dhcp->fqdn) { fprintf (f, "FQDNFLAGS='%u'\n", dhcp->fqdn->flags); fprintf (f, "FQDNRCODE1='%u'\n", dhcp->fqdn->r1); fprintf (f, "FQDNRCODE2='%u'\n", dhcp->fqdn->r2); fprintf (f, "FQDNHOSTNAME='%s'\n", dhcp->fqdn->name); } if (dhcp->ntpservers) { fprintf (f, "NTPSERVERS='"); for (address = dhcp->ntpservers; address; address = address->next) { fprintf (f, "%s", inet_ntoa (address->address)); if (address->next) fprintf (f, " "); } fprintf (f, "'\n"); } if (dhcp->nisdomain) fprintf (f, "NISDOMAIN='%s'\n", cleanmetas (dhcp->nisdomain)); if (dhcp->nisservers) { fprintf (f, "NISSERVERS='"); for (address = dhcp->nisservers; address; address = address->next) { fprintf (f, "%s", inet_ntoa (address->address)); if (address->next) fprintf (f, " "); } fprintf (f, "'\n"); } if (dhcp->rootpath) fprintf (f, "ROOTPATH='%s'\n", cleanmetas (dhcp->rootpath)); if (dhcp->sipservers) fprintf (f, "SIPSERVERS='%s'\n", cleanmetas (dhcp->sipservers)); if (dhcp->serveraddress.s_addr) fprintf (f, "DHCPSID='%s'\n", inet_ntoa (dhcp->serveraddress)); if (dhcp->servername[0]) fprintf (f, "DHCPSNAME='%s'\n", cleanmetas (dhcp->servername)); if (! options->doinform && dhcp->address.s_addr) { if (! options->test) fprintf (f, "LEASEDFROM='%u'\n", dhcp->leasedfrom); fprintf (f, "LEASETIME='%u'\n", dhcp->leasetime); fprintf (f, "RENEWALTIME='%u'\n", dhcp->renewaltime); fprintf (f, "REBINDTIME='%u'\n", dhcp->rebindtime); } fprintf (f, "INTERFACE='%s'\n", iface->name); fprintf (f, "CLASSID='%s'\n", cleanmetas (options->classid)); if (options->clientid_len > 0) fprintf (f, "CLIENTID='00:%s'\n", cleanmetas (options->clientid)); #ifdef ENABLE_DUID else if (iface->duid_length > 0 && options->clientid_len != -1) { unsigned char duid[256]; unsigned char *p = duid; uint32_t ul; *p++ = 255; /* IAID is 4 bytes, so if the interface name is 4 bytes then use it */ if (strlen (iface->name) == 4) { memcpy (p, iface->name, 4); } else { /* Name isn't 4 bytes, so use the index */ ul = htonl (if_nametoindex (iface->name)); memcpy (p, &ul, 4); } p += 4; memcpy (p, iface->duid, iface->duid_length); p += iface->duid_length; fprintf (f, "CLIENTID='%s'\n", hwaddr_ntoa (duid, p - duid)); } #endif else fprintf (f, "CLIENTID='%.2X:%s'\n", iface->family, hwaddr_ntoa (iface->hwaddr, iface->hwlen)); fprintf (f, "DHCPCHADDR='%s'\n", hwaddr_ntoa (iface->hwaddr, iface->hwlen)); #ifdef ENABLE_INFO_COMPAT /* Support the old .info settings if we need to */ fprintf (f, "\n# dhcpcd-1.x and 2.x compatible variables\n"); if (dhcp->dnsservers) { fprintf (f, "DNS='"); for (address = dhcp->dnsservers; address; address = address->next) { fprintf (f, "%s", inet_ntoa (address->address)); if (address->next) fprintf (f, ","); } fprintf (f, "'\n"); } if (dhcp->routes) { bool doneone = false; fprintf (f, "GATEWAY='"); for (route = dhcp->routes; route; route = route->next) { if (route->destination.s_addr == 0) { if (doneone) fprintf (f, ","); fprintf (f, "%s", inet_ntoa (route->gateway)); doneone = true; } } fprintf (f, "'\n"); } #endif if (! options->test) fclose (f); return (true); }
void start_interface(void *arg) { struct interface *ifp = arg; struct if_options *ifo = ifp->options; int nolease; size_t i; handle_carrier(LINK_UNKNOWN, 0, ifp->name); if (ifp->carrier == LINK_DOWN) { syslog(LOG_INFO, "%s: waiting for carrier", ifp->name); return; } if (ifo->options & (DHCPCD_DUID | DHCPCD_IPV6)) { /* Report client DUID */ if (duid == NULL) { if (duid_init(ifp) == 0) return; syslog(LOG_INFO, "DUID %s", hwaddr_ntoa(duid, duid_len)); } /* Report IAIDs */ syslog(LOG_INFO, "%s: IAID %s", ifp->name, hwaddr_ntoa(ifo->iaid, sizeof(ifo->iaid))); warn_iaid_conflict(ifp, ifo->iaid); for (i = 0; i < ifo->ia_len; i++) { if (memcmp(ifo->iaid, ifo->ia[i].iaid, sizeof(ifo->iaid))) { syslog(LOG_INFO, "%s: IAID %s", ifp->name, hwaddr_ntoa(ifo->ia[i].iaid, sizeof(ifo->ia[i].iaid))); warn_iaid_conflict(ifp, ifo->ia[i].iaid); } } } if (ifo->options & DHCPCD_IPV6) { if (ifo->options & DHCPCD_IPV6RS && !(ifo->options & DHCPCD_INFORM)) ipv6nd_startrs(ifp); if (!(ifo->options & DHCPCD_IPV6RS)) { if (ifo->options & DHCPCD_IA_FORCED) nolease = dhcp6_start(ifp, DH6S_INIT); else { nolease = dhcp6_find_delegates(ifp); /* Enabling the below doesn't really make * sense as there is currently no standard * to push routes via DHCPv6. * (There is an expired working draft, * maybe abandoned?) * You can also get it to work by forcing * an IA as shown above. */ #if 0 /* With no RS or delegates we might * as well try and solicit a DHCPv6 address */ if (nolease == 0) nolease = dhcp6_start(ifp, DH6S_INIT); #endif } if (nolease == -1) syslog(LOG_ERR, "%s: dhcp6_start: %m", ifp->name); } } if (ifo->options & DHCPCD_IPV4) dhcp_start(ifp); }