From owner-svn-src-head@FreeBSD.ORG Mon Jun 25 19:13:44 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 73E7E1065672; Mon, 25 Jun 2012 19:13:44 +0000 (UTC) (envelope-from tuexen@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 5D5558FC08; Mon, 25 Jun 2012 19:13:44 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q5PJDiLA090431; Mon, 25 Jun 2012 19:13:44 GMT (envelope-from tuexen@svn.freebsd.org) Received: (from tuexen@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q5PJDihX090427; Mon, 25 Jun 2012 19:13:44 GMT (envelope-from tuexen@svn.freebsd.org) Message-Id: <201206251913.q5PJDihX090427@svn.freebsd.org> From: Michael Tuexen Date: Mon, 25 Jun 2012 19:13:44 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r237569 - in head/sys: netinet netinet6 X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 25 Jun 2012 19:13:44 -0000 Author: tuexen Date: Mon Jun 25 19:13:43 2012 New Revision: 237569 URL: http://svn.freebsd.org/changeset/base/237569 Log: Unify sctp_input() and sctp6_input(). MFC after: 3 days Modified: head/sys/netinet/sctp_input.c head/sys/netinet6/sctp6_usrreq.c Modified: head/sys/netinet/sctp_input.c ============================================================================== --- head/sys/netinet/sctp_input.c Mon Jun 25 19:01:04 2012 (r237568) +++ head/sys/netinet/sctp_input.c Mon Jun 25 19:13:43 2012 (r237569) @@ -5885,12 +5885,12 @@ sctp_input_with_port(struct mbuf *i_pak, uint8_t ecn_bits; struct ip *ip; struct sctphdr *sh; + struct sctp_chunkhdr *ch; struct sctp_inpcb *inp = NULL; - struct sctp_nets *net; struct sctp_tcb *stcb = NULL; - struct sctp_chunkhdr *ch; + struct sctp_nets *net = NULL; int refcount_up = 0; - int length, mlen, offset; + int length, offset; uint32_t mflowid; uint8_t use_mflowid; @@ -5899,19 +5899,12 @@ sctp_input_with_port(struct mbuf *i_pak, #endif + iphlen = off; if (SCTP_GET_PKT_VRFID(i_pak, vrf_id)) { SCTP_RELEASE_PKT(i_pak); return; } - mlen = SCTP_HEADER_LEN(i_pak); - iphlen = off; m = SCTP_HEADER_TO_CHAIN(i_pak); - - net = NULL; - SCTP_STAT_INCR(sctps_recvpackets); - SCTP_STAT_INCR_COUNTER64(sctps_inpackets); - - #ifdef SCTP_MBUF_LOGGING /* Log in any input mbufs */ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { @@ -5925,8 +5918,9 @@ sctp_input_with_port(struct mbuf *i_pak, } #endif #ifdef SCTP_PACKET_LOGGING - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) { sctp_packet_log(m); + } #endif if (m->m_flags & M_FLOWID) { mflowid = m->m_pkthdr.flowid; @@ -5935,17 +5929,11 @@ sctp_input_with_port(struct mbuf *i_pak, mflowid = 0; use_mflowid = 0; } - /* - * Must take out the iphlen, since mlen expects this (only effect lb - * case) - */ - mlen -= iphlen; - - /* - * Get IP, SCTP, and first chunk header together in first mbuf. - */ + SCTP_STAT_INCR(sctps_recvpackets); + SCTP_STAT_INCR_COUNTER64(sctps_inpackets); + /* Get IP, SCTP, and first chunk header together in the first mbuf. */ ip = mtod(m, struct ip *); - offset = iphlen + sizeof(*sh) + sizeof(*ch); + offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); if (SCTP_BUF_LEN(m) < offset) { if ((m = m_pullup(m, offset)) == 0) { SCTP_STAT_INCR(sctps_hdrops); @@ -5953,28 +5941,26 @@ sctp_input_with_port(struct mbuf *i_pak, } ip = mtod(m, struct ip *); } - /* validate mbuf chain length with IP payload length */ - if (mlen < (SCTP_GET_IPV4_LENGTH(ip) - iphlen)) { + sh = (struct sctphdr *)((caddr_t)ip + iphlen); + ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr)); + offset -= sizeof(struct sctp_chunkhdr); + length = ip->ip_len + iphlen; + /* Validate mbuf chain length with IP payload length. */ + if (SCTP_HEADER_LEN(i_pak) != length) { + SCTPDBG(SCTP_DEBUG_INPUT1, + "sctp_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(i_pak)); SCTP_STAT_INCR(sctps_hdrops); goto bad; } - sh = (struct sctphdr *)((caddr_t)ip + iphlen); - ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(*sh)); - SCTPDBG(SCTP_DEBUG_INPUT1, - "sctp_input() length:%d iphlen:%d\n", mlen, iphlen); - /* SCTP does not allow broadcasts or multicasts */ if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) { goto bad; } if (SCTP_IS_IT_BROADCAST(ip->ip_dst, m)) { - /* - * We only look at broadcast if its a front state, All - * others we will not have a tcb for anyway. - */ goto bad; } - /* validate SCTP checksum */ + SCTPDBG(SCTP_DEBUG_INPUT1, + "sctp_input() length:%d iphlen:%d\n", length, iphlen); SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, "sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n", m->m_pkthdr.len, @@ -5985,21 +5971,18 @@ sctp_input_with_port(struct mbuf *i_pak, #else if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) { SCTP_STAT_INCR(sctps_recvhwcrc); - goto sctp_skip_csum_4; + goto sctp_skip_csum; } - check = sh->checksum; /* save incoming checksum */ - sh->checksum = 0; /* prepare for calc */ + check = sh->checksum; + sh->checksum = 0; calc_check = sctp_calculate_cksum(m, iphlen); sh->checksum = check; SCTP_STAT_INCR(sctps_recvswcrc); if (calc_check != check) { SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x m:%p mlen:%d iphlen:%d\n", - calc_check, check, m, mlen, iphlen); - - stcb = sctp_findassociation_addr(m, - offset - sizeof(*ch), - sh, ch, &inp, &net, - vrf_id); + calc_check, check, m, length, iphlen); + stcb = sctp_findassociation_addr(m, offset, + sh, ch, &inp, &net, vrf_id); if ((net) && (port)) { if (net->port == 0) { sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); @@ -6013,7 +5996,7 @@ sctp_input_with_port(struct mbuf *i_pak, #endif } if ((inp) && (stcb)) { - sctp_send_packet_dropped(stcb, net, m, mlen + iphlen, iphlen, 1); + sctp_send_packet_dropped(stcb, net, m, length, iphlen, 1); sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED); } else if ((inp != NULL) && (stcb == NULL)) { refcount_up = 1; @@ -6022,18 +6005,14 @@ sctp_input_with_port(struct mbuf *i_pak, SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors); goto bad; } -sctp_skip_csum_4: +sctp_skip_csum: #endif /* destination port of 0 is illegal, based on RFC2960. */ if (sh->dest_port == 0) { SCTP_STAT_INCR(sctps_hdrops); goto bad; } - /* - * Locate pcb and tcb for datagram sctp_findassociation_addr() wants - * IP/SCTP/first chunk header... - */ - stcb = sctp_findassociation_addr(m, offset - sizeof(*ch), + stcb = sctp_findassociation_addr(m, offset, sh, ch, &inp, &net, vrf_id); if ((net) && (port)) { if (net->port == 0) { @@ -6047,27 +6026,10 @@ sctp_skip_csum_4: net->flowidset = 1; #endif } - /* inp's ref-count increased && stcb locked */ if (inp == NULL) { - struct sctp_init_chunk *init_chk, chunk_buf; - SCTP_STAT_INCR(sctps_noport); if (badport_bandlim(BANDLIM_SCTP_OOTB) < 0) goto bad; - SCTPDBG(SCTP_DEBUG_INPUT1, - "Sending a ABORT from packet entry!\n"); - if (ch->chunk_type == SCTP_INITIATION) { - /* - * we do a trick here to get the INIT tag, dig in - * and get the tag from the INIT and put it in the - * common header. - */ - init_chk = (struct sctp_init_chunk *)sctp_m_getptr(m, - iphlen + sizeof(*sh), sizeof(*init_chk), - (uint8_t *) & chunk_buf); - if (init_chk != NULL) - sh->v_tag = init_chk->init.initiate_tag; - } if (ch->chunk_type == SCTP_SHUTDOWN_ACK) { sctp_send_shutdown_complete2(m, sh, use_mflowid, mflowid, @@ -6091,7 +6053,7 @@ sctp_skip_csum_4: refcount_up = 1; } #ifdef IPSEC - /* + /*- * I very much doubt any of the IPSEC stuff will work but I have no * idea, so I will leave it in place. */ @@ -6100,28 +6062,22 @@ sctp_skip_csum_4: SCTP_STAT_INCR(sctps_hdrops); goto bad; } -#endif /* IPSEC */ - - /* - * common chunk processing - */ - length = ip->ip_len + iphlen; - offset -= sizeof(struct sctp_chunkhdr); +#endif ecn_bits = ip->ip_tos; - /* sa_ignore NO_NULL_CHK */ sctp_common_input_processing(&m, iphlen, offset, length, sh, ch, inp, stcb, net, ecn_bits, use_mflowid, mflowid, vrf_id, port); - /* inp's ref-count reduced && stcb unlocked */ if (m) { sctp_m_freem(m); } if ((inp) && (refcount_up)) { /* reduce ref-count */ + SCTP_INP_WLOCK(inp); SCTP_INP_DECR_REF(inp); + SCTP_INP_WUNLOCK(inp); } return; bad: @@ -6130,7 +6086,9 @@ bad: } if ((inp) && (refcount_up)) { /* reduce ref-count */ + SCTP_INP_WLOCK(inp); SCTP_INP_DECR_REF(inp); + SCTP_INP_WUNLOCK(inp); } if (m) { sctp_m_freem(m); Modified: head/sys/netinet6/sctp6_usrreq.c ============================================================================== --- head/sys/netinet6/sctp6_usrreq.c Mon Jun 25 19:01:04 2012 (r237568) +++ head/sys/netinet6/sctp6_usrreq.c Mon Jun 25 19:13:43 2012 (r237569) @@ -68,22 +68,17 @@ int sctp6_input(struct mbuf **i_pak, int *offp, int proto) { struct mbuf *m; + int iphlen; + uint32_t vrf_id = 0; + uint8_t ecn_bits; struct ip6_hdr *ip6; struct sctphdr *sh; - struct sctp_inpcb *in6p = NULL; - struct sctp_nets *net; - int refcount_up = 0; - uint32_t vrf_id = 0; - -#ifdef IPSEC - struct inpcb *in6p_ip; - -#endif struct sctp_chunkhdr *ch; - int length, offset, iphlen; - uint8_t ecn_bits; + struct sctp_inpcb *inp = NULL; struct sctp_tcb *stcb = NULL; - int pkt_len = 0; + struct sctp_nets *net = NULL; + int refcount_up = 0; + int length, offset; uint32_t mflowid; uint8_t use_mflowid; @@ -91,17 +86,26 @@ sctp6_input(struct mbuf **i_pak, int *of uint32_t check, calc_check; #endif - int off = *offp; uint16_t port = 0; - /* get the VRF and table id's */ + iphlen = *offp; if (SCTP_GET_PKT_VRFID(*i_pak, vrf_id)) { SCTP_RELEASE_PKT(*i_pak); - return (-1); + return (IPPROTO_DONE); } m = SCTP_HEADER_TO_CHAIN(*i_pak); - pkt_len = SCTP_HEADER_LEN(*i_pak); - +#ifdef SCTP_MBUF_LOGGING + /* Log in any input mbufs */ + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { + struct mbuf *mat; + + for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) { + if (SCTP_BUF_IS_EXTENDED(mat)) { + sctp_log_mb(mat, SCTP_MBUF_INPUT); + } + } + } +#endif #ifdef SCTP_PACKET_LOGGING if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) { sctp_packet_log(m); @@ -114,42 +118,38 @@ sctp6_input(struct mbuf **i_pak, int *of mflowid = 0; use_mflowid = 0; } + SCTP_STAT_INCR(sctps_recvpackets); + SCTP_STAT_INCR_COUNTER64(sctps_inpackets); + /* Get IP, SCTP, and first chunk header together in the first mbuf. */ ip6 = mtod(m, struct ip6_hdr *); - /* Ensure that (sctphdr + sctp_chunkhdr) in a row. */ - IP6_EXTHDR_GET(sh, struct sctphdr *, m, off, - (int)(sizeof(*sh) + sizeof(*ch))); + offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); + IP6_EXTHDR_GET(sh, struct sctphdr *, m, iphlen, + (int)(sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr))); if (sh == NULL) { SCTP_STAT_INCR(sctps_hdrops); return (IPPROTO_DONE); } ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr)); - iphlen = off; - offset = iphlen + sizeof(*sh) + sizeof(*ch); - SCTPDBG(SCTP_DEBUG_INPUT1, - "sctp6_input() length:%d iphlen:%d\n", pkt_len, iphlen); - - -#if defined(NFAITH) && NFAITH > 0 - + offset -= sizeof(struct sctp_chunkhdr); if (faithprefix_p != NULL && (*faithprefix_p) (&ip6->ip6_dst)) { /* XXX send icmp6 host/port unreach? */ goto bad; } -#endif /* NFAITH defined and > 0 */ - SCTP_STAT_INCR(sctps_recvpackets); - SCTP_STAT_INCR_COUNTER64(sctps_inpackets); - SCTPDBG(SCTP_DEBUG_INPUT1, "V6 input gets a packet iphlen:%d pktlen:%d\n", - iphlen, pkt_len); - if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { - /* No multi-cast support in SCTP */ + length = ntohs(ip6->ip6_plen) + iphlen; + /* Validate mbuf chain length with IP payload length. */ + if (SCTP_HEADER_LEN(*i_pak) != length) { + SCTPDBG(SCTP_DEBUG_INPUT1, + "sctp6_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(*i_pak)); + SCTP_STAT_INCR(sctps_hdrops); goto bad; } - /* destination port of 0 is illegal, based on RFC2960. */ - if (sh->dest_port == 0) + if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { goto bad; - + } + SCTPDBG(SCTP_DEBUG_INPUT1, + "sctp6_input() length:%d iphlen:%d\n", length, iphlen); SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, - "sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n", + "sctp6_input(): Packet of length %d received on %s with csum_flags 0x%x.\n", m->m_pkthdr.len, if_name(m->m_pkthdr.rcvif), m->m_pkthdr.csum_flags); @@ -160,15 +160,16 @@ sctp6_input(struct mbuf **i_pak, int *of SCTP_STAT_INCR(sctps_recvhwcrc); goto sctp_skip_csum; } - check = sh->checksum; /* save incoming checksum */ - sh->checksum = 0; /* prepare for calc */ + check = sh->checksum; + sh->checksum = 0; calc_check = sctp_calculate_cksum(m, iphlen); + sh->checksum = check; SCTP_STAT_INCR(sctps_recvswcrc); if (calc_check != check) { - SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x m:%p phlen:%d\n", - calc_check, check, m, iphlen); - stcb = sctp_findassociation_addr(m, offset - sizeof(*ch), - sh, ch, &in6p, &net, vrf_id); + SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x m:%p mlen:%d iphlen:%d\n", + calc_check, check, m, length, iphlen); + stcb = sctp_findassociation_addr(m, offset, + sh, ch, &inp, &net, vrf_id); if ((net) && (port)) { if (net->port == 0) { sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); @@ -181,28 +182,25 @@ sctp6_input(struct mbuf **i_pak, int *of net->flowidset = 1; #endif } - /* in6p's ref-count increased && stcb locked */ - if ((in6p) && (stcb)) { - sctp_send_packet_dropped(stcb, net, m, pkt_len, iphlen, 1); - sctp_chunk_output((struct sctp_inpcb *)in6p, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED); - } else if ((in6p != NULL) && (stcb == NULL)) { + if ((inp) && (stcb)) { + sctp_send_packet_dropped(stcb, net, m, length, iphlen, 1); + sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED); + } else if ((inp != NULL) && (stcb == NULL)) { refcount_up = 1; } SCTP_STAT_INCR(sctps_badsum); SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors); goto bad; } - sh->checksum = calc_check; - sctp_skip_csum: #endif - net = NULL; - /* - * Locate pcb and tcb for datagram sctp_findassociation_addr() wants - * IP/SCTP/first chunk header... - */ - stcb = sctp_findassociation_addr(m, offset - sizeof(*ch), - sh, ch, &in6p, &net, vrf_id); + /* destination port of 0 is illegal, based on RFC2960. */ + if (sh->dest_port == 0) { + SCTP_STAT_INCR(sctps_hdrops); + goto bad; + } + stcb = sctp_findassociation_addr(m, offset, + sh, ch, &inp, &net, vrf_id); if ((net) && (port)) { if (net->port == 0) { sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); @@ -215,25 +213,10 @@ sctp_skip_csum: net->flowidset = 1; #endif } - /* in6p's ref-count increased */ - if (in6p == NULL) { - struct sctp_init_chunk *init_chk, chunk_buf; - + if (inp == NULL) { SCTP_STAT_INCR(sctps_noport); - if (ch->chunk_type == SCTP_INITIATION) { - /* - * we do a trick here to get the INIT tag, dig in - * and get the tag from the INIT and put it in the - * common header. - */ - init_chk = (struct sctp_init_chunk *)sctp_m_getptr(m, - iphlen + sizeof(*sh), sizeof(*init_chk), - (uint8_t *) & chunk_buf); - if (init_chk) - sh->v_tag = init_chk->init.initiate_tag; - else - sh->v_tag = 0; - } + if (badport_bandlim(BANDLIM_SCTP_OOTB) < 0) + goto bad; if (ch->chunk_type == SCTP_SHUTDOWN_ACK) { sctp_send_shutdown_complete2(m, sh, use_mflowid, mflowid, @@ -257,55 +240,46 @@ sctp_skip_csum: refcount_up = 1; } #ifdef IPSEC - /* - * Check AH/ESP integrity. + /*- + * I very much doubt any of the IPSEC stuff will work but I have no + * idea, so I will leave it in place. */ - in6p_ip = (struct inpcb *)in6p; - if (in6p_ip && (ipsec6_in_reject(m, in6p_ip))) { -/* XXX */ + if (inp && ipsec6_in_reject(m, &inp->ip_inp.inp)) { MODULE_GLOBAL(ipsec6stat).in_polvio++; + SCTP_STAT_INCR(sctps_hdrops); goto bad; } -#endif /* IPSEC */ +#endif - /* - * CONTROL chunk processing - */ - offset -= sizeof(*ch); ecn_bits = ((ntohl(ip6->ip6_flow) >> 20) & 0x000000ff); - - /* Length now holds the total packet length payload + iphlen */ - length = ntohs(ip6->ip6_plen) + iphlen; - /* sa_ignore NO_NULL_CHK */ sctp_common_input_processing(&m, iphlen, offset, length, sh, ch, - in6p, stcb, net, ecn_bits, + inp, stcb, net, ecn_bits, use_mflowid, mflowid, vrf_id, port); - /* inp's ref-count reduced && stcb unlocked */ - /* XXX this stuff below gets moved to appropriate parts later... */ - if (m) + if (m) { sctp_m_freem(m); - if ((in6p) && refcount_up) { + } + if ((inp) && (refcount_up)) { /* reduce ref-count */ - SCTP_INP_WLOCK(in6p); - SCTP_INP_DECR_REF(in6p); - SCTP_INP_WUNLOCK(in6p); + SCTP_INP_WLOCK(inp); + SCTP_INP_DECR_REF(inp); + SCTP_INP_WUNLOCK(inp); } return (IPPROTO_DONE); - bad: if (stcb) { SCTP_TCB_UNLOCK(stcb); } - if ((in6p) && refcount_up) { + if ((inp) && (refcount_up)) { /* reduce ref-count */ - SCTP_INP_WLOCK(in6p); - SCTP_INP_DECR_REF(in6p); - SCTP_INP_WUNLOCK(in6p); + SCTP_INP_WLOCK(inp); + SCTP_INP_DECR_REF(inp); + SCTP_INP_WUNLOCK(inp); } - if (m) + if (m) { sctp_m_freem(m); + } return (IPPROTO_DONE); }