diff options
author | rrs <rrs@FreeBSD.org> | 2007-07-24 20:06:02 +0000 |
---|---|---|
committer | rrs <rrs@FreeBSD.org> | 2007-07-24 20:06:02 +0000 |
commit | 1db8ba247453b3da31775f1a39199179ca75bfb7 (patch) | |
tree | d2ea0fd9ef19605e959e0ed17a4723e94186c995 /lib | |
parent | 4177278d87cbfa0b06b72d4b526e3a39dbd7838b (diff) | |
download | FreeBSD-src-1db8ba247453b3da31775f1a39199179ca75bfb7.zip FreeBSD-src-1db8ba247453b3da31775f1a39199179ca75bfb7.tar.gz |
- take out a needless panic under invariants for sctp_output.c
- Fix addrs's error checking of sctp_sendx(3) when addrcnt is less than
SCTP_SMALL_IOVEC_SIZE
- re-add back inpcb_bind local address check bypass capability
- Fix it so sctp_opt_info is independant of assoc_id postion.
- Fix cookie life set to use MSEC_TO_TICKS() macro.
- asconf changes
o More comment changes/clarifications related to the old local address
"not" list which is now an explicit restricted list.
o Rename some functions for clarity:
- sctp_add/del_local_addr_assoc to xxx_local_addr_restricted()
- asconf related iterator functions to sctp_asconf_iterator_xxx()
o Fix bug when the same address is deleted and added (and removed from
the asconf queue) where the ifa is "freed" twice refcount wise,
possibly freeing it completely.
o Fix bug in output where the first ASCONF would not go out after the
last address is changed (e.g. only goes out when retransmitted).
o Fix bug where multiple ASCONFs can be bundled in the same packet with
the and with the same serial numbers.
o Fix asconf stcb iterator to not send ASCONF until after all work
queue entries have been processed.
o Change behavior so that when the last address is deleted (auto asconf
on a bound all endpoint) no action is taken until an address is
added; at that time, an ASCONF add+delete is sent (if the assoc
is still up).
o Fix local address counting so that address scoping is taken into
account.
o #ifdef SCTP_TIMER_BASED_ASCONF the old timer triggered sending
of ASCONF (after an RTO). The default now is to send
ASCONF immediately (except for the case of changing/deleting the
last usable address).
Approved by: re(ken smith)@freebsd.org
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/net/sctp_sys_calls.c | 113 |
1 files changed, 107 insertions, 6 deletions
diff --git a/lib/libc/net/sctp_sys_calls.c b/lib/libc/net/sctp_sys_calls.c index 922e034..715fcbd 100644 --- a/lib/libc/net/sctp_sys_calls.c +++ b/lib/libc/net/sctp_sys_calls.c @@ -240,7 +240,10 @@ sctp_bindx(int sd, struct sockaddr *addrs, int addrcnt, int flags) { struct sctp_getaddresses *gaddrs; struct sockaddr *sa; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; int i, sz, argsz; + uint16_t sport = 0; /* validate the flags */ if ((flags != SCTP_BINDX_ADD_ADDR) && @@ -260,12 +263,63 @@ sctp_bindx(int sd, struct sockaddr *addrs, int addrcnt, int flags) errno = ENOMEM; return (-1); } + /* First pre-screen the addresses */ sa = addrs; for (i = 0; i < addrcnt; i++) { sz = sa->sa_len; if (sa->sa_family == AF_INET) { if (sa->sa_len != sizeof(struct sockaddr_in)) goto out_error; + sin = (struct sockaddr_in *)sa; + if (sin->sin_port) { + /* non-zero port, check or save */ + if (sport) { + /* Check against our port */ + if (sport != sin->sin_port) { + goto out_error; + } + } else { + /* save off the port */ + sport = sin->sin_port; + } + } + } else if (sa->sa_family == AF_INET6) { + if (sa->sa_len != sizeof(struct sockaddr_in6)) + goto out_error; + sin6 = (struct sockaddr_in6 *)sa; + if (sin6->sin6_port) { + /* non-zero port, check or save */ + if (sport) { + /* Check against our port */ + if (sport != sin6->sin6_port) { + goto out_error; + } + } else { + /* save off the port */ + sport = sin6->sin6_port; + } + } + } else { + /* invalid address family specified */ + goto out_error; + } + + + } + sa = addrs; + /* + * Now if there was a port mentioned, assure that the first address + * has that port to make sure it fails or succeeds correctly. + */ + if (sport) { + sin = (struct sockaddr_in *)sa; + sin->sin_port = sport; + } + for (i = 0; i < addrcnt; i++) { + sz = sa->sa_len; + if (sa->sa_family == AF_INET) { + if (sa->sa_len != sizeof(struct sockaddr_in)) + goto out_error; } else if (sa->sa_family == AF_INET6) { if (sa->sa_len != sizeof(struct sockaddr_in6)) goto out_error; @@ -298,7 +352,55 @@ sctp_opt_info(int sd, sctp_assoc_t id, int opt, void *arg, socklen_t * size) errno = EINVAL; return (-1); } - *(sctp_assoc_t *) arg = id; + switch (opt) { + case SCTP_RTOINFO: + ((struct sctp_rtoinfo *)arg)->srto_assoc_id = id; + break; + case SCTP_ASSOCINFO: + ((struct sctp_assocparams *)arg)->sasoc_assoc_id = id; + break; + case SCTP_DEFAULT_SEND_PARAM: + ((struct sctp_assocparams *)arg)->sasoc_assoc_id = id; + break; + case SCTP_SET_PEER_PRIMARY_ADDR: + ((struct sctp_setpeerprim *)arg)->sspp_assoc_id = id; + break; + case SCTP_PRIMARY_ADDR: + ((struct sctp_setprim *)arg)->ssp_assoc_id = id; + break; + case SCTP_PEER_ADDR_PARAMS: + ((struct sctp_paddrparams *)arg)->spp_assoc_id = id; + break; + case SCTP_MAXSEG: + ((struct sctp_assoc_value *)arg)->assoc_id = id; + break; + case SCTP_AUTH_KEY: + ((struct sctp_authkey *)arg)->sca_assoc_id = id; + break; + case SCTP_AUTH_ACTIVE_KEY: + ((struct sctp_authkeyid *)arg)->scact_assoc_id = id; + break; + case SCTP_DELAYED_SACK: + ((struct sctp_sack_info *)arg)->sack_assoc_id = id; + break; + case SCTP_CONTEXT: + ((struct sctp_assoc_value *)arg)->assoc_id = id; + break; + case SCTP_STATUS: + ((struct sctp_status *)arg)->sstat_assoc_id = id; + break; + case SCTP_GET_PEER_ADDR_INFO: + ((struct sctp_paddrinfo *)arg)->spinfo_assoc_id = id; + break; + case SCTP_PEER_AUTH_CHUNKS: + ((struct sctp_authchunks *)arg)->gauth_assoc_id = id; + break; + case SCTP_LOCAL_AUTH_CHUNKS: + ((struct sctp_authchunks *)arg)->gauth_assoc_id = id; + break; + default: + break; + } return (getsockopt(sd, IPPROTO_SCTP, opt, arg, size)); } @@ -628,7 +730,10 @@ sctp_sendx(int sd, const void *msg, size_t msg_len, int add_len, len, no_end_cx = 0; struct sockaddr *at; - + if (addrs == NULL) { + errno = EINVAL; + return (-1); + } #ifdef SYS_sctp_generic_sendmsg if (addrcnt < SCTP_SMALL_IOVEC_SIZE) { socklen_t l; @@ -643,10 +748,6 @@ sctp_sendx(int sd, const void *msg, size_t msg_len, } #endif - if (addrs == NULL) { - errno = EINVAL; - return (-1); - } len = sizeof(int); at = addrs; cnt = 0; |