Module Name: src Committed By: msaitoh Date: Wed Oct 11 08:10:00 UTC 2017
Modified Files: src/sys/net: if_vlan.c Log Message: Check if VLAN ID isn't duplicated on a same parent interface and return EEXIST if it failed. To generate a diff of this commit: cvs rdiff -u -r1.100 -r1.101 src/sys/net/if_vlan.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/net/if_vlan.c diff -u src/sys/net/if_vlan.c:1.100 src/sys/net/if_vlan.c:1.101 --- src/sys/net/if_vlan.c:1.100 Tue Sep 26 07:42:06 2017 +++ src/sys/net/if_vlan.c Wed Oct 11 08:10:00 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: if_vlan.c,v 1.100 2017/09/26 07:42:06 knakahara Exp $ */ +/* $NetBSD: if_vlan.c,v 1.101 2017/10/11 08:10:00 msaitoh Exp $ */ /*- * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc. @@ -78,7 +78,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.100 2017/09/26 07:42:06 knakahara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.101 2017/10/11 08:10:00 msaitoh Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -386,10 +386,12 @@ vlan_config(struct ifvlan *ifv, struct i struct ifnet *ifp = &ifv->ifv_if; struct ifvlan_linkmib *nmib = NULL; struct ifvlan_linkmib *omib = NULL; + struct ifvlan_linkmib *checkmib = NULL; struct psref_target *nmib_psref = NULL; int error = 0; int idx; bool omib_cleanup = false; + struct psref psref; nmib = kmem_alloc(sizeof(*nmib), KM_SLEEP); @@ -401,6 +403,14 @@ vlan_config(struct ifvlan *ifv, struct i goto done; } + /* Duplicate check */ + checkmib = vlan_lookup_tag_psref(p, tag, &psref); + if (checkmib != NULL) { + vlan_putref_linkmib(checkmib, &psref); + error = EEXIST; + goto done; + } + *nmib = *omib; nmib_psref = &nmib->ifvm_psref; @@ -410,6 +420,7 @@ vlan_config(struct ifvlan *ifv, struct i case IFT_ETHER: { struct ethercom *ec = (void *) p; + struct vlanidlist *vidmem; nmib->ifvm_msw = &vlan_ether_multisw; nmib->ifvm_encaplen = ETHER_VLAN_ENCAP_LEN; nmib->ifvm_mintu = ETHERMIN; @@ -433,7 +444,14 @@ vlan_config(struct ifvlan *ifv, struct i } error = 0; } - + vidmem = kmem_alloc(sizeof(struct vlanidlist), KM_SLEEP); + if (vidmem == NULL){ + ec->ec_nvlans--; + error = ENOMEM; + goto done; + } + vidmem->vid = tag; + SLIST_INSERT_HEAD(&ec->ec_vids, vidmem, vid_list); /* * If the parent interface can do hardware-assisted * VLAN encapsulation, then propagate its hardware- @@ -555,6 +573,15 @@ vlan_unconfig_locked(struct ifvlan *ifv, case IFT_ETHER: { struct ethercom *ec = (void *)p; + struct vlanidlist *vlanidp, *tmpp; + + SLIST_FOREACH_SAFE(vlanidp, &ec->ec_vids, vid_list, tmpp) { + if (vlanidp->vid == nmib->ifvm_tag) { + SLIST_REMOVE(&ec->ec_vids, vlanidp, vlanidlist, + vid_list); + kmem_free(vlanidp, sizeof(*vlanidp)); + } + } if (--ec->ec_nvlans == 0) (void)ether_disable_vlan_mtu(p);