Home | History | Annotate | Download | only in ktli
      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, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*
     23  * Copyright 1997 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     28 /*	  All Rights Reserved  	*/
     29 
     30 /*
     31  * University Copyright- Copyright (c) 1982, 1986, 1988
     32  * The Regents of the University of California
     33  * All Rights Reserved
     34  *
     35  * University Acknowledgment- Portions of this document are derived from
     36  * software developed by the University of California, Berkeley, and its
     37  * contributors.
     38  */
     39 
     40 #pragma ident	"@(#)t_ksndudat.c	1.21	05/06/08 SMI"
     41 
     42 /*
     43  * TLI-like function to send datagrams over a specified
     44  * transport endpoint.
     45  *
     46  * Returns:
     47  * 	0 on success or positive error code.
     48  */
     49 
     50 #include <sys/param.h>
     51 #include <sys/types.h>
     52 #include <sys/user.h>
     53 #include <sys/file.h>
     54 #include <sys/errno.h>
     55 #include <sys/stream.h>
     56 #include <sys/strsubr.h>
     57 #include <sys/vnode.h>
     58 #include <sys/ioctl.h>
     59 #include <sys/stropts.h>
     60 #include <sys/tihdr.h>
     61 #include <sys/timod.h>
     62 #include <sys/tiuser.h>
     63 #include <sys/t_kuser.h>
     64 #include <sys/debug.h>
     65 
     66 
     67 int
     68 t_ksndudata(TIUSER *tiptr, struct t_kunitdata *unitdata, frtn_t *frtn)
     69 {
     70 	int			msgsz;
     71 	file_t			*fp;
     72 	mblk_t			*bp;
     73 	mblk_t			*dbp;
     74 	struct T_unitdata_req	*udreq;
     75 	int			error;
     76 	int			flag;
     77 
     78 	error = 0;
     79 	fp = tiptr->fp;
     80 	msgsz = unitdata->udata.len;
     81 
     82 	/*
     83 	 * See if Class 0 is required
     84 	 */
     85 	if (frtn != NULL) {
     86 		ASSERT(unitdata->udata.udata_mp == NULL);
     87 		ASSERT(unitdata->udata.buf != NULL);
     88 		/*
     89 		 * user has supplied their own buffer, all we have to
     90 		 * do is allocate a class 0 streams buffer and set it
     91 		 * up.
     92 		 */
     93 		if ((dbp = (mblk_t *)esballoc((uchar_t *)unitdata->udata.buf,
     94 		    (size_t)msgsz, BPRI_LO, frtn)) == NULL)
     95 			return (ENOSR);
     96 
     97 		dbp->b_datap->db_type = M_DATA;
     98 		KTLILOG(2, "t_ksndudata: bp %x, ", dbp);
     99 		KTLILOG(2, "len %d, ", msgsz);
    100 		KTLILOG(2, "free func %x\n", frtn->free_func);
    101 
    102 	} else if (unitdata->udata.buf) {
    103 		ASSERT(unitdata->udata.udata_mp == NULL);
    104 		while (!(dbp = allocb(msgsz, BPRI_LO)))
    105 			if (strwaitbuf((size_t)msgsz, BPRI_LO))
    106 				return (ENOSR);
    107 
    108 		bcopy(unitdata->udata.buf, dbp->b_wptr, unitdata->udata.len);
    109 		dbp->b_datap->db_type = M_DATA;
    110 
    111 	} else if (unitdata->udata.udata_mp) {
    112 		ASSERT(unitdata->udata.buf == NULL);
    113 		/*
    114 		 * user has done it all
    115 		 */
    116 		dbp = unitdata->udata.udata_mp;
    117 		goto gotdp;
    118 
    119 	} else {
    120 		/*
    121 		 * zero length message.
    122 		 */
    123 		dbp = NULL;
    124 	}
    125 
    126 	if (dbp)
    127 		dbp->b_wptr += msgsz;		/* on behalf of the user */
    128 
    129 	/*
    130 	 * Okay, put the control part in
    131 	 */
    132 gotdp:
    133 	msgsz = (int)TUNITDATAREQSZ;
    134 	while (!(bp = allocb(msgsz + unitdata->addr.len + unitdata->opt.len,
    135 	    BPRI_LO))) {
    136 		if (strwaitbuf(msgsz + unitdata->addr.len + unitdata->opt.len,
    137 		    BPRI_LO)) {
    138 			if (dbp && (dbp != unitdata->udata.udata_mp))
    139 				freeb(dbp);
    140 			return (ENOSR);
    141 		}
    142 	}
    143 
    144 	/* LINTED pointer alignment */
    145 	udreq = (struct T_unitdata_req *)bp->b_wptr;
    146 	udreq->PRIM_type = T_UNITDATA_REQ;
    147 	udreq->DEST_length = unitdata->addr.len;
    148 	if (unitdata->addr.len) {
    149 		bcopy(unitdata->addr.buf, bp->b_wptr + msgsz,
    150 		    unitdata->addr.len);
    151 		udreq->DEST_offset = (t_scalar_t)msgsz;
    152 		msgsz += unitdata->addr.len;
    153 	} else
    154 		udreq->DEST_offset = 0;
    155 
    156 	udreq->OPT_length = unitdata->opt.len;
    157 	if (unitdata->opt.len) {
    158 		bcopy(unitdata->opt.buf, bp->b_wptr + msgsz, unitdata->opt.len);
    159 		udreq->OPT_offset = (t_scalar_t)msgsz;
    160 		msgsz += unitdata->opt.len;
    161 	} else
    162 		udreq->OPT_offset = 0;
    163 
    164 	bp->b_datap->db_type = M_PROTO;
    165 	bp->b_wptr += msgsz;
    166 
    167 	/*
    168 	 * link the two.
    169 	 */
    170 	linkb(bp, dbp);
    171 
    172 	/*
    173 	 * Put it to the transport provider.
    174 	 * tli_send() always consumes the message.
    175 	 */
    176 	flag = fp->f_flag;
    177 	error = tli_send(tiptr, bp, flag);
    178 	unitdata->udata.udata_mp = NULL;
    179 
    180 	return (error);
    181 }
    182