Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / usrsctp / usrsctplib / netinet / sctp_usrreq.c
index 796fd16..296b9f3 100755 (executable)
@@ -32,7 +32,7 @@
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 267688 2014-06-20 20:17:39Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 271221 2014-09-07 09:06:26Z tuexen $");
 #endif
 
 #include <netinet/sctp_os.h>
@@ -1676,7 +1676,7 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
                                        if (ipv4_addr_legal) {
                                                struct sockaddr_in *sin;
 
-                                               sin = (struct sockaddr_in *)&sctp_ifa->address.sa;
+                                               sin = &sctp_ifa->address.sin;
                                                if (sin->sin_addr.s_addr == 0) {
                                                        /*
                                                         * we skip unspecifed
@@ -1725,7 +1725,7 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
 #if defined(SCTP_EMBEDDED_V6_SCOPE) && !defined(SCTP_KAME)
                                                struct sockaddr_in6 lsa6;
 #endif
-                                               sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
+                                               sin6 = &sctp_ifa->address.sin6;
                                                if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
                                                        /*
                                                         * we skip unspecifed
@@ -4002,6 +4002,195 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
                }
                break;
        }
+       case SCTP_ECN_SUPPORTED:
+       {
+               struct sctp_assoc_value *av;
+
+               SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
+               SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+               if (stcb) {
+                       av->assoc_value = stcb->asoc.ecn_supported;
+                       SCTP_TCB_UNLOCK(stcb);
+               } else {
+                       if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+                           (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+                           (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+                               SCTP_INP_RLOCK(inp);
+                               av->assoc_value = inp->ecn_supported;
+                               SCTP_INP_RUNLOCK(inp);
+                       } else {
+                               SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                               error = EINVAL;
+                       }
+               }
+               if (error == 0) {
+                       *optsize = sizeof(struct sctp_assoc_value);
+               }
+               break;
+       }
+       case SCTP_PR_SUPPORTED:
+       {
+               struct sctp_assoc_value *av;
+
+               SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
+               SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+               if (stcb) {
+                       av->assoc_value = stcb->asoc.prsctp_supported;
+                       SCTP_TCB_UNLOCK(stcb);
+               } else {
+                       if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+                           (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+                           (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+                               SCTP_INP_RLOCK(inp);
+                               av->assoc_value = inp->prsctp_supported;
+                               SCTP_INP_RUNLOCK(inp);
+                       } else {
+                               SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                               error = EINVAL;
+                       }
+               }
+               if (error == 0) {
+                       *optsize = sizeof(struct sctp_assoc_value);
+               }
+               break;
+       }
+       case SCTP_AUTH_SUPPORTED:
+       {
+               struct sctp_assoc_value *av;
+
+               SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
+               SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+               if (stcb) {
+                       av->assoc_value = stcb->asoc.auth_supported;
+                       SCTP_TCB_UNLOCK(stcb);
+               } else {
+                       if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+                           (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+                           (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+                               SCTP_INP_RLOCK(inp);
+                               av->assoc_value = inp->auth_supported;
+                               SCTP_INP_RUNLOCK(inp);
+                       } else {
+                               SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                               error = EINVAL;
+                       }
+               }
+               if (error == 0) {
+                       *optsize = sizeof(struct sctp_assoc_value);
+               }
+               break;
+       }
+       case SCTP_ASCONF_SUPPORTED:
+       {
+               struct sctp_assoc_value *av;
+
+               SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
+               SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+               if (stcb) {
+                       av->assoc_value = stcb->asoc.asconf_supported;
+                       SCTP_TCB_UNLOCK(stcb);
+               } else {
+                       if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+                           (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+                           (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+                               SCTP_INP_RLOCK(inp);
+                               av->assoc_value = inp->asconf_supported;
+                               SCTP_INP_RUNLOCK(inp);
+                       } else {
+                               SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                               error = EINVAL;
+                       }
+               }
+               if (error == 0) {
+                       *optsize = sizeof(struct sctp_assoc_value);
+               }
+               break;
+       }
+       case SCTP_RECONFIG_SUPPORTED:
+       {
+               struct sctp_assoc_value *av;
+
+               SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
+               SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+               if (stcb) {
+                       av->assoc_value = stcb->asoc.reconfig_supported;
+                       SCTP_TCB_UNLOCK(stcb);
+               } else {
+                       if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+                           (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+                           (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+                               SCTP_INP_RLOCK(inp);
+                               av->assoc_value = inp->reconfig_supported;
+                               SCTP_INP_RUNLOCK(inp);
+                       } else {
+                               SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                               error = EINVAL;
+                       }
+               }
+               if (error == 0) {
+                       *optsize = sizeof(struct sctp_assoc_value);
+               }
+               break;
+       }
+       case SCTP_NRSACK_SUPPORTED:
+       {
+               struct sctp_assoc_value *av;
+
+               SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
+               SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+               if (stcb) {
+                       av->assoc_value = stcb->asoc.nrsack_supported;
+                       SCTP_TCB_UNLOCK(stcb);
+               } else {
+                       if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+                           (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+                           (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+                               SCTP_INP_RLOCK(inp);
+                               av->assoc_value = inp->nrsack_supported;
+                               SCTP_INP_RUNLOCK(inp);
+                       } else {
+                               SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                               error = EINVAL;
+                       }
+               }
+               if (error == 0) {
+                       *optsize = sizeof(struct sctp_assoc_value);
+               }
+               break;
+       }
+       case SCTP_PKTDROP_SUPPORTED:
+       {
+               struct sctp_assoc_value *av;
+
+               SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
+               SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+               if (stcb) {
+                       av->assoc_value = stcb->asoc.pktdrop_supported;
+                       SCTP_TCB_UNLOCK(stcb);
+               } else {
+                       if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+                           (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+                           (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+                               SCTP_INP_RLOCK(inp);
+                               av->assoc_value = inp->pktdrop_supported;
+                               SCTP_INP_RUNLOCK(inp);
+                       } else {
+                               SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                               error = EINVAL;
+                       }
+               }
+               if (error == 0) {
+                       *optsize = sizeof(struct sctp_assoc_value);
+               }
+               break;
+       }
        case SCTP_ENABLE_STREAM_RESET:
        {
                struct sctp_assoc_value *av;
@@ -4029,6 +4218,72 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
                }
                break;
        }
+       case SCTP_PR_STREAM_STATUS:
+       {
+               struct sctp_prstatus *sprstat;
+               uint16_t sid;
+               uint16_t policy;
+
+               SCTP_CHECK_AND_CAST(sprstat, optval, struct sctp_prstatus, *optsize);
+               SCTP_FIND_STCB(inp, stcb, sprstat->sprstat_assoc_id);
+
+               sid = sprstat->sprstat_sid;
+               policy = sprstat->sprstat_policy;
+#if defined(SCTP_DETAILED_STR_STATS)
+               if ((stcb != NULL) &&
+                   (policy != SCTP_PR_SCTP_NONE) &&
+                   (sid < stcb->asoc.streamoutcnt) &&
+                   ((policy == SCTP_PR_SCTP_ALL) ||
+                    (PR_SCTP_VALID_POLICY(policy)))) {
+#else
+               if ((stcb != NULL) &&
+                   (policy != SCTP_PR_SCTP_NONE) &&
+                   (sid < stcb->asoc.streamoutcnt) &&
+                   (policy == SCTP_PR_SCTP_ALL)) {
+#endif
+                       if (policy == SCTP_PR_SCTP_ALL) {
+                               sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[0];
+                               sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[0];
+                       } else {
+                               sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[policy];
+                               sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[policy];
+                       }
+                       SCTP_TCB_UNLOCK(stcb);
+                       *optsize = sizeof(struct sctp_prstatus);
+               } else {
+                       SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                       error = EINVAL;
+               }
+               break;
+       }
+       case SCTP_PR_ASSOC_STATUS:
+       {
+               struct sctp_prstatus *sprstat;
+               uint16_t policy;
+
+               SCTP_CHECK_AND_CAST(sprstat, optval, struct sctp_prstatus, *optsize);
+               SCTP_FIND_STCB(inp, stcb, sprstat->sprstat_assoc_id);
+
+               policy = sprstat->sprstat_policy;
+               if ((stcb != NULL) &&
+                   (policy != SCTP_PR_SCTP_NONE) &&
+                   ((policy == SCTP_PR_SCTP_ALL) ||
+                    (PR_SCTP_VALID_POLICY(policy)))) {
+                       if (policy == SCTP_PR_SCTP_ALL) {
+                               sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[0];
+                               sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[0];
+                       } else {
+                               sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[policy];
+                               sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[policy];
+                       }
+                       SCTP_TCB_UNLOCK(stcb);
+                       *optsize = sizeof(struct sctp_prstatus);
+               } else {
+                       SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                       error = EINVAL;
+               }
+               break;
+       }
        default:
                SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
                error = ENOPROTOOPT;
@@ -4452,7 +4707,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
                        /* The VRF must be in the VRF list */
                        if (*default_vrfid == inp->m_vrf_ids[i]) {
                                SCTP_INP_WLOCK(inp);
-                               inp->def_vrf_id = *default_vrfid;
+                               inp->def_vrf_id = *default_vrfid;
                                SCTP_INP_WUNLOCK(inp);
                                goto sctp_done;
                        }
@@ -4571,7 +4826,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
                SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
                error = EOPNOTSUPP;
 #endif
-               break;
+               break;
        }
        case SCTP_DELAYED_SACK:
        {
@@ -4987,7 +5242,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
                        error = ENOENT;
                        break;
                }
-               if (stcb->asoc.peer_supports_strreset == 0) {
+               if (stcb->asoc.reconfig_supported == 0) {
                        /*
                         * Peer does not support the chunk type.
                         */
@@ -5054,7 +5309,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
                        error = ENOENT;
                        break;
                }
-               if (stcb->asoc.peer_supports_strreset == 0) {
+               if (stcb->asoc.reconfig_supported == 0) {
                        /*
                         * Peer does not support the chunk type.
                         */
@@ -5120,7 +5375,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
                        error = ENOENT;
                        break;
                }
-               if (stcb->asoc.peer_supports_strreset == 0) {
+               if (stcb->asoc.reconfig_supported == 0) {
                        /*
                         * Peer does not support the chunk type.
                         */
@@ -5662,7 +5917,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
                                        }
                                        if (net->dest_state & SCTP_ADDR_REACHABLE) {
                                                if (net->error_count > paddrp->spp_pathmaxrxt) {
-                                                       net->dest_state &= ~SCTP_ADDR_REACHABLE;
+                                                       net->dest_state &= ~SCTP_ADDR_REACHABLE;
                                                        sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
                                                }
                                        } else {
@@ -5705,7 +5960,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
                                                }
                                                if (net->dest_state & SCTP_ADDR_REACHABLE) {
                                                        if (net->error_count > paddrp->spp_pathmaxrxt) {
-                                                               net->dest_state &= ~SCTP_ADDR_REACHABLE;
+                                                               net->dest_state &= ~SCTP_ADDR_REACHABLE;
                                                                sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
                                                        }
                                                } else {
@@ -6204,7 +6459,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
 #endif
                {
                       error = EAFNOSUPPORT;
-                      break;
+                      break;
                }
                sctp_bindx_add_address(so, inp, addrs->addr,
                                       addrs->sget_assoc_id, vrf_id,
@@ -6602,7 +6857,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
                                } else {
                                        if ((net->failure_threshold > thlds->spt_pathpfthld) &&
                                            (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
-                                               net->dest_state |= SCTP_ADDR_PF;
+                                               net->dest_state |= SCTP_ADDR_PF;
                                                sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
                                                sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
                                                sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
@@ -6631,7 +6886,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
                                        } else {
                                                if ((net->failure_threshold > thlds->spt_pathpfthld) &&
                                                    (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
-                                                       net->dest_state |= SCTP_ADDR_PF;
+                                                       net->dest_state |= SCTP_ADDR_PF;
                                                        sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
                                                        sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
                                                        sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
@@ -6762,6 +7017,231 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
                }
                break;
        }
+       case SCTP_ECN_SUPPORTED:
+       {
+               struct sctp_assoc_value *av;
+
+               SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
+               SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+               if (stcb) {
+                       SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                       error = EINVAL;
+                       SCTP_TCB_UNLOCK(stcb);
+               } else {
+                       if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+                           (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+                           (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+                               SCTP_INP_WLOCK(inp);
+                               if (av->assoc_value == 0) {
+                                       inp->ecn_supported = 0;
+                               } else {
+                                       inp->ecn_supported = 1;
+                               }
+                               SCTP_INP_WUNLOCK(inp);
+                       } else {
+                               SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                               error = EINVAL;
+                       }
+               }
+               break;
+       }
+       case SCTP_PR_SUPPORTED:
+       {
+               struct sctp_assoc_value *av;
+
+               SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
+               SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+               if (stcb) {
+                       SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                       error = EINVAL;
+                       SCTP_TCB_UNLOCK(stcb);
+               } else {
+                       if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+                           (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+                           (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+                               SCTP_INP_WLOCK(inp);
+                               if (av->assoc_value == 0) {
+                                       inp->prsctp_supported = 0;
+                               } else {
+                                       inp->prsctp_supported = 1;
+                               }
+                               SCTP_INP_WUNLOCK(inp);
+                       } else {
+                               SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                               error = EINVAL;
+                       }
+               }
+               break;
+       }
+       case SCTP_AUTH_SUPPORTED:
+       {
+               struct sctp_assoc_value *av;
+
+               SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
+               SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+               if (stcb) {
+                       SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                       error = EINVAL;
+                       SCTP_TCB_UNLOCK(stcb);
+               } else {
+                       if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+                           (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+                           (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+                               if ((av->assoc_value == 0) &&
+                                   (inp->asconf_supported == 1)) {
+                                       /* AUTH is required for ASCONF */
+                                       SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                                       error = EINVAL;
+                               } else {
+                                       SCTP_INP_WLOCK(inp);
+                                       if (av->assoc_value == 0) {
+                                               inp->auth_supported = 0;
+                                       } else {
+                                               inp->auth_supported = 1;
+                                       }
+                                       SCTP_INP_WUNLOCK(inp);
+                               }
+                       } else {
+                               SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                               error = EINVAL;
+                       }
+               }
+               break;
+       }
+       case SCTP_ASCONF_SUPPORTED:
+       {
+               struct sctp_assoc_value *av;
+
+               SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
+               SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+               if (stcb) {
+                       SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                       error = EINVAL;
+                       SCTP_TCB_UNLOCK(stcb);
+               } else {
+                       if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+                           (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+                           (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+                               if ((av->assoc_value != 0) &&
+                                   (inp->auth_supported == 0)) {
+                                       /* AUTH is required for ASCONF */
+                                       SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                                       error = EINVAL;
+                               } else {
+                                       SCTP_INP_WLOCK(inp);
+                                       if (av->assoc_value == 0) {
+                                               inp->asconf_supported = 0;
+                                               sctp_auth_delete_chunk(SCTP_ASCONF,
+                                                                      inp->sctp_ep.local_auth_chunks);
+                                               sctp_auth_delete_chunk(SCTP_ASCONF_ACK,
+                                                                      inp->sctp_ep.local_auth_chunks);
+                                       } else {
+                                               inp->asconf_supported = 1;
+                                               sctp_auth_add_chunk(SCTP_ASCONF,
+                                                                   inp->sctp_ep.local_auth_chunks);
+                                               sctp_auth_add_chunk(SCTP_ASCONF_ACK,
+                                                                   inp->sctp_ep.local_auth_chunks);
+                                       }
+                                       SCTP_INP_WUNLOCK(inp);
+                               }
+                       } else {
+                               SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                               error = EINVAL;
+                       }
+               }
+               break;
+       }
+       case SCTP_RECONFIG_SUPPORTED:
+       {
+               struct sctp_assoc_value *av;
+
+               SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
+               SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+               if (stcb) {
+                       SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                       error = EINVAL;
+                       SCTP_TCB_UNLOCK(stcb);
+               } else {
+                       if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+                           (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+                           (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+                               SCTP_INP_WLOCK(inp);
+                               if (av->assoc_value == 0) {
+                                       inp->reconfig_supported = 0;
+                               } else {
+                                       inp->reconfig_supported = 1;
+                               }
+                               SCTP_INP_WUNLOCK(inp);
+                       } else {
+                               SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                               error = EINVAL;
+                       }
+               }
+               break;
+       }
+       case SCTP_NRSACK_SUPPORTED:
+       {
+               struct sctp_assoc_value *av;
+
+               SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
+               SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+               if (stcb) {
+                       SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                       error = EINVAL;
+                       SCTP_TCB_UNLOCK(stcb);
+               } else {
+                       if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+                           (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+                           (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+                               SCTP_INP_WLOCK(inp);
+                               if (av->assoc_value == 0) {
+                                       inp->nrsack_supported = 0;
+                               } else {
+                                       inp->nrsack_supported = 1;
+                               }
+                               SCTP_INP_WUNLOCK(inp);
+                       } else {
+                               SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                               error = EINVAL;
+                       }
+               }
+               break;
+       }
+       case SCTP_PKTDROP_SUPPORTED:
+       {
+               struct sctp_assoc_value *av;
+
+               SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
+               SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+               if (stcb) {
+                       SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                       error = EINVAL;
+                       SCTP_TCB_UNLOCK(stcb);
+               } else {
+                       if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+                           (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+                           (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+                               SCTP_INP_WLOCK(inp);
+                               if (av->assoc_value == 0) {
+                                       inp->pktdrop_supported = 0;
+                               } else {
+                                       inp->pktdrop_supported = 1;
+                               }
+                               SCTP_INP_WUNLOCK(inp);
+                       } else {
+                               SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+                               error = EINVAL;
+                       }
+               }
+               break;
+       }
        default:
                SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
                error = ENOPROTOOPT;
@@ -6928,7 +7408,7 @@ sctp_connect(struct socket *so, struct mbuf *nam, struct proc *p)
 #endif
        default:
                SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
-               return (EAFNOSUPPORT);
+               return (EAFNOSUPPORT);
        }
 #endif
        SCTP_INP_INCR_REF(inp);
@@ -7103,7 +7583,7 @@ sctpconn_connect(struct socket *so, struct sockaddr *addr)
                break;
        default:
                SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
-               return (EAFNOSUPPORT);
+               return (EAFNOSUPPORT);
        }
        SCTP_INP_INCR_REF(inp);
        SCTP_ASOC_CREATE_LOCK(inp);
@@ -7735,7 +8215,7 @@ sctp_ingetaddr(struct socket *so, struct mbuf *nam)
                        if (laddr->ifa->address.sa.sa_family == AF_INET) {
                                struct sockaddr_in *sin_a;
 
-                               sin_a = (struct sockaddr_in *)&laddr->ifa->address.sa;
+                               sin_a = &laddr->ifa->address.sin;
                                sin->sin_addr = sin_a->sin_addr;
                                fnd = 1;
                                break;