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