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