embox

Форк
0
/
af_netlink.c 
201 строка · 4.4 Кб
1
/**
2
 * @file
3
 *
4
 * @brief AF_NETLINK protocol family socket handler
5
 *
6
 * @date 31.01.2012
7
 * @author Anton Bondarev
8
 */
9
#include <errno.h>
10
#include <sys/socket.h>
11

12
#include <util/math.h>
13

14
#include <mem/misc/pool.h>
15

16
#include <kernel/thread/thread_sched_wait.h>
17
#include <kernel/sched.h>
18
#include <kernel/thread.h>
19

20
#include <net/if.h>
21

22
#include <net/sock.h>
23
#include <net/netlink.h>
24
#include <net/inetdevice.h>
25

26
#include "family.h"
27
#include "net_sock.h"
28

29
#include <linux/if_link.h>
30
#include <linux/netlink.h>
31
#include <linux/rtnetlink.h>
32

33
#include <framework/mod/options.h>
34

35
#define MAX_SOCKS     OPTION_GET(NUMBER,max_socks)
36

37
struct netlink_sock {
38
	/* sk has to be the first member */
39
	struct sock sk;
40
	struct sockaddr_nl sockaddr_nl;
41

42
	struct netlink_msg netlink_msg;
43
	volatile int ready_to_read;
44
	struct thread *thread;
45
};
46

47
POOL_DEF(af_netlink_sock_pool, struct netlink_sock, MAX_SOCKS);
48

49
static struct netlink_sock *netlink_socket;
50

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) {
54
	hdr->nlmsg_len = len;
55
	hdr->nlmsg_type = type;
56
	hdr->nlmsg_flags = flags;
57
	hdr->nlmsg_seq = seq;
58
	hdr->nlmsg_pid = pid;
59
}
60

61
int netlink_notify_newlink(struct net_device *net_dev) {
62
	struct netlink_msg *nt_msg;
63

64
	if(!netlink_socket) {
65
		return 0;
66
	}
67

68
	nt_msg = &netlink_socket->netlink_msg;
69

70
	sched_lock();
71
	{
72
		memset(nt_msg, 0, sizeof(*nt_msg));
73

74
		nlmsghdr_init(&nt_msg->nlmsghdr,
75
				sizeof(struct netlink_msg),
76
				RTM_NEWLINK,
77
				0, 0, netlink_socket->sockaddr_nl.nl_pid);
78

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);
84
	}
85
	sched_unlock();
86

87
	return 0;
88
}
89

90
int netlink_notify_dellink(struct net_device *net_dev) {
91
	struct netlink_msg *nt_msg;
92

93
	if(!netlink_socket) {
94
		return 0;
95
	}
96

97
	nt_msg = &netlink_socket->netlink_msg;
98

99
	sched_lock();
100
	{
101
		memset(nt_msg, 0, sizeof(*nt_msg));
102

103
		nlmsghdr_init(&nt_msg->nlmsghdr,
104
				sizeof(struct netlink_msg),
105
				RTM_DELLINK,
106
				0, 0, netlink_socket->sockaddr_nl.nl_pid);
107

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);
113
	}
114
	sched_unlock();
115

116
	return 0;
117
}
118
/******* END netlink *************/
119

120
/******************af_netlink_sock ***************/
121
static int af_netlink_sock_init(struct sock *sock) {
122
	return ENOERR;
123
}
124

125
static int af_netlink_sock_close(struct sock *sk) {
126
	assert(sk);
127

128
	assert(sk->p_ops != NULL);
129
	if (sk->p_ops->close == NULL) {
130
		sock_release(sk);
131
		return 0;
132
	}
133

134
	return sk->p_ops->close(sk);
135
}
136

137
static int af_netlink_sock_bind(struct sock *sk, const struct sockaddr *addr,
138
		socklen_t addrlen) {
139
	struct netlink_sock *netlink_sock;
140

141
	netlink_sock = (struct netlink_sock *)sk;
142

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();
146

147
	netlink_socket = (struct netlink_sock *)sk;
148

149
	return 0;
150
}
151

152
static int af_netlink_sock_recvmsg(struct sock *sk, struct msghdr *msg, int flags) {
153
	struct netlink_sock *netlink_sock;
154
	int len;
155
	int ret;
156

157
	netlink_sock = (struct netlink_sock *)sk;
158

159
	sched_lock();
160
	{
161
		if (!(netlink_sock->ready_to_read)) {
162
			ret = SCHED_WAIT_TIMEOUT(netlink_sock->ready_to_read, 10000);
163
			if (ret) {
164
				len = 0;
165
				goto out;
166
			}
167
		}
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;
171
	}
172
out:
173
	sched_unlock();
174

175
	return len;
176
}
177

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
184
};
185

186
static const struct net_family_type netlink_types[] = {
187
	{ SOCK_RAW, &netlink_ops }
188
};
189

190
struct net_pack_out_ops;
191
static const struct net_pack_out_ops *out_ops_struct;
192

193
EMBOX_NET_FAMILY(AF_NETLINK, netlink_types, out_ops_struct);
194

195
static DLIST_DEFINE(netlink_sock_list);
196

197
static const struct sock_proto_ops netlink_sock_ops = {
198
		.sock_list = &netlink_sock_list
199
};
200

201
EMBOX_NET_SOCK(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE, 1, netlink_sock_ops);
202

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.