version 1.30.6.3, 2007/12/09 19:38:34 |
version 1.31, 2007/08/26 22:59:08 |
|
|
* Copyright (c) 2003, 2004 The NetBSD Foundation. |
* Copyright (c) 2003, 2004 The NetBSD Foundation. |
* All rights reserved. |
* All rights reserved. |
* |
* |
|
* This code is derived from software contributed to the NetBSD Foundation |
|
* by Quentin Garnier. |
|
* |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* modification, are permitted provided that the following conditions |
* are met: |
* are met: |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* documentation and/or other materials provided with the distribution. |
* 3. Neither the name of The NetBSD Foundation nor the names of its |
* 3. All advertising materials mentioning features or use of this software |
|
* must display the following acknowledgement: |
|
* This product includes software developed by the NetBSD |
|
* Foundation, Inc. and its contributors. |
|
* 4. Neither the name of The NetBSD Foundation nor the names of its |
* contributors may be used to endorse or promote products derived |
* contributors may be used to endorse or promote products derived |
* from this software without specific prior written permission. |
* from this software without specific prior written permission. |
* |
* |
Line 56 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 63 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <sys/sockio.h> |
#include <sys/sockio.h> |
#include <sys/sysctl.h> |
#include <sys/sysctl.h> |
#include <sys/kauth.h> |
#include <sys/kauth.h> |
#include <sys/mutex.h> |
|
|
|
#include <net/if.h> |
#include <net/if.h> |
#include <net/if_dl.h> |
#include <net/if_dl.h> |
Line 106 struct tap_softc { |
|
Line 112 struct tap_softc { |
|
#define TAP_GOING 0x00000008 /* interface is being destroyed */ |
#define TAP_GOING 0x00000008 /* interface is being destroyed */ |
struct selinfo sc_rsel; |
struct selinfo sc_rsel; |
pid_t sc_pgid; /* For async. IO */ |
pid_t sc_pgid; /* For async. IO */ |
kmutex_t sc_rdlock; |
struct lock sc_rdlock; |
struct simplelock sc_kqlock; |
struct simplelock sc_kqlock; |
}; |
}; |
|
|
Line 345 tap_attach(struct device *parent, struct |
|
Line 351 tap_attach(struct device *parent, struct |
|
* to be protected, too, but we don't need the same level of |
* to be protected, too, but we don't need the same level of |
* complexity for that lock, so a simple spinning lock is fine. |
* complexity for that lock, so a simple spinning lock is fine. |
*/ |
*/ |
mutex_init(&sc->sc_rdlock, MUTEX_DEFAULT, IPL_NONE); |
lockinit(&sc->sc_rdlock, PSOCK|PCATCH, "tapl", 0, LK_SLEEPFAIL); |
simple_lock_init(&sc->sc_kqlock); |
simple_lock_init(&sc->sc_kqlock); |
} |
} |
|
|
Line 360 tap_detach(struct device* self, int flag |
|
Line 366 tap_detach(struct device* self, int flag |
|
struct ifnet *ifp = &sc->sc_ec.ec_if; |
struct ifnet *ifp = &sc->sc_ec.ec_if; |
int error, s; |
int error, s; |
|
|
|
/* |
|
* Some processes might be sleeping on "tap", so we have to make |
|
* them release their hold on the device. |
|
* |
|
* The LK_DRAIN operation will wait for every locked process to |
|
* release their hold. |
|
*/ |
sc->sc_flags |= TAP_GOING; |
sc->sc_flags |= TAP_GOING; |
s = splnet(); |
s = splnet(); |
tap_stop(ifp, 1); |
tap_stop(ifp, 1); |
if_down(ifp); |
if_down(ifp); |
splx(s); |
splx(s); |
|
lockmgr(&sc->sc_rdlock, LK_DRAIN, NULL); |
|
|
/* |
/* |
* Destroying a single leaf is a very straightforward operation using |
* Destroying a single leaf is a very straightforward operation using |
Line 378 tap_detach(struct device* self, int flag |
|
Line 392 tap_detach(struct device* self, int flag |
|
ether_ifdetach(ifp); |
ether_ifdetach(ifp); |
if_detach(ifp); |
if_detach(ifp); |
ifmedia_delete_instance(&sc->sc_im, IFM_INST_ANY); |
ifmedia_delete_instance(&sc->sc_im, IFM_INST_ANY); |
mutex_destroy(&sc->sc_rdlock); |
|
|
|
return (0); |
return (0); |
} |
} |
Line 515 tap_lifaddr(struct ifnet *ifp, u_long cm |
|
Line 528 tap_lifaddr(struct ifnet *ifp, u_long cm |
|
if (sa->sa_family != AF_LINK) |
if (sa->sa_family != AF_LINK) |
return (EINVAL); |
return (EINVAL); |
|
|
(void)sockaddr_dl_setaddr(ifp->if_sadl, ifp->if_sadl->sdl_len, |
memcpy(LLADDR(ifp->if_sadl), sa->sa_data, ETHER_ADDR_LEN); |
sa->sa_data, ETHER_ADDR_LEN); |
|
|
|
return (0); |
return (0); |
} |
} |
Line 831 tap_dev_read(int unit, struct uio *uio, |
|
Line 843 tap_dev_read(int unit, struct uio *uio, |
|
/* |
/* |
* In the TAP_NBIO case, we have to make sure we won't be sleeping |
* In the TAP_NBIO case, we have to make sure we won't be sleeping |
*/ |
*/ |
if ((sc->sc_flags & TAP_NBIO) != 0) { |
if ((sc->sc_flags & TAP_NBIO) && |
if (!mutex_tryenter(&sc->sc_rdlock)) |
lockstatus(&sc->sc_rdlock) == LK_EXCLUSIVE) |
return (EWOULDBLOCK); |
return (EWOULDBLOCK); |
} else { |
error = lockmgr(&sc->sc_rdlock, LK_EXCLUSIVE, NULL); |
mutex_enter(&sc->sc_rdlock); |
if (error != 0) |
} |
return (error); |
|
|
s = splnet(); |
s = splnet(); |
if (IFQ_IS_EMPTY(&ifp->if_snd)) { |
if (IFQ_IS_EMPTY(&ifp->if_snd)) { |
Line 846 tap_dev_read(int unit, struct uio *uio, |
|
Line 858 tap_dev_read(int unit, struct uio *uio, |
|
* We must release the lock before sleeping, and re-acquire it |
* We must release the lock before sleeping, and re-acquire it |
* after. |
* after. |
*/ |
*/ |
mutex_exit(&sc->sc_rdlock); |
(void)lockmgr(&sc->sc_rdlock, LK_RELEASE, NULL); |
if (sc->sc_flags & TAP_NBIO) |
if (sc->sc_flags & TAP_NBIO) |
error = EWOULDBLOCK; |
error = EWOULDBLOCK; |
else |
else |
error = tsleep(sc, PSOCK|PCATCH, "tap", 0); |
error = tsleep(sc, PSOCK|PCATCH, "tap", 0); |
|
|
if (error != 0) |
if (error != 0) |
return (error); |
return (error); |
/* The device might have been downed */ |
/* The device might have been downed */ |
if ((ifp->if_flags & IFF_UP) == 0) |
if ((ifp->if_flags & IFF_UP) == 0) |
return (EHOSTDOWN); |
return (EHOSTDOWN); |
if ((sc->sc_flags & TAP_NBIO)) { |
if ((sc->sc_flags & TAP_NBIO) && |
if (!mutex_tryenter(&sc->sc_rdlock)) |
lockstatus(&sc->sc_rdlock) == LK_EXCLUSIVE) |
return (EWOULDBLOCK); |
return (EWOULDBLOCK); |
} else { |
error = lockmgr(&sc->sc_rdlock, LK_EXCLUSIVE, NULL); |
mutex_enter(&sc->sc_rdlock); |
if (error != 0) |
} |
return (error); |
s = splnet(); |
s = splnet(); |
} |
} |
|
|
Line 893 tap_dev_read(int unit, struct uio *uio, |
|
Line 906 tap_dev_read(int unit, struct uio *uio, |
|
m_freem(m); |
m_freem(m); |
|
|
out: |
out: |
mutex_exit(&sc->sc_rdlock); |
(void)lockmgr(&sc->sc_rdlock, LK_RELEASE, NULL); |
return (error); |
return (error); |
} |
} |
|
|
Line 1121 tap_dev_kqfilter(int unit, struct knote |
|
Line 1134 tap_dev_kqfilter(int unit, struct knote |
|
kn->kn_fop = &tap_seltrue_filterops; |
kn->kn_fop = &tap_seltrue_filterops; |
break; |
break; |
default: |
default: |
return (EINVAL); |
return (1); |
} |
} |
|
|
kn->kn_hook = sc; |
kn->kn_hook = sc; |
Line 1269 tap_sysctl_handler(SYSCTLFN_ARGS) |
|
Line 1282 tap_sysctl_handler(SYSCTLFN_ARGS) |
|
int error; |
int error; |
size_t len; |
size_t len; |
char addr[3 * ETHER_ADDR_LEN]; |
char addr[3 * ETHER_ADDR_LEN]; |
uint8_t enaddr[ETHER_ADDR_LEN]; |
|
|
|
node = *rnode; |
node = *rnode; |
sc = node.sysctl_data; |
sc = node.sysctl_data; |
Line 1285 tap_sysctl_handler(SYSCTLFN_ARGS) |
|
Line 1297 tap_sysctl_handler(SYSCTLFN_ARGS) |
|
return (EINVAL); |
return (EINVAL); |
|
|
/* Commit change */ |
/* Commit change */ |
if (ether_nonstatic_aton(enaddr, addr) != 0 || |
if (ether_nonstatic_aton(LLADDR(ifp->if_sadl), addr) != 0) |
sockaddr_dl_setaddr(ifp->if_sadl, ifp->if_sadl->sdl_len, enaddr, |
|
ETHER_ADDR_LEN) == NULL) |
|
return (EINVAL); |
return (EINVAL); |
return (error); |
return (error); |
} |
} |