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