sctp6_usrreq.c (237715) | sctp6_usrreq.c (238003) |
---|---|
1/*- 2 * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. 3 * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. 4 * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * --- 17 unchanged lines hidden (view full) --- 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 * THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. 3 * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. 4 * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * --- 17 unchanged lines hidden (view full) --- 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 * THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h> |
34__FBSDID("$FreeBSD: head/sys/netinet6/sctp6_usrreq.c 237715 2012-06-28 16:01:08Z tuexen $"); | 34__FBSDID("$FreeBSD: head/sys/netinet6/sctp6_usrreq.c 238003 2012-07-02 16:44:09Z tuexen $"); |
35 36#include <netinet/sctp_os.h> 37#include <sys/proc.h> 38#include <netinet/sctp_pcb.h> 39#include <netinet/sctp_header.h> 40#include <netinet/sctp_var.h> 41#if defined(INET6) 42#include <netinet6/sctp6_var.h> --- 21 unchanged lines hidden (view full) --- 64 65extern struct protosw inetsw[]; 66 67int 68sctp6_input(struct mbuf **i_pak, int *offp, int proto) 69{ 70 struct mbuf *m; 71 int iphlen; | 35 36#include <netinet/sctp_os.h> 37#include <sys/proc.h> 38#include <netinet/sctp_pcb.h> 39#include <netinet/sctp_header.h> 40#include <netinet/sctp_var.h> 41#if defined(INET6) 42#include <netinet6/sctp6_var.h> --- 21 unchanged lines hidden (view full) --- 64 65extern struct protosw inetsw[]; 66 67int 68sctp6_input(struct mbuf **i_pak, int *offp, int proto) 69{ 70 struct mbuf *m; 71 int iphlen; |
72 uint32_t vrf_id = 0; | 72 uint32_t vrf_id; |
73 uint8_t ecn_bits; 74 struct sockaddr_in6 src, dst; 75 struct ip6_hdr *ip6; 76 struct sctphdr *sh; 77 struct sctp_chunkhdr *ch; | 73 uint8_t ecn_bits; 74 struct sockaddr_in6 src, dst; 75 struct ip6_hdr *ip6; 76 struct sctphdr *sh; 77 struct sctp_chunkhdr *ch; |
78 struct sctp_inpcb *inp = NULL; 79 struct sctp_tcb *stcb = NULL; 80 struct sctp_nets *net = NULL; 81 int refcount_up = 0; | |
82 int length, offset; | 78 int length, offset; |
83 uint32_t mflowid; 84 uint8_t use_mflowid; | |
85 86#if !defined(SCTP_WITH_NO_CSUM) | 79 80#if !defined(SCTP_WITH_NO_CSUM) |
87 uint32_t check, calc_check; | 81 uint8_t compute_crc; |
88 89#endif | 82 83#endif |
84 uint32_t mflowid; 85 uint8_t use_mflowid; |
|
90 uint16_t port = 0; 91 92 iphlen = *offp; 93 if (SCTP_GET_PKT_VRFID(*i_pak, vrf_id)) { 94 SCTP_RELEASE_PKT(*i_pak); 95 return (IPPROTO_DONE); 96 } 97 m = SCTP_HEADER_TO_CHAIN(*i_pak); --- 9 unchanged lines hidden (view full) --- 107 } 108 } 109#endif 110#ifdef SCTP_PACKET_LOGGING 111 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) { 112 sctp_packet_log(m); 113 } 114#endif | 86 uint16_t port = 0; 87 88 iphlen = *offp; 89 if (SCTP_GET_PKT_VRFID(*i_pak, vrf_id)) { 90 SCTP_RELEASE_PKT(*i_pak); 91 return (IPPROTO_DONE); 92 } 93 m = SCTP_HEADER_TO_CHAIN(*i_pak); --- 9 unchanged lines hidden (view full) --- 103 } 104 } 105#endif 106#ifdef SCTP_PACKET_LOGGING 107 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) { 108 sctp_packet_log(m); 109 } 110#endif |
111 SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, 112 "sctp6_input(): Packet of length %d received on %s with csum_flags 0x%x.\n", 113 m->m_pkthdr.len, 114 if_name(m->m_pkthdr.rcvif), 115 m->m_pkthdr.csum_flags); |
|
115 if (m->m_flags & M_FLOWID) { 116 mflowid = m->m_pkthdr.flowid; 117 use_mflowid = 1; 118 } else { 119 mflowid = 0; 120 use_mflowid = 0; 121 } 122 SCTP_STAT_INCR(sctps_recvpackets); 123 SCTP_STAT_INCR_COUNTER64(sctps_inpackets); 124 /* Get IP, SCTP, and first chunk header together in the first mbuf. */ | 116 if (m->m_flags & M_FLOWID) { 117 mflowid = m->m_pkthdr.flowid; 118 use_mflowid = 1; 119 } else { 120 mflowid = 0; 121 use_mflowid = 0; 122 } 123 SCTP_STAT_INCR(sctps_recvpackets); 124 SCTP_STAT_INCR_COUNTER64(sctps_inpackets); 125 /* Get IP, SCTP, and first chunk header together in the first mbuf. */ |
125 ip6 = mtod(m, struct ip6_hdr *); | |
126 offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); | 126 offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); |
127 ip6 = mtod(m, struct ip6_hdr *); |
|
127 IP6_EXTHDR_GET(sh, struct sctphdr *, m, iphlen, 128 (int)(sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr))); 129 if (sh == NULL) { 130 SCTP_STAT_INCR(sctps_hdrops); 131 return (IPPROTO_DONE); 132 } 133 ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr)); 134 offset -= sizeof(struct sctp_chunkhdr); 135 memset(&src, 0, sizeof(struct sockaddr_in6)); 136 src.sin6_family = AF_INET6; 137 src.sin6_len = sizeof(struct sockaddr_in6); 138 src.sin6_port = sh->src_port; 139 src.sin6_addr = ip6->ip6_src; 140 if (in6_setscope(&src.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) { | 128 IP6_EXTHDR_GET(sh, struct sctphdr *, m, iphlen, 129 (int)(sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr))); 130 if (sh == NULL) { 131 SCTP_STAT_INCR(sctps_hdrops); 132 return (IPPROTO_DONE); 133 } 134 ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr)); 135 offset -= sizeof(struct sctp_chunkhdr); 136 memset(&src, 0, sizeof(struct sockaddr_in6)); 137 src.sin6_family = AF_INET6; 138 src.sin6_len = sizeof(struct sockaddr_in6); 139 src.sin6_port = sh->src_port; 140 src.sin6_addr = ip6->ip6_src; 141 if (in6_setscope(&src.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) { |
141 goto bad; | 142 goto out; |
142 } 143 memset(&dst, 0, sizeof(struct sockaddr_in6)); 144 dst.sin6_family = AF_INET6; 145 dst.sin6_len = sizeof(struct sockaddr_in6); 146 dst.sin6_port = sh->dest_port; 147 dst.sin6_addr = ip6->ip6_dst; 148 if (in6_setscope(&dst.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) { | 143 } 144 memset(&dst, 0, sizeof(struct sockaddr_in6)); 145 dst.sin6_family = AF_INET6; 146 dst.sin6_len = sizeof(struct sockaddr_in6); 147 dst.sin6_port = sh->dest_port; 148 dst.sin6_addr = ip6->ip6_dst; 149 if (in6_setscope(&dst.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) { |
149 goto bad; | 150 goto out; |
150 } 151 if (faithprefix_p != NULL && (*faithprefix_p) (&dst.sin6_addr)) { 152 /* XXX send icmp6 host/port unreach? */ | 151 } 152 if (faithprefix_p != NULL && (*faithprefix_p) (&dst.sin6_addr)) { 153 /* XXX send icmp6 host/port unreach? */ |
153 goto bad; | 154 goto out; |
154 } 155 length = ntohs(ip6->ip6_plen) + iphlen; 156 /* Validate mbuf chain length with IP payload length. */ | 155 } 156 length = ntohs(ip6->ip6_plen) + iphlen; 157 /* Validate mbuf chain length with IP payload length. */ |
157 if (SCTP_HEADER_LEN(*i_pak) != length) { | 158 if (SCTP_HEADER_LEN(m) != length) { |
158 SCTPDBG(SCTP_DEBUG_INPUT1, | 159 SCTPDBG(SCTP_DEBUG_INPUT1, |
159 "sctp6_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(*i_pak)); | 160 "sctp6_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(m)); |
160 SCTP_STAT_INCR(sctps_hdrops); | 161 SCTP_STAT_INCR(sctps_hdrops); |
161 goto bad; | 162 goto out; |
162 } 163 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { | 163 } 164 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { |
164 goto bad; | 165 goto out; |
165 } | 166 } |
166 SCTPDBG(SCTP_DEBUG_INPUT1, 167 "sctp6_input() length:%d iphlen:%d\n", length, iphlen); 168 SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, 169 "sctp6_input(): Packet of length %d received on %s with csum_flags 0x%x.\n", 170 m->m_pkthdr.len, 171 if_name(m->m_pkthdr.rcvif), 172 m->m_pkthdr.csum_flags); | 167 ecn_bits = ((ntohl(ip6->ip6_flow) >> 20) & 0x000000ff); |
173#if defined(SCTP_WITH_NO_CSUM) 174 SCTP_STAT_INCR(sctps_recvnocrc); 175#else 176 if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) { 177 SCTP_STAT_INCR(sctps_recvhwcrc); | 168#if defined(SCTP_WITH_NO_CSUM) 169 SCTP_STAT_INCR(sctps_recvnocrc); 170#else 171 if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) { 172 SCTP_STAT_INCR(sctps_recvhwcrc); |
178 goto sctp_skip_csum; | 173 compute_crc = 0; 174 } else { 175 SCTP_STAT_INCR(sctps_recvswcrc); 176 compute_crc = 1; |
179 } | 177 } |
180 check = sh->checksum; 181 sh->checksum = 0; 182 calc_check = sctp_calculate_cksum(m, iphlen); 183 sh->checksum = check; 184 SCTP_STAT_INCR(sctps_recvswcrc); 185 if (calc_check != check) { 186 SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x m:%p mlen:%d iphlen:%d\n", 187 calc_check, check, m, length, iphlen); 188 stcb = sctp_findassociation_addr(m, offset, 189 (struct sockaddr *)&src, 190 (struct sockaddr *)&dst, 191 sh, ch, &inp, &net, vrf_id); 192 if ((net) && (port)) { 193 if (net->port == 0) { 194 sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); 195 } 196 net->port = port; 197 } 198 if ((net != NULL) && (use_mflowid != 0)) { 199 net->flowid = mflowid; 200#ifdef INVARIANTS 201 net->flowidset = 1; | |
202#endif | 178#endif |
203 } 204 if ((inp) && (stcb)) { 205 sctp_send_packet_dropped(stcb, net, m, length, iphlen, 1); 206 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED); 207 } else if ((inp != NULL) && (stcb == NULL)) { 208 refcount_up = 1; 209 } 210 SCTP_STAT_INCR(sctps_badsum); 211 SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors); 212 goto bad; 213 } 214sctp_skip_csum: 215#endif 216 /* destination port of 0 is illegal, based on RFC2960. */ 217 if (sh->dest_port == 0) { 218 SCTP_STAT_INCR(sctps_hdrops); 219 goto bad; 220 } 221 stcb = sctp_findassociation_addr(m, offset, 222 (struct sockaddr *)&src, 223 (struct sockaddr *)&dst, 224 sh, ch, &inp, &net, vrf_id); 225 if ((net) && (port)) { 226 if (net->port == 0) { 227 sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); 228 } 229 net->port = port; 230 } 231 if ((net != NULL) && (use_mflowid != 0)) { 232 net->flowid = mflowid; 233#ifdef INVARIANTS 234 net->flowidset = 1; 235#endif 236 } 237 if (inp == NULL) { 238 SCTP_STAT_INCR(sctps_noport); 239 if (badport_bandlim(BANDLIM_SCTP_OOTB) < 0) 240 goto bad; 241 if (ch->chunk_type == SCTP_SHUTDOWN_ACK) { 242 sctp_send_shutdown_complete2((struct sockaddr *)&src, 243 (struct sockaddr *)&dst, 244 sh, 245 use_mflowid, mflowid, 246 vrf_id, port); 247 goto bad; 248 } 249 if (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) { 250 goto bad; 251 } 252 if (ch->chunk_type != SCTP_ABORT_ASSOCIATION) { 253 if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) || 254 ((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) && 255 (ch->chunk_type != SCTP_INIT))) { 256 sctp_send_abort(m, iphlen, 257 (struct sockaddr *)&src, 258 (struct sockaddr *)&dst, 259 sh, 0, NULL, 260 use_mflowid, mflowid, 261 vrf_id, port); 262 } 263 } 264 goto bad; 265 } else if (stcb == NULL) { 266 refcount_up = 1; 267 } 268#ifdef IPSEC 269 /*- 270 * I very much doubt any of the IPSEC stuff will work but I have no 271 * idea, so I will leave it in place. 272 */ 273 if (inp && ipsec6_in_reject(m, &inp->ip_inp.inp)) { 274 MODULE_GLOBAL(ipsec6stat).in_polvio++; 275 SCTP_STAT_INCR(sctps_hdrops); 276 goto bad; 277 } 278#endif 279 280 ecn_bits = ((ntohl(ip6->ip6_flow) >> 20) & 0x000000ff); 281 /* sa_ignore NO_NULL_CHK */ | |
282 sctp_common_input_processing(&m, iphlen, offset, length, 283 (struct sockaddr *)&src, 284 (struct sockaddr *)&dst, | 179 sctp_common_input_processing(&m, iphlen, offset, length, 180 (struct sockaddr *)&src, 181 (struct sockaddr *)&dst, |
285 sh, ch, inp, stcb, net, ecn_bits, | 182 sh, ch, 183#if !defined(SCTP_WITH_NO_CSUM) 184 compute_crc, 185#endif 186 ecn_bits, |
286 use_mflowid, mflowid, 287 vrf_id, port); | 187 use_mflowid, mflowid, 188 vrf_id, port); |
189out: |
|
288 if (m) { 289 sctp_m_freem(m); 290 } | 190 if (m) { 191 sctp_m_freem(m); 192 } |
291 if ((inp) && (refcount_up)) { 292 /* reduce ref-count */ 293 SCTP_INP_WLOCK(inp); 294 SCTP_INP_DECR_REF(inp); 295 SCTP_INP_WUNLOCK(inp); 296 } | |
297 return (IPPROTO_DONE); | 193 return (IPPROTO_DONE); |
298bad: 299 if (stcb) { 300 SCTP_TCB_UNLOCK(stcb); 301 } 302 if ((inp) && (refcount_up)) { 303 /* reduce ref-count */ 304 SCTP_INP_WLOCK(inp); 305 SCTP_INP_DECR_REF(inp); 306 SCTP_INP_WUNLOCK(inp); 307 } 308 if (m) { 309 sctp_m_freem(m); 310 } 311 return (IPPROTO_DONE); | |
312} 313 314 315static void 316sctp6_notify_mbuf(struct sctp_inpcb *inp, struct icmp6_hdr *icmp6, 317 struct sctphdr *sh, struct sctp_tcb *stcb, struct sctp_nets *net) 318{ 319 uint32_t nxtsz; --- 1041 unchanged lines hidden --- | 194} 195 196 197static void 198sctp6_notify_mbuf(struct sctp_inpcb *inp, struct icmp6_hdr *icmp6, 199 struct sctphdr *sh, struct sctp_tcb *stcb, struct sctp_nets *net) 200{ 201 uint32_t nxtsz; --- 1041 unchanged lines hidden --- |