-/* $OpenBSD: if_tun.c,v 1.138 2015/04/29 16:00:06 deraadt Exp $ */
+/* $OpenBSD: if_tun.c,v 1.139 2015/04/30 15:19:50 mpi Exp $ */
/* $NetBSD: if_tun.c,v 1.24 1996/05/07 02:40:48 thorpej Exp $ */
/*
void tun_wakeup(struct tun_softc *);
int tun_switch(struct tun_softc *, int);
+void tun_ifattach(struct ifnet *, int);
+void tun_ifdetach(struct ifnet *);
int tuninit(struct tun_softc *);
int filt_tunread(struct knote *, long);
int filt_tunwrite(struct knote *, long);
return (tun_create(ifc, unit, 0));
}
-int
-tun_create(struct if_clone *ifc, int unit, int flags)
+void
+tun_ifattach(struct ifnet *ifp, int flags)
{
- struct tun_softc *tp;
- struct ifnet *ifp;
+ struct tun_softc *tp = ifp->if_softc;
int s;
- tp = malloc(sizeof(*tp), M_DEVBUF, M_NOWAIT|M_ZERO);
- if (!tp)
- return (ENOMEM);
-
- tp->tun_unit = unit;
- tp->tun_flags = TUN_INITED|TUN_STAYUP;
-
- ifp = &tp->tun_if;
- snprintf(ifp->if_xname, sizeof ifp->if_xname, "%s%d", ifc->ifc_name,
- unit);
- ether_fakeaddr(ifp);
-
- ifp->if_softc = tp;
ifp->if_ioctl = tun_ioctl;
ifp->if_output = tun_output;
ifp->if_start = tunstart;
if_attach(ifp);
ether_ifattach(ifp);
}
- /* force output function to our function */
- ifp->if_output = tun_output;
s = splnet();
LIST_INSERT_HEAD(&tun_softc_list, tp, tun_list);
pipex_iface_init(&tp->pipex_iface, ifp);
#endif
- return (0);
}
-int
-tun_clone_destroy(struct ifnet *ifp)
+void
+tun_ifdetach(struct ifnet *ifp)
{
struct tun_softc *tp = ifp->if_softc;
int s;
ether_ifdetach(ifp);
if_detach(ifp);
+}
+
+int
+tun_create(struct if_clone *ifc, int unit, int flags)
+{
+ struct tun_softc *tp;
+ struct ifnet *ifp;
+
+ tp = malloc(sizeof(*tp), M_DEVBUF, M_NOWAIT|M_ZERO);
+ if (tp == NULL)
+ return (ENOMEM);
+
+ tp->tun_unit = unit;
+ tp->tun_flags = TUN_INITED|TUN_STAYUP;
+
+ ifp = &tp->tun_if;
+ snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d", ifc->ifc_name,
+ unit);
+ ether_fakeaddr(ifp);
+ ifp->if_softc = tp;
+
+ tun_ifattach(ifp, flags);
+
+ return (0);
+}
+
+int
+tun_clone_destroy(struct ifnet *ifp)
+{
+ struct tun_softc *tp = ifp->if_softc;
+
+ tun_ifdetach(ifp);
free(tp, M_DEVBUF, 0);
return (0);
tun_switch(struct tun_softc *tp, int flags)
{
struct ifnet *ifp = &tp->tun_if;
- int unit, open, r, s;
+ int unit, open, s;
struct ifg_list *ifgl;
u_int ifgr_len;
char *ifgrpnames, *p;
}
}
- /* remove old device and ... */
- tun_clone_destroy(ifp);
- /* attach new interface */
- r = tun_create(&tun_cloner, unit, flags);
+ if (ifp->if_flags & IFF_UP)
+ if_down(ifp);
- if (r == 0) {
- if ((tp = tun_lookup(unit)) == NULL) {
- /* this should never fail */
- r = ENXIO;
- goto abort;
- }
+ tun_ifdetach(ifp);
+ tun_ifattach(ifp, flags);
- /* rejoin groups */
- ifp = &tp->tun_if;
- for (p = ifgrpnames; p && *p; p += IFNAMSIZ)
- if_addgroup(ifp, p);
- }
- if (open && r == 0) {
+ /* rejoin groups */
+ for (p = ifgrpnames; p && *p; p += IFNAMSIZ)
+ if_addgroup(ifp, p);
+
+ if (open) {
/* already opened before ifconfig tunX link0 */
s = splnet();
tp->tun_flags |= open;
splx(s);
TUNDEBUG(("%s: already open\n", tp->tun_if.if_xname));
}
- abort:
if (ifgrpnames)
free(ifgrpnames, M_TEMP, 0);
- return (r);
+
+ return (0);
}
/*