diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2003-12-03 14:55:59 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2003-12-03 14:55:59 +0000 |
commit | df5bbc914d2ca35493ec7cacf0c23ad043634b10 (patch) | |
tree | 4a6e623275717b228e6b441339d35d989753dd68 /sys/net | |
parent | e90c50ef1e680cf6d41ba406eb0e767bbfef0fbd (diff) |
add support for ifconfig clone/destroy; ok henning deraadt
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/if_bridge.c | 126 | ||||
-rw-r--r-- | sys/net/if_bridge.h | 3 | ||||
-rw-r--r-- | sys/net/if_vlan.c | 113 | ||||
-rw-r--r-- | sys/net/if_vlan_var.h | 3 |
4 files changed, 163 insertions, 82 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 23d83c3315b..81a53cb7ac4 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bridge.c,v 1.125 2003/10/02 05:50:34 itojun Exp $ */ +/* $OpenBSD: if_bridge.c,v 1.126 2003/12/03 14:55:58 markus Exp $ */ /* * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) @@ -122,9 +122,6 @@ extern int ifqmaxlen; -struct bridge_softc *bridgectl; -int nbridge; - void bridgeattach(int); int bridge_ioctl(struct ifnet *, u_long, caddr_t); void bridge_start(struct ifnet *); @@ -169,6 +166,8 @@ void bridge_send_icmp_err(struct bridge_softc *, struct ifnet *, #ifdef IPSEC int bridge_ipsec(int, int, int, struct mbuf *); #endif +int bridge_clone_create(struct if_clone *, int); +void bridge_clone_destroy(struct ifnet *ifp); #define ETHERADDR_IS_IP_MCAST(a) \ /* struct etheraddr *a; */ \ @@ -176,47 +175,97 @@ int bridge_ipsec(int, int, int, struct mbuf *); (a)->ether_addr_octet[1] == 0x00 && \ (a)->ether_addr_octet[2] == 0x5e) +LIST_HEAD(, bridge_softc) bridge_list; + +struct if_clone bridge_cloner = + IF_CLONE_INITIALIZER("bridge", bridge_clone_create, bridge_clone_destroy); + +/* ARGSUSED */ void bridgeattach(int n) { + LIST_INIT(&bridge_list); + if_clone_attach(&bridge_cloner); +} + +int +bridge_clone_create(struct if_clone *ifc, int unit) +{ struct bridge_softc *sc; struct ifnet *ifp; - int i; + int s; - bridgectl = malloc(n * sizeof(*sc), M_DEVBUF, M_NOWAIT); - if (!bridgectl) - return; - nbridge = n; - bzero(bridgectl, n * sizeof(*sc)); - for (sc = bridgectl, i = 0; i < nbridge; i++, sc++) { - - sc->sc_brtmax = BRIDGE_RTABLE_MAX; - sc->sc_brttimeout = BRIDGE_RTABLE_TIMEOUT; - sc->sc_bridge_max_age = BSTP_DEFAULT_MAX_AGE; - sc->sc_bridge_hello_time = BSTP_DEFAULT_HELLO_TIME; - sc->sc_bridge_forward_delay= BSTP_DEFAULT_FORWARD_DELAY; - sc->sc_bridge_priority = BSTP_DEFAULT_BRIDGE_PRIORITY; - sc->sc_hold_time = BSTP_DEFAULT_HOLD_TIME; - timeout_set(&sc->sc_brtimeout, bridge_timer, sc); - LIST_INIT(&sc->sc_iflist); - LIST_INIT(&sc->sc_spanlist); - ifp = &sc->sc_if; - snprintf(ifp->if_xname, sizeof ifp->if_xname, "bridge%d", i); - ifp->if_softc = sc; - ifp->if_mtu = ETHERMTU; - ifp->if_ioctl = bridge_ioctl; - ifp->if_output = bridge_output; - ifp->if_start = bridge_start; - ifp->if_type = IFT_BRIDGE; - ifp->if_snd.ifq_maxlen = ifqmaxlen; - ifp->if_hdrlen = sizeof(struct ether_header); - if_attach(ifp); - if_alloc_sadl(ifp); + sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT); + if (!sc) + return (ENOMEM); + bzero(sc, sizeof(*sc)); + + sc->sc_brtmax = BRIDGE_RTABLE_MAX; + sc->sc_brttimeout = BRIDGE_RTABLE_TIMEOUT; + sc->sc_bridge_max_age = BSTP_DEFAULT_MAX_AGE; + sc->sc_bridge_hello_time = BSTP_DEFAULT_HELLO_TIME; + sc->sc_bridge_forward_delay= BSTP_DEFAULT_FORWARD_DELAY; + sc->sc_bridge_priority = BSTP_DEFAULT_BRIDGE_PRIORITY; + sc->sc_hold_time = BSTP_DEFAULT_HOLD_TIME; + timeout_set(&sc->sc_brtimeout, bridge_timer, sc); + LIST_INIT(&sc->sc_iflist); + LIST_INIT(&sc->sc_spanlist); + ifp = &sc->sc_if; + snprintf(ifp->if_xname, sizeof ifp->if_xname, "%s%d", ifc->ifc_name, + unit); + ifp->if_softc = sc; + ifp->if_mtu = ETHERMTU; + ifp->if_ioctl = bridge_ioctl; + ifp->if_output = bridge_output; + ifp->if_start = bridge_start; + ifp->if_type = IFT_BRIDGE; + ifp->if_snd.ifq_maxlen = ifqmaxlen; + ifp->if_hdrlen = sizeof(struct ether_header); + if_attach(ifp); + if_alloc_sadl(ifp); #if NBPFILTER > 0 - bpfattach(&sc->sc_if.if_bpf, ifp, - DLT_EN10MB, sizeof(struct ether_header)); + bpfattach(&sc->sc_if.if_bpf, ifp, + DLT_EN10MB, sizeof(struct ether_header)); #endif + s = splnet(); + LIST_INSERT_HEAD(&bridge_list, sc, sc_list); + splx(s); + + return (0); +} + +void +bridge_clone_destroy(struct ifnet *ifp) +{ + struct bridge_softc *sc = ifp->if_softc; + struct bridge_iflist *bif; + int s; + + bridge_stop(sc); + while ((bif = LIST_FIRST(&sc->sc_iflist)) != NULL) { + /* XXX shared with ioctl and detach */ + /* XXX promisc disable? */ + LIST_REMOVE(bif, next); + bridge_rtdelete(sc, bif->ifp, 0); + bridge_flushrule(bif); + bif->ifp->if_bridge = NULL; + free(bif, M_DEVBUF); + } + while ((bif = LIST_FIRST(&sc->sc_spanlist)) != NULL) { + LIST_REMOVE(bif, next); + free(bif, M_DEVBUF); } + + s = splnet(); + LIST_REMOVE(sc, sc_list); + splx(s); + +#if NBPFILTER > 0 + bpfdetach(ifp); +#endif + if_detach(ifp); + + free(sc, M_DEVBUF); } int @@ -1027,10 +1076,9 @@ bridgeintr(void) { struct bridge_softc *sc; struct mbuf *m; - int i, s; + int s; - for (i = 0; i < nbridge; i++) { - sc = &bridgectl[i]; + LIST_FOREACH(sc, &bridge_list, sc_list) { for (;;) { s = splimp(); IF_DEQUEUE(&sc->sc_if.if_snd, m); diff --git a/sys/net/if_bridge.h b/sys/net/if_bridge.h index 8e36e2076c3..1bbde37f079 100644 --- a/sys/net/if_bridge.h +++ b/sys/net/if_bridge.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bridge.h,v 1.25 2003/07/15 03:41:15 jason Exp $ */ +/* $OpenBSD: if_bridge.h,v 1.26 2003/12/03 14:55:58 markus Exp $ */ /* * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) @@ -235,6 +235,7 @@ struct bridge_rtnode { */ struct bridge_softc { struct ifnet sc_if; /* the interface */ + LIST_ENTRY(bridge_softc) sc_list; /* all bridges */ u_int64_t sc_designated_root; u_int64_t sc_bridge_id; struct bridge_iflist *sc_root_port; diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c index 990128f85bd..7b87936dcd5 100644 --- a/sys/net/if_vlan.c +++ b/sys/net/if_vlan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vlan.c,v 1.41 2003/08/15 20:32:19 tedu Exp $ */ +/* $OpenBSD: if_vlan.c,v 1.42 2003/12/03 14:55:58 markus Exp $ */ /* * Copyright 1998 Massachusetts Institute of Technology * @@ -79,10 +79,6 @@ #include <net/if_vlan_var.h> extern struct ifaddr **ifnet_addrs; - -struct ifvlan *ifv_softc; -int nifvlan; - extern int ifqmaxlen; void vlan_start (struct ifnet *ifp); @@ -95,40 +91,79 @@ int vlan_set_promisc (struct ifnet *ifp); int vlan_ether_addmulti(struct ifvlan *, struct ifreq *); int vlan_ether_delmulti(struct ifvlan *, struct ifreq *); void vlan_ether_purgemulti(struct ifvlan *); +int vlan_clone_create(struct if_clone *, int); +void vlan_clone_destroy(struct ifnet *); + +LIST_HEAD(, ifvlan) vlan_list; +struct if_clone vlan_cloner = + IF_CLONE_INITIALIZER("vlan", vlan_clone_create, vlan_clone_destroy); + +/* ARGSUSED */ void vlanattach(int count) { + LIST_INIT(&vlan_list); + if_clone_attach(&vlan_cloner); +} + +int +vlan_clone_create(struct if_clone *ifc, int unit) +{ + struct ifvlan *ifv; struct ifnet *ifp; - int i; + int s; + + ifv = malloc(sizeof(*ifv), M_DEVBUF, M_NOWAIT); + if (!ifv) + return (ENOMEM); + bzero(ifv, sizeof(*ifv)); + + LIST_INIT(&ifv->vlan_mc_listhead); + ifp = &ifv->ifv_if; + ifp->if_softc = ifv; + snprintf(ifp->if_xname, sizeof ifp->if_xname, "%s%d", ifc->ifc_name, + unit); + /* NB: flags are not set here */ + /* NB: mtu is not set here */ + + ifp->if_start = vlan_start; + ifp->if_ioctl = vlan_ioctl; + ifp->if_output = ether_output; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + IFQ_SET_READY(&ifp->if_snd); + if_attach(ifp); + ether_ifattach(ifp); + + /* Now undo some of the damage... */ + ifp->if_type = IFT_8021_VLAN; + ifp->if_hdrlen = EVL_ENCAPLEN; + + s = splnet(); + LIST_INSERT_HEAD(&vlan_list, ifv, ifv_list); + splx(s); - MALLOC(ifv_softc, struct ifvlan *, count * sizeof(struct ifvlan), - M_DEVBUF, M_NOWAIT); - if (ifv_softc == NULL) - panic("vlanattach: MALLOC failed"); - nifvlan = count; - bzero(ifv_softc, nifvlan * sizeof(struct ifvlan)); - - for (i = 0; i < nifvlan; i++) { - LIST_INIT(&ifv_softc[i].vlan_mc_listhead); - ifp = &ifv_softc[i].ifv_if; - ifp->if_softc = &ifv_softc[i]; - snprintf(ifp->if_xname, sizeof ifp->if_xname, "vlan%d", i); - /* NB: flags are not set here */ - /* NB: mtu is not set here */ - - ifp->if_start = vlan_start; - ifp->if_ioctl = vlan_ioctl; - ifp->if_output = ether_output; - IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); - IFQ_SET_READY(&ifp->if_snd); - if_attach(ifp); - ether_ifattach(ifp); - - /* Now undo some of the damage... */ - ifp->if_type = IFT_8021_VLAN; - ifp->if_hdrlen = EVL_ENCAPLEN; - } + return (0); +} + +void +vlan_clone_destroy(struct ifnet *ifp) +{ + struct ifvlan *ifv = ifp->if_softc; + int s; + + s = splnet(); + LIST_REMOVE(ifv, ifv_list); + splx(s); + + vlan_unconfig(ifp); +#if NBPFILTER > 0 + bpfdetach(ifp); +#endif + ether_ifdetach(ifp); + if_detach(ifp); + + free(ifv, M_DEVBUF); } void @@ -237,18 +272,16 @@ vlan_start(struct ifnet *ifp) int vlan_input_tag(struct mbuf *m, u_int16_t t) { - int i; struct ifvlan *ifv; struct ether_vlan_header vh; t = EVL_VLANOFTAG(t); - for (i = 0; i < nifvlan; i++) { - ifv = &ifv_softc[i]; + LIST_FOREACH(ifv, &vlan_list, ifv_list) { if (m->m_pkthdr.rcvif == ifv->ifv_p && t == ifv->ifv_tag) break; } - if (i >= nifvlan) { + if (ifv == NULL) { if (m->m_pkthdr.len < sizeof(struct ether_header)) { m_freem(m); return (-1); @@ -304,7 +337,6 @@ vlan_input(eh, m) struct ether_header *eh; struct mbuf *m; { - int i; struct ifvlan *ifv; u_int tag; struct ifnet *ifp = m->m_pkthdr.rcvif; @@ -317,13 +349,12 @@ vlan_input(eh, m) tag = EVL_VLANOFTAG(ntohs(*mtod(m, u_int16_t *))); - for (i = 0; i < nifvlan; i++) { - ifv = &ifv_softc[i]; + LIST_FOREACH(ifv, &vlan_list, ifv_list) { if (m->m_pkthdr.rcvif == ifv->ifv_p && tag == ifv->ifv_tag) break; } - if (i >= nifvlan || (ifv->ifv_if.if_flags & (IFF_UP|IFF_RUNNING)) != + if (ifv == NULL || (ifv->ifv_if.if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { m_freem(m); return -1; /* so ether_input can take note */ diff --git a/sys/net/if_vlan_var.h b/sys/net/if_vlan_var.h index 8c4882f87c2..d80e3dc838e 100644 --- a/sys/net/if_vlan_var.h +++ b/sys/net/if_vlan_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vlan_var.h,v 1.9 2003/02/01 00:14:40 chris Exp $ */ +/* $OpenBSD: if_vlan_var.h,v 1.10 2003/12/03 14:55:58 markus Exp $ */ /* * Copyright 1998 Massachusetts Institute of Technology @@ -54,6 +54,7 @@ struct ifvlan { u_int16_t ifvm_tag; /* tag to apply on packets leaving if */ } ifv_mib; LIST_HEAD(__vlan_mchead, vlan_mc_entry) vlan_mc_listhead; + LIST_ENTRY(ifvlan) ifv_list; /* all vlan interfaces */ int ifv_flags; }; |