Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/l2tp/l2tp_netlink.c
15109 views
1
/*
2
* L2TP netlink layer, for management
3
*
4
* Copyright (c) 2008,2009,2010 Katalix Systems Ltd
5
*
6
* Partly based on the IrDA nelink implementation
7
* (see net/irda/irnetlink.c) which is:
8
* Copyright (c) 2007 Samuel Ortiz <[email protected]>
9
* which is in turn partly based on the wireless netlink code:
10
* Copyright 2006 Johannes Berg <[email protected]>
11
*
12
* This program is free software; you can redistribute it and/or modify
13
* it under the terms of the GNU General Public License version 2 as
14
* published by the Free Software Foundation.
15
*/
16
17
#include <net/sock.h>
18
#include <net/genetlink.h>
19
#include <net/udp.h>
20
#include <linux/in.h>
21
#include <linux/udp.h>
22
#include <linux/socket.h>
23
#include <linux/module.h>
24
#include <linux/list.h>
25
#include <net/net_namespace.h>
26
27
#include <linux/l2tp.h>
28
29
#include "l2tp_core.h"
30
31
32
static struct genl_family l2tp_nl_family = {
33
.id = GENL_ID_GENERATE,
34
.name = L2TP_GENL_NAME,
35
.version = L2TP_GENL_VERSION,
36
.hdrsize = 0,
37
.maxattr = L2TP_ATTR_MAX,
38
};
39
40
/* Accessed under genl lock */
41
static const struct l2tp_nl_cmd_ops *l2tp_nl_cmd_ops[__L2TP_PWTYPE_MAX];
42
43
static struct l2tp_session *l2tp_nl_session_find(struct genl_info *info)
44
{
45
u32 tunnel_id;
46
u32 session_id;
47
char *ifname;
48
struct l2tp_tunnel *tunnel;
49
struct l2tp_session *session = NULL;
50
struct net *net = genl_info_net(info);
51
52
if (info->attrs[L2TP_ATTR_IFNAME]) {
53
ifname = nla_data(info->attrs[L2TP_ATTR_IFNAME]);
54
session = l2tp_session_find_by_ifname(net, ifname);
55
} else if ((info->attrs[L2TP_ATTR_SESSION_ID]) &&
56
(info->attrs[L2TP_ATTR_CONN_ID])) {
57
tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_CONN_ID]);
58
session_id = nla_get_u32(info->attrs[L2TP_ATTR_SESSION_ID]);
59
tunnel = l2tp_tunnel_find(net, tunnel_id);
60
if (tunnel)
61
session = l2tp_session_find(net, tunnel, session_id);
62
}
63
64
return session;
65
}
66
67
static int l2tp_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info)
68
{
69
struct sk_buff *msg;
70
void *hdr;
71
int ret = -ENOBUFS;
72
73
msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
74
if (!msg) {
75
ret = -ENOMEM;
76
goto out;
77
}
78
79
hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq,
80
&l2tp_nl_family, 0, L2TP_CMD_NOOP);
81
if (IS_ERR(hdr)) {
82
ret = PTR_ERR(hdr);
83
goto err_out;
84
}
85
86
genlmsg_end(msg, hdr);
87
88
return genlmsg_unicast(genl_info_net(info), msg, info->snd_pid);
89
90
err_out:
91
nlmsg_free(msg);
92
93
out:
94
return ret;
95
}
96
97
static int l2tp_nl_cmd_tunnel_create(struct sk_buff *skb, struct genl_info *info)
98
{
99
u32 tunnel_id;
100
u32 peer_tunnel_id;
101
int proto_version;
102
int fd;
103
int ret = 0;
104
struct l2tp_tunnel_cfg cfg = { 0, };
105
struct l2tp_tunnel *tunnel;
106
struct net *net = genl_info_net(info);
107
108
if (!info->attrs[L2TP_ATTR_CONN_ID]) {
109
ret = -EINVAL;
110
goto out;
111
}
112
tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_CONN_ID]);
113
114
if (!info->attrs[L2TP_ATTR_PEER_CONN_ID]) {
115
ret = -EINVAL;
116
goto out;
117
}
118
peer_tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_PEER_CONN_ID]);
119
120
if (!info->attrs[L2TP_ATTR_PROTO_VERSION]) {
121
ret = -EINVAL;
122
goto out;
123
}
124
proto_version = nla_get_u8(info->attrs[L2TP_ATTR_PROTO_VERSION]);
125
126
if (!info->attrs[L2TP_ATTR_ENCAP_TYPE]) {
127
ret = -EINVAL;
128
goto out;
129
}
130
cfg.encap = nla_get_u16(info->attrs[L2TP_ATTR_ENCAP_TYPE]);
131
132
fd = -1;
133
if (info->attrs[L2TP_ATTR_FD]) {
134
fd = nla_get_u32(info->attrs[L2TP_ATTR_FD]);
135
} else {
136
if (info->attrs[L2TP_ATTR_IP_SADDR])
137
cfg.local_ip.s_addr = nla_get_be32(info->attrs[L2TP_ATTR_IP_SADDR]);
138
if (info->attrs[L2TP_ATTR_IP_DADDR])
139
cfg.peer_ip.s_addr = nla_get_be32(info->attrs[L2TP_ATTR_IP_DADDR]);
140
if (info->attrs[L2TP_ATTR_UDP_SPORT])
141
cfg.local_udp_port = nla_get_u16(info->attrs[L2TP_ATTR_UDP_SPORT]);
142
if (info->attrs[L2TP_ATTR_UDP_DPORT])
143
cfg.peer_udp_port = nla_get_u16(info->attrs[L2TP_ATTR_UDP_DPORT]);
144
if (info->attrs[L2TP_ATTR_UDP_CSUM])
145
cfg.use_udp_checksums = nla_get_flag(info->attrs[L2TP_ATTR_UDP_CSUM]);
146
}
147
148
if (info->attrs[L2TP_ATTR_DEBUG])
149
cfg.debug = nla_get_u32(info->attrs[L2TP_ATTR_DEBUG]);
150
151
tunnel = l2tp_tunnel_find(net, tunnel_id);
152
if (tunnel != NULL) {
153
ret = -EEXIST;
154
goto out;
155
}
156
157
ret = -EINVAL;
158
switch (cfg.encap) {
159
case L2TP_ENCAPTYPE_UDP:
160
case L2TP_ENCAPTYPE_IP:
161
ret = l2tp_tunnel_create(net, fd, proto_version, tunnel_id,
162
peer_tunnel_id, &cfg, &tunnel);
163
break;
164
}
165
166
out:
167
return ret;
168
}
169
170
static int l2tp_nl_cmd_tunnel_delete(struct sk_buff *skb, struct genl_info *info)
171
{
172
struct l2tp_tunnel *tunnel;
173
u32 tunnel_id;
174
int ret = 0;
175
struct net *net = genl_info_net(info);
176
177
if (!info->attrs[L2TP_ATTR_CONN_ID]) {
178
ret = -EINVAL;
179
goto out;
180
}
181
tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_CONN_ID]);
182
183
tunnel = l2tp_tunnel_find(net, tunnel_id);
184
if (tunnel == NULL) {
185
ret = -ENODEV;
186
goto out;
187
}
188
189
(void) l2tp_tunnel_delete(tunnel);
190
191
out:
192
return ret;
193
}
194
195
static int l2tp_nl_cmd_tunnel_modify(struct sk_buff *skb, struct genl_info *info)
196
{
197
struct l2tp_tunnel *tunnel;
198
u32 tunnel_id;
199
int ret = 0;
200
struct net *net = genl_info_net(info);
201
202
if (!info->attrs[L2TP_ATTR_CONN_ID]) {
203
ret = -EINVAL;
204
goto out;
205
}
206
tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_CONN_ID]);
207
208
tunnel = l2tp_tunnel_find(net, tunnel_id);
209
if (tunnel == NULL) {
210
ret = -ENODEV;
211
goto out;
212
}
213
214
if (info->attrs[L2TP_ATTR_DEBUG])
215
tunnel->debug = nla_get_u32(info->attrs[L2TP_ATTR_DEBUG]);
216
217
out:
218
return ret;
219
}
220
221
static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 pid, u32 seq, int flags,
222
struct l2tp_tunnel *tunnel)
223
{
224
void *hdr;
225
struct nlattr *nest;
226
struct sock *sk = NULL;
227
struct inet_sock *inet;
228
229
hdr = genlmsg_put(skb, pid, seq, &l2tp_nl_family, flags,
230
L2TP_CMD_TUNNEL_GET);
231
if (IS_ERR(hdr))
232
return PTR_ERR(hdr);
233
234
NLA_PUT_U8(skb, L2TP_ATTR_PROTO_VERSION, tunnel->version);
235
NLA_PUT_U32(skb, L2TP_ATTR_CONN_ID, tunnel->tunnel_id);
236
NLA_PUT_U32(skb, L2TP_ATTR_PEER_CONN_ID, tunnel->peer_tunnel_id);
237
NLA_PUT_U32(skb, L2TP_ATTR_DEBUG, tunnel->debug);
238
NLA_PUT_U16(skb, L2TP_ATTR_ENCAP_TYPE, tunnel->encap);
239
240
nest = nla_nest_start(skb, L2TP_ATTR_STATS);
241
if (nest == NULL)
242
goto nla_put_failure;
243
244
NLA_PUT_U64(skb, L2TP_ATTR_TX_PACKETS, tunnel->stats.tx_packets);
245
NLA_PUT_U64(skb, L2TP_ATTR_TX_BYTES, tunnel->stats.tx_bytes);
246
NLA_PUT_U64(skb, L2TP_ATTR_TX_ERRORS, tunnel->stats.tx_errors);
247
NLA_PUT_U64(skb, L2TP_ATTR_RX_PACKETS, tunnel->stats.rx_packets);
248
NLA_PUT_U64(skb, L2TP_ATTR_RX_BYTES, tunnel->stats.rx_bytes);
249
NLA_PUT_U64(skb, L2TP_ATTR_RX_SEQ_DISCARDS, tunnel->stats.rx_seq_discards);
250
NLA_PUT_U64(skb, L2TP_ATTR_RX_OOS_PACKETS, tunnel->stats.rx_oos_packets);
251
NLA_PUT_U64(skb, L2TP_ATTR_RX_ERRORS, tunnel->stats.rx_errors);
252
nla_nest_end(skb, nest);
253
254
sk = tunnel->sock;
255
if (!sk)
256
goto out;
257
258
inet = inet_sk(sk);
259
260
switch (tunnel->encap) {
261
case L2TP_ENCAPTYPE_UDP:
262
NLA_PUT_U16(skb, L2TP_ATTR_UDP_SPORT, ntohs(inet->inet_sport));
263
NLA_PUT_U16(skb, L2TP_ATTR_UDP_DPORT, ntohs(inet->inet_dport));
264
NLA_PUT_U8(skb, L2TP_ATTR_UDP_CSUM, (sk->sk_no_check != UDP_CSUM_NOXMIT));
265
/* NOBREAK */
266
case L2TP_ENCAPTYPE_IP:
267
NLA_PUT_BE32(skb, L2TP_ATTR_IP_SADDR, inet->inet_saddr);
268
NLA_PUT_BE32(skb, L2TP_ATTR_IP_DADDR, inet->inet_daddr);
269
break;
270
}
271
272
out:
273
return genlmsg_end(skb, hdr);
274
275
nla_put_failure:
276
genlmsg_cancel(skb, hdr);
277
return -1;
278
}
279
280
static int l2tp_nl_cmd_tunnel_get(struct sk_buff *skb, struct genl_info *info)
281
{
282
struct l2tp_tunnel *tunnel;
283
struct sk_buff *msg;
284
u32 tunnel_id;
285
int ret = -ENOBUFS;
286
struct net *net = genl_info_net(info);
287
288
if (!info->attrs[L2TP_ATTR_CONN_ID]) {
289
ret = -EINVAL;
290
goto out;
291
}
292
293
tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_CONN_ID]);
294
295
tunnel = l2tp_tunnel_find(net, tunnel_id);
296
if (tunnel == NULL) {
297
ret = -ENODEV;
298
goto out;
299
}
300
301
msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
302
if (!msg) {
303
ret = -ENOMEM;
304
goto out;
305
}
306
307
ret = l2tp_nl_tunnel_send(msg, info->snd_pid, info->snd_seq,
308
NLM_F_ACK, tunnel);
309
if (ret < 0)
310
goto err_out;
311
312
return genlmsg_unicast(net, msg, info->snd_pid);
313
314
err_out:
315
nlmsg_free(msg);
316
317
out:
318
return ret;
319
}
320
321
static int l2tp_nl_cmd_tunnel_dump(struct sk_buff *skb, struct netlink_callback *cb)
322
{
323
int ti = cb->args[0];
324
struct l2tp_tunnel *tunnel;
325
struct net *net = sock_net(skb->sk);
326
327
for (;;) {
328
tunnel = l2tp_tunnel_find_nth(net, ti);
329
if (tunnel == NULL)
330
goto out;
331
332
if (l2tp_nl_tunnel_send(skb, NETLINK_CB(cb->skb).pid,
333
cb->nlh->nlmsg_seq, NLM_F_MULTI,
334
tunnel) <= 0)
335
goto out;
336
337
ti++;
338
}
339
340
out:
341
cb->args[0] = ti;
342
343
return skb->len;
344
}
345
346
static int l2tp_nl_cmd_session_create(struct sk_buff *skb, struct genl_info *info)
347
{
348
u32 tunnel_id = 0;
349
u32 session_id;
350
u32 peer_session_id;
351
int ret = 0;
352
struct l2tp_tunnel *tunnel;
353
struct l2tp_session *session;
354
struct l2tp_session_cfg cfg = { 0, };
355
struct net *net = genl_info_net(info);
356
357
if (!info->attrs[L2TP_ATTR_CONN_ID]) {
358
ret = -EINVAL;
359
goto out;
360
}
361
tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_CONN_ID]);
362
tunnel = l2tp_tunnel_find(net, tunnel_id);
363
if (!tunnel) {
364
ret = -ENODEV;
365
goto out;
366
}
367
368
if (!info->attrs[L2TP_ATTR_SESSION_ID]) {
369
ret = -EINVAL;
370
goto out;
371
}
372
session_id = nla_get_u32(info->attrs[L2TP_ATTR_SESSION_ID]);
373
session = l2tp_session_find(net, tunnel, session_id);
374
if (session) {
375
ret = -EEXIST;
376
goto out;
377
}
378
379
if (!info->attrs[L2TP_ATTR_PEER_SESSION_ID]) {
380
ret = -EINVAL;
381
goto out;
382
}
383
peer_session_id = nla_get_u32(info->attrs[L2TP_ATTR_PEER_SESSION_ID]);
384
385
if (!info->attrs[L2TP_ATTR_PW_TYPE]) {
386
ret = -EINVAL;
387
goto out;
388
}
389
cfg.pw_type = nla_get_u16(info->attrs[L2TP_ATTR_PW_TYPE]);
390
if (cfg.pw_type >= __L2TP_PWTYPE_MAX) {
391
ret = -EINVAL;
392
goto out;
393
}
394
395
if (tunnel->version > 2) {
396
if (info->attrs[L2TP_ATTR_OFFSET])
397
cfg.offset = nla_get_u16(info->attrs[L2TP_ATTR_OFFSET]);
398
399
if (info->attrs[L2TP_ATTR_DATA_SEQ])
400
cfg.data_seq = nla_get_u8(info->attrs[L2TP_ATTR_DATA_SEQ]);
401
402
cfg.l2specific_type = L2TP_L2SPECTYPE_DEFAULT;
403
if (info->attrs[L2TP_ATTR_L2SPEC_TYPE])
404
cfg.l2specific_type = nla_get_u8(info->attrs[L2TP_ATTR_L2SPEC_TYPE]);
405
406
cfg.l2specific_len = 4;
407
if (info->attrs[L2TP_ATTR_L2SPEC_LEN])
408
cfg.l2specific_len = nla_get_u8(info->attrs[L2TP_ATTR_L2SPEC_LEN]);
409
410
if (info->attrs[L2TP_ATTR_COOKIE]) {
411
u16 len = nla_len(info->attrs[L2TP_ATTR_COOKIE]);
412
if (len > 8) {
413
ret = -EINVAL;
414
goto out;
415
}
416
cfg.cookie_len = len;
417
memcpy(&cfg.cookie[0], nla_data(info->attrs[L2TP_ATTR_COOKIE]), len);
418
}
419
if (info->attrs[L2TP_ATTR_PEER_COOKIE]) {
420
u16 len = nla_len(info->attrs[L2TP_ATTR_PEER_COOKIE]);
421
if (len > 8) {
422
ret = -EINVAL;
423
goto out;
424
}
425
cfg.peer_cookie_len = len;
426
memcpy(&cfg.peer_cookie[0], nla_data(info->attrs[L2TP_ATTR_PEER_COOKIE]), len);
427
}
428
if (info->attrs[L2TP_ATTR_IFNAME])
429
cfg.ifname = nla_data(info->attrs[L2TP_ATTR_IFNAME]);
430
431
if (info->attrs[L2TP_ATTR_VLAN_ID])
432
cfg.vlan_id = nla_get_u16(info->attrs[L2TP_ATTR_VLAN_ID]);
433
}
434
435
if (info->attrs[L2TP_ATTR_DEBUG])
436
cfg.debug = nla_get_u32(info->attrs[L2TP_ATTR_DEBUG]);
437
438
if (info->attrs[L2TP_ATTR_RECV_SEQ])
439
cfg.recv_seq = nla_get_u8(info->attrs[L2TP_ATTR_RECV_SEQ]);
440
441
if (info->attrs[L2TP_ATTR_SEND_SEQ])
442
cfg.send_seq = nla_get_u8(info->attrs[L2TP_ATTR_SEND_SEQ]);
443
444
if (info->attrs[L2TP_ATTR_LNS_MODE])
445
cfg.lns_mode = nla_get_u8(info->attrs[L2TP_ATTR_LNS_MODE]);
446
447
if (info->attrs[L2TP_ATTR_RECV_TIMEOUT])
448
cfg.reorder_timeout = nla_get_msecs(info->attrs[L2TP_ATTR_RECV_TIMEOUT]);
449
450
if (info->attrs[L2TP_ATTR_MTU])
451
cfg.mtu = nla_get_u16(info->attrs[L2TP_ATTR_MTU]);
452
453
if (info->attrs[L2TP_ATTR_MRU])
454
cfg.mru = nla_get_u16(info->attrs[L2TP_ATTR_MRU]);
455
456
if ((l2tp_nl_cmd_ops[cfg.pw_type] == NULL) ||
457
(l2tp_nl_cmd_ops[cfg.pw_type]->session_create == NULL)) {
458
ret = -EPROTONOSUPPORT;
459
goto out;
460
}
461
462
/* Check that pseudowire-specific params are present */
463
switch (cfg.pw_type) {
464
case L2TP_PWTYPE_NONE:
465
break;
466
case L2TP_PWTYPE_ETH_VLAN:
467
if (!info->attrs[L2TP_ATTR_VLAN_ID]) {
468
ret = -EINVAL;
469
goto out;
470
}
471
break;
472
case L2TP_PWTYPE_ETH:
473
break;
474
case L2TP_PWTYPE_PPP:
475
case L2TP_PWTYPE_PPP_AC:
476
break;
477
case L2TP_PWTYPE_IP:
478
default:
479
ret = -EPROTONOSUPPORT;
480
break;
481
}
482
483
ret = -EPROTONOSUPPORT;
484
if (l2tp_nl_cmd_ops[cfg.pw_type]->session_create)
485
ret = (*l2tp_nl_cmd_ops[cfg.pw_type]->session_create)(net, tunnel_id,
486
session_id, peer_session_id, &cfg);
487
488
out:
489
return ret;
490
}
491
492
static int l2tp_nl_cmd_session_delete(struct sk_buff *skb, struct genl_info *info)
493
{
494
int ret = 0;
495
struct l2tp_session *session;
496
u16 pw_type;
497
498
session = l2tp_nl_session_find(info);
499
if (session == NULL) {
500
ret = -ENODEV;
501
goto out;
502
}
503
504
pw_type = session->pwtype;
505
if (pw_type < __L2TP_PWTYPE_MAX)
506
if (l2tp_nl_cmd_ops[pw_type] && l2tp_nl_cmd_ops[pw_type]->session_delete)
507
ret = (*l2tp_nl_cmd_ops[pw_type]->session_delete)(session);
508
509
out:
510
return ret;
511
}
512
513
static int l2tp_nl_cmd_session_modify(struct sk_buff *skb, struct genl_info *info)
514
{
515
int ret = 0;
516
struct l2tp_session *session;
517
518
session = l2tp_nl_session_find(info);
519
if (session == NULL) {
520
ret = -ENODEV;
521
goto out;
522
}
523
524
if (info->attrs[L2TP_ATTR_DEBUG])
525
session->debug = nla_get_u32(info->attrs[L2TP_ATTR_DEBUG]);
526
527
if (info->attrs[L2TP_ATTR_DATA_SEQ])
528
session->data_seq = nla_get_u8(info->attrs[L2TP_ATTR_DATA_SEQ]);
529
530
if (info->attrs[L2TP_ATTR_RECV_SEQ])
531
session->recv_seq = nla_get_u8(info->attrs[L2TP_ATTR_RECV_SEQ]);
532
533
if (info->attrs[L2TP_ATTR_SEND_SEQ])
534
session->send_seq = nla_get_u8(info->attrs[L2TP_ATTR_SEND_SEQ]);
535
536
if (info->attrs[L2TP_ATTR_LNS_MODE])
537
session->lns_mode = nla_get_u8(info->attrs[L2TP_ATTR_LNS_MODE]);
538
539
if (info->attrs[L2TP_ATTR_RECV_TIMEOUT])
540
session->reorder_timeout = nla_get_msecs(info->attrs[L2TP_ATTR_RECV_TIMEOUT]);
541
542
if (info->attrs[L2TP_ATTR_MTU])
543
session->mtu = nla_get_u16(info->attrs[L2TP_ATTR_MTU]);
544
545
if (info->attrs[L2TP_ATTR_MRU])
546
session->mru = nla_get_u16(info->attrs[L2TP_ATTR_MRU]);
547
548
out:
549
return ret;
550
}
551
552
static int l2tp_nl_session_send(struct sk_buff *skb, u32 pid, u32 seq, int flags,
553
struct l2tp_session *session)
554
{
555
void *hdr;
556
struct nlattr *nest;
557
struct l2tp_tunnel *tunnel = session->tunnel;
558
struct sock *sk = NULL;
559
560
sk = tunnel->sock;
561
562
hdr = genlmsg_put(skb, pid, seq, &l2tp_nl_family, flags, L2TP_CMD_SESSION_GET);
563
if (IS_ERR(hdr))
564
return PTR_ERR(hdr);
565
566
NLA_PUT_U32(skb, L2TP_ATTR_CONN_ID, tunnel->tunnel_id);
567
NLA_PUT_U32(skb, L2TP_ATTR_SESSION_ID, session->session_id);
568
NLA_PUT_U32(skb, L2TP_ATTR_PEER_CONN_ID, tunnel->peer_tunnel_id);
569
NLA_PUT_U32(skb, L2TP_ATTR_PEER_SESSION_ID, session->peer_session_id);
570
NLA_PUT_U32(skb, L2TP_ATTR_DEBUG, session->debug);
571
NLA_PUT_U16(skb, L2TP_ATTR_PW_TYPE, session->pwtype);
572
NLA_PUT_U16(skb, L2TP_ATTR_MTU, session->mtu);
573
if (session->mru)
574
NLA_PUT_U16(skb, L2TP_ATTR_MRU, session->mru);
575
576
if (session->ifname && session->ifname[0])
577
NLA_PUT_STRING(skb, L2TP_ATTR_IFNAME, session->ifname);
578
if (session->cookie_len)
579
NLA_PUT(skb, L2TP_ATTR_COOKIE, session->cookie_len, &session->cookie[0]);
580
if (session->peer_cookie_len)
581
NLA_PUT(skb, L2TP_ATTR_PEER_COOKIE, session->peer_cookie_len, &session->peer_cookie[0]);
582
NLA_PUT_U8(skb, L2TP_ATTR_RECV_SEQ, session->recv_seq);
583
NLA_PUT_U8(skb, L2TP_ATTR_SEND_SEQ, session->send_seq);
584
NLA_PUT_U8(skb, L2TP_ATTR_LNS_MODE, session->lns_mode);
585
#ifdef CONFIG_XFRM
586
if ((sk) && (sk->sk_policy[0] || sk->sk_policy[1]))
587
NLA_PUT_U8(skb, L2TP_ATTR_USING_IPSEC, 1);
588
#endif
589
if (session->reorder_timeout)
590
NLA_PUT_MSECS(skb, L2TP_ATTR_RECV_TIMEOUT, session->reorder_timeout);
591
592
nest = nla_nest_start(skb, L2TP_ATTR_STATS);
593
if (nest == NULL)
594
goto nla_put_failure;
595
NLA_PUT_U64(skb, L2TP_ATTR_TX_PACKETS, session->stats.tx_packets);
596
NLA_PUT_U64(skb, L2TP_ATTR_TX_BYTES, session->stats.tx_bytes);
597
NLA_PUT_U64(skb, L2TP_ATTR_TX_ERRORS, session->stats.tx_errors);
598
NLA_PUT_U64(skb, L2TP_ATTR_RX_PACKETS, session->stats.rx_packets);
599
NLA_PUT_U64(skb, L2TP_ATTR_RX_BYTES, session->stats.rx_bytes);
600
NLA_PUT_U64(skb, L2TP_ATTR_RX_SEQ_DISCARDS, session->stats.rx_seq_discards);
601
NLA_PUT_U64(skb, L2TP_ATTR_RX_OOS_PACKETS, session->stats.rx_oos_packets);
602
NLA_PUT_U64(skb, L2TP_ATTR_RX_ERRORS, session->stats.rx_errors);
603
nla_nest_end(skb, nest);
604
605
return genlmsg_end(skb, hdr);
606
607
nla_put_failure:
608
genlmsg_cancel(skb, hdr);
609
return -1;
610
}
611
612
static int l2tp_nl_cmd_session_get(struct sk_buff *skb, struct genl_info *info)
613
{
614
struct l2tp_session *session;
615
struct sk_buff *msg;
616
int ret;
617
618
session = l2tp_nl_session_find(info);
619
if (session == NULL) {
620
ret = -ENODEV;
621
goto out;
622
}
623
624
msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
625
if (!msg) {
626
ret = -ENOMEM;
627
goto out;
628
}
629
630
ret = l2tp_nl_session_send(msg, info->snd_pid, info->snd_seq,
631
0, session);
632
if (ret < 0)
633
goto err_out;
634
635
return genlmsg_unicast(genl_info_net(info), msg, info->snd_pid);
636
637
err_out:
638
nlmsg_free(msg);
639
640
out:
641
return ret;
642
}
643
644
static int l2tp_nl_cmd_session_dump(struct sk_buff *skb, struct netlink_callback *cb)
645
{
646
struct net *net = sock_net(skb->sk);
647
struct l2tp_session *session;
648
struct l2tp_tunnel *tunnel = NULL;
649
int ti = cb->args[0];
650
int si = cb->args[1];
651
652
for (;;) {
653
if (tunnel == NULL) {
654
tunnel = l2tp_tunnel_find_nth(net, ti);
655
if (tunnel == NULL)
656
goto out;
657
}
658
659
session = l2tp_session_find_nth(tunnel, si);
660
if (session == NULL) {
661
ti++;
662
tunnel = NULL;
663
si = 0;
664
continue;
665
}
666
667
if (l2tp_nl_session_send(skb, NETLINK_CB(cb->skb).pid,
668
cb->nlh->nlmsg_seq, NLM_F_MULTI,
669
session) <= 0)
670
break;
671
672
si++;
673
}
674
675
out:
676
cb->args[0] = ti;
677
cb->args[1] = si;
678
679
return skb->len;
680
}
681
682
static struct nla_policy l2tp_nl_policy[L2TP_ATTR_MAX + 1] = {
683
[L2TP_ATTR_NONE] = { .type = NLA_UNSPEC, },
684
[L2TP_ATTR_PW_TYPE] = { .type = NLA_U16, },
685
[L2TP_ATTR_ENCAP_TYPE] = { .type = NLA_U16, },
686
[L2TP_ATTR_OFFSET] = { .type = NLA_U16, },
687
[L2TP_ATTR_DATA_SEQ] = { .type = NLA_U8, },
688
[L2TP_ATTR_L2SPEC_TYPE] = { .type = NLA_U8, },
689
[L2TP_ATTR_L2SPEC_LEN] = { .type = NLA_U8, },
690
[L2TP_ATTR_PROTO_VERSION] = { .type = NLA_U8, },
691
[L2TP_ATTR_CONN_ID] = { .type = NLA_U32, },
692
[L2TP_ATTR_PEER_CONN_ID] = { .type = NLA_U32, },
693
[L2TP_ATTR_SESSION_ID] = { .type = NLA_U32, },
694
[L2TP_ATTR_PEER_SESSION_ID] = { .type = NLA_U32, },
695
[L2TP_ATTR_UDP_CSUM] = { .type = NLA_U8, },
696
[L2TP_ATTR_VLAN_ID] = { .type = NLA_U16, },
697
[L2TP_ATTR_DEBUG] = { .type = NLA_U32, },
698
[L2TP_ATTR_RECV_SEQ] = { .type = NLA_U8, },
699
[L2TP_ATTR_SEND_SEQ] = { .type = NLA_U8, },
700
[L2TP_ATTR_LNS_MODE] = { .type = NLA_U8, },
701
[L2TP_ATTR_USING_IPSEC] = { .type = NLA_U8, },
702
[L2TP_ATTR_RECV_TIMEOUT] = { .type = NLA_MSECS, },
703
[L2TP_ATTR_FD] = { .type = NLA_U32, },
704
[L2TP_ATTR_IP_SADDR] = { .type = NLA_U32, },
705
[L2TP_ATTR_IP_DADDR] = { .type = NLA_U32, },
706
[L2TP_ATTR_UDP_SPORT] = { .type = NLA_U16, },
707
[L2TP_ATTR_UDP_DPORT] = { .type = NLA_U16, },
708
[L2TP_ATTR_MTU] = { .type = NLA_U16, },
709
[L2TP_ATTR_MRU] = { .type = NLA_U16, },
710
[L2TP_ATTR_STATS] = { .type = NLA_NESTED, },
711
[L2TP_ATTR_IFNAME] = {
712
.type = NLA_NUL_STRING,
713
.len = IFNAMSIZ - 1,
714
},
715
[L2TP_ATTR_COOKIE] = {
716
.type = NLA_BINARY,
717
.len = 8,
718
},
719
[L2TP_ATTR_PEER_COOKIE] = {
720
.type = NLA_BINARY,
721
.len = 8,
722
},
723
};
724
725
static struct genl_ops l2tp_nl_ops[] = {
726
{
727
.cmd = L2TP_CMD_NOOP,
728
.doit = l2tp_nl_cmd_noop,
729
.policy = l2tp_nl_policy,
730
/* can be retrieved by unprivileged users */
731
},
732
{
733
.cmd = L2TP_CMD_TUNNEL_CREATE,
734
.doit = l2tp_nl_cmd_tunnel_create,
735
.policy = l2tp_nl_policy,
736
.flags = GENL_ADMIN_PERM,
737
},
738
{
739
.cmd = L2TP_CMD_TUNNEL_DELETE,
740
.doit = l2tp_nl_cmd_tunnel_delete,
741
.policy = l2tp_nl_policy,
742
.flags = GENL_ADMIN_PERM,
743
},
744
{
745
.cmd = L2TP_CMD_TUNNEL_MODIFY,
746
.doit = l2tp_nl_cmd_tunnel_modify,
747
.policy = l2tp_nl_policy,
748
.flags = GENL_ADMIN_PERM,
749
},
750
{
751
.cmd = L2TP_CMD_TUNNEL_GET,
752
.doit = l2tp_nl_cmd_tunnel_get,
753
.dumpit = l2tp_nl_cmd_tunnel_dump,
754
.policy = l2tp_nl_policy,
755
.flags = GENL_ADMIN_PERM,
756
},
757
{
758
.cmd = L2TP_CMD_SESSION_CREATE,
759
.doit = l2tp_nl_cmd_session_create,
760
.policy = l2tp_nl_policy,
761
.flags = GENL_ADMIN_PERM,
762
},
763
{
764
.cmd = L2TP_CMD_SESSION_DELETE,
765
.doit = l2tp_nl_cmd_session_delete,
766
.policy = l2tp_nl_policy,
767
.flags = GENL_ADMIN_PERM,
768
},
769
{
770
.cmd = L2TP_CMD_SESSION_MODIFY,
771
.doit = l2tp_nl_cmd_session_modify,
772
.policy = l2tp_nl_policy,
773
.flags = GENL_ADMIN_PERM,
774
},
775
{
776
.cmd = L2TP_CMD_SESSION_GET,
777
.doit = l2tp_nl_cmd_session_get,
778
.dumpit = l2tp_nl_cmd_session_dump,
779
.policy = l2tp_nl_policy,
780
.flags = GENL_ADMIN_PERM,
781
},
782
};
783
784
int l2tp_nl_register_ops(enum l2tp_pwtype pw_type, const struct l2tp_nl_cmd_ops *ops)
785
{
786
int ret;
787
788
ret = -EINVAL;
789
if (pw_type >= __L2TP_PWTYPE_MAX)
790
goto err;
791
792
genl_lock();
793
ret = -EBUSY;
794
if (l2tp_nl_cmd_ops[pw_type])
795
goto out;
796
797
l2tp_nl_cmd_ops[pw_type] = ops;
798
ret = 0;
799
800
out:
801
genl_unlock();
802
err:
803
return ret;
804
}
805
EXPORT_SYMBOL_GPL(l2tp_nl_register_ops);
806
807
void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type)
808
{
809
if (pw_type < __L2TP_PWTYPE_MAX) {
810
genl_lock();
811
l2tp_nl_cmd_ops[pw_type] = NULL;
812
genl_unlock();
813
}
814
}
815
EXPORT_SYMBOL_GPL(l2tp_nl_unregister_ops);
816
817
static int l2tp_nl_init(void)
818
{
819
int err;
820
821
printk(KERN_INFO "L2TP netlink interface\n");
822
err = genl_register_family_with_ops(&l2tp_nl_family, l2tp_nl_ops,
823
ARRAY_SIZE(l2tp_nl_ops));
824
825
return err;
826
}
827
828
static void l2tp_nl_cleanup(void)
829
{
830
genl_unregister_family(&l2tp_nl_family);
831
}
832
833
module_init(l2tp_nl_init);
834
module_exit(l2tp_nl_cleanup);
835
836
MODULE_AUTHOR("James Chapman <[email protected]>");
837
MODULE_DESCRIPTION("L2TP netlink");
838
MODULE_LICENSE("GPL");
839
MODULE_VERSION("1.0");
840
MODULE_ALIAS("net-pf-" __stringify(PF_NETLINK) "-proto-" \
841
__stringify(NETLINK_GENERIC) "-type-" "l2tp");
842
843