Changeset View
Changeset View
Standalone View
Standalone View
sys/netlink/netlink_module.c
Show All 20 Lines | |||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
* SUCH DAMAGE. | * SUCH DAMAGE. | ||||
*/ | */ | ||||
#include "opt_netlink.h" | |||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/module.h> | #include <sys/module.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/rmlock.h> | #include <sys/rmlock.h> | ||||
#include <sys/ck.h> | #include <sys/ck.h> | ||||
#include <sys/syslog.h> | #include <sys/syslog.h> | ||||
#include <netlink/netlink.h> | #include <netlink/netlink.h> | ||||
#include <netlink/netlink_ctl.h> | #include <netlink/netlink_ctl.h> | ||||
#include <netlink/netlink_var.h> | #include <netlink/netlink_var.h> | ||||
#include <machine/atomic.h> | #include <machine/atomic.h> | ||||
MALLOC_DEFINE(M_NETLINK, "netlink", "Memory used for netlink packets"); | |||||
FEATURE(netlink, "Netlink support"); | FEATURE(netlink, "Netlink support"); | ||||
#define DEBUG_MOD_NAME nl_mod | #define DEBUG_MOD_NAME nl_mod | ||||
#define DEBUG_MAX_LEVEL LOG_DEBUG3 | #define DEBUG_MAX_LEVEL LOG_DEBUG3 | ||||
#include <netlink/netlink_debug.h> | #include <netlink/netlink_debug.h> | ||||
_DECLARE_DEBUG(LOG_DEBUG); | _DECLARE_DEBUG(LOG_DEBUG); | ||||
SYSCTL_NODE(_net, OID_AUTO, netlink, CTLFLAG_RD, 0, ""); | |||||
SYSCTL_NODE(_net_netlink, OID_AUTO, debug, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, ""); | |||||
#define NL_MAX_HANDLERS 20 | #define NL_MAX_HANDLERS 20 | ||||
struct nl_proto_handler _nl_handlers[NL_MAX_HANDLERS]; | struct nl_proto_handler _nl_handlers[NL_MAX_HANDLERS]; | ||||
struct nl_proto_handler *nl_handlers = _nl_handlers; | struct nl_proto_handler *nl_handlers = _nl_handlers; | ||||
CK_LIST_HEAD(nl_control_head, nl_control); | CK_LIST_HEAD(nl_control_head, nl_control); | ||||
static struct nl_control_head vnets_head = CK_LIST_HEAD_INITIALIZER(); | static struct nl_control_head vnets_head = CK_LIST_HEAD_INITIALIZER(); | ||||
▲ Show 20 Lines • Show All 105 Lines • ▼ Show 20 Lines | netlink_unregister_proto(int proto) | ||||
KASSERT((nl_handlers[proto].cb != NULL), ("netlink handler %d is not set", proto)); | KASSERT((nl_handlers[proto].cb != NULL), ("netlink handler %d is not set", proto)); | ||||
nl_handlers[proto].cb = NULL; | nl_handlers[proto].cb = NULL; | ||||
nl_handlers[proto].proto_name = NULL; | nl_handlers[proto].proto_name = NULL; | ||||
NL_GLOBAL_UNLOCK(); | NL_GLOBAL_UNLOCK(); | ||||
NL_LOG(LOG_DEBUG2, "Unregistered netlink proto %d handler", proto); | NL_LOG(LOG_DEBUG2, "Unregistered netlink proto %d handler", proto); | ||||
return (true); | return (true); | ||||
} | } | ||||
#if !defined(NETLINK) && defined(NETLINK_MODULE) | |||||
/* Non-stub function provider */ | |||||
const static struct nl_function_wrapper nl_module = { | |||||
.nlmsg_add = _nlmsg_add, | |||||
.nlmsg_refill_buffer = _nlmsg_refill_buffer, | |||||
.nlmsg_flush = _nlmsg_flush, | |||||
.nlmsg_end = _nlmsg_end, | |||||
.nlmsg_abort = _nlmsg_abort, | |||||
.nlmsg_get_unicast_writer = _nlmsg_get_unicast_writer, | |||||
.nlmsg_get_group_writer = _nlmsg_get_group_writer, | |||||
.nlmsg_get_chain_writer = _nlmsg_get_chain_writer, | |||||
.nlmsg_end_dump = _nlmsg_end_dump, | |||||
}; | |||||
#endif | |||||
static bool | static bool | ||||
can_unload(void) | can_unload(void) | ||||
{ | { | ||||
struct nl_control *ctl; | struct nl_control *ctl; | ||||
bool result = true; | bool result = true; | ||||
NL_GLOBAL_LOCK(); | NL_GLOBAL_LOCK(); | ||||
Show All 14 Lines | |||||
static int | static int | ||||
netlink_modevent(module_t mod __unused, int what, void *priv __unused) | netlink_modevent(module_t mod __unused, int what, void *priv __unused) | ||||
{ | { | ||||
int ret = 0; | int ret = 0; | ||||
switch (what) { | switch (what) { | ||||
case MOD_LOAD: | case MOD_LOAD: | ||||
NL_LOG(LOG_DEBUG2, "Loading"); | NL_LOG(LOG_DEBUG2, "Loading"); | ||||
#if !defined(NETLINK) && defined(NETLINK_MODULE) | |||||
nl_set_functions(&nl_module); | |||||
#endif | |||||
break; | break; | ||||
case MOD_UNLOAD: | case MOD_UNLOAD: | ||||
NL_LOG(LOG_DEBUG2, "Unload called"); | NL_LOG(LOG_DEBUG2, "Unload called"); | ||||
if (can_unload()) { | if (can_unload()) { | ||||
NL_LOG(LOG_WARNING, "unloading"); | NL_LOG(LOG_WARNING, "unloading"); | ||||
netlink_unloading = 1; | netlink_unloading = 1; | ||||
#if !defined(NETLINK) && defined(NETLINK_MODULE) | |||||
nl_set_functions(NULL); | |||||
#endif | |||||
} else | } else | ||||
ret = EBUSY; | ret = EBUSY; | ||||
break; | break; | ||||
default: | default: | ||||
ret = EOPNOTSUPP; | ret = EOPNOTSUPP; | ||||
break; | break; | ||||
} | } | ||||
return (ret); | return (ret); | ||||
} | } | ||||
static moduledata_t netlink_mod = { "netlink", netlink_modevent, NULL }; | static moduledata_t netlink_mod = { "netlink", netlink_modevent, NULL }; | ||||
DECLARE_MODULE(netlink, netlink_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); | DECLARE_MODULE(netlink, netlink_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); | ||||
MODULE_VERSION(netlink, 1); | MODULE_VERSION(netlink, 1); |