1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * Copyright 2012 David Hoeppner. All rights reserved.
29 */
30
31 #include <sys/types.h>
32 #include <sys/stream.h>
33 #include <sys/strsun.h>
34 #include <sys/strsubr.h>
35 #include <sys/stropts.h>
36 #include <sys/strlog.h>
37 #define _SUN_TPI_VERSION 2
38 #include <sys/tihdr.h>
39 #include <sys/suntpi.h>
40 #include <sys/xti_inet.h>
41 #include <sys/squeue_impl.h>
42 #include <sys/squeue.h>
43 #include <sys/tsol/tnet.h>
44
45 #include <inet/common.h>
46 #include <inet/dccp_impl.h>
47 #include <inet/ip.h>
48
49 #include <sys/cmn_err.h>
50
51 static mblk_t *dccp_conn_create_v4(conn_t *, conn_t *, mblk_t *,
52 ip_recv_attr_t *);
53 static mblk_t *dccp_conn_create_v6(conn_t *, conn_t *, mblk_t *,
54 ip_recv_attr_t *);
55 static void dccp_input_listener(void *, mblk_t *, void *, ip_recv_attr_t *);
56 static void dccp_icmp_error_ipv6(dccp_t *, mblk_t *, ip_recv_attr_t *);
57 static int dccp_check_input(conn_t *, mblk_t *, ip_recv_attr_t *);
58
59 void
60 dccp_icmp_input(void *arg1, mblk_t *mp, void *arg2, ip_recv_attr_t *ira)
61 {
62 conn_t *connp = (conn_t *)arg1;
63 dccp_t *dccp = connp->conn_dccp;
64 ipha_t *ipha;
65 icmph_t *icmph;
66 sin_t sin;
67 sin6_t sin6;
68 int iph_hdr_length;
69 int error;
70
71 cmn_err(CE_NOTE, "dccp_input.c: dccp_icmp_input");
72
73 ipha = (ipha_t *)mp->b_rptr;
74
75 /* Assume IP provides aligned packets */
76 ASSERT(OK_32PTR(mp->b_rptr));
77 ASSERT((MBLKL(mp) >= sizeof (ipha_t)));
78
79 if (dccp->dccp_state == DCCPS_CLOSED) {
80 freemsg(mp);
81 return;
82 }
83
84 /*
85 * Verify IP version. Anything other than IPv4 or IPv6 packet is sent
86 * upstream. ICMPv6 is handled in dccp_icmp_error_ipv6.
87 */
88 if (IPH_HDR_VERSION(ipha) != IPV4_VERSION) {
89 ASSERT(IPH_HDR_VERSION(ipha) == IPV6_VERSION);
90 dccp_icmp_error_ipv6(dccp, mp, ira);
91 return;
92 }
93 ASSERT(IPH_HDR_VERSION(ipha) == IPV4_VERSION);
94
95 ASSERT(IPH_HDR_LENGTH(ipha) == ira->ira_ip_hdr_length);
96 /* Skip past the outer IP and ICMP headers */
97 iph_hdr_length = ira->ira_ip_hdr_length;
98 icmph = (icmph_t *)&mp->b_rptr[iph_hdr_length];
99
100 switch (icmph->icmph_type) {
101 case ICMP_DEST_UNREACHABLE:
102 switch (icmph->icmph_code) {
103 case ICMP_FRAGMENTATION_NEEDED:
104 case ICMP_PORT_UNREACHABLE:
105 case ICMP_PROTOCOL_UNREACHABLE:
106 case ICMP_HOST_UNREACHABLE:
107 case ICMP_NET_UNREACHABLE:
108 break;
109 default:
110 break;
111 }
112 break;
113 case ICMP_SOURCE_QUENCH:
114 break;
115 }
116
117 freemsg(mp);
118 }
119
120 /*
121 * Handler for ICMPv6 error messages.
122 */
123 static void
124 dccp_icmp_error_ipv6(dccp_t *dccp, mblk_t *mp, ip_recv_attr_t *ira)
125 {
126 ip6_t *ip6h;
127 icmp6_t *icmp6;
128 uint16_t iph_hdr_length = ira->ira_ip_hdr_length;
129
130 cmn_err(CE_NOTE, "dccp_input.c: dccp_icmp_error_ipv6");
131
132 ASSERT((MBLKL(mp) >= sizeof (ip6_t)));
133
134 icmp6 = (icmp6_t *)&mp->b_rptr[iph_hdr_length];
135 ip6h = (ip6_t *)&icmp6[1];
136
137 }
138
139 void
140 dccp_rsrv(queue_t *q)
141 {
142 cmn_err(CE_NOTE, "dccp_input.c: dccp_rsrv");
143 }
144
145 /*
146 * Handle a REQUEST on an AF_INET6 socket; can be either IPv4 or IPv6.
147 */
148 static mblk_t *
149 dccp_conn_create_v6(conn_t *lconnp, conn_t *connp, mblk_t *mp,
150 ip_recv_attr_t *ira)
151 {
152 dccp_t *ldccp = lconnp->conn_dccp;
153 dccp_t *dccp = connp->conn_dccp;
154 dccp_stack_t *dccps = dccp->dccp_dccps;
155 ipha_t *ipha;
156 ip6_t *ip6h;
157 mblk_t *tpi_mp;
158 sin6_t sin6;
159 uint_t ifindex = ira->ira_ruifindex;
160
161 if (ira->ira_flags & IRAF_IS_IPV4) {
162 ipha = (ipha_t *)mp->b_rptr;
163
164 connp->conn_ipversion = IPV4_VERSION;
165 IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &connp->conn_laddr_v6);
166 IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &connp->conn_faddr_v6);
167 connp->conn_saddr_v6 = connp->conn_laddr_v6;
168
169 sin6 = sin6_null;
170 sin6.sin6_addr = connp->conn_faddr_v6;
171 sin6.sin6_port = connp->conn_fport;
172 sin6.sin6_family = AF_INET6;
173 sin6.__sin6_src_id = ip_srcid_find_addr(&connp->conn_laddr_v6,
174 IPCL_ZONEID(lconnp), dccps->dccps_netstack);
175
176 if (connp->conn_recv_ancillary.crb_recvdstaddr) {
177 sin6_t sin6d;
178
179 sin6d = sin6_null;
180 sin6d.sin6_addr = connp->conn_laddr_v6;
181 sin6d.sin6_port = connp->conn_lport;
182 sin6d.sin6_family = AF_INET;
183 tpi_mp = mi_tpi_extconn_ind(NULL,
184 (char *)&sin6d, sizeof (sin6_t),
185 (char *)&dccp,
186 (t_scalar_t)sizeof (intptr_t),
187 (char *)&sin6d, sizeof (sin6_t),
188 (t_scalar_t)ldccp->dccp_conn_req_seqnum);
189 } else {
190 tpi_mp = mi_tpi_conn_ind(NULL,
191 (char *)&sin6, sizeof (sin6_t),
192 (char *)&dccp, (t_scalar_t)sizeof (intptr_t),
193 (t_scalar_t)ldccp->dccp_conn_req_seqnum);
194 }
195 } else {
196 ip6h = (ip6_t *)mp->b_rptr;
197
198 connp->conn_ipversion = IPV6_VERSION;
199 connp->conn_laddr_v6 = ip6h->ip6_dst;
200 connp->conn_faddr_v6 = ip6h->ip6_src;
201 connp->conn_saddr_v6 = connp->conn_laddr_v6;
202
203 sin6 = sin6_null;
204 sin6.sin6_addr = connp->conn_faddr_v6;
205 sin6.sin6_port = connp->conn_fport;
206 sin6.sin6_family = AF_INET6;
207 sin6.sin6_flowinfo = ip6h->ip6_vcf & ~IPV6_VERS_AND_FLOW_MASK;
208 sin6.__sin6_src_id = ip_srcid_find_addr(&connp->conn_laddr_v6,
209 IPCL_ZONEID(lconnp), dccps->dccps_netstack);
210
211 if (IN6_IS_ADDR_LINKSCOPE(&ip6h->ip6_src)) {
212 /* Pass up the scope_id of remote addr */
213 sin6.sin6_scope_id = ifindex;
214 } else {
215 sin6.sin6_scope_id = 0;
216 }
217 if (connp->conn_recv_ancillary.crb_recvdstaddr) {
218 sin6_t sin6d;
219
220 sin6d = sin6_null;
221 sin6.sin6_addr = connp->conn_laddr_v6;
222 sin6d.sin6_port = connp->conn_lport;
223 sin6d.sin6_family = AF_INET6;
224 if (IN6_IS_ADDR_LINKSCOPE(&connp->conn_laddr_v6))
225 sin6d.sin6_scope_id = ifindex;
226
227 tpi_mp = mi_tpi_extconn_ind(NULL,
228 (char *)&sin6d, sizeof (sin6_t),
229 (char *)&dccp, (t_scalar_t)sizeof (intptr_t),
230 (char *)&sin6d, sizeof (sin6_t),
231 (t_scalar_t)ldccp->dccp_conn_req_seqnum);
232 } else {
233 tpi_mp = mi_tpi_conn_ind(NULL,
234 (char *)&sin6, sizeof (sin6_t),
235 (char *)&dccp, (t_scalar_t)sizeof (intptr_t),
236 (t_scalar_t)ldccp->dccp_conn_req_seqnum);
237 }
238 }
239
240 /* XXX mss */
241 return (tpi_mp);
242 }
243
244 /*
245 * Handle a REQUEST on an AF_INET socket.
246 */
247 static mblk_t *
248 dccp_conn_create_v4(conn_t *lconnp, conn_t *connp, mblk_t *mp,
249 ip_recv_attr_t *ira)
250 {
251 dccp_t *ldccp = lconnp->conn_dccp;
252 dccp_t *dccp = connp->conn_dccp;
253 dccp_stack_t *dccps = dccp->dccp_dccps;
254 ipha_t *ipha;
255 mblk_t *tpi_mp;
256 sin_t sin;
257
258 ASSERT(ira->ira_flags & IRAF_IS_IPV4);
259 ipha = (ipha_t *)mp->b_rptr;
260
261 connp->conn_ipversion = IPV4_VERSION;
262 IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &connp->conn_laddr_v6);
263 IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &connp->conn_faddr_v6);
264 connp->conn_saddr_v6 = connp->conn_laddr_v6;
265
266 sin = sin_null;
267 sin.sin_addr.s_addr = connp->conn_faddr_v4;
268 sin.sin_port = connp->conn_fport;
269 sin.sin_family = AF_INET;
270
271 if (lconnp->conn_recv_ancillary.crb_recvdstaddr) {
272 cmn_err(CE_NOTE, "ancillary");
273
274 sin_t sind;
275
276 sind = sin_null;
277 sind.sin_addr.s_addr = connp->conn_laddr_v4;
278 sind.sin_port = connp->conn_lport;
279 sind.sin_family = AF_INET;
280
281 tpi_mp = mi_tpi_extconn_ind(NULL,
282 (char *)&sind, sizeof (sin_t), (char *)&dccp,
283 (t_scalar_t)sizeof (intptr_t), (char *)&sind,
284 sizeof (sin_t), (t_scalar_t)ldccp->dccp_conn_req_seqnum);
285
286 } else {
287 tpi_mp = mi_tpi_conn_ind(NULL,
288 (char *)&sin, sizeof (sin_t),
289 (char *)&dccp, (t_scalar_t)sizeof (intptr_t),
290 (t_scalar_t)ldccp->dccp_conn_req_seqnum);
291 }
292
293 /* XXX mss */
294
295 return (tpi_mp);
296 }
297
298 static void
299 dccp_input_listener(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *ira)
300 {
301 conn_t *lconnp = (conn_t *)arg;
302 conn_t *econnp;
303 dccp_t *listener = lconnp->conn_dccp;
304 dccp_t *eager;
305 dccp_stack_t *dccps = listener->dccp_dccps;
306 ip_stack_t *ipst = dccps->dccps_netstack->netstack_ip;
307 dccpha_t *dccpha;
308 squeue_t *new_sqp;
309 mblk_t *tpi_mp;
310 mblk_t *mp1;
311 uint_t ifindex = ira->ira_ruifindex;
312 uint_t ip_hdr_len;
313 uint_t type;
314 int error;
315
316 cmn_err(CE_NOTE, "dccp_input.c: dccp_input_listener");
317
318 ip_hdr_len = ira->ira_ip_hdr_length;
319 dccpha = (dccpha_t *)&mp->b_rptr[ip_hdr_len];
320 type = (uint_t)dccpha->dha_type;
321
322 DTRACE_DCCP5(receive, mblk_t *, NULL, ip_xmit_attr_t *, lconnp->conn_ixa,
323 __dtrace_dccp_void_ip_t *, mp->b_rptr, dccp_t *, listener,
324 __dtrace_dccp_dccph_t *, dccpha);
325
326 dccp_check_input(lconnp, mp, ira);
327
328 if (type != DCCP_PKT_REQUEST) {
329 cmn_err(CE_NOTE, "--- not request pkt");
330 if (type != DCCP_PKT_RESET) {
331 /* XXX send Reset(No Connection) */
332 }
333
334 freemsg(mp);
335 return;
336 }
337
338 /* XXX memory pressure */
339
340 /* XXX request defense */
341
342 /* XXX number of connections per listener */
343
344 ASSERT(ira->ira_sqp != NULL);
345 new_sqp = ira->ira_sqp;
346
347 econnp = (conn_t *)dccp_get_conn(arg2, dccps);
348 if (econnp == NULL) {
349 cmn_err(CE_NOTE, "econnp not found (eager)");
350 goto error2;
351 }
352
353 ASSERT(econnp->conn_netstack == lconnp->conn_netstack);
354 econnp->conn_sqp = new_sqp;
355 econnp->conn_initial_sqp = new_sqp;
356 econnp->conn_ixa->ixa_sqp = new_sqp;
357
358 econnp->conn_fport = dccpha->dha_lport;
359 econnp->conn_lport = dccpha->dha_fport;
360
361 error = conn_inherit_parent(lconnp, econnp);
362 if (error != 0) {
363 cmn_err(CE_NOTE, "conn_inherit_parent failed");
364 goto error3;
365 }
366
367 /* We already know the laddr of the new connection is ours */
368 econnp->conn_ixa->ixa_src_generation = ipst->ips_src_generation;
369
370 ASSERT(OK_32PTR(mp->b_rptr));
371 ASSERT(IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION ||
372 IPH_HDR_VERSION(mp->b_rptr) == IPV6_VERSION);
373
374 if (lconnp->conn_family == AF_INET) {
375 ASSERT(IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION);
376 tpi_mp = dccp_conn_create_v4(lconnp, econnp, mp, ira);
377 } else {
378 tpi_mp = dccp_conn_create_v6(lconnp, econnp, mp, ira);
379 }
380
381 if (tpi_mp == NULL) {
382 cmn_err(CE_NOTE, "tpi_mo == NULL");
383 goto error3;
384 }
385
386 eager = econnp->conn_dccp;
387 SOCK_CONNID_INIT(eager->dccp_connid);
388
389 dccp_init_values(eager, listener);
390
391 ASSERT((econnp->conn_ixa->ixa_flags &
392 (IXAF_SET_ULP_CKSUM | IXAF_VERIFY_SOURCE |
393 IXAF_VERIFY_PMTU | IXAF_VERIFY_LSO)) ==
394 (IXAF_SET_ULP_CKSUM | IXAF_VERIFY_SOURCE |
395 IXAF_VERIFY_PMTU | IXAF_VERIFY_LSO));
396
397 if (!(ira->ira_flags & IRAF_IS_IPV4) && econnp->conn_bound_if == 0) {
398 if (IN6_IS_ADDR_LINKSCOPE(&econnp->conn_faddr_v6) ||
399 IN6_IS_ADDR_LINKSCOPE(&econnp->conn_laddr_v6)) {
400 econnp->conn_incoming_ifindex = ifindex;
401 econnp->conn_ixa->ixa_flags |= IXAF_SCOPEID_SET;
402 econnp->conn_ixa->ixa_scopeid = ifindex;
403 }
404 }
405
406 if (ira->ira_cred != NULL) {
407 mblk_setcred(tpi_mp, ira->ira_cred, ira->ira_cpid);
408 }
409
410 if (IPCL_IS_NONSTR(lconnp)) {
411 econnp->conn_flags |= IPCL_NONSTR;
412 }
413
414 /* XXX dccps is right? */
415 dccp_bind_hash_insert(&dccps->dccps_bind_fanout[
416 DCCP_BIND_HASH(econnp->conn_lport, dccps->dccps_bind_fanout_size)],
417 eager, 0);
418
419 /* XXX CLUSTER */
420
421 SOCK_CONNID_BUMP(eager->dccp_connid);
422
423 error = dccp_set_destination(eager);
424 if (error != 0) {
425 cmn_err(CE_NOTE, "dccp_set_destination failed.");
426 dccp_bind_hash_remove(eager);
427 goto error3;
428 }
429
430 /* Process all DCCP options */
431 dccp_process_options(eager, dccpha);
432
433 /* Eager lock */
434 CONN_INC_REF(lconnp);
435
436 /* Set tcp_listener before adding it to tcp_conn_fanout */
437 eager->dccp_listener = listener;
438 eager->dccp_saved_listener = listener;
439
440 eager->dccp_conn_req_seqnum = listener->dccp_conn_req_seqnum;
441 if (++listener->dccp_conn_req_seqnum == -1) {
442 /*
443 * -1 is "special" and defined in TPI as something
444 * that should never be used in T_CONN_IND
445 */
446 ++listener->dccp_conn_req_seqnum;
447 }
448
449 /* XXX SYN DEFENSE */
450
451 eager->dccp_state = DCCPS_RESPOND;
452 DTRACE_DCCP6(state__change, void, NULL, ip_xmit_attr_t *,
453 econnp->conn_ixa, void, NULL, dccp_t *, eager, void, NULL,
454 int32_t, DCCPS_LISTEN);
455
456 /* ISS was set in set_destionation */
457 eager->dccp_gar = eager->dccp_iss;
458
459 mp1 = dccp_generate_response(econnp, mp);
460 if (mp1 == NULL) {
461 cmn_err(CE_NOTE, "dccp_generate_packet failed");
462 /*
463 * Increment the ref count as we are going to
464 * enqueueing an mp in squeue
465 */
466 CONN_INC_REF(econnp);
467 goto error;
468 }
469
470 CONN_INC_REF(econnp);
471
472 error = ipcl_conn_insert(econnp);
473 if (error != 0) {
474 cmn_err(CE_NOTE, "ipcl_conn_insert(econnp) failed");
475 goto error;
476 }
477
478 ASSERT(econnp->conn_ixa->ixa_notify_cookie == econnp->conn_dccp);
479 freemsg(mp);
480
481 /*
482 * Send the RESPONSE. Use the right squeue so that conn_ixa is
483 * only used by one thread at a time.
484 */
485 if (econnp->conn_sqp == lconnp->conn_sqp) {
486 DTRACE_DCCP5(send, mblk_t *, NULL, ip_xmit_attr_t *,
487 econnp->conn_ixa, __dtrace_dccp_void_ip_t *, mp1->b_rptr,
488 dccp_t *, eager, __dtrace_dccp_dccph_t *,
489 &mp1->b_rptr[econnp->conn_ixa->ixa_ip_hdr_length]);
490 (void) conn_ip_output(mp1, econnp->conn_ixa);
491 CONN_DEC_REF(econnp);
492 } else {
493 SQUEUE_ENTER_ONE(econnp->conn_sqp, mp1, dccp_send_synack,
494 econnp, NULL, SQ_PROCESS, SQTAG_DCCP_SEND_RESPONSE);
495 }
496
497 return;
498 error:
499 freemsg(mp1);
500 error2:
501 CONN_DEC_REF(econnp);
502 error3:
503 freemsg(mp);
504 }
505
506 void
507 dccp_input_listener_unbound(void *arg, mblk_t *mp, void *arg2,
508 ip_recv_attr_t *ira)
509 {
510 conn_t *connp = (conn_t *)arg;
511 squeue_t *sqp = (squeue_t *)arg2;
512 squeue_t *new_sqp;
513 uint32_t conn_flags;
514
515 cmn_err(CE_NOTE, "dccp_input.c: dccp_input_listener_unbound");
516
517 ASSERT(ira->ira_sqp != NULL);
518 new_sqp = ira->ira_sqp;
519
520 if (connp->conn_fanout == NULL) {
521 goto done;
522 }
523
524 /*
525 * Bind to correct squeue.
526 */
527 if (!(connp->conn_flags & IPCL_FULLY_BOUND)) {
528 cmn_err(CE_NOTE, "not fully bound");
529
530 mutex_enter(&connp->conn_fanout->connf_lock);
531 mutex_enter(&connp->conn_lock);
532
533 if (connp->conn_ref != 4 ||
534 connp->conn_dccp->dccp_state != DCCPS_LISTEN) {
535 mutex_exit(&connp->conn_lock);
536 mutex_exit(&connp->conn_fanout->connf_lock);
537 goto done;
538 }
539
540 if (connp->conn_sqp != new_sqp) {
541 while (connp->conn_sqp != new_sqp) {
542 (void) casptr(&connp->conn_sqp, sqp, new_sqp);
543 }
544 connp->conn_ixa->ixa_sqp = new_sqp;
545 }
546
547 do {
548 conn_flags = connp->conn_flags;
549 conn_flags |= IPCL_FULLY_BOUND;
550 (void) cas32(&connp->conn_flags, connp->conn_flags,
551 conn_flags);
552 } while (!(connp->conn_flags & IPCL_FULLY_BOUND));
553
554 mutex_exit(&connp->conn_lock);
555 mutex_exit(&connp->conn_fanout->connf_lock);
556
557 connp->conn_recv = dccp_input_listener;
558 }
559
560 done:
561 if (connp->conn_sqp != sqp) {
562 CONN_INC_REF(connp);
563 SQUEUE_ENTER_ONE(connp->conn_sqp, mp, connp->conn_recv, connp,
564 ira, SQ_FILL, SQTAG_DCCP_CONN_REQ_UNBOUND);
565 } else {
566 dccp_input_listener(connp, mp, sqp, ira);
567 }
568 }
569
570 boolean_t
571 dccp_verifyicmp(conn_t *connp, void *arg2, icmph_t *icmph, icmp6_t *icmp6,
572 ip_recv_attr_t *ira)
573 {
574 cmn_err(CE_NOTE, "dccp_input.c: dccp_verifyicmp");
575
576 return (B_TRUE);
577 }
578
579 /*
580 * Basic sanity checks on all input packets.
581 */
582 static int
583 dccp_check_input(conn_t *connp, mblk_t *mp, ip_recv_attr_t *ira)
584 {
585 dccp_t *dccp = connp->conn_dccp;
586 dccpha_t *dccpha;
587 uint32_t size;
588 uint32_t pkt_size;
589 uint_t ip_hdr_len = ira->ira_ip_hdr_length;
590
591 cmn_err(CE_NOTE, "dccp_input.c: dccp_check_input");
592
593 size = msgdsize(mp) - (ip_hdr_len);
594 dccpha = (dccpha_t *)&mp->b_rptr[ip_hdr_len];
595 pkt_size = dccpha->dha_offset * 4;
596
597 /* Is packet shorter then 12 bytes? */
598 if (size < DCCP_MIN_HEADER_LENGTH) {
599 return (0);
600 }
601
602 /* Data offset is greater then the packet itself */
603 if (pkt_size > size) {
604 return (0);
605 }
606
607 /* Check if known packet type */
608 if (dccpha->dha_type > DCCP_PKT_SYNCACK) {
609 return (0);
610 }
611
612 /*
613 * Check data offset for this packet type and
614 * Data, Ack, or DataAck and P.X == 0
615 */
616 if (dccpha->dha_x == 0) {
617 switch (dccpha->dha_type) {
618 case DCCP_PKT_DATA:
619 if (size < 12 || pkt_size < 12)
620 return (0);
621 break;
622 case DCCP_PKT_ACK:
623 case DCCP_PKT_DATAACK:
624 if (size < 16 || pkt_size < 16)
625 return (0);
626 break;
627 default:
628 return (0);
629 }
630 } else {
631 switch (dccpha->dha_type) {
632 case DCCP_PKT_REQUEST:
633 if (size < 20 || pkt_size < 20)
634 return (0);
635 break;
636 case DCCP_PKT_RESPONSE:
637 case DCCP_PKT_RESET:
638 if (size < 28 || pkt_size < 28)
639 return (0);
640 break;
641 case DCCP_PKT_DATA:
642 if (size < 16 || pkt_size < 16)
643 return (0);
644 break;
645 case DCCP_PKT_ACK:
646 case DCCP_PKT_DATAACK:
647 case DCCP_PKT_CLOSEREQ:
648 case DCCP_PKT_CLOSE:
649 case DCCP_PKT_SYNC:
650 case DCCP_PKT_SYNCACK:
651 if (size < 24 || pkt_size < 24)
652 return (0);
653 break;
654 default:
655 return (0);
656 }
657 }
658
659 return (1);
660 }
661
662 /*
663 * After a request-response-ack all packets end up here.
664 */
665 void
666 dccp_input_data(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *ira)
667 {
668 conn_t *connp = (conn_t *)arg;
669 squeue_t *sqp = (squeue_t *)arg2;
670 dccp_t *dccp = connp->conn_dccp;
671 dccp_stack_t *dccps = dccp->dccp_dccps;
672 dccpha_t *dccpha;
673 dccpha_ack_t *dccpha_ack;
674 dccpha_ext_t *dccpha_ext;
675 mblk_t *mp1;
676 uint64_t seq_seq;
677 uint64_t seq_ack;
678 uchar_t *iphdr;
679 uchar_t *rptr;
680 sock_upcalls_t *sockupcalls;
681 ip_pkt_t ipp;
682 uint_t ip_hdr_len;
683 uint_t len;
684 int seg_len;
685 int pkt_len;
686 int hdr_length;
687
688 cmn_err(CE_NOTE, "dccp_input.c: dccp_input_data");
689
690 ASSERT(DB_TYPE(mp) == M_DATA);
691 ASSERT(mp->b_next == NULL);
692
693 iphdr = mp->b_rptr;
694 rptr = mp->b_rptr;
695 ASSERT(OK_32PTR(rptr));
696
697 /* Check basic packet characteristics */
698 if (dccp_check_input(connp, mp, ira) == 0) {
699 cmn_err(CE_NOTE, "reject packet");
700 return;
701 }
702
703 ip_hdr_len = ira->ira_ip_hdr_length;
704 if (connp->conn_recv_ancillary.crb_all != 0) {
705 /*
706 * Record packet information in the ip_pkt_t
707 */
708 ipp.ipp_fields = 0;
709 if (ira->ira_flags & IRAF_IS_IPV4) {
710 (void) ip_find_hdr_v4((ipha_t *)rptr, &ipp,
711 B_FALSE);
712 } else {
713 uint8_t nexthdrp;
714
715 /*
716 * IPv6 packets can only be received by applications
717 * that are prepared to receive IPv6 addresses.
718 * The IP fanout must ensure this.
719 */
720 ASSERT(connp->conn_family == AF_INET6);
721
722 (void) ip_find_hdr_v6(mp, (ip6_t *)rptr, B_TRUE, &ipp,
723 &nexthdrp);
724 ASSERT(nexthdrp == IPPROTO_DCCP);
725
726 /* Could have caused a pullup? */
727 iphdr = mp->b_rptr;
728 rptr = mp->b_rptr;
729 }
730 }
731
732 len = ip_hdr_len;
733 dccpha = (dccpha_t *)&rptr[len];
734
735 ASSERT((uintptr_t)(mp->b_wptr - rptr) <= (uintptr_t)INT_MAX);
736 seg_len = (int)(mp->b_wptr - rptr) -
737 (ip_hdr_len + DCCP_HDR_LENGTH(dccpha));
738 if ((mp1 = mp->b_cont) != NULL && mp1->b_datap->db_type == M_DATA) {
739 do {
740 ASSERT((uintptr_t)(mp1->b_wptr - mp1->b_rptr) <=
741 (uintptr_t)INT_MAX);
742 seg_len += (int)(mp1->b_wptr - mp1->b_rptr);
743 } while ((mp1 = mp1->b_cont) != NULL &&
744 mp1->b_datap->db_type == M_DATA);
745 }
746
747 DTRACE_DCCP5(receive, mblk_t *, NULL, ip_xmit_attr_t *, connp->conn_ixa,
748 __dtrace_dccp_void_ip_t *, iphdr, dccp_t *, dccp,
749 __dtrace_dccp_dccph_t *, dccpha);
750
751 BUMP_LOCAL(dccp->dccp_ibsegs);
752 DTRACE_PROBE2(dccp__trace__recv, mblk_t *, mp, dccp_t *, dccp);
753
754 sockupcalls = connp->conn_upcalls;
755
756 len += sizeof (dccpha_t);
757 dccpha_ext = (dccpha_ext_t *)&rptr[len];
758
759 /* XXX length checks */
760 if (dccpha->dha_x == 1) {
761 seq_seq = ntohs(dccpha->dha_seq);
762 seq_seq = seq_seq << 32;
763 seq_seq |= ntohl(dccpha_ext->dha_ext_seq);
764 } else {
765 /* XXX */
766 }
767
768 dccp->dccp_gsr = seq_seq;
769
770 switch (dccp->dccp_state) {
771 case DCCPS_REQUEST:
772 cmn_err(CE_NOTE, "DCCPS_REQUEST");
773 break;
774 case DCCPS_RESPOND:
775 cmn_err(CE_NOTE, "DCCPS_RESPOND");
776 break;
777 case DCCPS_PARTOPEN:
778 cmn_err(CE_NOTE, "DCCPS_PARTOPEN");
779 break;
780 case DCCPS_LISTEN:
781 cmn_err(CE_NOTE, "DCCPS_LISTEN");
782 break;
783 case DCCPS_BOUND:
784 cmn_err(CE_NOTE, "DCCPS_BOUND");
785 break;
786 case DCCPS_OPEN:
787 cmn_err(CE_NOTE, "DCCPS_OPEN");
788 break;
789 default:
790 cmn_err(CE_NOTE, "Unknow state");
791 break;
792 }
793
794 if (dccp->dccp_state == DCCPS_RESPOND) {
795 dccp->dccp_state = DCCPS_OPEN;
796 //dccp->dccp_osr = DCCP_SEQNO_GET(mp);
797
798 if (dccp->dccp_active_open) {
799 cmn_err(CE_NOTE, "dccp_active_open");
800 if (!dccp_conn_con(dccp, iphdr, mp, NULL, ira)) {
801 cmn_err(CE_NOTE, "dccp_conn_con failed");
802 freemsg(mp);
803 dccp->dccp_state = DCCPS_RESPOND;
804 return;
805 }
806
807 DTRACE_DCCP5(connect__established, mblk_t *, NULL,
808 ip_xmit_attr_t *, connp->conn_ixa, void_ip_t *,
809 iphdr, dccp_t *, dccp, dccph_t *, dccpha);
810 } else if (IPCL_IS_NONSTR(connp)) {
811 /*
812 * Passive open socket
813 */
814 cmn_err(CE_NOTE, "nonstr");
815
816 CONN_INC_REF(connp);
817
818 if (!dccp_newconn_notify(dccp, ira)) {
819 cmn_err(CE_NOTE, "dccp_newconn_notify failed");
820 dccp->dccp_state = DCCPS_RESPOND;
821 freemsg(mp);
822
823 CONN_DEC_REF(connp);
824 return;
825 }
826
827 /*
828 * dccp_newconn_notify() changes conn_upcalls.
829 */
830 if (connp->conn_upcalls != NULL) {
831 sockupcalls = connp->conn_upcalls;
832 }
833
834 DTRACE_DCCP5(accept__established, mlbk_t *, NULL,
835 ip_xmit_attr_t *, connp->conn_ixa, void_ip_t *,
836 iphdr, dccp_t *, dccp, dccph_t *, dccpha);
837 } else {
838 cmn_err(CE_NOTE, "str stream");
839 dccp_t *listener = dccp->dccp_listener;
840
841 ASSERT(mp != NULL);
842 CONN_INC_REF(connp);
843 }
844 }
845
846 switch (dccpha->dha_type) {
847 case DCCP_PKT_REQUEST:
848 cmn_err(CE_NOTE, "DCCP_REQUEST");
849 break;
850 case DCCP_PKT_RESPONSE:
851 cmn_err(CE_NOTE, "DCCP_RESPONSE");
852 break;
853 case DCCP_PKT_DATA:
854 cmn_err(CE_NOTE, "DCCP_DATA");
855 break;
856 case DCCP_PKT_ACK:
857 cmn_err(CE_NOTE, "DCCP_PKT_ACK");
858 break;
859 case DCCP_PKT_DATAACK:
860 cmn_err(CE_NOTE, "DCCP_DATAACK");
861 break;
862 case DCCP_PKT_CLOSEREQ:
863 cmn_err(CE_NOTE, "DCCP_CLOSEREQ");
864 break;
865 case DCCP_PKT_CLOSE:
866 cmn_err(CE_NOTE, "DCCP_CLOSE");
867 break;
868 case DCCP_PKT_RESET:
869 cmn_err(CE_NOTE, "DCCP_RESET");
870 break;
871 case DCCP_PKT_SYNC:
872 cmn_err(CE_NOTE, "DCCP_SYNC");
873 break;
874 case DCCP_PKT_SYNCACK:
875 cmn_err(CE_NOTE, "DCCP_SYNCACK");
876 break;
877 default:
878 break;
879 }
880
881 switch (dccpha->dha_type) {
882 case DCCP_PKT_ACK:
883 dccp->dccp_state = DCCPS_OPEN;
884 return;
885 case DCCP_PKT_DATAACK:
886 dccp->dccp_state = DCCPS_OPEN;
887 break;
888 case DCCP_PKT_CLOSE: {
889 mblk_t *reset_mp;
890
891 reset_mp = dccp_generate_reset(connp);
892 dccp_send_data(dccp, reset_mp);
893 dccp->dccp_state = DCCPS_CLOSED;
894 return;
895 }
896 default:
897 break;
898 }
899
900 hdr_length = ira->ira_ip_hdr_length;
901 hdr_length += DCCP_HDR_LENGTH(dccpha);
902 pkt_len = ira->ira_pktlen;
903
904 mp->b_wptr = rptr + pkt_len;
905 mp->b_rptr = (uchar_t *)&mp->b_rptr[hdr_length];
906 pkt_len -= hdr_length;
907
908 if (IPCL_IS_NONSTR(connp)) {
909 /*
910 * Non-STREAMS socket.
911 */
912 boolean_t push;
913 int error;
914
915 if ((*sockupcalls->su_recv)(connp->conn_upper_handle,
916 mp, pkt_len, 0, &error, NULL) <= 0) {
917 cmn_err(CE_NOTE, "su_recv failed");
918 ASSERT(error != EOPNOTSUPP);
919 }
920 } else if (dccp->dccp_listener != NULL) {
921 // dccp_recv_enqueue(dccp, mp, seq_len, ira->ira_cred);
922 } else {
923 /*
924 * Active-STREAMS socket.
925 */
926 }
927 }