1 /*- 2 * Copyright (c) 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)tp_usrreq.c 8.1 (Berkeley) 06/10/93 8 */ 9 10 /*********************************************************** 11 Copyright IBM Corporation 1987 12 13 All Rights Reserved 14 15 Permission to use, copy, modify, and distribute this software and its 16 documentation for any purpose and without fee is hereby granted, 17 provided that the above copyright notice appear in all copies and that 18 both that copyright notice and this permission notice appear in 19 supporting documentation, and that the name of IBM not be 20 used in advertising or publicity pertaining to distribution of the 21 software without specific, written prior permission. 22 23 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 24 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 25 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 26 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 27 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 28 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 29 SOFTWARE. 30 31 ******************************************************************/ 32 33 /* 34 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 35 */ 36 /* 37 * ARGO TP 38 * 39 * $Header: tp_usrreq.c,v 5.4 88/11/18 17:29:18 nhall Exp $ 40 * $Source: /usr/argo/sys/netiso/RCS/tp_usrreq.c,v $ 41 * 42 * tp_usrreq(), the fellow that gets called from most of the socket code. 43 * Pretty straighforward. 44 * THe only really awful stuff here is the OOB processing, which is done 45 * wholly here. 46 * tp_rcvoob() and tp_sendoob() are contained here and called by tp_usrreq(). 47 */ 48 49 #include <sys/param.h> 50 #include <sys/systm.h> 51 #include <sys/mbuf.h> 52 #include <sys/socket.h> 53 #include <sys/socketvar.h> 54 #include <sys/domain.h> 55 #include <sys/protosw.h> 56 #include <sys/errno.h> 57 #include <sys/time.h> 58 59 #include <netiso/tp_param.h> 60 #include <netiso/tp_timer.h> 61 #include <netiso/tp_stat.h> 62 #include <netiso/tp_seq.h> 63 #include <netiso/tp_ip.h> 64 #include <netiso/tp_pcb.h> 65 #include <netiso/argo_debug.h> 66 #include <netiso/tp_trace.h> 67 #include <netiso/tp_meas.h> 68 #include <netiso/iso.h> 69 #include <netiso/iso_errno.h> 70 71 int tp_attach(), tp_driver(), tp_pcbbind(); 72 int TNew; 73 int TPNagle1, TPNagle2; 74 struct tp_pcb *tp_listeners, *tp_intercepts; 75 76 #ifdef ARGO_DEBUG 77 /* 78 * CALLED FROM: 79 * anywhere you want to debug... 80 * FUNCTION and ARGUMENTS: 81 * print (str) followed by the control info in the mbufs of an mbuf chain (n) 82 */ 83 void 84 dump_mbuf(n, str) 85 struct mbuf *n; 86 char *str; 87 { 88 struct mbuf *nextrecord; 89 90 printf("dump %s\n", str); 91 92 if (n == MNULL) { 93 printf("EMPTY:\n"); 94 return; 95 } 96 97 while (n) { 98 nextrecord = n->m_act; 99 printf("RECORD:\n"); 100 while (n) { 101 printf("%x : Len %x Data %x A %x Nx %x Tp %x\n", 102 n, n->m_len, n->m_data, n->m_act, n->m_next, n->m_type); 103 #ifdef notdef 104 { 105 register char *p = mtod(n, char *); 106 register int i; 107 108 printf("data: "); 109 for (i = 0; i < n->m_len; i++) { 110 if (i%8 == 0) 111 printf("\n"); 112 printf("0x%x ", *(p+i)); 113 } 114 printf("\n"); 115 } 116 #endif /* notdef */ 117 if (n->m_next == n) { 118 printf("LOOP!\n"); 119 return; 120 } 121 n = n->m_next; 122 } 123 n = nextrecord; 124 } 125 printf("\n"); 126 } 127 128 #endif /* ARGO_DEBUG */ 129 130 /* 131 * CALLED FROM: 132 * tp_usrreq(), PRU_RCVOOB 133 * FUNCTION and ARGUMENTS: 134 * Copy data from the expedited data socket buffer into 135 * the pre-allocated mbuf m. 136 * There is an isomorphism between XPD TPDUs and expedited data TSDUs. 137 * XPD tpdus are limited to 16 bytes of data so they fit in one mbuf. 138 * RETURN VALUE: 139 * EINVAL if debugging is on and a disaster has occurred 140 * ENOTCONN if the socket isn't connected 141 * EWOULDBLOCK if the socket is in non-blocking mode and there's no 142 * xpd data in the buffer 143 * E* whatever is returned from the fsm. 144 */ 145 tp_rcvoob(tpcb, so, m, outflags, inflags) 146 struct tp_pcb *tpcb; 147 register struct socket *so; 148 register struct mbuf *m; 149 int *outflags; 150 int inflags; 151 { 152 register struct mbuf *n; 153 register struct sockbuf *sb = &so->so_rcv; 154 struct tp_event E; 155 int error = 0; 156 register struct mbuf **nn; 157 158 IFDEBUG(D_XPD) 159 printf("PRU_RCVOOB, sostate 0x%x\n", so->so_state); 160 ENDDEBUG 161 162 /* if you use soreceive */ 163 if (m == MNULL) 164 return ENOBUFS; 165 166 restart: 167 if ((((so->so_state & SS_ISCONNECTED) == 0) 168 || (so->so_state & SS_ISDISCONNECTING) != 0) && 169 (so->so_proto->pr_flags & PR_CONNREQUIRED)) { 170 return ENOTCONN; 171 } 172 173 /* Take the first mbuf off the chain. 174 * Each XPD TPDU gives you a complete TSDU so the chains don't get 175 * coalesced, but one TSDU may span several mbufs. 176 * Nevertheless, since n should have a most 16 bytes, it 177 * will fit into m. (size was checked in tp_input() ) 178 */ 179 180 /* 181 * Code for excision of OOB data should be added to 182 * uipc_socket2.c (like sbappend). 183 */ 184 185 sblock(sb, M_WAITOK); 186 for (nn = &sb->sb_mb; n = *nn; nn = &n->m_act) 187 if (n->m_type == MT_OOBDATA) 188 break; 189 190 if (n == 0) { 191 IFDEBUG(D_XPD) 192 printf("RCVOOB: empty queue!\n"); 193 ENDDEBUG 194 sbunlock(sb); 195 if (so->so_state & SS_NBIO) { 196 return EWOULDBLOCK; 197 } 198 sbwait(sb); 199 goto restart; 200 } 201 m->m_len = 0; 202 203 /* Assuming at most one xpd tpdu is in the buffer at once */ 204 while (n != MNULL) { 205 m->m_len += n->m_len; 206 bcopy(mtod(n, caddr_t), mtod(m, caddr_t), (unsigned)n->m_len); 207 m->m_data += n->m_len; /* so mtod() in bcopy() above gives right addr */ 208 n = n->m_next; 209 } 210 m->m_data = m->m_dat; 211 m->m_flags |= M_EOR; 212 213 IFDEBUG(D_XPD) 214 printf("tp_rcvoob: xpdlen 0x%x\n", m->m_len); 215 dump_mbuf(so->so_rcv.sb_mb, "RCVOOB: Rcv socketbuf"); 216 dump_mbuf(sb->sb_mb, "RCVOOB: Xrcv socketbuf"); 217 ENDDEBUG 218 219 if ((inflags & MSG_PEEK) == 0) { 220 n = *nn; 221 *nn = n->m_act; 222 for (; n; n = m_free(n)) 223 sbfree(sb, n); 224 } 225 226 release: 227 sbunlock(sb); 228 229 IFTRACE(D_XPD) 230 tptraceTPCB(TPPTmisc, "PRU_RCVOOB @ release sb_cc m_len", 231 tpcb->tp_Xrcv.sb_cc, m->m_len, 0, 0); 232 ENDTRACE 233 if (error == 0) 234 error = DoEvent(T_USR_Xrcvd); 235 return error; 236 } 237 238 /* 239 * CALLED FROM: 240 * tp_usrreq(), PRU_SENDOOB 241 * FUNCTION and ARGUMENTS: 242 * Send what's in the mbuf chain (m) as an XPD TPDU. 243 * The mbuf may not contain more then 16 bytes of data. 244 * XPD TSDUs aren't segmented, so they translate into 245 * exactly one XPD TPDU, with EOT bit set. 246 * RETURN VALUE: 247 * EWOULDBLOCK if socket is in non-blocking mode and the previous 248 * xpd data haven't been acked yet. 249 * EMSGSIZE if trying to send > max-xpd bytes (16) 250 * ENOBUFS if ran out of mbufs 251 */ 252 tp_sendoob(tpcb, so, xdata, outflags) 253 struct tp_pcb *tpcb; 254 register struct socket *so; 255 register struct mbuf *xdata; 256 int *outflags; /* not used */ 257 { 258 /* 259 * Each mbuf chain represents a sequence # in the XPD seq space. 260 * The first one in the queue has sequence # tp_Xuna. 261 * When we add to the XPD queue, we stuff a zero-length 262 * mbuf (mark) into the DATA queue, with its sequence number in m_next 263 * to be assigned to this XPD tpdu, so data xfer can stop 264 * when it reaches the zero-length mbuf if this XPD TPDU hasn't 265 * yet been acknowledged. 266 */ 267 register struct sockbuf *sb = &(tpcb->tp_Xsnd); 268 register struct mbuf *xmark; 269 register int len=0; 270 struct tp_event E; 271 272 IFDEBUG(D_XPD) 273 printf("tp_sendoob:"); 274 if (xdata) 275 printf("xdata len 0x%x\n", xdata->m_len); 276 ENDDEBUG 277 /* DO NOT LOCK the Xsnd buffer!!!! You can have at MOST one 278 * socket buf locked at any time!!! (otherwise you might 279 * sleep() in sblock() w/ a signal pending and cause the 280 * system call to be aborted w/ a locked socketbuf, which 281 * is a problem. So the so_snd buffer lock 282 * (done in sosend()) serves as the lock for Xpd. 283 */ 284 if (sb->sb_mb) { /* Anything already in eXpedited data sockbuf? */ 285 if (so->so_state & SS_NBIO) { 286 return EWOULDBLOCK; 287 } 288 while (sb->sb_mb) { 289 sbunlock(&so->so_snd); /* already locked by sosend */ 290 sbwait(&so->so_snd); 291 sblock(&so->so_snd, M_WAITOK); /* sosend will unlock on return */ 292 } 293 } 294 295 if (xdata == (struct mbuf *)0) { 296 /* empty xpd packet */ 297 MGETHDR(xdata, M_WAIT, MT_OOBDATA); 298 if (xdata == NULL) { 299 return ENOBUFS; 300 } 301 xdata->m_len = 0; 302 xdata->m_pkthdr.len = 0; 303 } 304 IFDEBUG(D_XPD) 305 printf("tp_sendoob 1:"); 306 if (xdata) 307 printf("xdata len 0x%x\n", xdata->m_len); 308 ENDDEBUG 309 xmark = xdata; /* temporary use of variable xmark */ 310 while (xmark) { 311 len += xmark->m_len; 312 xmark = xmark->m_next; 313 } 314 if (len > TP_MAX_XPD_DATA) { 315 return EMSGSIZE; 316 } 317 IFDEBUG(D_XPD) 318 printf("tp_sendoob 2:"); 319 if (xdata) 320 printf("xdata len 0x%x\n", len); 321 ENDDEBUG 322 323 324 IFTRACE(D_XPD) 325 tptraceTPCB(TPPTmisc, "XPD mark m_next ", xdata->m_next, 0, 0, 0); 326 ENDTRACE 327 328 sbappendrecord(sb, xdata); 329 330 IFDEBUG(D_XPD) 331 printf("tp_sendoob len 0x%x\n", len); 332 dump_mbuf(so->so_snd.sb_mb, "XPD request Regular sndbuf:"); 333 dump_mbuf(tpcb->tp_Xsnd.sb_mb, "XPD request Xsndbuf:"); 334 ENDDEBUG 335 return DoEvent(T_XPD_req); 336 } 337 338 /* 339 * CALLED FROM: 340 * the socket routines 341 * FUNCTION and ARGUMENTS: 342 * Handles all "user requests" except the [gs]ockopts() requests. 343 * The argument (req) is the request type (PRU*), 344 * (m) is an mbuf chain, generally used for send and 345 * receive type requests only. 346 * (nam) is used for addresses usually, in particular for the bind request. 347 * 348 */ 349 /*ARGSUSED*/ 350 ProtoHook 351 tp_usrreq(so, req, m, nam, controlp) 352 struct socket *so; 353 u_int req; 354 struct mbuf *m, *nam, *controlp; 355 { 356 register struct tp_pcb *tpcb = sototpcb(so); 357 int s = splnet(); 358 int error = 0; 359 int flags, *outflags = &flags; 360 u_long eotsdu = 0; 361 struct tp_event E; 362 363 IFDEBUG(D_REQUEST) 364 printf("usrreq(0x%x,%d,0x%x,0x%x,0x%x)\n",so,req,m,nam,outflags); 365 if (so->so_error) 366 printf("WARNING!!! so->so_error is 0x%x\n", so->so_error); 367 ENDDEBUG 368 IFTRACE(D_REQUEST) 369 tptraceTPCB(TPPTusrreq, "req so m state [", req, so, m, 370 tpcb?tpcb->tp_state:0); 371 ENDTRACE 372 373 if ((u_int)tpcb == 0 && req != PRU_ATTACH) { 374 IFTRACE(D_REQUEST) 375 tptraceTPCB(TPPTusrreq, "req failed NO TPCB[", 0, 0, 0, 0); 376 ENDTRACE 377 splx(s); 378 return ENOTCONN; 379 } 380 381 switch (req) { 382 383 case PRU_ATTACH: 384 if (tpcb) { 385 error = EISCONN; 386 } else if ((error = tp_attach(so, (int)nam)) == 0) 387 tpcb = sototpcb(so); 388 break; 389 390 case PRU_ABORT: /* called from close() */ 391 /* called for each incoming connect queued on the 392 * parent (accepting) socket 393 */ 394 if (tpcb->tp_state == TP_OPEN || tpcb->tp_state == TP_CONFIRMING) { 395 E.ATTR(T_DISC_req).e_reason = E_TP_NO_SESSION; 396 error = DoEvent(T_DISC_req); /* pretend it was a close() */ 397 break; 398 } /* else DROP THROUGH */ 399 400 case PRU_DETACH: /* called from close() */ 401 /* called only after disconnect was called */ 402 error = DoEvent(T_DETACH); 403 if (tpcb->tp_state == TP_CLOSED) { 404 if (tpcb->tp_notdetached) { 405 IFDEBUG(D_CONN) 406 printf("PRU_DETACH: not detached\n"); 407 ENDDEBUG 408 tp_detach(tpcb); 409 } 410 free((caddr_t)tpcb, M_PCB); 411 tpcb = 0; 412 } 413 break; 414 415 case PRU_SHUTDOWN: 416 /* recv end may have been released; local credit might be zero */ 417 case PRU_DISCONNECT: 418 E.ATTR(T_DISC_req).e_reason = E_TP_NORMAL_DISC; 419 error = DoEvent(T_DISC_req); 420 break; 421 422 case PRU_BIND: 423 error = tp_pcbbind(tpcb, nam); 424 break; 425 426 case PRU_LISTEN: 427 if (tpcb->tp_state != TP_CLOSED || tpcb->tp_lsuffixlen == 0 || 428 tpcb->tp_next == 0) 429 error = EINVAL; 430 else { 431 register struct tp_pcb **tt; 432 remque(tpcb); 433 tpcb->tp_next = tpcb->tp_prev = tpcb; 434 for (tt = &tp_listeners; *tt; tt = &((*tt)->tp_nextlisten)) 435 if ((*tt)->tp_lsuffixlen) 436 break; 437 tpcb->tp_nextlisten = *tt; 438 *tt = tpcb; 439 error = DoEvent(T_LISTEN_req); 440 } 441 break; 442 443 case PRU_CONNECT2: 444 error = EOPNOTSUPP; /* for unix domain sockets */ 445 break; 446 447 case PRU_CONNECT: 448 IFTRACE(D_CONN) 449 tptraceTPCB(TPPTmisc, 450 "PRU_CONNECT: so 0x%x *SHORT_LSUFXP(tpcb) 0x%x lsuflen 0x%x, class 0x%x", 451 tpcb->tp_sock, *SHORT_LSUFXP(tpcb), tpcb->tp_lsuffixlen, 452 tpcb->tp_class); 453 ENDTRACE 454 IFDEBUG(D_CONN) 455 printf("PRU_CONNECT: so *SHORT_LSUFXP(tpcb) 0x%x lsuflen 0x%x, class 0x%x", 456 tpcb->tp_sock, *SHORT_LSUFXP(tpcb), tpcb->tp_lsuffixlen, 457 tpcb->tp_class); 458 ENDDEBUG 459 if (tpcb->tp_lsuffixlen == 0) { 460 if (error = tp_pcbbind(tpcb, MNULL)) { 461 IFDEBUG(D_CONN) 462 printf("pcbbind returns error 0x%x\n", error); 463 ENDDEBUG 464 break; 465 } 466 } 467 IFDEBUG(D_CONN) 468 printf("isop 0x%x isop->isop_socket offset 12 :\n", tpcb->tp_npcb); 469 dump_buf(tpcb->tp_npcb, 16); 470 ENDDEBUG 471 if (error = tp_route_to(nam, tpcb, /* channel */0)) 472 break; 473 IFDEBUG(D_CONN) 474 printf( 475 "PRU_CONNECT after tpcb 0x%x so 0x%x npcb 0x%x flags 0x%x\n", 476 tpcb, so, tpcb->tp_npcb, tpcb->tp_flags); 477 printf("isop 0x%x isop->isop_socket offset 12 :\n", tpcb->tp_npcb); 478 dump_buf(tpcb->tp_npcb, 16); 479 ENDDEBUG 480 if (tpcb->tp_fsuffixlen == 0) { 481 /* didn't set peer extended suffix */ 482 (tpcb->tp_nlproto->nlp_getsufx)(tpcb->tp_npcb, &tpcb->tp_fsuffixlen, 483 tpcb->tp_fsuffix, TP_FOREIGN); 484 } 485 if (tpcb->tp_state == TP_CLOSED) { 486 soisconnecting(so); 487 error = DoEvent(T_CONN_req); 488 } else { 489 (tpcb->tp_nlproto->nlp_pcbdisc)(tpcb->tp_npcb); 490 error = EISCONN; 491 } 492 IFPERF(tpcb) 493 u_int lsufx, fsufx; 494 lsufx = *(u_short *)(tpcb->tp_lsuffix); 495 fsufx = *(u_short *)(tpcb->tp_fsuffix); 496 497 tpmeas(tpcb->tp_lref, 498 TPtime_open | (tpcb->tp_xtd_format << 4), 499 &time, lsufx, fsufx, tpcb->tp_fref); 500 ENDPERF 501 break; 502 503 case PRU_ACCEPT: 504 (tpcb->tp_nlproto->nlp_getnetaddr)(tpcb->tp_npcb, nam, TP_FOREIGN); 505 IFDEBUG(D_REQUEST) 506 printf("ACCEPT PEERADDDR:"); 507 dump_buf(mtod(nam, char *), nam->m_len); 508 ENDDEBUG 509 IFPERF(tpcb) 510 u_int lsufx, fsufx; 511 lsufx = *(u_short *)(tpcb->tp_lsuffix); 512 fsufx = *(u_short *)(tpcb->tp_fsuffix); 513 514 tpmeas(tpcb->tp_lref, TPtime_open, 515 &time, lsufx, fsufx, tpcb->tp_fref); 516 ENDPERF 517 break; 518 519 case PRU_RCVD: 520 if (so->so_state & SS_ISCONFIRMING) { 521 if (tpcb->tp_state == TP_CONFIRMING) 522 error = tp_confirm(tpcb); 523 break; 524 } 525 IFTRACE(D_DATA) 526 tptraceTPCB(TPPTmisc, 527 "RCVD BF: lcredit sent_lcdt cc hiwat \n", 528 tpcb->tp_lcredit, tpcb->tp_sent_lcdt, 529 so->so_rcv.sb_cc, so->so_rcv.sb_hiwat); 530 LOCAL_CREDIT(tpcb); 531 tptraceTPCB(TPPTmisc, 532 "PRU_RCVD AF sbspace lcredit hiwat cc", 533 sbspace(&so->so_rcv), tpcb->tp_lcredit, 534 so->so_rcv.sb_cc, so->so_rcv.sb_hiwat); 535 ENDTRACE 536 IFDEBUG(D_REQUEST) 537 printf("RCVD: cc %d space %d hiwat %d\n", 538 so->so_rcv.sb_cc, sbspace(&so->so_rcv), 539 so->so_rcv.sb_hiwat); 540 ENDDEBUG 541 if (((int)nam) & MSG_OOB) 542 error = DoEvent(T_USR_Xrcvd); 543 else 544 error = DoEvent(T_USR_rcvd); 545 break; 546 547 case PRU_RCVOOB: 548 if ((so->so_state & SS_ISCONNECTED) == 0) { 549 error = ENOTCONN; 550 break; 551 } 552 if (! tpcb->tp_xpd_service) { 553 error = EOPNOTSUPP; 554 break; 555 } 556 /* kludge - nam is really flags here */ 557 error = tp_rcvoob(tpcb, so, m, outflags, (int)nam); 558 break; 559 560 case PRU_SEND: 561 case PRU_SENDOOB: 562 if (controlp) { 563 error = tp_snd_control(controlp, so, &m); 564 controlp = NULL; 565 if (error) 566 break; 567 } 568 if ((so->so_state & SS_ISCONFIRMING) && 569 (tpcb->tp_state == TP_CONFIRMING) && 570 (error = tp_confirm(tpcb))) 571 break; 572 if (req == PRU_SENDOOB) { 573 error = (tpcb->tp_xpd_service == 0) ? 574 EOPNOTSUPP : tp_sendoob(tpcb, so, m, outflags); 575 break; 576 } 577 if (m == 0) 578 break; 579 if (m->m_flags & M_EOR) { 580 eotsdu = 1; 581 m->m_flags &= ~M_EOR; 582 } 583 if (eotsdu == 0 && m->m_pkthdr.len == 0) 584 break; 585 if (tpcb->tp_state != TP_AKWAIT && tpcb->tp_state != TP_OPEN) { 586 error = ENOTCONN; 587 break; 588 } 589 /* 590 * The protocol machine copies mbuf chains, 591 * prepends headers, assigns seq numbers, and 592 * puts the packets on the device. 593 * When they are acked they are removed from the socket buf. 594 * 595 * sosend calls this up until sbspace goes negative. 596 * Sbspace may be made negative by appending this mbuf chain, 597 * possibly by a whole cluster. 598 */ 599 { 600 /* 601 * Could have eotsdu and no data.(presently MUST have 602 * an mbuf though, even if its length == 0) 603 */ 604 int totlen = m->m_pkthdr.len; 605 struct sockbuf *sb = &so->so_snd; 606 IFPERF(tpcb) 607 PStat(tpcb, Nb_from_sess) += totlen; 608 tpmeas(tpcb->tp_lref, TPtime_from_session, 0, 0, 609 PStat(tpcb, Nb_from_sess), totlen); 610 ENDPERF 611 IFDEBUG(D_SYSCALL) 612 printf( 613 "PRU_SEND: eot %d before sbappend 0x%x len 0x%x to sb @ 0x%x\n", 614 eotsdu, m, totlen, sb); 615 dump_mbuf(sb->sb_mb, "so_snd.sb_mb"); 616 dump_mbuf(m, "m : to be added"); 617 ENDDEBUG 618 tp_packetize(tpcb, m, eotsdu); 619 IFDEBUG(D_SYSCALL) 620 printf("PRU_SEND: eot %d after sbappend 0x%x\n", eotsdu, m); 621 dump_mbuf(sb->sb_mb, "so_snd.sb_mb"); 622 ENDDEBUG 623 if (tpcb->tp_state == TP_OPEN) 624 error = DoEvent(T_DATA_req); 625 IFDEBUG(D_SYSCALL) 626 printf("PRU_SEND: after driver error 0x%x \n",error); 627 printf("so_snd 0x%x cc 0t%d mbcnt 0t%d\n", 628 sb, sb->sb_cc, sb->sb_mbcnt); 629 dump_mbuf(sb->sb_mb, "so_snd.sb_mb after driver"); 630 ENDDEBUG 631 } 632 break; 633 634 case PRU_SOCKADDR: 635 (tpcb->tp_nlproto->nlp_getnetaddr)(tpcb->tp_npcb, nam, TP_LOCAL); 636 break; 637 638 case PRU_PEERADDR: 639 (tpcb->tp_nlproto->nlp_getnetaddr)(tpcb->tp_npcb, nam, TP_FOREIGN); 640 break; 641 642 case PRU_CONTROL: 643 error = EOPNOTSUPP; 644 break; 645 646 case PRU_PROTOSEND: 647 case PRU_PROTORCV: 648 case PRU_SENSE: 649 case PRU_SLOWTIMO: 650 case PRU_FASTTIMO: 651 error = EOPNOTSUPP; 652 break; 653 654 default: 655 #ifdef ARGO_DEBUG 656 printf("tp_usrreq UNKNOWN PRU %d\n", req); 657 #endif /* ARGO_DEBUG */ 658 error = EOPNOTSUPP; 659 } 660 661 IFDEBUG(D_REQUEST) 662 printf("%s, so 0x%x, tpcb 0x%x, error %d, state %d\n", 663 "returning from tp_usrreq", so, tpcb, error, 664 tpcb ? tpcb->tp_state : 0); 665 ENDDEBUG 666 IFTRACE(D_REQUEST) 667 tptraceTPCB(TPPTusrreq, "END req so m state [", req, so, m, 668 tpcb ? tpcb->tp_state : 0); 669 ENDTRACE 670 if (controlp) { 671 m_freem(controlp); 672 printf("control data unexpectedly retained in tp_usrreq()"); 673 } 674 splx(s); 675 return error; 676 } 677 tp_ltrace(so, uio) 678 struct socket *so; 679 struct uio *uio; 680 { 681 IFTRACE(D_DATA) 682 register struct tp_pcb *tpcb = sototpcb(so); 683 if (tpcb) { 684 tptraceTPCB(TPPTmisc, "sosend so resid iovcnt", so, 685 uio->uio_resid, uio->uio_iovcnt, 0); 686 } 687 ENDTRACE 688 } 689 690 tp_confirm(tpcb) 691 register struct tp_pcb *tpcb; 692 { 693 struct tp_event E; 694 if (tpcb->tp_state == TP_CONFIRMING) 695 return DoEvent(T_ACPT_req); 696 printf("Tp confirm called when not confirming; tpcb 0x%x, state 0x%x\n", 697 tpcb, tpcb->tp_state); 698 return 0; 699 } 700 701 /* 702 * Process control data sent with sendmsg() 703 */ 704 tp_snd_control(m, so, data) 705 struct mbuf *m; 706 struct socket *so; 707 register struct mbuf **data; 708 { 709 register struct cmsghdr *ch; 710 int error = 0; 711 712 if (m && m->m_len) { 713 ch = mtod(m, struct cmsghdr *); 714 m->m_len -= sizeof (*ch); 715 m->m_data += sizeof (*ch); 716 error = tp_ctloutput(PRCO_SETOPT, 717 so, ch->cmsg_level, ch->cmsg_type, &m); 718 if (ch->cmsg_type == TPOPT_DISC_DATA) { 719 if (data && *data) { 720 m_freem(*data); 721 *data = 0; 722 } 723 error = tp_usrreq(so, PRU_DISCONNECT, (struct mbuf *)0, 724 (caddr_t)0, (struct mbuf *)0); 725 } 726 } 727 if (m) 728 m_freem(m); 729 return error; 730 } 731