Deleted Added
full compact
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 ---