socksctp.c revision 8348:4137e18bfaf0
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 2008 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#include <sys/types.h>
28#include <sys/t_lock.h>
29#include <sys/param.h>
30#include <sys/systm.h>
31#include <sys/buf.h>
32#include <sys/vfs.h>
33#include <sys/vnode.h>
34#include <sys/debug.h>
35#include <sys/errno.h>
36#include <sys/stropts.h>
37#include <sys/cmn_err.h>
38#include <sys/sysmacros.h>
39#include <sys/filio.h>
40
41#include <sys/project.h>
42#include <sys/tihdr.h>
43#include <sys/strsubr.h>
44#include <sys/esunddi.h>
45#include <sys/ddi.h>
46
47#include <sys/sockio.h>
48#include <sys/socket.h>
49#include <sys/socketvar.h>
50#include <sys/strsun.h>
51
52#include <netinet/sctp.h>
53#include <inet/sctp_itf.h>
54#include <fs/sockfs/sockcommon.h>
55#include "socksctp.h"
56
57/*
58 * SCTP sockfs sonode operations, 1-1 socket
59 */
60static int sosctp_init(struct sonode *, struct sonode *, struct cred *, int);
61static int sosctp_accept(struct sonode *, int, struct cred *, struct sonode **);
62static int sosctp_bind(struct sonode *, struct sockaddr *, socklen_t, int,
63    struct cred *);
64static int sosctp_listen(struct sonode *, int, struct cred *);
65static int sosctp_connect(struct sonode *, const struct sockaddr *, socklen_t,
66    int, int, struct cred *);
67static int sosctp_recvmsg(struct sonode *, struct nmsghdr *, struct uio *,
68    struct cred *);
69static int sosctp_sendmsg(struct sonode *, struct nmsghdr *, struct uio *,
70    struct cred *);
71static int sosctp_getpeername(struct sonode *, struct sockaddr *, socklen_t *,
72    boolean_t, struct cred *);
73static int sosctp_getsockname(struct sonode *, struct sockaddr *, socklen_t *,
74    struct cred *);
75static int sosctp_shutdown(struct sonode *, int, struct cred *);
76static int sosctp_getsockopt(struct sonode *, int, int, void *, socklen_t *,
77    int, struct cred *);
78static int sosctp_setsockopt(struct sonode *, int, int, const void *,
79    socklen_t, struct cred *);
80static int sosctp_ioctl(struct sonode *, int, intptr_t, int, struct cred *,
81    int32_t *);
82static int sosctp_close(struct sonode *, int, struct cred *);
83void sosctp_fini(struct sonode *, struct cred *);
84
85/*
86 * SCTP sockfs sonode operations, 1-N socket
87 */
88static int sosctp_seq_connect(struct sonode *, const struct sockaddr *,
89    socklen_t, int, int, struct cred *);
90static int sosctp_seq_sendmsg(struct sonode *, struct nmsghdr *, struct uio *,
91    struct cred *);
92
93/*
94 * Socket association upcalls, 1-N socket connection
95 */
96sock_upper_handle_t sctp_assoc_newconn(sock_upper_handle_t,
97    sock_lower_handle_t, sock_downcalls_t *, struct cred *, pid_t,
98    sock_upcalls_t **);
99static void sctp_assoc_connected(sock_upper_handle_t, sock_connid_t,
100    struct cred *, pid_t);
101static int sctp_assoc_disconnected(sock_upper_handle_t, sock_connid_t, int);
102static void sctp_assoc_disconnecting(sock_upper_handle_t, sock_opctl_action_t,
103    uintptr_t arg);
104static ssize_t sctp_assoc_recv(sock_upper_handle_t, mblk_t *, size_t, int,
105    int *, boolean_t *);
106static void sctp_assoc_xmitted(sock_upper_handle_t, boolean_t);
107static void sctp_assoc_properties(sock_upper_handle_t,
108    struct sock_proto_props *);
109
110sonodeops_t sosctp_sonodeops = {
111	sosctp_init,			/* sop_init	*/
112	sosctp_accept,			/* sop_accept	*/
113	sosctp_bind,			/* sop_bind	*/
114	sosctp_listen,			/* sop_listen	*/
115	sosctp_connect,			/* sop_connect	*/
116	sosctp_recvmsg,			/* sop_recvmsg	*/
117	sosctp_sendmsg,			/* sop_sendmsg	*/
118	so_sendmblk_notsupp,		/* sop_sendmblk	*/
119	sosctp_getpeername,		/* sop_getpeername */
120	sosctp_getsockname,		/* sop_getsockname */
121	sosctp_shutdown,		/* sop_shutdown */
122	sosctp_getsockopt,		/* sop_getsockopt */
123	sosctp_setsockopt,		/* sop_setsockopt */
124	sosctp_ioctl,			/* sop_ioctl	*/
125	so_poll,			/* sop_poll	*/
126	sosctp_close,			/* sop_close 	*/
127};
128
129sonodeops_t sosctp_seq_sonodeops = {
130	sosctp_init,			/* sop_init	*/
131	so_accept_notsupp,		/* sop_accept	*/
132	sosctp_bind,			/* sop_bind	*/
133	sosctp_listen,			/* sop_listen	*/
134	sosctp_seq_connect,		/* sop_connect	*/
135	sosctp_recvmsg,			/* sop_recvmsg	*/
136	sosctp_seq_sendmsg,		/* sop_sendmsg	*/
137	so_sendmblk_notsupp,		/* sop_sendmblk	*/
138	so_getpeername_notsupp,		/* sop_getpeername */
139	sosctp_getsockname,		/* sop_getsockname */
140	so_shutdown_notsupp,		/* sop_shutdown */
141	sosctp_getsockopt,		/* sop_getsockopt */
142	sosctp_setsockopt,		/* sop_setsockopt */
143	sosctp_ioctl,			/* sop_ioctl	*/
144	so_poll,			/* sop_poll	*/
145	sosctp_close,			/* sop_close 	*/
146};
147
148sock_upcalls_t sosctp_sock_upcalls = {
149	so_newconn,
150	so_connected,
151	so_disconnected,
152	so_opctl,
153	so_queue_msg,
154	so_set_prop,
155	so_txq_full,
156	NULL,			/* su_signal_oob */
157};
158
159sock_upcalls_t sosctp_assoc_upcalls = {
160	sctp_assoc_newconn,
161	sctp_assoc_connected,
162	sctp_assoc_disconnected,
163	sctp_assoc_disconnecting,
164	sctp_assoc_recv,
165	sctp_assoc_properties,
166	sctp_assoc_xmitted,
167	NULL,			/* su_recv_space */
168	NULL,			/* su_signal_oob */
169};
170
171/* ARGSUSED */
172static int
173sosctp_init(struct sonode *so, struct sonode *pso, struct cred *cr, int flags)
174{
175	struct sctp_sonode *ss;
176	struct sctp_sonode *pss;
177	sctp_sockbuf_limits_t sbl;
178	sock_upcalls_t *upcalls;
179
180	ss = SOTOSSO(so);
181
182	if (pso != NULL) {
183		/*
184		 * Passive open, just inherit settings from parent. We should
185		 * not end up here for SOCK_SEQPACKET type sockets, since no
186		 * new sonode is created in that case.
187		 */
188		ASSERT(so->so_type == SOCK_STREAM);
189		pss = SOTOSSO(pso);
190
191		mutex_enter(&pso->so_lock);
192		so->so_state |= (SS_ISBOUND | SS_ISCONNECTED |
193		    (pso->so_state & SS_ASYNC));
194		sosctp_so_inherit(pss, ss);
195		so->so_proto_props = pso->so_proto_props;
196		so->so_mode = pso->so_mode;
197		mutex_exit(&pso->so_lock);
198
199		return (0);
200	}
201
202	if (so->so_type == SOCK_STREAM) {
203		upcalls = &sosctp_sock_upcalls;
204		so->so_mode = SM_CONNREQUIRED;
205	} else {
206		ASSERT(so->so_type == SOCK_SEQPACKET);
207		upcalls = &sosctp_assoc_upcalls;
208	}
209	so->so_proto_handle = (sock_lower_handle_t)sctp_create(so, NULL,
210	    so->so_family, SCTP_CAN_BLOCK, upcalls, &sbl, cr);
211	if (so->so_proto_handle == NULL)
212		return (ENOMEM);
213
214	so->so_rcvbuf = sbl.sbl_rxbuf;
215	so->so_rcvlowat = sbl.sbl_rxlowat;
216	so->so_sndbuf = sbl.sbl_txbuf;
217	so->so_sndlowat = sbl.sbl_txlowat;
218
219	return (0);
220}
221
222/*
223 * Accept incoming connection.
224 */
225/*ARGSUSED*/
226static int
227sosctp_accept(struct sonode *so, int fflag, struct cred *cr,
228    struct sonode **nsop)
229{
230	int error = 0;
231
232	if ((so->so_state & SS_ACCEPTCONN) == 0)
233		return (EINVAL);
234
235	error = so_acceptq_dequeue(so, (fflag & (FNONBLOCK|FNDELAY)), nsop);
236
237	return (error);
238}
239
240/*
241 * Bind local endpoint.
242 */
243/*ARGSUSED*/
244static int
245sosctp_bind(struct sonode *so, struct sockaddr *name, socklen_t namelen,
246    int flags, struct cred *cr)
247{
248	int error;
249
250	if (!(flags & _SOBIND_LOCK_HELD)) {
251		mutex_enter(&so->so_lock);
252		so_lock_single(so);	/* Set SOLOCKED */
253	} else {
254		ASSERT(MUTEX_HELD(&so->so_lock));
255	}
256
257	/*
258	 * X/Open requires this check
259	 */
260	if (so->so_state & SS_CANTSENDMORE) {
261		error = EINVAL;
262		goto done;
263	}
264
265
266	/*
267	 * Protocol module does address family checks.
268	 */
269	mutex_exit(&so->so_lock);
270
271	error = sctp_bind((struct sctp_s *)so->so_proto_handle, name, namelen);
272
273	mutex_enter(&so->so_lock);
274	if (error == 0) {
275		so->so_state |= SS_ISBOUND;
276	} else {
277		eprintsoline(so, error);
278	}
279done:
280	if (!(flags & _SOBIND_LOCK_HELD)) {
281		so_unlock_single(so, SOLOCKED);
282		mutex_exit(&so->so_lock);
283	} else {
284		/* If the caller held the lock don't release it here */
285		ASSERT(MUTEX_HELD(&so->so_lock));
286		ASSERT(so->so_flag & SOLOCKED);
287	}
288
289	return (error);
290}
291
292/*
293 * Turn socket into a listen socket.
294 */
295/* ARGSUSED */
296static int
297sosctp_listen(struct sonode *so, int backlog, struct cred *cr)
298{
299	int error = 0;
300
301	mutex_enter(&so->so_lock);
302	so_lock_single(so);
303
304	/*
305	 * If this socket is trying to do connect, or if it has
306	 * been connected, disallow.
307	 */
308	if (so->so_state & (SS_ISCONNECTING | SS_ISCONNECTED |
309	    SS_ISDISCONNECTING | SS_CANTRCVMORE | SS_CANTSENDMORE)) {
310		error = EINVAL;
311		eprintsoline(so, error);
312		goto done;
313	}
314
315	if (backlog < 0) {
316		backlog = 0;
317	}
318
319	/*
320	 * If listen() is only called to change backlog, we don't
321	 * need to notify protocol module.
322	 */
323	if (so->so_state & SS_ACCEPTCONN) {
324		so->so_backlog = backlog;
325		goto done;
326	}
327
328	mutex_exit(&so->so_lock);
329	error = sctp_listen((struct sctp_s *)so->so_proto_handle);
330	mutex_enter(&so->so_lock);
331	if (error == 0) {
332		so->so_state |= (SS_ACCEPTCONN|SS_ISBOUND);
333		so->so_backlog = backlog;
334	} else {
335		eprintsoline(so, error);
336	}
337done:
338	so_unlock_single(so, SOLOCKED);
339	mutex_exit(&so->so_lock);
340
341	return (error);
342}
343
344/*
345 * Active open.
346 */
347/*ARGSUSED*/
348static int
349sosctp_connect(struct sonode *so, const struct sockaddr *name,
350    socklen_t namelen, int fflag, int flags, struct cred *cr)
351{
352	int error = 0;
353
354	ASSERT(so->so_type == SOCK_STREAM);
355
356	mutex_enter(&so->so_lock);
357	so_lock_single(so);
358
359	/*
360	 * Can't connect() after listen(), or if the socket is already
361	 * connected.
362	 */
363	if (so->so_state & (SS_ACCEPTCONN|SS_ISCONNECTED|SS_ISCONNECTING)) {
364		if (so->so_state & SS_ISCONNECTED) {
365			error = EISCONN;
366		} else if (so->so_state & SS_ISCONNECTING) {
367			error = EALREADY;
368		} else {
369			error = EOPNOTSUPP;
370		}
371		eprintsoline(so, error);
372		goto done;
373	}
374
375	/*
376	 * Check for failure of an earlier call
377	 */
378	if (so->so_error != 0) {
379		error = sogeterr(so, B_TRUE);
380		eprintsoline(so, error);
381		goto done;
382	}
383
384	/*
385	 * Connection is closing, or closed, don't allow reconnect.
386	 * TCP allows this to proceed, but the socket remains unwriteable.
387	 * BSD returns EINVAL.
388	 */
389	if (so->so_state & (SS_ISDISCONNECTING|SS_CANTRCVMORE|
390	    SS_CANTSENDMORE)) {
391		error = EINVAL;
392		eprintsoline(so, error);
393		goto done;
394	}
395
396	if (name == NULL || namelen == 0) {
397		mutex_exit(&so->so_lock);
398		error = EINVAL;
399		eprintsoline(so, error);
400		goto done;
401	}
402
403	soisconnecting(so);
404	mutex_exit(&so->so_lock);
405
406	error = sctp_connect((struct sctp_s *)so->so_proto_handle,
407	    name, namelen);
408
409	mutex_enter(&so->so_lock);
410	if (error == 0) {
411		/*
412		 * Allow other threads to access the socket
413		 */
414		error = sowaitconnected(so, fflag, 0);
415	}
416done:
417	so_unlock_single(so, SOLOCKED);
418	mutex_exit(&so->so_lock);
419	return (error);
420}
421
422/*
423 * Active open for 1-N sockets, create a new association and
424 * call connect on that.
425 * If there parent hasn't been bound yet (this is the first association),
426 * make it so.
427 */
428static int
429sosctp_seq_connect(struct sonode *so, const struct sockaddr *name,
430    socklen_t namelen, int fflag, int flags, struct cred *cr)
431{
432	struct sctp_soassoc *ssa;
433	struct sctp_sonode *ss;
434	int error;
435
436	ASSERT(so->so_type == SOCK_SEQPACKET);
437
438	mutex_enter(&so->so_lock);
439	so_lock_single(so);
440
441	if (name == NULL || namelen == 0) {
442		error = EINVAL;
443		eprintsoline(so, error);
444		goto done;
445	}
446
447	ss = SOTOSSO(so);
448
449	error = sosctp_assoc_createconn(ss, name, namelen, NULL, 0, fflag,
450	    cr, &ssa);
451	if (error != 0) {
452		if ((error == EHOSTUNREACH) && (flags & _SOCONNECT_XPG4_2)) {
453			error = ENETUNREACH;
454		}
455	}
456	if (ssa != NULL) {
457		SSA_REFRELE(ss, ssa);
458	}
459
460done:
461	so_unlock_single(so, SOLOCKED);
462	mutex_exit(&so->so_lock);
463	return (error);
464}
465
466/*
467 * Receive data.
468 */
469/* ARGSUSED */
470static int
471sosctp_recvmsg(struct sonode *so, struct nmsghdr *msg, struct uio *uiop,
472    struct cred *cr)
473{
474	struct sctp_sonode *ss = SOTOSSO(so);
475	struct sctp_soassoc *ssa = NULL;
476	int flags, error = 0;
477	struct T_unitdata_ind *tind;
478	int len, count, readcnt = 0, rxqueued;
479	socklen_t controllen, namelen;
480	void *opt;
481	mblk_t *mp;
482	rval_t	rval;
483
484	controllen = msg->msg_controllen;
485	namelen = msg->msg_namelen;
486	flags = msg->msg_flags;
487	msg->msg_flags = 0;
488	msg->msg_controllen = 0;
489	msg->msg_namelen = 0;
490
491	if (so->so_type == SOCK_STREAM) {
492		if (!(so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING|
493		    SS_CANTRCVMORE))) {
494			return (ENOTCONN);
495		}
496	} else {
497		/* NOTE: Will come here from vop_read() as well */
498		/* For 1-N socket, recv() cannot be used. */
499		if (namelen == 0)
500			return (EOPNOTSUPP);
501		/*
502		 * If there are no associations, and no new connections are
503		 * coming in, there's not going to be new messages coming
504		 * in either.
505		 */
506		if (so->so_rcv_q_head == NULL && ss->ss_assoccnt == 0 &&
507		    !(so->so_state & SS_ACCEPTCONN)) {
508			return (ENOTCONN);
509		}
510	}
511
512	/*
513	 * out-of-band data not supported.
514	 */
515	if (flags & MSG_OOB) {
516		return (EOPNOTSUPP);
517	}
518
519	/*
520	 * flag possibilities:
521	 *
522	 * MSG_PEEK	Don't consume data
523	 * MSG_WAITALL	Wait for full quantity of data (ignored if MSG_PEEK)
524	 * MSG_DONTWAIT Non-blocking (same as FNDELAY | FNONBLOCK)
525	 *
526	 * MSG_WAITALL can return less than the full buffer if either
527	 *
528	 * 1. we would block and we are non-blocking
529	 * 2. a full message cannot be delivered
530	 *
531	 * Given that we always get a full message from proto below,
532	 * MSG_WAITALL is not meaningful.
533	 */
534
535	mutex_enter(&so->so_lock);
536
537	/*
538	 * Allow just one reader at a time.
539	 */
540	error = so_lock_read_intr(so,
541	    uiop->uio_fmode | ((flags & MSG_DONTWAIT) ? FNONBLOCK : 0));
542	if (error) {
543		mutex_exit(&so->so_lock);
544		return (error);
545	}
546	mutex_exit(&so->so_lock);
547again:
548	error = so_dequeue_msg(so, &mp, uiop, &rval, flags | MSG_DUPCTRL);
549	if (mp != NULL) {
550		if (so->so_type == SOCK_SEQPACKET) {
551			ssa = *(struct sctp_soassoc **)DB_BASE(mp);
552		}
553
554		tind = (struct T_unitdata_ind *)mp->b_rptr;
555
556		len = tind->SRC_length;
557
558		if (namelen > 0 && len > 0) {
559
560			opt = sogetoff(mp, tind->SRC_offset, len, 1);
561
562			ASSERT(opt != NULL);
563
564			msg->msg_name = kmem_alloc(len, KM_SLEEP);
565			msg->msg_namelen = len;
566
567			bcopy(opt, msg->msg_name, len);
568		}
569
570		len = tind->OPT_length;
571		if (controllen == 0) {
572			if (len > 0) {
573				msg->msg_flags |= MSG_CTRUNC;
574			}
575		} else if (len > 0) {
576			opt = sogetoff(mp, tind->OPT_offset, len,
577			    __TPI_ALIGN_SIZE);
578
579			ASSERT(opt != NULL);
580			sosctp_pack_cmsg(opt, msg, len);
581		}
582
583		if (mp->b_flag & SCTP_NOTIFICATION) {
584			msg->msg_flags |= MSG_NOTIFICATION;
585		}
586
587		if (!(mp->b_flag & SCTP_PARTIAL_DATA))
588			msg->msg_flags |= MSG_EOR;
589		freemsg(mp);
590	}
591done:
592	/*
593	 * Determine if we need to update SCTP about the buffer
594	 * space.  For performance reason, we cannot update SCTP
595	 * every time a message is read.  The socket buffer low
596	 * watermark is used as the threshold.
597	 */
598	if (ssa == NULL) {
599		mutex_enter(&so->so_lock);
600		rxqueued = so->so_rcv_queued;
601
602		so->so_rcv_queued = rxqueued - readcnt;
603		count = so->so_rcvbuf - so->so_rcv_queued;
604
605		ASSERT(so->so_rcv_q_head != NULL ||
606		    so->so_rcv_head != NULL ||
607		    so->so_rcv_queued == 0);
608
609		so_unlock_read(so);
610		mutex_exit(&so->so_lock);
611
612		if (readcnt > 0 && (((count > 0) &&
613		    (rxqueued >= so->so_rcvlowat)) ||
614		    (so->so_rcv_queued == 0))) {
615			/*
616			 * If amount of queued data is higher than watermark,
617			 * updata SCTP's idea of available buffer space.
618			 */
619			sctp_recvd((struct sctp_s *)so->so_proto_handle, count);
620		}
621	} else {
622		mutex_enter(&so->so_lock);
623		rxqueued = ssa->ssa_rcv_queued;
624
625		ssa->ssa_rcv_queued = rxqueued - readcnt;
626		count = so->so_rcvbuf - ssa->ssa_rcv_queued;
627
628		so_unlock_read(so);
629
630		if (readcnt > 0 &&
631		    (((count > 0) && (rxqueued >= so->so_rcvlowat)) ||
632		    (ssa->ssa_rcv_queued == 0))) {
633			/*
634			 * If amount of queued data is higher than watermark,
635			 * updata SCTP's idea of available buffer space.
636			 */
637			mutex_exit(&so->so_lock);
638
639			sctp_recvd((struct sctp_s *)ssa->ssa_conn, count);
640
641			mutex_enter(&so->so_lock);
642		}
643		/*
644		 * MOREDATA flag is set if all data could not be copied
645		 */
646		if (!(flags & MSG_PEEK) && !(rval.r_val1 & MOREDATA)) {
647			SSA_REFRELE(ss, ssa);
648		}
649		mutex_exit(&so->so_lock);
650	}
651
652	return (error);
653}
654
655int
656sosctp_uiomove(mblk_t *hdr_mp, ssize_t count, ssize_t blk_size, int wroff,
657    struct uio *uiop, int flags, cred_t *cr)
658{
659	ssize_t size;
660	int error;
661	mblk_t *mp;
662	dblk_t *dp;
663
664	/*
665	 * Loop until we have all data copied into mblk's.
666	 */
667	while (count > 0) {
668		size = MIN(count, blk_size);
669
670		/*
671		 * As a message can be splitted up and sent in different
672		 * packets, each mblk will have the extra space before
673		 * data to accommodate what SCTP wants to put in there.
674		 */
675		while ((mp = allocb_cred(size + wroff, cr)) == NULL) {
676			if ((uiop->uio_fmode & (FNDELAY|FNONBLOCK)) ||
677			    (flags & MSG_DONTWAIT)) {
678				return (EAGAIN);
679			}
680			if ((error = strwaitbuf(size + wroff, BPRI_MED))) {
681				return (error);
682			}
683		}
684
685		dp = mp->b_datap;
686		dp->db_cpid = curproc->p_pid;
687		ASSERT(wroff <= dp->db_lim - mp->b_wptr);
688		mp->b_rptr += wroff;
689		error = uiomove(mp->b_rptr, size, UIO_WRITE, uiop);
690		if (error != 0) {
691			freeb(mp);
692			return (error);
693		}
694		mp->b_wptr = mp->b_rptr + size;
695		count -= size;
696		hdr_mp->b_cont = mp;
697		hdr_mp = mp;
698	}
699	return (0);
700}
701
702/*
703 * Send message.
704 */
705static int
706sosctp_sendmsg(struct sonode *so, struct nmsghdr *msg, struct uio *uiop,
707    struct cred *cr)
708{
709	struct sctp_sonode *ss = SOTOSSO(so);
710	mblk_t *mctl;
711	struct cmsghdr *cmsg;
712	struct sctp_sndrcvinfo *sinfo;
713	int optlen, flags, fflag;
714	ssize_t count, msglen;
715	int error;
716
717	ASSERT(so->so_type == SOCK_STREAM);
718
719	flags = msg->msg_flags;
720	if (flags & MSG_OOB) {
721		/*
722		 * No out-of-band data support.
723		 */
724		return (EOPNOTSUPP);
725	}
726
727	if (msg->msg_controllen != 0) {
728		optlen = msg->msg_controllen;
729		cmsg = sosctp_find_cmsg(msg->msg_control, optlen, SCTP_SNDRCV);
730		if (cmsg != NULL) {
731			if (cmsg->cmsg_len <
732			    (sizeof (*sinfo) + sizeof (*cmsg))) {
733				eprintsoline(so, EINVAL);
734				return (EINVAL);
735			}
736			sinfo = (struct sctp_sndrcvinfo *)(cmsg + 1);
737
738			/* Both flags should not be set together. */
739			if ((sinfo->sinfo_flags & MSG_EOF) &&
740			    (sinfo->sinfo_flags & MSG_ABORT)) {
741				eprintsoline(so, EINVAL);
742				return (EINVAL);
743			}
744
745			/* Initiate a graceful shutdown. */
746			if (sinfo->sinfo_flags & MSG_EOF) {
747				/* Can't include data in MSG_EOF message. */
748				if (uiop->uio_resid != 0) {
749					eprintsoline(so, EINVAL);
750					return (EINVAL);
751				}
752
753				/*
754				 * This is the same sequence as done in
755				 * shutdown(SHUT_WR).
756				 */
757				mutex_enter(&so->so_lock);
758				so_lock_single(so);
759				socantsendmore(so);
760				cv_broadcast(&so->so_snd_cv);
761				so->so_state |= SS_ISDISCONNECTING;
762				mutex_exit(&so->so_lock);
763
764				pollwakeup(&so->so_poll_list, POLLOUT);
765				sctp_recvd((struct sctp_s *)so->so_proto_handle,
766				    so->so_rcvbuf);
767				error = sctp_disconnect(
768				    (struct sctp_s *)so->so_proto_handle);
769
770				mutex_enter(&so->so_lock);
771				so_unlock_single(so, SOLOCKED);
772				mutex_exit(&so->so_lock);
773				return (error);
774			}
775		}
776	} else {
777		optlen = 0;
778	}
779
780	mutex_enter(&so->so_lock);
781	for (;;) {
782		if (so->so_state & SS_CANTSENDMORE) {
783			mutex_exit(&so->so_lock);
784			return (EPIPE);
785		}
786
787		if (so->so_error != 0) {
788			error = sogeterr(so, B_TRUE);
789			mutex_exit(&so->so_lock);
790			return (error);
791		}
792
793		if (!so->so_snd_qfull)
794			break;
795
796		if (so->so_state & SS_CLOSING) {
797			mutex_exit(&so->so_lock);
798			return (EINTR);
799		}
800		/*
801		 * Xmit window full in a blocking socket.
802		 */
803		if ((uiop->uio_fmode & (FNDELAY|FNONBLOCK)) ||
804		    (flags & MSG_DONTWAIT)) {
805			mutex_exit(&so->so_lock);
806			return (EAGAIN);
807		} else {
808			/*
809			 * Wait for space to become available and try again.
810			 */
811			error = cv_wait_sig(&so->so_snd_cv, &so->so_lock);
812			if (!error) { /* signal */
813				mutex_exit(&so->so_lock);
814				return (EINTR);
815			}
816		}
817	}
818	msglen = count = uiop->uio_resid;
819
820	/* Don't allow sending a message larger than the send buffer size. */
821	/* XXX Transport module need to enforce this */
822	if (msglen > so->so_sndbuf) {
823		mutex_exit(&so->so_lock);
824		return (EMSGSIZE);
825	}
826
827	/*
828	 * Allow piggybacking data on handshake messages (SS_ISCONNECTING).
829	 */
830	if (!(so->so_state & (SS_ISCONNECTING | SS_ISCONNECTED))) {
831		/*
832		 * We need to check here for listener so that the
833		 * same error will be returned as with a TCP socket.
834		 * In this case, sosctp_connect() returns EOPNOTSUPP
835		 * while a TCP socket returns ENOTCONN instead.  Catch it
836		 * here to have the same behavior as a TCP socket.
837		 *
838		 * We also need to make sure that the peer address is
839		 * provided before we attempt to do the connect.
840		 */
841		if ((so->so_state & SS_ACCEPTCONN) ||
842		    msg->msg_name == NULL) {
843			mutex_exit(&so->so_lock);
844			error = ENOTCONN;
845			goto error_nofree;
846		}
847		mutex_exit(&so->so_lock);
848		fflag = uiop->uio_fmode;
849		if (flags & MSG_DONTWAIT) {
850			fflag |= FNDELAY;
851		}
852		error = sosctp_connect(so, msg->msg_name, msg->msg_namelen,
853		    fflag, (so->so_version == SOV_XPG4_2) * _SOCONNECT_XPG4_2,
854		    cr);
855		if (error) {
856			/*
857			 * Check for non-fatal errors, socket connected
858			 * while the lock had been lifted.
859			 */
860			if (error != EISCONN && error != EALREADY) {
861				goto error_nofree;
862			}
863			error = 0;
864		}
865	} else {
866		mutex_exit(&so->so_lock);
867	}
868
869	mctl = sctp_alloc_hdr(msg->msg_name, msg->msg_namelen,
870	    msg->msg_control, optlen, SCTP_CAN_BLOCK);
871	if (mctl == NULL) {
872		error = EINTR;
873		goto error_nofree;
874	}
875
876	/* Copy in the message. */
877	if ((error = sosctp_uiomove(mctl, count, ss->ss_wrsize, ss->ss_wroff,
878	    uiop, flags, cr)) != 0) {
879		goto error_ret;
880	}
881	error = sctp_sendmsg((struct sctp_s *)so->so_proto_handle, mctl, 0);
882	if (error == 0)
883		return (0);
884
885error_ret:
886	freemsg(mctl);
887error_nofree:
888	mutex_enter(&so->so_lock);
889	if ((error == EPIPE) && (so->so_state & SS_CANTSENDMORE)) {
890		/*
891		 * We received shutdown between the time lock was
892		 * lifted and call to sctp_sendmsg().
893		 */
894		mutex_exit(&so->so_lock);
895		return (EPIPE);
896	}
897	mutex_exit(&so->so_lock);
898	return (error);
899}
900
901/*
902 * Send message on 1-N socket. Connects automatically if there is
903 * no association.
904 */
905static int
906sosctp_seq_sendmsg(struct sonode *so, struct nmsghdr *msg, struct uio *uiop,
907    struct cred *cr)
908{
909	struct sctp_sonode *ss;
910	struct sctp_soassoc *ssa;
911	struct cmsghdr *cmsg;
912	struct sctp_sndrcvinfo *sinfo;
913	int aid = 0;
914	mblk_t *mctl;
915	int namelen, optlen, flags;
916	ssize_t count, msglen;
917	int error;
918	uint16_t s_flags = 0;
919
920	ASSERT(so->so_type == SOCK_SEQPACKET);
921
922	/*
923	 * There shouldn't be problems with alignment, as the memory for
924	 * msg_control was alloced with kmem_alloc.
925	 */
926	cmsg = sosctp_find_cmsg(msg->msg_control, msg->msg_controllen,
927	    SCTP_SNDRCV);
928	if (cmsg != NULL) {
929		if (cmsg->cmsg_len < (sizeof (*sinfo) + sizeof (*cmsg))) {
930			eprintsoline(so, EINVAL);
931			return (EINVAL);
932		}
933		sinfo = (struct sctp_sndrcvinfo *)(cmsg + 1);
934		s_flags = sinfo->sinfo_flags;
935		aid = sinfo->sinfo_assoc_id;
936	}
937
938	ss = SOTOSSO(so);
939	namelen = msg->msg_namelen;
940
941	if (msg->msg_controllen > 0) {
942		optlen = msg->msg_controllen;
943	} else {
944		optlen = 0;
945	}
946
947	mutex_enter(&so->so_lock);
948
949	/*
950	 * If there is no association id, connect to address specified
951	 * in msg_name.  Otherwise look up the association using the id.
952	 */
953	if (aid == 0) {
954		/*
955		 * Connect and shutdown cannot be done together, so check for
956		 * MSG_EOF.
957		 */
958		if (msg->msg_name == NULL || namelen == 0 ||
959		    (s_flags & MSG_EOF)) {
960			error = EINVAL;
961			eprintsoline(so, error);
962			goto done;
963		}
964		flags = uiop->uio_fmode;
965		if (msg->msg_flags & MSG_DONTWAIT) {
966			flags |= FNDELAY;
967		}
968		so_lock_single(so);
969		error = sosctp_assoc_createconn(ss, msg->msg_name, namelen,
970		    msg->msg_control, optlen, flags, cr, &ssa);
971		if (error) {
972			if ((so->so_version == SOV_XPG4_2) &&
973			    (error == EHOSTUNREACH)) {
974				error = ENETUNREACH;
975			}
976			if (ssa == NULL) {
977				/*
978				 * Fatal error during connect(). Bail out.
979				 * If ssa exists, it means that the handshake
980				 * is in progress.
981				 */
982				eprintsoline(so, error);
983				so_unlock_single(so, SOLOCKED);
984				goto done;
985			}
986			/*
987			 * All the errors are non-fatal ones, don't return
988			 * e.g. EINPROGRESS from sendmsg().
989			 */
990			error = 0;
991		}
992		so_unlock_single(so, SOLOCKED);
993	} else {
994		if ((error = sosctp_assoc(ss, aid, &ssa)) != 0) {
995			eprintsoline(so, error);
996			goto done;
997		}
998	}
999
1000	/*
1001	 * Now we have an association.
1002	 */
1003	flags = msg->msg_flags;
1004
1005	/*
1006	 * MSG_EOF initiates graceful shutdown.
1007	 */
1008	if (s_flags & MSG_EOF) {
1009		if (uiop->uio_resid) {
1010			/*
1011			 * Can't include data in MSG_EOF message.
1012			 */
1013			error = EINVAL;
1014		} else {
1015			mutex_exit(&so->so_lock);
1016			ssa->ssa_state |= SS_ISDISCONNECTING;
1017			sctp_recvd((struct sctp_s *)ssa->ssa_conn,
1018			    so->so_rcvbuf);
1019			error = sctp_disconnect((struct sctp_s *)ssa->ssa_conn);
1020			mutex_enter(&so->so_lock);
1021		}
1022		goto refrele;
1023	}
1024
1025	for (;;) {
1026		if (ssa->ssa_state & SS_CANTSENDMORE) {
1027			SSA_REFRELE(ss, ssa);
1028			mutex_exit(&so->so_lock);
1029			return (EPIPE);
1030		}
1031		if (ssa->ssa_error != 0) {
1032			error = ssa->ssa_error;
1033			ssa->ssa_error = 0;
1034			goto refrele;
1035		}
1036
1037		if (!ssa->ssa_snd_qfull)
1038			break;
1039
1040		if (so->so_state & SS_CLOSING) {
1041			error = EINTR;
1042			goto refrele;
1043		}
1044		if ((uiop->uio_fmode & (FNDELAY|FNONBLOCK)) ||
1045		    (flags & MSG_DONTWAIT)) {
1046			error = EAGAIN;
1047			goto refrele;
1048		} else {
1049			/*
1050			 * Wait for space to become available and try again.
1051			 */
1052			error = cv_wait_sig(&so->so_snd_cv, &so->so_lock);
1053			if (!error) { /* signal */
1054				error = EINTR;
1055				goto refrele;
1056			}
1057		}
1058	}
1059
1060	msglen = count = uiop->uio_resid;
1061
1062	/* Don't allow sending a message larger than the send buffer size. */
1063	if (msglen > so->so_sndbuf) {
1064		error = EMSGSIZE;
1065		goto refrele;
1066	}
1067
1068	/*
1069	 * Update TX buffer usage here so that we can lift the socket lock.
1070	 */
1071	mutex_exit(&so->so_lock);
1072
1073	mctl = sctp_alloc_hdr(msg->msg_name, namelen, msg->msg_control,
1074	    optlen, SCTP_CAN_BLOCK);
1075	if (mctl == NULL) {
1076		error = EINTR;
1077		goto lock_rele;
1078	}
1079
1080	/* Copy in the message. */
1081	if ((error = sosctp_uiomove(mctl, count, ssa->ssa_wrsize,
1082	    ssa->ssa_wroff, uiop, flags, cr)) != 0) {
1083		goto lock_rele;
1084	}
1085	error = sctp_sendmsg((struct sctp_s *)ssa->ssa_conn, mctl, 0);
1086lock_rele:
1087	mutex_enter(&so->so_lock);
1088	if (error != 0) {
1089		freemsg(mctl);
1090		if ((error == EPIPE) && (ssa->ssa_state & SS_CANTSENDMORE)) {
1091			/*
1092			 * We received shutdown between the time lock was
1093			 * lifted and call to sctp_sendmsg().
1094			 */
1095			SSA_REFRELE(ss, ssa);
1096			mutex_exit(&so->so_lock);
1097			return (EPIPE);
1098		}
1099	}
1100
1101refrele:
1102	SSA_REFRELE(ss, ssa);
1103done:
1104	mutex_exit(&so->so_lock);
1105	return (error);
1106}
1107
1108/*
1109 * Get address of remote node.
1110 */
1111/* ARGSUSED */
1112static int
1113sosctp_getpeername(struct sonode *so, struct sockaddr *addr, socklen_t *addrlen,
1114    boolean_t accept, struct cred *cr)
1115{
1116	return (sctp_getpeername((struct sctp_s *)so->so_proto_handle, addr,
1117	    addrlen));
1118}
1119
1120/*
1121 * Get local address.
1122 */
1123/* ARGSUSED */
1124static int
1125sosctp_getsockname(struct sonode *so, struct sockaddr *addr, socklen_t *addrlen,
1126    struct cred *cr)
1127{
1128	return (sctp_getsockname((struct sctp_s *)so->so_proto_handle, addr,
1129	    addrlen));
1130}
1131
1132/*
1133 * Called from shutdown().
1134 */
1135/* ARGSUSED */
1136static int
1137sosctp_shutdown(struct sonode *so, int how, struct cred *cr)
1138{
1139	uint_t state_change;
1140	int wakesig = 0;
1141	int error = 0;
1142
1143	mutex_enter(&so->so_lock);
1144	/*
1145	 * Record the current state and then perform any state changes.
1146	 * Then use the difference between the old and new states to
1147	 * determine which needs to be done.
1148	 */
1149	state_change = so->so_state;
1150
1151	switch (how) {
1152	case SHUT_RD:
1153		socantrcvmore(so);
1154		break;
1155	case SHUT_WR:
1156		socantsendmore(so);
1157		break;
1158	case SHUT_RDWR:
1159		socantsendmore(so);
1160		socantrcvmore(so);
1161		break;
1162	default:
1163		mutex_exit(&so->so_lock);
1164		return (EINVAL);
1165	}
1166
1167	state_change = so->so_state & ~state_change;
1168
1169	if (state_change & SS_CANTRCVMORE) {
1170		if (so->so_rcv_q_head == NULL) {
1171			cv_signal(&so->so_rcv_cv);
1172		}
1173		wakesig = POLLIN|POLLRDNORM;
1174
1175		socket_sendsig(so, SOCKETSIG_READ);
1176	}
1177	if (state_change & SS_CANTSENDMORE) {
1178		cv_broadcast(&so->so_snd_cv);
1179		wakesig |= POLLOUT;
1180
1181		so->so_state |= SS_ISDISCONNECTING;
1182	}
1183	mutex_exit(&so->so_lock);
1184
1185	pollwakeup(&so->so_poll_list, wakesig);
1186
1187	if (state_change & SS_CANTSENDMORE) {
1188		sctp_recvd((struct sctp_s *)so->so_proto_handle, so->so_rcvbuf);
1189		error = sctp_disconnect((struct sctp_s *)so->so_proto_handle);
1190	}
1191
1192	/*
1193	 * HACK: sctp_disconnect() may return EWOULDBLOCK.  But this error is
1194	 * not documented in standard socket API.  Catch it here.
1195	 */
1196	if (error == EWOULDBLOCK)
1197		error = 0;
1198	return (error);
1199}
1200
1201/*
1202 * Get socket options.
1203 */
1204/*ARGSUSED5*/
1205static int
1206sosctp_getsockopt(struct sonode *so, int level, int option_name,
1207    void *optval, socklen_t *optlenp, int flags, struct cred *cr)
1208{
1209	if (level == IPPROTO_SCTP) {
1210		/*
1211		 * Should go through ioctl().
1212		 */
1213		return (EINVAL);
1214	}
1215	return (sctp_get_opt((struct sctp_s *)so->so_proto_handle, level,
1216	    option_name, optval, optlenp));
1217}
1218
1219/*
1220 * Set socket options
1221 */
1222/* ARGSUSED */
1223static int
1224sosctp_setsockopt(struct sonode *so, int level, int option_name,
1225    const void *optval, t_uscalar_t optlen, struct cred *cr)
1226{
1227	struct sctp_sonode *ss = SOTOSSO(so);
1228	struct sctp_soassoc *ssa = NULL;
1229	sctp_assoc_t id;
1230	int error, rc;
1231	void *conn = NULL;
1232
1233	mutex_enter(&so->so_lock);
1234
1235	/*
1236	 * For some SCTP level options, one can select the association this
1237	 * applies to.
1238	 */
1239	if (so->so_type == SOCK_STREAM) {
1240		conn = so->so_proto_handle;
1241	} else {
1242		/*
1243		 * SOCK_SEQPACKET only
1244		 */
1245		id = 0;
1246		if (level == IPPROTO_SCTP) {
1247			switch (option_name) {
1248			case SCTP_RTOINFO:
1249			case SCTP_ASSOCINFO:
1250			case SCTP_SET_PEER_PRIMARY_ADDR:
1251			case SCTP_PRIMARY_ADDR:
1252			case SCTP_PEER_ADDR_PARAMS:
1253				/*
1254				 * Association ID is the first element
1255				 * params struct
1256				 */
1257				if (optlen < sizeof (sctp_assoc_t)) {
1258					error = EINVAL;
1259					eprintsoline(so, error);
1260					goto done;
1261				}
1262				id = *(sctp_assoc_t *)optval;
1263				break;
1264			case SCTP_DEFAULT_SEND_PARAM:
1265				if (optlen != sizeof (struct sctp_sndrcvinfo)) {
1266					error = EINVAL;
1267					eprintsoline(so, error);
1268					goto done;
1269				}
1270				id = ((struct sctp_sndrcvinfo *)
1271				    optval)->sinfo_assoc_id;
1272				break;
1273			case SCTP_INITMSG:
1274				/*
1275				 * Only applies to future associations
1276				 */
1277				conn = so->so_proto_handle;
1278				break;
1279			default:
1280				break;
1281			}
1282		} else if (level == SOL_SOCKET) {
1283			if (option_name == SO_LINGER) {
1284				error = EOPNOTSUPP;
1285				eprintsoline(so, error);
1286				goto done;
1287			}
1288			/*
1289			 * These 2 options are applied to all associations.
1290			 * The other socket level options are only applied
1291			 * to the socket (not associations).
1292			 */
1293			if ((option_name != SO_RCVBUF) &&
1294			    (option_name != SO_SNDBUF)) {
1295				conn = so->so_proto_handle;
1296			}
1297		} else {
1298			conn = NULL;
1299		}
1300
1301		/*
1302		 * If association ID was specified, do op on that assoc.
1303		 * Otherwise set the default setting of a socket.
1304		 */
1305		if (id != 0) {
1306			if ((error = sosctp_assoc(ss, id, &ssa)) != 0) {
1307				eprintsoline(so, error);
1308				goto done;
1309			}
1310			conn = ssa->ssa_conn;
1311		}
1312	}
1313	dprint(2, ("sosctp_setsockopt %p (%d) - conn %p %d %d id:%d\n",
1314	    (void *)ss, so->so_type, (void *)conn, level, option_name, id));
1315
1316	ASSERT(ssa == NULL || (ssa != NULL && conn != NULL));
1317	if (conn != NULL) {
1318		mutex_exit(&so->so_lock);
1319		error = sctp_set_opt((struct sctp_s *)conn, level, option_name,
1320		    optval, optlen);
1321		mutex_enter(&so->so_lock);
1322		if (ssa != NULL)
1323			SSA_REFRELE(ss, ssa);
1324	} else {
1325		/*
1326		 * 1-N socket, and we have to apply the operation to ALL
1327		 * associations. Like with anything of this sort, the
1328		 * problem is what to do if the operation fails.
1329		 * Just try to apply the setting to everyone, but store
1330		 * error number if someone returns such.  And since we are
1331		 * looping through all possible aids, some of them can be
1332		 * invalid.  We just ignore this kind (sosctp_assoc()) of
1333		 * errors.
1334		 */
1335		sctp_assoc_t aid;
1336
1337		mutex_exit(&so->so_lock);
1338		error = sctp_set_opt((struct sctp_s *)so->so_proto_handle,
1339		    level, option_name, optval, optlen);
1340		mutex_enter(&so->so_lock);
1341		for (aid = 1; aid < ss->ss_maxassoc; aid++) {
1342			if (sosctp_assoc(ss, aid, &ssa) != 0)
1343				continue;
1344			mutex_exit(&so->so_lock);
1345			rc = sctp_set_opt((struct sctp_s *)ssa->ssa_conn, level,
1346			    option_name, optval, optlen);
1347			mutex_enter(&so->so_lock);
1348			SSA_REFRELE(ss, ssa);
1349			if (error == 0) {
1350				error = rc;
1351			}
1352		}
1353	}
1354done:
1355	mutex_exit(&so->so_lock);
1356	return (error);
1357}
1358
1359/*ARGSUSED*/
1360static int
1361sosctp_ioctl(struct sonode *so, int cmd, intptr_t arg, int mode,
1362    struct cred *cr, int32_t *rvalp)
1363{
1364	struct sctp_sonode	*ss;
1365	int32_t			value;
1366	int			error;
1367	int			intval;
1368	pid_t			pid;
1369	struct sctp_soassoc	*ssa;
1370	void			*conn;
1371	void			*buf;
1372	STRUCT_DECL(sctpopt, opt);
1373	uint32_t		optlen;
1374	int			buflen;
1375
1376	ss = SOTOSSO(so);
1377
1378	/* handle socket specific ioctls */
1379	switch (cmd) {
1380	case FIONBIO:
1381		if (so_copyin((void *)arg, &value, sizeof (int32_t),
1382		    (mode & (int)FKIOCTL))) {
1383			return (EFAULT);
1384		}
1385		mutex_enter(&so->so_lock);
1386		if (value) {
1387			so->so_state |= SS_NDELAY;
1388		} else {
1389			so->so_state &= ~SS_NDELAY;
1390		}
1391		mutex_exit(&so->so_lock);
1392		return (0);
1393
1394	case FIOASYNC:
1395		if (so_copyin((void *)arg, &value, sizeof (int32_t),
1396		    (mode & (int)FKIOCTL))) {
1397			return (EFAULT);
1398		}
1399		mutex_enter(&so->so_lock);
1400
1401		if (value) {
1402			/* Turn on SIGIO */
1403			so->so_state |= SS_ASYNC;
1404		} else {
1405			/* Turn off SIGIO */
1406			so->so_state &= ~SS_ASYNC;
1407		}
1408		mutex_exit(&so->so_lock);
1409		return (0);
1410
1411	case SIOCSPGRP:
1412	case FIOSETOWN:
1413		if (so_copyin((void *)arg, &pid, sizeof (pid_t),
1414		    (mode & (int)FKIOCTL))) {
1415			return (EFAULT);
1416		}
1417		mutex_enter(&so->so_lock);
1418
1419		error = (pid != so->so_pgrp) ? socket_chgpgrp(so, pid) : 0;
1420		mutex_exit(&so->so_lock);
1421		return (error);
1422
1423	case SIOCGPGRP:
1424	case FIOGETOWN:
1425		if (so_copyout(&so->so_pgrp, (void *)arg,
1426		    sizeof (pid_t), (mode & (int)FKIOCTL)))
1427			return (EFAULT);
1428		return (0);
1429
1430	case FIONREAD:
1431		/* XXX: Cannot be used unless standard buffer is used */
1432		/*
1433		 * Return number of bytes of data in all data messages
1434		 * in queue in "arg".
1435		 * For stream socket, amount of available data.
1436		 * For sock_dgram, # of available bytes + addresses.
1437		 */
1438		intval = (so->so_state & SS_ACCEPTCONN) ? 0 :
1439		    MIN(so->so_rcv_queued, INT_MAX);
1440		if (so_copyout(&intval, (void *)arg, sizeof (intval),
1441		    (mode & (int)FKIOCTL)))
1442			return (EFAULT);
1443		return (0);
1444	case SIOCATMARK:
1445		/*
1446		 * No support for urgent data.
1447		 */
1448		intval = 0;
1449
1450		if (so_copyout(&intval, (void *)arg, sizeof (int),
1451		    (mode & (int)FKIOCTL)))
1452			return (EFAULT);
1453		return (0);
1454	case SIOCSCTPGOPT:
1455		STRUCT_INIT(opt, mode);
1456
1457		if (so_copyin((void *)arg, STRUCT_BUF(opt), STRUCT_SIZE(opt),
1458		    (mode & (int)FKIOCTL))) {
1459			return (EFAULT);
1460		}
1461		if ((optlen = STRUCT_FGET(opt, sopt_len)) > SO_MAXARGSIZE)
1462			return (EINVAL);
1463
1464		/*
1465		 * Find the correct sctp_t based on whether it is 1-N socket
1466		 * or not.
1467		 */
1468		intval = STRUCT_FGET(opt, sopt_aid);
1469		mutex_enter(&so->so_lock);
1470		if ((so->so_type == SOCK_SEQPACKET) && intval) {
1471			if ((error = sosctp_assoc(ss, intval, &ssa)) != 0) {
1472				mutex_exit(&so->so_lock);
1473				return (error);
1474			}
1475			conn = ssa->ssa_conn;
1476			ASSERT(conn != NULL);
1477		} else {
1478			conn = so->so_proto_handle;
1479			ssa = NULL;
1480		}
1481		mutex_exit(&so->so_lock);
1482
1483		/* Copyin the option buffer and then call sctp_get_opt(). */
1484		buflen = optlen;
1485		/* Let's allocate a buffer enough to hold an int */
1486		if (buflen < sizeof (uint32_t))
1487			buflen = sizeof (uint32_t);
1488		buf = kmem_alloc(buflen, KM_SLEEP);
1489		if (so_copyin(STRUCT_FGETP(opt, sopt_val), buf, optlen,
1490		    (mode & (int)FKIOCTL))) {
1491			if (ssa != NULL) {
1492				mutex_enter(&so->so_lock);
1493				SSA_REFRELE(ss, ssa);
1494				mutex_exit(&so->so_lock);
1495			}
1496			kmem_free(buf, buflen);
1497			return (EFAULT);
1498		}
1499		/* The option level has to be IPPROTO_SCTP */
1500		error = sctp_get_opt((struct sctp_s *)conn, IPPROTO_SCTP,
1501		    STRUCT_FGET(opt, sopt_name), buf, &optlen);
1502		if (ssa != NULL) {
1503			mutex_enter(&so->so_lock);
1504			SSA_REFRELE(ss, ssa);
1505			mutex_exit(&so->so_lock);
1506		}
1507		optlen = MIN(buflen, optlen);
1508		/* No error, copyout the result with the correct buf len. */
1509		if (error == 0) {
1510			STRUCT_FSET(opt, sopt_len, optlen);
1511			if (so_copyout(STRUCT_BUF(opt), (void *)arg,
1512			    STRUCT_SIZE(opt), (mode & (int)FKIOCTL))) {
1513				error = EFAULT;
1514			} else if (so_copyout(buf, STRUCT_FGETP(opt, sopt_val),
1515			    optlen, (mode & (int)FKIOCTL))) {
1516				error = EFAULT;
1517			}
1518		}
1519		kmem_free(buf, buflen);
1520		return (error);
1521
1522	case SIOCSCTPSOPT:
1523		STRUCT_INIT(opt, mode);
1524
1525		if (so_copyin((void *)arg, STRUCT_BUF(opt), STRUCT_SIZE(opt),
1526		    (mode & (int)FKIOCTL))) {
1527			return (EFAULT);
1528		}
1529		if ((optlen = STRUCT_FGET(opt, sopt_len)) > SO_MAXARGSIZE)
1530			return (EINVAL);
1531
1532		/*
1533		 * Find the correct sctp_t based on whether it is 1-N socket
1534		 * or not.
1535		 */
1536		intval = STRUCT_FGET(opt, sopt_aid);
1537		mutex_enter(&so->so_lock);
1538		if (intval != 0) {
1539			if ((error = sosctp_assoc(ss, intval, &ssa)) != 0) {
1540				mutex_exit(&so->so_lock);
1541				return (error);
1542			}
1543			conn = ssa->ssa_conn;
1544			ASSERT(conn != NULL);
1545		} else {
1546			conn = so->so_proto_handle;
1547			ssa = NULL;
1548		}
1549		mutex_exit(&so->so_lock);
1550
1551		/* Copyin the option buffer and then call sctp_set_opt(). */
1552		buf = kmem_alloc(optlen, KM_SLEEP);
1553		if (so_copyin(STRUCT_FGETP(opt, sopt_val), buf, optlen,
1554		    (mode & (int)FKIOCTL))) {
1555			if (ssa != NULL) {
1556				mutex_enter(&so->so_lock);
1557				SSA_REFRELE(ss, ssa);
1558				mutex_exit(&so->so_lock);
1559			}
1560			kmem_free(buf, intval);
1561			return (EFAULT);
1562		}
1563		/* The option level has to be IPPROTO_SCTP */
1564		error = sctp_set_opt((struct sctp_s *)conn, IPPROTO_SCTP,
1565		    STRUCT_FGET(opt, sopt_name), buf, optlen);
1566		if (ssa) {
1567			mutex_enter(&so->so_lock);
1568			SSA_REFRELE(ss, ssa);
1569			mutex_exit(&so->so_lock);
1570		}
1571		kmem_free(buf, optlen);
1572		return (error);
1573
1574	case SIOCSCTPPEELOFF: {
1575		struct sonode *nso;
1576		struct sctp_uc_swap us;
1577		int nfd;
1578		struct file *nfp;
1579		struct vnode *nvp = NULL;
1580		struct sockparams *sp;
1581
1582		dprint(2, ("sctppeeloff %p\n", (void *)ss));
1583
1584		if (so->so_type != SOCK_SEQPACKET) {
1585			return (EOPNOTSUPP);
1586		}
1587		if (so_copyin((void *)arg, &intval, sizeof (intval),
1588		    (mode & (int)FKIOCTL))) {
1589			return (EFAULT);
1590		}
1591		if (intval == 0) {
1592			return (EINVAL);
1593		}
1594
1595		/*
1596		 * Find sockparams. This is different from parent's entry,
1597		 * as the socket type is different.
1598		 */
1599		error = solookup(so->so_family, SOCK_STREAM, so->so_protocol,
1600		    &sp);
1601
1602		/*
1603		 * Allocate the user fd.
1604		 */
1605		if ((nfd = ufalloc(0)) == -1) {
1606			eprintsoline(so, EMFILE);
1607			return (EMFILE);
1608		}
1609
1610		/*
1611		 * Copy the fd out.
1612		 */
1613		if (so_copyout(&nfd, (void *)arg, sizeof (nfd),
1614		    (mode & (int)FKIOCTL))) {
1615			error = EFAULT;
1616			goto err;
1617		}
1618		mutex_enter(&so->so_lock);
1619
1620		/*
1621		 * Don't use sosctp_assoc() in order to peel off disconnected
1622		 * associations.
1623		 */
1624		ssa = ((uint32_t)intval >= ss->ss_maxassoc) ? NULL :
1625		    ss->ss_assocs[intval].ssi_assoc;
1626		if (ssa == NULL) {
1627			mutex_exit(&so->so_lock);
1628			error = EINVAL;
1629			goto err;
1630		}
1631		SSA_REFHOLD(ssa);
1632
1633		nso = socksctp_create(sp, so->so_family, SOCK_STREAM,
1634		    so->so_protocol, so->so_version, SOCKET_NOSLEEP,
1635		    &error, cr);
1636		if (nso == NULL) {
1637			SSA_REFRELE(ss, ssa);
1638			mutex_exit(&so->so_lock);
1639			goto err;
1640		}
1641		/* cannot fail, only inheriting properties */
1642		(void) sosctp_init(nso, so, CRED(), 0);
1643		nvp = SOTOV(nso);
1644		so_lock_single(so);
1645		mutex_exit(&so->so_lock);
1646		us.sus_handle = SOTOSSO(nso);
1647		us.sus_upcalls = &sosctp_sock_upcalls;
1648
1649		/*
1650		 * Upcalls to new socket are blocked for the duration of
1651		 * downcall.
1652		 */
1653		mutex_enter(&nso->so_lock);
1654
1655		error = sctp_set_opt((struct sctp_s *)ssa->ssa_conn,
1656		    IPPROTO_SCTP, SCTP_UC_SWAP, &us, sizeof (us));
1657		if (error) {
1658			goto peelerr;
1659		}
1660		error = falloc(nvp, FWRITE|FREAD, &nfp, NULL);
1661		if (error) {
1662			goto peelerr;
1663		}
1664
1665		/*
1666		 * fill in the entries that falloc reserved
1667		 */
1668		nfp->f_vnode = nvp;
1669		mutex_exit(&nfp->f_tlock);
1670		setf(nfd, nfp);
1671
1672		mutex_enter(&so->so_lock);
1673
1674		sosctp_assoc_move(ss, SOTOSSO(nso), ssa);
1675
1676		mutex_exit(&nso->so_lock);
1677
1678		ssa->ssa_conn = NULL;
1679		sosctp_assoc_free(ss, ssa);
1680
1681		so_unlock_single(so, SOLOCKED);
1682		mutex_exit(&so->so_lock);
1683
1684		return (0);
1685
1686err:
1687		setf(nfd, NULL);
1688		eprintsoline(so, error);
1689		return (error);
1690
1691peelerr:
1692		mutex_exit(&nso->so_lock);
1693		mutex_enter(&so->so_lock);
1694		ASSERT(nso->so_count == 1);
1695		nso->so_count = 0;
1696		so_unlock_single(so, SOLOCKED);
1697		SSA_REFRELE(ss, ssa);
1698		mutex_exit(&so->so_lock);
1699
1700		setf(nfd, NULL);
1701		ASSERT(nvp->v_count == 1);
1702		socket_destroy(nso);
1703		eprintsoline(so, error);
1704		return (error);
1705	}
1706	default:
1707		return (EINVAL);
1708	}
1709}
1710
1711/*ARGSUSED*/
1712static int
1713sosctp_close(struct sonode *so, int flag, struct cred *cr)
1714{
1715	struct sctp_sonode *ss;
1716	struct sctp_sa_id *ssi;
1717	struct sctp_soassoc *ssa;
1718	int32_t i;
1719
1720	ss = SOTOSSO(so);
1721
1722	/*
1723	 * Initiate connection shutdown.  Update SCTP's receive
1724	 * window.
1725	 */
1726	sctp_recvd((struct sctp_s *)so->so_proto_handle,
1727	    so->so_rcvbuf - so->so_rcv_queued);
1728	(void) sctp_disconnect((struct sctp_s *)so->so_proto_handle);
1729
1730	/*
1731	 * New associations can't come in, but old ones might get
1732	 * closed in upcall. Protect against that by taking a reference
1733	 * on the association.
1734	 */
1735	mutex_enter(&so->so_lock);
1736	ssi = ss->ss_assocs;
1737	for (i = 0; i < ss->ss_maxassoc; i++, ssi++) {
1738		if ((ssa = ssi->ssi_assoc) != NULL) {
1739			SSA_REFHOLD(ssa);
1740			sosctp_assoc_isdisconnected(ssa, 0);
1741			mutex_exit(&so->so_lock);
1742
1743			sctp_recvd((struct sctp_s *)ssa->ssa_conn,
1744			    so->so_rcvbuf - ssa->ssa_rcv_queued);
1745			(void) sctp_disconnect((struct sctp_s *)ssa->ssa_conn);
1746
1747			mutex_enter(&so->so_lock);
1748			SSA_REFRELE(ss, ssa);
1749		}
1750	}
1751	mutex_exit(&so->so_lock);
1752
1753	return (0);
1754}
1755
1756/*
1757 * Closes incoming connections which were never accepted, frees
1758 * resources.
1759 */
1760/* ARGSUSED */
1761void
1762sosctp_fini(struct sonode *so, struct cred *cr)
1763{
1764	struct sctp_sonode *ss;
1765	struct sctp_sa_id *ssi;
1766	struct sctp_soassoc *ssa;
1767	int32_t i;
1768
1769	ss = SOTOSSO(so);
1770
1771	ASSERT(so->so_ops == &sosctp_sonodeops ||
1772	    so->so_ops == &sosctp_seq_sonodeops);
1773
1774	/* We are the sole owner of so now */
1775	mutex_enter(&so->so_lock);
1776
1777	so_rcv_flush(so);
1778
1779	/* Free all pending connections */
1780	so_acceptq_flush(so);
1781
1782	ssi = ss->ss_assocs;
1783	for (i = 0; i < ss->ss_maxassoc; i++, ssi++) {
1784		if ((ssa = ssi->ssi_assoc) != NULL) {
1785			SSA_REFHOLD(ssa);
1786			mutex_exit(&so->so_lock);
1787
1788			sctp_close((struct sctp_s *)ssa->ssa_conn);
1789
1790			mutex_enter(&so->so_lock);
1791			ssa->ssa_conn = NULL;
1792			sosctp_assoc_free(ss, ssa);
1793		}
1794	}
1795	if (ss->ss_assocs != NULL) {
1796		ASSERT(ss->ss_assoccnt == 0);
1797		kmem_free(ss->ss_assocs,
1798		    ss->ss_maxassoc * sizeof (struct sctp_sa_id));
1799	}
1800	mutex_exit(&so->so_lock);
1801
1802	if (so->so_proto_handle)
1803		sctp_close((struct sctp_s *)so->so_proto_handle);
1804	so->so_proto_handle = NULL;
1805
1806	sonode_fini(so);
1807}
1808
1809/*
1810 * Upcalls from SCTP
1811 */
1812
1813/*
1814 * This is the upcall function for 1-N (SOCK_SEQPACKET) socket when a new
1815 * association is created.  Note that the first argument (handle) is of type
1816 * sctp_sonode *, which is the one changed to a listener for new
1817 * associations.  All the other upcalls for 1-N socket take sctp_soassoc *
1818 * as handle.  The only exception is the su_properties upcall, which
1819 * can take both types as handle.
1820 */
1821/* ARGSUSED */
1822sock_upper_handle_t
1823sctp_assoc_newconn(sock_upper_handle_t parenthandle,
1824    sock_lower_handle_t connind, sock_downcalls_t *dc,
1825    struct cred *peer_cred, pid_t peer_cpid, sock_upcalls_t **ucp)
1826{
1827	struct sonode *lso = (struct sonode *)parenthandle;
1828	struct sctp_sonode *lss = SOTOSSO(lso);
1829	struct sctp_soassoc *ssa;
1830	sctp_assoc_t id;
1831
1832	ASSERT(lss->ss_type == SOSCTP_SOCKET);
1833	ASSERT(lso->so_state & SS_ACCEPTCONN);
1834	ASSERT(lso->so_proto_handle != NULL); /* closed conn */
1835	ASSERT(lso->so_type == SOCK_SEQPACKET);
1836
1837	mutex_enter(&lso->so_lock);
1838
1839	if ((id = sosctp_aid_get(lss)) == -1) {
1840		/*
1841		 * Array not large enough; increase size.
1842		 */
1843		if (sosctp_aid_grow(lss, lss->ss_maxassoc, KM_NOSLEEP) < 0) {
1844			mutex_exit(&lso->so_lock);
1845			return (NULL);
1846		}
1847		id = sosctp_aid_get(lss);
1848		ASSERT(id != -1);
1849	}
1850
1851	/*
1852	 * Create soassoc for this connection
1853	 */
1854	ssa = sosctp_assoc_create(lss, KM_NOSLEEP);
1855	if (ssa == NULL) {
1856		mutex_exit(&lso->so_lock);
1857		return (NULL);
1858	}
1859	sosctp_aid_reserve(lss, id, 1);
1860	lss->ss_assocs[id].ssi_assoc = ssa;
1861	++lss->ss_assoccnt;
1862	ssa->ssa_id = id;
1863	ssa->ssa_conn = (struct sctp_s *)connind;
1864	ssa->ssa_state = (SS_ISBOUND | SS_ISCONNECTED);
1865	ssa->ssa_wroff = lss->ss_wroff;
1866	ssa->ssa_wrsize = lss->ss_wrsize;
1867
1868	mutex_exit(&lso->so_lock);
1869
1870	*ucp = &sosctp_assoc_upcalls;
1871
1872	return ((sock_upper_handle_t)ssa);
1873}
1874
1875/* ARGSUSED */
1876static void
1877sctp_assoc_connected(sock_upper_handle_t handle, sock_connid_t id,
1878    struct cred *peer_cred, pid_t peer_cpid)
1879{
1880	struct sctp_soassoc *ssa = (struct sctp_soassoc *)handle;
1881	struct sonode *so = &ssa->ssa_sonode->ss_so;
1882
1883	ASSERT(so->so_type == SOCK_SEQPACKET);
1884	ASSERT(ssa->ssa_conn);
1885
1886	mutex_enter(&so->so_lock);
1887	sosctp_assoc_isconnected(ssa);
1888	mutex_exit(&so->so_lock);
1889}
1890
1891/* ARGSUSED */
1892static int
1893sctp_assoc_disconnected(sock_upper_handle_t handle, sock_connid_t id, int error)
1894{
1895	struct sctp_soassoc *ssa = (struct sctp_soassoc *)handle;
1896	struct sonode *so = &ssa->ssa_sonode->ss_so;
1897	int ret;
1898
1899	ASSERT(so->so_type == SOCK_SEQPACKET);
1900	ASSERT(ssa->ssa_conn != NULL);
1901
1902	mutex_enter(&so->so_lock);
1903	sosctp_assoc_isdisconnected(ssa, error);
1904	if (ssa->ssa_refcnt == 1) {
1905		ret = 1;
1906		ssa->ssa_conn = NULL;
1907	} else {
1908		ret = 0;
1909	}
1910	SSA_REFRELE(SOTOSSO(so), ssa);
1911
1912	cv_broadcast(&so->so_snd_cv);
1913
1914	mutex_exit(&so->so_lock);
1915
1916	return (ret);
1917}
1918
1919/* ARGSUSED */
1920static void
1921sctp_assoc_disconnecting(sock_upper_handle_t handle, sock_opctl_action_t action,
1922    uintptr_t arg)
1923{
1924	struct sctp_soassoc *ssa = (struct sctp_soassoc *)handle;
1925	struct sonode *so = &ssa->ssa_sonode->ss_so;
1926
1927	ASSERT(so->so_type == SOCK_SEQPACKET);
1928	ASSERT(ssa->ssa_conn != NULL);
1929	ASSERT(action == SOCK_OPCTL_SHUT_SEND);
1930
1931	mutex_enter(&so->so_lock);
1932	sosctp_assoc_isdisconnecting(ssa);
1933	mutex_exit(&so->so_lock);
1934}
1935
1936/* ARGSUSED */
1937static ssize_t
1938sctp_assoc_recv(sock_upper_handle_t handle, mblk_t *mp, size_t len, int flags,
1939    int *errorp, boolean_t *forcepush)
1940{
1941	struct sctp_soassoc *ssa = (struct sctp_soassoc *)handle;
1942	struct sctp_sonode *ss = ssa->ssa_sonode;
1943	struct sonode *so = &ss->ss_so;
1944	struct T_unitdata_ind *tind;
1945	mblk_t *mp2;
1946	union sctp_notification *sn;
1947	struct sctp_sndrcvinfo *sinfo;
1948
1949	ASSERT(ssa->ssa_type == SOSCTP_ASSOC);
1950	ASSERT(so->so_type == SOCK_SEQPACKET);
1951	ASSERT(ssa->ssa_conn != NULL); /* closed conn */
1952	ASSERT(mp != NULL);
1953
1954	ASSERT(errorp != NULL);
1955	*errorp = 0;
1956
1957	/*
1958	 * Should be getting T_unitdata_req's only.
1959	 * Must have address as part of packet.
1960	 */
1961	tind = (struct T_unitdata_ind *)mp->b_rptr;
1962	ASSERT((DB_TYPE(mp) == M_PROTO) &&
1963	    (tind->PRIM_type == T_UNITDATA_IND));
1964	ASSERT(tind->SRC_length);
1965
1966	mutex_enter(&so->so_lock);
1967
1968	/*
1969	 * Override b_flag for SCTP sockfs internal use
1970	 */
1971	mp->b_flag = (short)flags;
1972
1973	/*
1974	 * For notify messages, need to fill in association id.
1975	 * For data messages, sndrcvinfo could be in ancillary data.
1976	 */
1977	if (flags & SCTP_NOTIFICATION) {
1978		mp2 = mp->b_cont;
1979		sn = (union sctp_notification *)mp2->b_rptr;
1980		switch (sn->sn_header.sn_type) {
1981		case SCTP_ASSOC_CHANGE:
1982			sn->sn_assoc_change.sac_assoc_id = ssa->ssa_id;
1983			break;
1984		case SCTP_PEER_ADDR_CHANGE:
1985			sn->sn_paddr_change.spc_assoc_id = ssa->ssa_id;
1986			break;
1987		case SCTP_REMOTE_ERROR:
1988			sn->sn_remote_error.sre_assoc_id = ssa->ssa_id;
1989			break;
1990		case SCTP_SEND_FAILED:
1991			sn->sn_send_failed.ssf_assoc_id = ssa->ssa_id;
1992			break;
1993		case SCTP_SHUTDOWN_EVENT:
1994			sn->sn_shutdown_event.sse_assoc_id = ssa->ssa_id;
1995			break;
1996		case SCTP_ADAPTATION_INDICATION:
1997			sn->sn_adaptation_event.sai_assoc_id = ssa->ssa_id;
1998			break;
1999		case SCTP_PARTIAL_DELIVERY_EVENT:
2000			sn->sn_pdapi_event.pdapi_assoc_id = ssa->ssa_id;
2001			break;
2002		default:
2003			ASSERT(0);
2004			break;
2005		}
2006	} else {
2007		if (tind->OPT_length > 0) {
2008			struct cmsghdr	*cmsg;
2009			char		*cend;
2010
2011			cmsg = (struct cmsghdr *)
2012			    ((uchar_t *)mp->b_rptr + tind->OPT_offset);
2013			cend = (char *)cmsg + tind->OPT_length;
2014			for (;;) {
2015				if ((char *)(cmsg + 1) > cend ||
2016				    ((char *)cmsg + cmsg->cmsg_len) > cend) {
2017					break;
2018				}
2019				if ((cmsg->cmsg_level == IPPROTO_SCTP) &&
2020				    (cmsg->cmsg_type == SCTP_SNDRCV)) {
2021					sinfo = (struct sctp_sndrcvinfo *)
2022					    (cmsg + 1);
2023					sinfo->sinfo_assoc_id = ssa->ssa_id;
2024					break;
2025				}
2026				if (cmsg->cmsg_len > 0) {
2027					cmsg = (struct cmsghdr *)
2028					    ((uchar_t *)cmsg + cmsg->cmsg_len);
2029				} else {
2030					break;
2031				}
2032			}
2033		}
2034	}
2035
2036	/*
2037	 * SCTP has reserved space in the header for storing a pointer.
2038	 * Put the pointer to assocation there, and queue the data.
2039	 */
2040	SSA_REFHOLD(ssa);
2041	ASSERT((mp->b_rptr - DB_BASE(mp)) >= sizeof (ssa));
2042	*(struct sctp_soassoc **)DB_BASE(mp) = ssa;
2043
2044	mutex_exit(&so->so_lock);
2045
2046	return (so_queue_msg((sock_upper_handle_t)so, mp, len, 0, errorp,
2047	    NULL));
2048}
2049
2050static void
2051sctp_assoc_xmitted(sock_upper_handle_t handle, boolean_t qfull)
2052{
2053	struct sctp_soassoc *ssa = (struct sctp_soassoc *)handle;
2054	struct sctp_sonode *ss = ssa->ssa_sonode;
2055
2056	ASSERT(ssa->ssa_type == SOSCTP_ASSOC);
2057	ASSERT(ss->ss_so.so_type == SOCK_SEQPACKET);
2058	ASSERT(ssa->ssa_conn != NULL);
2059
2060	mutex_enter(&ss->ss_so.so_lock);
2061
2062	ssa->ssa_snd_qfull = qfull;
2063
2064	/*
2065	 * Wake blocked writers.
2066	 */
2067	cv_broadcast(&ss->ss_so.so_snd_cv);
2068
2069	mutex_exit(&ss->ss_so.so_lock);
2070}
2071
2072static void
2073sctp_assoc_properties(sock_upper_handle_t handle,
2074    struct sock_proto_props *soppp)
2075{
2076	struct sctp_soassoc *ssa = (struct sctp_soassoc *)handle;
2077	struct sctp_sonode *ss;
2078
2079	if (ssa->ssa_type == SOSCTP_ASSOC) {
2080		ss = ssa->ssa_sonode;
2081		mutex_enter(&ss->ss_so.so_lock);
2082
2083		/*
2084		 * Only change them if they're set.
2085		 */
2086		if (soppp->sopp_wroff != 0) {
2087			ssa->ssa_wroff = soppp->sopp_wroff;
2088		}
2089		if (soppp->sopp_maxblk != 0) {
2090			ssa->ssa_wrsize = soppp->sopp_maxblk;
2091		}
2092	} else {
2093		ss = (struct sctp_sonode *)handle;
2094		mutex_enter(&ss->ss_so.so_lock);
2095
2096		if (soppp->sopp_wroff != 0) {
2097			ss->ss_wroff = soppp->sopp_wroff;
2098		}
2099		if (soppp->sopp_maxblk != 0) {
2100			ss->ss_wrsize = soppp->sopp_maxblk;
2101		}
2102	}
2103
2104	mutex_exit(&ss->ss_so.so_lock);
2105}
2106