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