|
@@ -48,7 +48,8 @@ static int l2tp_nl_session_send(struct sk_buff *skb, u32 portid, u32 seq,
|
|
|
/* Accessed under genl lock */
|
|
/* Accessed under genl lock */
|
|
|
static const struct l2tp_nl_cmd_ops *l2tp_nl_cmd_ops[__L2TP_PWTYPE_MAX];
|
|
static const struct l2tp_nl_cmd_ops *l2tp_nl_cmd_ops[__L2TP_PWTYPE_MAX];
|
|
|
|
|
|
|
|
-static struct l2tp_session *l2tp_nl_session_find(struct genl_info *info)
|
|
|
|
|
|
|
+static struct l2tp_session *l2tp_nl_session_get(struct genl_info *info,
|
|
|
|
|
+ bool do_ref)
|
|
|
{
|
|
{
|
|
|
u32 tunnel_id;
|
|
u32 tunnel_id;
|
|
|
u32 session_id;
|
|
u32 session_id;
|
|
@@ -59,14 +60,15 @@ static struct l2tp_session *l2tp_nl_session_find(struct genl_info *info)
|
|
|
|
|
|
|
|
if (info->attrs[L2TP_ATTR_IFNAME]) {
|
|
if (info->attrs[L2TP_ATTR_IFNAME]) {
|
|
|
ifname = nla_data(info->attrs[L2TP_ATTR_IFNAME]);
|
|
ifname = nla_data(info->attrs[L2TP_ATTR_IFNAME]);
|
|
|
- session = l2tp_session_find_by_ifname(net, ifname);
|
|
|
|
|
|
|
+ session = l2tp_session_get_by_ifname(net, ifname, do_ref);
|
|
|
} else if ((info->attrs[L2TP_ATTR_SESSION_ID]) &&
|
|
} else if ((info->attrs[L2TP_ATTR_SESSION_ID]) &&
|
|
|
(info->attrs[L2TP_ATTR_CONN_ID])) {
|
|
(info->attrs[L2TP_ATTR_CONN_ID])) {
|
|
|
tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_CONN_ID]);
|
|
tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_CONN_ID]);
|
|
|
session_id = nla_get_u32(info->attrs[L2TP_ATTR_SESSION_ID]);
|
|
session_id = nla_get_u32(info->attrs[L2TP_ATTR_SESSION_ID]);
|
|
|
tunnel = l2tp_tunnel_find(net, tunnel_id);
|
|
tunnel = l2tp_tunnel_find(net, tunnel_id);
|
|
|
if (tunnel)
|
|
if (tunnel)
|
|
|
- session = l2tp_session_find(net, tunnel, session_id);
|
|
|
|
|
|
|
+ session = l2tp_session_get(net, tunnel, session_id,
|
|
|
|
|
+ do_ref);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return session;
|
|
return session;
|
|
@@ -660,7 +662,7 @@ static int l2tp_nl_cmd_session_delete(struct sk_buff *skb, struct genl_info *inf
|
|
|
struct l2tp_session *session;
|
|
struct l2tp_session *session;
|
|
|
u16 pw_type;
|
|
u16 pw_type;
|
|
|
|
|
|
|
|
- session = l2tp_nl_session_find(info);
|
|
|
|
|
|
|
+ session = l2tp_nl_session_get(info, true);
|
|
|
if (session == NULL) {
|
|
if (session == NULL) {
|
|
|
ret = -ENODEV;
|
|
ret = -ENODEV;
|
|
|
goto out;
|
|
goto out;
|
|
@@ -674,6 +676,10 @@ static int l2tp_nl_cmd_session_delete(struct sk_buff *skb, struct genl_info *inf
|
|
|
if (l2tp_nl_cmd_ops[pw_type] && l2tp_nl_cmd_ops[pw_type]->session_delete)
|
|
if (l2tp_nl_cmd_ops[pw_type] && l2tp_nl_cmd_ops[pw_type]->session_delete)
|
|
|
ret = (*l2tp_nl_cmd_ops[pw_type]->session_delete)(session);
|
|
ret = (*l2tp_nl_cmd_ops[pw_type]->session_delete)(session);
|
|
|
|
|
|
|
|
|
|
+ if (session->deref)
|
|
|
|
|
+ session->deref(session);
|
|
|
|
|
+ l2tp_session_dec_refcount(session);
|
|
|
|
|
+
|
|
|
out:
|
|
out:
|
|
|
return ret;
|
|
return ret;
|
|
|
}
|
|
}
|
|
@@ -683,7 +689,7 @@ static int l2tp_nl_cmd_session_modify(struct sk_buff *skb, struct genl_info *inf
|
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
struct l2tp_session *session;
|
|
struct l2tp_session *session;
|
|
|
|
|
|
|
|
- session = l2tp_nl_session_find(info);
|
|
|
|
|
|
|
+ session = l2tp_nl_session_get(info, false);
|
|
|
if (session == NULL) {
|
|
if (session == NULL) {
|
|
|
ret = -ENODEV;
|
|
ret = -ENODEV;
|
|
|
goto out;
|
|
goto out;
|
|
@@ -718,6 +724,8 @@ static int l2tp_nl_cmd_session_modify(struct sk_buff *skb, struct genl_info *inf
|
|
|
ret = l2tp_session_notify(&l2tp_nl_family, info,
|
|
ret = l2tp_session_notify(&l2tp_nl_family, info,
|
|
|
session, L2TP_CMD_SESSION_MODIFY);
|
|
session, L2TP_CMD_SESSION_MODIFY);
|
|
|
|
|
|
|
|
|
|
+ l2tp_session_dec_refcount(session);
|
|
|
|
|
+
|
|
|
out:
|
|
out:
|
|
|
return ret;
|
|
return ret;
|
|
|
}
|
|
}
|
|
@@ -813,29 +821,34 @@ static int l2tp_nl_cmd_session_get(struct sk_buff *skb, struct genl_info *info)
|
|
|
struct sk_buff *msg;
|
|
struct sk_buff *msg;
|
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
|
|
- session = l2tp_nl_session_find(info);
|
|
|
|
|
|
|
+ session = l2tp_nl_session_get(info, false);
|
|
|
if (session == NULL) {
|
|
if (session == NULL) {
|
|
|
ret = -ENODEV;
|
|
ret = -ENODEV;
|
|
|
- goto out;
|
|
|
|
|
|
|
+ goto err;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
|
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
|
|
if (!msg) {
|
|
if (!msg) {
|
|
|
ret = -ENOMEM;
|
|
ret = -ENOMEM;
|
|
|
- goto out;
|
|
|
|
|
|
|
+ goto err_ref;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
ret = l2tp_nl_session_send(msg, info->snd_portid, info->snd_seq,
|
|
ret = l2tp_nl_session_send(msg, info->snd_portid, info->snd_seq,
|
|
|
0, session, L2TP_CMD_SESSION_GET);
|
|
0, session, L2TP_CMD_SESSION_GET);
|
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
|
- goto err_out;
|
|
|
|
|
|
|
+ goto err_ref_msg;
|
|
|
|
|
|
|
|
- return genlmsg_unicast(genl_info_net(info), msg, info->snd_portid);
|
|
|
|
|
|
|
+ ret = genlmsg_unicast(genl_info_net(info), msg, info->snd_portid);
|
|
|
|
|
|
|
|
-err_out:
|
|
|
|
|
- nlmsg_free(msg);
|
|
|
|
|
|
|
+ l2tp_session_dec_refcount(session);
|
|
|
|
|
|
|
|
-out:
|
|
|
|
|
|
|
+ return ret;
|
|
|
|
|
+
|
|
|
|
|
+err_ref_msg:
|
|
|
|
|
+ nlmsg_free(msg);
|
|
|
|
|
+err_ref:
|
|
|
|
|
+ l2tp_session_dec_refcount(session);
|
|
|
|
|
+err:
|
|
|
return ret;
|
|
return ret;
|
|
|
}
|
|
}
|
|
|
|
|
|