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 dccpha_ext_t *dccpha_ext;
309 squeue_t *new_sqp;
310 mblk_t *tpi_mp;
311 mblk_t *mp1;
312 uint64_t seq;
313 uint_t ifindex = ira->ira_ruifindex;
314 uint_t ip_hdr_len;
315 uint_t type;
316 int error;
317
318 cmn_err(CE_NOTE, "dccp_input.c: dccp_input_listener");
319
320
321 DTRACE_DCCP5(receive, mblk_t *, NULL, ip_xmit_attr_t *, lconnp->conn_ixa,
322 __dtrace_dccp_void_ip_t *, mp->b_rptr, dccp_t *, listener,
323 __dtrace_dccp_dccph_t *, dccpha);
324
325 /* Basic checks on packet */
326 if (dccp_check_input(lconnp, mp, ira) == 0) {
327 cmn_err(CE_NOTE, "dccp_check_input failed.");
328 freemsg(mp);
329 return;
330 }
331
332 ip_hdr_len = ira->ira_ip_hdr_length;
333 dccpha = (dccpha_t *)&mp->b_rptr[ip_hdr_len];
334 dccpha_ext = (dccpha_ext_t *)&mp->b_rptr[ip_hdr_len + sizeof (dccpha_t)];
335 type = (uint_t)dccpha->dha_type;
336
337 if (type != DCCP_PKT_REQUEST) {
338 if (type != DCCP_PKT_RESET) {
339 listener->dccp_reset_code = DCCP_RESET_NO_CONNECTION;
340 dccp_xmit_listeners_reset(mp, ira, ipst, lconnp);
341 }
342
343 freemsg(mp);
344 return;
345 }
346
347 /* XXX memory pressure */
348
349 /* XXX request defense */
350
351 /* XXX number of connections per listener */
352
353 ASSERT(ira->ira_sqp != NULL);
354 new_sqp = ira->ira_sqp;
355
356 econnp = (conn_t *)dccp_get_conn(arg2, dccps);
357 if (econnp == NULL) {
358 cmn_err(CE_NOTE, "econnp not found (eager)");
359 goto error2;
360 }
361
362 ASSERT(econnp->conn_netstack == lconnp->conn_netstack);
363 econnp->conn_sqp = new_sqp;
364 econnp->conn_initial_sqp = new_sqp;
365 econnp->conn_ixa->ixa_sqp = new_sqp;
366
367 econnp->conn_fport = dccpha->dha_lport;
368 econnp->conn_lport = dccpha->dha_fport;
369
370 error = conn_inherit_parent(lconnp, econnp);
371 if (error != 0) {
372 cmn_err(CE_NOTE, "conn_inherit_parent failed");
373 goto error3;
374 }
375
376 /* We already know the laddr of the new connection is ours */
377 econnp->conn_ixa->ixa_src_generation = ipst->ips_src_generation;
378
379 ASSERT(OK_32PTR(mp->b_rptr));
380 ASSERT(IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION ||
381 IPH_HDR_VERSION(mp->b_rptr) == IPV6_VERSION);
382
383 if (lconnp->conn_family == AF_INET) {
384 ASSERT(IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION);
385 tpi_mp = dccp_conn_create_v4(lconnp, econnp, mp, ira);
386 } else {
387 tpi_mp = dccp_conn_create_v6(lconnp, econnp, mp, ira);
388 }
389
390 if (tpi_mp == NULL) {
391 cmn_err(CE_NOTE, "tpi_mo == NULL");
392 goto error3;
393 }
394
395 eager = econnp->conn_dccp;
396 SOCK_CONNID_INIT(eager->dccp_connid);
397
398 dccp_init_values(eager, listener);
399
400 ASSERT((econnp->conn_ixa->ixa_flags &
401 (IXAF_SET_ULP_CKSUM | IXAF_VERIFY_SOURCE |
402 IXAF_VERIFY_PMTU | IXAF_VERIFY_LSO)) ==
403 (IXAF_SET_ULP_CKSUM | IXAF_VERIFY_SOURCE |
404 IXAF_VERIFY_PMTU | IXAF_VERIFY_LSO));
405
406 if (!(ira->ira_flags & IRAF_IS_IPV4) && econnp->conn_bound_if == 0) {
407 if (IN6_IS_ADDR_LINKSCOPE(&econnp->conn_faddr_v6) ||
408 IN6_IS_ADDR_LINKSCOPE(&econnp->conn_laddr_v6)) {
409 econnp->conn_incoming_ifindex = ifindex;
410 econnp->conn_ixa->ixa_flags |= IXAF_SCOPEID_SET;
411 econnp->conn_ixa->ixa_scopeid = ifindex;
412 }
413 }
414
415 if (ira->ira_cred != NULL) {
416 mblk_setcred(tpi_mp, ira->ira_cred, ira->ira_cpid);
417 }
418
419 if (IPCL_IS_NONSTR(lconnp)) {
420 econnp->conn_flags |= IPCL_NONSTR;
421 }
422
423 /* XXX dccps is right? */
424 dccp_bind_hash_insert(&dccps->dccps_bind_fanout[
425 DCCP_BIND_HASH(econnp->conn_lport, dccps->dccps_bind_fanout_size)],
426 eager, 0);
427
428 /* XXX CLUSTER */
429
430 SOCK_CONNID_BUMP(eager->dccp_connid);
431
432 error = dccp_set_destination(eager);
433 if (error != 0) {
434 cmn_err(CE_NOTE, "dccp_set_destination failed.");
435 DCCPS_BUMP_MIB(dccps, dccpAttemptFails);
436 /* Undo the bind_hash_insert */
437 dccp_bind_hash_remove(eager);
438 goto error3;
439 }
440
441 /* Eager lock */
442 CONN_INC_REF(lconnp);
443
444 /* Set tcp_listener before adding it to tcp_conn_fanout */
445 eager->dccp_listener = listener;
446 eager->dccp_saved_listener = listener;
447
448 eager->dccp_conn_req_seqnum = listener->dccp_conn_req_seqnum;
449 if (++listener->dccp_conn_req_seqnum == -1) {
450 /*
451 * -1 is "special" and defined in TPI as something
452 * that should never be used in T_CONN_IND
453 */
454 ++listener->dccp_conn_req_seqnum;
455 }
456
457 /* XXX SYN DEFENSE */
458
459 seq = ntohs(dccpha->dha_seq);
460 seq = seq << 32;
461 seq |= ntohl(dccpha_ext->dha_ext_seq);
462
463 /* ISS was set in set_destination */
464 eager->dccp_gar = eager->dccp_iss;
465 eager->dccp_gsr = seq;
466 eager->dccp_osr = seq;
467
468 /* Process all DCCP options */
469 error = dccp_process_options(eager, dccpha);
470 if (error != 0) {
471 cmn_err(CE_NOTE, "dccp_process_options failed.");
472 mp1 = dccp_generate_reset(econnp);
473 eager->dccp_state = DCCPS_CLOSED;
474 if (mp1 == NULL) {
475 cmn_err(CE_NOTE, "dccp_generate_reset failed.");
476 goto error;
477 }
478
479 ip_xmit_attr_t *ixa = econnp->conn_ixa;
480
481 ixa->ixa_pktlen = msgdsize(mp1);
482 (void) conn_ip_output(mp1, ixa);
483
484 return;
485 }
486
487 eager->dccp_state = DCCPS_RESPOND;
488 DTRACE_DCCP6(state__change, void, NULL, ip_xmit_attr_t *,
489 econnp->conn_ixa, void, NULL, dccp_t *, eager, void, NULL,
490 int32_t, DCCPS_LISTEN);
491
492 mp1 = dccp_generate_response(econnp, mp);
493 if (mp1 == NULL) {
494 cmn_err(CE_NOTE, "dccp_generate_packet failed");
495 /*
496 * Increment the ref count as we are going to
497 * enqueueing an mp in squeue
498 */
499 CONN_INC_REF(econnp);
500 goto error;
501 }
502
503 CONN_INC_REF(econnp);
504
505 error = ipcl_conn_insert(econnp);
506 if (error != 0) {
507 cmn_err(CE_NOTE, "ipcl_conn_insert(econnp) failed");
508 goto error;
509 }
510
511 ASSERT(econnp->conn_ixa->ixa_notify_cookie == econnp->conn_dccp);
512 freemsg(mp);
513
514 /*
515 * Send the RESPONSE. Use the right squeue so that conn_ixa is
516 * only used by one thread at a time.
517 */
518 if (econnp->conn_sqp == lconnp->conn_sqp) {
519 DTRACE_DCCP5(send, mblk_t *, NULL, ip_xmit_attr_t *,
520 econnp->conn_ixa, __dtrace_dccp_void_ip_t *, mp1->b_rptr,
521 dccp_t *, eager, __dtrace_dccp_dccph_t *,
522 &mp1->b_rptr[econnp->conn_ixa->ixa_ip_hdr_length]);
523 (void) conn_ip_output(mp1, econnp->conn_ixa);
524 CONN_DEC_REF(econnp);
525 } else {
526 SQUEUE_ENTER_ONE(econnp->conn_sqp, mp1, dccp_send_synack,
527 econnp, NULL, SQ_PROCESS, SQTAG_DCCP_SEND_RESPONSE);
528 }
529
530 return;
531 error:
532 freemsg(mp1);
533 error2:
534 CONN_DEC_REF(econnp);
535 error3:
536 freemsg(mp);
537 }
538
539 void
540 dccp_input_listener_unbound(void *arg, mblk_t *mp, void *arg2,
541 ip_recv_attr_t *ira)
542 {
543 conn_t *connp = (conn_t *)arg;
544 squeue_t *sqp = (squeue_t *)arg2;
545 squeue_t *new_sqp;
546 uint32_t conn_flags;
547
548 cmn_err(CE_NOTE, "dccp_input.c: dccp_input_listener_unbound");
549
550 ASSERT(ira->ira_sqp != NULL);
551 new_sqp = ira->ira_sqp;
552
553 if (connp->conn_fanout == NULL) {
554 goto done;
555 }
556
557 /*
558 * Bind to correct squeue.
559 */
560 if (!(connp->conn_flags & IPCL_FULLY_BOUND)) {
561 cmn_err(CE_NOTE, "not fully bound");
562
563 mutex_enter(&connp->conn_fanout->connf_lock);
564 mutex_enter(&connp->conn_lock);
565
566 if (connp->conn_ref != 4 ||
567 connp->conn_dccp->dccp_state != DCCPS_LISTEN) {
568 mutex_exit(&connp->conn_lock);
569 mutex_exit(&connp->conn_fanout->connf_lock);
570 goto done;
571 }
572
573 if (connp->conn_sqp != new_sqp) {
574 while (connp->conn_sqp != new_sqp) {
575 (void) casptr(&connp->conn_sqp, sqp, new_sqp);
576 }
577 connp->conn_ixa->ixa_sqp = new_sqp;
578 }
579
580 do {
581 conn_flags = connp->conn_flags;
582 conn_flags |= IPCL_FULLY_BOUND;
583 (void) cas32(&connp->conn_flags, connp->conn_flags,
584 conn_flags);
585 } while (!(connp->conn_flags & IPCL_FULLY_BOUND));
586
587 mutex_exit(&connp->conn_lock);
588 mutex_exit(&connp->conn_fanout->connf_lock);
589
590 connp->conn_recv = dccp_input_listener;
591 }
592
593 done:
594 if (connp->conn_sqp != sqp) {
595 CONN_INC_REF(connp);
596 SQUEUE_ENTER_ONE(connp->conn_sqp, mp, connp->conn_recv, connp,
597 ira, SQ_FILL, SQTAG_DCCP_CONN_REQ_UNBOUND);
598 } else {
599 dccp_input_listener(connp, mp, sqp, ira);
600 }
601 }
602
603 boolean_t
604 dccp_verifyicmp(conn_t *connp, void *arg2, icmph_t *icmph, icmp6_t *icmp6,
605 ip_recv_attr_t *ira)
606 {
607 cmn_err(CE_NOTE, "dccp_input.c: dccp_verifyicmp");
608
609 return (B_TRUE);
610 }
611
612 /*
613 * Basic sanity checks on all input packets.
614 */
615 static int
616 dccp_check_input(conn_t *connp, mblk_t *mp, ip_recv_attr_t *ira)
617 {
618 dccp_t *dccp = connp->conn_dccp;
619 dccpha_t *dccpha;
620 uint32_t size;
621 uint32_t offset_size;
622 uint_t ip_hdr_len = ira->ira_ip_hdr_length;
623
624 cmn_err(CE_NOTE, "dccp_input.c: dccp_check_input");
625
626 size = msgdsize(mp) - (ip_hdr_len);
627 dccpha = (dccpha_t *)&mp->b_rptr[ip_hdr_len];
628 offset_size = dccpha->dha_offset * 4;
629
630 cmn_err(CE_NOTE, "size: %d", size);
631 cmn_err(CE_NOTE, "offset_size: %d", offset_size);
632
633 /* Is packet shorter then 12 bytes? */
634 if (size < DCCP_MIN_HEADER_LENGTH) {
635 cmn_err(CE_NOTE, "header < 12");
636 return (0);
637 }
638
639 /* Data offset is greater then the packet itself */
640 if (offset_size > size) {
641 cmn_err(CE_NOTE, "offset > size");
642 return (0);
643 }
644
645 /* Check if known packet type */
646 if (dccpha->dha_type > DCCP_PKT_SYNCACK) {
647 cmn_err(CE_NOTE, "type unknown");
648 return (0);
649 }
650
651 /*
652 * Check data offset for this packet type and
653 * Data, Ack, or DataAck and P.X == 0
654 */
655 if (dccpha->dha_x == 0) {
656 switch (dccpha->dha_type) {
657 case DCCP_PKT_DATA:
658 if (size < 12 || offset_size < 12)
659 return (0);
660 break;
661 case DCCP_PKT_ACK:
662 case DCCP_PKT_DATAACK:
663 if (size < 16 || offset_size < 16)
664 return (0);
665 break;
666 default:
667 return (0);
668 }
669 } else {
670 switch (dccpha->dha_type) {
671 case DCCP_PKT_REQUEST:
672 if (size < 20 || offset_size < 20)
673 return (0);
674 break;
675 case DCCP_PKT_RESPONSE:
676 case DCCP_PKT_RESET:
677 if (size < 28 || offset_size < 28)
678 return (0);
679 break;
680 case DCCP_PKT_DATA:
681 if (size < 16 || offset_size < 16)
682 return (0);
683 break;
684 case DCCP_PKT_ACK:
685 case DCCP_PKT_DATAACK:
686 case DCCP_PKT_CLOSEREQ:
687 case DCCP_PKT_CLOSE:
688 case DCCP_PKT_SYNC:
689 case DCCP_PKT_SYNCACK:
690 if (size < 24 || offset_size < 24)
691 return (0);
692 break;
693 default:
694 return (0);
695 }
696 }
697
698 /* Checksum coverage check */
699 if (dccpha->dha_cscov != 0 && ((dccpha->dha_offset +
700 dccpha->dha_cscov - 1) * 4) > size) {
701 cmn_err(CE_NOTE, "cscov too large");
702 return (0);
703 }
704
705 return (1);
706 }
707
708 /*
709 * After a request-response-ack all packets end up here.
710 */
711 void
712 dccp_input_data(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *ira)
713 {
714 conn_t *connp = (conn_t *)arg;
715 squeue_t *sqp = (squeue_t *)arg2;
716 dccp_t *dccp = connp->conn_dccp;
717 dccp_stack_t *dccps = dccp->dccp_dccps;
718 dccpha_t *dccpha;
719 dccpha_ack_t *dccpha_ack;
720 dccpha_ext_t *dccpha_ext;
721 mblk_t *mp1;
722 uint64_t seq_seq;
723 uint64_t seq_ack;
724 uchar_t *iphdr;
725 uchar_t *rptr;
726 sock_upcalls_t *sockupcalls;
727 ip_pkt_t ipp;
728 uint_t ip_hdr_len;
729 uint_t len;
730 int seg_len;
731 int pkt_len;
732 int hdr_length;
733 int error;
734
735 cmn_err(CE_NOTE, "dccp_input.c: dccp_input_data");
736
737 ASSERT(DB_TYPE(mp) == M_DATA);
738 ASSERT(mp->b_next == NULL);
739
740 iphdr = mp->b_rptr;
741 rptr = mp->b_rptr;
742 ASSERT(OK_32PTR(rptr));
743
744 /* Check basic characteristics */
745 if (dccp_check_input(connp, mp, ira) == 0) {
746 cmn_err(CE_NOTE, "rejected packet");
747 return;
748 }
749
750 ip_hdr_len = ira->ira_ip_hdr_length;
751 if (connp->conn_recv_ancillary.crb_all != 0) {
752 /*
753 * Record packet information in the ip_pkt_t
754 */
755 ipp.ipp_fields = 0;
756 if (ira->ira_flags & IRAF_IS_IPV4) {
757 (void) ip_find_hdr_v4((ipha_t *)rptr, &ipp,
758 B_FALSE);
759 } else {
760 uint8_t nexthdrp;
761
762 /*
763 * IPv6 packets can only be received by applications
764 * that are prepared to receive IPv6 addresses.
765 * The IP fanout must ensure this.
766 */
767 ASSERT(connp->conn_family == AF_INET6);
768
769 (void) ip_find_hdr_v6(mp, (ip6_t *)rptr, B_TRUE, &ipp,
770 &nexthdrp);
771 ASSERT(nexthdrp == IPPROTO_DCCP);
772
773 /* Could have caused a pullup? */
774 iphdr = mp->b_rptr;
775 rptr = mp->b_rptr;
776 }
777 }
778
779 len = ip_hdr_len;
780 dccpha = (dccpha_t *)&rptr[len];
781
782 ASSERT((uintptr_t)(mp->b_wptr - rptr) <= (uintptr_t)INT_MAX);
783 seg_len = (int)(mp->b_wptr - rptr) -
784 (ip_hdr_len + DCCP_HDR_LENGTH(dccpha));
785 if ((mp1 = mp->b_cont) != NULL && mp1->b_datap->db_type == M_DATA) {
786 do {
787 ASSERT((uintptr_t)(mp1->b_wptr - mp1->b_rptr) <=
788 (uintptr_t)INT_MAX);
789 seg_len += (int)(mp1->b_wptr - mp1->b_rptr);
790 } while ((mp1 = mp1->b_cont) != NULL &&
791 mp1->b_datap->db_type == M_DATA);
792 }
793
794 DTRACE_DCCP5(receive, mblk_t *, NULL, ip_xmit_attr_t *, connp->conn_ixa,
795 __dtrace_dccp_void_ip_t *, iphdr, dccp_t *, dccp,
796 __dtrace_dccp_dccph_t *, dccpha);
797
798 if (sqp != NULL) {
799 dccp->dccp_last_recv_time = LBOLT_FASTPATH;
800 }
801
802 BUMP_LOCAL(dccp->dccp_ibsegs);
803 DTRACE_PROBE2(dccp__trace__recv, mblk_t *, mp, dccp_t *, dccp);
804
805 sockupcalls = connp->conn_upcalls;
806
807 len += sizeof (dccpha_t);
808 dccpha_ext = (dccpha_ext_t *)&rptr[len];
809
810 /*
811 * Sequence number.
812 */
813 if (dccpha->dha_x == 1) {
814 seq_seq = ntohs(dccpha->dha_seq);
815 seq_seq = seq_seq << 32;
816 seq_seq |= ntohl(dccpha_ext->dha_ext_seq);
817 } else {
818 /* XXX */
819 }
820
821 dccp->dccp_gsr = seq_seq;
822
823 /*
824 * Acknowledgement Number.
825 */
826 if (dccpha->dha_type != DCCP_PKT_DATA) {
827 dccpha_ack = (dccpha_ack_t *)&rptr[ip_hdr_len +
828 sizeof (dccpha_t) + sizeof (dccpha_ext_t)];
829 seq_ack = ntohs(dccpha_ack->dha_ack_high);
830 seq_ack = seq_ack << 32;
831 seq_ack |= ntohl(dccpha_ack->dha_ack_low);
832
833 dccp->dccp_gar = seq_ack;
834 }
835
836
837 switch (dccp->dccp_state) {
838 case DCCPS_REQUEST:
839 cmn_err(CE_NOTE, "DCCPS_REQUEST");
840 break;
841 case DCCPS_RESPOND:
842 cmn_err(CE_NOTE, "DCCPS_RESPOND");
843 break;
844 case DCCPS_PARTOPEN:
845 cmn_err(CE_NOTE, "DCCPS_PARTOPEN");
846 break;
847 case DCCPS_LISTEN:
848 cmn_err(CE_NOTE, "DCCPS_LISTEN");
849 break;
850 case DCCPS_BOUND:
851 cmn_err(CE_NOTE, "DCCPS_BOUND");
852 break;
853 case DCCPS_OPEN:
854 cmn_err(CE_NOTE, "DCCPS_OPEN");
855 break;
856 default:
857 cmn_err(CE_NOTE, "Unknow state");
858 break;
859 }
860
861 /*
862 * Check for unexpected packet types.
863 */
864 if ((dccp->dccp_active_open == B_FALSE &&
865 (dccpha->dha_type == DCCP_PKT_RESPONSE ||
866 dccpha->dha_type == DCCP_PKT_CLOSEREQ)) ||
867 (dccp->dccp_state >= DCCPS_OPEN &&
868 (dccpha->dha_type == DCCP_PACKET_REQUEST ||
869 dccpha->dha_type == DCCP_PACKET_RESPONSE) &&
870 seq_seq >= dccp->dccp_osr) ||
871 (dccp->dccp_state == DCCPS_RESPOND &&
872 dccpha->dha_type == DCCP_PACKET_DATA)) {
873 mblk_t *sync_mp;
874
875 sync_mp = dccp_generate_sync(connp);
876 if (sync_mp != NULL)
877 dccp_send_data(dccp, sync_mp);
878 return;
879 }
880
881 /*
882 * Process options.
883 */
884 error = dccp_process_options(dccp, dccpha);
885 if (error != 0) {
886 mblk_t *reset_mp;
887
888 cmn_err(CE_NOTE, "dccp_process_options failed.");
889
890 reset_mp = dccp_generate_reset(connp);
891 dccp->dccp_state = DCCPS_CLOSED;
892 if (reset_mp != NULL) {
893 ip_xmit_attr_t *ixa = connp->conn_ixa;
894
895 ixa->ixa_pktlen = msgdsize(reset_mp);
896 (void) conn_ip_output(reset_mp, ixa);
897 }
898
899 return;
900 }
901
902 if (dccp->dccp_state == DCCPS_RESPOND) {
903 dccp->dccp_state = DCCPS_OPEN;
904 //dccp->dccp_osr = DCCP_SEQNO_GET(mp);
905
906 if (dccp->dccp_active_open) {
907 cmn_err(CE_NOTE, "dccp_active_open");
908 if (!dccp_conn_con(dccp, iphdr, mp, NULL, ira)) {
909 cmn_err(CE_NOTE, "dccp_conn_con failed");
910 freemsg(mp);
911 dccp->dccp_state = DCCPS_RESPOND;
912 return;
913 }
914
915 DTRACE_DCCP5(connect__established, mblk_t *, NULL,
916 ip_xmit_attr_t *, connp->conn_ixa, void_ip_t *,
917 iphdr, dccp_t *, dccp, dccph_t *, dccpha);
918 } else if (IPCL_IS_NONSTR(connp)) {
919 /*
920 * Passive open socket
921 */
922 cmn_err(CE_NOTE, "nonstr");
923
924 CONN_INC_REF(connp);
925
926 if (!dccp_newconn_notify(dccp, ira)) {
927 cmn_err(CE_NOTE, "dccp_newconn_notify failed");
928 dccp->dccp_state = DCCPS_RESPOND;
929 freemsg(mp);
930
931 CONN_DEC_REF(connp);
932 return;
933 }
934
935 /*
936 * dccp_newconn_notify() changes conn_upcalls.
937 */
938 if (connp->conn_upcalls != NULL) {
939 sockupcalls = connp->conn_upcalls;
940 }
941
942 DTRACE_DCCP5(accept__established, mlbk_t *, NULL,
943 ip_xmit_attr_t *, connp->conn_ixa, void_ip_t *,
944 iphdr, dccp_t *, dccp, dccph_t *, dccpha);
945 } else {
946 cmn_err(CE_NOTE, "str stream");
947 dccp_t *listener = dccp->dccp_listener;
948
949 ASSERT(mp != NULL);
950 CONN_INC_REF(connp);
951 }
952 }
953
954 switch (dccpha->dha_type) {
955 case DCCP_PKT_REQUEST:
956 cmn_err(CE_NOTE, "DCCP_REQUEST");
957 break;
958 case DCCP_PKT_RESPONSE:
959 cmn_err(CE_NOTE, "DCCP_RESPONSE");
960 break;
961 case DCCP_PKT_DATA:
962 cmn_err(CE_NOTE, "DCCP_DATA");
963 break;
964 case DCCP_PKT_ACK:
965 cmn_err(CE_NOTE, "DCCP_PKT_ACK");
966 break;
967 case DCCP_PKT_DATAACK:
968 cmn_err(CE_NOTE, "DCCP_DATAACK");
969 break;
970 case DCCP_PKT_CLOSEREQ:
971 cmn_err(CE_NOTE, "DCCP_CLOSEREQ");
972 break;
973 case DCCP_PKT_CLOSE:
974 cmn_err(CE_NOTE, "DCCP_CLOSE");
975 break;
976 case DCCP_PKT_RESET:
977 cmn_err(CE_NOTE, "DCCP_RESET");
978 break;
979 case DCCP_PKT_SYNC:
980 cmn_err(CE_NOTE, "DCCP_SYNC");
981 break;
982 case DCCP_PKT_SYNCACK:
983 cmn_err(CE_NOTE, "DCCP_SYNCACK");
984 break;
985 default:
986 break;
987 }
988
989 switch (dccpha->dha_type) {
990 /* case DCCP_PKT_ACK: { */
991 case DCCP_PKT_DATAACK: {
992 mblk_t *ack_mp;
993
994 ack_mp = dccp_generate_ack(connp);
995 if (ack_mp != NULL)
996 dccp_send_data(dccp, ack_mp);
997
998 dccp->dccp_state = DCCPS_OPEN;
999 return;
1000 }
1001 case DCCP_PKT_CLOSE: {
1002 mblk_t *reset_mp;
1003
1004 dccp->dccp_reset_code = DCCP_RESET_CLOSED;
1005 dccp->dccp_reset_data[0] = 0;
1006 dccp->dccp_reset_data[1] = 0;
1007 dccp->dccp_reset_data[2] = 0;
1008 reset_mp = dccp_generate_reset(connp);
1009 dccp_send_data(dccp, reset_mp);
1010 dccp->dccp_state = DCCPS_CLOSED;
1011 return;
1012 }
1013 default:
1014 break;
1015 }
1016
1017 hdr_length = ira->ira_ip_hdr_length;
1018 hdr_length += DCCP_HDR_LENGTH(dccpha);
1019 pkt_len = ira->ira_pktlen;
1020
1021 mp->b_wptr = rptr + pkt_len;
1022 mp->b_rptr = (uchar_t *)&mp->b_rptr[hdr_length];
1023 pkt_len -= hdr_length;
1024
1025 if (IPCL_IS_NONSTR(connp)) {
1026 /*
1027 * Non-STREAMS socket.
1028 */
1029 boolean_t push;
1030 int error;
1031
1032 if ((*sockupcalls->su_recv)(connp->conn_upper_handle,
1033 mp, pkt_len, 0, &error, NULL) <= 0) {
1034 cmn_err(CE_NOTE, "su_recv failed");
1035 ASSERT(error != EOPNOTSUPP);
1036 }
1037 } else if (dccp->dccp_listener != NULL) {
1038 // dccp_recv_enqueue(dccp, mp, seq_len, ira->ira_cred);
1039 } else {
1040 /*
1041 * Active-STREAMS socket.
1042 */
1043 }
1044 }