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