4
* @brief AF_NETLINK protocol family socket handler
7
* @author Anton Bondarev
10
#include <sys/socket.h>
14
#include <mem/misc/pool.h>
16
#include <kernel/thread/thread_sched_wait.h>
17
#include <kernel/sched.h>
18
#include <kernel/thread.h>
23
#include <net/netlink.h>
24
#include <net/inetdevice.h>
29
#include <linux/if_link.h>
30
#include <linux/netlink.h>
31
#include <linux/rtnetlink.h>
33
#include <framework/mod/options.h>
35
#define MAX_SOCKS OPTION_GET(NUMBER,max_socks)
38
/* sk has to be the first member */
40
struct sockaddr_nl sockaddr_nl;
42
struct netlink_msg netlink_msg;
43
volatile int ready_to_read;
44
struct thread *thread;
47
POOL_DEF(af_netlink_sock_pool, struct netlink_sock, MAX_SOCKS);
49
static struct netlink_sock *netlink_socket;
51
/********************** netlink *******************/
52
static inline void nlmsghdr_init(struct nlmsghdr *hdr,
53
uint32_t len, uint16_t type, uint16_t flags, uint32_t seq, uint32_t pid) {
55
hdr->nlmsg_type = type;
56
hdr->nlmsg_flags = flags;
61
int netlink_notify_newlink(struct net_device *net_dev) {
62
struct netlink_msg *nt_msg;
68
nt_msg = &netlink_socket->netlink_msg;
72
memset(nt_msg, 0, sizeof(*nt_msg));
74
nlmsghdr_init(&nt_msg->nlmsghdr,
75
sizeof(struct netlink_msg),
77
0, 0, netlink_socket->sockaddr_nl.nl_pid);
79
nt_msg->attr_if_name.rta_len = sizeof(nt_msg->if_name) + 4;
80
nt_msg->attr_if_name.rta_type = IFLA_IFNAME;
81
memcpy(nt_msg->if_name, net_dev->name, IFNAMSIZ);
82
netlink_socket->ready_to_read = 1;
83
sched_wakeup(&netlink_socket->thread->schedee);
90
int netlink_notify_dellink(struct net_device *net_dev) {
91
struct netlink_msg *nt_msg;
97
nt_msg = &netlink_socket->netlink_msg;
101
memset(nt_msg, 0, sizeof(*nt_msg));
103
nlmsghdr_init(&nt_msg->nlmsghdr,
104
sizeof(struct netlink_msg),
106
0, 0, netlink_socket->sockaddr_nl.nl_pid);
108
nt_msg->attr_if_name.rta_len = sizeof(nt_msg->if_name) + 4;
109
nt_msg->attr_if_name.rta_type = IFLA_IFNAME;
110
memcpy(nt_msg->if_name, net_dev->name, IFNAMSIZ);
111
netlink_socket->ready_to_read = 1;
112
sched_wakeup(&netlink_socket->thread->schedee);
118
/******* END netlink *************/
120
/******************af_netlink_sock ***************/
121
static int af_netlink_sock_init(struct sock *sock) {
125
static int af_netlink_sock_close(struct sock *sk) {
128
assert(sk->p_ops != NULL);
129
if (sk->p_ops->close == NULL) {
134
return sk->p_ops->close(sk);
137
static int af_netlink_sock_bind(struct sock *sk, const struct sockaddr *addr,
139
struct netlink_sock *netlink_sock;
141
netlink_sock = (struct netlink_sock *)sk;
143
memcpy(&netlink_sock->sockaddr_nl, addr, sizeof(netlink_sock->sockaddr_nl));
144
netlink_sock->ready_to_read = 0;
145
netlink_sock->thread = thread_self();
147
netlink_socket = (struct netlink_sock *)sk;
152
static int af_netlink_sock_recvmsg(struct sock *sk, struct msghdr *msg, int flags) {
153
struct netlink_sock *netlink_sock;
157
netlink_sock = (struct netlink_sock *)sk;
161
if (!(netlink_sock->ready_to_read)) {
162
ret = SCHED_WAIT_TIMEOUT(netlink_sock->ready_to_read, 10000);
168
len = min(msg->msg_iov->iov_len, sizeof(netlink_sock->netlink_msg));
169
memcpy(msg->msg_iov->iov_base, &netlink_sock->netlink_msg, len);
170
netlink_sock->ready_to_read = 0;
178
static const struct sock_family_ops netlink_ops = {
179
.init = af_netlink_sock_init,
180
.close = af_netlink_sock_close,
181
.bind = af_netlink_sock_bind,
182
.recvmsg = af_netlink_sock_recvmsg,
183
.sock_pool = &af_netlink_sock_pool
186
static const struct net_family_type netlink_types[] = {
187
{ SOCK_RAW, &netlink_ops }
190
struct net_pack_out_ops;
191
static const struct net_pack_out_ops *out_ops_struct;
193
EMBOX_NET_FAMILY(AF_NETLINK, netlink_types, out_ops_struct);
195
static DLIST_DEFINE(netlink_sock_list);
197
static const struct sock_proto_ops netlink_sock_ops = {
198
.sock_list = &netlink_sock_list
201
EMBOX_NET_SOCK(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE, 1, netlink_sock_ops);