summaryrefslogtreecommitdiffstats
path: root/sys/netinet/sctputil.c
diff options
context:
space:
mode:
authorrrs <rrs@FreeBSD.org>2007-06-12 11:21:00 +0000
committerrrs <rrs@FreeBSD.org>2007-06-12 11:21:00 +0000
commit1cd5c5dd060ed74ed2778ad4f459ed32f0ad4a8a (patch)
tree8ceb26064a095a4ca496c0d65130e07c6bab67a1 /sys/netinet/sctputil.c
parent59136b3a6d401102fb2c9ec125e4155ad39526cf (diff)
downloadFreeBSD-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.c144
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
+ */
+ }
+}
OpenPOWER on IntegriCloud