* between reboots without persitent storage,
* generating the IAID from the MAC address is the only
* logical default.
+ * Saying that, if a VLANID has been specified then we
+ * can use that. It's possible that different interfaces
+ * can have the same VLANID, but this is no worse than
+ * generating the IAID from the duplicate MAC address.
*
* dhclient uses the last 4 bytes of the MAC address.
* dibbler uses an increamenting counter.
* dhcpcd-6.1.0 and earlier used the interface name,
* falling back to interface index if name > 4.
*/
- if (ifp->hwlen >= sizeof(ifo->iaid))
+ if (ifp->vlanid != 0) {
+ uint32_t vlanid;
+
+ /* Maximal VLANID is 4095, so prefix with 0xff
+ * so we don't conflict with an interface index. */
+ vlanid = htonl(ifp->vlanid | 0xff000000);
+ memcpy(ifo->iaid, &vlanid, sizeof(vlanid));
+ } else if (ifp->hwlen >= sizeof(ifo->iaid)) {
memcpy(ifo->iaid,
ifp->hwaddr + ifp->hwlen - sizeof(ifo->iaid),
sizeof(ifo->iaid));
- else {
+ } else {
uint32_t len;
len = (uint32_t)strlen(ifp->name);
} else {
/* IAID is the same size as a uint32_t */
len = htonl(ifp->index);
- memcpy(ifo->iaid, &len, sizeof(len));
+ memcpy(ifo->iaid, &len, sizeof(ifo->iaid));
}
}
ifo->options |= DHCPCD_IAID;
This option must be used in an
.Ic interface
block.
-This defaults to the last 4 bytes of the hardware address assigned to the
+This defaults to the VLANID (prefixed with 0xff) for the interface if set,
+otherwise the last 4 bytes of the hardware address assigned to the
interface.
Each instance of this should be unique within the scope of the client and
.Nm dhcpcd
sa_family_t family;
unsigned char hwaddr[HWADDR_LEN];
uint8_t hwlen;
+ unsigned short vlanid;
unsigned int metric;
int carrier;
int wireless;
#include <netinet/in_var.h>
#include <netinet6/in6_var.h>
#include <netinet6/nd6.h>
+#ifdef __NetBSD__
+#include <net/if_vlanvar.h> /* Needs netinet/if_ether.h */
+#else
+#include <net/if_vlan_var.h>
+#endif
#ifdef __DragonFly__
# include <netproto/802_11/ieee80211_ioctl.h>
#elif __APPLE__
}
#endif
+#if defined(SIOCG80211NWID) || defined(SIOCGETVLAN)
+static int if_direct_ioctl(int s, const char *ifname,
+ unsigned long cmd, void *data)
+{
+
+ strlcpy(data, ifname, IFNAMSIZ);
+ return ioctl(s, cmd, data);
+}
+
+static int if_indirect_ioctl(int s, const char *ifname,
+ unsigned long cmd, void *data)
+{
+ struct ifreq ifr;
+
+ memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_data = data;
+ return if_direct_ioctl(s, ifname, cmd, &ifr);
+}
+#endif
+
static int
if_getssid1(int s, const char *ifname, void *ssid)
{
int retval = -1;
#if defined(SIOCG80211NWID)
- struct ifreq ifr;
struct ieee80211_nwid nwid;
#elif defined(IEEE80211_IOC_SSID)
struct ieee80211req ireq;
#endif
#if defined(SIOCG80211NWID) /* NetBSD */
- memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
memset(&nwid, 0, sizeof(nwid));
- ifr.ifr_data = (void *)&nwid;
- if (ioctl(s, SIOCG80211NWID, &ifr) == 0) {
+ if (if_indirect_ioctl(s, ifname, SIOCG80211NWID, &nwid) == 0) {
if (ssid == NULL)
retval = nwid.i_len;
else if (nwid.i_len > IF_SSIDLEN)
return 0;
}
+unsigned short
+if_vlanid(const struct interface *ifp)
+{
+#ifdef SIOCGETVLAN
+ struct vlanreq vlr;
+
+ memset(&vlr, 0, sizeof(vlr));
+ if (if_indirect_ioctl(ifp->ctx->pf_inet_fd,
+ ifp->name, SIOCGETVLAN, &vlr) != 0)
+ return 0; /* 0 means no VLANID */
+ return vlr.vlr_tag;
+#elif defined(SIOCGVNETID)
+ struct ifreq ifr;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
+ if (ioctl(ifp->ctx->pf_inet_fd, SIOCGVNETID, &ifr) != 0)
+ return 0; /* 0 means no VLANID */
+ return ifr.ifr_vnetid;
+#else
+ UNUSED(ifp);
+ return 0; /* 0 means no VLANID */
+#endif
+}
+
static void
get_addrs(int type, const void *data, const struct sockaddr **sa)
{
#include <asm/types.h> /* Needed for 2.4 kernels */
#include <sys/types.h>
-#include <sys/socket.h>
#include <sys/ioctl.h>
+#include <sys/socket.h>
#include <sys/param.h>
#include <linux/if_addr.h>
#include <linux/if_link.h>
#include <linux/if_packet.h>
+#include <linux/if_vlan.h>
#include <linux/filter.h>
#include <linux/netlink.h>
+#include <linux/sockios.h>
#include <linux/rtnetlink.h>
#include <arpa/inet.h>
return 0;
}
+unsigned short
+if_vlanid(const struct interface *ifp)
+{
+ struct vlan_ioctl_args v;
+
+ memset(&v, 0, sizeof(v));
+ strlcpy(v.device1, ifp->name, sizeof(v.device1));
+ v.cmd = GET_VLAN_VID_CMD;
+ if (ioctl(ifp->ctx->pf_inet_fd, SIOCSIFVLAN, &v) != 0)
+ return 0; /* 0 means no VLANID */
+ return (unsigned short)v.u.VID;
+}
+
static int
_open_link_socket(struct sockaddr_nl *nl, int protocol)
{
return -1;
}
+unsigned short
+if_vlanid(__unused const struct interface *ifp)
+{
+
+ return 0;
+}
+
int
if_vimaster(__unused const struct dhcpcd_ctx *ctx, __unused const char *ifname)
{
}
}
+ ifp->vlanid = if_vlanid(ifp);
+
#ifdef SIOCGIFPRIORITY
/* Respect the interface priority */
memset(&ifr, 0, sizeof(ifr));
int if_init(struct interface *);
int if_getssid(struct interface *);
int if_vimaster(const struct dhcpcd_ctx *ctx, const char *);
+unsigned short if_vlanid(const struct interface *);
int if_opensockets(struct dhcpcd_ctx *);
int if_opensockets_os(struct dhcpcd_ctx *);
void if_closesockets(struct dhcpcd_ctx *);