diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/Kconfig | 39 | ||||
-rw-r--r-- | net/sctp/input.c | 2 | ||||
-rw-r--r-- | net/sctp/outqueue.c | 15 | ||||
-rw-r--r-- | net/sctp/protocol.c | 9 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 7 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 2 | ||||
-rw-r--r-- | net/sctp/socket.c | 36 | ||||
-rw-r--r-- | net/sctp/sysctl.c | 59 |
8 files changed, 124 insertions, 45 deletions
diff --git a/net/sctp/Kconfig b/net/sctp/Kconfig index 126b014eb79b..a9edd2e205f4 100644 --- a/net/sctp/Kconfig +++ b/net/sctp/Kconfig | |||
@@ -9,7 +9,6 @@ menuconfig IP_SCTP | |||
9 | select CRYPTO | 9 | select CRYPTO |
10 | select CRYPTO_HMAC | 10 | select CRYPTO_HMAC |
11 | select CRYPTO_SHA1 | 11 | select CRYPTO_SHA1 |
12 | select CRYPTO_MD5 if SCTP_HMAC_MD5 | ||
13 | select LIBCRC32C | 12 | select LIBCRC32C |
14 | ---help--- | 13 | ---help--- |
15 | Stream Control Transmission Protocol | 14 | Stream Control Transmission Protocol |
@@ -68,33 +67,21 @@ config SCTP_DBG_OBJCNT | |||
68 | 67 | ||
69 | If unsure, say N | 68 | If unsure, say N |
70 | 69 | ||
71 | choice | 70 | config SCTP_COOKIE_HMAC_MD5 |
72 | prompt "SCTP: Cookie HMAC Algorithm" | 71 | bool "Enable optional MD5 hmac cookie generation" |
73 | default SCTP_HMAC_MD5 | ||
74 | help | 72 | help |
75 | HMAC algorithm to be used during association initialization. It | 73 | Enable optional MD5 hmac based SCTP cookie generation |
76 | is strongly recommended to use HMAC-SHA1 or HMAC-MD5. See | 74 | default y |
77 | configuration for Cryptographic API and enable those algorithms | 75 | select CRYPTO_HMAC if SCTP_COOKIE_HMAC_MD5 |
78 | to make usable by SCTP. | 76 | select CRYPTO_MD5 if SCTP_COOKIE_HMAC_MD5 |
79 | 77 | ||
80 | config SCTP_HMAC_NONE | 78 | config SCTP_COOKIE_HMAC_SHA1 |
81 | bool "None" | 79 | bool "Enable optional SHA1 hmac cookie generation" |
82 | help | ||
83 | Choosing this disables the use of an HMAC during association | ||
84 | establishment. It is advised to use either HMAC-MD5 or HMAC-SHA1. | ||
85 | |||
86 | config SCTP_HMAC_SHA1 | ||
87 | bool "HMAC-SHA1" | ||
88 | help | ||
89 | Enable the use of HMAC-SHA1 during association establishment. It | ||
90 | is advised to use either HMAC-MD5 or HMAC-SHA1. | ||
91 | |||
92 | config SCTP_HMAC_MD5 | ||
93 | bool "HMAC-MD5" | ||
94 | help | 80 | help |
95 | Enable the use of HMAC-MD5 during association establishment. It is | 81 | Enable optional SHA1 hmac based SCTP cookie generation |
96 | advised to use either HMAC-MD5 or HMAC-SHA1. | 82 | default y |
83 | select CRYPTO_HMAC if SCTP_COOKIE_HMAC_SHA1 | ||
84 | select CRYPTO_SHA1 if SCTP_COOKIE_HMAC_SHA1 | ||
97 | 85 | ||
98 | endchoice | ||
99 | 86 | ||
100 | endif # IP_SCTP | 87 | endif # IP_SCTP |
diff --git a/net/sctp/input.c b/net/sctp/input.c index 25dfe7380479..8bd3c279427e 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -68,8 +68,8 @@ | |||
68 | static int sctp_rcv_ootb(struct sk_buff *); | 68 | static int sctp_rcv_ootb(struct sk_buff *); |
69 | static struct sctp_association *__sctp_rcv_lookup(struct net *net, | 69 | static struct sctp_association *__sctp_rcv_lookup(struct net *net, |
70 | struct sk_buff *skb, | 70 | struct sk_buff *skb, |
71 | const union sctp_addr *laddr, | ||
72 | const union sctp_addr *paddr, | 71 | const union sctp_addr *paddr, |
72 | const union sctp_addr *laddr, | ||
73 | struct sctp_transport **transportp); | 73 | struct sctp_transport **transportp); |
74 | static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net, | 74 | static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net, |
75 | const union sctp_addr *laddr); | 75 | const union sctp_addr *laddr); |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index d16632e1503a..1b4a7f8ec3fd 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -63,6 +63,7 @@ static int sctp_acked(struct sctp_sackhdr *sack, __u32 tsn); | |||
63 | static void sctp_check_transmitted(struct sctp_outq *q, | 63 | static void sctp_check_transmitted(struct sctp_outq *q, |
64 | struct list_head *transmitted_queue, | 64 | struct list_head *transmitted_queue, |
65 | struct sctp_transport *transport, | 65 | struct sctp_transport *transport, |
66 | union sctp_addr *saddr, | ||
66 | struct sctp_sackhdr *sack, | 67 | struct sctp_sackhdr *sack, |
67 | __u32 *highest_new_tsn); | 68 | __u32 *highest_new_tsn); |
68 | 69 | ||
@@ -1139,9 +1140,10 @@ static void sctp_sack_update_unack_data(struct sctp_association *assoc, | |||
1139 | * Process the SACK against the outqueue. Mostly, this just frees | 1140 | * Process the SACK against the outqueue. Mostly, this just frees |
1140 | * things off the transmitted queue. | 1141 | * things off the transmitted queue. |
1141 | */ | 1142 | */ |
1142 | int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) | 1143 | int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk) |
1143 | { | 1144 | { |
1144 | struct sctp_association *asoc = q->asoc; | 1145 | struct sctp_association *asoc = q->asoc; |
1146 | struct sctp_sackhdr *sack = chunk->subh.sack_hdr; | ||
1145 | struct sctp_transport *transport; | 1147 | struct sctp_transport *transport; |
1146 | struct sctp_chunk *tchunk = NULL; | 1148 | struct sctp_chunk *tchunk = NULL; |
1147 | struct list_head *lchunk, *transport_list, *temp; | 1149 | struct list_head *lchunk, *transport_list, *temp; |
@@ -1210,7 +1212,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) | |||
1210 | /* Run through the retransmit queue. Credit bytes received | 1212 | /* Run through the retransmit queue. Credit bytes received |
1211 | * and free those chunks that we can. | 1213 | * and free those chunks that we can. |
1212 | */ | 1214 | */ |
1213 | sctp_check_transmitted(q, &q->retransmit, NULL, sack, &highest_new_tsn); | 1215 | sctp_check_transmitted(q, &q->retransmit, NULL, NULL, sack, &highest_new_tsn); |
1214 | 1216 | ||
1215 | /* Run through the transmitted queue. | 1217 | /* Run through the transmitted queue. |
1216 | * Credit bytes received and free those chunks which we can. | 1218 | * Credit bytes received and free those chunks which we can. |
@@ -1219,7 +1221,8 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) | |||
1219 | */ | 1221 | */ |
1220 | list_for_each_entry(transport, transport_list, transports) { | 1222 | list_for_each_entry(transport, transport_list, transports) { |
1221 | sctp_check_transmitted(q, &transport->transmitted, | 1223 | sctp_check_transmitted(q, &transport->transmitted, |
1222 | transport, sack, &highest_new_tsn); | 1224 | transport, &chunk->source, sack, |
1225 | &highest_new_tsn); | ||
1223 | /* | 1226 | /* |
1224 | * SFR-CACC algorithm: | 1227 | * SFR-CACC algorithm: |
1225 | * C) Let count_of_newacks be the number of | 1228 | * C) Let count_of_newacks be the number of |
@@ -1326,6 +1329,7 @@ int sctp_outq_is_empty(const struct sctp_outq *q) | |||
1326 | static void sctp_check_transmitted(struct sctp_outq *q, | 1329 | static void sctp_check_transmitted(struct sctp_outq *q, |
1327 | struct list_head *transmitted_queue, | 1330 | struct list_head *transmitted_queue, |
1328 | struct sctp_transport *transport, | 1331 | struct sctp_transport *transport, |
1332 | union sctp_addr *saddr, | ||
1329 | struct sctp_sackhdr *sack, | 1333 | struct sctp_sackhdr *sack, |
1330 | __u32 *highest_new_tsn_in_sack) | 1334 | __u32 *highest_new_tsn_in_sack) |
1331 | { | 1335 | { |
@@ -1633,8 +1637,9 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1633 | /* Mark the destination transport address as | 1637 | /* Mark the destination transport address as |
1634 | * active if it is not so marked. | 1638 | * active if it is not so marked. |
1635 | */ | 1639 | */ |
1636 | if ((transport->state == SCTP_INACTIVE) || | 1640 | if ((transport->state == SCTP_INACTIVE || |
1637 | (transport->state == SCTP_UNCONFIRMED)) { | 1641 | transport->state == SCTP_UNCONFIRMED) && |
1642 | sctp_cmp_addr_exact(&transport->ipaddr, saddr)) { | ||
1638 | sctp_assoc_control_transport( | 1643 | sctp_assoc_control_transport( |
1639 | transport->asoc, | 1644 | transport->asoc, |
1640 | transport, | 1645 | transport, |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 2d518425d598..456bc3dbdd51 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -1190,6 +1190,15 @@ static int sctp_net_init(struct net *net) | |||
1190 | /* Whether Cookie Preservative is enabled(1) or not(0) */ | 1190 | /* Whether Cookie Preservative is enabled(1) or not(0) */ |
1191 | net->sctp.cookie_preserve_enable = 1; | 1191 | net->sctp.cookie_preserve_enable = 1; |
1192 | 1192 | ||
1193 | /* Default sctp sockets to use md5 as their hmac alg */ | ||
1194 | #if defined (CONFIG_CRYPTO_MD5) | ||
1195 | net->sctp.sctp_hmac_alg = "md5"; | ||
1196 | #elif defined (CONFIG_CRYPTO_SHA1) | ||
1197 | net->sctp.sctp_hmac_alg = "sha1"; | ||
1198 | #else | ||
1199 | net->sctp.sctp_hmac_alg = NULL; | ||
1200 | #endif | ||
1201 | |||
1193 | /* Max.Burst - 4 */ | 1202 | /* Max.Burst - 4 */ |
1194 | net->sctp.max_burst = SCTP_DEFAULT_MAX_BURST; | 1203 | net->sctp.max_burst = SCTP_DEFAULT_MAX_BURST; |
1195 | 1204 | ||
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index bcfebb91559d..6773d7803627 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -752,11 +752,11 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds, | |||
752 | /* Helper function to process the process SACK command. */ | 752 | /* Helper function to process the process SACK command. */ |
753 | static int sctp_cmd_process_sack(sctp_cmd_seq_t *cmds, | 753 | static int sctp_cmd_process_sack(sctp_cmd_seq_t *cmds, |
754 | struct sctp_association *asoc, | 754 | struct sctp_association *asoc, |
755 | struct sctp_sackhdr *sackh) | 755 | struct sctp_chunk *chunk) |
756 | { | 756 | { |
757 | int err = 0; | 757 | int err = 0; |
758 | 758 | ||
759 | if (sctp_outq_sack(&asoc->outqueue, sackh)) { | 759 | if (sctp_outq_sack(&asoc->outqueue, chunk)) { |
760 | struct net *net = sock_net(asoc->base.sk); | 760 | struct net *net = sock_net(asoc->base.sk); |
761 | 761 | ||
762 | /* There are no more TSNs awaiting SACK. */ | 762 | /* There are no more TSNs awaiting SACK. */ |
@@ -1642,8 +1642,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1642 | asoc->outqueue.outstanding_bytes; | 1642 | asoc->outqueue.outstanding_bytes; |
1643 | sackh.num_gap_ack_blocks = 0; | 1643 | sackh.num_gap_ack_blocks = 0; |
1644 | sackh.num_dup_tsns = 0; | 1644 | sackh.num_dup_tsns = 0; |
1645 | chunk->subh.sack_hdr = &sackh; | ||
1645 | sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, | 1646 | sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, |
1646 | SCTP_SACKH(&sackh)); | 1647 | SCTP_CHUNK(chunk)); |
1647 | break; | 1648 | break; |
1648 | 1649 | ||
1649 | case SCTP_CMD_DISCARD_PACKET: | 1650 | case SCTP_CMD_DISCARD_PACKET: |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 094813b6c3c3..b6adef8a1e93 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -3179,7 +3179,7 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(struct net *net, | |||
3179 | return sctp_sf_violation_ctsn(net, ep, asoc, type, arg, commands); | 3179 | return sctp_sf_violation_ctsn(net, ep, asoc, type, arg, commands); |
3180 | 3180 | ||
3181 | /* Return this SACK for further processing. */ | 3181 | /* Return this SACK for further processing. */ |
3182 | sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, SCTP_SACKH(sackh)); | 3182 | sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, SCTP_CHUNK(chunk)); |
3183 | 3183 | ||
3184 | /* Note: We do the rest of the work on the PROCESS_SACK | 3184 | /* Note: We do the rest of the work on the PROCESS_SACK |
3185 | * sideeffect. | 3185 | * sideeffect. |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index d37d24ff197f..fa81bdee00a5 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -70,6 +70,7 @@ | |||
70 | #include <linux/init.h> | 70 | #include <linux/init.h> |
71 | #include <linux/crypto.h> | 71 | #include <linux/crypto.h> |
72 | #include <linux/slab.h> | 72 | #include <linux/slab.h> |
73 | #include <linux/file.h> | ||
73 | 74 | ||
74 | #include <net/ip.h> | 75 | #include <net/ip.h> |
75 | #include <net/icmp.h> | 76 | #include <net/icmp.h> |
@@ -109,7 +110,6 @@ static int sctp_do_bind(struct sock *, union sctp_addr *, int); | |||
109 | static int sctp_autobind(struct sock *sk); | 110 | static int sctp_autobind(struct sock *sk); |
110 | static void sctp_sock_migrate(struct sock *, struct sock *, | 111 | static void sctp_sock_migrate(struct sock *, struct sock *, |
111 | struct sctp_association *, sctp_socket_type_t); | 112 | struct sctp_association *, sctp_socket_type_t); |
112 | static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG; | ||
113 | 113 | ||
114 | extern struct kmem_cache *sctp_bucket_cachep; | 114 | extern struct kmem_cache *sctp_bucket_cachep; |
115 | extern long sysctl_sctp_mem[3]; | 115 | extern long sysctl_sctp_mem[3]; |
@@ -3889,6 +3889,8 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) | |||
3889 | sp->default_rcv_context = 0; | 3889 | sp->default_rcv_context = 0; |
3890 | sp->max_burst = net->sctp.max_burst; | 3890 | sp->max_burst = net->sctp.max_burst; |
3891 | 3891 | ||
3892 | sp->sctp_hmac_alg = net->sctp.sctp_hmac_alg; | ||
3893 | |||
3892 | /* Initialize default setup parameters. These parameters | 3894 | /* Initialize default setup parameters. These parameters |
3893 | * can be modified with the SCTP_INITMSG socket option or | 3895 | * can be modified with the SCTP_INITMSG socket option or |
3894 | * overridden by the SCTP_INIT CMSG. | 3896 | * overridden by the SCTP_INIT CMSG. |
@@ -4292,6 +4294,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval | |||
4292 | { | 4294 | { |
4293 | sctp_peeloff_arg_t peeloff; | 4295 | sctp_peeloff_arg_t peeloff; |
4294 | struct socket *newsock; | 4296 | struct socket *newsock; |
4297 | struct file *newfile; | ||
4295 | int retval = 0; | 4298 | int retval = 0; |
4296 | 4299 | ||
4297 | if (len < sizeof(sctp_peeloff_arg_t)) | 4300 | if (len < sizeof(sctp_peeloff_arg_t)) |
@@ -4305,22 +4308,35 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval | |||
4305 | goto out; | 4308 | goto out; |
4306 | 4309 | ||
4307 | /* Map the socket to an unused fd that can be returned to the user. */ | 4310 | /* Map the socket to an unused fd that can be returned to the user. */ |
4308 | retval = sock_map_fd(newsock, 0); | 4311 | retval = get_unused_fd(); |
4309 | if (retval < 0) { | 4312 | if (retval < 0) { |
4310 | sock_release(newsock); | 4313 | sock_release(newsock); |
4311 | goto out; | 4314 | goto out; |
4312 | } | 4315 | } |
4313 | 4316 | ||
4317 | newfile = sock_alloc_file(newsock, 0, NULL); | ||
4318 | if (unlikely(IS_ERR(newfile))) { | ||
4319 | put_unused_fd(retval); | ||
4320 | sock_release(newsock); | ||
4321 | return PTR_ERR(newfile); | ||
4322 | } | ||
4323 | |||
4314 | SCTP_DEBUG_PRINTK("%s: sk: %p newsk: %p sd: %d\n", | 4324 | SCTP_DEBUG_PRINTK("%s: sk: %p newsk: %p sd: %d\n", |
4315 | __func__, sk, newsock->sk, retval); | 4325 | __func__, sk, newsock->sk, retval); |
4316 | 4326 | ||
4317 | /* Return the fd mapped to the new socket. */ | 4327 | /* Return the fd mapped to the new socket. */ |
4328 | if (put_user(len, optlen)) { | ||
4329 | fput(newfile); | ||
4330 | put_unused_fd(retval); | ||
4331 | return -EFAULT; | ||
4332 | } | ||
4318 | peeloff.sd = retval; | 4333 | peeloff.sd = retval; |
4319 | if (put_user(len, optlen)) | 4334 | if (copy_to_user(optval, &peeloff, len)) { |
4335 | fput(newfile); | ||
4336 | put_unused_fd(retval); | ||
4320 | return -EFAULT; | 4337 | return -EFAULT; |
4321 | if (copy_to_user(optval, &peeloff, len)) | 4338 | } |
4322 | retval = -EFAULT; | 4339 | fd_install(retval, newfile); |
4323 | |||
4324 | out: | 4340 | out: |
4325 | return retval; | 4341 | return retval; |
4326 | } | 4342 | } |
@@ -5966,13 +5982,15 @@ SCTP_STATIC int sctp_listen_start(struct sock *sk, int backlog) | |||
5966 | struct sctp_sock *sp = sctp_sk(sk); | 5982 | struct sctp_sock *sp = sctp_sk(sk); |
5967 | struct sctp_endpoint *ep = sp->ep; | 5983 | struct sctp_endpoint *ep = sp->ep; |
5968 | struct crypto_hash *tfm = NULL; | 5984 | struct crypto_hash *tfm = NULL; |
5985 | char alg[32]; | ||
5969 | 5986 | ||
5970 | /* Allocate HMAC for generating cookie. */ | 5987 | /* Allocate HMAC for generating cookie. */ |
5971 | if (!sctp_sk(sk)->hmac && sctp_hmac_alg) { | 5988 | if (!sp->hmac && sp->sctp_hmac_alg) { |
5972 | tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC); | 5989 | sprintf(alg, "hmac(%s)", sp->sctp_hmac_alg); |
5990 | tfm = crypto_alloc_hash(alg, 0, CRYPTO_ALG_ASYNC); | ||
5973 | if (IS_ERR(tfm)) { | 5991 | if (IS_ERR(tfm)) { |
5974 | net_info_ratelimited("failed to load transform for %s: %ld\n", | 5992 | net_info_ratelimited("failed to load transform for %s: %ld\n", |
5975 | sctp_hmac_alg, PTR_ERR(tfm)); | 5993 | sp->sctp_hmac_alg, PTR_ERR(tfm)); |
5976 | return -ENOSYS; | 5994 | return -ENOSYS; |
5977 | } | 5995 | } |
5978 | sctp_sk(sk)->hmac = tfm; | 5996 | sctp_sk(sk)->hmac = tfm; |
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index 70e3ba5cb50b..043889ac86c0 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c | |||
@@ -62,6 +62,11 @@ extern long sysctl_sctp_mem[3]; | |||
62 | extern int sysctl_sctp_rmem[3]; | 62 | extern int sysctl_sctp_rmem[3]; |
63 | extern int sysctl_sctp_wmem[3]; | 63 | extern int sysctl_sctp_wmem[3]; |
64 | 64 | ||
65 | static int proc_sctp_do_hmac_alg(ctl_table *ctl, | ||
66 | int write, | ||
67 | void __user *buffer, size_t *lenp, | ||
68 | |||
69 | loff_t *ppos); | ||
65 | static ctl_table sctp_table[] = { | 70 | static ctl_table sctp_table[] = { |
66 | { | 71 | { |
67 | .procname = "sctp_mem", | 72 | .procname = "sctp_mem", |
@@ -147,6 +152,12 @@ static ctl_table sctp_net_table[] = { | |||
147 | .proc_handler = proc_dointvec, | 152 | .proc_handler = proc_dointvec, |
148 | }, | 153 | }, |
149 | { | 154 | { |
155 | .procname = "cookie_hmac_alg", | ||
156 | .maxlen = 8, | ||
157 | .mode = 0644, | ||
158 | .proc_handler = proc_sctp_do_hmac_alg, | ||
159 | }, | ||
160 | { | ||
150 | .procname = "valid_cookie_life", | 161 | .procname = "valid_cookie_life", |
151 | .data = &init_net.sctp.valid_cookie_life, | 162 | .data = &init_net.sctp.valid_cookie_life, |
152 | .maxlen = sizeof(unsigned int), | 163 | .maxlen = sizeof(unsigned int), |
@@ -289,6 +300,54 @@ static ctl_table sctp_net_table[] = { | |||
289 | { /* sentinel */ } | 300 | { /* sentinel */ } |
290 | }; | 301 | }; |
291 | 302 | ||
303 | static int proc_sctp_do_hmac_alg(ctl_table *ctl, | ||
304 | int write, | ||
305 | void __user *buffer, size_t *lenp, | ||
306 | loff_t *ppos) | ||
307 | { | ||
308 | struct net *net = current->nsproxy->net_ns; | ||
309 | char tmp[8]; | ||
310 | ctl_table tbl; | ||
311 | int ret; | ||
312 | int changed = 0; | ||
313 | char *none = "none"; | ||
314 | |||
315 | memset(&tbl, 0, sizeof(struct ctl_table)); | ||
316 | |||
317 | if (write) { | ||
318 | tbl.data = tmp; | ||
319 | tbl.maxlen = 8; | ||
320 | } else { | ||
321 | tbl.data = net->sctp.sctp_hmac_alg ? : none; | ||
322 | tbl.maxlen = strlen(tbl.data); | ||
323 | } | ||
324 | ret = proc_dostring(&tbl, write, buffer, lenp, ppos); | ||
325 | |||
326 | if (write) { | ||
327 | #ifdef CONFIG_CRYPTO_MD5 | ||
328 | if (!strncmp(tmp, "md5", 3)) { | ||
329 | net->sctp.sctp_hmac_alg = "md5"; | ||
330 | changed = 1; | ||
331 | } | ||
332 | #endif | ||
333 | #ifdef CONFIG_CRYPTO_SHA1 | ||
334 | if (!strncmp(tmp, "sha1", 4)) { | ||
335 | net->sctp.sctp_hmac_alg = "sha1"; | ||
336 | changed = 1; | ||
337 | } | ||
338 | #endif | ||
339 | if (!strncmp(tmp, "none", 4)) { | ||
340 | net->sctp.sctp_hmac_alg = NULL; | ||
341 | changed = 1; | ||
342 | } | ||
343 | |||
344 | if (!changed) | ||
345 | ret = -EINVAL; | ||
346 | } | ||
347 | |||
348 | return ret; | ||
349 | } | ||
350 | |||
292 | int sctp_sysctl_net_register(struct net *net) | 351 | int sctp_sysctl_net_register(struct net *net) |
293 | { | 352 | { |
294 | struct ctl_table *table; | 353 | struct ctl_table *table; |