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