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 /*
32 * This file contains all DCCP kernel socket related functions.
33 */
34
35 #include <sys/types.h>
36 #include <sys/strlog.h>
37 #include <sys/policy.h>
38 #include <sys/sockio.h>
39 #include <sys/strsubr.h>
40 #include <sys/strsun.h>
41 #define _SUN_TPI_VERSION 2
42 #include <sys/tihdr.h>
43 #include <sys/timod.h>
44 #include <sys/squeue_impl.h>
45 #include <sys/squeue.h>
46 #include <sys/socketvar.h>
47
48 #include <inet/common.h>
49 #include <inet/dccp_impl.h>
50 #include <inet/dccp_stack.h>
51 #include <inet/proto_set.h>
52 #include <inet/ip.h>
53
54 #include <sys/cmn_err.h>
55
56 static void dccp_activate(sock_lower_handle_t, sock_upper_handle_t,
57 sock_upcalls_t *, int, cred_t *);
58 static int dccp_accept(sock_lower_handle_t, sock_lower_handle_t,
59 sock_upper_handle_t, cred_t *);
60 static int dccp_bind(sock_lower_handle_t, struct sockaddr *,
61 socklen_t, cred_t *);
62 static int dccp_listen(sock_lower_handle_t, int, cred_t *);
63 static int dccp_connect(sock_lower_handle_t, const struct sockaddr *,
64 socklen_t, sock_connid_t *, cred_t *);
65 static int dccp_getpeername(sock_lower_handle_t, struct sockaddr *,
66 socklen_t *, cred_t *);
67 static int dccp_getsockname(sock_lower_handle_t, struct sockaddr *,
68 socklen_t *, cred_t *);
69 static int dccp_getsockopt(sock_lower_handle_t, int, int, void *,
70 socklen_t *, cred_t *);
71 static int dccp_setsockopt(sock_lower_handle_t, int, int, const void *,
72 socklen_t, cred_t *);
73 static int dccp_send(sock_lower_handle_t, mblk_t *, struct nmsghdr *,
74 cred_t *);
75 static int dccp_shutdown(sock_lower_handle_t, int, cred_t *);
76 static void dccp_clr_flowctrl(sock_lower_handle_t);
77 static int dccp_ioctl(sock_lower_handle_t, int, intptr_t, int, int32_t *,
78 cred_t *);
79 static int dccp_close(sock_lower_handle_t, int, cred_t *);
80
81 sock_downcalls_t sock_dccp_downcalls = {
82 dccp_activate, /* sd_activate */
83 dccp_accept, /* sd_accept */
84 dccp_bind, /* sd_bind */
85 dccp_listen, /* sd_listen */
86 dccp_connect, /* sd_connect */
87 dccp_getpeername, /* sd_getpeername */
88 dccp_getsockname, /* sd_getsockname */
89 dccp_getsockopt, /* sd_getsockopt */
90 dccp_setsockopt, /* sd_setsockopt */
91 dccp_send, /* sd_send */
92 NULL, /* sd_send_uio */
93 NULL, /* sd_recv_uio */
94 NULL, /* sd_poll */
95 dccp_shutdown, /* sd_shutdown */
96 dccp_clr_flowctrl, /* sd_setflowctrl */
97 dccp_ioctl, /* sd_ioctl */
98 dccp_close, /* sd_close */
99 };
100
101 /* ARGSUSED */
102 static void
103 dccp_activate(sock_lower_handle_t proto_handle, sock_upper_handle_t sock_handle,
104 sock_upcalls_t *sock_upcalls, int flags, cred_t *cr)
105 {
106 conn_t *connp = (conn_t *)proto_handle;
107 struct sock_proto_props sopp;
108 extern struct module_info dccp_rinfo;
109
110 cmn_err(CE_NOTE, "dccp_socket.c: dccp_activate");
111
112 ASSERT(connp->conn_upper_handle == NULL);
113
114 /* All Solaris components should pass a cred for this operation */
115 ASSERT(cr != NULL);
116
117 sopp.sopp_flags = SOCKOPT_RCVHIWAT | SOCKOPT_RCVLOWAT |
118 SOCKOPT_MAXPSZ | SOCKOPT_MAXBLK | SOCKOPT_RCVTIMER |
119 SOCKOPT_RCVTHRESH | SOCKOPT_MAXADDRLEN | SOCKOPT_MINPSZ;
120
121 sopp.sopp_rxhiwat = SOCKET_RECVHIWATER;
122 sopp.sopp_rxlowat = SOCKET_RECVLOWATER;
123 sopp.sopp_maxpsz = INFPSZ;
124 sopp.sopp_maxblk = INFPSZ;
125 sopp.sopp_rcvtimer = SOCKET_TIMER_INTERVAL;
126 sopp.sopp_rcvthresh = SOCKET_RECVHIWATER >> 3;
127 sopp.sopp_maxaddrlen = sizeof (sin6_t);
128 sopp.sopp_minpsz = (dccp_rinfo.mi_minpsz == 1) ? 0 :
129 dccp_rinfo.mi_minpsz;
130
131 connp->conn_upcalls = sock_upcalls;
132 connp->conn_upper_handle = sock_handle;
133
134 /* XXX conn_rcvbuf */
135 (*connp->conn_upcalls->su_set_proto_props)(connp->conn_upper_handle,
136 &sopp);
137 }
138
139 /*ARGSUSED*/
140 static int
141 dccp_accept(sock_lower_handle_t lproto_handle,
142 sock_lower_handle_t eproto_handle, sock_upper_handle_t sock_handle,
143 cred_t *cr)
144 {
145 conn_t *lconnp, *econnp;
146 dccp_t *listener, *eager;
147
148 cmn_err(CE_NOTE, "dccp_socket.c: dccp_accept");
149
150 econnp = (conn_t *)eproto_handle;
151 eager = econnp->conn_dccp;
152 ASSERT(IPCL_IS_NONSTR(econnp));
153 ASSERT(eager->dccp_listener != NULL);
154 listener = eager->dccp_listener;
155 lconnp = (conn_t *)listener->dccp_connp;
156 ASSERT(listener->dccp_state == DCCPS_LISTEN);
157 ASSERT(lconnp->conn_upper_handle != NULL);
158
159 ASSERT(econnp->conn_upper_handle == NULL ||
160 econnp->conn_upper_handle == sock_handle);
161 ASSERT(econnp->conn_upcalls == NULL ||
162 econnp->conn_upcalls == lconnp->conn_upcalls);
163 econnp->conn_upper_handle = sock_handle;
164 econnp->conn_upcalls = lconnp->conn_upcalls;
165
166 ASSERT(econnp->conn_netstack ==
167 listener->dccp_connp->conn_netstack);
168 ASSERT(eager->dccp_dccps == listener->dccp_dccps);
169
170 ASSERT(econnp->conn_ref >= 2);
171 eager->dccp_listener = NULL; /* XXX */
172 CONN_DEC_REF(listener->dccp_connp);
173
174 return ((eager->dccp_state < DCCPS_OPEN) ? ECONNABORTED : 0);
175 }
176
177 static int
178 dccp_bind(sock_lower_handle_t proto_handle, struct sockaddr *sa,
179 socklen_t len, cred_t *cr)
180 {
181 conn_t *connp = (conn_t *)proto_handle;
182 int error;
183
184 cmn_err(CE_NOTE, "dccp_socket.c: dccp_bind");
185
186 ASSERT(connp->conn_upper_handle != NULL);
187
188 /* All Solaris components should pass a cred for this operation */
189 ASSERT(cr != NULL);
190
191 error = squeue_synch_enter(connp, NULL);
192 if (error != 0) {
193 /* Failed to enter */
194 return (ENOSR);
195 }
196
197 /* Binding to NULL address means unbind */
198 if (sa == NULL) {
199 if (connp->conn_dccp->dccp_state < DCCPS_LISTEN) {
200 error = dccp_do_unbind(connp);
201 } else {
202 error = EINVAL;
203 }
204 } else {
205 error = dccp_do_bind(connp, sa, len, cr, B_TRUE);
206 }
207
208 squeue_synch_exit(connp);
209
210 if (error < 0) {
211 if (error == -TOUTSTATE) {
212 error = EINVAL;
213 } else {
214 error = proto_tlitosyserr(-error);
215 }
216 }
217
218 return (error);
219 }
220
221 /* ARGSUSED */
222 static int
223 dccp_listen(sock_lower_handle_t proto_handle, int backlog, cred_t *cr)
224 {
225 conn_t *connp = (conn_t *)proto_handle;
226 dccp_t *dccp = connp->conn_dccp;
227 int error;
228
229 cmn_err(CE_NOTE, "dccp_socket.c: dccp_listen");
230
231 ASSERT(connp->conn_upper_handle != NULL);
232
233 /* All Solaris components should pass a cred for this operation */
234 ASSERT(cr != NULL);
235
236 error = squeue_synch_enter(connp, NULL);
237 if (error != 0) {
238 /* Failed to enter */
239 return (ENOBUFS);
240 }
241
242 error = dccp_do_listen(connp, NULL, 0, backlog, cr, B_FALSE);
243 if (error == 0) {
244 /* XXX dccps->dccps_conn_req_max_q0 */
245 (*connp->conn_upcalls->su_opctl)(connp->conn_upper_handle,
246 SOCK_OPCTL_ENAB_ACCEPT,
247 (uintptr_t)(dccp->dccp_conn_req_max));
248 } else if (error < 0) {
249 if (error == -TOUTSTATE) {
250 error = EINVAL;
251 } else {
252 error = proto_tlitosyserr(-error);
253 }
254 }
255
256 squeue_synch_exit(connp);
257
258 return (error);
259 }
260
261 /*
262 * Socket connect.
263 */
264 static int
265 dccp_connect(sock_lower_handle_t proto_handle, const struct sockaddr *sa,
266 socklen_t len, sock_connid_t *id, cred_t *cr)
267 {
268 conn_t *connp = (conn_t *)proto_handle;
269 int error;
270
271 cmn_err(CE_NOTE, "dccp_socket.c: dccp_connect");
272
273 ASSERT(connp->conn_upper_handle != NULL);
274
275 /* All Solaris components should pass a cred for this operation */
276 ASSERT(cr != NULL);
277
278 error = proto_verify_ip_addr(connp->conn_family, sa, len);
279 if (error != 0) {
280 return (error);
281 }
282
283 error = squeue_synch_enter(connp, NULL);
284 if (error != 0) {
285 /* Failed to enter */
286 return (ENOSR);
287 }
288
289 /*
290 * DCCP supports quick connect, so no need to do an implicit bind.
291 */
292 error = dccp_do_connect(connp, sa, len, cr, curproc->p_pid);
293 if (error == 0) {
294 *id = connp->conn_dccp->dccp_connid;
295 } else if (error < 0) {
296 if (error == -TOUTSTATE) {
297 switch (connp->conn_dccp->dccp_state) {
298 case DCCPS_REQUEST:
299 error = EALREADY;
300 break;
301 case DCCPS_PARTOPEN:
302 error = EISCONN;
303 break;
304 case DCCPS_LISTEN:
305 error = EOPNOTSUPP;
306 break;
307 default:
308 error = EINVAL;
309 break;
310 }
311 } else {
312 error = proto_tlitosyserr(-error);
313 }
314 }
315
316 /* XXX loopback */
317
318 squeue_synch_exit(connp);
319
320 return ((error == 0) ? EINPROGRESS : error);
321 }
322
323 /* ARGSUSED3 */
324 static int
325 dccp_getpeername(sock_lower_handle_t proto_handle, struct sockaddr *addr,
326 socklen_t *addrlenp, cred_t *cr)
327 {
328 conn_t *connp = (conn_t *)proto_handle;
329 dccp_t *dccp = connp->conn_dccp;
330
331 cmn_err(CE_NOTE, "dccp_socket.c: dccp_getpeername");
332
333 /* All Solaris components should pass a cred for this operation */
334 ASSERT(cr != NULL);
335
336 ASSERT(dccp != NULL);
337 if (dccp->dccp_state < DCCPS_OPEN) {
338 return (ENOTCONN);
339 }
340
341 return (conn_getpeername(connp, addr, addrlenp));
342 }
343
344 /* ARGSUSED3 */
345 static int
346 dccp_getsockname(sock_lower_handle_t proto_handle, struct sockaddr *addr,
347 socklen_t *addrlenp, cred_t *cr)
348 {
349 conn_t *connp = (conn_t *)proto_handle;
350 int error;
351
352 cmn_err(CE_NOTE, "dccp_socket.c: dccp_getsockname");
353
354 /* All Solaris components should pass a cred for this operation */
355 ASSERT(cr != NULL);
356
357 /* XXX UDP has locks here, TCP not */
358 mutex_enter(&connp->conn_lock);
359 error = conn_getsockname(connp, addr, addrlenp);
360 mutex_exit(&connp->conn_lock);
361
362 return (error);
363 }
364
365 static int
366 dccp_getsockopt(sock_lower_handle_t proto_handle, int level, int option_name,
367 void *optvalp, socklen_t *optlen, cred_t *cr)
368 {
369 conn_t *connp = (conn_t *)proto_handle;
370 void *optvalp_buf;
371 t_uscalar_t max_optbuf_len;
372 int len;
373 int error;
374
375 cmn_err(CE_NOTE, "dccp_socket.c: dccp_getsockopt");
376
377 ASSERT(connp->conn_upper_handle != NULL);
378
379 /* All Solaris components should pass a cred for this operation */
380 ASSERT(cr != NULL);
381
382 error = proto_opt_check(level, option_name, *optlen, &max_optbuf_len,
383 dccp_opt_obj.odb_opt_des_arr,
384 dccp_opt_obj.odb_opt_arr_cnt,
385 B_FALSE, B_TRUE, cr);
386 if (error != 0) {
387 if (error < 0) {
388 error = proto_tlitosyserr(-error);
389 }
390 return (error);
391 }
392
393 optvalp_buf = kmem_alloc(max_optbuf_len, KM_SLEEP);
394 if (optvalp_buf == NULL) {
395 return (ENOMEM);
396 }
397
398 error = squeue_synch_enter(connp, NULL);
399 if (error == ENOMEM) {
400 kmem_free(optvalp_buf, max_optbuf_len);
401 return (ENOMEM);
402 }
403
404 len = dccp_opt_get(connp, level, option_name, optvalp_buf);
405 squeue_synch_exit(connp);
406
407 if (len == -1) {
408 kmem_free(optvalp_buf, max_optbuf_len);
409 return (EINVAL);
410 }
411
412 /*
413 * Update optlen and copy option value.
414 */
415 t_uscalar_t size = MIN(len, *optlen);
416
417 bcopy(optvalp_buf, optvalp, size);
418 bcopy(&size, optlen, sizeof (size));
419
420 kmem_free(optvalp_buf, max_optbuf_len);
421
422 return (0);
423 }
424
425 static int
426 dccp_setsockopt(sock_lower_handle_t proto_handle, int level, int option_name,
427 const void *optvalp, socklen_t optlen, cred_t *cr)
428 {
429 conn_t *connp = (conn_t *)proto_handle;
430 int error;
431
432 cmn_err(CE_NOTE, "dccp_socket.c: dccp_setsockopt");
433
434 ASSERT(connp->conn_upper_handle != NULL);
435
436 /* All Solaris components should pass a cred for this operation */
437 ASSERT(cr != NULL);
438
439 error = squeue_synch_enter(connp, NULL);
440 if (error == ENOMEM) {
441 return (ENOMEM);
442 }
443
444 error = proto_opt_check(level, option_name, optlen, NULL,
445 dccp_opt_obj.odb_opt_des_arr,
446 dccp_opt_obj.odb_opt_arr_cnt,
447 B_TRUE, B_FALSE, cr);
448
449 if (error != 0) {
450 if (error < 0) {
451 error = proto_tlitosyserr(-error);
452 }
453 squeue_synch_exit(connp);
454 return (error);
455 }
456
457 error = dccp_opt_set(connp, SETFN_OPTCOM_NEGOTIATE, level, option_name,
458 optlen, (uchar_t *)optvalp, (uint_t *)&optlen, (uchar_t *)optvalp,
459 NULL, cr);
460 squeue_synch_exit(connp);
461
462 ASSERT(error >= 0);
463
464 return (error);
465 }
466
467 /* ARGSUSED */
468 static int
469 dccp_send(sock_lower_handle_t proto_handle, mblk_t *mp, struct nmsghdr *msg,
470 cred_t *cr)
471 {
472 conn_t *connp = (conn_t *)proto_handle;
473 dccp_t *dccp;
474 uint32_t msize;
475 int32_t dccpstate;
476
477 cmn_err(CE_NOTE, "dccp_socket.c: dccp_send");
478
479 /* All Solaris components should pass a cred for this operation */
480 ASSERT(cr != NULL);
481
482 ASSERT(connp->conn_ref >= 2);
483 ASSERT(connp->conn_upper_handle != NULL);
484
485 if (msg->msg_controllen != 0) {
486 freemsg(mp);
487 return (EOPNOTSUPP);
488 }
489
490 switch (DB_TYPE(mp)) {
491 case M_DATA:
492 dccp = connp->conn_dccp;
493 ASSERT(dccp != NULL);
494
495 dccpstate = dccp->dccp_state;
496 if (dccpstate < DCCPS_OPEN) {
497 freemsg(mp);
498
499 /*
500 * We return ENOTCONN if the endpoint is trying to
501 * connect or has never been connected, and EPIPE if it
502 * has been disconnected. The connection id helps us
503 * distinguish between the last two cases.
504 */
505 return ((dccpstate == DCCPS_REQUEST) ? ENOTCONN :
506 ((dccp->dccp_connid > 0) ? EPIPE : ENOTCONN));
507 } else if (dccpstate > DCCPS_CLOSING) {
508 freemsg(mp);
509 return (EPIPE);
510 }
511
512 /* XXX */
513
514 msize = msgdsize(mp);
515
516 CONN_INC_REF(connp);
517
518 if (msg->msg_flags & MSG_OOB) {
519 SQUEUE_ENTER_ONE(connp->conn_sqp, mp, dccp_output_urgent,
520 connp, NULL, dccp_squeue_flag, SQTAG_DCCP_OUTPUT);
521 } else {
522 SQUEUE_ENTER_ONE(connp->conn_sqp, mp, dccp_output,
523 connp, NULL, dccp_squeue_flag, SQTAG_DCCP_OUTPUT);
524 }
525
526 return (0);
527
528 default:
529 ASSERT(0);
530 }
531
532 freemsg(mp);
533
534 return (0);
535 }
536
537 /* ARGSUSED */
538 static int
539 dccp_shutdown(sock_lower_handle_t proto_handle, int how, cred_t *cr)
540 {
541 conn_t *connp = (conn_t *)proto_handle;
542 dccp_t *dccp = connp->conn_dccp;
543
544 cmn_err(CE_NOTE, "dccp_socket.c: dccp_shutdown");
545
546 /* All Solaris components should pass a cred for this operation. */
547 ASSERT(cr != NULL);
548
549 ASSERT(connp->conn_upper_handle != NULL);
550
551 /*
552 * X/Open requires that we check the connected state.
553 */
554 if (dccp->dccp_state < DCCPS_REQUEST)
555 return (ENOTCONN);
556
557 /* Shutdown the send side */
558 if (how != SHUT_RD) {
559 mblk_t *bp;
560
561 bp = allocb_wait(0, BPRI_HI, STR_NOSIG, NULL);
562 CONN_INC_REF(connp);
563 SQUEUE_ENTER_ONE(connp->conn_sqp, bp, dccp_shutdown_output,
564 connp, NULL, SQ_NODRAIN, SQTAG_DCCP_SHUTDOWN_OUTPUT);
565
566 (*connp->conn_upcalls->su_opctl)(connp->conn_upper_handle,
567 SOCK_OPCTL_SHUT_SEND, 0);
568 }
569
570 /* Shutdown the recv side */
571 if (how != SHUT_WR) {
572 (*connp->conn_upcalls->su_opctl)(connp->conn_upper_handle,
573 SOCK_OPCTL_SHUT_RECV, 0);
574 }
575
576 return (0);
577 }
578
579 static void
580 dccp_clr_flowctrl(sock_lower_handle_t proto_handle)
581 {
582 conn_t *connp = (conn_t *)proto_handle;
583 dccp_t *dccp = connp->conn_dccp;
584 mblk_t *mp;
585 int error;
586
587 ASSERT(connp->conn_upper_handle != NULL);
588
589 cmn_err(CE_NOTE, "dccp_socket.c: dccp_clr_flowctrl");
590
591 error = squeue_synch_enter(connp, mp);
592 ASSERT(error == 0);
593
594 squeue_synch_exit(connp);
595 }
596
597 /* ARGSUSED */
598 static int
599 dccp_ioctl(sock_lower_handle_t proto_handle, int cmd, intptr_t arg,
600 int mode, int32_t *rvalp, cred_t *cr)
601 {
602 conn_t *connp = (conn_t *)proto_handle;
603 int error;
604
605 cmn_err(CE_NOTE, "dccp_socket.c: dccp_ioctl");
606
607 ASSERT(connp->conn_upper_handle != NULL);
608
609 /* All Solaris components should pass a cred for this operation. */
610 ASSERT(cr != NULL);
611
612 /*
613 * If we don't have a helper stream then create one.
614 * ip_create_helper_stream takes care of locking the conn_t,
615 * so this check for NULL is just a performance optimization.
616 */
617 if (connp->conn_helper_info == NULL) {
618 dccp_stack_t *dccps = connp->conn_dccp->dccp_dccps;
619
620 /*
621 * Create a helper stream for non-STREAMS socket.
622 */
623 error = ip_create_helper_stream(connp, dccps->dccps_ldi_ident);
624 if (error != 0) {
625 ip0dbg(("dccp_ioctl: create of IP helper stream "
626 "failed %d\n", error));
627 return (error);
628 }
629 }
630
631 switch (cmd) {
632 case ND_SET:
633 case ND_GET:
634 case _SIOCSOCKFALLBACK:
635 /* XXX case DCCP_IOC_ABORT_CONN: */
636 case TI_GETPEERNAME:
637 case TI_GETMYNAME:
638 ip1dbg(("dccp_ioctl: cmd 0x%x on non streams socket", cmd));
639 error = EINVAL;
640 break;
641 default:
642 /*
643 * If the conn is not closing, pass on to IP using
644 * helper stream. Bump the ioctlref to prevent dccp_close
645 * from closing the rq/wq out from underneath the ioctl
646 * if it ends up queued or aborted/interrupted.
647 */
648 mutex_enter(&connp->conn_lock);
649 if (connp->conn_state_flags & (CONN_CLOSING)) {
650 mutex_exit(&connp->conn_lock);
651 error = EINVAL;
652 break;
653 }
654 CONN_INC_IOCTLREF_LOCKED(connp);
655 error = ldi_ioctl(connp->conn_helper_info->iphs_handle,
656 cmd, arg, mode, cr, rvalp);
657 CONN_DEC_IOCTLREF(connp);
658 break;
659 }
660
661 return (error);
662 }
663
664 /* ARGSUSED */
665 static int
666 dccp_close(sock_lower_handle_t proto_handle, int flags, cred_t *cr)
667 {
668 conn_t *connp = (conn_t *)proto_handle;
669
670 cmn_err(CE_NOTE, "dccp_socket.c: dccp_close\n");
671
672 ASSERT(connp->conn_upper_handle != NULL);
673
674 /* All Solaris components should pass a cred for this operation */
675 ASSERT(cr != NULL);
676
677 dccp_close_common(connp, flags);
678
679 ip_free_helper_stream(connp);
680
681 CONN_DEC_REF(connp);
682
683 /*
684 * EINPROGRESS tells sockfs to wait for a 'closed' upcall before
685 * freeing the socket.
686 */
687 return (EINPROGRESS);
688 }
689
690
691 /*
692 * Socket create function.
693 */
694 sock_lower_handle_t
695 dccp_create(int family, int type, int proto, sock_downcalls_t **sockdowncalls,
696 uint_t *smodep, int *errorp, int flags, cred_t *credp)
697 {
698 conn_t *connp;
699 boolean_t isv6;
700
701 /* XXX (type != SOCK_STREAM */
702 if ((family != AF_INET && family != AF_INET6) ||
703 (proto != 0 && proto != IPPROTO_DCCP)) {
704 *errorp = EPROTONOSUPPORT;
705 return (NULL);
706 }
707
708 cmn_err(CE_NOTE, "dccp_socket: dccp_create\n");
709
710 isv6 = family == AF_INET6 ? B_TRUE: B_FALSE;
711 connp = dccp_create_common(credp, isv6, B_TRUE, errorp);
712 if (connp == NULL) {
713 return (NULL);
714 }
715
716 /*
717 * Increment ref for DCCP connection.
718 */
719 mutex_enter(&connp->conn_lock);
720 CONN_INC_REF_LOCKED(connp);
721 ASSERT(connp->conn_ref == 2);
722 connp->conn_state_flags &= ~CONN_INCIPIENT;
723 connp->conn_flags |= IPCL_NONSTR;
724 mutex_exit(&connp->conn_lock);
725
726 ASSERT(errorp != NULL);
727 *errorp = 0;
728 *sockdowncalls = &sock_dccp_downcalls;
729 *smodep = SM_CONNREQUIRED | SM_EXDATA | SM_ACCEPTSUPP |
730 SM_SENDFILESUPP;
731
732 return ((sock_lower_handle_t)connp);
733 }
734
735 int
736 dccp_fallback(sock_lower_handle_t proto_handle, queue_t *q,
737 boolean_t issocket, so_proto_quiesced_cb_t quiesced_cb,
738 sock_quiesce_arg_t *arg)
739 {
740 cmn_err(CE_NOTE, "dccp_socket: dccp_fallback\n");
741
742 return (0);
743 }
744
745 /*
746 * Notifies a non-STREAMS based listener about a new connection. This
747 * function is executed on the *eager*'s squeue once the 3 way handshake
748 * has completed. Note that the behavior differs from STREAMS, where the
749 * T_CONN_IND is sent up by tcp_send_conn_ind() while on the *listener*'s
750 * squeue.
751 *
752 * Returns B_TRUE if the notification succeeded and an upper handle was
753 * obtained. `tcp' should be closed on failure.
754 */
755 boolean_t
756 dccp_newconn_notify(dccp_t *dccp, ip_recv_attr_t *ira)
757 {
758 dccp_t *listener = dccp->dccp_listener;
759 dccp_t *tail;
760 conn_t *lconnp = listener->dccp_connp;
761 conn_t *econnp = dccp->dccp_connp;
762 ipaddr_t *addr_cache;
763 sock_upper_handle_t upper;
764 struct sock_proto_props sopp;
765
766 cmn_err(CE_NOTE, "dccp_socket.c: dccp_newconn_notify");
767
768 /*
769 mutex_enter(&listener->dccp_eager_lock);
770 addr_cache = (ipaddr_t *)(listener->dccp_ip_addr_cache);
771 if (addr_cache != NULL) {
772 addr_cache[IP_ADDR_CACHE_HASH(dccp->dccp_connp->conn_faddr_v4)] =
773 dccp->dccp_connp->conn_faddr_v4;
774 }
775 mutex_exit(&listener->dccp_eager_lock);
776 */
777
778 /*
779 * Notify the ULP about the new connection.
780 */
781 if ((upper = (*lconnp->conn_upcalls->su_newconn)
782 (lconnp->conn_upper_handle, (sock_lower_handle_t)econnp,
783 &sock_dccp_downcalls, ira->ira_cred, ira->ira_cpid,
784 &econnp->conn_upcalls)) == NULL) {
785 return (B_FALSE);
786 }
787 econnp->conn_upper_handle = upper;
788
789 dccp->dccp_detached = B_FALSE;
790 dccp->dccp_hard_binding = B_FALSE;
791 dccp->dccp_tconnind_started = B_TRUE;
792
793 if (econnp->conn_keepalive) {
794 dccp->dccp_ka_last_intrvl = 0;
795 dccp->dccp_ka_tid = DCCP_TIMER(dccp, dccp_keepalive_timer,
796 dccp->dccp_ka_interval);
797 }
798
799 /* Update the necessary parameters */
800 dccp_get_proto_props(dccp, &sopp);
801
802 (*econnp->conn_upcalls->su_set_proto_props)
803 (econnp->conn_upper_handle, &sopp);
804
805 return (B_TRUE);
806 }