Skip to content

Commit 33f72e6

Browse files
Bill Hongdavem330
authored andcommitted
l2tp : multicast notification to the registered listeners
Previously l2tp module did not provide any means for the user space to get notified when tunnels/sessions are added/modified/deleted. This change contains the following - create a multicast group for the listeners to register. - notify the registered listeners when the tunnels/sessions are created/modified/deleted. Signed-off-by: Bill Hong <bhong@brocade.com> Reviewed-by: Stephen Hemminger <stephen@networkplumber.org> Reviewed-by: Sven-Thorsten Dietrich <sven@brocade.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 957f094 commit 33f72e6

File tree

2 files changed

+92
-10
lines changed

2 files changed

+92
-10
lines changed

include/uapi/linux/l2tp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,5 +178,6 @@ enum l2tp_seqmode {
178178
*/
179179
#define L2TP_GENL_NAME "l2tp"
180180
#define L2TP_GENL_VERSION 0x1
181+
#define L2TP_GENL_MCGROUP "l2tp"
181182

182183
#endif /* _UAPI_LINUX_L2TP_H_ */

net/l2tp/l2tp_netlink.c

Lines changed: 91 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,18 @@ static struct genl_family l2tp_nl_family = {
4040
.netnsok = true,
4141
};
4242

43+
static const struct genl_multicast_group l2tp_multicast_group[] = {
44+
{
45+
.name = L2TP_GENL_MCGROUP,
46+
},
47+
};
48+
49+
static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 portid, u32 seq,
50+
int flags, struct l2tp_tunnel *tunnel, u8 cmd);
51+
static int l2tp_nl_session_send(struct sk_buff *skb, u32 portid, u32 seq,
52+
int flags, struct l2tp_session *session,
53+
u8 cmd);
54+
4355
/* Accessed under genl lock */
4456
static const struct l2tp_nl_cmd_ops *l2tp_nl_cmd_ops[__L2TP_PWTYPE_MAX];
4557

@@ -97,6 +109,52 @@ static int l2tp_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info)
97109
return ret;
98110
}
99111

112+
static int l2tp_tunnel_notify(struct genl_family *family,
113+
struct genl_info *info,
114+
struct l2tp_tunnel *tunnel,
115+
u8 cmd)
116+
{
117+
struct sk_buff *msg;
118+
int ret;
119+
120+
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
121+
if (!msg)
122+
return -ENOMEM;
123+
124+
ret = l2tp_nl_tunnel_send(msg, info->snd_portid, info->snd_seq,
125+
NLM_F_ACK, tunnel, cmd);
126+
127+
if (ret >= 0)
128+
return genlmsg_multicast_allns(family, msg, 0, 0, GFP_ATOMIC);
129+
130+
nlmsg_free(msg);
131+
132+
return ret;
133+
}
134+
135+
static int l2tp_session_notify(struct genl_family *family,
136+
struct genl_info *info,
137+
struct l2tp_session *session,
138+
u8 cmd)
139+
{
140+
struct sk_buff *msg;
141+
int ret;
142+
143+
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
144+
if (!msg)
145+
return -ENOMEM;
146+
147+
ret = l2tp_nl_session_send(msg, info->snd_portid, info->snd_seq,
148+
NLM_F_ACK, session, cmd);
149+
150+
if (ret >= 0)
151+
return genlmsg_multicast_allns(family, msg, 0, 0, GFP_ATOMIC);
152+
153+
nlmsg_free(msg);
154+
155+
return ret;
156+
}
157+
100158
static int l2tp_nl_cmd_tunnel_create(struct sk_buff *skb, struct genl_info *info)
101159
{
102160
u32 tunnel_id;
@@ -188,6 +246,9 @@ static int l2tp_nl_cmd_tunnel_create(struct sk_buff *skb, struct genl_info *info
188246
break;
189247
}
190248

249+
if (ret >= 0)
250+
ret = l2tp_tunnel_notify(&l2tp_nl_family, info,
251+
tunnel, L2TP_CMD_TUNNEL_CREATE);
191252
out:
192253
return ret;
193254
}
@@ -211,6 +272,9 @@ static int l2tp_nl_cmd_tunnel_delete(struct sk_buff *skb, struct genl_info *info
211272
goto out;
212273
}
213274

275+
l2tp_tunnel_notify(&l2tp_nl_family, info,
276+
tunnel, L2TP_CMD_TUNNEL_DELETE);
277+
214278
(void) l2tp_tunnel_delete(tunnel);
215279

216280
out:
@@ -239,12 +303,15 @@ static int l2tp_nl_cmd_tunnel_modify(struct sk_buff *skb, struct genl_info *info
239303
if (info->attrs[L2TP_ATTR_DEBUG])
240304
tunnel->debug = nla_get_u32(info->attrs[L2TP_ATTR_DEBUG]);
241305

306+
ret = l2tp_tunnel_notify(&l2tp_nl_family, info,
307+
tunnel, L2TP_CMD_TUNNEL_MODIFY);
308+
242309
out:
243310
return ret;
244311
}
245312

246313
static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 portid, u32 seq, int flags,
247-
struct l2tp_tunnel *tunnel)
314+
struct l2tp_tunnel *tunnel, u8 cmd)
248315
{
249316
void *hdr;
250317
struct nlattr *nest;
@@ -254,8 +321,7 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 portid, u32 seq, int fla
254321
struct ipv6_pinfo *np = NULL;
255322
#endif
256323

257-
hdr = genlmsg_put(skb, portid, seq, &l2tp_nl_family, flags,
258-
L2TP_CMD_TUNNEL_GET);
324+
hdr = genlmsg_put(skb, portid, seq, &l2tp_nl_family, flags, cmd);
259325
if (!hdr)
260326
return -EMSGSIZE;
261327

@@ -359,7 +425,7 @@ static int l2tp_nl_cmd_tunnel_get(struct sk_buff *skb, struct genl_info *info)
359425
}
360426

361427
ret = l2tp_nl_tunnel_send(msg, info->snd_portid, info->snd_seq,
362-
NLM_F_ACK, tunnel);
428+
NLM_F_ACK, tunnel, L2TP_CMD_TUNNEL_GET);
363429
if (ret < 0)
364430
goto err_out;
365431

@@ -385,7 +451,7 @@ static int l2tp_nl_cmd_tunnel_dump(struct sk_buff *skb, struct netlink_callback
385451

386452
if (l2tp_nl_tunnel_send(skb, NETLINK_CB(cb->skb).portid,
387453
cb->nlh->nlmsg_seq, NLM_F_MULTI,
388-
tunnel) <= 0)
454+
tunnel, L2TP_CMD_TUNNEL_GET) <= 0)
389455
goto out;
390456

391457
ti++;
@@ -539,6 +605,13 @@ static int l2tp_nl_cmd_session_create(struct sk_buff *skb, struct genl_info *inf
539605
ret = (*l2tp_nl_cmd_ops[cfg.pw_type]->session_create)(net, tunnel_id,
540606
session_id, peer_session_id, &cfg);
541607

608+
if (ret >= 0) {
609+
session = l2tp_session_find(net, tunnel, session_id);
610+
if (session)
611+
ret = l2tp_session_notify(&l2tp_nl_family, info, session,
612+
L2TP_CMD_SESSION_CREATE);
613+
}
614+
542615
out:
543616
return ret;
544617
}
@@ -555,6 +628,9 @@ static int l2tp_nl_cmd_session_delete(struct sk_buff *skb, struct genl_info *inf
555628
goto out;
556629
}
557630

631+
l2tp_session_notify(&l2tp_nl_family, info,
632+
session, L2TP_CMD_SESSION_DELETE);
633+
558634
pw_type = session->pwtype;
559635
if (pw_type < __L2TP_PWTYPE_MAX)
560636
if (l2tp_nl_cmd_ops[pw_type] && l2tp_nl_cmd_ops[pw_type]->session_delete)
@@ -601,12 +677,15 @@ static int l2tp_nl_cmd_session_modify(struct sk_buff *skb, struct genl_info *inf
601677
if (info->attrs[L2TP_ATTR_MRU])
602678
session->mru = nla_get_u16(info->attrs[L2TP_ATTR_MRU]);
603679

680+
ret = l2tp_session_notify(&l2tp_nl_family, info,
681+
session, L2TP_CMD_SESSION_MODIFY);
682+
604683
out:
605684
return ret;
606685
}
607686

608687
static int l2tp_nl_session_send(struct sk_buff *skb, u32 portid, u32 seq, int flags,
609-
struct l2tp_session *session)
688+
struct l2tp_session *session, u8 cmd)
610689
{
611690
void *hdr;
612691
struct nlattr *nest;
@@ -615,7 +694,7 @@ static int l2tp_nl_session_send(struct sk_buff *skb, u32 portid, u32 seq, int fl
615694

616695
sk = tunnel->sock;
617696

618-
hdr = genlmsg_put(skb, portid, seq, &l2tp_nl_family, flags, L2TP_CMD_SESSION_GET);
697+
hdr = genlmsg_put(skb, portid, seq, &l2tp_nl_family, flags, cmd);
619698
if (!hdr)
620699
return -EMSGSIZE;
621700

@@ -699,7 +778,7 @@ static int l2tp_nl_cmd_session_get(struct sk_buff *skb, struct genl_info *info)
699778
}
700779

701780
ret = l2tp_nl_session_send(msg, info->snd_portid, info->snd_seq,
702-
0, session);
781+
0, session, L2TP_CMD_SESSION_GET);
703782
if (ret < 0)
704783
goto err_out;
705784

@@ -737,7 +816,7 @@ static int l2tp_nl_cmd_session_dump(struct sk_buff *skb, struct netlink_callback
737816

738817
if (l2tp_nl_session_send(skb, NETLINK_CB(cb->skb).portid,
739818
cb->nlh->nlmsg_seq, NLM_F_MULTI,
740-
session) <= 0)
819+
session, L2TP_CMD_SESSION_GET) <= 0)
741820
break;
742821

743822
si++;
@@ -896,7 +975,9 @@ EXPORT_SYMBOL_GPL(l2tp_nl_unregister_ops);
896975
static int l2tp_nl_init(void)
897976
{
898977
pr_info("L2TP netlink interface\n");
899-
return genl_register_family_with_ops(&l2tp_nl_family, l2tp_nl_ops);
978+
return genl_register_family_with_ops_groups(&l2tp_nl_family,
979+
l2tp_nl_ops,
980+
l2tp_multicast_group);
900981
}
901982

902983
static void l2tp_nl_cleanup(void)

0 commit comments

Comments
 (0)