Esempio n. 1
0
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;
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
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);
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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);
}
Esempio n. 8
0
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);
}