* [PATCH net-next 4/8] sctp: add SCTP_ASCONF_SUPPORTED sockopt
@ 2019-08-19 14:02 ` Xin Long
0 siblings, 0 replies; 32+ messages in thread
From: Xin Long @ 2019-08-19 14:02 UTC (permalink / raw)
To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem
SCTP_ASCONF_SUPPORTED sockopt is used to set enpoint's asconf
flag. With this feature, each endpoint will have its own flag
for its future asoc's asconf_capable, instead of netns asconf
flag.
Note that when both ep's asconf_enable and auth_enable are
enabled, SCTP_CID_ASCONF and SCTP_CID_ASCONF_ACK should be
added into auth_chunk_list.
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
include/uapi/linux/sctp.h | 1 +
net/sctp/socket.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 83 insertions(+)
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index b8f2c4d..9b9b82d 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -134,6 +134,7 @@ typedef __s32 sctp_assoc_t;
#define SCTP_INTERLEAVING_SUPPORTED 125
#define SCTP_SENDMSG_CONNECT 126
#define SCTP_EVENT 127
+#define SCTP_ASCONF_SUPPORTED 128
/* PR-SCTP policies */
#define SCTP_PR_SCTP_NONE 0x0000
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 559793f..b21a707 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4496,6 +4496,42 @@ static int sctp_setsockopt_event(struct sock *sk, char __user *optval,
return retval;
}
+static int sctp_setsockopt_asconf_supported(struct sock *sk,
+ char __user *optval,
+ unsigned int optlen)
+{
+ struct sctp_assoc_value params;
+ struct sctp_association *asoc;
+ struct sctp_endpoint *ep;
+ int retval = -EINVAL;
+
+ if (optlen != sizeof(params))
+ goto out;
+
+ if (copy_from_user(¶ms, optval, optlen)) {
+ retval = -EFAULT;
+ goto out;
+ }
+
+ asoc = sctp_id2assoc(sk, params.assoc_id);
+ if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC &&
+ sctp_style(sk, UDP))
+ goto out;
+
+ ep = sctp_sk(sk)->ep;
+ ep->asconf_enable = !!params.assoc_value;
+
+ if (ep->asconf_enable && ep->auth_enable) {
+ sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF);
+ sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF_ACK);
+ }
+
+ retval = 0;
+
+out:
+ return retval;
+}
+
/* API 6.2 setsockopt(), getsockopt()
*
* Applications use setsockopt() and getsockopt() to set or retrieve
@@ -4696,6 +4732,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname,
case SCTP_EVENT:
retval = sctp_setsockopt_event(sk, optval, optlen);
break;
+ case SCTP_ASCONF_SUPPORTED:
+ retval = sctp_setsockopt_asconf_supported(sk, optval, optlen);
+ break;
default:
retval = -ENOPROTOOPT;
break;
@@ -7675,6 +7714,45 @@ static int sctp_getsockopt_event(struct sock *sk, int len, char __user *optval,
return 0;
}
+static int sctp_getsockopt_asconf_supported(struct sock *sk, int len,
+ char __user *optval,
+ int __user *optlen)
+{
+ struct sctp_assoc_value params;
+ struct sctp_association *asoc;
+ int retval = -EFAULT;
+
+ if (len < sizeof(params)) {
+ retval = -EINVAL;
+ goto out;
+ }
+
+ len = sizeof(params);
+ if (copy_from_user(¶ms, optval, len))
+ goto out;
+
+ asoc = sctp_id2assoc(sk, params.assoc_id);
+ if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC &&
+ sctp_style(sk, UDP)) {
+ retval = -EINVAL;
+ goto out;
+ }
+
+ params.assoc_value = asoc ? asoc->peer.asconf_capable
+ : sctp_sk(sk)->ep->asconf_enable;
+
+ if (put_user(len, optlen))
+ goto out;
+
+ if (copy_to_user(optval, ¶ms, len))
+ goto out;
+
+ retval = 0;
+
+out:
+ return retval;
+}
+
static int sctp_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen)
{
@@ -7876,6 +7954,10 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname,
case SCTP_EVENT:
retval = sctp_getsockopt_event(sk, len, optval, optlen);
break;
+ case SCTP_ASCONF_SUPPORTED:
+ retval = sctp_getsockopt_asconf_supported(sk, len, optval,
+ optlen);
+ break;
default:
retval = -ENOPROTOOPT;
break;
--
2.1.0
^ permalink raw reply related [flat|nested] 32+ messages in thread* [PATCH net-next 5/8] sctp: use ep and asoc auth_enable properly
2019-08-19 14:02 ` Xin Long
@ 2019-08-19 14:02 ` Xin Long
-1 siblings, 0 replies; 32+ messages in thread
From: Xin Long @ 2019-08-19 14:02 UTC (permalink / raw)
To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem
sctp has per endpoint auth flag and per asoc auth flag, and
the asoc one should be checked when coming to asoc and the
endpoint one should be checked when coming to endpoint.
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
net/sctp/auth.c | 32 +++++++++++++++++++++++++-------
net/sctp/socket.c | 45 +++++++++++++++++++--------------------------
2 files changed, 44 insertions(+), 33 deletions(-)
diff --git a/net/sctp/auth.c b/net/sctp/auth.c
index de4c78d..61b0090 100644
--- a/net/sctp/auth.c
+++ b/net/sctp/auth.c
@@ -389,7 +389,7 @@ int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp)
/* If we don't support AUTH, or peer is not capable
* we don't need to do anything.
*/
- if (!asoc->ep->auth_enable || !asoc->peer.auth_capable)
+ if (!asoc->peer.auth_capable)
return 0;
/* If the key_id is non-zero and we couldn't find an
@@ -675,7 +675,7 @@ int sctp_auth_send_cid(enum sctp_cid chunk, const struct sctp_association *asoc)
if (!asoc)
return 0;
- if (!asoc->ep->auth_enable || !asoc->peer.auth_capable)
+ if (!asoc->peer.auth_capable)
return 0;
return __sctp_auth_cid(chunk, asoc->peer.peer_chunks);
@@ -687,7 +687,7 @@ int sctp_auth_recv_cid(enum sctp_cid chunk, const struct sctp_association *asoc)
if (!asoc)
return 0;
- if (!asoc->ep->auth_enable)
+ if (!asoc->peer.auth_capable)
return 0;
return __sctp_auth_cid(chunk,
@@ -831,10 +831,15 @@ int sctp_auth_set_key(struct sctp_endpoint *ep,
/* Try to find the given key id to see if
* we are doing a replace, or adding a new key
*/
- if (asoc)
+ if (asoc) {
+ if (!asoc->peer.auth_capable)
+ return -EACCES;
sh_keys = &asoc->endpoint_shared_keys;
- else
+ } else {
+ if (!ep->auth_enable)
+ return -EACCES;
sh_keys = &ep->endpoint_shared_keys;
+ }
key_for_each(shkey, sh_keys) {
if (shkey->key_id = auth_key->sca_keynumber) {
@@ -875,10 +880,15 @@ int sctp_auth_set_active_key(struct sctp_endpoint *ep,
int found = 0;
/* The key identifier MUST correst to an existing key */
- if (asoc)
+ if (asoc) {
+ if (!asoc->peer.auth_capable)
+ return -EACCES;
sh_keys = &asoc->endpoint_shared_keys;
- else
+ } else {
+ if (!ep->auth_enable)
+ return -EACCES;
sh_keys = &ep->endpoint_shared_keys;
+ }
key_for_each(key, sh_keys) {
if (key->key_id = key_id) {
@@ -911,11 +921,15 @@ int sctp_auth_del_key_id(struct sctp_endpoint *ep,
* The key identifier MUST correst to an existing key
*/
if (asoc) {
+ if (!asoc->peer.auth_capable)
+ return -EACCES;
if (asoc->active_key_id = key_id)
return -EINVAL;
sh_keys = &asoc->endpoint_shared_keys;
} else {
+ if (!ep->auth_enable)
+ return -EACCES;
if (ep->active_key_id = key_id)
return -EINVAL;
@@ -950,11 +964,15 @@ int sctp_auth_deact_key_id(struct sctp_endpoint *ep,
* The key identifier MUST correst to an existing key
*/
if (asoc) {
+ if (!asoc->peer.auth_capable)
+ return -EACCES;
if (asoc->active_key_id = key_id)
return -EINVAL;
sh_keys = &asoc->endpoint_shared_keys;
} else {
+ if (!ep->auth_enable)
+ return -EACCES;
if (ep->active_key_id = key_id)
return -EINVAL;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index b21a707..dcde8d9 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3687,9 +3687,6 @@ static int sctp_setsockopt_auth_key(struct sock *sk,
struct sctp_association *asoc;
int ret = -EINVAL;
- if (!ep->auth_enable)
- return -EACCES;
-
if (optlen <= sizeof(struct sctp_authkey))
return -EINVAL;
/* authkey->sca_keylength is u16, so optlen can't be bigger than
@@ -3756,9 +3753,6 @@ static int sctp_setsockopt_active_key(struct sock *sk,
struct sctp_authkeyid val;
int ret = 0;
- if (!ep->auth_enable)
- return -EACCES;
-
if (optlen != sizeof(struct sctp_authkeyid))
return -EINVAL;
if (copy_from_user(&val, optval, optlen))
@@ -3810,9 +3804,6 @@ static int sctp_setsockopt_del_key(struct sock *sk,
struct sctp_authkeyid val;
int ret = 0;
- if (!ep->auth_enable)
- return -EACCES;
-
if (optlen != sizeof(struct sctp_authkeyid))
return -EINVAL;
if (copy_from_user(&val, optval, optlen))
@@ -3863,9 +3854,6 @@ static int sctp_setsockopt_deactivate_key(struct sock *sk, char __user *optval,
struct sctp_authkeyid val;
int ret = 0;
- if (!ep->auth_enable)
- return -EACCES;
-
if (optlen != sizeof(struct sctp_authkeyid))
return -EINVAL;
if (copy_from_user(&val, optval, optlen))
@@ -6872,9 +6860,6 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len,
struct sctp_authkeyid val;
struct sctp_association *asoc;
- if (!ep->auth_enable)
- return -EACCES;
-
if (len < sizeof(struct sctp_authkeyid))
return -EINVAL;
@@ -6886,10 +6871,15 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len,
if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP))
return -EINVAL;
- if (asoc)
+ if (asoc) {
+ if (!asoc->peer.auth_capable)
+ return -EACCES;
val.scact_keynumber = asoc->active_key_id;
- else
+ } else {
+ if (!ep->auth_enable)
+ return -EACCES;
val.scact_keynumber = ep->active_key_id;
+ }
if (put_user(len, optlen))
return -EFAULT;
@@ -6902,7 +6892,6 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len,
static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
char __user *optval, int __user *optlen)
{
- struct sctp_endpoint *ep = sctp_sk(sk)->ep;
struct sctp_authchunks __user *p = (void __user *)optval;
struct sctp_authchunks val;
struct sctp_association *asoc;
@@ -6910,9 +6899,6 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
u32 num_chunks = 0;
char __user *to;
- if (!ep->auth_enable)
- return -EACCES;
-
if (len < sizeof(struct sctp_authchunks))
return -EINVAL;
@@ -6924,6 +6910,9 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
if (!asoc)
return -EINVAL;
+ if (!asoc->peer.auth_capable)
+ return -EACCES;
+
ch = asoc->peer.peer_chunks;
if (!ch)
goto num;
@@ -6955,9 +6944,6 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len,
u32 num_chunks = 0;
char __user *to;
- if (!ep->auth_enable)
- return -EACCES;
-
if (len < sizeof(struct sctp_authchunks))
return -EINVAL;
@@ -6970,8 +6956,15 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len,
sctp_style(sk, UDP))
return -EINVAL;
- ch = asoc ? (struct sctp_chunks_param *)asoc->c.auth_chunks
- : ep->auth_chunk_list;
+ if (asoc) {
+ if (!asoc->peer.auth_capable)
+ return -EACCES;
+ ch = (struct sctp_chunks_param *)asoc->c.auth_chunks;
+ } else {
+ if (!ep->auth_enable)
+ return -EACCES;
+ ch = ep->auth_chunk_list;
+ }
if (!ch)
goto num;
--
2.1.0
^ permalink raw reply related [flat|nested] 32+ messages in thread* [PATCH net-next 5/8] sctp: use ep and asoc auth_enable properly
@ 2019-08-19 14:02 ` Xin Long
0 siblings, 0 replies; 32+ messages in thread
From: Xin Long @ 2019-08-19 14:02 UTC (permalink / raw)
To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem
sctp has per endpoint auth flag and per asoc auth flag, and
the asoc one should be checked when coming to asoc and the
endpoint one should be checked when coming to endpoint.
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
net/sctp/auth.c | 32 +++++++++++++++++++++++++-------
net/sctp/socket.c | 45 +++++++++++++++++++--------------------------
2 files changed, 44 insertions(+), 33 deletions(-)
diff --git a/net/sctp/auth.c b/net/sctp/auth.c
index de4c78d..61b0090 100644
--- a/net/sctp/auth.c
+++ b/net/sctp/auth.c
@@ -389,7 +389,7 @@ int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp)
/* If we don't support AUTH, or peer is not capable
* we don't need to do anything.
*/
- if (!asoc->ep->auth_enable || !asoc->peer.auth_capable)
+ if (!asoc->peer.auth_capable)
return 0;
/* If the key_id is non-zero and we couldn't find an
@@ -675,7 +675,7 @@ int sctp_auth_send_cid(enum sctp_cid chunk, const struct sctp_association *asoc)
if (!asoc)
return 0;
- if (!asoc->ep->auth_enable || !asoc->peer.auth_capable)
+ if (!asoc->peer.auth_capable)
return 0;
return __sctp_auth_cid(chunk, asoc->peer.peer_chunks);
@@ -687,7 +687,7 @@ int sctp_auth_recv_cid(enum sctp_cid chunk, const struct sctp_association *asoc)
if (!asoc)
return 0;
- if (!asoc->ep->auth_enable)
+ if (!asoc->peer.auth_capable)
return 0;
return __sctp_auth_cid(chunk,
@@ -831,10 +831,15 @@ int sctp_auth_set_key(struct sctp_endpoint *ep,
/* Try to find the given key id to see if
* we are doing a replace, or adding a new key
*/
- if (asoc)
+ if (asoc) {
+ if (!asoc->peer.auth_capable)
+ return -EACCES;
sh_keys = &asoc->endpoint_shared_keys;
- else
+ } else {
+ if (!ep->auth_enable)
+ return -EACCES;
sh_keys = &ep->endpoint_shared_keys;
+ }
key_for_each(shkey, sh_keys) {
if (shkey->key_id == auth_key->sca_keynumber) {
@@ -875,10 +880,15 @@ int sctp_auth_set_active_key(struct sctp_endpoint *ep,
int found = 0;
/* The key identifier MUST correst to an existing key */
- if (asoc)
+ if (asoc) {
+ if (!asoc->peer.auth_capable)
+ return -EACCES;
sh_keys = &asoc->endpoint_shared_keys;
- else
+ } else {
+ if (!ep->auth_enable)
+ return -EACCES;
sh_keys = &ep->endpoint_shared_keys;
+ }
key_for_each(key, sh_keys) {
if (key->key_id == key_id) {
@@ -911,11 +921,15 @@ int sctp_auth_del_key_id(struct sctp_endpoint *ep,
* The key identifier MUST correst to an existing key
*/
if (asoc) {
+ if (!asoc->peer.auth_capable)
+ return -EACCES;
if (asoc->active_key_id == key_id)
return -EINVAL;
sh_keys = &asoc->endpoint_shared_keys;
} else {
+ if (!ep->auth_enable)
+ return -EACCES;
if (ep->active_key_id == key_id)
return -EINVAL;
@@ -950,11 +964,15 @@ int sctp_auth_deact_key_id(struct sctp_endpoint *ep,
* The key identifier MUST correst to an existing key
*/
if (asoc) {
+ if (!asoc->peer.auth_capable)
+ return -EACCES;
if (asoc->active_key_id == key_id)
return -EINVAL;
sh_keys = &asoc->endpoint_shared_keys;
} else {
+ if (!ep->auth_enable)
+ return -EACCES;
if (ep->active_key_id == key_id)
return -EINVAL;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index b21a707..dcde8d9 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3687,9 +3687,6 @@ static int sctp_setsockopt_auth_key(struct sock *sk,
struct sctp_association *asoc;
int ret = -EINVAL;
- if (!ep->auth_enable)
- return -EACCES;
-
if (optlen <= sizeof(struct sctp_authkey))
return -EINVAL;
/* authkey->sca_keylength is u16, so optlen can't be bigger than
@@ -3756,9 +3753,6 @@ static int sctp_setsockopt_active_key(struct sock *sk,
struct sctp_authkeyid val;
int ret = 0;
- if (!ep->auth_enable)
- return -EACCES;
-
if (optlen != sizeof(struct sctp_authkeyid))
return -EINVAL;
if (copy_from_user(&val, optval, optlen))
@@ -3810,9 +3804,6 @@ static int sctp_setsockopt_del_key(struct sock *sk,
struct sctp_authkeyid val;
int ret = 0;
- if (!ep->auth_enable)
- return -EACCES;
-
if (optlen != sizeof(struct sctp_authkeyid))
return -EINVAL;
if (copy_from_user(&val, optval, optlen))
@@ -3863,9 +3854,6 @@ static int sctp_setsockopt_deactivate_key(struct sock *sk, char __user *optval,
struct sctp_authkeyid val;
int ret = 0;
- if (!ep->auth_enable)
- return -EACCES;
-
if (optlen != sizeof(struct sctp_authkeyid))
return -EINVAL;
if (copy_from_user(&val, optval, optlen))
@@ -6872,9 +6860,6 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len,
struct sctp_authkeyid val;
struct sctp_association *asoc;
- if (!ep->auth_enable)
- return -EACCES;
-
if (len < sizeof(struct sctp_authkeyid))
return -EINVAL;
@@ -6886,10 +6871,15 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len,
if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP))
return -EINVAL;
- if (asoc)
+ if (asoc) {
+ if (!asoc->peer.auth_capable)
+ return -EACCES;
val.scact_keynumber = asoc->active_key_id;
- else
+ } else {
+ if (!ep->auth_enable)
+ return -EACCES;
val.scact_keynumber = ep->active_key_id;
+ }
if (put_user(len, optlen))
return -EFAULT;
@@ -6902,7 +6892,6 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len,
static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
char __user *optval, int __user *optlen)
{
- struct sctp_endpoint *ep = sctp_sk(sk)->ep;
struct sctp_authchunks __user *p = (void __user *)optval;
struct sctp_authchunks val;
struct sctp_association *asoc;
@@ -6910,9 +6899,6 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
u32 num_chunks = 0;
char __user *to;
- if (!ep->auth_enable)
- return -EACCES;
-
if (len < sizeof(struct sctp_authchunks))
return -EINVAL;
@@ -6924,6 +6910,9 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
if (!asoc)
return -EINVAL;
+ if (!asoc->peer.auth_capable)
+ return -EACCES;
+
ch = asoc->peer.peer_chunks;
if (!ch)
goto num;
@@ -6955,9 +6944,6 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len,
u32 num_chunks = 0;
char __user *to;
- if (!ep->auth_enable)
- return -EACCES;
-
if (len < sizeof(struct sctp_authchunks))
return -EINVAL;
@@ -6970,8 +6956,15 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len,
sctp_style(sk, UDP))
return -EINVAL;
- ch = asoc ? (struct sctp_chunks_param *)asoc->c.auth_chunks
- : ep->auth_chunk_list;
+ if (asoc) {
+ if (!asoc->peer.auth_capable)
+ return -EACCES;
+ ch = (struct sctp_chunks_param *)asoc->c.auth_chunks;
+ } else {
+ if (!ep->auth_enable)
+ return -EACCES;
+ ch = ep->auth_chunk_list;
+ }
if (!ch)
goto num;
--
2.1.0
^ permalink raw reply related [flat|nested] 32+ messages in thread* [PATCH net-next 6/8] sctp: add sctp_auth_init and sctp_auth_free
2019-08-19 14:02 ` Xin Long
@ 2019-08-19 14:02 ` Xin Long
-1 siblings, 0 replies; 32+ messages in thread
From: Xin Long @ 2019-08-19 14:02 UTC (permalink / raw)
To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem
This patch is to factor out sctp_auth_init and sctp_auth_free
functions, and sctp_auth_init will also be used in the next
patch for SCTP_AUTH_SUPPORTED sockopt.
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
include/net/sctp/auth.h | 2 ++
net/sctp/auth.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++
net/sctp/endpointola.c | 61 ++++---------------------------------------
3 files changed, 76 insertions(+), 56 deletions(-)
diff --git a/include/net/sctp/auth.h b/include/net/sctp/auth.h
index caaae2d..d4b3b2d 100644
--- a/include/net/sctp/auth.h
+++ b/include/net/sctp/auth.h
@@ -107,5 +107,7 @@ int sctp_auth_del_key_id(struct sctp_endpoint *ep,
struct sctp_association *asoc, __u16 key_id);
int sctp_auth_deact_key_id(struct sctp_endpoint *ep,
struct sctp_association *asoc, __u16 key_id);
+int sctp_auth_init(struct sctp_endpoint *ep, gfp_t gfp);
+void sctp_auth_free(struct sctp_endpoint *ep);
#endif
diff --git a/net/sctp/auth.c b/net/sctp/auth.c
index 61b0090..4278764 100644
--- a/net/sctp/auth.c
+++ b/net/sctp/auth.c
@@ -1007,3 +1007,72 @@ int sctp_auth_deact_key_id(struct sctp_endpoint *ep,
return 0;
}
+
+int sctp_auth_init(struct sctp_endpoint *ep, gfp_t gfp)
+{
+ int err = -ENOMEM;
+
+ /* Allocate space for HMACS and CHUNKS authentication
+ * variables. There are arrays that we encode directly
+ * into parameters to make the rest of the operations easier.
+ */
+ if (!ep->auth_hmacs_list) {
+ struct sctp_hmac_algo_param *auth_hmacs;
+
+ auth_hmacs = kzalloc(struct_size(auth_hmacs, hmac_ids,
+ SCTP_AUTH_NUM_HMACS), gfp);
+ if (!auth_hmacs)
+ goto nomem;
+ /* Initialize the HMACS parameter.
+ * SCTP-AUTH: Section 3.3
+ * Every endpoint supporting SCTP chunk authentication MUST
+ * support the HMAC based on the SHA-1 algorithm.
+ */
+ auth_hmacs->param_hdr.type = SCTP_PARAM_HMAC_ALGO;
+ auth_hmacs->param_hdr.length + htons(sizeof(struct sctp_paramhdr) + 2);
+ auth_hmacs->hmac_ids[0] = htons(SCTP_AUTH_HMAC_ID_SHA1);
+ ep->auth_hmacs_list = auth_hmacs;
+ }
+
+ if (!ep->auth_chunk_list) {
+ struct sctp_chunks_param *auth_chunks;
+
+ auth_chunks = kzalloc(sizeof(*auth_chunks) +
+ SCTP_NUM_CHUNK_TYPES, gfp);
+ if (!auth_chunks)
+ goto nomem;
+ /* Initialize the CHUNKS parameter */
+ auth_chunks->param_hdr.type = SCTP_PARAM_CHUNKS;
+ auth_chunks->param_hdr.length + htons(sizeof(struct sctp_paramhdr));
+ ep->auth_chunk_list = auth_chunks;
+ }
+
+ /* Allocate and initialize transorms arrays for supported
+ * HMACs.
+ */
+ err = sctp_auth_init_hmacs(ep, gfp);
+ if (err)
+ goto nomem;
+
+ return 0;
+
+nomem:
+ /* Free all allocations */
+ kfree(ep->auth_hmacs_list);
+ kfree(ep->auth_chunk_list);
+ ep->auth_hmacs_list = NULL;
+ ep->auth_chunk_list = NULL;
+ return err;
+}
+
+void sctp_auth_free(struct sctp_endpoint *ep)
+{
+ kfree(ep->auth_hmacs_list);
+ kfree(ep->auth_chunk_list);
+ ep->auth_hmacs_list = NULL;
+ ep->auth_chunk_list = NULL;
+ sctp_auth_destroy_hmacs(ep->auth_hmacs);
+ ep->auth_hmacs = NULL;
+}
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 38b8d7c..75a407d 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -43,10 +43,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
gfp_t gfp)
{
struct net *net = sock_net(sk);
- struct sctp_hmac_algo_param *auth_hmacs = NULL;
- struct sctp_chunks_param *auth_chunks = NULL;
struct sctp_shared_key *null_key;
- int err;
ep->digest = kzalloc(SCTP_SIGNATURE_SIZE, gfp);
if (!ep->digest)
@@ -55,51 +52,12 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
ep->asconf_enable = net->sctp.addip_enable;
ep->auth_enable = net->sctp.auth_enable;
if (ep->auth_enable) {
- /* Allocate space for HMACS and CHUNKS authentication
- * variables. There are arrays that we encode directly
- * into parameters to make the rest of the operations easier.
- */
- auth_hmacs = kzalloc(struct_size(auth_hmacs, hmac_ids,
- SCTP_AUTH_NUM_HMACS), gfp);
- if (!auth_hmacs)
- goto nomem;
-
- auth_chunks = kzalloc(sizeof(*auth_chunks) +
- SCTP_NUM_CHUNK_TYPES, gfp);
- if (!auth_chunks)
+ if (sctp_auth_init(ep, gfp))
goto nomem;
-
- /* Initialize the HMACS parameter.
- * SCTP-AUTH: Section 3.3
- * Every endpoint supporting SCTP chunk authentication MUST
- * support the HMAC based on the SHA-1 algorithm.
- */
- auth_hmacs->param_hdr.type = SCTP_PARAM_HMAC_ALGO;
- auth_hmacs->param_hdr.length - htons(sizeof(struct sctp_paramhdr) + 2);
- auth_hmacs->hmac_ids[0] = htons(SCTP_AUTH_HMAC_ID_SHA1);
-
- /* Initialize the CHUNKS parameter */
- auth_chunks->param_hdr.type = SCTP_PARAM_CHUNKS;
- auth_chunks->param_hdr.length - htons(sizeof(struct sctp_paramhdr));
-
- /* If the Add-IP functionality is enabled, we must
- * authenticate, ASCONF and ASCONF-ACK chunks
- */
if (ep->asconf_enable) {
- auth_chunks->chunks[0] = SCTP_CID_ASCONF;
- auth_chunks->chunks[1] = SCTP_CID_ASCONF_ACK;
- auth_chunks->param_hdr.length - htons(sizeof(struct sctp_paramhdr) + 2);
+ sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF);
+ sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF_ACK);
}
-
- /* Allocate and initialize transorms arrays for supported
- * HMACs.
- */
- err = sctp_auth_init_hmacs(ep, gfp);
- if (err)
- goto nomem;
}
/* Initialize the base structure. */
@@ -146,8 +104,6 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
/* Add the null key to the endpoint shared keys list and
* set the hmcas and chunks pointers.
*/
- ep->auth_hmacs_list = auth_hmacs;
- ep->auth_chunk_list = auth_chunks;
ep->prsctp_enable = net->sctp.prsctp_enable;
ep->reconf_enable = net->sctp.reconf_enable;
@@ -158,11 +114,8 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
return ep;
nomem_shkey:
- sctp_auth_destroy_hmacs(ep->auth_hmacs);
+ sctp_auth_free(ep);
nomem:
- /* Free all allocations */
- kfree(auth_hmacs);
- kfree(auth_chunks);
kfree(ep->digest);
return NULL;
@@ -245,11 +198,7 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep)
* chunks and hmacs arrays that were allocated
*/
sctp_auth_destroy_keys(&ep->endpoint_shared_keys);
- kfree(ep->auth_hmacs_list);
- kfree(ep->auth_chunk_list);
-
- /* AUTH - Free any allocated HMAC transform containers */
- sctp_auth_destroy_hmacs(ep->auth_hmacs);
+ sctp_auth_free(ep);
/* Cleanup. */
sctp_inq_free(&ep->base.inqueue);
--
2.1.0
^ permalink raw reply related [flat|nested] 32+ messages in thread* [PATCH net-next 6/8] sctp: add sctp_auth_init and sctp_auth_free
@ 2019-08-19 14:02 ` Xin Long
0 siblings, 0 replies; 32+ messages in thread
From: Xin Long @ 2019-08-19 14:02 UTC (permalink / raw)
To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem
This patch is to factor out sctp_auth_init and sctp_auth_free
functions, and sctp_auth_init will also be used in the next
patch for SCTP_AUTH_SUPPORTED sockopt.
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
include/net/sctp/auth.h | 2 ++
net/sctp/auth.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++
net/sctp/endpointola.c | 61 ++++---------------------------------------
3 files changed, 76 insertions(+), 56 deletions(-)
diff --git a/include/net/sctp/auth.h b/include/net/sctp/auth.h
index caaae2d..d4b3b2d 100644
--- a/include/net/sctp/auth.h
+++ b/include/net/sctp/auth.h
@@ -107,5 +107,7 @@ int sctp_auth_del_key_id(struct sctp_endpoint *ep,
struct sctp_association *asoc, __u16 key_id);
int sctp_auth_deact_key_id(struct sctp_endpoint *ep,
struct sctp_association *asoc, __u16 key_id);
+int sctp_auth_init(struct sctp_endpoint *ep, gfp_t gfp);
+void sctp_auth_free(struct sctp_endpoint *ep);
#endif
diff --git a/net/sctp/auth.c b/net/sctp/auth.c
index 61b0090..4278764 100644
--- a/net/sctp/auth.c
+++ b/net/sctp/auth.c
@@ -1007,3 +1007,72 @@ int sctp_auth_deact_key_id(struct sctp_endpoint *ep,
return 0;
}
+
+int sctp_auth_init(struct sctp_endpoint *ep, gfp_t gfp)
+{
+ int err = -ENOMEM;
+
+ /* Allocate space for HMACS and CHUNKS authentication
+ * variables. There are arrays that we encode directly
+ * into parameters to make the rest of the operations easier.
+ */
+ if (!ep->auth_hmacs_list) {
+ struct sctp_hmac_algo_param *auth_hmacs;
+
+ auth_hmacs = kzalloc(struct_size(auth_hmacs, hmac_ids,
+ SCTP_AUTH_NUM_HMACS), gfp);
+ if (!auth_hmacs)
+ goto nomem;
+ /* Initialize the HMACS parameter.
+ * SCTP-AUTH: Section 3.3
+ * Every endpoint supporting SCTP chunk authentication MUST
+ * support the HMAC based on the SHA-1 algorithm.
+ */
+ auth_hmacs->param_hdr.type = SCTP_PARAM_HMAC_ALGO;
+ auth_hmacs->param_hdr.length =
+ htons(sizeof(struct sctp_paramhdr) + 2);
+ auth_hmacs->hmac_ids[0] = htons(SCTP_AUTH_HMAC_ID_SHA1);
+ ep->auth_hmacs_list = auth_hmacs;
+ }
+
+ if (!ep->auth_chunk_list) {
+ struct sctp_chunks_param *auth_chunks;
+
+ auth_chunks = kzalloc(sizeof(*auth_chunks) +
+ SCTP_NUM_CHUNK_TYPES, gfp);
+ if (!auth_chunks)
+ goto nomem;
+ /* Initialize the CHUNKS parameter */
+ auth_chunks->param_hdr.type = SCTP_PARAM_CHUNKS;
+ auth_chunks->param_hdr.length =
+ htons(sizeof(struct sctp_paramhdr));
+ ep->auth_chunk_list = auth_chunks;
+ }
+
+ /* Allocate and initialize transorms arrays for supported
+ * HMACs.
+ */
+ err = sctp_auth_init_hmacs(ep, gfp);
+ if (err)
+ goto nomem;
+
+ return 0;
+
+nomem:
+ /* Free all allocations */
+ kfree(ep->auth_hmacs_list);
+ kfree(ep->auth_chunk_list);
+ ep->auth_hmacs_list = NULL;
+ ep->auth_chunk_list = NULL;
+ return err;
+}
+
+void sctp_auth_free(struct sctp_endpoint *ep)
+{
+ kfree(ep->auth_hmacs_list);
+ kfree(ep->auth_chunk_list);
+ ep->auth_hmacs_list = NULL;
+ ep->auth_chunk_list = NULL;
+ sctp_auth_destroy_hmacs(ep->auth_hmacs);
+ ep->auth_hmacs = NULL;
+}
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 38b8d7c..75a407d 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -43,10 +43,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
gfp_t gfp)
{
struct net *net = sock_net(sk);
- struct sctp_hmac_algo_param *auth_hmacs = NULL;
- struct sctp_chunks_param *auth_chunks = NULL;
struct sctp_shared_key *null_key;
- int err;
ep->digest = kzalloc(SCTP_SIGNATURE_SIZE, gfp);
if (!ep->digest)
@@ -55,51 +52,12 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
ep->asconf_enable = net->sctp.addip_enable;
ep->auth_enable = net->sctp.auth_enable;
if (ep->auth_enable) {
- /* Allocate space for HMACS and CHUNKS authentication
- * variables. There are arrays that we encode directly
- * into parameters to make the rest of the operations easier.
- */
- auth_hmacs = kzalloc(struct_size(auth_hmacs, hmac_ids,
- SCTP_AUTH_NUM_HMACS), gfp);
- if (!auth_hmacs)
- goto nomem;
-
- auth_chunks = kzalloc(sizeof(*auth_chunks) +
- SCTP_NUM_CHUNK_TYPES, gfp);
- if (!auth_chunks)
+ if (sctp_auth_init(ep, gfp))
goto nomem;
-
- /* Initialize the HMACS parameter.
- * SCTP-AUTH: Section 3.3
- * Every endpoint supporting SCTP chunk authentication MUST
- * support the HMAC based on the SHA-1 algorithm.
- */
- auth_hmacs->param_hdr.type = SCTP_PARAM_HMAC_ALGO;
- auth_hmacs->param_hdr.length =
- htons(sizeof(struct sctp_paramhdr) + 2);
- auth_hmacs->hmac_ids[0] = htons(SCTP_AUTH_HMAC_ID_SHA1);
-
- /* Initialize the CHUNKS parameter */
- auth_chunks->param_hdr.type = SCTP_PARAM_CHUNKS;
- auth_chunks->param_hdr.length =
- htons(sizeof(struct sctp_paramhdr));
-
- /* If the Add-IP functionality is enabled, we must
- * authenticate, ASCONF and ASCONF-ACK chunks
- */
if (ep->asconf_enable) {
- auth_chunks->chunks[0] = SCTP_CID_ASCONF;
- auth_chunks->chunks[1] = SCTP_CID_ASCONF_ACK;
- auth_chunks->param_hdr.length =
- htons(sizeof(struct sctp_paramhdr) + 2);
+ sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF);
+ sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF_ACK);
}
-
- /* Allocate and initialize transorms arrays for supported
- * HMACs.
- */
- err = sctp_auth_init_hmacs(ep, gfp);
- if (err)
- goto nomem;
}
/* Initialize the base structure. */
@@ -146,8 +104,6 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
/* Add the null key to the endpoint shared keys list and
* set the hmcas and chunks pointers.
*/
- ep->auth_hmacs_list = auth_hmacs;
- ep->auth_chunk_list = auth_chunks;
ep->prsctp_enable = net->sctp.prsctp_enable;
ep->reconf_enable = net->sctp.reconf_enable;
@@ -158,11 +114,8 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
return ep;
nomem_shkey:
- sctp_auth_destroy_hmacs(ep->auth_hmacs);
+ sctp_auth_free(ep);
nomem:
- /* Free all allocations */
- kfree(auth_hmacs);
- kfree(auth_chunks);
kfree(ep->digest);
return NULL;
@@ -245,11 +198,7 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep)
* chunks and hmacs arrays that were allocated
*/
sctp_auth_destroy_keys(&ep->endpoint_shared_keys);
- kfree(ep->auth_hmacs_list);
- kfree(ep->auth_chunk_list);
-
- /* AUTH - Free any allocated HMAC transform containers */
- sctp_auth_destroy_hmacs(ep->auth_hmacs);
+ sctp_auth_free(ep);
/* Cleanup. */
sctp_inq_free(&ep->base.inqueue);
--
2.1.0
^ permalink raw reply related [flat|nested] 32+ messages in thread* [PATCH net-next 7/8] sctp: add SCTP_AUTH_SUPPORTED sockopt
2019-08-19 14:02 ` Xin Long
@ 2019-08-19 14:02 ` Xin Long
-1 siblings, 0 replies; 32+ messages in thread
From: Xin Long @ 2019-08-19 14:02 UTC (permalink / raw)
To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem
SCTP_AUTH_SUPPORTED sockopt is used to set enpoint's auth
flag. With this feature, each endpoint will have its own
flag for its future asoc's auth_capable, instead of netns
auth flag.
Note that when both ep's auth_enable is enabled, endpoint
auth related data should be initialized. If asconf_enable
is also set, SCTP_CID_ASCONF/SCTP_CID_ASCONF_ACK should
be added into auth_chunk_list.
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
include/uapi/linux/sctp.h | 1 +
net/sctp/socket.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 87 insertions(+)
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index 9b9b82d..62527ac 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -135,6 +135,7 @@ typedef __s32 sctp_assoc_t;
#define SCTP_SENDMSG_CONNECT 126
#define SCTP_EVENT 127
#define SCTP_ASCONF_SUPPORTED 128
+#define SCTP_AUTH_SUPPORTED 129
/* PR-SCTP policies */
#define SCTP_PR_SCTP_NONE 0x0000
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index dcde8d9..82bc252 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4520,6 +4520,46 @@ static int sctp_setsockopt_asconf_supported(struct sock *sk,
return retval;
}
+static int sctp_setsockopt_auth_supported(struct sock *sk,
+ char __user *optval,
+ unsigned int optlen)
+{
+ struct sctp_assoc_value params;
+ struct sctp_association *asoc;
+ struct sctp_endpoint *ep;
+ int retval = -EINVAL;
+
+ if (optlen != sizeof(params))
+ goto out;
+
+ if (copy_from_user(¶ms, optval, optlen)) {
+ retval = -EFAULT;
+ goto out;
+ }
+
+ asoc = sctp_id2assoc(sk, params.assoc_id);
+ if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC &&
+ sctp_style(sk, UDP))
+ goto out;
+
+ ep = sctp_sk(sk)->ep;
+ if (params.assoc_value) {
+ retval = sctp_auth_init(ep, GFP_KERNEL);
+ if (retval)
+ goto out;
+ if (ep->asconf_enable) {
+ sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF);
+ sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF_ACK);
+ }
+ }
+
+ ep->auth_enable = !!params.assoc_value;
+ retval = 0;
+
+out:
+ return retval;
+}
+
/* API 6.2 setsockopt(), getsockopt()
*
* Applications use setsockopt() and getsockopt() to set or retrieve
@@ -4723,6 +4763,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname,
case SCTP_ASCONF_SUPPORTED:
retval = sctp_setsockopt_asconf_supported(sk, optval, optlen);
break;
+ case SCTP_AUTH_SUPPORTED:
+ retval = sctp_setsockopt_auth_supported(sk, optval, optlen);
+ break;
default:
retval = -ENOPROTOOPT;
break;
@@ -7746,6 +7789,45 @@ static int sctp_getsockopt_asconf_supported(struct sock *sk, int len,
return retval;
}
+static int sctp_getsockopt_auth_supported(struct sock *sk, int len,
+ char __user *optval,
+ int __user *optlen)
+{
+ struct sctp_assoc_value params;
+ struct sctp_association *asoc;
+ int retval = -EFAULT;
+
+ if (len < sizeof(params)) {
+ retval = -EINVAL;
+ goto out;
+ }
+
+ len = sizeof(params);
+ if (copy_from_user(¶ms, optval, len))
+ goto out;
+
+ asoc = sctp_id2assoc(sk, params.assoc_id);
+ if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC &&
+ sctp_style(sk, UDP)) {
+ retval = -EINVAL;
+ goto out;
+ }
+
+ params.assoc_value = asoc ? asoc->peer.auth_capable
+ : sctp_sk(sk)->ep->auth_enable;
+
+ if (put_user(len, optlen))
+ goto out;
+
+ if (copy_to_user(optval, ¶ms, len))
+ goto out;
+
+ retval = 0;
+
+out:
+ return retval;
+}
+
static int sctp_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen)
{
@@ -7951,6 +8033,10 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname,
retval = sctp_getsockopt_asconf_supported(sk, len, optval,
optlen);
break;
+ case SCTP_AUTH_SUPPORTED:
+ retval = sctp_getsockopt_auth_supported(sk, len, optval,
+ optlen);
+ break;
default:
retval = -ENOPROTOOPT;
break;
--
2.1.0
^ permalink raw reply related [flat|nested] 32+ messages in thread* [PATCH net-next 7/8] sctp: add SCTP_AUTH_SUPPORTED sockopt
@ 2019-08-19 14:02 ` Xin Long
0 siblings, 0 replies; 32+ messages in thread
From: Xin Long @ 2019-08-19 14:02 UTC (permalink / raw)
To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem
SCTP_AUTH_SUPPORTED sockopt is used to set enpoint's auth
flag. With this feature, each endpoint will have its own
flag for its future asoc's auth_capable, instead of netns
auth flag.
Note that when both ep's auth_enable is enabled, endpoint
auth related data should be initialized. If asconf_enable
is also set, SCTP_CID_ASCONF/SCTP_CID_ASCONF_ACK should
be added into auth_chunk_list.
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
include/uapi/linux/sctp.h | 1 +
net/sctp/socket.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 87 insertions(+)
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index 9b9b82d..62527ac 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -135,6 +135,7 @@ typedef __s32 sctp_assoc_t;
#define SCTP_SENDMSG_CONNECT 126
#define SCTP_EVENT 127
#define SCTP_ASCONF_SUPPORTED 128
+#define SCTP_AUTH_SUPPORTED 129
/* PR-SCTP policies */
#define SCTP_PR_SCTP_NONE 0x0000
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index dcde8d9..82bc252 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4520,6 +4520,46 @@ static int sctp_setsockopt_asconf_supported(struct sock *sk,
return retval;
}
+static int sctp_setsockopt_auth_supported(struct sock *sk,
+ char __user *optval,
+ unsigned int optlen)
+{
+ struct sctp_assoc_value params;
+ struct sctp_association *asoc;
+ struct sctp_endpoint *ep;
+ int retval = -EINVAL;
+
+ if (optlen != sizeof(params))
+ goto out;
+
+ if (copy_from_user(¶ms, optval, optlen)) {
+ retval = -EFAULT;
+ goto out;
+ }
+
+ asoc = sctp_id2assoc(sk, params.assoc_id);
+ if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC &&
+ sctp_style(sk, UDP))
+ goto out;
+
+ ep = sctp_sk(sk)->ep;
+ if (params.assoc_value) {
+ retval = sctp_auth_init(ep, GFP_KERNEL);
+ if (retval)
+ goto out;
+ if (ep->asconf_enable) {
+ sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF);
+ sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF_ACK);
+ }
+ }
+
+ ep->auth_enable = !!params.assoc_value;
+ retval = 0;
+
+out:
+ return retval;
+}
+
/* API 6.2 setsockopt(), getsockopt()
*
* Applications use setsockopt() and getsockopt() to set or retrieve
@@ -4723,6 +4763,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname,
case SCTP_ASCONF_SUPPORTED:
retval = sctp_setsockopt_asconf_supported(sk, optval, optlen);
break;
+ case SCTP_AUTH_SUPPORTED:
+ retval = sctp_setsockopt_auth_supported(sk, optval, optlen);
+ break;
default:
retval = -ENOPROTOOPT;
break;
@@ -7746,6 +7789,45 @@ static int sctp_getsockopt_asconf_supported(struct sock *sk, int len,
return retval;
}
+static int sctp_getsockopt_auth_supported(struct sock *sk, int len,
+ char __user *optval,
+ int __user *optlen)
+{
+ struct sctp_assoc_value params;
+ struct sctp_association *asoc;
+ int retval = -EFAULT;
+
+ if (len < sizeof(params)) {
+ retval = -EINVAL;
+ goto out;
+ }
+
+ len = sizeof(params);
+ if (copy_from_user(¶ms, optval, len))
+ goto out;
+
+ asoc = sctp_id2assoc(sk, params.assoc_id);
+ if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC &&
+ sctp_style(sk, UDP)) {
+ retval = -EINVAL;
+ goto out;
+ }
+
+ params.assoc_value = asoc ? asoc->peer.auth_capable
+ : sctp_sk(sk)->ep->auth_enable;
+
+ if (put_user(len, optlen))
+ goto out;
+
+ if (copy_to_user(optval, ¶ms, len))
+ goto out;
+
+ retval = 0;
+
+out:
+ return retval;
+}
+
static int sctp_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen)
{
@@ -7951,6 +8033,10 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname,
retval = sctp_getsockopt_asconf_supported(sk, len, optval,
optlen);
break;
+ case SCTP_AUTH_SUPPORTED:
+ retval = sctp_getsockopt_auth_supported(sk, len, optval,
+ optlen);
+ break;
default:
retval = -ENOPROTOOPT;
break;
--
2.1.0
^ permalink raw reply related [flat|nested] 32+ messages in thread* [PATCH net-next 8/8] sctp: remove net sctp.x_enable working as a global switch
2019-08-19 14:02 ` Xin Long
@ 2019-08-19 14:02 ` Xin Long
-1 siblings, 0 replies; 32+ messages in thread
From: Xin Long @ 2019-08-19 14:02 UTC (permalink / raw)
To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem
The netns sctp feature flags shouldn't work as a global switch,
which is mostly like a firewall/netfilter's job. Also, it will
break asoc as it discard or accept chunks incorrectly when net
sctp.x_enable is changed after the asoc is created.
Since each type of chunk's processing function will check the
corresp asoc's feature flag, this 'global switch' should be
removed, and net sctp.x_enable will only work as the default
feature flags for the future sctp sockets/endpoints.
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
net/sctp/sm_statetable.c | 28 ++++++++++++----------------
1 file changed, 12 insertions(+), 16 deletions(-)
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index 61ed9c6..88ea87f 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -976,26 +976,22 @@ static const struct sctp_sm_table_entry *sctp_chunk_event_lookup(
if (cid <= SCTP_CID_BASE_MAX)
return &chunk_event_table[cid][state];
- if (net->sctp.prsctp_enable) {
- if (cid = SCTP_CID_FWD_TSN || cid = SCTP_CID_I_FWD_TSN)
- return &prsctp_chunk_event_table[0][state];
- }
+ switch ((u16)cid) {
+ case SCTP_CID_FWD_TSN:
+ case SCTP_CID_I_FWD_TSN:
+ return &prsctp_chunk_event_table[0][state];
- if (net->sctp.addip_enable) {
- if (cid = SCTP_CID_ASCONF)
- return &addip_chunk_event_table[0][state];
+ case SCTP_CID_ASCONF:
+ return &addip_chunk_event_table[0][state];
- if (cid = SCTP_CID_ASCONF_ACK)
- return &addip_chunk_event_table[1][state];
- }
+ case SCTP_CID_ASCONF_ACK:
+ return &addip_chunk_event_table[1][state];
- if (net->sctp.reconf_enable)
- if (cid = SCTP_CID_RECONF)
- return &reconf_chunk_event_table[0][state];
+ case SCTP_CID_RECONF:
+ return &reconf_chunk_event_table[0][state];
- if (net->sctp.auth_enable) {
- if (cid = SCTP_CID_AUTH)
- return &auth_chunk_event_table[0][state];
+ case SCTP_CID_AUTH:
+ return &auth_chunk_event_table[0][state];
}
return &chunk_event_table_unknown[state];
--
2.1.0
^ permalink raw reply related [flat|nested] 32+ messages in thread* [PATCH net-next 8/8] sctp: remove net sctp.x_enable working as a global switch
@ 2019-08-19 14:02 ` Xin Long
0 siblings, 0 replies; 32+ messages in thread
From: Xin Long @ 2019-08-19 14:02 UTC (permalink / raw)
To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem
The netns sctp feature flags shouldn't work as a global switch,
which is mostly like a firewall/netfilter's job. Also, it will
break asoc as it discard or accept chunks incorrectly when net
sctp.x_enable is changed after the asoc is created.
Since each type of chunk's processing function will check the
corresp asoc's feature flag, this 'global switch' should be
removed, and net sctp.x_enable will only work as the default
feature flags for the future sctp sockets/endpoints.
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
net/sctp/sm_statetable.c | 28 ++++++++++++----------------
1 file changed, 12 insertions(+), 16 deletions(-)
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index 61ed9c6..88ea87f 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -976,26 +976,22 @@ static const struct sctp_sm_table_entry *sctp_chunk_event_lookup(
if (cid <= SCTP_CID_BASE_MAX)
return &chunk_event_table[cid][state];
- if (net->sctp.prsctp_enable) {
- if (cid == SCTP_CID_FWD_TSN || cid == SCTP_CID_I_FWD_TSN)
- return &prsctp_chunk_event_table[0][state];
- }
+ switch ((u16)cid) {
+ case SCTP_CID_FWD_TSN:
+ case SCTP_CID_I_FWD_TSN:
+ return &prsctp_chunk_event_table[0][state];
- if (net->sctp.addip_enable) {
- if (cid == SCTP_CID_ASCONF)
- return &addip_chunk_event_table[0][state];
+ case SCTP_CID_ASCONF:
+ return &addip_chunk_event_table[0][state];
- if (cid == SCTP_CID_ASCONF_ACK)
- return &addip_chunk_event_table[1][state];
- }
+ case SCTP_CID_ASCONF_ACK:
+ return &addip_chunk_event_table[1][state];
- if (net->sctp.reconf_enable)
- if (cid == SCTP_CID_RECONF)
- return &reconf_chunk_event_table[0][state];
+ case SCTP_CID_RECONF:
+ return &reconf_chunk_event_table[0][state];
- if (net->sctp.auth_enable) {
- if (cid == SCTP_CID_AUTH)
- return &auth_chunk_event_table[0][state];
+ case SCTP_CID_AUTH:
+ return &auth_chunk_event_table[0][state];
}
return &chunk_event_table_unknown[state];
--
2.1.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH net-next 4/8] sctp: add SCTP_ASCONF_SUPPORTED sockopt
2019-08-19 14:02 ` Xin Long
@ 2019-08-19 14:30 ` Marcelo Ricardo Leitner
-1 siblings, 0 replies; 32+ messages in thread
From: Marcelo Ricardo Leitner @ 2019-08-19 14:30 UTC (permalink / raw)
To: Xin Long; +Cc: network dev, linux-sctp, Neil Horman, davem
On Mon, Aug 19, 2019 at 10:02:46PM +0800, Xin Long wrote:
> SCTP_ASCONF_SUPPORTED sockopt is used to set enpoint's asconf
> flag. With this feature, each endpoint will have its own flag
> for its future asoc's asconf_capable, instead of netns asconf
> flag.
Is this backed by a RFC? If yes, it should be noted in the patch
description.
Quickly searching, I found only FreeBSD references.
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH net-next 4/8] sctp: add SCTP_ASCONF_SUPPORTED sockopt
@ 2019-08-19 14:30 ` Marcelo Ricardo Leitner
0 siblings, 0 replies; 32+ messages in thread
From: Marcelo Ricardo Leitner @ 2019-08-19 14:30 UTC (permalink / raw)
To: Xin Long; +Cc: network dev, linux-sctp, Neil Horman, davem
On Mon, Aug 19, 2019 at 10:02:46PM +0800, Xin Long wrote:
> SCTP_ASCONF_SUPPORTED sockopt is used to set enpoint's asconf
> flag. With this feature, each endpoint will have its own flag
> for its future asoc's asconf_capable, instead of netns asconf
> flag.
Is this backed by a RFC? If yes, it should be noted in the patch
description.
Quickly searching, I found only FreeBSD references.
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH net-next 4/8] sctp: add SCTP_ASCONF_SUPPORTED sockopt
2019-08-19 14:30 ` Marcelo Ricardo Leitner
@ 2019-08-19 14:43 ` Xin Long
-1 siblings, 0 replies; 32+ messages in thread
From: Xin Long @ 2019-08-19 14:43 UTC (permalink / raw)
To: Marcelo Ricardo Leitner; +Cc: network dev, linux-sctp, Neil Horman, davem
On Mon, Aug 19, 2019 at 10:30 PM Marcelo Ricardo Leitner
<marcelo.leitner@gmail.com> wrote:
>
> On Mon, Aug 19, 2019 at 10:02:46PM +0800, Xin Long wrote:
> > SCTP_ASCONF_SUPPORTED sockopt is used to set enpoint's asconf
> > flag. With this feature, each endpoint will have its own flag
> > for its future asoc's asconf_capable, instead of netns asconf
> > flag.
>
> Is this backed by a RFC? If yes, it should be noted in the patch
> description.
> Quickly searching, I found only FreeBSD references.
RFC doesn't define this sockopt clearly, unlike prsctp and reconfig,
not sure why.
but BSD supports it, so does some userland SCTP.
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH net-next 4/8] sctp: add SCTP_ASCONF_SUPPORTED sockopt
@ 2019-08-19 14:43 ` Xin Long
0 siblings, 0 replies; 32+ messages in thread
From: Xin Long @ 2019-08-19 14:43 UTC (permalink / raw)
To: Marcelo Ricardo Leitner; +Cc: network dev, linux-sctp, Neil Horman, davem
On Mon, Aug 19, 2019 at 10:30 PM Marcelo Ricardo Leitner
<marcelo.leitner@gmail.com> wrote:
>
> On Mon, Aug 19, 2019 at 10:02:46PM +0800, Xin Long wrote:
> > SCTP_ASCONF_SUPPORTED sockopt is used to set enpoint's asconf
> > flag. With this feature, each endpoint will have its own flag
> > for its future asoc's asconf_capable, instead of netns asconf
> > flag.
>
> Is this backed by a RFC? If yes, it should be noted in the patch
> description.
> Quickly searching, I found only FreeBSD references.
RFC doesn't define this sockopt clearly, unlike prsctp and reconfig,
not sure why.
but BSD supports it, so does some userland SCTP.
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH net-next 4/8] sctp: add SCTP_ASCONF_SUPPORTED sockopt
2019-08-19 14:43 ` Xin Long
@ 2019-08-19 14:46 ` Marcelo Ricardo Leitner
-1 siblings, 0 replies; 32+ messages in thread
From: Marcelo Ricardo Leitner @ 2019-08-19 14:46 UTC (permalink / raw)
To: Xin Long; +Cc: network dev, linux-sctp, Neil Horman, davem
On Mon, Aug 19, 2019 at 10:43:03PM +0800, Xin Long wrote:
> On Mon, Aug 19, 2019 at 10:30 PM Marcelo Ricardo Leitner
> <marcelo.leitner@gmail.com> wrote:
> >
> > On Mon, Aug 19, 2019 at 10:02:46PM +0800, Xin Long wrote:
> > > SCTP_ASCONF_SUPPORTED sockopt is used to set enpoint's asconf
> > > flag. With this feature, each endpoint will have its own flag
> > > for its future asoc's asconf_capable, instead of netns asconf
> > > flag.
> >
> > Is this backed by a RFC? If yes, it should be noted in the patch
> > description.
> > Quickly searching, I found only FreeBSD references.
> RFC doesn't define this sockopt clearly, unlike prsctp and reconfig,
> not sure why.
> but BSD supports it, so does some userland SCTP.
Ok. Thanks.
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH net-next 4/8] sctp: add SCTP_ASCONF_SUPPORTED sockopt
@ 2019-08-19 14:46 ` Marcelo Ricardo Leitner
0 siblings, 0 replies; 32+ messages in thread
From: Marcelo Ricardo Leitner @ 2019-08-19 14:46 UTC (permalink / raw)
To: Xin Long; +Cc: network dev, linux-sctp, Neil Horman, davem
On Mon, Aug 19, 2019 at 10:43:03PM +0800, Xin Long wrote:
> On Mon, Aug 19, 2019 at 10:30 PM Marcelo Ricardo Leitner
> <marcelo.leitner@gmail.com> wrote:
> >
> > On Mon, Aug 19, 2019 at 10:02:46PM +0800, Xin Long wrote:
> > > SCTP_ASCONF_SUPPORTED sockopt is used to set enpoint's asconf
> > > flag. With this feature, each endpoint will have its own flag
> > > for its future asoc's asconf_capable, instead of netns asconf
> > > flag.
> >
> > Is this backed by a RFC? If yes, it should be noted in the patch
> > description.
> > Quickly searching, I found only FreeBSD references.
> RFC doesn't define this sockopt clearly, unlike prsctp and reconfig,
> not sure why.
> but BSD supports it, so does some userland SCTP.
Ok. Thanks.
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH net-next 4/8] sctp: add SCTP_ASCONF_SUPPORTED sockopt
2019-08-19 14:02 ` Xin Long
@ 2019-08-19 14:58 ` Marcelo Ricardo Leitner
-1 siblings, 0 replies; 32+ messages in thread
From: Marcelo Ricardo Leitner @ 2019-08-19 14:58 UTC (permalink / raw)
To: Xin Long; +Cc: network dev, linux-sctp, Neil Horman, davem
On Mon, Aug 19, 2019 at 10:02:46PM +0800, Xin Long wrote:
> +static int sctp_setsockopt_asconf_supported(struct sock *sk,
> + char __user *optval,
> + unsigned int optlen)
> +{
> + struct sctp_assoc_value params;
> + struct sctp_association *asoc;
> + struct sctp_endpoint *ep;
> + int retval = -EINVAL;
> +
> + if (optlen != sizeof(params))
> + goto out;
> +
> + if (copy_from_user(¶ms, optval, optlen)) {
> + retval = -EFAULT;
> + goto out;
> + }
> +
> + asoc = sctp_id2assoc(sk, params.assoc_id);
> + if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC &&
> + sctp_style(sk, UDP))
> + goto out;
> +
> + ep = sctp_sk(sk)->ep;
> + ep->asconf_enable = !!params.assoc_value;
Considering this will be negotiated on handshake, shouldn't it deny
changes to Established asocs? (Same for Auth)
> +
> + if (ep->asconf_enable && ep->auth_enable) {
> + sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF);
> + sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF_ACK);
> + }
> +
> + retval = 0;
> +
> +out:
> + return retval;
> +}
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [PATCH net-next 4/8] sctp: add SCTP_ASCONF_SUPPORTED sockopt
@ 2019-08-19 14:58 ` Marcelo Ricardo Leitner
0 siblings, 0 replies; 32+ messages in thread
From: Marcelo Ricardo Leitner @ 2019-08-19 14:58 UTC (permalink / raw)
To: Xin Long; +Cc: network dev, linux-sctp, Neil Horman, davem
On Mon, Aug 19, 2019 at 10:02:46PM +0800, Xin Long wrote:
> +static int sctp_setsockopt_asconf_supported(struct sock *sk,
> + char __user *optval,
> + unsigned int optlen)
> +{
> + struct sctp_assoc_value params;
> + struct sctp_association *asoc;
> + struct sctp_endpoint *ep;
> + int retval = -EINVAL;
> +
> + if (optlen != sizeof(params))
> + goto out;
> +
> + if (copy_from_user(¶ms, optval, optlen)) {
> + retval = -EFAULT;
> + goto out;
> + }
> +
> + asoc = sctp_id2assoc(sk, params.assoc_id);
> + if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC &&
> + sctp_style(sk, UDP))
> + goto out;
> +
> + ep = sctp_sk(sk)->ep;
> + ep->asconf_enable = !!params.assoc_value;
Considering this will be negotiated on handshake, shouldn't it deny
changes to Established asocs? (Same for Auth)
> +
> + if (ep->asconf_enable && ep->auth_enable) {
> + sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF);
> + sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF_ACK);
> + }
> +
> + retval = 0;
> +
> +out:
> + return retval;
> +}
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [PATCH net-next 4/8] sctp: add SCTP_ASCONF_SUPPORTED sockopt
2019-08-19 14:58 ` Marcelo Ricardo Leitner
@ 2019-08-19 15:19 ` Xin Long
-1 siblings, 0 replies; 32+ messages in thread
From: Xin Long @ 2019-08-19 15:19 UTC (permalink / raw)
To: Marcelo Ricardo Leitner; +Cc: network dev, linux-sctp, Neil Horman, davem
On Mon, Aug 19, 2019 at 10:58 PM Marcelo Ricardo Leitner
<marcelo.leitner@gmail.com> wrote:
>
> On Mon, Aug 19, 2019 at 10:02:46PM +0800, Xin Long wrote:
> > +static int sctp_setsockopt_asconf_supported(struct sock *sk,
> > + char __user *optval,
> > + unsigned int optlen)
> > +{
> > + struct sctp_assoc_value params;
> > + struct sctp_association *asoc;
> > + struct sctp_endpoint *ep;
> > + int retval = -EINVAL;
> > +
> > + if (optlen != sizeof(params))
> > + goto out;
> > +
> > + if (copy_from_user(¶ms, optval, optlen)) {
> > + retval = -EFAULT;
> > + goto out;
> > + }
> > +
> > + asoc = sctp_id2assoc(sk, params.assoc_id);
> > + if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC &&
> > + sctp_style(sk, UDP))
> > + goto out;
> > +
> > + ep = sctp_sk(sk)->ep;
> > + ep->asconf_enable = !!params.assoc_value;
>
> Considering this will be negotiated on handshake, shouldn't it deny
> changes to Established asocs? (Same for Auth)
ep->asconf_enable is for 'furture' asocs, and furture
asoc->peer.asconf_capable will be negotiated according to
peer ep->asconf_enable (EXT chunk) and local ep->asconf_enable.
It won't affect the 'current'/Established asocs, and the Established
asocs have asoc->peer.asconf_capable, which can't be changed by sockopt.
>
> > +
> > + if (ep->asconf_enable && ep->auth_enable) {
> > + sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF);
> > + sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF_ACK);
> > + }
> > +
> > + retval = 0;
> > +
> > +out:
> > + return retval;
> > +}
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [PATCH net-next 4/8] sctp: add SCTP_ASCONF_SUPPORTED sockopt
@ 2019-08-19 15:19 ` Xin Long
0 siblings, 0 replies; 32+ messages in thread
From: Xin Long @ 2019-08-19 15:19 UTC (permalink / raw)
To: Marcelo Ricardo Leitner; +Cc: network dev, linux-sctp, Neil Horman, davem
On Mon, Aug 19, 2019 at 10:58 PM Marcelo Ricardo Leitner
<marcelo.leitner@gmail.com> wrote:
>
> On Mon, Aug 19, 2019 at 10:02:46PM +0800, Xin Long wrote:
> > +static int sctp_setsockopt_asconf_supported(struct sock *sk,
> > + char __user *optval,
> > + unsigned int optlen)
> > +{
> > + struct sctp_assoc_value params;
> > + struct sctp_association *asoc;
> > + struct sctp_endpoint *ep;
> > + int retval = -EINVAL;
> > +
> > + if (optlen != sizeof(params))
> > + goto out;
> > +
> > + if (copy_from_user(¶ms, optval, optlen)) {
> > + retval = -EFAULT;
> > + goto out;
> > + }
> > +
> > + asoc = sctp_id2assoc(sk, params.assoc_id);
> > + if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC &&
> > + sctp_style(sk, UDP))
> > + goto out;
> > +
> > + ep = sctp_sk(sk)->ep;
> > + ep->asconf_enable = !!params.assoc_value;
>
> Considering this will be negotiated on handshake, shouldn't it deny
> changes to Established asocs? (Same for Auth)
ep->asconf_enable is for 'furture' asocs, and furture
asoc->peer.asconf_capable will be negotiated according to
peer ep->asconf_enable (EXT chunk) and local ep->asconf_enable.
It won't affect the 'current'/Established asocs, and the Established
asocs have asoc->peer.asconf_capable, which can't be changed by sockopt.
>
> > +
> > + if (ep->asconf_enable && ep->auth_enable) {
> > + sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF);
> > + sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF_ACK);
> > + }
> > +
> > + retval = 0;
> > +
> > +out:
> > + return retval;
> > +}
^ permalink raw reply [flat|nested] 32+ messages in thread