t_ksndudat.c revision de8c4a14ec9a49bad5e62b2cfa6c1ba21de1c708
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * CDDL HEADER START
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The contents of this file are subject to the terms of the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Common Development and Distribution License (the "License").
843e19887f64dde75055cf8842fc4db2171eff45johnlev * You may not use this file except in compliance with the License.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
843e19887f64dde75055cf8842fc4db2171eff45johnlev * or http://www.opensolaris.org/os/licensing.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * See the License for the specific language governing permissions
843e19887f64dde75055cf8842fc4db2171eff45johnlev * and limitations under the License.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * When distributing Covered Code, include this CDDL HEADER in each
843e19887f64dde75055cf8842fc4db2171eff45johnlev * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If applicable, add the following below this CDDL HEADER, with the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * fields enclosed by brackets "[]" replaced with your own identifying
843e19887f64dde75055cf8842fc4db2171eff45johnlev * information: Portions Copyright [yyyy] [name of copyright owner]
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * CDDL HEADER END
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Use is subject to license terms.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab/* All Rights Reserved */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab/*
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * University Copyright- Copyright (c) 1982, 1986, 1988
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * The Regents of the University of California
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * All Rights Reserved
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab *
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * University Acknowledgment- Portions of this document are derived from
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * software developed by the University of California, Berkeley, and its
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * contributors.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab/*
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * TLI-like function to send datagrams over a specified
843e19887f64dde75055cf8842fc4db2171eff45johnlev * transport endpoint.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Returns:
843e19887f64dde75055cf8842fc4db2171eff45johnlev * 0 on success or positive error code.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/param.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/types.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/user.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/file.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/errno.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/stream.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/strsubr.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/vnode.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/ioctl.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/stropts.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/tihdr.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/timod.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/tiuser.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/t_kuser.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/debug.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevt_ksndudata(TIUSER *tiptr, struct t_kunitdata *unitdata, frtn_t *frtn)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev int msgsz;
843e19887f64dde75055cf8842fc4db2171eff45johnlev file_t *fp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev mblk_t *bp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev mblk_t *dbp;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab struct T_unitdata_req *udreq;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab int error;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int flag;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev error = 0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev fp = tiptr->fp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev msgsz = unitdata->udata.len;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * See if Class 0 is required
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (frtn != NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(unitdata->udata.udata_mp == NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(unitdata->udata.buf != NULL);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /*
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * user has supplied their own buffer, all we have to
5d2eda970e48f8985448151c73e699614ce9f357John Levon * do is allocate a class 0 streams buffer and set it
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * up.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab */
5d2eda970e48f8985448151c73e699614ce9f357John Levon if ((dbp = (mblk_t *)esballoc((uchar_t *)unitdata->udata.buf,
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab (size_t)msgsz, BPRI_LO, frtn)) == NULL)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (ENOSR);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev dbp->b_datap->db_type = M_DATA;
843e19887f64dde75055cf8842fc4db2171eff45johnlev KTLILOG(2, "t_ksndudata: bp %x, ", dbp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev KTLILOG(2, "len %d, ", msgsz);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab KTLILOG(2, "free func %x\n", frtn->free_func);
5d2eda970e48f8985448151c73e699614ce9f357John Levon
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else if (unitdata->udata.buf) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(unitdata->udata.udata_mp == NULL);
5d2eda970e48f8985448151c73e699614ce9f357John Levon while (!(dbp = allocb(msgsz, BPRI_LO)))
5d2eda970e48f8985448151c73e699614ce9f357John Levon if (strwaitbuf((size_t)msgsz, BPRI_LO))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (ENOSR);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev bcopy(unitdata->udata.buf, dbp->b_wptr, unitdata->udata.len);
843e19887f64dde75055cf8842fc4db2171eff45johnlev dbp->b_datap->db_type = M_DATA;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else if (unitdata->udata.udata_mp) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(unitdata->udata.buf == NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * user has done it all
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev dbp = unitdata->udata.udata_mp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto gotdp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * zero length message.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab dbp = NULL;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab }
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (dbp)
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab dbp->b_wptr += msgsz; /* on behalf of the user */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /*
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * Okay, put the control part in
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rabgotdp:
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab msgsz = (int)TUNITDATAREQSZ;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /*
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * Usually sendto()s are performed with the credential of the caller;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * in this particular case we specifically use the credential of
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * the opener as this call is typically done in the context of a user
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * process but on behalf of the kernel, e.g., a client connection
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * to a server which is later shared by different users.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * At open time, we make sure to set fp->f_cred to kcred if such is
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * the case.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab *
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * Note: if the receiver uses SCM_UCRED/getpeerucred the pid will
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * appear as -1.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab while (!(bp = allocb_cred(msgsz + unitdata->addr.len +
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab unitdata->opt.len, fp->f_cred, NOPID))) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (strwaitbuf(msgsz + unitdata->addr.len + unitdata->opt.len,
843e19887f64dde75055cf8842fc4db2171eff45johnlev BPRI_LO)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (dbp && (dbp != unitdata->udata.udata_mp))
843e19887f64dde75055cf8842fc4db2171eff45johnlev freeb(dbp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (ENOSR);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* LINTED pointer alignment */
843e19887f64dde75055cf8842fc4db2171eff45johnlev udreq = (struct T_unitdata_req *)bp->b_wptr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev udreq->PRIM_type = T_UNITDATA_REQ;
843e19887f64dde75055cf8842fc4db2171eff45johnlev udreq->DEST_length = unitdata->addr.len;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (unitdata->addr.len) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab bcopy(unitdata->addr.buf, bp->b_wptr + msgsz,
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab unitdata->addr.len);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab udreq->DEST_offset = (t_scalar_t)msgsz;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab msgsz += unitdata->addr.len;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab } else
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab udreq->DEST_offset = 0;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab udreq->OPT_length = unitdata->opt.len;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab if (unitdata->opt.len) {
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab bcopy(unitdata->opt.buf, bp->b_wptr + msgsz, unitdata->opt.len);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab udreq->OPT_offset = (t_scalar_t)msgsz;
843e19887f64dde75055cf8842fc4db2171eff45johnlev msgsz += unitdata->opt.len;
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else
843e19887f64dde75055cf8842fc4db2171eff45johnlev udreq->OPT_offset = 0;
5d2eda970e48f8985448151c73e699614ce9f357John Levon
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab bp->b_datap->db_type = M_PROTO;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab bp->b_wptr += msgsz;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /*
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * link the two.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab linkb(bp, dbp);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Put it to the transport provider.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * tli_send() always consumes the message.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab */
843e19887f64dde75055cf8842fc4db2171eff45johnlev flag = fp->f_flag;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab error = tli_send(tiptr, bp, flag);
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab unitdata->udata.udata_mp = NULL;
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab return (error);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev