From 046752104c7090e3679b09274f02d8fd2aa0b4b2 Mon Sep 17 00:00:00 2001 From: "sebastian@breakpoint.cc" Date: Thu, 26 Jul 2007 23:21:31 +0200 Subject: sctp: make locally used function static Forward declarion is static, the function itself is not. Make it consistent. Signed-off-by: Sebastian Siewior Signed-off-by: Vlad Yasevich diff --git a/net/sctp/input.c b/net/sctp/input.c index d57ff7f..47e5601 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -590,7 +590,7 @@ out_unlock: * Return 0 - If further processing is needed. * Return 1 - If the packet can be discarded right away. */ -int sctp_rcv_ootb(struct sk_buff *skb) +static int sctp_rcv_ootb(struct sk_buff *skb) { sctp_chunkhdr_t *ch; __u8 *ch_end; diff --git a/net/sctp/socket.c b/net/sctp/socket.c index ee88f2e..f8bacc8 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -433,7 +433,7 @@ out: * * Only sctp_setsockopt_bindx() is supposed to call this function. */ -int sctp_bindx_add(struct sock *sk, struct sockaddr *addrs, int addrcnt) +static int sctp_bindx_add(struct sock *sk, struct sockaddr *addrs, int addrcnt) { int cnt; int retval = 0; @@ -602,7 +602,7 @@ out: * * Only sctp_setsockopt_bindx() is supposed to call this function. */ -int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt) +static int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt) { struct sctp_sock *sp = sctp_sk(sk); struct sctp_endpoint *ep = sp->ep; @@ -5964,7 +5964,7 @@ static int sctp_wait_for_accept(struct sock *sk, long timeo) return err; } -void sctp_wait_for_close(struct sock *sk, long timeout) +static void sctp_wait_for_close(struct sock *sk, long timeout) { DEFINE_WAIT(wait); -- cgit v0.10.2 From 0a5fcb9cf8e5c3fabaab1c20668f58fe85d7c70d Mon Sep 17 00:00:00 2001 From: "sebastian@breakpoint.cc" Date: Thu, 26 Jul 2007 23:21:32 +0200 Subject: sctp: move global declaration to header file. sctp_chunk_cachep & sctp_bucket_cachep is used module global, so move it to a header file. Signed-off-by: Sebastian Siewior Signed-off-by: Vlad Yasevich diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 16baef4..d529045 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -190,6 +190,16 @@ void sctp_assocs_proc_exit(void); /* + * Module global variables + */ + + /* + * sctp/protocol.c + */ +extern struct kmem_cache *sctp_chunk_cachep __read_mostly; +extern struct kmem_cache *sctp_bucket_cachep __read_mostly; + +/* * Section: Macros, externs, and inlines */ diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 8d18f57..ad02311 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -65,8 +65,6 @@ #include #include -extern struct kmem_cache *sctp_chunk_cachep; - SCTP_STATIC struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc, __u8 type, __u8 flags, int paylen); diff --git a/net/sctp/socket.c b/net/sctp/socket.c index f8bacc8..f8de0eb 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -107,8 +107,6 @@ static void sctp_sock_migrate(struct sock *, struct sock *, struct sctp_association *, sctp_socket_type_t); static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG; -extern struct kmem_cache *sctp_bucket_cachep; - /* Get the sndbuf space available at the time on the association. */ static inline int sctp_wspace(struct sctp_association *asoc) { -- cgit v0.10.2 From c86dabcf00f3ca167df59f3526a53b3da3ede2c8 Mon Sep 17 00:00:00 2001 From: "sebastian@breakpoint.cc" Date: Thu, 26 Jul 2007 23:21:33 +0200 Subject: sctp: remove shadowed symbols Fixes the following sparse warnings: net/sctp/sm_make_chunk.c:1457:9: warning: symbol 'len' shadows an earlier one net/sctp/sm_make_chunk.c:1356:23: originally declared here net/sctp/socket.c:1534:22: warning: symbol 'chunk' shadows an earlier one net/sctp/socket.c:1387:20: originally declared here Signed-off-by: Sebastian Siewior Signed-off-by: Vlad Yasevich diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index ad02311..ba76cec 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1452,7 +1452,6 @@ no_hmac: do_gettimeofday(&tv); if (!asoc && tv_lt(bear_cookie->expiration, tv)) { - __u16 len; /* * Section 3.3.10.3 Stale Cookie Error (3) * diff --git a/net/sctp/socket.c b/net/sctp/socket.c index f8de0eb..b31be09 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1529,7 +1529,6 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, goto out_unlock; } if (sinfo_flags & SCTP_ABORT) { - struct sctp_chunk *chunk; chunk = sctp_make_abort_user(asoc, msg, msg_len); if (!chunk) { -- cgit v0.10.2 From d6f9fdaf643eca8fb49fffdd6269b78f4ef1ef86 Mon Sep 17 00:00:00 2001 From: Sebastian Siewior Date: Fri, 27 Jul 2007 22:55:59 +0200 Subject: sctp: try to fix readlock unlock the reader lock in error case. Signed-off-by: Sebastian Siewior Signed-off-by: Vlad Yasevich diff --git a/net/sctp/socket.c b/net/sctp/socket.c index b31be09..be743d4 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -4350,7 +4350,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, space_left, &bytes_copied); if (cnt < 0) { err = cnt; - goto error; + goto error_lock; } goto copy_getaddrs; } @@ -4364,7 +4364,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; if (space_left < addrlen) { err = -ENOMEM; /*fixme: right error?*/ - goto error; + goto error_lock; } memcpy(buf, &temp, addrlen); buf += addrlen; @@ -4378,15 +4378,21 @@ copy_getaddrs: if (copy_to_user(to, addrs, bytes_copied)) { err = -EFAULT; - goto error; + goto out; } if (put_user(cnt, &((struct sctp_getaddrs __user *)optval)->addr_num)) { err = -EFAULT; - goto error; + goto out; } if (put_user(bytes_copied, optlen)) err = -EFAULT; -error: + + goto out; + +error_lock: + sctp_read_unlock(addr_lock); + +out: kfree(addrs); return err; } -- cgit v0.10.2 From cc121fa87a0ce356c23fb4d7358310e747cad8cc Mon Sep 17 00:00:00 2001 From: Sebastian Siewior Date: Fri, 27 Jul 2007 22:59:49 +0200 Subject: sctp: fix shadow symbol in net/sctp/tsnmap.c net/sctp/tsnmap.c:164:16: warning: symbol '_end' shadows an earlier one include/asm-generic/sections.h:13:13: originally declared here Renamed renamed _end to end_ and _start (for consistence). Signed-off-by: Sebastian Siewior Signed-off-by: Vlad Yasevich diff --git a/net/sctp/tsnmap.c b/net/sctp/tsnmap.c index d3192a1..1ff0daa 100644 --- a/net/sctp/tsnmap.c +++ b/net/sctp/tsnmap.c @@ -161,7 +161,7 @@ SCTP_STATIC int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map, __u16 *start, __u16 *end) { int started, ended; - __u16 _start, _end, offset; + __u16 start_, end_, offset; /* We haven't found a gap yet. */ started = ended = 0; @@ -175,7 +175,7 @@ SCTP_STATIC int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map, offset = iter->start - map->base_tsn; sctp_tsnmap_find_gap_ack(map->tsn_map, offset, map->len, 0, - &started, &_start, &ended, &_end); + &started, &start_, &ended, &end_); } /* Do we need to check the overflow map? */ @@ -193,8 +193,8 @@ SCTP_STATIC int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map, offset, map->len, map->len, - &started, &_start, - &ended, &_end); + &started, &start_, + &ended, &end_); } /* The Gap Ack Block happens to end at the end of the @@ -202,7 +202,7 @@ SCTP_STATIC int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map, */ if (started && !ended) { ended++; - _end = map->len + map->len - 1; + end_ = map->len + map->len - 1; } /* If we found a Gap Ack Block, return the start and end and @@ -215,8 +215,8 @@ SCTP_STATIC int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map, int gap = map->cumulative_tsn_ack_point - map->base_tsn; - *start = _start - gap; - *end = _end - gap; + *start = start_ - gap; + *end = end_ - gap; /* Move the iterator forward. */ iter->start = map->cumulative_tsn_ack_point + *end + 1; -- cgit v0.10.2 From b225b884a18a1932db5414abd3ef94a45e4e348e Mon Sep 17 00:00:00 2001 From: Dave Johnson Date: Wed, 25 Jul 2007 19:49:29 -0400 Subject: SCTP: IPv4 mapped addr not returned in SCTPv6 accept() An accept() call on a SCTPv6 socket that returns due to connection of a IPv4 mapped peer will fill out the 'struct sockaddr' with a zero IPv6 address instead of the IPv4 mapped address of the peer. This is due to the v4mapped flag not getting copied into the new socket on accept() as well as a missing check for INET6 socket type in sctp_v4_to_sk_*addr(). Signed-off-by: Dave Johnson Cc: Srinivas Akkipeddi Signed-off-by: Vlad Yasevich diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 2c29394..f8aa23d 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -641,6 +641,8 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk, newsctp6sk = (struct sctp6_sock *)newsk; inet_sk(newsk)->pinet6 = &newsctp6sk->inet6; + sctp_sk(newsk)->v4mapped = sctp_sk(sk)->v4mapped; + newinet = inet_sk(newsk); newnp = inet6_sk(newsk); -- cgit v0.10.2 From e4d1feab5df035312494ce3037ac5f041d0f5fc9 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Wed, 1 Aug 2007 10:56:43 -0400 Subject: SCTP: IPv4 mapped addr not returned in SCTPv6 accept() When issuing a connect call on an AF_INET6 sctp socket with a IPv4-mapped destination, the peer address that is returned by getpeeraddr() should be v4-mapped as well. Signed-off-by: Vlad Yasevich diff --git a/net/sctp/socket.c b/net/sctp/socket.c index be743d4..01c6364 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -975,7 +975,7 @@ static int __sctp_connect(struct sock* sk, int err = 0; int addrcnt = 0; int walk_size = 0; - union sctp_addr *sa_addr; + union sctp_addr *sa_addr = NULL; void *addr_buf; unsigned short port; unsigned int f_flags = 0; @@ -1009,7 +1009,10 @@ static int __sctp_connect(struct sock* sk, goto out_free; } - err = sctp_verify_addr(sk, sa_addr, af->sockaddr_len); + /* Save current address so we can work with it */ + memcpy(&to, sa_addr, af->sockaddr_len); + + err = sctp_verify_addr(sk, &to, af->sockaddr_len); if (err) goto out_free; @@ -1019,12 +1022,11 @@ static int __sctp_connect(struct sock* sk, if (asoc && asoc->peer.port && asoc->peer.port != port) goto out_free; - memcpy(&to, sa_addr, af->sockaddr_len); /* Check if there already is a matching association on the * endpoint (other than the one created here). */ - asoc2 = sctp_endpoint_lookup_assoc(ep, sa_addr, &transport); + asoc2 = sctp_endpoint_lookup_assoc(ep, &to, &transport); if (asoc2 && asoc2 != asoc) { if (asoc2->state >= SCTP_STATE_ESTABLISHED) err = -EISCONN; @@ -1037,7 +1039,7 @@ static int __sctp_connect(struct sock* sk, * make sure that there is no peeled-off association matching * the peer address even on another socket. */ - if (sctp_endpoint_is_peeled_off(ep, sa_addr)) { + if (sctp_endpoint_is_peeled_off(ep, &to)) { err = -EADDRNOTAVAIL; goto out_free; } @@ -1068,7 +1070,7 @@ static int __sctp_connect(struct sock* sk, } } - scope = sctp_scope(sa_addr); + scope = sctp_scope(&to); asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); if (!asoc) { err = -ENOMEM; @@ -1077,7 +1079,7 @@ static int __sctp_connect(struct sock* sk, } /* Prime the peer's transport structures. */ - transport = sctp_assoc_add_peer(asoc, sa_addr, GFP_KERNEL, + transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, SCTP_UNKNOWN); if (!transport) { err = -ENOMEM; @@ -1101,8 +1103,8 @@ static int __sctp_connect(struct sock* sk, /* Initialize sk's dport and daddr for getpeername() */ inet_sk(sk)->dport = htons(asoc->peer.port); - af = sctp_get_af_specific(to.sa.sa_family); - af->to_sk_daddr(&to, sk); + af = sctp_get_af_specific(sa_addr->sa.sa_family); + af->to_sk_daddr(sa_addr, sk); sk->sk_err = 0; /* in-kernel sockets don't generally have a file allocated to them -- cgit v0.10.2 From aecedeab6fcf914929cd8ff6fa0b8ae9bfdf3d30 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 2 Aug 2007 16:57:44 +0800 Subject: SCTP: drop SACK if ctsn is not less than the next tsn of assoc We need to drop the SACK if the peer is attempting to acknowledge unset data, i.e. the CTSN in the SACK is greater or equal to the next TSN we will send. Example: Endpoint A Endpoint B <--------------- DATA (TSN=1) SACK(TSN=1) ---------------> <--------------- DATA (TSN=2) <--------------- DATA (TSN=3) <--------------- DATA (TSN=4) <--------------- DATA (TSN=5) SACK(TSN=1000) ---------------> <--------------- DATA (TSN=6) <--------------- DATA (TSN=7) Signed-off-by: Wei Yongjun Signed-off-by: Vlad Yasevich diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index fd2dfdd..71cad56 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -97,6 +97,13 @@ static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, const struct sctp_association *asoc, struct sctp_transport *transport); +static sctp_disposition_t sctp_sf_abort_violation( + const struct sctp_association *asoc, + void *arg, + sctp_cmd_seq_t *commands, + const __u8 *payload, + const size_t paylen); + static sctp_disposition_t sctp_sf_violation_chunklen( const struct sctp_endpoint *ep, const struct sctp_association *asoc, @@ -104,6 +111,13 @@ static sctp_disposition_t sctp_sf_violation_chunklen( void *arg, sctp_cmd_seq_t *commands); +static sctp_disposition_t sctp_sf_violation_ctsn( + const struct sctp_endpoint *ep, + const struct sctp_association *asoc, + const sctp_subtype_t type, + void *arg, + sctp_cmd_seq_t *commands); + /* Small helper function that checks if the chunk length * is of the appropriate length. The 'required_length' argument * is set to be the size of a specific chunk we are testing. @@ -2880,6 +2894,13 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(const struct sctp_endpoint *ep, return SCTP_DISPOSITION_DISCARD; } + /* If Cumulative TSN Ack beyond the max tsn currently + * send, terminating the association and respond to the + * sender with an ABORT. + */ + if (!TSN_lt(ctsn, asoc->next_tsn)) + return sctp_sf_violation_ctsn(ep, asoc, type, arg, commands); + /* Return this SACK for further processing. */ sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, SCTP_SACKH(sackh)); @@ -3691,40 +3712,21 @@ sctp_disposition_t sctp_sf_violation(const struct sctp_endpoint *ep, return SCTP_DISPOSITION_VIOLATION; } - /* - * Handle a protocol violation when the chunk length is invalid. - * "Invalid" length is identified as smaller then the minimal length a - * given chunk can be. For example, a SACK chunk has invalid length - * if it's length is set to be smaller then the size of sctp_sack_chunk_t. - * - * We inform the other end by sending an ABORT with a Protocol Violation - * error code. - * - * Section: Not specified - * Verification Tag: Nothing to do - * Inputs - * (endpoint, asoc, chunk) - * - * Outputs - * (reply_msg, msg_up, counters) - * - * Generate an ABORT chunk and terminate the association. + * Common function to handle a protocol violation. */ -static sctp_disposition_t sctp_sf_violation_chunklen( - const struct sctp_endpoint *ep, +static sctp_disposition_t sctp_sf_abort_violation( const struct sctp_association *asoc, - const sctp_subtype_t type, void *arg, - sctp_cmd_seq_t *commands) + sctp_cmd_seq_t *commands, + const __u8 *payload, + const size_t paylen) { struct sctp_chunk *chunk = arg; struct sctp_chunk *abort = NULL; - char err_str[]="The following chunk had invalid length:"; /* Make the abort chunk. */ - abort = sctp_make_abort_violation(asoc, chunk, err_str, - sizeof(err_str)); + abort = sctp_make_abort_violation(asoc, chunk, payload, paylen); if (!abort) goto nomem; @@ -3756,6 +3758,57 @@ nomem: return SCTP_DISPOSITION_NOMEM; } +/* + * Handle a protocol violation when the chunk length is invalid. + * "Invalid" length is identified as smaller then the minimal length a + * given chunk can be. For example, a SACK chunk has invalid length + * if it's length is set to be smaller then the size of sctp_sack_chunk_t. + * + * We inform the other end by sending an ABORT with a Protocol Violation + * error code. + * + * Section: Not specified + * Verification Tag: Nothing to do + * Inputs + * (endpoint, asoc, chunk) + * + * Outputs + * (reply_msg, msg_up, counters) + * + * Generate an ABORT chunk and terminate the association. + */ +static sctp_disposition_t sctp_sf_violation_chunklen( + const struct sctp_endpoint *ep, + const struct sctp_association *asoc, + const sctp_subtype_t type, + void *arg, + sctp_cmd_seq_t *commands) +{ + char err_str[]="The following chunk had invalid length:"; + + return sctp_sf_abort_violation(asoc, arg, commands, err_str, + sizeof(err_str)); +} + +/* Handle a protocol violation when the peer trying to advance the + * cumulative tsn ack to a point beyond the max tsn currently sent. + * + * We inform the other end by sending an ABORT with a Protocol Violation + * error code. + */ +static sctp_disposition_t sctp_sf_violation_ctsn( + const struct sctp_endpoint *ep, + const struct sctp_association *asoc, + const sctp_subtype_t type, + void *arg, + sctp_cmd_seq_t *commands) +{ + char err_str[]="The cumulative tsn ack beyond the max tsn currently sent:"; + + return sctp_sf_abort_violation(asoc, arg, commands, err_str, + sizeof(err_str)); +} + /*************************************************************************** * These are the state functions for handling primitive (Section 10) events. ***************************************************************************/ -- cgit v0.10.2 From 5f8f1c3c87e44f1bd0180cf19d0e7c83d062b4dc Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 2 Aug 2007 17:02:29 +0800 Subject: SCTP: remove useless code in function sctp_init_cause Some code in function sctp_init_cause() seem useless, this patch remove them. Signed-off-by: Wei Yongjun Signed-off-by: Vlad Yasevich diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index ba76cec..51c4d7f 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -113,15 +113,12 @@ void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code, const void *payload, size_t paylen) { sctp_errhdr_t err; - int padlen; __u16 len; /* Cause code constants are now defined in network order. */ err.cause = cause_code; len = sizeof(sctp_errhdr_t) + paylen; - padlen = len % 4; err.length = htons(len); - len += padlen; chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err); sctp_addto_chunk(chunk, paylen, payload); } -- cgit v0.10.2