diff options
author | rrs <rrs@FreeBSD.org> | 2007-06-12 11:21:00 +0000 |
---|---|---|
committer | rrs <rrs@FreeBSD.org> | 2007-06-12 11:21:00 +0000 |
commit | 1cd5c5dd060ed74ed2778ad4f459ed32f0ad4a8a (patch) | |
tree | 8ceb26064a095a4ca496c0d65130e07c6bab67a1 /sys/netinet/sctputil.c | |
parent | 59136b3a6d401102fb2c9ec125e4155ad39526cf (diff) | |
download | FreeBSD-src-1cd5c5dd060ed74ed2778ad4f459ed32f0ad4a8a.zip FreeBSD-src-1cd5c5dd060ed74ed2778ad4f459ed32f0ad4a8a.tar.gz |
- Restructure so bindx functions are not done inline to socket option
but are a seperate call that can be re-used if needed.
- 64 bit issues
o re-arrange cookie so it is better 64 bit aligned
o For wire level things we need the packed attribute.
Diffstat (limited to 'sys/netinet/sctputil.c')
-rw-r--r-- | sys/netinet/sctputil.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index 9dcc551..fb2e1ad 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -5877,3 +5877,147 @@ sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr, } return ((struct sctp_tcb *)NULL); } + + +/* + * sctp_bindx(ADD) for one address. + * assumes all arguments are valid/checked by caller. + */ +void +sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp, + struct sockaddr *sa, sctp_assoc_t assoc_id, + uint32_t vrf_id, int *error, void *p) +{ + struct sockaddr *addr_touse; + struct sockaddr_in sin; + + /* see if we're bound all already! */ + if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { + *error = EINVAL; + return; + } + addr_touse = sa; +#if defined(INET6) + if (sa->sa_family == AF_INET6) { + struct sockaddr_in6 *sin6; + + if (sa->sa_len != sizeof(struct sockaddr_in6)) { + *error = EINVAL; + return; + } + sin6 = (struct sockaddr_in6 *)addr_touse; + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { + in6_sin6_2_sin(&sin, sin6); + addr_touse = (struct sockaddr *)&sin; + } + } +#endif + if (sa->sa_family == AF_INET) { + if (sa->sa_len != sizeof(struct sockaddr_in)) { + *error = EINVAL; + return; + } + } + if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) { + if (p == NULL) { + /* Can't get proc for Net/Open BSD */ + *error = EINVAL; + return; + } + *error = sctp_inpcb_bind(so, addr_touse, p); + return; + } + /* + * No locks required here since bind and mgmt_ep_sa all do their own + * locking. If we do something for the FIX: below we may need to + * lock in that case. + */ + if (assoc_id == 0) { + /* add the address */ + struct sctp_inpcb *lep; + + ((struct sockaddr_in *)addr_touse)->sin_port = inp->sctp_lport; + lep = sctp_pcb_findep(addr_touse, 1, 0, vrf_id); + if (lep != NULL) { + /* + * We must decrement the refcount since we have the + * ep already and are binding. No remove going on + * here. + */ + SCTP_INP_DECR_REF(inp); + } + if (lep == inp) { + /* already bound to it.. ok */ + return; + } else if (lep == NULL) { + ((struct sockaddr_in *)addr_touse)->sin_port = 0; + *error = sctp_addr_mgmt_ep_sa(inp, addr_touse, + SCTP_ADD_IP_ADDRESS, + vrf_id); + } else { + *error = EADDRINUSE; + } + if (*error) + return; + } else { + /* + * FIX: decide whether we allow assoc based bindx + */ + } +} + +/* + * sctp_bindx(DELETE) for one address. + * assumes all arguments are valid/checked by caller. + */ +void +sctp_bindx_delete_address(struct socket *so, struct sctp_inpcb *inp, + struct sockaddr *sa, sctp_assoc_t assoc_id, + uint32_t vrf_id, int *error) +{ + struct sockaddr *addr_touse; + struct sockaddr_in sin; + + /* see if we're bound all already! */ + if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { + *error = EINVAL; + return; + } + addr_touse = sa; +#if defined(INET6) + if (sa->sa_family == AF_INET6) { + struct sockaddr_in6 *sin6; + + if (sa->sa_len != sizeof(struct sockaddr_in6)) { + *error = EINVAL; + return; + } + sin6 = (struct sockaddr_in6 *)addr_touse; + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { + in6_sin6_2_sin(&sin, sin6); + addr_touse = (struct sockaddr *)&sin; + } + } +#endif + if (sa->sa_family == AF_INET) { + if (sa->sa_len != sizeof(struct sockaddr_in)) { + *error = EINVAL; + return; + } + } + /* + * No lock required mgmt_ep_sa does its own locking. If the FIX: + * below is ever changed we may need to lock before calling + * association level binding. + */ + if (assoc_id == 0) { + /* delete the address */ + *error = sctp_addr_mgmt_ep_sa(inp, addr_touse, + SCTP_DEL_IP_ADDRESS, + vrf_id); + } else { + /* + * FIX: decide whether we allow assoc based bindx + */ + } +} |