From 7eeb079d84bc4abe9897be0047fc28a754e46ecd Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 2 Feb 2015 14:27:13 +0100 Subject: Update to FreeBSD 9.3 --- freebsd/sys/netinet/if_ether.c | 8 +- freebsd/sys/netinet/in.c | 52 +-- freebsd/sys/netinet/in_mcast.c | 30 +- freebsd/sys/netinet/in_pcb.c | 2 +- freebsd/sys/netinet/ip_icmp.c | 1 + freebsd/sys/netinet/ip_input.c | 5 +- freebsd/sys/netinet/ip_mroute.c | 20 +- freebsd/sys/netinet/ip_output.c | 16 +- freebsd/sys/netinet/sctp.h | 79 ++-- freebsd/sys/netinet/sctp_asconf.c | 92 +++- freebsd/sys/netinet/sctp_auth.c | 137 ++---- freebsd/sys/netinet/sctp_auth.h | 15 +- freebsd/sys/netinet/sctp_bsd_addr.c | 13 +- freebsd/sys/netinet/sctp_constants.h | 16 +- freebsd/sys/netinet/sctp_dtrace_define.h | 261 +++++------ freebsd/sys/netinet/sctp_indata.c | 725 ++++++++++--------------------- freebsd/sys/netinet/sctp_input.c | 128 +++--- freebsd/sys/netinet/sctp_os_bsd.h | 26 +- freebsd/sys/netinet/sctp_output.c | 302 ++++++++++--- freebsd/sys/netinet/sctp_pcb.c | 229 ++++++---- freebsd/sys/netinet/sctp_pcb.h | 2 +- freebsd/sys/netinet/sctp_structs.h | 4 +- freebsd/sys/netinet/sctp_sysctl.c | 17 +- freebsd/sys/netinet/sctp_sysctl.h | 8 +- freebsd/sys/netinet/sctp_timer.c | 48 +- freebsd/sys/netinet/sctp_uio.h | 4 - freebsd/sys/netinet/sctp_usrreq.c | 176 +++++--- freebsd/sys/netinet/sctputil.c | 138 ++++-- freebsd/sys/netinet/sctputil.h | 4 +- freebsd/sys/netinet/tcp_input.c | 6 +- freebsd/sys/netinet/tcp_reass.c | 7 +- freebsd/sys/netinet/tcp_subr.c | 6 +- 32 files changed, 1231 insertions(+), 1346 deletions(-) (limited to 'freebsd/sys/netinet') diff --git a/freebsd/sys/netinet/if_ether.c b/freebsd/sys/netinet/if_ether.c index 98ed0b36..e4f76fee 100644 --- a/freebsd/sys/netinet/if_ether.c +++ b/freebsd/sys/netinet/if_ether.c @@ -156,10 +156,10 @@ arp_ifscrub(struct ifnet *ifp, uint32_t addr) addr4.sin_len = sizeof(addr4); addr4.sin_family = AF_INET; addr4.sin_addr.s_addr = addr; - IF_AFDATA_LOCK(ifp); + IF_AFDATA_RLOCK(ifp); lla_lookup(LLTABLE(ifp), (LLE_DELETE | LLE_IFADDR), (struct sockaddr *)&addr4); - IF_AFDATA_UNLOCK(ifp); + IF_AFDATA_RUNLOCK(ifp); } #endif @@ -792,9 +792,9 @@ reply: struct llentry *lle = NULL; sin.sin_addr = itaddr; - IF_AFDATA_LOCK(ifp); + IF_AFDATA_RLOCK(ifp); lle = lla_lookup(LLTABLE(ifp), 0, (struct sockaddr *)&sin); - IF_AFDATA_UNLOCK(ifp); + IF_AFDATA_RUNLOCK(ifp); if ((lle != NULL) && (lle->la_flags & LLE_PUB)) { (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); diff --git a/freebsd/sys/netinet/in.c b/freebsd/sys/netinet/in.c index 0c3f72bc..bc7323e3 100644 --- a/freebsd/sys/netinet/in.c +++ b/freebsd/sys/netinet/in.c @@ -962,45 +962,6 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin, ((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) \ ? RTF_HOST : 0) -/* - * Generate a routing message when inserting or deleting - * an interface address alias. - */ -static void in_addralias_rtmsg(int cmd, struct in_addr *prefix, - struct in_ifaddr *target) -{ - struct route pfx_ro; - struct sockaddr_in *pfx_addr; - struct rtentry msg_rt; - - /* QL: XXX - * This is a bit questionable because there is no - * additional route entry added/deleted for an address - * alias. Therefore this route report is inaccurate. - */ - bzero(&pfx_ro, sizeof(pfx_ro)); - pfx_addr = (struct sockaddr_in *)(&pfx_ro.ro_dst); - pfx_addr->sin_len = sizeof(*pfx_addr); - pfx_addr->sin_family = AF_INET; - pfx_addr->sin_addr = *prefix; - rtalloc_ign_fib(&pfx_ro, 0, 0); - if (pfx_ro.ro_rt != NULL) { - msg_rt = *pfx_ro.ro_rt; - - /* QL: XXX - * Point the gateway to the new interface - * address as if a new prefix route entry has - * been added through the new address alias. - * All other parts of the rtentry is accurate, - * e.g., rt_key, rt_mask, rt_ifp etc. - */ - msg_rt.rt_gateway = (struct sockaddr *)&target->ia_addr; - rt_newaddrmsg(cmd, (struct ifaddr *)target, 0, &msg_rt); - RTFREE(pfx_ro.ro_rt); - } - return; -} - /* * Check if we have a route for the given prefix already or add one accordingly. */ @@ -1009,7 +970,7 @@ in_addprefix(struct in_ifaddr *target, int flags) { struct in_ifaddr *ia; struct in_addr prefix, mask, p, m; - int error; + int error, fibnum; if ((flags & RTF_HOST) != 0) { prefix = target->ia_dstaddr.sin_addr; @@ -1020,6 +981,8 @@ in_addprefix(struct in_ifaddr *target, int flags) prefix.s_addr &= mask.s_addr; } + fibnum = rt_add_addr_allfibs ? RT_ALL_FIBS : target->ia_ifp->if_fib; + IN_IFADDR_RLOCK(); TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) { if (rtinitflags(ia)) { @@ -1056,7 +1019,7 @@ in_addprefix(struct in_ifaddr *target, int flags) IN_IFADDR_RUNLOCK(); return (EEXIST); } else { - in_addralias_rtmsg(RTM_ADD, &prefix, target); + rt_addrmsg(RTM_ADD, &target->ia_ifa, fibnum); IN_IFADDR_RUNLOCK(); return (0); } @@ -1085,9 +1048,11 @@ in_scrubprefix(struct in_ifaddr *target, u_int flags) { struct in_ifaddr *ia; struct in_addr prefix, mask, p; - int error = 0; + int error = 0, fibnum; struct sockaddr_in prefix0, mask0; + fibnum = rt_add_addr_allfibs ? RT_ALL_FIBS : target->ia_ifp->if_fib; + /* * Remove the loopback route to the interface address. * The "useloopback" setting is not consulted because if the @@ -1139,7 +1104,7 @@ in_scrubprefix(struct in_ifaddr *target, u_int flags) } if ((target->ia_flags & IFA_ROUTE) == 0) { - in_addralias_rtmsg(RTM_DELETE, &prefix, target); + rt_addrmsg(RTM_DELETE, &target->ia_ifa, fibnum); return (0); } @@ -1501,6 +1466,7 @@ in_lltable_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3add #endif if (!(flags & LLE_CREATE)) return (NULL); + IF_AFDATA_WLOCK_ASSERT(ifp); /* * A route that covers the given address must have * been installed 1st because we are doing a resolution, diff --git a/freebsd/sys/netinet/in_mcast.c b/freebsd/sys/netinet/in_mcast.c index 6d748f1f..4112046c 100644 --- a/freebsd/sys/netinet/in_mcast.c +++ b/freebsd/sys/netinet/in_mcast.c @@ -140,7 +140,9 @@ static int in_getmulti(struct ifnet *, const struct in_addr *, struct in_multi **); static int inm_get_source(struct in_multi *inm, const in_addr_t haddr, const int noalloc, struct ip_msource **pims); +#ifdef KTR static int inm_is_ifp_detached(const struct in_multi *); +#endif static int inm_merge(struct in_multi *, /*const*/ struct in_mfilter *); static void inm_purge(struct in_multi *); static void inm_reap(struct in_multi *); @@ -181,6 +183,7 @@ static SYSCTL_NODE(_net_inet_ip_mcast, OID_AUTO, filters, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_ip_mcast_filters, "Per-interface stack-wide source filters"); +#ifdef KTR /* * Inline function which wraps assertions for a valid ifp. * The ifnet layer will set the ifma's ifp pointer to NULL if the ifp @@ -203,6 +206,7 @@ inm_is_ifp_detached(const struct in_multi *inm) return (ifp == NULL); } +#endif /* * Initialize an in_mfilter structure to a known state at t0, t1 @@ -1444,7 +1448,7 @@ inp_block_unblock_source(struct inpcb *inp, struct sockopt *sopt) error = inm_merge(inm, imf); if (error) { CTR1(KTR_IGMPV3, "%s: failed to merge inm state", __func__); - goto out_imf_rollback; + goto out_in_multi_locked; } CTR1(KTR_IGMPV3, "%s: doing igmp downcall", __func__); @@ -1452,6 +1456,8 @@ inp_block_unblock_source(struct inpcb *inp, struct sockopt *sopt) if (error) CTR1(KTR_IGMPV3, "%s: failed igmp downcall", __func__); +out_in_multi_locked: + IN_MULTI_UNLOCK(); out_imf_rollback: @@ -2092,8 +2098,12 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt) if (is_new) { error = in_joingroup_locked(ifp, &gsa->sin.sin_addr, imf, &inm); - if (error) + if (error) { + CTR1(KTR_IGMPV3, "%s: in_joingroup_locked failed", + __func__); + IN_MULTI_UNLOCK(); goto out_imo_free; + } imo->imo_membership[idx] = inm; } else { CTR1(KTR_IGMPV3, "%s: merge inm state", __func__); @@ -2101,20 +2111,21 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt) if (error) { CTR1(KTR_IGMPV3, "%s: failed to merge inm state", __func__); - goto out_imf_rollback; + goto out_in_multi_locked; } CTR1(KTR_IGMPV3, "%s: doing igmp downcall", __func__); error = igmp_change_state(inm); if (error) { CTR1(KTR_IGMPV3, "%s: failed igmp downcall", __func__); - goto out_imf_rollback; + goto out_in_multi_locked; } } +out_in_multi_locked: + IN_MULTI_UNLOCK(); -out_imf_rollback: INP_WLOCK_ASSERT(inp); if (error) { imf_rollback(imf); @@ -2318,7 +2329,7 @@ inp_leave_group(struct inpcb *inp, struct sockopt *sopt) if (error) { CTR1(KTR_IGMPV3, "%s: failed to merge inm state", __func__); - goto out_imf_rollback; + goto out_in_multi_locked; } CTR1(KTR_IGMPV3, "%s: doing igmp downcall", __func__); @@ -2329,9 +2340,10 @@ inp_leave_group(struct inpcb *inp, struct sockopt *sopt) } } +out_in_multi_locked: + IN_MULTI_UNLOCK(); -out_imf_rollback: if (error) imf_rollback(imf); else @@ -2565,7 +2577,7 @@ inp_set_source_filters(struct inpcb *inp, struct sockopt *sopt) error = inm_merge(inm, imf); if (error) { CTR1(KTR_IGMPV3, "%s: failed to merge inm state", __func__); - goto out_imf_rollback; + goto out_in_multi_locked; } CTR1(KTR_IGMPV3, "%s: doing igmp downcall", __func__); @@ -2573,6 +2585,8 @@ inp_set_source_filters(struct inpcb *inp, struct sockopt *sopt) if (error) CTR1(KTR_IGMPV3, "%s: failed igmp downcall", __func__); +out_in_multi_locked: + IN_MULTI_UNLOCK(); out_imf_rollback: diff --git a/freebsd/sys/netinet/in_pcb.c b/freebsd/sys/netinet/in_pcb.c index 5100ac9b..b93abadf 100644 --- a/freebsd/sys/netinet/in_pcb.c +++ b/freebsd/sys/netinet/in_pcb.c @@ -559,7 +559,7 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp, * and a multicast address is bound on both * new and duplicated sockets. */ - if (so->so_options & SO_REUSEADDR) + if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) != 0) reuseport = SO_REUSEADDR|SO_REUSEPORT; } else if (sin->sin_addr.s_addr != INADDR_ANY) { sin->sin_port = 0; /* yech... */ diff --git a/freebsd/sys/netinet/ip_icmp.c b/freebsd/sys/netinet/ip_icmp.c index b003d03f..b6876f77 100644 --- a/freebsd/sys/netinet/ip_icmp.c +++ b/freebsd/sys/netinet/ip_icmp.c @@ -345,6 +345,7 @@ stdreply: icmpelen = max(8, min(V_icmp_quotelen, oip->ip_len - oiphlen)); nip->ip_hl = 5; nip->ip_p = IPPROTO_ICMP; nip->ip_tos = 0; + nip->ip_off = 0; icmp_reflect(m); freeit: diff --git a/freebsd/sys/netinet/ip_input.c b/freebsd/sys/netinet/ip_input.c index 2dbb2a7a..2247c1a8 100644 --- a/freebsd/sys/netinet/ip_input.c +++ b/freebsd/sys/netinet/ip_input.c @@ -1110,8 +1110,9 @@ found: * (and not in for{} loop), though it implies we are not going to * reassemble more than 64k fragments. */ - m->m_pkthdr.csum_data = - (m->m_pkthdr.csum_data & 0xffff) + (m->m_pkthdr.csum_data >> 16); + while (m->m_pkthdr.csum_data & 0xffff0000) + m->m_pkthdr.csum_data = (m->m_pkthdr.csum_data & 0xffff) + + (m->m_pkthdr.csum_data >> 16); #ifdef MAC mac_ipq_reassemble(fp, m); mac_ipq_destroy(fp); diff --git a/freebsd/sys/netinet/ip_mroute.c b/freebsd/sys/netinet/ip_mroute.c index 6fc5cc68..20daee5a 100644 --- a/freebsd/sys/netinet/ip_mroute.c +++ b/freebsd/sys/netinet/ip_mroute.c @@ -610,7 +610,7 @@ static void if_detached_event(void *arg __unused, struct ifnet *ifp) { vifi_t vifi; - int i; + u_long i; MROUTER_LOCK(); @@ -705,10 +705,9 @@ ip_mrouter_init(struct socket *so, int version) static int X_ip_mrouter_done(void) { - vifi_t vifi; - int i; struct ifnet *ifp; - struct ifreq ifr; + u_long i; + vifi_t vifi; MROUTER_LOCK(); @@ -733,11 +732,6 @@ X_ip_mrouter_done(void) for (vifi = 0; vifi < V_numvifs; vifi++) { if (!in_nullhost(V_viftable[vifi].v_lcl_addr) && !(V_viftable[vifi].v_flags & (VIFF_TUNNEL | VIFF_REGISTER))) { - struct sockaddr_in *so = (struct sockaddr_in *)&(ifr.ifr_addr); - - so->sin_len = sizeof(struct sockaddr_in); - so->sin_family = AF_INET; - so->sin_addr.s_addr = INADDR_ANY; ifp = V_viftable[vifi].v_ifp; if_allmulti(ifp, 0); } @@ -804,7 +798,7 @@ set_assert(int i) int set_api_config(uint32_t *apival) { - int i; + u_long i; /* * We can set the API capabilities only if it is the first operation @@ -826,6 +820,7 @@ set_api_config(uint32_t *apival) for (i = 0; i < mfchashsize; i++) { if (LIST_FIRST(&V_mfchashtbl[i]) != NULL) { + MFC_UNLOCK(); *apival = 0; return EPERM; } @@ -1439,7 +1434,7 @@ non_fatal: static void expire_upcalls(void *arg) { - int i; + u_long i; CURVNET_SET((struct vnet *) arg); @@ -2848,7 +2843,8 @@ ip_mroute_modevent(module_t mod, int type, void *unused) if_detach_event_tag = EVENTHANDLER_REGISTER(ifnet_departure_event, if_detached_event, NULL, EVENTHANDLER_PRI_ANY); if (if_detach_event_tag == NULL) { - printf("ip_mroute: unable to ifnet_deperture_even handler\n"); + printf("ip_mroute: unable to register " + "ifnet_departure_event handler\n"); MROUTER_LOCK_DESTROY(); return (EINVAL); } diff --git a/freebsd/sys/netinet/ip_output.c b/freebsd/sys/netinet/ip_output.c index a70d3142..93ebf4d6 100644 --- a/freebsd/sys/netinet/ip_output.c +++ b/freebsd/sys/netinet/ip_output.c @@ -869,17 +869,13 @@ in_delayed_cksum(struct mbuf *m) csum = 0xffff; offset += m->m_pkthdr.csum_data; /* checksum offset */ - if (offset + sizeof(u_short) > m->m_len) { - printf("delayed m_pullup, m->len: %d off: %d p: %d\n", - m->m_len, offset, ip->ip_p); - /* - * XXX - * this shouldn't happen, but if it does, the - * correct behavior may be to insert the checksum - * in the appropriate next mbuf in the chain. - */ - return; + /* find the mbuf in the chain where the checksum starts*/ + while ((m != NULL) && (offset >= m->m_len)) { + offset -= m->m_len; + m = m->m_next; } + KASSERT(m != NULL, ("in_delayed_cksum: checksum outside mbuf chain.")); + KASSERT(offset + sizeof(u_short) <= m->m_len, ("in_delayed_cksum: checksum split between mbufs.")); *(u_short *)(m->m_data + offset) = csum; } diff --git a/freebsd/sys/netinet/sctp.h b/freebsd/sys/netinet/sctp.h index 03cf86a3..d0b90d34 100644 --- a/freebsd/sys/netinet/sctp.h +++ b/freebsd/sys/netinet/sctp.h @@ -43,13 +43,13 @@ __FBSDID("$FreeBSD$"); #define SCTP_PACKED __attribute__((packed)) /* - * SCTP protocol - RFC2960. + * SCTP protocol - RFC4960. */ struct sctphdr { uint16_t src_port; /* source port */ uint16_t dest_port; /* destination port */ uint32_t v_tag; /* verification tag of packet */ - uint32_t checksum; /* Adler32 C-Sum */ + uint32_t checksum; /* CRC32C checksum */ /* chunks follow... */ } SCTP_PACKED; @@ -365,6 +365,12 @@ struct sctp_paramhdr { /* * error cause parameters (user visible) */ +struct sctp_gen_error_cause { + uint16_t code; + uint16_t length; + uint8_t info[]; +} SCTP_PACKED; + struct sctp_error_cause { uint16_t code; uint16_t length; @@ -402,6 +408,11 @@ struct sctp_error_unrecognized_chunk { struct sctp_chunkhdr ch;/* header from chunk in error */ } SCTP_PACKED; +struct sctp_error_no_user_data { + struct sctp_error_cause cause; /* code=SCTP_CAUSE_NO_USER_DATA */ + uint32_t tsn; /* TSN of the empty data chunk */ +} SCTP_PACKED; + /* * Main SCTP chunk types we place these here so natd and f/w's in user land * can find them. @@ -425,7 +436,7 @@ struct sctp_error_unrecognized_chunk { /* RFC4895 */ #define SCTP_AUTHENTICATION 0x0f /* EY nr_sack chunk id*/ -#define SCTP_NR_SELECTIVE_ACK 0x10 +#define SCTP_NR_SELECTIVE_ACK 0x10 /************0x40 series ***********/ /************0x80 series ***********/ /* RFC5061 */ @@ -509,38 +520,38 @@ struct sctp_error_unrecognized_chunk { /* * PCB Features (in sctp_features bitmask) */ -#define SCTP_PCB_FLAGS_DO_NOT_PMTUD 0x00000001 -#define SCTP_PCB_FLAGS_EXT_RCVINFO 0x00000002 /* deprecated */ -#define SCTP_PCB_FLAGS_DONOT_HEARTBEAT 0x00000004 -#define SCTP_PCB_FLAGS_FRAG_INTERLEAVE 0x00000008 -#define SCTP_PCB_FLAGS_INTERLEAVE_STRMS 0x00000010 -#define SCTP_PCB_FLAGS_DO_ASCONF 0x00000020 -#define SCTP_PCB_FLAGS_AUTO_ASCONF 0x00000040 -#define SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE 0x00000080 +#define SCTP_PCB_FLAGS_DO_NOT_PMTUD 0x0000000000000001 +#define SCTP_PCB_FLAGS_EXT_RCVINFO 0x0000000000000002 /* deprecated */ +#define SCTP_PCB_FLAGS_DONOT_HEARTBEAT 0x0000000000000004 +#define SCTP_PCB_FLAGS_FRAG_INTERLEAVE 0x0000000000000008 +#define SCTP_PCB_FLAGS_INTERLEAVE_STRMS 0x0000000000000010 +#define SCTP_PCB_FLAGS_DO_ASCONF 0x0000000000000020 +#define SCTP_PCB_FLAGS_AUTO_ASCONF 0x0000000000000040 +#define SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE 0x0000000000000080 /* socket options */ -#define SCTP_PCB_FLAGS_NODELAY 0x00000100 -#define SCTP_PCB_FLAGS_AUTOCLOSE 0x00000200 -#define SCTP_PCB_FLAGS_RECVDATAIOEVNT 0x00000400 /* deprecated */ -#define SCTP_PCB_FLAGS_RECVASSOCEVNT 0x00000800 -#define SCTP_PCB_FLAGS_RECVPADDREVNT 0x00001000 -#define SCTP_PCB_FLAGS_RECVPEERERR 0x00002000 -#define SCTP_PCB_FLAGS_RECVSENDFAILEVNT 0x00004000 /* deprecated */ -#define SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT 0x00008000 -#define SCTP_PCB_FLAGS_ADAPTATIONEVNT 0x00010000 -#define SCTP_PCB_FLAGS_PDAPIEVNT 0x00020000 -#define SCTP_PCB_FLAGS_AUTHEVNT 0x00040000 -#define SCTP_PCB_FLAGS_STREAM_RESETEVNT 0x00080000 -#define SCTP_PCB_FLAGS_NO_FRAGMENT 0x00100000 -#define SCTP_PCB_FLAGS_EXPLICIT_EOR 0x00400000 -#define SCTP_PCB_FLAGS_NEEDS_MAPPED_V4 0x00800000 -#define SCTP_PCB_FLAGS_MULTIPLE_ASCONFS 0x01000000 -#define SCTP_PCB_FLAGS_PORTREUSE 0x02000000 -#define SCTP_PCB_FLAGS_DRYEVNT 0x04000000 -#define SCTP_PCB_FLAGS_RECVRCVINFO 0x08000000 -#define SCTP_PCB_FLAGS_RECVNXTINFO 0x10000000 -#define SCTP_PCB_FLAGS_ASSOC_RESETEVNT 0x20000000 -#define SCTP_PCB_FLAGS_STREAM_CHANGEEVNT 0x40000000 -#define SCTP_PCB_FLAGS_RECVNSENDFAILEVNT 0x80000000 +#define SCTP_PCB_FLAGS_NODELAY 0x0000000000000100 +#define SCTP_PCB_FLAGS_AUTOCLOSE 0x0000000000000200 +#define SCTP_PCB_FLAGS_RECVDATAIOEVNT 0x0000000000000400 /* deprecated */ +#define SCTP_PCB_FLAGS_RECVASSOCEVNT 0x0000000000000800 +#define SCTP_PCB_FLAGS_RECVPADDREVNT 0x0000000000001000 +#define SCTP_PCB_FLAGS_RECVPEERERR 0x0000000000002000 +#define SCTP_PCB_FLAGS_RECVSENDFAILEVNT 0x0000000000004000 /* deprecated */ +#define SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT 0x0000000000008000 +#define SCTP_PCB_FLAGS_ADAPTATIONEVNT 0x0000000000010000 +#define SCTP_PCB_FLAGS_PDAPIEVNT 0x0000000000020000 +#define SCTP_PCB_FLAGS_AUTHEVNT 0x0000000000040000 +#define SCTP_PCB_FLAGS_STREAM_RESETEVNT 0x0000000000080000 +#define SCTP_PCB_FLAGS_NO_FRAGMENT 0x0000000000100000 +#define SCTP_PCB_FLAGS_EXPLICIT_EOR 0x0000000000400000 +#define SCTP_PCB_FLAGS_NEEDS_MAPPED_V4 0x0000000000800000 +#define SCTP_PCB_FLAGS_MULTIPLE_ASCONFS 0x0000000001000000 +#define SCTP_PCB_FLAGS_PORTREUSE 0x0000000002000000 +#define SCTP_PCB_FLAGS_DRYEVNT 0x0000000004000000 +#define SCTP_PCB_FLAGS_RECVRCVINFO 0x0000000008000000 +#define SCTP_PCB_FLAGS_RECVNXTINFO 0x0000000010000000 +#define SCTP_PCB_FLAGS_ASSOC_RESETEVNT 0x0000000020000000 +#define SCTP_PCB_FLAGS_STREAM_CHANGEEVNT 0x0000000040000000 +#define SCTP_PCB_FLAGS_RECVNSENDFAILEVNT 0x0000000080000000 /*- * mobility_features parameters (by micchie).Note diff --git a/freebsd/sys/netinet/sctp_asconf.c b/freebsd/sys/netinet/sctp_asconf.c index 71fa307c..551f0690 100644 --- a/freebsd/sys/netinet/sctp_asconf.c +++ b/freebsd/sys/netinet/sctp_asconf.c @@ -152,7 +152,12 @@ sctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *ap struct mbuf *m_reply = NULL; struct sockaddr_storage sa_store; struct sctp_paramhdr *ph; - uint16_t param_type, param_length, aparam_length; + uint16_t param_type, aparam_length; + +#if defined(INET) || defined(INET6) + uint16_t param_length; + +#endif struct sockaddr *sa; int zero_address = 0; int bad_address = 0; @@ -171,8 +176,9 @@ sctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *ap aparam_length = ntohs(aph->ph.param_length); ph = (struct sctp_paramhdr *)(aph + 1); param_type = ntohs(ph->param_type); +#if defined(INET) || defined(INET6) param_length = ntohs(ph->param_length); - +#endif sa = (struct sockaddr *)&sa_store; switch (param_type) { #ifdef INET @@ -300,7 +306,12 @@ sctp_process_asconf_delete_ip(struct sockaddr *src, struct mbuf *m_reply = NULL; struct sockaddr_storage sa_store; struct sctp_paramhdr *ph; - uint16_t param_type, param_length, aparam_length; + uint16_t param_type, aparam_length; + +#if defined(INET) || defined(INET6) + uint16_t param_length; + +#endif struct sockaddr *sa; int zero_address = 0; int result; @@ -319,8 +330,9 @@ sctp_process_asconf_delete_ip(struct sockaddr *src, aparam_length = ntohs(aph->ph.param_length); ph = (struct sctp_paramhdr *)(aph + 1); param_type = ntohs(ph->param_type); +#if defined(INET) || defined(INET6) param_length = ntohs(ph->param_length); - +#endif sa = (struct sockaddr *)&sa_store; switch (param_type) { #ifdef INET @@ -429,7 +441,12 @@ sctp_process_asconf_set_primary(struct sockaddr *src, struct mbuf *m_reply = NULL; struct sockaddr_storage sa_store; struct sctp_paramhdr *ph; - uint16_t param_type, param_length, aparam_length; + uint16_t param_type, aparam_length; + +#if defined(INET) || defined(INET6) + uint16_t param_length; + +#endif struct sockaddr *sa; int zero_address = 0; @@ -447,8 +464,9 @@ sctp_process_asconf_set_primary(struct sockaddr *src, aparam_length = ntohs(aph->ph.param_length); ph = (struct sctp_paramhdr *)(aph + 1); param_type = ntohs(ph->param_type); +#if defined(INET) || defined(INET6) param_length = ntohs(ph->param_length); - +#endif sa = (struct sockaddr *)&sa_store; switch (param_type) { #ifdef INET @@ -862,10 +880,12 @@ sctp_asconf_addr_match(struct sctp_asconf_addr *aa, struct sockaddr *sa) static uint32_t sctp_addr_match(struct sctp_paramhdr *ph, struct sockaddr *sa) { +#if defined(INET) || defined(INET6) uint16_t param_type, param_length; param_type = ntohs(ph->param_type); param_length = ntohs(ph->param_length); +#endif switch (sa->sa_family) { #ifdef INET6 case AF_INET6: @@ -876,7 +896,7 @@ sctp_addr_match(struct sctp_paramhdr *ph, struct sockaddr *sa) v6addr = (struct sctp_ipv6addr_param *)ph; if ((param_type == SCTP_IPV6_ADDRESS) && - param_length == sizeof(struct sctp_ipv6addr_param) && + (param_length == sizeof(struct sctp_ipv6addr_param)) && (memcmp(&v6addr->addr, &sin6->sin6_addr, sizeof(struct in6_addr)) == 0)) { return (1); @@ -892,7 +912,7 @@ sctp_addr_match(struct sctp_paramhdr *ph, struct sockaddr *sa) v4addr = (struct sctp_ipv4addr_param *)ph; if ((param_type == SCTP_IPV4_ADDRESS) && - param_length == sizeof(struct sctp_ipv4addr_param) && + (param_length == sizeof(struct sctp_ipv4addr_param)) && (memcmp(&v4addr->addr, &sin->sin_addr, sizeof(struct in_addr)) == 0)) { return (1); @@ -1193,7 +1213,6 @@ sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa, uint16_t type) { struct sctp_asconf_addr *aa, *aa_next; - struct sockaddr *sa; /* make sure the request isn't already in the queue */ TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) { @@ -1257,7 +1276,6 @@ sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa, struct sockaddr_in6 *sin6; sin6 = (struct sockaddr_in6 *)&ifa->address.sa; - sa = (struct sockaddr *)sin6; aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param)); aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + @@ -1273,7 +1291,6 @@ sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa, struct sockaddr_in *sin; sin = (struct sockaddr_in *)&ifa->address.sa; - sa = (struct sockaddr *)sin; aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param)); aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + @@ -1296,13 +1313,13 @@ sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa, if (SCTP_BASE_SYSCTL(sctp_debug_on) & SCTP_DEBUG_ASCONF2) { if (type == SCTP_ADD_IP_ADDRESS) { SCTP_PRINTF("asconf_queue_mgmt: inserted asconf ADD_IP_ADDRESS: "); - SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa); + SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa); } else if (type == SCTP_DEL_IP_ADDRESS) { SCTP_PRINTF("asconf_queue_mgmt: appended asconf DEL_IP_ADDRESS: "); - SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa); + SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa); } else { SCTP_PRINTF("asconf_queue_mgmt: appended asconf SET_PRIM_ADDR: "); - SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa); + SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa); } } #endif @@ -1874,14 +1891,22 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, * this is boundall or subset bound w/ASCONF allowed */ - /* first, make sure it's a good address family */ + /* first, make sure that the address is IPv4 or IPv6 and not jailed */ switch (ifa->address.sa.sa_family) { #ifdef INET6 case AF_INET6: + if (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &ifa->address.sin6.sin6_addr) != 0) { + return; + } break; #endif #ifdef INET case AF_INET: + if (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &ifa->address.sin.sin_addr) != 0) { + return; + } break; #endif default: @@ -2107,6 +2132,10 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb, /* we skip unspecifed addresses */ continue; } + if (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sin6->sin6_addr) != 0) { + continue; + } if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { if (stcb->asoc.scope.local_scope == 0) { continue; @@ -2137,6 +2166,10 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb, /* we skip unspecifed addresses */ continue; } + if (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sin->sin_addr) != 0) { + continue; + } if (stcb->asoc.scope.ipv4_local_scope == 0 && IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { continue; @@ -2450,6 +2483,10 @@ sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked) /* skip unspecifed addresses */ continue; } + if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred, + &sin->sin_addr) != 0) { + continue; + } if (stcb->asoc.scope.ipv4_local_scope == 0 && IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) continue; @@ -2483,6 +2520,10 @@ sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked) */ continue; } + if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred, + &sin6->sin6_addr) != 0) { + continue; + } if (stcb->asoc.scope.local_scope == 0 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) continue; @@ -2601,7 +2642,8 @@ sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked) /* get the parameter length */ p_length = SCTP_SIZE32(aa->ap.aph.ph.param_length); /* will it fit in current chunk? */ - if (SCTP_BUF_LEN(m_asconf) + p_length > stcb->asoc.smallest_mtu) { + if ((SCTP_BUF_LEN(m_asconf) + p_length > stcb->asoc.smallest_mtu) || + (SCTP_BUF_LEN(m_asconf) + p_length > MCLBYTES)) { /* won't fit, so we're done with this chunk */ break; } @@ -2722,7 +2764,7 @@ sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked) /* chain it all together */ SCTP_BUF_NEXT(m_asconf_chk) = m_asconf; *retlen = SCTP_BUF_LEN(m_asconf_chk) + SCTP_BUF_LEN(m_asconf); - acp->ch.chunk_length = ntohs(*retlen); + acp->ch.chunk_length = htons(*retlen); return (m_asconf_chk); } @@ -3096,6 +3138,10 @@ sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset, #ifdef INET case AF_INET: sin = (struct sockaddr_in *)&sctp_ifa->address.sin; + if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred, + &sin->sin_addr) != 0) { + continue; + } if ((ipv4_scope == 0) && (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { /* private address not in scope */ @@ -3106,6 +3152,10 @@ sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset, #ifdef INET6 case AF_INET6: sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sin6; + if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred, + &sin6->sin6_addr) != 0) { + continue; + } if ((local_scope == 0) && (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))) { continue; @@ -3391,6 +3441,10 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb, #ifdef INET case AF_INET: to = &sctp_ifap->address.sin; + if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred, + &to->sin_addr) != 0) { + continue; + } if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) { continue; } @@ -3402,6 +3456,10 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb, #ifdef INET6 case AF_INET6: to6 = &sctp_ifap->address.sin6; + if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred, + &to6->sin6_addr) != 0) { + continue; + } if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) { continue; } diff --git a/freebsd/sys/netinet/sctp_auth.c b/freebsd/sys/netinet/sctp_auth.c index ddb12560..fc649032 100644 --- a/freebsd/sys/netinet/sctp_auth.c +++ b/freebsd/sys/netinet/sctp_auth.c @@ -335,10 +335,6 @@ sctp_generate_random_key(uint32_t keylen) { sctp_key_t *new_key; - /* validate keylen */ - if (keylen > SCTP_AUTH_RANDOM_SIZE_MAX) - keylen = SCTP_AUTH_RANDOM_SIZE_MAX; - new_key = sctp_alloc_key(keylen); if (new_key == NULL) { /* out of memory */ @@ -376,7 +372,7 @@ sctp_compare_key(sctp_key_t * key1, sctp_key_t * key2) uint32_t i; uint32_t key1len, key2len; uint8_t *key_1, *key_2; - uint8_t temp[SCTP_AUTH_RANDOM_SIZE_MAX]; + uint8_t val1, val2; /* sanity/length check */ key1len = sctp_get_keylen(key1); @@ -388,38 +384,24 @@ sctp_compare_key(sctp_key_t * key1, sctp_key_t * key2) else if (key2len == 0) return (1); - if (key1len != key2len) { - if (key1len >= key2len) - maxlen = key1len; - else - maxlen = key2len; - bzero(temp, maxlen); - if (key1len < maxlen) { - /* prepend zeroes to key1 */ - bcopy(key1->key, temp + (maxlen - key1len), key1len); - key_1 = temp; - key_2 = key2->key; - } else { - /* prepend zeroes to key2 */ - bcopy(key2->key, temp + (maxlen - key2len), key2len); - key_1 = key1->key; - key_2 = temp; - } + if (key1len < key2len) { + maxlen = key2len; } else { maxlen = key1len; - key_1 = key1->key; - key_2 = key2->key; } - + key_1 = key1->key; + key_2 = key2->key; + /* check for numeric equality */ for (i = 0; i < maxlen; i++) { - if (*key_1 > *key_2) + /* left-pad with zeros */ + val1 = (i < (maxlen - key1len)) ? 0 : *(key_1++); + val2 = (i < (maxlen - key2len)) ? 0 : *(key_2++); + if (val1 > val2) { return (1); - else if (*key_1 < *key_2) + } else if (val1 < val2) { return (-1); - key_1++; - key_2++; + } } - /* keys are equal value, so check lengths */ if (key1len == key2len) return (0); @@ -705,15 +687,7 @@ sctp_auth_add_hmacid(sctp_hmaclist_t * list, uint16_t hmac_id) return (-1); } if ((hmac_id != SCTP_AUTH_HMAC_ID_SHA1) && -#ifdef HAVE_SHA224 - (hmac_id != SCTP_AUTH_HMAC_ID_SHA224) && -#endif -#ifdef HAVE_SHA2 - (hmac_id != SCTP_AUTH_HMAC_ID_SHA256) && - (hmac_id != SCTP_AUTH_HMAC_ID_SHA384) && - (hmac_id != SCTP_AUTH_HMAC_ID_SHA512) && -#endif - 1) { + (hmac_id != SCTP_AUTH_HMAC_ID_SHA256)) { return (-1); } /* Now is it already in the list */ @@ -756,8 +730,9 @@ sctp_default_supported_hmaclist(void) new_list = sctp_alloc_hmaclist(2); if (new_list == NULL) return (NULL); - (void)sctp_auth_add_hmacid(new_list, SCTP_AUTH_HMAC_ID_SHA1); + /* We prefer SHA256, so list it first */ (void)sctp_auth_add_hmacid(new_list, SCTP_AUTH_HMAC_ID_SHA256); + (void)sctp_auth_add_hmacid(new_list, SCTP_AUTH_HMAC_ID_SHA1); return (new_list); } @@ -813,19 +788,13 @@ int sctp_verify_hmac_param(struct sctp_auth_hmac_algo *hmacs, uint32_t num_hmacs) { uint32_t i; - uint16_t hmac_id; - uint32_t sha1_supported = 0; for (i = 0; i < num_hmacs; i++) { - hmac_id = ntohs(hmacs->hmac_ids[i]); - if (hmac_id == SCTP_AUTH_HMAC_ID_SHA1) - sha1_supported = 1; + if (ntohs(hmacs->hmac_ids[i]) == SCTP_AUTH_HMAC_ID_SHA1) { + return (0); + } } - /* all HMAC id's are supported */ - if (sha1_supported == 0) - return (-1); - else - return (0); + return (-1); } sctp_authinfo_t * @@ -879,18 +848,8 @@ sctp_get_hmac_digest_len(uint16_t hmac_algo) switch (hmac_algo) { case SCTP_AUTH_HMAC_ID_SHA1: return (SCTP_AUTH_DIGEST_LEN_SHA1); -#ifdef HAVE_SHA224 - case SCTP_AUTH_HMAC_ID_SHA224: - return (SCTP_AUTH_DIGEST_LEN_SHA224); -#endif -#ifdef HAVE_SHA2 case SCTP_AUTH_HMAC_ID_SHA256: return (SCTP_AUTH_DIGEST_LEN_SHA256); - case SCTP_AUTH_HMAC_ID_SHA384: - return (SCTP_AUTH_DIGEST_LEN_SHA384); - case SCTP_AUTH_HMAC_ID_SHA512: - return (SCTP_AUTH_DIGEST_LEN_SHA512); -#endif default: /* unknown HMAC algorithm: can't do anything */ return (0); @@ -902,17 +861,9 @@ sctp_get_hmac_block_len(uint16_t hmac_algo) { switch (hmac_algo) { case SCTP_AUTH_HMAC_ID_SHA1: -#ifdef HAVE_SHA224 - case SCTP_AUTH_HMAC_ID_SHA224: -#endif return (64); -#ifdef HAVE_SHA2 case SCTP_AUTH_HMAC_ID_SHA256: return (64); - case SCTP_AUTH_HMAC_ID_SHA384: - case SCTP_AUTH_HMAC_ID_SHA512: - return (128); -#endif case SCTP_AUTH_HMAC_ID_RSVD: default: /* unknown HMAC algorithm: can't do anything */ @@ -925,23 +876,11 @@ sctp_hmac_init(uint16_t hmac_algo, sctp_hash_context_t * ctx) { switch (hmac_algo) { case SCTP_AUTH_HMAC_ID_SHA1: - SHA1_Init(&ctx->sha1); + SCTP_SHA1_INIT(&ctx->sha1); break; -#ifdef HAVE_SHA224 - case SCTP_AUTH_HMAC_ID_SHA224: - break; -#endif -#ifdef HAVE_SHA2 case SCTP_AUTH_HMAC_ID_SHA256: - SHA256_Init(&ctx->sha256); + SCTP_SHA256_INIT(&ctx->sha256); break; - case SCTP_AUTH_HMAC_ID_SHA384: - SHA384_Init(&ctx->sha384); - break; - case SCTP_AUTH_HMAC_ID_SHA512: - SHA512_Init(&ctx->sha512); - break; -#endif case SCTP_AUTH_HMAC_ID_RSVD: default: /* unknown HMAC algorithm: can't do anything */ @@ -955,23 +894,11 @@ sctp_hmac_update(uint16_t hmac_algo, sctp_hash_context_t * ctx, { switch (hmac_algo) { case SCTP_AUTH_HMAC_ID_SHA1: - SHA1_Update(&ctx->sha1, text, textlen); - break; -#ifdef HAVE_SHA224 - case SCTP_AUTH_HMAC_ID_SHA224: + SCTP_SHA1_UPDATE(&ctx->sha1, text, textlen); break; -#endif -#ifdef HAVE_SHA2 case SCTP_AUTH_HMAC_ID_SHA256: - SHA256_Update(&ctx->sha256, text, textlen); - break; - case SCTP_AUTH_HMAC_ID_SHA384: - SHA384_Update(&ctx->sha384, text, textlen); - break; - case SCTP_AUTH_HMAC_ID_SHA512: - SHA512_Update(&ctx->sha512, text, textlen); + SCTP_SHA256_UPDATE(&ctx->sha256, text, textlen); break; -#endif case SCTP_AUTH_HMAC_ID_RSVD: default: /* unknown HMAC algorithm: can't do anything */ @@ -985,24 +912,11 @@ sctp_hmac_final(uint16_t hmac_algo, sctp_hash_context_t * ctx, { switch (hmac_algo) { case SCTP_AUTH_HMAC_ID_SHA1: - SHA1_Final(digest, &ctx->sha1); - break; -#ifdef HAVE_SHA224 - case SCTP_AUTH_HMAC_ID_SHA224: + SCTP_SHA1_FINAL(digest, &ctx->sha1); break; -#endif -#ifdef HAVE_SHA2 case SCTP_AUTH_HMAC_ID_SHA256: - SHA256_Final(digest, &ctx->sha256); - break; - case SCTP_AUTH_HMAC_ID_SHA384: - /* SHA384 is truncated SHA512 */ - SHA384_Final(digest, &ctx->sha384); + SCTP_SHA256_FINAL(digest, &ctx->sha256); break; - case SCTP_AUTH_HMAC_ID_SHA512: - SHA512_Final(digest, &ctx->sha512); - break; -#endif case SCTP_AUTH_HMAC_ID_RSVD: default: /* unknown HMAC algorithm: can't do anything */ @@ -1878,6 +1792,7 @@ sctp_notify_authentication(struct sctp_tcb *stcb, uint32_t indication, SCTP_BUF_LEN(m_notify) = 0; auth = mtod(m_notify, struct sctp_authkey_event *); + memset(auth, 0, sizeof(struct sctp_authkey_event)); auth->auth_type = SCTP_AUTHENTICATION_EVENT; auth->auth_flags = 0; auth->auth_length = sizeof(*auth); diff --git a/freebsd/sys/netinet/sctp_auth.h b/freebsd/sys/netinet/sctp_auth.h index eac89f6f..535c0fc0 100644 --- a/freebsd/sys/netinet/sctp_auth.h +++ b/freebsd/sys/netinet/sctp_auth.h @@ -36,28 +36,21 @@ __FBSDID("$FreeBSD$"); #ifndef _NETINET_SCTP_AUTH_H_ #define _NETINET_SCTP_AUTH_H_ +#include /* digest lengths */ #define SCTP_AUTH_DIGEST_LEN_SHA1 20 -#define SCTP_AUTH_DIGEST_LEN_SHA224 28 #define SCTP_AUTH_DIGEST_LEN_SHA256 32 -#define SCTP_AUTH_DIGEST_LEN_SHA384 48 -#define SCTP_AUTH_DIGEST_LEN_SHA512 64 -#define SCTP_AUTH_DIGEST_LEN_MAX 64 +#define SCTP_AUTH_DIGEST_LEN_MAX SCTP_AUTH_DIGEST_LEN_SHA256 /* random sizes */ #define SCTP_AUTH_RANDOM_SIZE_DEFAULT 32 #define SCTP_AUTH_RANDOM_SIZE_REQUIRED 32 -#define SCTP_AUTH_RANDOM_SIZE_MAX 256 /* union of all supported HMAC algorithm contexts */ typedef union sctp_hash_context { - SHA1_CTX sha1; -#ifdef HAVE_SHA2 - SHA256_CTX sha256; - SHA384_CTX sha384; - SHA512_CTX sha512; -#endif + SCTP_SHA1_CTX sha1; + SCTP_SHA256_CTX sha256; } sctp_hash_context_t; typedef struct sctp_key { diff --git a/freebsd/sys/netinet/sctp_bsd_addr.c b/freebsd/sys/netinet/sctp_bsd_addr.c index 4653b251..d558bd82 100644 --- a/freebsd/sys/netinet/sctp_bsd_addr.c +++ b/freebsd/sys/netinet/sctp_bsd_addr.c @@ -98,22 +98,15 @@ sctp_iterator_thread(void *v SCTP_UNUSED) void sctp_startup_iterator(void) { - static int called = 0; - int ret; - - if (called) { + if (sctp_it_ctl.thread_proc) { /* You only get one */ return; } - /* init the iterator head */ - called = 1; - sctp_it_ctl.iterator_running = 0; - sctp_it_ctl.iterator_flags = 0; - sctp_it_ctl.cur_it = NULL; + /* Initialize global locks here, thus only once. */ SCTP_ITERATOR_LOCK_INIT(); SCTP_IPI_ITERATOR_WQ_INIT(); TAILQ_INIT(&sctp_it_ctl.iteratorhead); - ret = kproc_create(sctp_iterator_thread, + kproc_create(sctp_iterator_thread, (void *)NULL, &sctp_it_ctl.thread_proc, RFPROC, diff --git a/freebsd/sys/netinet/sctp_constants.h b/freebsd/sys/netinet/sctp_constants.h index 58ca808e..0ede04ca 100644 --- a/freebsd/sys/netinet/sctp_constants.h +++ b/freebsd/sys/netinet/sctp_constants.h @@ -36,16 +36,10 @@ __FBSDID("$FreeBSD$"); #ifndef _NETINET_SCTP_CONSTANTS_H_ #define _NETINET_SCTP_CONSTANTS_H_ + /* IANA assigned port number for SCTP over UDP encapsulation */ -/* For freebsd we cannot bind the port at - * startup. Otherwise what will happen is - * we really won't be bound. The user must - * put it into the sysctl... or we need - * to build a special timer for this to allow - * us to wait 1 second or so after the system - * comes up. - */ -#define SCTP_OVER_UDP_TUNNELING_PORT 0 +#define SCTP_OVER_UDP_TUNNELING_PORT 9899 + /* Number of packets to get before sack sent by default */ #define SCTP_DEFAULT_SACK_FREQ 2 @@ -726,7 +720,6 @@ __FBSDID("$FreeBSD$"); /* small chunk store for looking at chunk_list in auth */ #define SCTP_SMALL_CHUNK_STORE 260 -#define SCTP_DEFAULT_MINSEGMENT 512 /* MTU size ... if no mtu disc */ #define SCTP_HOW_MANY_SECRETS 2 /* how many secrets I keep */ #define SCTP_NUMBER_OF_SECRETS 8 /* or 8 * 4 = 32 octets */ @@ -772,6 +765,9 @@ __FBSDID("$FreeBSD$"); */ #define SCTP_DEFAULT_SPLIT_POINT_MIN 2904 +/* Maximum length of diagnostic information in error causes */ +#define SCTP_DIAG_INFO_LEN 64 + /* ABORT CODES and other tell-tale location * codes are generated by adding the below * to the instance id. diff --git a/freebsd/sys/netinet/sctp_dtrace_define.h b/freebsd/sys/netinet/sctp_dtrace_define.h index 1eb28f65..0bfe18c0 100644 --- a/freebsd/sys/netinet/sctp_dtrace_define.h +++ b/freebsd/sys/netinet/sctp_dtrace_define.h @@ -45,189 +45,132 @@ SDT_PROVIDER_DEFINE(sctp); /* Cwnd probe - tracks changes in the congestion window on a netp */ /********************************************************/ /* Initial */ -SDT_PROBE_DEFINE(sctp, cwnd, net, init, init); -/* The Vtag for this end */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 0, "uint32_t"); -/* The port number of the local side << 16 | port number of remote - * in network byte order. - */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 1, "uint32_t"); -/* The pointer to the struct sctp_nets * changing */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 2, "uintptr_t"); -/* The old value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 3, "int"); -/* The new value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 4, "int"); - +SDT_PROBE_DEFINE5(sctp, cwnd, net, init, + "uint32_t", /* The Vtag for this end */ + "uint32_t", /* + * The port number of the local side << 16 | port number + * of remote in network byte order. + */ + "uintptr_t", /* The pointer to the struct sctp_nets * changing */ + "int", /* The old value of the cwnd */ + "int"); /* The new value of the cwnd */ /* ACK-INCREASE */ -SDT_PROBE_DEFINE(sctp, cwnd, net, ack, ack); -/* The Vtag for this end */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 0, "uint32_t"); -/* The port number of the local side << 16 | port number of remote - * in network byte order. - */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 1, "uint32_t"); -/* The pointer to the struct sctp_nets * changing */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 2, "uintptr_t"); -/* The old value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 3, "int"); -/* The new value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 4, "int"); - +SDT_PROBE_DEFINE5(sctp, cwnd, net, ack, + "uint32_t", /* The Vtag for this end */ + "uint32_t", /* + * The port number of the local side << 16 | port number + * of remote in network byte order. + */ + "uintptr_t", /* The pointer to the struct sctp_nets * changing */ + "int", /* The old value of the cwnd */ + "int"); /* The new value of the cwnd */ /* ACK-INCREASE */ -SDT_PROBE_DEFINE(sctp, cwnd, net, rttvar, rttvar); -/* The Vtag << 32 | localport << 16 | remoteport */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 0, "uint64_t"); -/* obw | nbw */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 1, "uint64_t"); -/* bwrtt | newrtt */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 2, "uint64_t"); -/* flight */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 3, "uint64_t"); -/* (cwnd << 32) | point << 16 | retval(0/1) */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 4, "uint64_t"); - - -SDT_PROBE_DEFINE(sctp, cwnd, net, rttstep, rttstep); -/* The Vtag << 32 | localport << 16 | remoteport */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 0, "uint64_t"); -/* obw | nbw */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 1, "uint64_t"); -/* bwrtt | nrtt */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 2, "uint64_t"); -/* cwnd_saved | stepcnt << 16 | oldstep */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 3, "uint64_t"); -/* (cwnd << 32) | point << 16 | retval(0/1) */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 4, "uint64_t"); - +SDT_PROBE_DEFINE5(sctp, cwnd, net, rttvar, + "uint64_t", /* The Vtag << 32 | localport << 16 | remoteport */ + "uint64_t", /* obw | nbw */ + "uint64_t", /* bwrtt | newrtt */ + "uint64_t", /* flight */ + "uint64_t"); /* (cwnd << 32) | point << 16 | retval(0/1) */ + +SDT_PROBE_DEFINE5(sctp, cwnd, net, rttstep, + "uint64_t", /* The Vtag << 32 | localport << 16 | remoteport */ + "uint64_t", /* obw | nbw */ + "uint64_t", /* bwrtt | newrtt */ + "uint64_t", /* flight */ + "uint64_t"); /* (cwnd << 32) | point << 16 | retval(0/1) */ /* FastRetransmit-DECREASE */ -SDT_PROBE_DEFINE(sctp, cwnd, net, fr, fr); -/* The Vtag for this end */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 0, "uint32_t"); -/* The port number of the local side << 16 | port number of remote - * in network byte order. - */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 1, "uint32_t"); -/* The pointer to the struct sctp_nets * changing */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 2, "uintptr_t"); -/* The old value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 3, "int"); -/* The new value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 4, "int"); - +SDT_PROBE_DEFINE5(sctp, cwnd, net, fr, + "uint32_t", /* The Vtag for this end */ + "uint32_t", /* + * The port number of the local side << 16 | port number + * of remote in network byte order. + */ + "uintptr_t", /* The pointer to the struct sctp_nets * changing */ + "int", /* The old value of the cwnd */ + "int"); /* The new value of the cwnd */ /* TimeOut-DECREASE */ -SDT_PROBE_DEFINE(sctp, cwnd, net, to, to); -/* The Vtag for this end */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 0, "uint32_t"); -/* The port number of the local side << 16 | port number of remote - * in network byte order. - */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 1, "uint32_t"); -/* The pointer to the struct sctp_nets * changing */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 2, "uintptr_t"); -/* The old value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 3, "int"); -/* The new value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 4, "int"); - +SDT_PROBE_DEFINE5(sctp, cwnd, net, to, + "uint32_t", /* The Vtag for this end */ + "uint32_t", /* + * The port number of the local side << 16 | port number + * of remote in network byte order. + */ + "uintptr_t", /* The pointer to the struct sctp_nets * changing */ + "int", /* The old value of the cwnd */ + "int"); /* The new value of the cwnd */ /* BurstLimit-DECREASE */ -SDT_PROBE_DEFINE(sctp, cwnd, net, bl, bl); -/* The Vtag for this end */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 0, "uint32_t"); -/* The port number of the local side << 16 | port number of remote - * in network byte order. - */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 1, "uint32_t"); -/* The pointer to the struct sctp_nets * changing */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 2, "uintptr_t"); -/* The old value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 3, "int"); -/* The new value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 4, "int"); - +SDT_PROBE_DEFINE5(sctp, cwnd, net, bl, + "uint32_t", /* The Vtag for this end */ + "uint32_t", /* + * The port number of the local side << 16 | port number + * of remote in network byte order. + */ + "uintptr_t", /* The pointer to the struct sctp_nets * changing */ + "int", /* The old value of the cwnd */ + "int"); /* The new value of the cwnd */ /* ECN-DECREASE */ -SDT_PROBE_DEFINE(sctp, cwnd, net, ecn, ecn); -/* The Vtag for this end */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 0, "uint32_t"); -/* The port number of the local side << 16 | port number of remote - * in network byte order. - */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 1, "uint32_t"); -/* The pointer to the struct sctp_nets * changing */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 2, "uintptr_t"); -/* The old value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 3, "int"); -/* The new value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 4, "int"); - +SDT_PROBE_DEFINE5(sctp, cwnd, net, ecn, + "uint32_t", /* The Vtag for this end */ + "uint32_t", /* + * The port number of the local side << 16 | port number + * of remote in network byte order. + */ + "uintptr_t", /* The pointer to the struct sctp_nets * changing */ + "int", /* The old value of the cwnd */ + "int"); /* The new value of the cwnd */ /* PacketDrop-DECREASE */ -SDT_PROBE_DEFINE(sctp, cwnd, net, pd, pd); -/* The Vtag for this end */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 0, "uint32_t"); -/* The port number of the local side << 16 | port number of remote - * in network byte order. - */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 1, "uint32_t"); -/* The pointer to the struct sctp_nets * changing */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 2, "uintptr_t"); -/* The old value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 3, "int"); -/* The new value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 4, "int"); - - +SDT_PROBE_DEFINE5(sctp, cwnd, net, pd, + "uint32_t", /* The Vtag for this end */ + "uint32_t", /* + * The port number of the local side << 16 | port number + * of remote in network byte order. + */ + "uintptr_t", /* The pointer to the struct sctp_nets * changing */ + "int", /* The old value of the cwnd */ + "int"); /* The new value of the cwnd */ /********************************************************/ /* Rwnd probe - tracks changes in the receiver window for an assoc */ /********************************************************/ -SDT_PROBE_DEFINE(sctp, rwnd, assoc, val, val); -/* The Vtag for this end */ -SDT_PROBE_ARGTYPE(sctp, rwnd, assoc, val, 0, "uint32_t"); -/* The port number of the local side << 16 | port number of remote - * in network byte order. - */ -SDT_PROBE_ARGTYPE(sctp, rwnd, assoc, val, 1, "uint32_t"); -/* The up/down amount */ -SDT_PROBE_ARGTYPE(sctp, rwnd, assoc, val, 2, "int"); -/* The new value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, rwnd, assoc, val, 3, "int"); +SDT_PROBE_DEFINE4(sctp, rwnd, assoc, val, + "uint32_t", /* The Vtag for this end */ + "uint32_t", /* + * The port number of the local side << 16 | port number + * of remote in network byte order. + */ + "int", /* The up/down amount */ + "int"); /* The new value of the cwnd */ /********************************************************/ /* flight probe - tracks changes in the flight size on a net or assoc */ /********************************************************/ -SDT_PROBE_DEFINE(sctp, flightsize, net, val, val); -/* The Vtag for this end */ -SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 0, "uint32_t"); -/* The port number of the local side << 16 | port number of remote - * in network byte order. - */ -SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 1, "uint32_t"); -/* The pointer to the struct sctp_nets * changing */ -SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 2, "uintptr_t"); -/* The up/down amount */ -SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 3, "int"); -/* The new value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 4, "int"); +SDT_PROBE_DEFINE5(sctp, flightsize, net, val, + "uint32_t", /* The Vtag for this end */ + "uint32_t", /* + * The port number of the local side << 16 | port number + * of remote in network byte order. + */ + "uintptr_t", /* The pointer to the struct sctp_nets * changing */ + "int", /* The up/down amount */ + "int"); /* The new value of the cwnd */ + /********************************************************/ /* The total flight version */ /********************************************************/ -SDT_PROBE_DEFINE(sctp, flightsize, assoc, val, val); -/* The Vtag for this end */ -SDT_PROBE_ARGTYPE(sctp, flightsize, assoc, val, 0, "uint32_t"); -/* The port number of the local side << 16 | port number of remote - * in network byte order. - */ -SDT_PROBE_ARGTYPE(sctp, flightsize, assoc, val, 1, "uint32_t"); -/* The up/down amount */ -SDT_PROBE_ARGTYPE(sctp, flightsize, assoc, val, 2, "int"); -/* The new value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, flightsize, assoc, val, 3, "int"); +SDT_PROBE_DEFINE4(sctp, flightsize, assoc, val, + "uint32_t", /* The Vtag for this end */ + "uint32_t", /* + * The port number of the local side << 16 | port number + * of remote in network byte order. + */ + "int", /* The up/down amount */ + "int"); /* The new value of the cwnd */ #endif diff --git a/freebsd/sys/netinet/sctp_indata.c b/freebsd/sys/netinet/sctp_indata.c index e00a470d..07d8fd2b 100644 --- a/freebsd/sys/netinet/sctp_indata.c +++ b/freebsd/sys/netinet/sctp_indata.c @@ -252,6 +252,11 @@ sctp_build_ctl_nchunk(struct sctp_inpcb *inp, struct sctp_sndrcvinfo *sinfo) /* We need a CMSG header followed by the struct */ cmh = mtod(ret, struct cmsghdr *); + /* + * Make sure that there is no un-initialized padding between the + * cmsg header and cmsg data and after the cmsg data. + */ + memset(cmh, 0, len); if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO)) { cmh->cmsg_level = IPPROTO_SCTP; cmh->cmsg_len = CMSG_LEN(sizeof(struct sctp_rcvinfo)); @@ -563,7 +568,8 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc, struct sctp_queued_to_read *at; int queue_needed; uint16_t nxt_todel; - struct mbuf *oper; + struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; queue_needed = 1; asoc->size_on_all_streams += control->length; @@ -580,7 +586,7 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc, (uint32_t) nxt_todel); if (SCTP_SSN_GE(strm->last_sequence_delivered, control->sinfo_ssn)) { /* The incoming sseq is behind where we last delivered? */ - SCTPDBG(SCTP_DEBUG_INDATA1, "Duplicate S-SEQ:%d delivered:%d from peer, Abort association\n", + SCTPDBG(SCTP_DEBUG_INDATA1, "Duplicate S-SEQ:%d delivered:%d from peer, Abort association\n", control->sinfo_ssn, strm->last_sequence_delivered); protocol_error: /* @@ -588,26 +594,12 @@ protocol_error: * association destruction */ TAILQ_INSERT_HEAD(&strm->inqueue, control, next); - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), - 0, M_DONTWAIT, 1, MT_DATA); - if (oper) { - struct sctp_paramhdr *ph; - uint32_t *ippp; - - SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + - (sizeof(uint32_t) * 3); - ph = mtod(oper, struct sctp_paramhdr *); - ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_1); - ippp++; - *ippp = control->sinfo_tsn; - ippp++; - *ippp = ((control->sinfo_stream << 16) | control->sinfo_ssn); - } + snprintf(msg, sizeof(msg), "Delivered SSN=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", + strm->last_sequence_delivered, control->sinfo_tsn, + control->sinfo_stream, control->sinfo_ssn); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_1; - sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; @@ -791,13 +783,12 @@ doit_again: * but should we? */ if (stcb->sctp_socket) { - pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket), + pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket) >> SCTP_PARTIAL_DELIVERY_SHIFT, stcb->sctp_ep->partial_delivery_point); } else { pd_point = stcb->sctp_ep->partial_delivery_point; } if (sctp_is_all_msg_on_reasm(asoc, &tsize) || (tsize >= pd_point)) { - /* * Yes, we setup to start reception, by * backing down the TSN just in case we @@ -842,7 +833,8 @@ static void sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, struct sctp_tmit_chunk *chk, int *abort_flag) { - struct mbuf *oper; + struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; uint32_t cum_ackp1, prev_tsn, post_tsn; struct sctp_tmit_chunk *at, *prev, *next; @@ -867,30 +859,14 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, * a FIRST fragment mark. */ SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, its not first, no fragmented delivery in progress\n"); - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), - 0, M_DONTWAIT, 1, MT_DATA); - - if (oper) { - struct sctp_paramhdr *ph; - uint32_t *ippp; - - SCTP_BUF_LEN(oper) = - sizeof(struct sctp_paramhdr) + - (sizeof(uint32_t) * 3); - ph = mtod(oper, struct sctp_paramhdr *); - ph->param_type = - htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_2); - ippp++; - *ippp = chk->rec.data.TSN_seq; - ippp++; - *ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq); - - } + snprintf(msg, sizeof(msg), + "Expected B-bit for TSN=%8.8x, SID=%4.4x, SSN=%4.4x", + chk->rec.data.TSN_seq, + chk->rec.data.stream_number, + chk->rec.data.stream_seq); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_2; - sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; } else if (asoc->fragmented_delivery_inprogress && (chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) { @@ -900,28 +876,14 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, * MIDDLE fragment NOT a FIRST */ SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, it IS a first and fragmented delivery in progress\n"); - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), - 0, M_DONTWAIT, 1, MT_DATA); - if (oper) { - struct sctp_paramhdr *ph; - uint32_t *ippp; - - SCTP_BUF_LEN(oper) = - sizeof(struct sctp_paramhdr) + - (3 * sizeof(uint32_t)); - ph = mtod(oper, struct sctp_paramhdr *); - ph->param_type = - htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_3); - ippp++; - *ippp = chk->rec.data.TSN_seq; - ippp++; - *ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq); - } + snprintf(msg, sizeof(msg), + "Didn't expect B-bit for TSN=%8.8x, SID=%4.4x, SSN=%4.4x", + chk->rec.data.TSN_seq, + chk->rec.data.stream_number, + chk->rec.data.stream_seq); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_3; - sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; } else if (asoc->fragmented_delivery_inprogress) { /* @@ -934,30 +896,15 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, it IS not same stream number %d vs %d\n", chk->rec.data.stream_number, asoc->str_of_pdapi); - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), - 0, M_DONTWAIT, 1, MT_DATA); - if (oper) { - struct sctp_paramhdr *ph; - uint32_t *ippp; - - SCTP_BUF_LEN(oper) = - sizeof(struct sctp_paramhdr) + - (sizeof(uint32_t) * 3); - ph = mtod(oper, - struct sctp_paramhdr *); - ph->param_type = - htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = - htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_4); - ippp++; - *ippp = chk->rec.data.TSN_seq; - ippp++; - *ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq); - } + snprintf(msg, sizeof(msg), + "Expected SID=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", + asoc->str_of_pdapi, + chk->rec.data.TSN_seq, + chk->rec.data.stream_number, + chk->rec.data.stream_seq); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_4; - sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; } else if ((asoc->fragment_flags & SCTP_DATA_UNORDERED) != SCTP_DATA_UNORDERED && @@ -966,31 +913,15 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, it IS not same stream seq %d vs %d\n", chk->rec.data.stream_seq, asoc->ssn_of_pdapi); - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), - 0, M_DONTWAIT, 1, MT_DATA); - if (oper) { - struct sctp_paramhdr *ph; - uint32_t *ippp; - - SCTP_BUF_LEN(oper) = - sizeof(struct sctp_paramhdr) + - (3 * sizeof(uint32_t)); - ph = mtod(oper, - struct sctp_paramhdr *); - ph->param_type = - htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = - htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_5); - ippp++; - *ippp = chk->rec.data.TSN_seq; - ippp++; - *ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq); - - } + snprintf(msg, sizeof(msg), + "Expected SSN=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", + asoc->ssn_of_pdapi, + chk->rec.data.TSN_seq, + chk->rec.data.stream_number, + chk->rec.data.stream_seq); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_5; - sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; } } @@ -1060,31 +991,14 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, SCTP_DATA_FIRST_FRAG) { SCTPDBG(SCTP_DEBUG_INDATA1, "Prev check - It can be a midlle or last but not a first\n"); SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, it's a FIRST!\n"); - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), - 0, M_DONTWAIT, 1, MT_DATA); - if (oper) { - struct sctp_paramhdr *ph; - uint32_t *ippp; - - SCTP_BUF_LEN(oper) = - sizeof(struct sctp_paramhdr) + - (3 * sizeof(uint32_t)); - ph = mtod(oper, - struct sctp_paramhdr *); - ph->param_type = - htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = - htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_6); - ippp++; - *ippp = chk->rec.data.TSN_seq; - ippp++; - *ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq); - - } + snprintf(msg, sizeof(msg), + "Can't handle B-bit, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", + chk->rec.data.TSN_seq, + chk->rec.data.stream_number, + chk->rec.data.stream_seq); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_6; - sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; } @@ -1094,33 +1008,36 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, * Huh, need the correct STR here, * they must be the same. */ - SCTP_PRINTF("Prev check - Gak, Evil plot, ssn:%d not the same as at:%d\n", + SCTPDBG(SCTP_DEBUG_INDATA1, "Prev check - Gak, Evil plot, sid:%d not the same as at:%d\n", chk->rec.data.stream_number, prev->rec.data.stream_number); - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), - 0, M_DONTWAIT, 1, MT_DATA); - if (oper) { - struct sctp_paramhdr *ph; - uint32_t *ippp; - - SCTP_BUF_LEN(oper) = - sizeof(struct sctp_paramhdr) + - (3 * sizeof(uint32_t)); - ph = mtod(oper, - struct sctp_paramhdr *); - ph->param_type = - htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = - htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_7); - ippp++; - *ippp = chk->rec.data.TSN_seq; - ippp++; - *ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq); - } + snprintf(msg, sizeof(msg), + "Expect SID=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", + prev->rec.data.stream_number, + chk->rec.data.TSN_seq, + chk->rec.data.stream_number, + chk->rec.data.stream_seq); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_7; - sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); + *abort_flag = 1; + return; + } + if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) != + (prev->rec.data.rcv_flags & SCTP_DATA_UNORDERED)) { + /* + * Huh, need the same ordering here, + * they must be the same. + */ + SCTPDBG(SCTP_DEBUG_INDATA1, "Prev check - Gak, Evil plot, U-bit not constant\n"); + snprintf(msg, sizeof(msg), + "Expect U-bit=%d for TSN=%8.8x, got U-bit=%d", + (prev->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0, + chk->rec.data.TSN_seq, + (chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_7; + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; } @@ -1134,30 +1051,15 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, SCTPDBG(SCTP_DEBUG_INDATA1, "Prev check - Gak, Evil plot, sseq:%d not the same as at:%d\n", chk->rec.data.stream_seq, prev->rec.data.stream_seq); - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), - 0, M_DONTWAIT, 1, MT_DATA); - if (oper) { - struct sctp_paramhdr *ph; - uint32_t *ippp; - - SCTP_BUF_LEN(oper) = - sizeof(struct sctp_paramhdr) + - (3 * sizeof(uint32_t)); - ph = mtod(oper, - struct sctp_paramhdr *); - ph->param_type = - htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = - htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_8); - ippp++; - *ippp = chk->rec.data.TSN_seq; - ippp++; - *ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq); - } + snprintf(msg, sizeof(msg), + "Expect SSN=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", + prev->rec.data.stream_seq, + chk->rec.data.TSN_seq, + chk->rec.data.stream_number, + chk->rec.data.stream_seq); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_8; - sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; } @@ -1167,31 +1069,14 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, if ((chk->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) != SCTP_DATA_FIRST_FRAG) { SCTPDBG(SCTP_DEBUG_INDATA1, "Prev check - Gak, evil plot, its not FIRST and it must be!\n"); - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), - 0, M_DONTWAIT, 1, MT_DATA); - if (oper) { - struct sctp_paramhdr *ph; - uint32_t *ippp; - - SCTP_BUF_LEN(oper) = - sizeof(struct sctp_paramhdr) + - (3 * sizeof(uint32_t)); - ph = mtod(oper, - struct sctp_paramhdr *); - ph->param_type = - htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = - htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_9); - ippp++; - *ippp = chk->rec.data.TSN_seq; - ippp++; - *ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq); - - } + snprintf(msg, sizeof(msg), + "Expect B-bit, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", + chk->rec.data.TSN_seq, + chk->rec.data.stream_number, + chk->rec.data.stream_seq); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_9; - sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; } @@ -1211,30 +1096,14 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, != SCTP_DATA_LAST_FRAG) { SCTPDBG(SCTP_DEBUG_INDATA1, "Next chk - Next is FIRST, we must be LAST\n"); SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, its not a last!\n"); - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), - 0, M_DONTWAIT, 1, MT_DATA); - if (oper) { - struct sctp_paramhdr *ph; - uint32_t *ippp; - - SCTP_BUF_LEN(oper) = - sizeof(struct sctp_paramhdr) + - (3 * sizeof(uint32_t)); - ph = mtod(oper, - struct sctp_paramhdr *); - ph->param_type = - htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = - htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_10); - ippp++; - *ippp = chk->rec.data.TSN_seq; - ippp++; - *ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq); - } + snprintf(msg, sizeof(msg), + "Expect only E-bit, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", + chk->rec.data.TSN_seq, + chk->rec.data.stream_number, + chk->rec.data.stream_seq); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_10; - sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; } @@ -1250,31 +1119,14 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, SCTP_DATA_LAST_FRAG) { SCTPDBG(SCTP_DEBUG_INDATA1, "Next chk - Next is a MIDDLE/LAST\n"); SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, new prev chunk is a LAST\n"); - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), - 0, M_DONTWAIT, 1, MT_DATA); - if (oper) { - struct sctp_paramhdr *ph; - uint32_t *ippp; - - SCTP_BUF_LEN(oper) = - sizeof(struct sctp_paramhdr) + - (3 * sizeof(uint32_t)); - ph = mtod(oper, - struct sctp_paramhdr *); - ph->param_type = - htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = - htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_11); - ippp++; - *ippp = chk->rec.data.TSN_seq; - ippp++; - *ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq); - - } + snprintf(msg, sizeof(msg), + "Didn't expect E-bit, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", + chk->rec.data.TSN_seq, + chk->rec.data.stream_number, + chk->rec.data.stream_seq); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_11; - sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; } @@ -1287,31 +1139,33 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, SCTPDBG(SCTP_DEBUG_INDATA1, "Next chk - Gak, Evil plot, ssn:%d not the same as at:%d\n", chk->rec.data.stream_number, next->rec.data.stream_number); - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), - 0, M_DONTWAIT, 1, MT_DATA); - if (oper) { - struct sctp_paramhdr *ph; - uint32_t *ippp; - - SCTP_BUF_LEN(oper) = - sizeof(struct sctp_paramhdr) + - (3 * sizeof(uint32_t)); - ph = mtod(oper, - struct sctp_paramhdr *); - ph->param_type = - htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = - htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_12); - ippp++; - *ippp = chk->rec.data.TSN_seq; - ippp++; - *ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq); - - } + snprintf(msg, sizeof(msg), + "Required SID %4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", + next->rec.data.stream_number, + chk->rec.data.TSN_seq, + chk->rec.data.stream_number, + chk->rec.data.stream_seq); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_12; - sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); + *abort_flag = 1; + return; + } + if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) != + (next->rec.data.rcv_flags & SCTP_DATA_UNORDERED)) { + /* + * Huh, need the same ordering here, + * they must be the same. + */ + SCTPDBG(SCTP_DEBUG_INDATA1, "Next check - Gak, Evil plot, U-bit not constant\n"); + snprintf(msg, sizeof(msg), + "Expect U-bit=%d for TSN=%8.8x, got U-bit=%d", + (next->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0, + chk->rec.data.TSN_seq, + (chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_12; + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; } @@ -1325,30 +1179,15 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, SCTPDBG(SCTP_DEBUG_INDATA1, "Next chk - Gak, Evil plot, sseq:%d not the same as at:%d\n", chk->rec.data.stream_seq, next->rec.data.stream_seq); - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), - 0, M_DONTWAIT, 1, MT_DATA); - if (oper) { - struct sctp_paramhdr *ph; - uint32_t *ippp; - - SCTP_BUF_LEN(oper) = - sizeof(struct sctp_paramhdr) + - (3 * sizeof(uint32_t)); - ph = mtod(oper, - struct sctp_paramhdr *); - ph->param_type = - htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = - htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_13); - ippp++; - *ippp = chk->rec.data.TSN_seq; - ippp++; - *ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq); - } + snprintf(msg, sizeof(msg), + "Required SSN %4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", + next->rec.data.stream_seq, + chk->rec.data.TSN_seq, + chk->rec.data.stream_number, + chk->rec.data.stream_seq); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_13; - sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; } @@ -1419,7 +1258,6 @@ sctp_does_tsn_belong_to_reasm(struct sctp_association *asoc, return (0); } - static int sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, struct mbuf **m, int offset, struct sctp_data_chunk *ch, int chk_length, @@ -1434,7 +1272,8 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, int the_len; int need_reasm_check = 0; uint16_t strmno, strmseq; - struct mbuf *oper; + struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; struct sctp_queued_to_read *control; int ordered; uint32_t protocol_id; @@ -1501,15 +1340,12 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, */ if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || - (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) - ) { + (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET))) { /* * wait a minute, this guy is gone, there is no longer a * receiver. Send peer an ABORT! */ - struct mbuf *op_err; - - op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC); + op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return (0); @@ -1637,27 +1473,12 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, /* The incoming sseq is behind where we last delivered? */ SCTPDBG(SCTP_DEBUG_INDATA1, "EVIL/Broken-Dup S-SEQ:%d delivered:%d from peer, Abort!\n", strmseq, asoc->strmin[strmno].last_sequence_delivered); - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), - 0, M_DONTWAIT, 1, MT_DATA); - if (oper) { - struct sctp_paramhdr *ph; - uint32_t *ippp; - - SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + - (3 * sizeof(uint32_t)); - ph = mtod(oper, struct sctp_paramhdr *); - ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_14); - ippp++; - *ippp = tsn; - ippp++; - *ippp = ((strmno << 16) | strmseq); - - } + snprintf(msg, sizeof(msg), "Delivered SSN=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", + asoc->strmin[strmno].last_sequence_delivered, + tsn, strmno, strmseq); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_14; - sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return (0); } @@ -1791,7 +1612,6 @@ failed_express_del: asoc->highest_tsn_inside_nr_map = tsn; } SCTP_STAT_INCR(sctps_recvexpressm); - control->sinfo_tsn = tsn; asoc->tsn_last_delivered = tsn; asoc->fragment_flags = chunk_flags; asoc->tsn_of_pdapi_last_delivered = tsn; @@ -1897,29 +1717,15 @@ failed_pdapi_express_del: control->whoFrom = NULL; } sctp_free_a_readq(stcb, control); - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), - 0, M_DONTWAIT, 1, MT_DATA); - if (oper) { - struct sctp_paramhdr *ph; - uint32_t *ippp; - - SCTP_BUF_LEN(oper) = - sizeof(struct sctp_paramhdr) + - (3 * sizeof(uint32_t)); - ph = mtod(oper, struct sctp_paramhdr *); - ph->param_type = - htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_15); - ippp++; - *ippp = tsn; - ippp++; - *ippp = ((strmno << 16) | strmseq); - } + snprintf(msg, sizeof(msg), "Reas. queue emtpy, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", + tsn, strmno, strmseq); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_15; - sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; + if (last_chunk) { + *m = NULL; + } return (0); } else { if (sctp_does_tsn_belong_to_reasm(asoc, control->sinfo_tsn)) { @@ -1930,32 +1736,15 @@ failed_pdapi_express_del: control->whoFrom = NULL; } sctp_free_a_readq(stcb, control); - - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), - 0, M_DONTWAIT, 1, MT_DATA); - if (oper) { - struct sctp_paramhdr *ph; - uint32_t *ippp; - - SCTP_BUF_LEN(oper) = - sizeof(struct sctp_paramhdr) + - (3 * sizeof(uint32_t)); - ph = mtod(oper, - struct sctp_paramhdr *); - ph->param_type = - htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = - htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_16); - ippp++; - *ippp = tsn; - ippp++; - *ippp = ((strmno << 16) | strmseq); - } + snprintf(msg, sizeof(msg), "PD ongoing, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", + tsn, strmno, strmseq); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_16; - sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; + if (last_chunk) { + *m = NULL; + } return (0); } } @@ -1976,31 +1765,15 @@ failed_pdapi_express_del: control->whoFrom = NULL; } sctp_free_a_readq(stcb, control); - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), - 0, M_DONTWAIT, 1, MT_DATA); - if (oper) { - struct sctp_paramhdr *ph; - uint32_t *ippp; - - SCTP_BUF_LEN(oper) = - sizeof(struct sctp_paramhdr) + - (3 * sizeof(uint32_t)); - ph = mtod(oper, - struct sctp_paramhdr *); - ph->param_type = - htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = - htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_17); - ippp++; - *ippp = tsn; - ippp++; - *ippp = ((strmno << 16) | strmseq); - } + snprintf(msg, sizeof(msg), "No PD ongoing, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", + tsn, strmno, strmseq); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_17; - sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; + if (last_chunk) { + *m = NULL; + } return (0); } } @@ -2064,6 +1837,9 @@ failed_pdapi_express_del: } else { sctp_queue_data_to_stream(stcb, asoc, control, abort_flag); if (*abort_flag) { + if (last_chunk) { + *m = NULL; + } return (0); } } @@ -2076,7 +1852,9 @@ failed_pdapi_express_del: * the assoc is now gone and chk was put onto the * reasm queue, which has all been freed. */ - *m = NULL; + if (last_chunk) { + *m = NULL; + } return (0); } } @@ -2494,7 +2272,7 @@ doit_again: * delivery queue and something can be delivered. */ if (stcb->sctp_socket) { - pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket), + pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket) >> SCTP_PARTIAL_DELIVERY_SHIFT, stcb->sctp_ep->partial_delivery_point); } else { pd_point = stcb->sctp_ep->partial_delivery_point; @@ -2600,32 +2378,32 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, continue; } if (ch->ch.chunk_type == SCTP_DATA) { - if ((size_t)chk_length < sizeof(struct sctp_data_chunk) + 1) { + if ((size_t)chk_length < sizeof(struct sctp_data_chunk)) { /* * Need to send an abort since we had a * invalid data chunk. */ struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; - op_err = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 2 * sizeof(uint32_t)), - 0, M_DONTWAIT, 1, MT_DATA); - - if (op_err) { - struct sctp_paramhdr *ph; - uint32_t *ippp; - - SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr) + - (2 * sizeof(uint32_t)); - ph = mtod(op_err, struct sctp_paramhdr *); - ph->param_type = - htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = htons(SCTP_BUF_LEN(op_err)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_19); - ippp++; - *ippp = asoc->cumulative_tsn; + snprintf(msg, sizeof(msg), "DATA chunk of length %d", + chk_length); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_19; + sctp_abort_association(inp, stcb, m, iphlen, + src, dst, sh, op_err, + use_mflowid, mflowid, + vrf_id, port); + return (2); + } + if ((size_t)chk_length == sizeof(struct sctp_data_chunk)) { + /* + * Need to send an abort since we had an + * empty data chunk. + */ + struct mbuf *op_err; - } + op_err = sctp_generate_no_user_data_cause(ch->dp.tsn); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_19; sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, @@ -2693,7 +2471,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, if (SCTP_BASE_SYSCTL(sctp_strict_data_order)) { struct mbuf *op_err; - op_err = sctp_generate_invmanparam(SCTP_CAUSE_PROTOCOL_VIOLATION); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, ""); sctp_abort_association(inp, stcb, m, iphlen, src, dst, @@ -3842,7 +3620,8 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, } if (SCTP_TSN_GE(cumack, send_s)) { #ifndef INVARIANTS - struct mbuf *oper; + struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; #endif #ifdef INVARIANTS @@ -3851,22 +3630,11 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, *abort_now = 1; /* XXX */ - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), - 0, M_DONTWAIT, 1, MT_DATA); - if (oper) { - struct sctp_paramhdr *ph; - uint32_t *ippp; - - SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + - sizeof(uint32_t); - ph = mtod(oper, struct sctp_paramhdr *); - ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_25); - } + snprintf(msg, sizeof(msg), "Cum ack %8.8x greater or equal then TSN %8.8x", + cumack, send_s); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_25; - sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); return; #endif } @@ -4216,23 +3984,14 @@ again: (asoc->stream_queue_cnt == 0)) { if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) { /* Need to abort here */ - struct mbuf *oper; + struct mbuf *op_err; abort_out_now: *abort_now = 1; /* XXX */ - oper = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), - 0, M_DONTWAIT, 1, MT_DATA); - if (oper) { - struct sctp_paramhdr *ph; - - SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr); - ph = mtod(oper, struct sctp_paramhdr *); - ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons(SCTP_BUF_LEN(oper)); - } + op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_24; - sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); } else { struct sctp_nets *netp; @@ -4425,7 +4184,8 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, send_s = asoc->sending_seq; } if (SCTP_TSN_GE(cum_ack, send_s)) { - struct mbuf *oper; + struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; /* * no way, we have not even sent this TSN out yet. @@ -4440,22 +4200,11 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, hopeless_peer: *abort_now = 1; /* XXX */ - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), - 0, M_DONTWAIT, 1, MT_DATA); - if (oper) { - struct sctp_paramhdr *ph; - uint32_t *ippp; - - SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + - sizeof(uint32_t); - ph = mtod(oper, struct sctp_paramhdr *); - ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_25); - } + snprintf(msg, sizeof(msg), "Cum ack %8.8x greater or equal then TSN %8.8x", + cum_ack, send_s); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_25; - sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); return; } } @@ -4721,7 +4470,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, } } TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next); - if (tp1->pr_sctp_on) { + if (PR_SCTP_ENABLED(tp1->flags)) { if (asoc->pr_sctp_cnt != 0) asoc->pr_sctp_cnt--; } @@ -4944,23 +4693,14 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, (asoc->stream_queue_cnt == 0)) { if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) { /* Need to abort here */ - struct mbuf *oper; + struct mbuf *op_err; abort_out_now: *abort_now = 1; /* XXX */ - oper = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), - 0, M_DONTWAIT, 1, MT_DATA); - if (oper) { - struct sctp_paramhdr *ph; - - SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr); - ph = mtod(oper, struct sctp_paramhdr *); - ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons(SCTP_BUF_LEN(oper)); - } + op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_31; - sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); return; } else { struct sctp_nets *netp; @@ -5389,33 +5129,20 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, asoc->cumulative_tsn = new_cum_tsn; if (gap >= m_size) { if ((long)gap > sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv)) { - struct mbuf *oper; + struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; /* * out of range (of single byte chunks in the rwnd I * give out). This must be an attacker. */ *abort_flag = 1; - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), - 0, M_DONTWAIT, 1, MT_DATA); - if (oper) { - struct sctp_paramhdr *ph; - uint32_t *ippp; - - SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + - (sizeof(uint32_t) * 3); - ph = mtod(oper, struct sctp_paramhdr *); - ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_33); - ippp++; - *ippp = asoc->highest_tsn_inside_map; - ippp++; - *ippp = new_cum_tsn; - } + snprintf(msg, sizeof(msg), + "New cum ack %8.8x too high, highest TSN %8.8x", + new_cum_tsn, asoc->highest_tsn_inside_map); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_33; - sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); return; } SCTP_STAT_INCR(sctps_fwdtsn_map_over); diff --git a/freebsd/sys/netinet/sctp_input.c b/freebsd/sys/netinet/sctp_input.c index 7cdb5b09..baf25af8 100644 --- a/freebsd/sys/netinet/sctp_input.c +++ b/freebsd/sys/netinet/sctp_input.c @@ -99,7 +99,7 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, } /* validate length */ if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_chunk)) { - op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); + op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, vrf_id, port); @@ -111,7 +111,7 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, init = &cp->init; if (init->initiate_tag == 0) { /* protocol error... send abort */ - op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); + op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, vrf_id, port); @@ -121,7 +121,7 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, } if (ntohl(init->a_rwnd) < SCTP_MIN_RWND) { /* invalid parameter... send abort */ - op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); + op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, vrf_id, port); @@ -131,7 +131,7 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, } if (init->num_inbound_streams == 0) { /* protocol error... send abort */ - op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); + op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, vrf_id, port); @@ -141,7 +141,7 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, } if (init->num_outbound_streams == 0) { /* protocol error... send abort */ - op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); + op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, vrf_id, port); @@ -152,7 +152,9 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, if (sctp_validate_init_auth_params(m, offset + sizeof(*cp), offset + ntohs(cp->ch.chunk_length))) { /* auth parameter(s) error... send abort */ - sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, NULL, + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + "Problem with AUTH parameters"); + sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, vrf_id, port); if (stcb) @@ -181,7 +183,9 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, * state :-) */ if (SCTP_BASE_SYSCTL(sctp_blackhole) == 0) { - sctp_send_abort(m, iphlen, src, dst, sh, 0, NULL, + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + "No listener"); + sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err, use_mflowid, mflowid, vrf_id, port); } @@ -441,7 +445,6 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset, /* First verify that we have no illegal param's */ abort_flag = 0; - op_err = NULL; op_err = sctp_arethere_unrecognized_parameters(m, (offset + sizeof(struct sctp_init_chunk)), @@ -464,12 +467,13 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset, if ((retval = sctp_load_addresses_from_init(stcb, m, (offset + sizeof(struct sctp_init_chunk)), initack_limit, src, dst, NULL))) { - /* Huh, we should abort */ + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + "Problem with address parameters"); SCTPDBG(SCTP_DEBUG_INPUT1, "Load addresses from INIT causes an abort %d\n", retval); sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, - src, dst, sh, NULL, + src, dst, sh, op_err, use_mflowid, mflowid, vrf_id, net->port); *abort_no_unlock = 1; @@ -524,8 +528,7 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset, */ if (retval == -3) { /* We abort with an error of missing mandatory param */ - op_err = - sctp_generate_invmanparam(SCTP_CAUSE_MISSING_PARAM); + op_err = sctp_generate_cause(SCTP_CAUSE_MISSING_PARAM, ""); if (op_err) { /* * Expand beyond to include the mandatory @@ -1308,7 +1311,7 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, } if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_ack_chunk)) { /* Invalid length */ - op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); + op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, @@ -1320,7 +1323,7 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, /* validate parameters */ if (init_ack->initiate_tag == 0) { /* protocol error... send an abort */ - op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); + op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, @@ -1330,7 +1333,7 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, } if (ntohl(init_ack->a_rwnd) < SCTP_MIN_RWND) { /* protocol error... send an abort */ - op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); + op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, @@ -1340,7 +1343,7 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, } if (init_ack->num_inbound_streams == 0) { /* protocol error... send an abort */ - op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); + op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, @@ -1350,7 +1353,7 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, } if (init_ack->num_outbound_streams == 0) { /* protocol error... send an abort */ - op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); + op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, @@ -1460,7 +1463,6 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, struct sctp_init_ack_chunk *initack_cp, initack_buf; struct sctp_nets *net; struct mbuf *op_err; - struct sctp_paramhdr *ph; int init_offset, initack_offset, i; int retval; int spec_flag = 0; @@ -1479,17 +1481,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { /* SHUTDOWN came in after sending INIT-ACK */ sctp_send_shutdown_ack(stcb, stcb->asoc.primary_destination); - op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), - 0, M_DONTWAIT, 1, MT_DATA); - if (op_err == NULL) { - /* FOOBAR */ - return (NULL); - } - /* Set the len */ - SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr); - ph = mtod(op_err, struct sctp_paramhdr *); - ph->param_type = htons(SCTP_CAUSE_COOKIE_IN_SHUTDOWN); - ph->param_length = htons(sizeof(struct sctp_paramhdr)); + op_err = sctp_generate_cause(SCTP_CAUSE_COOKIE_IN_SHUTDOWN, ""); sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err, use_mflowid, mflowid, vrf_id, net->port); @@ -1555,8 +1547,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, return (NULL); } - switch SCTP_GET_STATE - (asoc) { + switch (SCTP_GET_STATE(asoc)) { case SCTP_STATE_COOKIE_WAIT: case SCTP_STATE_COOKIE_ECHOED: /* @@ -1646,7 +1637,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, * have simply lost the COOKIE-ACK */ break; - } /* end switch */ + } /* end switch */ sctp_stop_all_cookie_timers(stcb); /* * We ignore the return code here.. not sure if we should @@ -1697,25 +1688,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, * Now we have colliding state. We must send an abort here * with colliding state indication. */ - op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), - 0, M_DONTWAIT, 1, MT_DATA); - if (op_err == NULL) { - /* FOOBAR */ - return (NULL); - } - /* pre-reserve some space */ -#ifdef INET6 - SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr)); -#else - SCTP_BUF_RESV_UF(op_err, sizeof(struct ip)); -#endif - SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr)); - SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); - /* Set the len */ - SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr); - ph = mtod(op_err, struct sctp_paramhdr *); - ph->param_type = htons(SCTP_CAUSE_NAT_COLLIDING_STATE); - ph->param_length = htons(sizeof(struct sctp_paramhdr)); + op_err = sctp_generate_cause(SCTP_CAUSE_NAT_COLLIDING_STATE, ""); sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err, use_mflowid, mflowid, vrf_id, port); @@ -2128,8 +2101,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, /* memory problem? */ SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: no room for another TCB!\n"); - op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC); - + op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, @@ -2157,7 +2129,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, * association. */ atomic_add_int(&stcb->asoc.refcnt, 1); - op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC); + op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, @@ -2776,7 +2748,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, #endif /* Too many sockets */ SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: no room for another socket!\n"); - op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC); + op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); sctp_abort_association(*inp_p, NULL, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, @@ -4398,6 +4370,8 @@ __attribute__((noinline)) uint32_t vrf_id, uint16_t port) { struct sctp_association *asoc; + struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; uint32_t vtag_in; int num_chunks = 0; /* number of control chunks processed */ uint32_t chk_length; @@ -4551,8 +4525,11 @@ __attribute__((noinline)) } } if (stcb == NULL) { + snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + msg); /* no association, so it's out of the blue... */ - sctp_handle_ootb(m, iphlen, *offset, src, dst, sh, inp, + sctp_handle_ootb(m, iphlen, *offset, src, dst, sh, inp, op_err, use_mflowid, mflowid, vrf_id, port); *offset = length; @@ -4592,8 +4569,11 @@ __attribute__((noinline)) if (locked_tcb) { SCTP_TCB_UNLOCK(locked_tcb); } + snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + msg); sctp_handle_ootb(m, iphlen, *offset, src, dst, - sh, inp, + sh, inp, op_err, use_mflowid, mflowid, vrf_id, port); return (NULL); @@ -4735,8 +4715,10 @@ process_control_chunks: /* The INIT chunk must be the only chunk. */ if ((num_chunks > 1) || (length - *offset > (int)SCTP_SIZE32(chk_length))) { + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + "INIT not the only chunk"); sctp_abort_association(inp, stcb, m, iphlen, - src, dst, sh, NULL, + src, dst, sh, op_err, use_mflowid, mflowid, vrf_id, port); *offset = length; @@ -4744,9 +4726,7 @@ process_control_chunks: } /* Honor our resource limit. */ if (chk_length > SCTP_LARGEST_INIT_ACCEPTED) { - struct mbuf *op_err; - - op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC); + op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, @@ -5114,9 +5094,7 @@ process_control_chunks: if ((stcb == NULL) && (inp->sctp_socket->so_qlen >= inp->sctp_socket->so_qlimit)) { if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && (SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit))) { - struct mbuf *op_err; - - op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC); + op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, @@ -5601,7 +5579,8 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt { uint32_t high_tsn; int fwd_tsn_seen = 0, data_processed = 0; - struct mbuf *m = *mm; + struct mbuf *m = *mm, *op_err; + char msg[SCTP_DIAG_INFO_LEN]; int un_sent; int cnt_ctrl_ready = 0; struct sctp_inpcb *inp = NULL, *inp_decr = NULL; @@ -5687,8 +5666,10 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) || ((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) && (ch->chunk_type != SCTP_INIT))) { + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + "Out of the blue"); sctp_send_abort(m, iphlen, src, dst, - sh, 0, NULL, + sh, 0, op_err, use_mflowid, mflowid, vrf_id, port); } @@ -5746,7 +5727,10 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt */ SCTP_TCB_UNLOCK(stcb); stcb = NULL; - sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, + snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + msg); + sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, use_mflowid, mflowid, vrf_id, port); goto out; @@ -5793,7 +5777,10 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt } if (stcb == NULL) { /* out of the blue DATA chunk */ - sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, + snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + msg); + sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, use_mflowid, mflowid, vrf_id, port); goto out; @@ -5862,7 +5849,10 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt /* * We consider OOTB any data sent during asoc setup. */ - sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, + snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + msg); + sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, use_mflowid, mflowid, vrf_id, port); goto out; diff --git a/freebsd/sys/netinet/sctp_os_bsd.h b/freebsd/sys/netinet/sctp_os_bsd.h index ca4be706..d33d1fd3 100644 --- a/freebsd/sys/netinet/sctp_os_bsd.h +++ b/freebsd/sys/netinet/sctp_os_bsd.h @@ -104,6 +104,9 @@ __FBSDID("$FreeBSD$"); #include +#include +#include + #ifndef in6pcb #define in6pcb inpcb #endif @@ -461,23 +464,18 @@ sctp_get_mbuf_for_msg(unsigned int space_needed, /* * SCTP AUTH */ -#define HAVE_SHA2 - #define SCTP_READ_RANDOM(buf, len) read_random(buf, len) -#ifdef USE_SCTP_SHA1 -#include -#else -#include /* map standard crypto API names */ -#define SHA1_Init SHA1Init -#define SHA1_Update SHA1Update -#define SHA1_Final(x,y) SHA1Final((caddr_t)x, y) -#endif - -#if defined(HAVE_SHA2) -#include -#endif +#define SCTP_SHA1_CTX SHA1_CTX +#define SCTP_SHA1_INIT SHA1Init +#define SCTP_SHA1_UPDATE SHA1Update +#define SCTP_SHA1_FINAL(x,y) SHA1Final((caddr_t)x, y) + +#define SCTP_SHA256_CTX SHA256_CTX +#define SCTP_SHA256_INIT SHA256_Init +#define SCTP_SHA256_UPDATE SHA256_Update +#define SCTP_SHA256_FINAL(x,y) SHA256_Final((caddr_t)x, y) #endif diff --git a/freebsd/sys/netinet/sctp_output.c b/freebsd/sys/netinet/sctp_output.c index 61260fb7..f3cb4b44 100644 --- a/freebsd/sys/netinet/sctp_output.c +++ b/freebsd/sys/netinet/sctp_output.c @@ -1939,10 +1939,13 @@ sctp_is_address_in_scope(struct sctp_ifa *ifa, static struct mbuf * sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa, uint16_t * len) { +#if defined(INET) || defined(INET6) struct sctp_paramhdr *parmh; struct mbuf *mret; uint16_t plen; +#endif + switch (ifa->address.sa.sa_family) { #ifdef INET case AF_INET: @@ -1957,6 +1960,7 @@ sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa, uint16_t * len) default: return (m); } +#if defined(INET) || defined(INET6) if (M_TRAILINGSPACE(m) >= plen) { /* easy side we just drop it on the end */ parmh = (struct sctp_paramhdr *)(SCTP_BUF_AT(m, SCTP_BUF_LEN(m))); @@ -2017,6 +2021,7 @@ sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa, uint16_t * len) *len += plen; } return (mret); +#endif } @@ -2057,6 +2062,20 @@ sctp_add_addresses_to_i_ia(struct sctp_inpcb *inp, struct sctp_tcb *stcb, continue; } LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) { +#ifdef INET + if ((sctp_ifap->address.sa.sa_family == AF_INET) && + (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sctp_ifap->address.sin.sin_addr) != 0)) { + continue; + } +#endif +#ifdef INET6 + if ((sctp_ifap->address.sa.sa_family == AF_INET6) && + (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sctp_ifap->address.sin6.sin6_addr) != 0)) { + continue; + } +#endif if (sctp_is_addr_restricted(stcb, sctp_ifap)) { continue; } @@ -2086,6 +2105,20 @@ skip_count: continue; } LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) { +#ifdef INET + if ((sctp_ifap->address.sa.sa_family == AF_INET) && + (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sctp_ifap->address.sin.sin_addr) != 0)) { + continue; + } +#endif +#ifdef INET6 + if ((sctp_ifap->address.sa.sa_family == AF_INET6) && + (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sctp_ifap->address.sin6.sin6_addr) != 0)) { + continue; + } +#endif if (sctp_is_addr_restricted(stcb, sctp_ifap)) { continue; } @@ -2450,6 +2483,20 @@ sctp_choose_boundspecific_inp(struct sctp_inpcb *inp, if (sctp_ifn) { /* is a preferred one on the interface we route out? */ LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { +#ifdef INET + if ((sctp_ifa->address.sa.sa_family == AF_INET) && + (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin.sin_addr) != 0)) { + continue; + } +#endif +#ifdef INET6 + if ((sctp_ifa->address.sa.sa_family == AF_INET6) && + (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin6.sin6_addr) != 0)) { + continue; + } +#endif if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) continue; @@ -2573,6 +2620,20 @@ sctp_choose_boundspecific_stcb(struct sctp_inpcb *inp, if (sctp_ifn) { /* first try for a preferred address on the ep */ LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { +#ifdef INET + if ((sctp_ifa->address.sa.sa_family == AF_INET) && + (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin.sin_addr) != 0)) { + continue; + } +#endif +#ifdef INET6 + if ((sctp_ifa->address.sa.sa_family == AF_INET6) && + (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin6.sin6_addr) != 0)) { + continue; + } +#endif if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) continue; if (sctp_is_addr_in_ep(inp, sctp_ifa)) { @@ -2593,6 +2654,20 @@ sctp_choose_boundspecific_stcb(struct sctp_inpcb *inp, } /* next try for an acceptable address on the ep */ LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { +#ifdef INET + if ((sctp_ifa->address.sa.sa_family == AF_INET) && + (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin.sin_addr) != 0)) { + continue; + } +#endif +#ifdef INET6 + if ((sctp_ifa->address.sa.sa_family == AF_INET6) && + (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin6.sin6_addr) != 0)) { + continue; + } +#endif if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) continue; if (sctp_is_addr_in_ep(inp, sctp_ifa)) { @@ -2697,6 +2772,7 @@ sctp_from_the_top2: static struct sctp_ifa * sctp_select_nth_preferred_addr_from_ifn_boundall(struct sctp_ifn *ifn, + struct sctp_inpcb *inp, struct sctp_tcb *stcb, int non_asoc_addr_ok, uint8_t dest_is_loop, @@ -2718,6 +2794,20 @@ sctp_select_nth_preferred_addr_from_ifn_boundall(struct sctp_ifn *ifn, } #endif /* INET6 */ LIST_FOREACH(ifa, &ifn->ifalist, next_ifa) { +#ifdef INET + if ((ifa->address.sa.sa_family == AF_INET) && + (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &ifa->address.sin.sin_addr) != 0)) { + continue; + } +#endif +#ifdef INET6 + if ((ifa->address.sa.sa_family == AF_INET6) && + (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &ifa->address.sin6.sin6_addr) != 0)) { + continue; + } +#endif if ((ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) continue; @@ -2803,6 +2893,7 @@ sctp_select_nth_preferred_addr_from_ifn_boundall(struct sctp_ifn *ifn, static int sctp_count_num_preferred_boundall(struct sctp_ifn *ifn, + struct sctp_inpcb *inp, struct sctp_tcb *stcb, int non_asoc_addr_ok, uint8_t dest_is_loop, @@ -2813,6 +2904,21 @@ sctp_count_num_preferred_boundall(struct sctp_ifn *ifn, int num_eligible_addr = 0; LIST_FOREACH(ifa, &ifn->ifalist, next_ifa) { +#ifdef INET + if ((ifa->address.sa.sa_family == AF_INET) && + (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &ifa->address.sin.sin_addr) != 0)) { + continue; + } +#endif +#ifdef INET6 + if ((ifa->address.sa.sa_family == AF_INET6) && + (stcb != NULL) && + (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &ifa->address.sin6.sin6_addr) != 0)) { + continue; + } +#endif if ((ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) { continue; @@ -2844,7 +2950,8 @@ sctp_count_num_preferred_boundall(struct sctp_ifn *ifn, } static struct sctp_ifa * -sctp_choose_boundall(struct sctp_tcb *stcb, +sctp_choose_boundall(struct sctp_inpcb *inp, + struct sctp_tcb *stcb, struct sctp_nets *net, sctp_route_t * ro, uint32_t vrf_id, @@ -2899,7 +3006,7 @@ sctp_choose_boundall(struct sctp_tcb *stcb, cur_addr_num = net->indx_of_eligible_next_to_use; } num_preferred = sctp_count_num_preferred_boundall(sctp_ifn, - stcb, + inp, stcb, non_asoc_addr_ok, dest_is_loop, dest_is_priv, fam); @@ -2926,7 +3033,7 @@ sctp_choose_boundall(struct sctp_tcb *stcb, */ SCTPDBG(SCTP_DEBUG_OUTPUT2, "cur_addr_num:%d\n", cur_addr_num); - sctp_ifa = sctp_select_nth_preferred_addr_from_ifn_boundall(sctp_ifn, stcb, non_asoc_addr_ok, dest_is_loop, + sctp_ifa = sctp_select_nth_preferred_addr_from_ifn_boundall(sctp_ifn, inp, stcb, non_asoc_addr_ok, dest_is_loop, dest_is_priv, cur_addr_num, fam, ro); /* if sctp_ifa is NULL something changed??, fall to plan b. */ @@ -2957,7 +3064,7 @@ bound_all_plan_b: SCTPDBG(SCTP_DEBUG_OUTPUT2, "already seen\n"); continue; } - num_preferred = sctp_count_num_preferred_boundall(sctp_ifn, stcb, non_asoc_addr_ok, + num_preferred = sctp_count_num_preferred_boundall(sctp_ifn, inp, stcb, non_asoc_addr_ok, dest_is_loop, dest_is_priv, fam); SCTPDBG(SCTP_DEBUG_OUTPUT2, "Found ifn:%p %d preferred source addresses\n", @@ -2979,7 +3086,7 @@ bound_all_plan_b: if (cur_addr_num >= num_preferred) { cur_addr_num = 0; } - sifa = sctp_select_nth_preferred_addr_from_ifn_boundall(sctp_ifn, stcb, non_asoc_addr_ok, dest_is_loop, + sifa = sctp_select_nth_preferred_addr_from_ifn_boundall(sctp_ifn, inp, stcb, non_asoc_addr_ok, dest_is_loop, dest_is_priv, cur_addr_num, fam, ro); if (sifa == NULL) continue; @@ -3007,6 +3114,22 @@ again_with_private_addresses_allowed: } LIST_FOREACH(sctp_ifa, &emit_ifn->ifalist, next_ifa) { SCTPDBG(SCTP_DEBUG_OUTPUT2, "ifa:%p\n", (void *)sctp_ifa); +#ifdef INET + if ((sctp_ifa->address.sa.sa_family == AF_INET) && + (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin.sin_addr) != 0)) { + SCTPDBG(SCTP_DEBUG_OUTPUT2, "Jailed\n"); + continue; + } +#endif +#ifdef INET6 + if ((sctp_ifa->address.sa.sa_family == AF_INET6) && + (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin6.sin6_addr) != 0)) { + SCTPDBG(SCTP_DEBUG_OUTPUT2, "Jailed\n"); + continue; + } +#endif if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) { SCTPDBG(SCTP_DEBUG_OUTPUT2, "Defer\n"); @@ -3057,6 +3180,20 @@ plan_d: continue; } LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { +#ifdef INET + if ((sctp_ifa->address.sa.sa_family == AF_INET) && + (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin.sin_addr) != 0)) { + continue; + } +#endif +#ifdef INET6 + if ((sctp_ifa->address.sa.sa_family == AF_INET6) && + (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin6.sin6_addr) != 0)) { + continue; + } +#endif if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) continue; @@ -3107,6 +3244,20 @@ out: LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { struct sctp_ifa *tmp_sifa; +#ifdef INET + if ((sctp_ifa->address.sa.sa_family == AF_INET) && + (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin.sin_addr) != 0)) { + continue; + } +#endif +#ifdef INET6 + if ((sctp_ifa->address.sa.sa_family == AF_INET6) && + (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sctp_ifa->address.sin6.sin6_addr) != 0)) { + continue; + } +#endif if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) continue; @@ -3292,7 +3443,7 @@ sctp_source_address_selection(struct sctp_inpcb *inp, /* * Bound all case */ - answer = sctp_choose_boundall(stcb, net, ro, vrf_id, + answer = sctp_choose_boundall(inp, stcb, net, ro, vrf_id, dest_is_priv, dest_is_loop, non_asoc_addr_ok, fam); SCTP_IPI_ADDR_RUNLOCK(); @@ -3386,7 +3537,11 @@ sctp_find_cmsg(int c_type, void *data, struct mbuf *control, size_t cpsize) return (found); } m_copydata(control, at + CMSG_ALIGN(sizeof(cmh)), sizeof(struct sctp_prinfo), (caddr_t)&prinfo); - sndrcvinfo->sinfo_timetolive = prinfo.pr_value; + if (prinfo.pr_policy != SCTP_PR_SCTP_NONE) { + sndrcvinfo->sinfo_timetolive = prinfo.pr_value; + } else { + sndrcvinfo->sinfo_timetolive = 0; + } sndrcvinfo->sinfo_flags |= prinfo.pr_policy; break; case SCTP_AUTHINFO: @@ -3563,7 +3718,7 @@ sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *er static struct sctp_tcb * sctp_findassociation_cmsgs(struct sctp_inpcb **inp_p, - in_port_t port, + uint16_t port, struct mbuf *control, struct sctp_nets **net_p, int *error) @@ -3664,7 +3819,6 @@ sctp_add_cookie(struct mbuf *init, int init_offset, int sig_offset; uint16_t cookie_sz; - mret = NULL; mret = sctp_get_mbuf_for_msg((sizeof(struct sctp_state_cookie) + sizeof(struct sctp_paramhdr)), 0, M_DONTWAIT, 1, MT_DATA); @@ -3857,8 +4011,11 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, struct sctphdr *sctphdr; int packet_length; int ret; + +#if defined(INET) || defined(INET6) uint32_t vrf_id; +#endif #if defined(INET) || defined(INET6) struct mbuf *o_pak; sctp_route_t *ro = NULL; @@ -3877,12 +4034,13 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, sctp_m_freem(m); return (EFAULT); } +#if defined(INET) || defined(INET6) if (stcb) { vrf_id = stcb->asoc.vrf_id; } else { vrf_id = inp->def_vrf_id; } - +#endif /* fill in the HMAC digest for any AUTH chunk in the packet */ if ((auth != NULL) && (stcb != NULL)) { sctp_fill_hmac_digest_m(m, auth_offset, auth, stcb, auth_keyid); @@ -4098,7 +4256,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, SCTP_STAT_INCR(sctps_sendnocrc); #else m->m_pkthdr.csum_flags = CSUM_SCTP; - m->m_pkthdr.csum_data = 0; + m->m_pkthdr.csum_data = offsetof(struct sctphdr, checksum); SCTP_STAT_INCR(sctps_sendhwcrc); #endif } @@ -4447,7 +4605,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, SCTP_STAT_INCR(sctps_sendnocrc); #else m->m_pkthdr.csum_flags = CSUM_SCTP_IPV6; - m->m_pkthdr.csum_data = 0; + m->m_pkthdr.csum_data = offsetof(struct sctphdr, checksum); SCTP_STAT_INCR(sctps_sendhwcrc); #endif } @@ -4545,11 +4703,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked struct mbuf *m; struct sctp_nets *net; struct sctp_init_chunk *init; - -#if defined(INET) || defined(INET6) struct sctp_supported_addr_param *sup_addr; - -#endif struct sctp_adaptation_layer_indication *ali; struct sctp_supported_chunk_types_param *pr_supported; struct sctp_paramhdr *ph; @@ -5386,7 +5540,9 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, * though we even set the T bit and copy in the 0 tag.. this * looks no different than if no listener was present. */ - sctp_send_abort(init_pkt, iphlen, src, dst, sh, 0, NULL, + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + "Address added"); + sctp_send_abort(init_pkt, iphlen, src, dst, sh, 0, op_err, use_mflowid, mflowid, vrf_id, port); return; @@ -5397,6 +5553,13 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, &abort_flag, (struct sctp_chunkhdr *)init_chk, &nat_friendly); if (abort_flag) { do_a_abort: + if (op_err == NULL) { + char msg[SCTP_DIAG_INFO_LEN]; + + snprintf(msg, sizeof(msg), "%s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + msg); + } sctp_send_abort(init_pkt, iphlen, src, dst, sh, init_chk->init.initiate_tag, op_err, use_mflowid, mflowid, @@ -6073,17 +6236,15 @@ sctp_get_frag_point(struct sctp_tcb *stcb, static void sctp_set_prsctp_policy(struct sctp_stream_queue_pending *sp) { - sp->pr_sctp_on = 0; /* * We assume that the user wants PR_SCTP_TTL if the user provides a - * positive lifetime but does not specify any PR_SCTP policy. This - * is a BAD assumption and causes problems at least with the - * U-Vancovers MPI folks. I will change this to be no policy means - * NO PR-SCTP. + * positive lifetime but does not specify any PR_SCTP policy. */ if (PR_SCTP_ENABLED(sp->sinfo_flags)) { sp->act_flags |= PR_SCTP_POLICY(sp->sinfo_flags); - sp->pr_sctp_on = 1; + } else if (sp->timetolive > 0) { + sp->sinfo_flags |= SCTP_PR_SCTP_TTL; + sp->act_flags |= PR_SCTP_POLICY(sp->sinfo_flags); } else { return; } @@ -6420,7 +6581,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr, /* TSNH */ return; } - if ((ca->m) && ca->sndlen) { + if (ca->sndlen > 0) { m = SCTP_M_COPYM(ca->m, 0, M_COPYALL, M_DONTWAIT); if (m == NULL) { /* can't copy so we are done */ @@ -6449,38 +6610,40 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr, } if (ca->sndrcv.sinfo_flags & SCTP_ABORT) { /* Abort this assoc with m as the user defined reason */ - if (m) { + if (m != NULL) { + SCTP_BUF_PREPEND(m, sizeof(struct sctp_paramhdr), M_NOWAIT); + } else { + m = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), + 0, M_NOWAIT, 1, MT_DATA); + SCTP_BUF_LEN(m) = sizeof(struct sctp_paramhdr); + } + if (m != NULL) { struct sctp_paramhdr *ph; - SCTP_BUF_PREPEND(m, sizeof(struct sctp_paramhdr), M_DONTWAIT); - if (m) { - ph = mtod(m, struct sctp_paramhdr *); - ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons(sizeof(struct sctp_paramhdr) + ca->sndlen); - } - /* - * We add one here to keep the assoc from - * dis-appearing on us. - */ - atomic_add_int(&stcb->asoc.refcnt, 1); - sctp_abort_an_association(inp, stcb, m, SCTP_SO_NOT_LOCKED); - /* - * sctp_abort_an_association calls sctp_free_asoc() - * free association will NOT free it since we - * incremented the refcnt .. we do this to prevent - * it being freed and things getting tricky since we - * could end up (from free_asoc) calling inpcb_free - * which would get a recursive lock call to the - * iterator lock.. But as a consequence of that the - * stcb will return to us un-locked.. since - * free_asoc returns with either no TCB or the TCB - * unlocked, we must relock.. to unlock in the - * iterator timer :-0 - */ - SCTP_TCB_LOCK(stcb); - atomic_add_int(&stcb->asoc.refcnt, -1); - goto no_chunk_output; + ph = mtod(m, struct sctp_paramhdr *); + ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); + ph->param_length = htons(sizeof(struct sctp_paramhdr) + ca->sndlen); } + /* + * We add one here to keep the assoc from dis-appearing on + * us. + */ + atomic_add_int(&stcb->asoc.refcnt, 1); + sctp_abort_an_association(inp, stcb, m, SCTP_SO_NOT_LOCKED); + /* + * sctp_abort_an_association calls sctp_free_asoc() free + * association will NOT free it since we incremented the + * refcnt .. we do this to prevent it being freed and things + * getting tricky since we could end up (from free_asoc) + * calling inpcb_free which would get a recursive lock call + * to the iterator lock.. But as a consequence of that the + * stcb will return to us un-locked.. since free_asoc + * returns with either no TCB or the TCB unlocked, we must + * relock.. to unlock in the iterator timer :-0 + */ + SCTP_TCB_LOCK(stcb); + atomic_add_int(&stcb->asoc.refcnt, -1); + goto no_chunk_output; } else { if (m) { ret = sctp_msg_append(stcb, net, m, @@ -6574,8 +6737,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr, if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_NODELAY)) && (stcb->asoc.total_flight > 0) && - (un_sent < (int)(stcb->asoc.smallest_mtu - SCTP_MIN_OVERHEAD)) - ) { + (un_sent < (int)(stcb->asoc.smallest_mtu - SCTP_MIN_OVERHEAD))) { do_chunk_output = 0; } if (do_chunk_output) @@ -6704,13 +6866,10 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m, /* Gather the length of the send */ struct mbuf *mat; - mat = m; ca->sndlen = 0; - while (m) { - ca->sndlen += SCTP_BUF_LEN(m); - m = SCTP_BUF_NEXT(m); + for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) { + ca->sndlen += SCTP_BUF_LEN(mat); } - ca->m = mat; } ret = sctp_initiate_iterator(NULL, sctp_sendall_iterator, NULL, SCTP_PCB_ANY_FLAGS, SCTP_PCB_ANY_FEATURES, @@ -7356,7 +7515,8 @@ dont_do_it: chk->pad_inplace = 0; chk->no_fr_allowed = 0; chk->rec.data.stream_seq = strq->next_sequence_send; - if (rcv_flags & SCTP_DATA_LAST_FRAG) { + if ((rcv_flags & SCTP_DATA_LAST_FRAG) && + !(rcv_flags & SCTP_DATA_UNORDERED)) { strq->next_sequence_send++; } chk->rec.data.stream_number = sp->stream; @@ -7431,13 +7591,8 @@ dont_do_it: } chk->send_size += pads; } - /* We only re-set the policy if it is on */ - if (sp->pr_sctp_on) { - sctp_set_prsctp_policy(sp); + if (PR_SCTP_ENABLED(chk->flags)) { asoc->pr_sctp_cnt++; - chk->pr_sctp_on = 1; - } else { - chk->pr_sctp_on = 0; } if (sp->msg_is_complete && (sp->length == 0) && (sp->sender_all_done)) { /* All done pull and kill the message */ @@ -7627,7 +7782,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp, #endif ) { - /* + /** * Ok this is the generic chunk service queue. we must do the * following: - Service the stream queue that is next, moving any * message (note I must get a complete message i.e. FIRST/MIDDLE and @@ -8962,7 +9117,6 @@ sctp_send_cookie_ack(struct sctp_tcb *stcb) struct sctp_chunkhdr *hdr; struct sctp_tmit_chunk *chk; - cookie_ack = NULL; SCTP_TCB_LOCK_ASSERT(stcb); cookie_ack = sctp_get_mbuf_for_msg(sizeof(struct sctp_chunkhdr), 0, M_DONTWAIT, 1, MT_HEADER); @@ -10813,8 +10967,12 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst, struct sctphdr *shout; struct sctp_chunkhdr *ch; struct udphdr *udp; - int len, cause_len, padding_len, ret; + int len, cause_len, padding_len; +#if defined(INET) || defined(INET6) + int ret; + +#endif #ifdef INET struct sockaddr_in *src_sin, *dst_sin; struct ip *ip; @@ -11007,7 +11165,7 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst, SCTP_STAT_INCR(sctps_sendnocrc); #else mout->m_pkthdr.csum_flags = CSUM_SCTP; - mout->m_pkthdr.csum_data = 0; + mout->m_pkthdr.csum_data = offsetof(struct sctphdr, checksum); SCTP_STAT_INCR(sctps_sendhwcrc); #endif } @@ -11037,7 +11195,7 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst, SCTP_STAT_INCR(sctps_sendnocrc); #else mout->m_pkthdr.csum_flags = CSUM_SCTP_IPV6; - mout->m_pkthdr.csum_data = 0; + mout->m_pkthdr.csum_data = offsetof(struct sctphdr, checksum); SCTP_STAT_INCR(sctps_sendhwcrc); #endif } diff --git a/freebsd/sys/netinet/sctp_pcb.c b/freebsd/sys/netinet/sctp_pcb.c index e21c2e03..16dc231f 100644 --- a/freebsd/sys/netinet/sctp_pcb.c +++ b/freebsd/sys/netinet/sctp_pcb.c @@ -774,7 +774,14 @@ sctp_del_addr_from_vrf(uint32_t vrf_id, struct sockaddr *addr, } SCTPDBG(SCTP_DEBUG_PCB4, "Deleting ifa %p\n", (void *)sctp_ifap); sctp_ifap->localifa_flags &= SCTP_ADDR_VALID; - sctp_ifap->localifa_flags |= SCTP_BEING_DELETED; + /* + * We don't set the flag. This means that the structure will + * hang around in EP's that have bound specific to it until + * they close. This gives us TCP like behavior if someone + * removes an address (or for that matter adds it right + * back). + */ + /* sctp_ifap->localifa_flags |= SCTP_BEING_DELETED; */ vrf->total_ifa_count--; LIST_REMOVE(sctp_ifap, next_bucket); sctp_remove_ifa_from_ifn(sctp_ifap); @@ -829,18 +836,30 @@ out_now: static int sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to) { - int loopback_scope, ipv4_local_scope, local_scope, site_scope; - int ipv4_addr_legal, ipv6_addr_legal; + int loopback_scope; + +#if defined(INET) + int ipv4_local_scope, ipv4_addr_legal; + +#endif +#if defined(INET6) + int local_scope, site_scope, ipv6_addr_legal; + +#endif struct sctp_vrf *vrf; struct sctp_ifn *sctp_ifn; struct sctp_ifa *sctp_ifa; loopback_scope = stcb->asoc.scope.loopback_scope; +#if defined(INET) ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope; + ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal; +#endif +#if defined(INET6) local_scope = stcb->asoc.scope.local_scope; site_scope = stcb->asoc.scope.site_scope; - ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal; ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal; +#endif SCTP_IPI_ADDR_RLOCK(); vrf = sctp_find_vrf(stcb->asoc.vrf_id); @@ -865,6 +884,9 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to) */ continue; } + if (sctp_ifa->address.sa.sa_family != to->sa_family) { + continue; + } switch (sctp_ifa->address.sa.sa_family) { #ifdef INET case AF_INET: @@ -878,6 +900,10 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to) IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { continue; } + if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred, + &sin->sin_addr) != 0) { + continue; + } if (sin->sin_addr.s_addr == rsin->sin_addr.s_addr) { SCTP_IPI_ADDR_RUNLOCK(); return (1); @@ -893,6 +919,10 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to) sin6 = &sctp_ifa->address.sin6; rsin6 = (struct sockaddr_in6 *)to; + if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred, + &sin6->sin6_addr) != 0) { + continue; + } if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { if (local_scope == 0) continue; @@ -1040,6 +1070,39 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from, SCTP_INP_RUNLOCK(inp); continue; } + switch (to->sa_family) { +#ifdef INET + case AF_INET: + { + struct sockaddr_in *sin; + + sin = (struct sockaddr_in *)to; + if (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sin->sin_addr) != 0) { + SCTP_INP_RUNLOCK(inp); + continue; + } + break; + } +#endif +#ifdef INET6 + case AF_INET6: + { + struct sockaddr_in6 *sin6; + + sin6 = (struct sockaddr_in6 *)to; + if (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sin6->sin6_addr) != 0) { + SCTP_INP_RUNLOCK(inp); + continue; + } + break; + } +#endif + default: + SCTP_INP_RUNLOCK(inp); + continue; + } if (inp->def_vrf_id != vrf_id) { SCTP_INP_RUNLOCK(inp); continue; @@ -1608,23 +1671,45 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head, if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) && (inp->sctp_lport == lport)) { /* got it */ + switch (nam->sa_family) { #ifdef INET - if ((nam->sa_family == AF_INET) && - (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && - SCTP_IPV6_V6ONLY(inp)) { - /* IPv4 on a IPv6 socket with ONLY IPv6 set */ - SCTP_INP_RUNLOCK(inp); - continue; - } + case AF_INET: + if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && + SCTP_IPV6_V6ONLY(inp)) { + /* + * IPv4 on a IPv6 socket with ONLY + * IPv6 set + */ + SCTP_INP_RUNLOCK(inp); + continue; + } + if (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sin->sin_addr) != 0) { + SCTP_INP_RUNLOCK(inp); + continue; + } + break; #endif #ifdef INET6 - /* A V6 address and the endpoint is NOT bound V6 */ - if (nam->sa_family == AF_INET6 && - (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { - SCTP_INP_RUNLOCK(inp); - continue; - } + case AF_INET6: + /* + * A V6 address and the endpoint is NOT + * bound V6 + */ + if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { + SCTP_INP_RUNLOCK(inp); + continue; + } + if (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sin6->sin6_addr) != 0) { + SCTP_INP_RUNLOCK(inp); + continue; + } + break; #endif + default: + break; + } /* does a VRF id match? */ fnd = 0; if (inp->def_vrf_id == vrf_id) @@ -1973,8 +2058,13 @@ sctp_findassociation_special_addr(struct mbuf *m, int offset, struct sockaddr *dst) { struct sctp_paramhdr *phdr, parm_buf; + +#if defined(INET) || defined(INET6) struct sctp_tcb *stcb; - uint32_t ptype, plen; + uint16_t ptype; + +#endif + uint16_t plen; #ifdef INET struct sockaddr_in sin4; @@ -1998,13 +2088,14 @@ sctp_findassociation_special_addr(struct mbuf *m, int offset, sin6.sin6_port = sh->src_port; #endif - stcb = NULL; offset += sizeof(struct sctp_init_chunk); phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf)); while (phdr != NULL) { /* now we must see if we want the parameter */ +#if defined(INET) || defined(INET6) ptype = ntohs(phdr->param_type); +#endif plen = ntohs(phdr->param_length); if (plen == 0) { break; @@ -2377,6 +2468,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) /* setup socket pointers */ inp->sctp_socket = so; inp->ip_inp.inp.inp_socket = so; + inp->ip_inp.inp.inp_cred = crhold(so->so_cred); #ifdef INET6 if (INP_SOCKAF(so) == AF_INET6) { if (MODULE_GLOBAL(ip6_auto_flowlabel)) { @@ -2395,6 +2487,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) /* init the small hash table we use to track asocid <-> tcb */ inp->sctp_asocidhash = SCTP_HASH_INIT(SCTP_STACK_VTAG_HASH_SIZE, &inp->hashasocidmark); if (inp->sctp_asocidhash == NULL) { + crfree(inp->ip_inp.inp.inp_cred); SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); SCTP_INP_INFO_WUNLOCK(); return (ENOBUFS); @@ -2409,6 +2502,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) ((struct in6pcb *)(&inp->ip_inp.inp))->in6p_sp = pcb_sp; } if (error != 0) { + crfree(inp->ip_inp.inp.inp_cred); SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); SCTP_INP_INFO_WUNLOCK(); return error; @@ -2439,6 +2533,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) */ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EOPNOTSUPP); so->so_pcb = NULL; + crfree(inp->ip_inp.inp.inp_cred); SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); return (EOPNOTSUPP); } @@ -2458,6 +2553,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) SCTP_PRINTF("Out of SCTP-INPCB->hashinit - no resources\n"); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS); so->so_pcb = NULL; + crfree(inp->ip_inp.inp.inp_cred); SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); return (ENOBUFS); } @@ -2709,7 +2805,6 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, uint32_t vrf_id; lport = 0; - error = 0; bindall = 1; inp = (struct sctp_inpcb *)so->so_pcb; ip_inp = (struct inpcb *)so->so_pcb; @@ -2830,13 +2925,6 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, return (error); } } - if (p == NULL) { - SCTP_INP_DECR_REF(inp); - SCTP_INP_WUNLOCK(inp); - SCTP_INP_INFO_WUNLOCK(); - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error); - return (error); - } SCTP_INP_WUNLOCK(inp); if (bindall) { vrf_id = inp->def_vrf_id; @@ -3314,17 +3402,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) /* Left with Data unread */ struct mbuf *op_err; - op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), - 0, M_DONTWAIT, 1, MT_DATA); - if (op_err) { - /* Fill in the user initiated abort */ - struct sctp_paramhdr *ph; - - SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr); - ph = mtod(op_err, struct sctp_paramhdr *); - ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons(SCTP_BUF_LEN(op_err)); - } + op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_3; sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED); SCTP_STAT_INCR_COUNTER32(sctps_aborted); @@ -3395,20 +3473,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) struct mbuf *op_err; abort_anyway: - op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), - 0, M_DONTWAIT, 1, MT_DATA); - if (op_err) { - /* - * Fill in the user - * initiated abort - */ - struct sctp_paramhdr *ph; - - SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr); - ph = mtod(op_err, struct sctp_paramhdr *); - ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons(SCTP_BUF_LEN(op_err)); - } + op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_5; sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED); SCTP_STAT_INCR_COUNTER32(sctps_aborted); @@ -3472,17 +3537,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) ((asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0)) { struct mbuf *op_err; - op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), - 0, M_DONTWAIT, 1, MT_DATA); - if (op_err) { - /* Fill in the user initiated abort */ - struct sctp_paramhdr *ph; - - SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr); - ph = mtod(op_err, struct sctp_paramhdr *); - ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons(SCTP_BUF_LEN(op_err)); - } + op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_7; sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED); SCTP_STAT_INCR_COUNTER32(sctps_aborted); @@ -3647,6 +3702,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) inp->sctp_tcbhash = NULL; } /* Now we must put the ep memory back into the zone pool */ + crfree(inp->ip_inp.inp.inp_cred); INP_LOCK_DESTROY(&inp->ip_inp.inp); SCTP_INP_LOCK_DESTROY(inp); SCTP_INP_READ_DESTROY(inp); @@ -3744,7 +3800,7 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, sin->sin_len = sizeof(struct sockaddr_in); if (set_scope) { #ifdef SCTP_DONT_DO_PRIVADDR_SCOPE - stcb->ipv4_local_scope = 1; + stcb->asoc.scope.ipv4_local_scope = 1; #else if (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { stcb->asoc.scope.ipv4_local_scope = 1; @@ -4318,6 +4374,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr, asoc->nr_mapping_array = NULL; } SCTP_DECR_ASOC_COUNT(); + SCTP_TCB_UNLOCK(stcb); SCTP_TCB_LOCK_DESTROY(stcb); SCTP_TCB_SEND_LOCK_DESTROY(stcb); LIST_REMOVE(stcb, sctp_tcbasocidhash); @@ -5120,6 +5177,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre /* Insert new items here :> */ /* Get rid of LOCK */ + SCTP_TCB_UNLOCK(stcb); SCTP_TCB_LOCK_DESTROY(stcb); SCTP_TCB_SEND_LOCK_DESTROY(stcb); if (from_inpcbfree == SCTP_NORMAL_PROC) { @@ -5845,7 +5903,6 @@ sctp_pcb_init() for (i = 0; i < SCTP_STACK_VTAG_HASH_SIZE; i++) { LIST_INIT(&SCTP_BASE_INFO(vtag_timewait)[i]); } - sctp_startup_iterator(); #if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP) @@ -5874,35 +5931,31 @@ sctp_pcb_finish(void) struct sctp_tagblock *twait_block, *prev_twait_block; struct sctp_laddr *wi, *nwi; int i; + struct sctp_iterator *it, *nit; /* - * Free BSD the it thread never exits but we do clean up. The only - * way freebsd reaches here if we have VRF's but we still add the - * ifdef to make it compile on old versions. + * In FreeBSD the iterator thread never exits but we do clean up. + * The only way FreeBSD reaches here is if we have VRF's but we + * still add the ifdef to make it compile on old versions. */ - { - struct sctp_iterator *it, *nit; - - SCTP_IPI_ITERATOR_WQ_LOCK(); - TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) { - if (it->vn != curvnet) { - continue; - } - TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr); - if (it->function_atend != NULL) { - (*it->function_atend) (it->pointer, it->val); - } - SCTP_FREE(it, SCTP_M_ITER); + SCTP_IPI_ITERATOR_WQ_LOCK(); + TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) { + if (it->vn != curvnet) { + continue; } - SCTP_IPI_ITERATOR_WQ_UNLOCK(); - SCTP_ITERATOR_LOCK(); - if ((sctp_it_ctl.cur_it) && - (sctp_it_ctl.cur_it->vn == curvnet)) { - sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_STOP_CUR_IT; + TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr); + if (it->function_atend != NULL) { + (*it->function_atend) (it->pointer, it->val); } - SCTP_ITERATOR_UNLOCK(); + SCTP_FREE(it, SCTP_M_ITER); } - + SCTP_IPI_ITERATOR_WQ_UNLOCK(); + SCTP_ITERATOR_LOCK(); + if ((sctp_it_ctl.cur_it) && + (sctp_it_ctl.cur_it->vn == curvnet)) { + sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_STOP_CUR_IT; + } + SCTP_ITERATOR_UNLOCK(); SCTP_OS_TIMER_STOP(&SCTP_BASE_INFO(addr_wq_timer.timer)); SCTP_WQ_ADDR_LOCK(); LIST_FOREACH_SAFE(wi, &SCTP_BASE_INFO(addr_wq), sctp_nxt_addr, nwi) { diff --git a/freebsd/sys/netinet/sctp_pcb.h b/freebsd/sys/netinet/sctp_pcb.h index 91807c7c..8045765c 100644 --- a/freebsd/sys/netinet/sctp_pcb.h +++ b/freebsd/sys/netinet/sctp_pcb.h @@ -388,8 +388,8 @@ struct sctp_inpcb { /* back pointer to our socket */ struct socket *sctp_socket; + uint64_t sctp_features; /* Feature flags */ uint32_t sctp_flags; /* INP state flag set */ - uint32_t sctp_features; /* Feature flags */ uint32_t sctp_mobility_features; /* Mobility Feature flags */ struct sctp_pcb sctp_ep;/* SCTP ep data */ /* head of the hash of all associations */ diff --git a/freebsd/sys/netinet/sctp_structs.h b/freebsd/sys/netinet/sctp_structs.h index bc18f0e8..a8b86c62 100644 --- a/freebsd/sys/netinet/sctp_structs.h +++ b/freebsd/sys/netinet/sctp_structs.h @@ -446,7 +446,6 @@ struct sctp_tmit_chunk { uint8_t do_rtt; uint8_t book_size_scale; uint8_t no_fr_allowed; - uint8_t pr_sctp_on; uint8_t copy_by_ref; uint8_t window_probe; }; @@ -522,7 +521,6 @@ struct sctp_stream_queue_pending { uint8_t holds_key_ref; uint8_t msg_is_complete; uint8_t some_taken; - uint8_t pr_sctp_on; uint8_t sender_all_done; uint8_t put_last_out; uint8_t discard_rest; @@ -1205,7 +1203,7 @@ struct sctp_association { /* JRS 5/21/07 - CMT PF variable */ uint8_t sctp_cmt_pf; uint8_t use_precise_time; - uint32_t sctp_features; + uint64_t sctp_features; uint16_t port; /* remote UDP encapsulation port */ /* * The mapping array is used to track out of order sequences above diff --git a/freebsd/sys/netinet/sctp_sysctl.c b/freebsd/sys/netinet/sctp_sysctl.c index 95e3c589..ba7a00bf 100644 --- a/freebsd/sys/netinet/sctp_sysctl.c +++ b/freebsd/sys/netinet/sctp_sysctl.c @@ -118,7 +118,7 @@ sctp_init_sysctls() SCTP_BASE_SYSCTL(sctp_steady_step) = SCTPCTL_RTTVAR_STEADYS_DEFAULT; SCTP_BASE_SYSCTL(sctp_use_dccc_ecn) = SCTPCTL_RTTVAR_DCCCECN_DEFAULT; SCTP_BASE_SYSCTL(sctp_blackhole) = SCTPCTL_BLACKHOLE_DEFAULT; - + SCTP_BASE_SYSCTL(sctp_diag_info_code) = SCTPCTL_DIAG_INFO_CODE_DEFAULT; #if defined(SCTP_LOCAL_TRACE_BUF) memset(&SCTP_BASE_SYSCTL(sctp_log), 0, sizeof(struct sctp_log)); #endif @@ -254,6 +254,10 @@ copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct s sin = (struct sockaddr_in *)&sctp_ifa->address.sa; if (sin->sin_addr.s_addr == 0) continue; + if (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sin->sin_addr) != 0) { + continue; + } if ((ipv4_local_scope == 0) && (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) continue; } else { @@ -269,6 +273,10 @@ copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct s sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa; if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) continue; + if (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sin6->sin6_addr) != 0) { + continue; + } if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { if (local_scope == 0) continue; @@ -404,7 +412,7 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS) xinpcb.last = 0; xinpcb.local_port = ntohs(inp->sctp_lport); xinpcb.flags = inp->sctp_flags; - xinpcb.features = inp->sctp_features; + xinpcb.features = (uint32_t) inp->sctp_features; xinpcb.total_sends = inp->total_sends; xinpcb.total_recvs = inp->total_recvs; xinpcb.total_nospaces = inp->total_nospaces; @@ -661,6 +669,7 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS) RANGECHK(SCTP_BASE_SYSCTL(sctp_enable_sack_immediately), SCTPCTL_SACK_IMMEDIATELY_ENABLE_MIN, SCTPCTL_SACK_IMMEDIATELY_ENABLE_MAX); RANGECHK(SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly), SCTPCTL_NAT_FRIENDLY_INITS_MIN, SCTPCTL_NAT_FRIENDLY_INITS_MAX); RANGECHK(SCTP_BASE_SYSCTL(sctp_blackhole), SCTPCTL_BLACKHOLE_MIN, SCTPCTL_BLACKHOLE_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_diag_info_code), SCTPCTL_DIAG_INFO_CODE_MIN, SCTPCTL_DIAG_INFO_CODE_MAX); #ifdef SCTP_DEBUG RANGECHK(SCTP_BASE_SYSCTL(sctp_debug_on), SCTPCTL_DEBUG_MIN, SCTPCTL_DEBUG_MAX); @@ -1119,6 +1128,10 @@ SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, blackhole, CTLTYPE_UINT | CTLFLAG_RW, &SCTP_BASE_SYSCTL(sctp_blackhole), 0, sysctl_sctp_check, "IU", SCTPCTL_BLACKHOLE_DESC); +SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, diag_info_code, CTLTYPE_UINT | CTLFLAG_RW, + &SCTP_BASE_SYSCTL(sctp_diag_info_code), 0, sysctl_sctp_check, "IU", + SCTPCTL_DIAG_INFO_CODE_DESC); + #ifdef SCTP_DEBUG SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, debug, CTLTYPE_UINT | CTLFLAG_RW, &SCTP_BASE_SYSCTL(sctp_debug_on), 0, sysctl_sctp_check, "IU", diff --git a/freebsd/sys/netinet/sctp_sysctl.h b/freebsd/sys/netinet/sctp_sysctl.h index 8090373e..432d36a4 100644 --- a/freebsd/sys/netinet/sctp_sysctl.h +++ b/freebsd/sys/netinet/sctp_sysctl.h @@ -104,6 +104,7 @@ struct sctp_sysctl { uint32_t sctp_rttvar_eqret; uint32_t sctp_steady_step; uint32_t sctp_use_dccc_ecn; + uint32_t sctp_diag_info_code; #if defined(SCTP_LOCAL_TRACE_BUF) struct sctp_log sctp_log; #endif @@ -465,7 +466,7 @@ struct sctp_sysctl { #define SCTPCTL_UDP_TUNNELING_PORT_DESC "Set the SCTP/UDP tunneling port" #define SCTPCTL_UDP_TUNNELING_PORT_MIN 0 #define SCTPCTL_UDP_TUNNELING_PORT_MAX 65535 -#define SCTPCTL_UDP_TUNNELING_PORT_DEFAULT SCTP_OVER_UDP_TUNNELING_PORT +#define SCTPCTL_UDP_TUNNELING_PORT_DEFAULT 0 /* Enable sending of the SACK-IMMEDIATELY bit */ #define SCTPCTL_SACK_IMMEDIATELY_ENABLE_DESC "Enable sending of the SACK-IMMEDIATELY-bit." @@ -529,6 +530,11 @@ struct sctp_sysctl { #define SCTPCTL_BLACKHOLE_MAX 2 #define SCTPCTL_BLACKHOLE_DEFAULT SCTPCTL_BLACKHOLE_MIN +#define SCTPCTL_DIAG_INFO_CODE_DESC "Diagnostic information error cause code" +#define SCTPCTL_DIAG_INFO_CODE_MIN 0 +#define SCTPCTL_DIAG_INFO_CODE_MAX 65535 +#define SCTPCTL_DIAG_INFO_CODE_DEFAULT 0 + #if defined(SCTP_DEBUG) /* debug: Configure debug output */ #define SCTPCTL_DEBUG_DESC "Configure debug output" diff --git a/freebsd/sys/netinet/sctp_timer.c b/freebsd/sys/netinet/sctp_timer.c index be601113..7d010c7b 100644 --- a/freebsd/sys/netinet/sctp_timer.c +++ b/freebsd/sys/netinet/sctp_timer.c @@ -149,24 +149,12 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb, */ if (stcb->asoc.overall_error_count > threshold) { /* Abort notification sends a ULP notify */ - struct mbuf *oper; - - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), - 0, M_DONTWAIT, 1, MT_DATA); - if (oper) { - struct sctp_paramhdr *ph; - uint32_t *ippp; - - SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + - sizeof(uint32_t); - ph = mtod(oper, struct sctp_paramhdr *); - ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_TIMER + SCTP_LOC_1); - } + struct mbuf *op_err; + + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, + "Association error couter exceeded"); inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_1; - sctp_abort_an_association(inp, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED); return (1); } return (0); @@ -448,7 +436,7 @@ sctp_recover_sent_list(struct sctp_tcb *stcb) } } TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next); - if (chk->pr_sctp_on) { + if (PR_SCTP_ENABLED(chk->flags)) { if (asoc->pr_sctp_cnt != 0) asoc->pr_sctp_cnt--; } @@ -554,7 +542,7 @@ start_again: TAILQ_FOREACH_SAFE(chk, &stcb->asoc.sent_queue, sctp_next, nchk) { if (SCTP_TSN_GE(stcb->asoc.last_acked_seq, chk->rec.data.TSN_seq)) { /* Strange case our list got out of order? */ - SCTP_PRINTF("Our list is out of order? last_acked:%x chk:%x", + SCTP_PRINTF("Our list is out of order? last_acked:%x chk:%x\n", (unsigned int)stcb->asoc.last_acked_seq, (unsigned int)chk->rec.data.TSN_seq); recovery_cnt++; #ifdef INVARIANTS @@ -1053,24 +1041,12 @@ sctp_cookie_timer(struct sctp_inpcb *inp, if (cookie == NULL) { if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) { /* FOOBAR! */ - struct mbuf *oper; - - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), - 0, M_DONTWAIT, 1, MT_DATA); - if (oper) { - struct sctp_paramhdr *ph; - uint32_t *ippp; - - SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + - sizeof(uint32_t); - ph = mtod(oper, struct sctp_paramhdr *); - ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_TIMER + SCTP_LOC_3); - } + struct mbuf *op_err; + + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, + "Cookie timer expired, but no cookie"); inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_4; - sctp_abort_an_association(inp, stcb, oper, SCTP_SO_NOT_LOCKED); + sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED); } else { #ifdef INVARIANTS panic("Cookie timer expires in wrong state?"); diff --git a/freebsd/sys/netinet/sctp_uio.h b/freebsd/sys/netinet/sctp_uio.h index 063fd9f1..df9c2d2d 100644 --- a/freebsd/sys/netinet/sctp_uio.h +++ b/freebsd/sys/netinet/sctp_uio.h @@ -662,10 +662,6 @@ struct sctp_hmacalgo { #define SCTP_AUTH_HMAC_ID_RSVD 0x0000 #define SCTP_AUTH_HMAC_ID_SHA1 0x0001 /* default, mandatory */ #define SCTP_AUTH_HMAC_ID_SHA256 0x0003 -#define SCTP_AUTH_HMAC_ID_SHA224 0x0004 -#define SCTP_AUTH_HMAC_ID_SHA384 0x0005 -#define SCTP_AUTH_HMAC_ID_SHA512 0x0006 - /* SCTP_AUTH_ACTIVE_KEY / SCTP_AUTH_DELETE_KEY */ struct sctp_authkeyid { diff --git a/freebsd/sys/netinet/sctp_usrreq.c b/freebsd/sys/netinet/sctp_usrreq.c index 81db1dc1..e2bbced4 100644 --- a/freebsd/sys/netinet/sctp_usrreq.c +++ b/freebsd/sys/netinet/sctp_usrreq.c @@ -856,20 +856,7 @@ sctp_disconnect(struct socket *so) struct mbuf *op_err; abort_anyway: - op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), - 0, M_DONTWAIT, 1, MT_DATA); - if (op_err) { - /* - * Fill in the user - * initiated abort - */ - struct sctp_paramhdr *ph; - - SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr); - ph = mtod(op_err, struct sctp_paramhdr *); - ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons(SCTP_BUF_LEN(op_err)); - } + op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4; sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED); SCTP_STAT_INCR_COUNTER32(sctps_aborted); @@ -1065,17 +1052,7 @@ sctp_shutdown(struct socket *so) struct mbuf *op_err; abort_anyway: - op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), - 0, M_DONTWAIT, 1, MT_DATA); - if (op_err) { - /* Fill in the user initiated abort */ - struct sctp_paramhdr *ph; - - SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr); - ph = mtod(op_err, struct sctp_paramhdr *); - ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons(SCTP_BUF_LEN(op_err)); - } + op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_LOCKED); @@ -1122,9 +1099,17 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, { struct sctp_ifn *sctp_ifn; struct sctp_ifa *sctp_ifa; - int loopback_scope, ipv4_local_scope, local_scope, site_scope; size_t actual; - int ipv4_addr_legal, ipv6_addr_legal; + int loopback_scope; + +#if defined(INET) + int ipv4_local_scope, ipv4_addr_legal; + +#endif +#if defined(INET6) + int local_scope, site_scope, ipv6_addr_legal; + +#endif struct sctp_vrf *vrf; actual = 0; @@ -1134,27 +1119,43 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, if (stcb) { /* Turn on all the appropriate scope */ loopback_scope = stcb->asoc.scope.loopback_scope; +#if defined(INET) ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope; + ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal; +#endif +#if defined(INET6) local_scope = stcb->asoc.scope.local_scope; site_scope = stcb->asoc.scope.site_scope; - ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal; ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal; +#endif } else { /* Use generic values for endpoints. */ loopback_scope = 1; +#if defined(INET) ipv4_local_scope = 1; +#endif +#if defined(INET6) local_scope = 1; site_scope = 1; +#endif if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { +#if defined(INET6) ipv6_addr_legal = 1; +#endif +#if defined(INET) if (SCTP_IPV6_V6ONLY(inp)) { ipv4_addr_legal = 0; } else { ipv4_addr_legal = 1; } +#endif } else { +#if defined(INET6) ipv6_addr_legal = 0; +#endif +#if defined(INET) ipv4_addr_legal = 1; +#endif } } vrf = sctp_find_vrf(vrf_id); @@ -1198,6 +1199,10 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, */ continue; } + if (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sin->sin_addr) != 0) { + continue; + } if ((ipv4_local_scope == 0) && (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { continue; @@ -1239,6 +1244,10 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, */ continue; } + if (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sin6->sin6_addr) != 0) { + continue; + } if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { if (local_scope == 0) continue; @@ -2766,7 +2775,7 @@ flags_out: if (stcb) { /* simply copy out the sockaddr_storage... */ - int len; + size_t len; len = *optsize; if (len > stcb->asoc.primary_destination->ro._l_addr.sa.sa_len) @@ -3283,7 +3292,7 @@ flags_out: } } if (error == 0) { - *optsize = sizeof(struct sctp_paddrparams); + *optsize = sizeof(struct sctp_udpencaps); } break; } @@ -3944,7 +3953,6 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, sctp_hmaclist_t *hmaclist; uint16_t hmacid; uint32_t i; - size_t found; SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, optsize); if (optsize < sizeof(struct sctp_hmacalgo) + shmac->shmac_number_of_idents * sizeof(uint16_t)) { @@ -3968,14 +3976,14 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, goto sctp_set_hmac_done; } } - found = 0; for (i = 0; i < hmaclist->num_algo; i++) { if (hmaclist->hmac[i] == SCTP_AUTH_HMAC_ID_SHA1) { /* already in list */ - found = 1; + break; } } - if (!found) { + if (i == hmaclist->num_algo) { + /* not found in list */ sctp_free_hmaclist(hmaclist); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); error = EINVAL; @@ -4799,11 +4807,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10); } net->dest_state |= SCTP_ADDR_NO_PMTUD; - if (paddrp->spp_pathmtu > SCTP_DEFAULT_MINSEGMENT) { - net->mtu = paddrp->spp_pathmtu + ovh; - if (net->mtu < stcb->asoc.smallest_mtu) { - sctp_pathmtu_adjustment(stcb, net->mtu); - } + net->mtu = paddrp->spp_pathmtu + ovh; + if (net->mtu < stcb->asoc.smallest_mtu) { + sctp_pathmtu_adjustment(stcb, net->mtu); } } if (paddrp->spp_flags & SPP_PMTUD_ENABLE) { @@ -4923,11 +4929,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10); } net->dest_state |= SCTP_ADDR_NO_PMTUD; - if (paddrp->spp_pathmtu > SCTP_DEFAULT_MINSEGMENT) { - net->mtu = paddrp->spp_pathmtu + ovh; - if (net->mtu < stcb->asoc.smallest_mtu) { - sctp_pathmtu_adjustment(stcb, net->mtu); - } + net->mtu = paddrp->spp_pathmtu + ovh; + if (net->mtu < stcb->asoc.smallest_mtu) { + sctp_pathmtu_adjustment(stcb, net->mtu); } } sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD); @@ -5245,6 +5249,43 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, error = EINVAL; goto out_of_it; } + } else { + switch (sspp->sspp_addr.ss_family) { +#ifdef INET + case AF_INET: + { + struct sockaddr_in *sin; + + sin = (struct sockaddr_in *)&sspp->sspp_addr; + if (prison_check_ip4(inp->ip_inp.inp.inp_cred, + &sin->sin_addr) != 0) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + goto out_of_it; + } + break; + } +#endif +#ifdef INET6 + case AF_INET6: + { + struct sockaddr_in6 *sin6; + + sin6 = (struct sockaddr_in6 *)&sspp->sspp_addr; + if (prison_check_ip6(inp->ip_inp.inp.inp_cred, + &sin6->sin6_addr) != 0) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + goto out_of_it; + } + break; + } +#endif + default: + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + goto out_of_it; + } } if (sctp_set_primary_ip_address_sa(stcb, (struct sockaddr *)&sspp->sspp_addr) != 0) { @@ -5603,7 +5644,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id); net = NULL; if (stcb) { - net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_assoc_id); + net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_address); } else { /* * We increment here since @@ -5614,7 +5655,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, */ SCTP_INP_INCR_REF(inp); stcb = sctp_findassociation_ep_addr(&inp, - (struct sockaddr *)&thlds->spt_assoc_id, + (struct sockaddr *)&thlds->spt_address, &net, NULL, NULL); if (stcb == NULL) { SCTP_INP_DECR_REF(inp); @@ -5623,7 +5664,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, if (stcb && (net == NULL)) { struct sockaddr *sa; - sa = (struct sockaddr *)&thlds->spt_assoc_id; + sa = (struct sockaddr *)&thlds->spt_address; #ifdef INET if (sa->sa_family == AF_INET) { @@ -6059,30 +6100,29 @@ sctp_listen(struct socket *so, int backlog, struct thread *p) if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) { /* See if we have a listener */ struct sctp_inpcb *tinp; - union sctp_sockstore store, *sp; + union sctp_sockstore store; - sp = &store; if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) { /* not bound all */ struct sctp_laddr *laddr; LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { memcpy(&store, &laddr->ifa->address, sizeof(store)); - switch (sp->sa.sa_family) { + switch (store.sa.sa_family) { #ifdef INET case AF_INET: - sp->sin.sin_port = inp->sctp_lport; + store.sin.sin_port = inp->sctp_lport; break; #endif #ifdef INET6 case AF_INET6: - sp->sin6.sin6_port = inp->sctp_lport; + store.sin6.sin6_port = inp->sctp_lport; break; #endif default: break; } - tinp = sctp_pcb_findep(&sp->sa, 0, 0, inp->def_vrf_id); + tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id); if (tinp && (tinp != inp) && ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) && ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) && @@ -6100,20 +6140,6 @@ sctp_listen(struct socket *so, int backlog, struct thread *p) } else { /* Setup a local addr bound all */ memset(&store, 0, sizeof(store)); - switch (sp->sa.sa_family) { -#ifdef INET - case AF_INET: - store.sin.sin_port = inp->sctp_lport; - break; -#endif -#ifdef INET6 - case AF_INET6: - sp->sin6.sin6_port = inp->sctp_lport; - break; -#endif - default: - break; - } #ifdef INET6 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { store.sa.sa_family = AF_INET6; @@ -6126,7 +6152,21 @@ sctp_listen(struct socket *so, int backlog, struct thread *p) store.sa.sa_len = sizeof(struct sockaddr_in); } #endif - tinp = sctp_pcb_findep(&sp->sa, 0, 0, inp->def_vrf_id); + switch (store.sa.sa_family) { +#ifdef INET + case AF_INET: + store.sin.sin_port = inp->sctp_lport; + break; +#endif +#ifdef INET6 + case AF_INET6: + store.sin6.sin6_port = inp->sctp_lport; + break; +#endif + default: + break; + } + tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id); if (tinp && (tinp != inp) && ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) && ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) && diff --git a/freebsd/sys/netinet/sctputil.c b/freebsd/sys/netinet/sctputil.c index 15928d8b..6cd82739 100644 --- a/freebsd/sys/netinet/sctputil.c +++ b/freebsd/sys/netinet/sctputil.c @@ -2604,7 +2604,7 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb, if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT)) { notif_len = sizeof(struct sctp_assoc_change); if (abort != NULL) { - abort_len = htons(abort->ch.chunk_length); + abort_len = ntohs(abort->ch.chunk_length); } else { abort_len = 0; } @@ -2624,6 +2624,7 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb, } SCTP_BUF_NEXT(m_notify) = NULL; sac = mtod(m_notify, struct sctp_assoc_change *); + memset(sac, 0, notif_len); sac->sac_type = SCTP_ASSOC_CHANGE; sac->sac_flags = 0; sac->sac_length = sizeof(struct sctp_assoc_change); @@ -2837,21 +2838,21 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error, if (m_notify == NULL) /* no space left */ return; - length += chk->send_size; - length -= sizeof(struct sctp_data_chunk); SCTP_BUF_LEN(m_notify) = 0; if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) { ssfe = mtod(m_notify, struct sctp_send_failed_event *); + memset(ssfe, 0, length); ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT; if (sent) { ssfe->ssfe_flags = SCTP_DATA_SENT; } else { ssfe->ssfe_flags = SCTP_DATA_UNSENT; } + length += chk->send_size; + length -= sizeof(struct sctp_data_chunk); ssfe->ssfe_length = length; ssfe->ssfe_error = error; /* not exactly what the user sent in, but should be close :) */ - bzero(&ssfe->ssfe_info, sizeof(ssfe->ssfe_info)); ssfe->ssfe_info.snd_sid = chk->rec.data.stream_number; ssfe->ssfe_info.snd_flags = chk->rec.data.rcv_flags; ssfe->ssfe_info.snd_ppid = chk->rec.data.payloadtype; @@ -2861,12 +2862,15 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error, SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event); } else { ssf = mtod(m_notify, struct sctp_send_failed *); + memset(ssf, 0, length); ssf->ssf_type = SCTP_SEND_FAILED; if (sent) { ssf->ssf_flags = SCTP_DATA_SENT; } else { ssf->ssf_flags = SCTP_DATA_UNSENT; } + length += chk->send_size; + length -= sizeof(struct sctp_data_chunk); ssf->ssf_length = length; ssf->ssf_error = error; /* not exactly what the user sent in, but should be close :) */ @@ -2950,16 +2954,16 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error, /* no space left */ return; } - length += sp->length; SCTP_BUF_LEN(m_notify) = 0; if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) { ssfe = mtod(m_notify, struct sctp_send_failed_event *); + memset(ssfe, 0, length); ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT; ssfe->ssfe_flags = SCTP_DATA_UNSENT; + length += sp->length; ssfe->ssfe_length = length; ssfe->ssfe_error = error; /* not exactly what the user sent in, but should be close :) */ - bzero(&ssfe->ssfe_info, sizeof(ssfe->ssfe_info)); ssfe->ssfe_info.snd_sid = sp->stream; if (sp->some_taken) { ssfe->ssfe_info.snd_flags = SCTP_DATA_LAST_FRAG; @@ -2973,12 +2977,13 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error, SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event); } else { ssf = mtod(m_notify, struct sctp_send_failed *); + memset(ssf, 0, length); ssf->ssf_type = SCTP_SEND_FAILED; ssf->ssf_flags = SCTP_DATA_UNSENT; + length += sp->length; ssf->ssf_length = length; ssf->ssf_error = error; /* not exactly what the user sent in, but should be close :) */ - bzero(&ssf->ssf_info, sizeof(ssf->ssf_info)); ssf->ssf_info.sinfo_stream = sp->stream; ssf->ssf_info.sinfo_ssn = 0; if (sp->some_taken) { @@ -3040,6 +3045,7 @@ sctp_notify_adaptation_layer(struct sctp_tcb *stcb) return; SCTP_BUF_LEN(m_notify) = 0; sai = mtod(m_notify, struct sctp_adaptation_event *); + memset(sai, 0, sizeof(struct sctp_adaptation_event)); sai->sai_type = SCTP_ADAPTATION_INDICATION; sai->sai_flags = 0; sai->sai_length = sizeof(struct sctp_adaptation_event); @@ -3095,6 +3101,7 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error, return; SCTP_BUF_LEN(m_notify) = 0; pdapi = mtod(m_notify, struct sctp_pdapi_event *); + memset(pdapi, 0, sizeof(struct sctp_pdapi_event)); pdapi->pdapi_type = SCTP_PARTIAL_DELIVERY_EVENT; pdapi->pdapi_flags = 0; pdapi->pdapi_length = sizeof(struct sctp_pdapi_event); @@ -3204,6 +3211,7 @@ sctp_notify_shutdown_event(struct sctp_tcb *stcb) /* no space left */ return; sse = mtod(m_notify, struct sctp_shutdown_event *); + memset(sse, 0, sizeof(struct sctp_shutdown_event)); sse->sse_type = SCTP_SHUTDOWN_EVENT; sse->sse_flags = 0; sse->sse_length = sizeof(struct sctp_shutdown_event); @@ -3254,6 +3262,7 @@ sctp_notify_sender_dry_event(struct sctp_tcb *stcb, } SCTP_BUF_LEN(m_notify) = 0; event = mtod(m_notify, struct sctp_sender_dry_event *); + memset(event, 0, sizeof(struct sctp_sender_dry_event)); event->sender_dry_type = SCTP_SENDER_DRY_EVENT; event->sender_dry_flags = 0; event->sender_dry_length = sizeof(struct sctp_sender_dry_event); @@ -3286,7 +3295,6 @@ sctp_notify_stream_reset_add(struct sctp_tcb *stcb, uint16_t numberin, uint16_t struct mbuf *m_notify; struct sctp_queued_to_read *control; struct sctp_stream_change_event *stradd; - int len; if ((stcb == NULL) || (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_STREAM_CHANGEEVNT))) { @@ -3299,25 +3307,20 @@ sctp_notify_stream_reset_add(struct sctp_tcb *stcb, uint16_t numberin, uint16_t return; } stcb->asoc.peer_req_out = 0; - m_notify = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA); + m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_stream_change_event), 0, M_DONTWAIT, 1, MT_DATA); if (m_notify == NULL) /* no space left */ return; SCTP_BUF_LEN(m_notify) = 0; - len = sizeof(struct sctp_stream_change_event); - if (len > M_TRAILINGSPACE(m_notify)) { - /* never enough room */ - sctp_m_freem(m_notify); - return; - } stradd = mtod(m_notify, struct sctp_stream_change_event *); + memset(stradd, 0, sizeof(struct sctp_stream_change_event)); stradd->strchange_type = SCTP_STREAM_CHANGE_EVENT; stradd->strchange_flags = flag; - stradd->strchange_length = len; + stradd->strchange_length = sizeof(struct sctp_stream_change_event); stradd->strchange_assoc_id = sctp_get_associd(stcb); stradd->strchange_instrms = numberin; stradd->strchange_outstrms = numberout; - SCTP_BUF_LEN(m_notify) = len; + SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_stream_change_event); SCTP_BUF_NEXT(m_notify) = NULL; if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) { /* no space */ @@ -3348,32 +3351,26 @@ sctp_notify_stream_reset_tsn(struct sctp_tcb *stcb, uint32_t sending_tsn, uint32 struct mbuf *m_notify; struct sctp_queued_to_read *control; struct sctp_assoc_reset_event *strasoc; - int len; if ((stcb == NULL) || (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_ASSOC_RESETEVNT))) { /* event not enabled */ return; } - m_notify = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA); + m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_assoc_reset_event), 0, M_DONTWAIT, 1, MT_DATA); if (m_notify == NULL) /* no space left */ return; SCTP_BUF_LEN(m_notify) = 0; - len = sizeof(struct sctp_assoc_reset_event); - if (len > M_TRAILINGSPACE(m_notify)) { - /* never enough room */ - sctp_m_freem(m_notify); - return; - } strasoc = mtod(m_notify, struct sctp_assoc_reset_event *); + memset(strasoc, 0, sizeof(struct sctp_assoc_reset_event)); strasoc->assocreset_type = SCTP_ASSOC_RESET_EVENT; strasoc->assocreset_flags = flag; - strasoc->assocreset_length = len; + strasoc->assocreset_length = sizeof(struct sctp_assoc_reset_event); strasoc->assocreset_assoc_id = sctp_get_associd(stcb); strasoc->assocreset_local_tsn = sending_tsn; strasoc->assocreset_remote_tsn = recv_tsn; - SCTP_BUF_LEN(m_notify) = len; + SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_assoc_reset_event); SCTP_BUF_NEXT(m_notify) = NULL; if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) { /* no space */ @@ -3426,6 +3423,7 @@ sctp_notify_stream_reset(struct sctp_tcb *stcb, return; } strreset = mtod(m_notify, struct sctp_stream_reset_event *); + memset(strreset, 0, len); strreset->strreset_type = SCTP_STREAM_RESET_EVENT; strreset->strreset_flags = flag; strreset->strreset_length = len; @@ -3476,7 +3474,7 @@ sctp_notify_remote_error(struct sctp_tcb *stcb, uint16_t error, struct sctp_erro return; } if (chunk != NULL) { - chunk_len = htons(chunk->ch.chunk_length); + chunk_len = ntohs(chunk->ch.chunk_length); } else { chunk_len = 0; } @@ -4020,6 +4018,7 @@ void sctp_handle_ootb(struct mbuf *m, int iphlen, int offset, struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, struct sctp_inpcb *inp, + struct mbuf *cause, uint8_t use_mflowid, uint32_t mflowid, uint32_t vrf_id, uint16_t port) { @@ -4048,9 +4047,6 @@ sctp_handle_ootb(struct mbuf *m, int iphlen, int offset, case SCTP_INIT: contains_init_chunk = 1; break; - case SCTP_COOKIE_ECHO: - /* We hit here only if the assoc is being freed */ - return; case SCTP_PACKET_DROPPED: /* we don't respond to pkt-dropped */ return; @@ -4078,7 +4074,7 @@ sctp_handle_ootb(struct mbuf *m, int iphlen, int offset, if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) || ((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) && (contains_init_chunk == 0))) { - sctp_send_abort(m, iphlen, src, dst, sh, 0, NULL, + sctp_send_abort(m, iphlen, src, dst, sh, 0, cause, use_mflowid, mflowid, vrf_id, port); } @@ -4633,19 +4629,43 @@ get_out: */ struct mbuf * -sctp_generate_invmanparam(int err) +sctp_generate_cause(uint16_t code, char *info) { - /* Return a MBUF with a invalid mandatory parameter */ struct mbuf *m; + struct sctp_gen_error_cause *cause; + size_t info_len, len; - m = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 0, M_DONTWAIT, 1, MT_DATA); - if (m) { - struct sctp_paramhdr *ph; + if ((code == 0) || (info == NULL)) { + return (NULL); + } + info_len = strlen(info); + len = sizeof(struct sctp_paramhdr) + info_len; + m = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA); + if (m != NULL) { + SCTP_BUF_LEN(m) = len; + cause = mtod(m, struct sctp_gen_error_cause *); + cause->code = htons(code); + cause->length = htons((uint16_t) len); + memcpy(cause->info, info, info_len); + } + return (m); +} - SCTP_BUF_LEN(m) = sizeof(struct sctp_paramhdr); - ph = mtod(m, struct sctp_paramhdr *); - ph->param_length = htons(sizeof(struct sctp_paramhdr)); - ph->param_type = htons(err); +struct mbuf * +sctp_generate_no_user_data_cause(uint32_t tsn) +{ + struct mbuf *m; + struct sctp_error_no_user_data *no_user_data_cause; + size_t len; + + len = sizeof(struct sctp_error_no_user_data); + m = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA); + if (m != NULL) { + SCTP_BUF_LEN(m) = len; + no_user_data_cause = mtod(m, struct sctp_error_no_user_data *); + no_user_data_cause->cause.code = htons(SCTP_CAUSE_NO_USER_DATA); + no_user_data_cause->cause.length = htons((uint16_t) len); + no_user_data_cause->tsn = tsn; /* tsn is passed in as NBO */ } return (m); } @@ -4835,7 +4855,6 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1, atomic_add_int(&chk->whoTo->ref_count, 1); chk->rec.data.TSN_seq = atomic_fetchadd_int(&stcb->asoc.sending_seq, 1); stcb->asoc.pr_sctp_cnt++; - chk->pr_sctp_on = 1; TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, chk, sctp_next); stcb->asoc.sent_queue_cnt++; stcb->asoc.pr_sctp_cnt++; @@ -5871,8 +5890,8 @@ get_more_data: goto release; } if ((uio->uio_resid == 0) || - ((in_eeor_mode) && (copied_so_far >= max(so->so_rcv.sb_lowat, 1))) - ) { + ((in_eeor_mode) && + (copied_so_far >= (uint32_t) max(so->so_rcv.sb_lowat, 1)))) { goto release; } /* @@ -6217,9 +6236,12 @@ sctp_soreceive(struct socket *so, fromlen = 0; } + if (filling_sinfo) { + memset(&sinfo, 0, sizeof(struct sctp_extrcvinfo)); + } error = sctp_sorecvmsg(so, uio, mp0, from, fromlen, flagsp, (struct sctp_sndrcvinfo *)&sinfo, filling_sinfo); - if ((controlp) && (filling_sinfo)) { + if (controlp != NULL) { /* copy back the sinfo in a CMSG format */ if (filling_sinfo) *controlp = sctp_build_ctl_nchunk(inp, @@ -6615,8 +6637,16 @@ sctp_bindx_delete_address(struct sctp_inpcb *inp, int sctp_local_addr_count(struct sctp_tcb *stcb) { - int loopback_scope, ipv4_local_scope, local_scope, site_scope; - int ipv4_addr_legal, ipv6_addr_legal; + int loopback_scope; + +#if defined(INET) + int ipv4_local_scope, ipv4_addr_legal; + +#endif +#if defined (INET6) + int local_scope, site_scope, ipv6_addr_legal; + +#endif struct sctp_vrf *vrf; struct sctp_ifn *sctp_ifn; struct sctp_ifa *sctp_ifa; @@ -6624,11 +6654,15 @@ sctp_local_addr_count(struct sctp_tcb *stcb) /* Turn on all the appropriate scopes */ loopback_scope = stcb->asoc.scope.loopback_scope; +#if defined(INET) ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope; + ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal; +#endif +#if defined(INET6) local_scope = stcb->asoc.scope.local_scope; site_scope = stcb->asoc.scope.site_scope; - ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal; ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal; +#endif SCTP_IPI_ADDR_RLOCK(); vrf = sctp_find_vrf(stcb->asoc.vrf_id); if (vrf == NULL) { @@ -6662,6 +6696,10 @@ sctp_local_addr_count(struct sctp_tcb *stcb) */ continue; } + if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred, + &sin->sin_addr) != 0) { + continue; + } if ((ipv4_local_scope == 0) && (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { continue; @@ -6682,6 +6720,10 @@ sctp_local_addr_count(struct sctp_tcb *stcb) if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { continue; } + if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred, + &sin6->sin6_addr) != 0) { + continue; + } if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { if (local_scope == 0) continue; diff --git a/freebsd/sys/netinet/sctputil.h b/freebsd/sys/netinet/sctputil.h index 411bfafc..af5a0f29 100644 --- a/freebsd/sys/netinet/sctputil.h +++ b/freebsd/sys/netinet/sctputil.h @@ -205,6 +205,7 @@ void sctp_handle_ootb(struct mbuf *, int, int, struct sockaddr *, struct sockaddr *, struct sctphdr *, struct sctp_inpcb *, + struct mbuf *, uint8_t, uint32_t, uint32_t, uint16_t); @@ -252,7 +253,8 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *, struct sctp_tmit_chunk *, #endif ); -struct mbuf *sctp_generate_invmanparam(int); +struct mbuf *sctp_generate_cause(uint16_t, char *); +struct mbuf *sctp_generate_no_user_data_cause(uint32_t); void sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp, diff --git a/freebsd/sys/netinet/tcp_input.c b/freebsd/sys/netinet/tcp_input.c index 50dfc1ce..20d645f0 100644 --- a/freebsd/sys/netinet/tcp_input.c +++ b/freebsd/sys/netinet/tcp_input.c @@ -163,10 +163,10 @@ SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, rfc3390, CTLFLAG_RW, SYSCTL_NODE(_net_inet_tcp, OID_AUTO, experimental, CTLFLAG_RW, 0, "Experimental TCP extensions"); -VNET_DEFINE(int, tcp_do_initcwnd10) = 0; +VNET_DEFINE(int, tcp_do_initcwnd10) = 1; SYSCTL_VNET_INT(_net_inet_tcp_experimental, OID_AUTO, initcwnd10, CTLFLAG_RW, &VNET_NAME(tcp_do_initcwnd10), 0, - "Enable draft-ietf-tcpm-initcwnd-05 (Increasing initial CWND to 10)"); + "Enable RFC 6928 (Increasing initial CWND to 10)"); VNET_DEFINE(int, tcp_do_rfc3465) = 1; SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, rfc3465, CTLFLAG_RW, @@ -356,7 +356,7 @@ cc_conn_init(struct tcpcb *tp) * * RFC5681 Section 3.1 specifies the default conservative values. * RFC3390 specifies slightly more aggressive values. - * Draft-ietf-tcpm-initcwnd-05 increases it to ten segments. + * RFC6928 increases it to ten segments. * * If a SYN or SYN/ACK was lost and retransmitted, we have to * reduce the initial CWND to one segment as congestion is likely diff --git a/freebsd/sys/netinet/tcp_reass.c b/freebsd/sys/netinet/tcp_reass.c index aebda9db..d4f0bcde 100644 --- a/freebsd/sys/netinet/tcp_reass.c +++ b/freebsd/sys/netinet/tcp_reass.c @@ -207,7 +207,7 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m) * Investigate why and re-evaluate the below limit after the behaviour * is understood. */ - if (th->th_seq != tp->rcv_nxt && + if ((th->th_seq != tp->rcv_nxt || !TCPS_HAVEESTABLISHED(tp->t_state)) && tp->t_segqlen >= (so->so_rcv.sb_hiwat / tp->t_maxseg) + 1) { V_tcp_reass_overflows++; TCPSTAT_INC(tcps_rcvmemdrop); @@ -230,7 +230,7 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m) */ te = uma_zalloc(V_tcp_reass_zone, M_NOWAIT); if (te == NULL) { - if (th->th_seq != tp->rcv_nxt) { + if (th->th_seq != tp->rcv_nxt || !TCPS_HAVEESTABLISHED(tp->t_state)) { TCPSTAT_INC(tcps_rcvmemdrop); m_freem(m); *tlenp = 0; @@ -278,7 +278,8 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m) TCPSTAT_INC(tcps_rcvduppack); TCPSTAT_ADD(tcps_rcvdupbyte, *tlenp); m_freem(m); - uma_zfree(V_tcp_reass_zone, te); + if (te != &tqs) + uma_zfree(V_tcp_reass_zone, te); tp->t_segqlen--; /* * Try to present any queued data diff --git a/freebsd/sys/netinet/tcp_subr.c b/freebsd/sys/netinet/tcp_subr.c index 4c6d14eb..d577f18f 100644 --- a/freebsd/sys/netinet/tcp_subr.c +++ b/freebsd/sys/netinet/tcp_subr.c @@ -1747,9 +1747,10 @@ tcp_maxmtu(struct in_conninfo *inc, struct tcp_ifcap *cap) /* Report additional interface capabilities. */ if (cap != NULL) { if (ifp->if_capenable & IFCAP_TSO4 && - ifp->if_hwassist & CSUM_TSO) + ifp->if_hwassist & CSUM_TSO) { cap->ifcap |= CSUM_TSO; cap->tsomax = ifp->if_hw_tsomax; + } } RTFREE(sro.ro_rt); } @@ -1785,9 +1786,10 @@ tcp_maxmtu6(struct in_conninfo *inc, struct tcp_ifcap *cap) /* Report additional interface capabilities. */ if (cap != NULL) { if (ifp->if_capenable & IFCAP_TSO6 && - ifp->if_hwassist & CSUM_TSO) + ifp->if_hwassist & CSUM_TSO) { cap->ifcap |= CSUM_TSO; cap->tsomax = ifp->if_hw_tsomax; + } } RTFREE(sro6.ro_rt); } -- cgit v1.2.3