net: sockev: Initial Commit
Added module which subscribes to socket notifier events. Notifier events are then converted to a multicast netlink message for user space applications to consume. CRs-Fixed: 626021 Change-Id: Id5c6808d972b69f5f065d7fba9094e75c6ad0b2c Signed-off-by: Harout Hedeshian <harouth@codeaurora.org> [subashab@codeaurora.org: resolve trivial merge conflicts] Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
This commit is contained in:
parent
d675b4b3d4
commit
274f3cfdd0
6 changed files with 182 additions and 1 deletions
|
@ -385,6 +385,7 @@ header-y += smiapp.h
|
|||
header-y += snmp.h
|
||||
header-y += sock_diag.h
|
||||
header-y += socket.h
|
||||
header-y += sockev.h
|
||||
header-y += sockios.h
|
||||
header-y += sonet.h
|
||||
header-y += sonypi.h
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#define NETLINK_ECRYPTFS 19
|
||||
#define NETLINK_RDMA 20
|
||||
#define NETLINK_CRYPTO 21 /* Crypto layer */
|
||||
|
||||
#define NETLINK_SOCKEV 22 /* Socket Administrative Events */
|
||||
#define NETLINK_INET_DIAG NETLINK_SOCK_DIAG
|
||||
|
||||
#define MAX_LINKS 32
|
||||
|
|
31
include/uapi/linux/sockev.h
Normal file
31
include/uapi/linux/sockev.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#ifndef _SOCKEV_H_
|
||||
#define _SOCKEV_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/socket.h>
|
||||
|
||||
enum sknetlink_groups {
|
||||
SKNLGRP_UNICAST,
|
||||
SKNLGRP_SOCKEV,
|
||||
__SKNLGRP_MAX
|
||||
};
|
||||
|
||||
#define SOCKEV_STR_MAX 32
|
||||
|
||||
/********************************************************************
|
||||
* Socket operation messages
|
||||
****/
|
||||
|
||||
struct sknlsockevmsg {
|
||||
__u8 event[SOCKEV_STR_MAX];
|
||||
__u32 pid; /* (struct task_struct*)->pid */
|
||||
__u16 skfamily; /* (struct socket*)->sk->sk_family */
|
||||
__u8 skstate; /* (struct socket*)->sk->sk_state */
|
||||
__u8 skprotocol; /* (struct socket*)->sk->sk_protocol */
|
||||
__u16 sktype; /* (struct socket*)->sk->sk_type */
|
||||
__u64 skflags; /* (struct socket*)->sk->sk_flags */
|
||||
};
|
||||
|
||||
#endif /* _SOCKEV_H_ */
|
||||
|
|
@ -312,6 +312,15 @@ config NET_FLOW_LIMIT
|
|||
with many clients some protection against DoS by a single (spoofed)
|
||||
flow that greatly exceeds average workload.
|
||||
|
||||
config SOCKEV_NLMCAST
|
||||
bool "Enable SOCKEV Netlink Multicast"
|
||||
default n
|
||||
---help---
|
||||
Default client for SOCKEV notifier events. Sends multicast netlink
|
||||
messages whenever the socket event notifier is invoked. Enable if
|
||||
user space entities need to be notified of socket events without
|
||||
having to poll /proc
|
||||
|
||||
menu "Network testing"
|
||||
|
||||
config NET_PKTGEN
|
||||
|
|
|
@ -24,3 +24,4 @@ obj-$(CONFIG_NET_PTP_CLASSIFY) += ptp_classifier.o
|
|||
obj-$(CONFIG_CGROUP_NET_PRIO) += netprio_cgroup.o
|
||||
obj-$(CONFIG_CGROUP_NET_CLASSID) += netclassid_cgroup.o
|
||||
obj-$(CONFIG_LWTUNNEL) += lwtunnel.o
|
||||
obj-$(CONFIG_SOCKEV_NLMCAST) += sockev_nlmcast.o
|
||||
|
|
139
net/core/sockev_nlmcast.c
Normal file
139
net/core/sockev_nlmcast.c
Normal file
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Copyright (c) 2014, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* Default SOCKEV client implementation
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/sockev.h>
|
||||
#include <net/sock.h>
|
||||
|
||||
static int registration_status;
|
||||
static struct sock *socknlmsgsk;
|
||||
|
||||
static void sockev_skmsg_recv(struct sk_buff *skb)
|
||||
{
|
||||
pr_debug("%s(): Got unsolicited request\n", __func__);
|
||||
}
|
||||
|
||||
static struct netlink_kernel_cfg nlcfg = {
|
||||
.input = sockev_skmsg_recv
|
||||
};
|
||||
|
||||
static void _sockev_event(unsigned long event, __u8 *evstr, int buflen)
|
||||
{
|
||||
switch (event) {
|
||||
case SOCKEV_SOCKET:
|
||||
strlcpy(evstr, "SOCKEV_SOCKET", buflen);
|
||||
break;
|
||||
case SOCKEV_BIND:
|
||||
strlcpy(evstr, "SOCKEV_BIND", buflen);
|
||||
break;
|
||||
case SOCKEV_LISTEN:
|
||||
strlcpy(evstr, "SOCKEV_LISTEN", buflen);
|
||||
break;
|
||||
case SOCKEV_ACCEPT:
|
||||
strlcpy(evstr, "SOCKEV_ACCEPT", buflen);
|
||||
break;
|
||||
case SOCKEV_CONNECT:
|
||||
strlcpy(evstr, "SOCKEV_CONNECT", buflen);
|
||||
break;
|
||||
case SOCKEV_SHUTDOWN:
|
||||
strlcpy(evstr, "SOCKEV_SHUTDOWN", buflen);
|
||||
break;
|
||||
default:
|
||||
strlcpy(evstr, "UNKOWN", buflen);
|
||||
}
|
||||
}
|
||||
|
||||
static int sockev_client_cb(struct notifier_block *nb,
|
||||
unsigned long event, void *data)
|
||||
{
|
||||
|
||||
struct sk_buff *skb;
|
||||
struct nlmsghdr *nlh;
|
||||
struct sknlsockevmsg *smsg;
|
||||
struct socket *sock;
|
||||
|
||||
sock = (struct socket *)data;
|
||||
if (socknlmsgsk == 0)
|
||||
goto done;
|
||||
if ((socknlmsgsk == NULL) || (sock == NULL) || (sock->sk == NULL))
|
||||
goto done;
|
||||
|
||||
skb = nlmsg_new(sizeof(struct sknlsockevmsg), GFP_KERNEL);
|
||||
if (skb == NULL)
|
||||
goto done;
|
||||
|
||||
nlh = nlmsg_put(skb, 0, 0, event, sizeof(struct sknlsockevmsg), 0);
|
||||
if (nlh == NULL) {
|
||||
kfree_skb(skb);
|
||||
goto done;
|
||||
}
|
||||
|
||||
NETLINK_CB(skb).dst_group = SKNLGRP_SOCKEV;
|
||||
|
||||
smsg = nlmsg_data(nlh);
|
||||
smsg->pid = current->pid;
|
||||
_sockev_event(event, smsg->event, sizeof(smsg->event));
|
||||
smsg->skfamily = sock->sk->sk_family;
|
||||
smsg->skstate = sock->sk->sk_state;
|
||||
smsg->skprotocol = sock->sk->sk_protocol;
|
||||
smsg->sktype = sock->sk->sk_type;
|
||||
smsg->skflags = sock->sk->sk_flags;
|
||||
|
||||
nlmsg_notify(socknlmsgsk, skb, 0, SKNLGRP_SOCKEV, 0, GFP_KERNEL);
|
||||
done:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct notifier_block sockev_notifier_client = {
|
||||
.notifier_call = sockev_client_cb,
|
||||
.next = 0,
|
||||
.priority = 0
|
||||
};
|
||||
|
||||
/* ***************** Startup/Shutdown *************************************** */
|
||||
|
||||
static int __init sockev_client_init(void)
|
||||
{
|
||||
int rc;
|
||||
registration_status = 1;
|
||||
rc = sockev_register_notify(&sockev_notifier_client);
|
||||
if (rc != 0) {
|
||||
registration_status = 0;
|
||||
pr_err("%s(): Failed to register cb (%d)\n", __func__, rc);
|
||||
}
|
||||
socknlmsgsk = netlink_kernel_create(&init_net, NETLINK_SOCKEV, &nlcfg);
|
||||
if (!socknlmsgsk) {
|
||||
pr_err("%s(): Failed to initialize netlink socket\n", __func__);
|
||||
if (registration_status)
|
||||
sockev_unregister_notify(&sockev_notifier_client);
|
||||
registration_status = 0;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
static void __exit sockev_client_exit(void)
|
||||
{
|
||||
if (registration_status)
|
||||
sockev_unregister_notify(&sockev_notifier_client);
|
||||
}
|
||||
module_init(sockev_client_init)
|
||||
module_exit(sockev_client_exit)
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
Loading…
Add table
Reference in a new issue