-/* $OpenBSD: if_vlan.c,v 1.172 2017/05/29 06:44:54 mpi Exp $ */
+/* $OpenBSD: if_vlan.c,v 1.173 2017/05/31 05:14:51 dlg Exp $ */
/*
* Copyright 1998 Massachusetts Institute of Technology
void vlan_link_state(struct ifvlan *, u_char, u_int64_t);
int vlan_set_vnetid(struct ifvlan *, uint16_t);
+int vlan_set_parent(struct ifvlan *, const char *);
+int vlan_del_parent(struct ifvlan *);
int vlan_inuse(uint16_t, unsigned int, uint16_t);
int vlan_inuse_locked(uint16_t, unsigned int, uint16_t);
/* parent is fine, let's prepare the ifv to handle packets */
ifp->if_hardmtu = hardmtu;
SET(ifp->if_flags, ifp0->if_flags & IFF_SIMPLEX);
- if (!ISSET(ifv->ifv_flags, IFVF_LLADDR))
- if_setlladdr(ifp, LLADDR(ifp0->if_sadl));
if (ifv->ifv_type != ETHERTYPE_VLAN) {
/*
rw_exit(&vlan_tagh_lk);
scrub:
ifp->if_capabilities = 0;
- if (!ISSET(ifv->ifv_flags, IFVF_LLADDR))
- if_setlladdr(ifp, etheranyaddr);
CLR(ifp->if_flags, IFF_SIMPLEX);
ifp->if_hardmtu = 0xffff;
put:
rw_exit_write(&vlan_tagh_lk);
ifp->if_capabilities = 0;
- if (!ISSET(ifv->ifv_flags, IFVF_LLADDR))
- if_setlladdr(ifp, etheranyaddr);
CLR(ifp->if_flags, IFF_SIMPLEX);
ifp->if_hardmtu = 0xffff;
break;
case SIOCSIFPARENT:
- if (ISSET(ifp->if_flags, IFF_RUNNING)) {
- error = EBUSY;
- break;
- }
-
- ifp0 = ifunit(parent->ifp_parent);
- if (ifp0 == NULL) {
- error = EINVAL;
- break;
- }
-
- if (ifv->ifv_ifp0 == ifp0->if_index) {
- /* nop */
- break;
- }
-
- if (ifp0->if_type != IFT_ETHER) {
- error = EPROTONOSUPPORT;
- break;
- }
-
- error = vlan_inuse(ifv->ifv_type, ifp0->if_index, ifv->ifv_tag);
- if (error != 0)
- break;
-
- ifv->ifv_ifp0 = ifp0->if_index;
+ error = vlan_set_parent(ifv, parent->ifp_parent);
break;
case SIOCGIFPARENT:
break;
case SIOCDIFPARENT:
- if (ISSET(ifp->if_flags, IFF_RUNNING)) {
- error = EBUSY;
- break;
- }
-
- ifv->ifv_ifp0 = 0;
+ error = vlan_del_parent(ifv);
break;
case SIOCADDMULTI:
{
struct ifnet *ifp = &ifv->ifv_if;;
struct ifnet *ifp0;
- int flag = IFVF_LLADDR;
-
- /* setting the mac addr to 00:00:00:00:00:00 means reset lladdr */
- if (memcmp(ifr->ifr_addr.sa_data, etheranyaddr, ETHER_ADDR_LEN) == 0)
- flag = 0;
+ uint8_t lladdr[ETHER_ADDR_LEN];
+ int flag;
- if (ISSET(ifv->ifv_flags, IFVF_LLADDR) == flag)
- return (0);
+ memcpy(lladdr, ifr->ifr_addr.sa_data, sizeof(lladdr));
- /* if we're up and the mac is reset, inherit the parents mac */
- if (ISSET(ifp->if_flags, IFF_RUNNING) && flag == 0) {
+ /* setting the mac addr to 00:00:00:00:00:00 means reset lladdr */
+ if (memcmp(lladdr, etheranyaddr, sizeof(lladdr)) == 0) {
ifp0 = if_get(ifv->ifv_ifp0);
if (ifp0 != NULL)
- if_setlladdr(ifp, LLADDR(ifp0->if_sadl));
+ memcpy(lladdr, LLADDR(ifp0->if_sadl), sizeof(lladdr));
if_put(ifp0);
+
+ flag = 0;
+ } else
+ flag = IFVF_LLADDR;
+
+ if (memcmp(lladdr, LLADDR(ifp->if_sadl), sizeof(lladdr)) == 0 &&
+ ISSET(ifv->ifv_flags, IFVF_LLADDR) == flag) {
+ /* nop */
+ return (0);
}
+ /* commit */
+ if_setlladdr(ifp, lladdr);
CLR(ifv->ifv_flags, IFVF_LLADDR);
SET(ifv->ifv_flags, flag);
return (error);
}
+int
+vlan_set_parent(struct ifvlan *ifv, const char *parent)
+{
+ struct ifnet *ifp = &ifv->ifv_if;
+ struct ifnet *ifp0;
+ int error = 0;
+
+ ifp0 = ifunit(parent); /* doesn't need an if_put */
+ if (ifp0 == NULL)
+ return (EINVAL);
+
+ if (ifp0->if_type != IFT_ETHER)
+ return (EPROTONOSUPPORT);
+
+ if (ifv->ifv_ifp0 == ifp0->if_index) {
+ /* nop */
+ return (0);
+ }
+
+ if (ISSET(ifp->if_flags, IFF_RUNNING))
+ return (EBUSY);
+
+ error = vlan_inuse(ifv->ifv_type, ifp0->if_index, ifv->ifv_tag);
+ if (error != 0)
+ return (error);
+
+ /* commit */
+ ifv->ifv_ifp0 = ifp0->if_index;
+ if (!ISSET(ifv->ifv_flags, IFVF_LLADDR))
+ if_setlladdr(ifp, LLADDR(ifp0->if_sadl));
+
+ return (0);
+}
+
+int
+vlan_del_parent(struct ifvlan *ifv)
+{
+ struct ifnet *ifp = &ifv->ifv_if;
+
+ if (ISSET(ifp->if_flags, IFF_RUNNING))
+ return (EBUSY);
+
+ /* commit */
+ ifv->ifv_ifp0 = 0;
+ if (!ISSET(ifv->ifv_flags, IFVF_LLADDR))
+ if_setlladdr(ifp, etheranyaddr);
+
+ return (0);
+}
+
int
vlan_set_compat(struct ifnet *ifp, struct ifreq *ifr)
{