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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 29 /* 30 * University Copyright- Copyright (c) 1982, 1986, 1988 31 * The Regents of the University of California 32 * All Rights Reserved 33 * 34 * University Acknowledgment- Portions of this document are derived from 35 * software developed by the University of California, Berkeley, and its 36 * contributors. 37 */ 38 39 /* 40 * Contains the following utility functions: 41 * tli_send: 42 * tli_recv: 43 * get_ok_ack: 44 * 45 * Returns: 46 * See individual functions. 47 */ 48 49 #include <sys/param.h> 50 #include <sys/types.h> 51 #include <sys/proc.h> 52 #include <sys/file.h> 53 #include <sys/user.h> 54 #include <sys/vnode.h> 55 #include <sys/errno.h> 56 #include <sys/stream.h> 57 #include <sys/ioctl.h> 58 #include <sys/stropts.h> 59 #include <sys/strsubr.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/strsun.h> 65 #include <inet/common.h> 66 #include <inet/mi.h> 67 #include <netinet/ip6.h> 68 #include <inet/ip.h> 69 70 extern int getiocseqno(void); 71 72 int 73 tli_send(TIUSER *tiptr, mblk_t *bp, int fmode) 74 { 75 vnode_t *vp; 76 int error; 77 78 vp = tiptr->fp->f_vnode; 79 80 /* 81 * Send data honoring flow control and errors 82 */ 83 error = kstrputmsg(vp, bp, NULL, 0, 0, MSG_BAND | MSG_HOLDSIG, fmode); 84 return (error); 85 } 86 87 int 88 tli_recv(TIUSER *tiptr, mblk_t **bp, int fmode) 89 { 90 vnode_t *vp; 91 int error; 92 uchar_t pri; 93 int pflag; 94 rval_t rval; 95 clock_t timout; 96 97 vp = tiptr->fp->f_vnode; 98 if (fmode & (FNDELAY|FNONBLOCK)) 99 timout = 0; 100 else 101 timout = -1; 102 103 pflag = MSG_ANY; 104 pri = 0; 105 *bp = NULL; 106 error = kstrgetmsg(vp, bp, NULL, &pri, &pflag, timout, &rval); 107 if (error == ETIME) 108 error = EAGAIN; 109 110 return (error); 111 } 112 113 int 114 get_ok_ack(TIUSER *tiptr, int type, int fmode) 115 { 116 int msgsz; 117 union T_primitives *pptr; 118 mblk_t *bp; 119 int error; 120 121 error = 0; 122 123 /* 124 * wait for ack 125 */ 126 bp = NULL; 127 if ((error = tli_recv(tiptr, &bp, fmode)) != 0) 128 return (error); 129 130 if ((msgsz = (int)MBLKL(bp)) < sizeof (int)) { 131 freemsg(bp); 132 return (EPROTO); 133 } 134 135 pptr = (void *)bp->b_rptr; 136 switch (pptr->type) { 137 case T_OK_ACK: 138 if (msgsz < TOKACKSZ || pptr->ok_ack.CORRECT_prim != type) 139 error = EPROTO; 140 break; 141 142 case T_ERROR_ACK: 143 if (msgsz < TERRORACKSZ) { 144 error = EPROTO; 145 break; 146 } 147 148 if (pptr->error_ack.TLI_error == TSYSERR) 149 error = pptr->error_ack.UNIX_error; 150 else 151 error = t_tlitosyserr(pptr->error_ack.TLI_error); 152 break; 153 154 default: 155 error = EPROTO; 156 break; 157 } 158 freemsg(bp); 159 return (error); 160 } 161 162 /* 163 * Translate a TLI error into a system error as best we can. 164 */ 165 static const int tli_errs[] = { 166 0, /* no error */ 167 EADDRNOTAVAIL, /* TBADADDR */ 168 ENOPROTOOPT, /* TBADOPT */ 169 EACCES, /* TACCES */ 170 EBADF, /* TBADF */ 171 EADDRNOTAVAIL, /* TNOADDR */ 172 EPROTO, /* TOUTSTATE */ 173 EPROTO, /* TBADSEQ */ 174 0, /* TSYSERR - will never get */ 175 EPROTO, /* TLOOK - should never be sent by transport */ 176 EMSGSIZE, /* TBADDATA */ 177 EMSGSIZE, /* TBUFOVFLW */ 178 EPROTO, /* TFLOW */ 179 EWOULDBLOCK, /* TNODATA */ 180 EPROTO, /* TNODIS */ 181 EPROTO, /* TNOUDERR */ 182 EINVAL, /* TBADFLAG */ 183 EPROTO, /* TNOREL */ 184 EOPNOTSUPP, /* TNOTSUPPORT */ 185 EPROTO, /* TSTATECHNG */ 186 }; 187 188 int 189 t_tlitosyserr(int terr) 190 { 191 if (terr < 0 || (terr >= (sizeof (tli_errs) / sizeof (tli_errs[0])))) 192 return (EPROTO); 193 else 194 return (tli_errs[terr]); 195 } 196 197 /* 198 * Notify transport that we are having trouble with this connection. 199 * If transport is TCP/IP, IP should delete the IRE and start over. 200 */ 201 void 202 t_kadvise(TIUSER *tiptr, uchar_t *addr, int addr_len) 203 { 204 file_t *fp; 205 vnode_t *vp; 206 struct iocblk *iocp; 207 ipid_t *ipid; 208 mblk_t *mp; 209 210 fp = tiptr->fp; 211 vp = fp->f_vnode; 212 213 mp = mkiocb(IP_IOCTL); 214 if (!mp) 215 return; 216 217 iocp = (void *)mp->b_rptr; 218 iocp->ioc_count = sizeof (ipid_t) + addr_len; 219 220 mp->b_cont = allocb(iocp->ioc_count, BPRI_HI); 221 if (!mp->b_cont) { 222 freeb(mp); 223 return; 224 } 225 226 ipid = (void *)mp->b_cont->b_rptr; 227 mp->b_cont->b_wptr += iocp->ioc_count; 228 229 bzero(ipid, sizeof (*ipid)); 230 ipid->ipid_cmd = IP_IOC_IRE_DELETE_NO_REPLY; 231 ipid->ipid_ire_type = 0; 232 ipid->ipid_addr_offset = sizeof (ipid_t); 233 ipid->ipid_addr_length = addr_len; 234 235 bcopy(addr, &ipid[1], addr_len); 236 237 /* Ignore flow control, signals and errors */ 238 (void) kstrputmsg(vp, mp, NULL, 0, 0, 239 MSG_BAND | MSG_IGNFLOW | MSG_HOLDSIG | MSG_IGNERROR, 0); 240 } 241 242 #ifdef KTLIDEBUG 243 int ktlilog = 0; 244 245 /* 246 * Kernel level debugging aid. The global variable "ktlilog" is a bit 247 * mask which allows various types of debugging messages to be printed 248 * out. 249 * 250 * ktlilog & 1 will cause actual failures to be printed. 251 * ktlilog & 2 will cause informational messages to be 252 * printed. 253 */ 254 int 255 ktli_log(int level, char *str, int a1) 256 { 257 if (level & ktlilog) 258 printf(str, a1); 259 } 260 #endif 261