|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /*- ! 26: * Copyright (c) 1991, 1993 ! 27: * The Regents of the University of California. All rights reserved. ! 28: * ! 29: * Redistribution and use in source and binary forms, with or without ! 30: * modification, are permitted provided that the following conditions ! 31: * are met: ! 32: * 1. Redistributions of source code must retain the above copyright ! 33: * notice, this list of conditions and the following disclaimer. ! 34: * 2. Redistributions in binary form must reproduce the above copyright ! 35: * notice, this list of conditions and the following disclaimer in the ! 36: * documentation and/or other materials provided with the distribution. ! 37: * 3. All advertising materials mentioning features or use of this software ! 38: * must display the following acknowledgement: ! 39: * This product includes software developed by the University of ! 40: * California, Berkeley and its contributors. ! 41: * 4. Neither the name of the University nor the names of its contributors ! 42: * may be used to endorse or promote products derived from this software ! 43: * without specific prior written permission. ! 44: * ! 45: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 46: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 47: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 48: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 49: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 50: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 51: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 52: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 53: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 54: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 55: * SUCH DAMAGE. ! 56: * ! 57: * @(#)tp_output.c 8.1 (Berkeley) 6/10/93 ! 58: */ ! 59: ! 60: /*********************************************************** ! 61: Copyright IBM Corporation 1987 ! 62: ! 63: All Rights Reserved ! 64: ! 65: Permission to use, copy, modify, and distribute this software and its ! 66: documentation for any purpose and without fee is hereby granted, ! 67: provided that the above copyright notice appear in all copies and that ! 68: both that copyright notice and this permission notice appear in ! 69: supporting documentation, and that the name of IBM not be ! 70: used in advertising or publicity pertaining to distribution of the ! 71: software without specific, written prior permission. ! 72: ! 73: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ! 74: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ! 75: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ! 76: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ! 77: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ! 78: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ! 79: SOFTWARE. ! 80: ! 81: ******************************************************************/ ! 82: ! 83: /* ! 84: * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison ! 85: */ ! 86: /* ! 87: * ARGO TP ! 88: * ! 89: * In here is tp_ctloutput(), the guy called by [sg]etsockopt(), ! 90: */ ! 91: ! 92: #include <sys/param.h> ! 93: #include <sys/mbuf.h> ! 94: #include <sys/systm.h> ! 95: #include <sys/socket.h> ! 96: #include <sys/socketvar.h> ! 97: #include <sys/protosw.h> ! 98: #include <sys/errno.h> ! 99: #include <sys/time.h> ! 100: #include <sys/kernel.h> ! 101: ! 102: #include <netiso/tp_param.h> ! 103: #include <netiso/tp_user.h> ! 104: #include <netiso/tp_stat.h> ! 105: #include <netiso/tp_ip.h> ! 106: #include <netiso/tp_clnp.h> ! 107: #include <netiso/tp_timer.h> ! 108: #include <netiso/argo_debug.h> ! 109: #include <netiso/tp_pcb.h> ! 110: #include <netiso/tp_trace.h> ! 111: ! 112: #define TPDUSIZESHIFT 24 ! 113: #define CLASSHIFT 16 ! 114: ! 115: /* ! 116: * NAME: tp_consistency() ! 117: * ! 118: * CALLED FROM: ! 119: * tp_ctloutput(), tp_input() ! 120: * ! 121: * FUNCTION and ARGUMENTS: ! 122: * Checks the consistency of options and tpdusize with class, ! 123: * using the parameters passed in via (param). ! 124: * (cmd) may be TP_STRICT or TP_FORCE or both. ! 125: * Force means it will set all the values in (tpcb) to those in ! 126: * the input arguements iff no errors were encountered. ! 127: * Strict means that no inconsistency will be tolerated. If it's ! 128: * not used, checksum and tpdusize inconsistencies will be tolerated. ! 129: * The reason for this is that in some cases, when we're negotiating down ! 130: * from class 4, these options should be changed but should not ! 131: * cause negotiation to fail. ! 132: * ! 133: * RETURNS ! 134: * E* or EOK ! 135: * E* if the various parms aren't ok for a given class ! 136: * EOK if they are ok for a given class ! 137: */ ! 138: ! 139: int ! 140: tp_consistency( tpcb, cmd, param ) ! 141: u_int cmd; ! 142: struct tp_conn_param *param; ! 143: struct tp_pcb *tpcb; ! 144: { ! 145: register int error = EOK; ! 146: int class_to_use = tp_mask_to_num(param->p_class); ! 147: ! 148: IFTRACE(D_SETPARAMS) ! 149: tptrace(TPPTmisc, ! 150: "tp_consist enter class_to_use dontchange param.class cmd", ! 151: class_to_use, param->p_dont_change_params, param->p_class, cmd); ! 152: ENDTRACE ! 153: IFDEBUG(D_SETPARAMS) ! 154: printf("tp_consistency %s %s\n", ! 155: cmd& TP_FORCE? "TP_FORCE": "", ! 156: cmd& TP_STRICT? "TP_STRICT":""); ! 157: ENDDEBUG ! 158: if ((cmd & TP_FORCE) && (param->p_dont_change_params)) { ! 159: cmd &= ~TP_FORCE; ! 160: } ! 161: /* can switch net services within a domain, but ! 162: * cannot switch domains ! 163: */ ! 164: switch( param->p_netservice) { ! 165: case ISO_CONS: ! 166: case ISO_CLNS: ! 167: case ISO_COSNS: ! 168: /* param->p_netservice in ISO DOMAIN */ ! 169: if(tpcb->tp_domain != AF_ISO ) { ! 170: error = EINVAL; goto done; ! 171: } ! 172: break; ! 173: case IN_CLNS: ! 174: /* param->p_netservice in INET DOMAIN */ ! 175: if( tpcb->tp_domain != AF_INET ) { ! 176: error = EINVAL; goto done; ! 177: } ! 178: break; ! 179: /* no others not possible-> netservice is a 2-bit field! */ ! 180: } ! 181: ! 182: IFDEBUG(D_SETPARAMS) ! 183: printf("p_class 0x%x, class_to_use 0x%x\n", param->p_class, ! 184: class_to_use); ! 185: ENDDEBUG ! 186: if((param->p_netservice < 0) || (param->p_netservice > TP_MAX_NETSERVICES)){ ! 187: error = EINVAL; goto done; ! 188: } ! 189: if( (param->p_class & TP_CLASSES_IMPLEMENTED) == 0 ) { ! 190: error = EINVAL; goto done; ! 191: } ! 192: IFDEBUG(D_SETPARAMS) ! 193: printf("Nretrans 0x%x\n", param->p_Nretrans ); ! 194: ENDDEBUG ! 195: if( ( param->p_Nretrans < 1 ) || ! 196: (param->p_cr_ticks < 1) || (param->p_cc_ticks < 1) ) { ! 197: /* bad for any class because negot has to be done a la class 4 */ ! 198: error = EINVAL; goto done; ! 199: } ! 200: IFDEBUG(D_SETPARAMS) ! 201: printf("use_csum 0x%x\n", param->p_use_checksum ); ! 202: printf("xtd_format 0x%x\n", param->p_xtd_format ); ! 203: printf("xpd_service 0x%x\n", param->p_xpd_service ); ! 204: printf("tpdusize 0x%x\n", param->p_tpdusize ); ! 205: printf("tpcb->flags 0x%x\n", tpcb->tp_flags ); ! 206: ENDDEBUG ! 207: switch( class_to_use ) { ! 208: ! 209: case 0: ! 210: /* do not use checksums, xtd format, or XPD */ ! 211: ! 212: if( param->p_use_checksum | param->p_xtd_format | param->p_xpd_service ) { ! 213: if(cmd & TP_STRICT) { ! 214: error = EINVAL; ! 215: } else { ! 216: param->p_use_checksum = 0; ! 217: param->p_xtd_format = 0; ! 218: param->p_xpd_service = 0; ! 219: } ! 220: break; ! 221: } ! 222: ! 223: if (param->p_tpdusize < TP_MIN_TPDUSIZE) { ! 224: if(cmd & TP_STRICT) { ! 225: error = EINVAL; ! 226: } else { ! 227: param->p_tpdusize = TP_MIN_TPDUSIZE; ! 228: } ! 229: break; ! 230: } ! 231: if (param->p_tpdusize > TP0_TPDUSIZE) { ! 232: if (cmd & TP_STRICT) { ! 233: error = EINVAL; ! 234: } else { ! 235: param->p_tpdusize = TP0_TPDUSIZE; ! 236: } ! 237: break; ! 238: } ! 239: ! 240: /* connect/disc data not allowed for class 0 */ ! 241: if (tpcb->tp_ucddata) { ! 242: if(cmd & TP_STRICT) { ! 243: error = EINVAL; ! 244: } else if(cmd & TP_FORCE) { ! 245: m_freem(tpcb->tp_ucddata); ! 246: tpcb->tp_ucddata = 0; ! 247: } ! 248: } ! 249: break; ! 250: ! 251: case 4: ! 252: IFDEBUG(D_SETPARAMS) ! 253: printf("dt_ticks 0x%x\n", param->p_dt_ticks ); ! 254: printf("x_ticks 0x%x\n", param->p_x_ticks ); ! 255: printf("dr_ticks 0x%x\n", param->p_dr_ticks ); ! 256: printf("keepalive 0x%x\n", param->p_keepalive_ticks ); ! 257: printf("sendack 0x%x\n", param->p_sendack_ticks ); ! 258: printf("inact 0x%x\n", param->p_inact_ticks ); ! 259: printf("ref 0x%x\n", param->p_ref_ticks ); ! 260: ENDDEBUG ! 261: if( (param->p_class & TP_CLASS_4 ) && ( ! 262: (param->p_dt_ticks < 1) || (param->p_dr_ticks < 1) || ! 263: (param->p_x_ticks < 1) || (param->p_keepalive_ticks < 1) || ! 264: (param->p_sendack_ticks < 1) || (param->p_ref_ticks < 1) || ! 265: (param->p_inact_ticks < 1) ) ) { ! 266: error = EINVAL; ! 267: break; ! 268: } ! 269: IFDEBUG(D_SETPARAMS) ! 270: printf("rx_strat 0x%x\n", param->p_rx_strat ); ! 271: ENDDEBUG ! 272: if(param->p_rx_strat > ! 273: ( TPRX_USE_CW | TPRX_EACH | TPRX_FASTSTART) ) { ! 274: if(cmd & TP_STRICT) { ! 275: error = EINVAL; ! 276: } else { ! 277: param->p_rx_strat = TPRX_USE_CW; ! 278: } ! 279: break; ! 280: } ! 281: IFDEBUG(D_SETPARAMS) ! 282: printf("ack_strat 0x%x\n", param->p_ack_strat ); ! 283: ENDDEBUG ! 284: if((param->p_ack_strat != 0) && (param->p_ack_strat != 1)) { ! 285: if(cmd & TP_STRICT) { ! 286: error = EINVAL; ! 287: } else { ! 288: param->p_ack_strat = TPACK_WINDOW; ! 289: } ! 290: break; ! 291: } ! 292: if (param->p_tpdusize < TP_MIN_TPDUSIZE) { ! 293: if(cmd & TP_STRICT) { ! 294: error = EINVAL; ! 295: } else { ! 296: param->p_tpdusize = TP_MIN_TPDUSIZE; ! 297: } ! 298: break; ! 299: } ! 300: if (param->p_tpdusize > TP_TPDUSIZE) { ! 301: if(cmd & TP_STRICT) { ! 302: error = EINVAL; ! 303: } else { ! 304: param->p_tpdusize = TP_TPDUSIZE; ! 305: } ! 306: break; ! 307: } ! 308: break; ! 309: } ! 310: ! 311: if ((error==0) && (cmd & TP_FORCE)) { ! 312: long dusize = ((long)param->p_ptpdusize) << 7; ! 313: /* Enforce Negotation rules below */ ! 314: tpcb->tp_class = param->p_class; ! 315: if (tpcb->tp_use_checksum || param->p_use_checksum) ! 316: tpcb->tp_use_checksum = 1; ! 317: if (!tpcb->tp_xpd_service || !param->p_xpd_service) ! 318: tpcb->tp_xpd_service = 0; ! 319: if (!tpcb->tp_xtd_format || !param->p_xtd_format) ! 320: tpcb->tp_xtd_format = 0; ! 321: if (dusize) { ! 322: if (tpcb->tp_l_tpdusize > dusize) ! 323: tpcb->tp_l_tpdusize = dusize; ! 324: if (tpcb->tp_ptpdusize == 0 || ! 325: tpcb->tp_ptpdusize > param->p_ptpdusize) ! 326: tpcb->tp_ptpdusize = param->p_ptpdusize; ! 327: } else { ! 328: if (param->p_tpdusize != 0 && ! 329: tpcb->tp_tpdusize > param->p_tpdusize) ! 330: tpcb->tp_tpdusize = param->p_tpdusize; ! 331: tpcb->tp_l_tpdusize = 1 << tpcb->tp_tpdusize; ! 332: } ! 333: } ! 334: done: ! 335: ! 336: IFTRACE(D_CONN) ! 337: tptrace(TPPTmisc, "tp_consist returns class xtdfmt cmd", ! 338: error, tpcb->tp_class, tpcb->tp_xtd_format, cmd); ! 339: ENDTRACE ! 340: IFDEBUG(D_CONN) ! 341: printf( ! 342: "tp_consist rtns 0x%x class 0x%x xtd_fmt 0x%x cmd 0x%x\n", ! 343: error, tpcb->tp_class, tpcb->tp_xtd_format, cmd); ! 344: ENDDEBUG ! 345: return error; ! 346: } ! 347: ! 348: /* ! 349: * NAME: tp_ctloutput() ! 350: * ! 351: * CALLED FROM: ! 352: * [sg]etsockopt(), via so[sg]etopt(). ! 353: * ! 354: * FUNCTION and ARGUMENTS: ! 355: * Implements the socket options at transport level. ! 356: * (cmd) is either PRCO_SETOPT or PRCO_GETOPT (see ../sys/protosw.h). ! 357: * (so) is the socket. ! 358: * (level) is SOL_TRANSPORT (see ../sys/socket.h) ! 359: * (optname) is the particular command or option to be set. ! 360: * (**mp) is an mbuf structure. ! 361: * ! 362: * RETURN VALUE: ! 363: * ENOTSOCK if the socket hasn't got an associated tpcb ! 364: * EINVAL if ! 365: * trying to set window too big ! 366: * trying to set illegal max tpdu size ! 367: * trying to set illegal credit fraction ! 368: * trying to use unknown or unimplemented class of TP ! 369: * structure passed to set timer values is wrong size ! 370: * illegal combination of command/GET-SET option, ! 371: * e.g., GET w/ TPOPT_CDDATA_CLEAR: ! 372: * EOPNOTSUPP if the level isn't transport, or command is neither GET nor SET ! 373: * or if the transport-specific command is not implemented ! 374: * EISCONN if trying a command that isn't allowed after a connection ! 375: * is established ! 376: * ENOTCONN if trying a command that is allowed only if a connection is ! 377: * established ! 378: * EMSGSIZE if trying to give too much data on connect/disconnect ! 379: * ! 380: * SIDE EFFECTS: ! 381: * ! 382: * NOTES: ! 383: */ ! 384: ProtoHook ! 385: tp_ctloutput(cmd, so, level, optname, mp) ! 386: int cmd, level, optname; ! 387: struct socket *so; ! 388: struct mbuf **mp; ! 389: { ! 390: struct tp_pcb *tpcb = sototpcb(so); ! 391: int s = splnet(); ! 392: caddr_t value; ! 393: unsigned val_len; ! 394: int error = 0; ! 395: ! 396: IFTRACE(D_REQUEST) ! 397: tptrace(TPPTmisc, "tp_ctloutput cmd so optname mp", ! 398: cmd, so, optname, mp); ! 399: ENDTRACE ! 400: IFDEBUG(D_REQUEST) ! 401: printf( ! 402: "tp_ctloutput so 0x%x cmd 0x%x optname 0x%x, mp 0x%x *mp 0x%x tpcb 0x%x\n", ! 403: so, cmd, optname, mp, mp?*mp:0, tpcb); ! 404: ENDDEBUG ! 405: if( tpcb == (struct tp_pcb *)0 ) { ! 406: error = ENOTSOCK; goto done; ! 407: } ! 408: if(*mp == MNULL) { ! 409: register struct mbuf *m; ! 410: ! 411: MGET(m, M_DONTWAIT, TPMT_SONAME); /* does off, type, next */ ! 412: if (m == NULL) { ! 413: splx(s); ! 414: return ENOBUFS; ! 415: } ! 416: m->m_len = 0; ! 417: m->m_act = 0; ! 418: *mp = m; ! 419: } ! 420: ! 421: /* ! 422: * Hook so one can set network options via a tp socket. ! 423: */ ! 424: if ( level == SOL_NETWORK ) { ! 425: if ((tpcb->tp_nlproto == NULL) || (tpcb->tp_npcb == NULL)) ! 426: error = ENOTSOCK; ! 427: else if (tpcb->tp_nlproto->nlp_ctloutput == NULL) ! 428: error = EOPNOTSUPP; ! 429: else ! 430: return ((tpcb->tp_nlproto->nlp_ctloutput)(cmd, optname, ! 431: tpcb->tp_npcb, *mp)); ! 432: goto done; ! 433: } else if ( level == SOL_SOCKET) { ! 434: if (optname == SO_RCVBUF && cmd == PRCO_SETOPT) { ! 435: u_long old_credit = tpcb->tp_maxlcredit; ! 436: tp_rsyset(tpcb); ! 437: if (tpcb->tp_rhiwat != so->so_rcv.sb_hiwat && ! 438: tpcb->tp_state == TP_OPEN && ! 439: (old_credit < tpcb->tp_maxlcredit)) ! 440: tp_emit(AK_TPDU_type, tpcb, ! 441: tpcb->tp_rcvnxt, 0, MNULL); ! 442: tpcb->tp_rhiwat = so->so_rcv.sb_hiwat; ! 443: } ! 444: goto done; ! 445: } else if ( level != SOL_TRANSPORT ) { ! 446: error = EOPNOTSUPP; goto done; ! 447: } ! 448: if (cmd != PRCO_GETOPT && cmd != PRCO_SETOPT) { ! 449: error = EOPNOTSUPP; goto done; ! 450: } ! 451: if ( so->so_error ) { ! 452: error = so->so_error; goto done; ! 453: } ! 454: ! 455: /* The only options allowed after connection is established ! 456: * are GET (anything) and SET DISC DATA and SET PERF MEAS ! 457: */ ! 458: if ( ((so->so_state & SS_ISCONNECTING)||(so->so_state & SS_ISCONNECTED)) ! 459: && ! 460: (cmd == PRCO_SETOPT && ! 461: optname != TPOPT_DISC_DATA && ! 462: optname != TPOPT_CFRM_DATA && ! 463: optname != TPOPT_PERF_MEAS && ! 464: optname != TPOPT_CDDATA_CLEAR ) ) { ! 465: error = EISCONN; goto done; ! 466: } ! 467: /* The only options allowed after disconnection are GET DISC DATA, ! 468: * and TPOPT_PSTATISTICS ! 469: * and they're not allowed if the ref timer has gone off, because ! 470: * the tpcb is gone ! 471: */ ! 472: if ((so->so_state & (SS_ISCONNECTED | SS_ISCONFIRMING)) == 0) { ! 473: if ( so->so_pcb == (caddr_t)0 ) { ! 474: error = ENOTCONN; goto done; ! 475: } ! 476: if ( (tpcb->tp_state == TP_REFWAIT || tpcb->tp_state == TP_CLOSING) && ! 477: (optname != TPOPT_DISC_DATA && optname != TPOPT_PSTATISTICS)) { ! 478: error = ENOTCONN; goto done; ! 479: } ! 480: } ! 481: ! 482: value = mtod(*mp, caddr_t); /* it's aligned, don't worry, ! 483: * but lint complains about it ! 484: */ ! 485: val_len = (*mp)->m_len; ! 486: ! 487: switch (optname) { ! 488: ! 489: case TPOPT_INTERCEPT: ! 490: #define INA(t) (((struct inpcb *)(t->tp_npcb))->inp_laddr.s_addr) ! 491: #define ISOA(t) (((struct isopcb *)(t->tp_npcb))->isop_laddr->siso_addr) ! 492: ! 493: if ((so->so_state & SS_PRIV) == 0) { ! 494: error = EPERM; ! 495: } else if (cmd != PRCO_SETOPT || tpcb->tp_state != TP_CLOSED || ! 496: (tpcb->tp_flags & TPF_GENERAL_ADDR) || ! 497: tpcb->tp_next == 0) ! 498: error = EINVAL; ! 499: else { ! 500: register struct tp_pcb *t; ! 501: error = EADDRINUSE; ! 502: for (t = tp_listeners; t; t = t->tp_nextlisten) ! 503: if ((t->tp_flags & TPF_GENERAL_ADDR) == 0 && ! 504: t->tp_domain == tpcb->tp_domain) ! 505: switch (tpcb->tp_domain) { ! 506: default: ! 507: goto done; ! 508: #if INET ! 509: case AF_INET: ! 510: if (INA(t) == INA(tpcb)) ! 511: goto done; ! 512: continue; ! 513: #endif ! 514: #if ISO ! 515: case AF_ISO: ! 516: if (bcmp(ISOA(t).isoa_genaddr, ISOA(tpcb).isoa_genaddr, ! 517: ISOA(t).isoa_len) == 0) ! 518: goto done; ! 519: continue; ! 520: #endif ! 521: } ! 522: tpcb->tp_lsuffixlen = 0; ! 523: tpcb->tp_state = TP_LISTENING; ! 524: error = 0; ! 525: remque(tpcb); ! 526: tpcb->tp_next = tpcb->tp_prev = tpcb; ! 527: tpcb->tp_nextlisten = tp_listeners; ! 528: tp_listeners = tpcb; ! 529: } ! 530: break; ! 531: ! 532: case TPOPT_MY_TSEL: ! 533: if ( cmd == PRCO_GETOPT ) { ! 534: ASSERT( tpcb->tp_lsuffixlen <= MAX_TSAP_SEL_LEN ); ! 535: bcopy((caddr_t)tpcb->tp_lsuffix, value, tpcb->tp_lsuffixlen); ! 536: (*mp)->m_len = tpcb->tp_lsuffixlen; ! 537: } else /* cmd == PRCO_SETOPT */ { ! 538: if( (val_len > MAX_TSAP_SEL_LEN) || (val_len <= 0 )) { ! 539: printf("val_len 0x%x (*mp)->m_len 0x%x\n", val_len, (*mp)); ! 540: error = EINVAL; ! 541: } else { ! 542: bcopy(value, (caddr_t)tpcb->tp_lsuffix, val_len); ! 543: tpcb->tp_lsuffixlen = val_len; ! 544: } ! 545: } ! 546: break; ! 547: ! 548: case TPOPT_PEER_TSEL: ! 549: if ( cmd == PRCO_GETOPT ) { ! 550: ASSERT( tpcb->tp_fsuffixlen <= MAX_TSAP_SEL_LEN ); ! 551: bcopy((caddr_t)tpcb->tp_fsuffix, value, tpcb->tp_fsuffixlen); ! 552: (*mp)->m_len = tpcb->tp_fsuffixlen; ! 553: } else /* cmd == PRCO_SETOPT */ { ! 554: if( (val_len > MAX_TSAP_SEL_LEN) || (val_len <= 0 )) { ! 555: printf("val_len 0x%x (*mp)->m_len 0x%x\n", val_len, (*mp)); ! 556: error = EINVAL; ! 557: } else { ! 558: bcopy(value, (caddr_t)tpcb->tp_fsuffix, val_len); ! 559: tpcb->tp_fsuffixlen = val_len; ! 560: } ! 561: } ! 562: break; ! 563: ! 564: case TPOPT_FLAGS: ! 565: IFDEBUG(D_REQUEST) ! 566: printf("%s TPOPT_FLAGS value 0x%x *value 0x%x, flags 0x%x \n", ! 567: cmd==PRCO_GETOPT?"GET":"SET", ! 568: value, ! 569: *value, ! 570: tpcb->tp_flags); ! 571: ENDDEBUG ! 572: ! 573: if ( cmd == PRCO_GETOPT ) { ! 574: *(int *)value = (int)tpcb->tp_flags; ! 575: (*mp)->m_len = sizeof(u_int); ! 576: } else /* cmd == PRCO_SETOPT */ { ! 577: error = EINVAL; goto done; ! 578: } ! 579: break; ! 580: ! 581: case TPOPT_PARAMS: ! 582: /* This handles: ! 583: * timer values, ! 584: * class, use of transport expedited data, ! 585: * max tpdu size, checksum, xtd format and ! 586: * disconnect indications, and may get rid of connect/disc data ! 587: */ ! 588: IFDEBUG(D_SETPARAMS) ! 589: printf("TPOPT_PARAMS value 0x%x, cmd %s \n", value, ! 590: cmd==PRCO_GETOPT?"GET":"SET"); ! 591: ENDDEBUG ! 592: IFDEBUG(D_REQUEST) ! 593: printf("TPOPT_PARAMS value 0x%x, cmd %s \n", value, ! 594: cmd==PRCO_GETOPT?"GET":"SET"); ! 595: ENDDEBUG ! 596: ! 597: if ( cmd == PRCO_GETOPT ) { ! 598: *(struct tp_conn_param *)value = tpcb->_tp_param; ! 599: (*mp)->m_len = sizeof(tpcb->_tp_param); ! 600: } else /* cmd == PRCO_SETOPT */ { ! 601: if( (error = ! 602: tp_consistency(tpcb, TP_STRICT | TP_FORCE, ! 603: (struct tp_conn_param *)value))==0) { ! 604: /* ! 605: * tp_consistency doesn't copy the whole set of params ! 606: */ ! 607: tpcb->_tp_param = *(struct tp_conn_param *)value; ! 608: (*mp)->m_len = sizeof(tpcb->_tp_param); ! 609: } ! 610: } ! 611: break; ! 612: ! 613: case TPOPT_PSTATISTICS: ! 614: #ifdef TP_PERF_MEAS ! 615: if (cmd == PRCO_SETOPT) { ! 616: error = EINVAL; goto done; ! 617: } ! 618: IFPERF(tpcb) ! 619: if (*mp) { ! 620: struct mbuf * n; ! 621: do { ! 622: MFREE(*mp, n); ! 623: *mp = n; ! 624: } while (n); ! 625: } ! 626: *mp = m_copym(tpcb->tp_p_mbuf, (int)M_COPYALL, M_WAITOK); ! 627: ENDPERF ! 628: else { ! 629: error = EINVAL; goto done; ! 630: } ! 631: break; ! 632: #else ! 633: error = EOPNOTSUPP; ! 634: goto done; ! 635: #endif /* TP_PERF_MEAS */ ! 636: ! 637: case TPOPT_CDDATA_CLEAR: ! 638: if (cmd == PRCO_GETOPT) { ! 639: error = EINVAL; ! 640: } else { ! 641: if (tpcb->tp_ucddata) { ! 642: m_freem(tpcb->tp_ucddata); ! 643: tpcb->tp_ucddata = 0; ! 644: } ! 645: } ! 646: break; ! 647: ! 648: case TPOPT_CFRM_DATA: ! 649: case TPOPT_DISC_DATA: ! 650: case TPOPT_CONN_DATA: ! 651: if( tpcb->tp_class == TP_CLASS_0 ) { ! 652: error = EOPNOTSUPP; ! 653: break; ! 654: } ! 655: IFDEBUG(D_REQUEST) ! 656: printf("%s\n", optname==TPOPT_DISC_DATA?"DISC data":"CONN data"); ! 657: printf("m_len 0x%x, vallen 0x%x so_snd.cc 0x%x\n", ! 658: (*mp)->m_len, val_len, so->so_snd.sb_cc); ! 659: dump_mbuf(so->so_snd.sb_mb, "tp_ctloutput: sosnd "); ! 660: ENDDEBUG ! 661: if (cmd == PRCO_SETOPT) { ! 662: int len = tpcb->tp_ucddata ? tpcb->tp_ucddata->m_len : 0; ! 663: /* can append connect data in several calls */ ! 664: if (len + val_len > ! 665: (optname==TPOPT_CONN_DATA?TP_MAX_CR_DATA:TP_MAX_DR_DATA) ) { ! 666: error = EMSGSIZE; goto done; ! 667: } ! 668: (*mp)->m_next = MNULL; ! 669: (*mp)->m_act = 0; ! 670: if (tpcb->tp_ucddata) ! 671: m_cat(tpcb->tp_ucddata, *mp); ! 672: else ! 673: tpcb->tp_ucddata = *mp; ! 674: IFDEBUG(D_REQUEST) ! 675: dump_mbuf(tpcb->tp_ucddata, "tp_ctloutput after CONN_DATA"); ! 676: ENDDEBUG ! 677: IFTRACE(D_REQUEST) ! 678: tptrace(TPPTmisc,"C/D DATA: flags snd.sbcc val_len", ! 679: tpcb->tp_flags, so->so_snd.sb_cc,val_len,0); ! 680: ENDTRACE ! 681: *mp = MNULL; ! 682: if (optname == TPOPT_CFRM_DATA && (so->so_state & SS_ISCONFIRMING)) ! 683: (void) tp_confirm(tpcb); ! 684: } ! 685: break; ! 686: ! 687: case TPOPT_PERF_MEAS: ! 688: #ifdef TP_PERF_MEAS ! 689: if (cmd == PRCO_GETOPT) { ! 690: *value = (u_int)tpcb->tp_perf_on; ! 691: (*mp)->m_len = sizeof(u_int); ! 692: } else if (cmd == PRCO_SETOPT) { ! 693: (*mp)->m_len = 0; ! 694: if ((*value) != 0 && (*value) != 1 ) ! 695: error = EINVAL; ! 696: else tpcb->tp_perf_on = (*value); ! 697: } ! 698: if( tpcb->tp_perf_on ) ! 699: error = tp_setup_perf(tpcb); ! 700: #else /* TP_PERF_MEAS */ ! 701: error = EOPNOTSUPP; ! 702: #endif /* TP_PERF_MEAS */ ! 703: break; ! 704: ! 705: default: ! 706: error = EOPNOTSUPP; ! 707: } ! 708: ! 709: done: ! 710: IFDEBUG(D_REQUEST) ! 711: dump_mbuf(so->so_snd.sb_mb, "tp_ctloutput sosnd at end"); ! 712: dump_mbuf(*mp, "tp_ctloutput *mp"); ! 713: ENDDEBUG ! 714: /* ! 715: * sigh: getsockopt looks only at m_len : all output data must ! 716: * reside in the first mbuf ! 717: */ ! 718: if (*mp) { ! 719: if (cmd == PRCO_SETOPT) { ! 720: m_freem(*mp); ! 721: *mp = MNULL; ! 722: } else { ! 723: ASSERT ( m_compress(*mp, mp) <= MLEN ); ! 724: if (error) ! 725: (*mp)->m_len = 0; ! 726: IFDEBUG(D_REQUEST) ! 727: dump_mbuf(*mp, "tp_ctloutput *mp after compress"); ! 728: ENDDEBUG ! 729: } ! 730: } ! 731: splx(s); ! 732: return error; ! 733: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.