|
|
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_pcb.c,v 5.4 88/11/18 17:28:24 nhall Exp $
31: * $Source: /usr/argo/sys/netiso/RCS/tp_pcb.c,v $
32: * @(#)tp_pcb.c 7.6 (Berkeley) 6/28/90 *
33: *
34: *
35: * This is the initialization and cleanup stuff -
36: * for the tp machine in general as well as for the individual pcbs.
37: * tp_init() is called at system startup. tp_attach() and tp_getref() are
38: * called when a socket is created. tp_detach() and tp_freeref()
39: * are called during the closing stage and/or when the reference timer
40: * goes off.
41: * tp_soisdisconnecting() and tp_soisdisconnected() are tp-specific
42: * versions of soisconnect*
43: * and are called (obviously) during the closing phase.
44: *
45: */
46:
47: #ifndef lint
48: static char *rcsid = "$Header: tp_pcb.c,v 5.4 88/11/18 17:28:24 nhall Exp $";
49: #endif lint
50:
51: #include "argoxtwentyfive.h"
52: #include "types.h"
53: #include "param.h"
54: #include "mbuf.h"
55: #include "socket.h"
56: #include "socketvar.h"
57: #include "protosw.h"
58: #include "errno.h"
59: #include "time.h"
60: #include "argo_debug.h"
61: #include "tp_param.h"
62: #include "tp_timer.h"
63: #include "tp_ip.h"
64: #include "tp_stat.h"
65: #include "tp_pcb.h"
66: #include "tp_tpdu.h"
67: #include "tp_trace.h"
68: #include "tp_meas.h"
69: #include "tp_seq.h"
70: #include "tp_clnp.h"
71:
72: /* list of reference structures */
73: struct tp_ref tp_ref[N_TPREF];
74:
75: struct tp_param tp_param = {
76: 1, /* configured */
77: };
78:
79: /* ticks are in units of:
80: * 500 nano-fortnights ;-) or
81: * 500 ms or
82: * 1/2 second
83: */
84:
85: struct tp_conn_param tp_conn_param[] = {
86: /* ISO_CLNS: TP4 CONNECTION LESS */
87: {
88: TP_NRETRANS, /* short p_Nretrans; */
89: 20, /* 10 sec */ /* short p_dr_ticks; */
90:
91: 20, /* 10 sec */ /* short p_cc_ticks; */
92: 20, /* 10 sec */ /* short p_dt_ticks; */
93:
94: 40, /* 20 sec */ /* short p_x_ticks; */
95: 80, /* 40 sec */ /* short p_cr_ticks;*/
96:
97: 240, /* 2 min */ /* short p_keepalive_ticks;*/
98: 10, /* 5 sec */ /* short p_sendack_ticks; */
99:
100: 600, /* 5 min */ /* short p_ref_ticks; */
101: 360, /* 3 min */ /* short p_inact_ticks; */
102:
103: (short) 100, /* short p_lcdtfract */
104: (short) TP_SOCKBUFSIZE, /* short p_winsize */
105: TP_TPDUSIZE, /* u_char p_tpdusize */
106:
107: TPACK_WINDOW, /* 4 bits p_ack_strat */
108: TPRX_USE_CW | TPRX_FASTSTART,
109: /* 4 bits p_rx_strat*/
110: TP_CLASS_4 | TP_CLASS_0,/* 5 bits p_class */
111: 1, /* 1 bit xtd format */
112: 1, /* 1 bit xpd service */
113: 1, /* 1 bit use_checksum */
114: 0, /* 1 bit use net xpd */
115: 0, /* 1 bit use rcc */
116: 0, /* 1 bit use efc */
117: 1, /* no disc indications */
118: 0, /* don't change params */
119: ISO_CLNS, /* p_netservice */
120: },
121: /* IN_CLNS: TP4 CONNECTION LESS */
122: {
123: TP_NRETRANS, /* short p_Nretrans; */
124: 20, /* 10 sec */ /* short p_dr_ticks; */
125:
126: 20, /* 10 sec */ /* short p_cc_ticks; */
127: 20, /* 10 sec */ /* short p_dt_ticks; */
128:
129: 40, /* 20 sec */ /* short p_x_ticks; */
130: 80, /* 40 sec */ /* short p_cr_ticks;*/
131:
132: 240, /* 2 min */ /* short p_keepalive_ticks;*/
133: 10, /* 5 sec */ /* short p_sendack_ticks; */
134:
135: 600, /* 5 min */ /* short p_ref_ticks; */
136: 360, /* 3 min */ /* short p_inact_ticks; */
137:
138: (short) 100, /* short p_lcdtfract */
139: (short) TP_SOCKBUFSIZE, /* short p_winsize */
140: TP_TPDUSIZE, /* u_char p_tpdusize */
141:
142: TPACK_WINDOW, /* 4 bits p_ack_strat */
143: TPRX_USE_CW | TPRX_FASTSTART,
144: /* 4 bits p_rx_strat*/
145: TP_CLASS_4, /* 5 bits p_class */
146: 1, /* 1 bit xtd format */
147: 1, /* 1 bit xpd service */
148: 1, /* 1 bit use_checksum */
149: 0, /* 1 bit use net xpd */
150: 0, /* 1 bit use rcc */
151: 0, /* 1 bit use efc */
152: 1, /* no disc indications */
153: 0, /* don't change params */
154: IN_CLNS, /* p_netservice */
155: },
156: /* ISO_CONS: TP0 CONNECTION MODE */
157: {
158: TP_NRETRANS, /* short p_Nretrans; */
159: 0, /* n/a */ /* short p_dr_ticks; */
160:
161: 40, /* 20 sec */ /* short p_cc_ticks; */
162: 0, /* n/a */ /* short p_dt_ticks; */
163:
164: 0, /* n/a */ /* short p_x_ticks; */
165: 360, /* 3 min */ /* short p_cr_ticks;*/
166:
167: 0, /* n/a */ /* short p_keepalive_ticks;*/
168: 0, /* n/a */ /* short p_sendack_ticks; */
169:
170: 600, /* for cr/cc to clear *//* short p_ref_ticks; */
171: 0, /* n/a */ /* short p_inact_ticks; */
172:
173: /* Use tp4 defaults just in case the user changes ONLY
174: * the class
175: */
176: (short) 100, /* short p_lcdtfract */
177: (short) TP0_SOCKBUFSIZE, /* short p_winsize */
178: TP0_TPDUSIZE, /* 8 bits p_tpdusize */
179:
180: 0, /* 4 bits p_ack_strat */
181: 0, /* 4 bits p_rx_strat*/
182: TP_CLASS_0, /* 5 bits p_class */
183: 0, /* 1 bit xtd format */
184: 0, /* 1 bit xpd service */
185: 0, /* 1 bit use_checksum */
186: 0, /* 1 bit use net xpd */
187: 0, /* 1 bit use rcc */
188: 0, /* 1 bit use efc */
189: 0, /* no disc indications */
190: 0, /* don't change params */
191: ISO_CONS, /* p_netservice */
192: },
193: /* ISO_COSNS: TP4 CONNECTION LESS SERVICE over CONSNS */
194: {
195: TP_NRETRANS, /* short p_Nretrans; */
196: 40, /* 20 sec */ /* short p_dr_ticks; */
197:
198: 40, /* 20 sec */ /* short p_cc_ticks; */
199: 80, /* 40 sec */ /* short p_dt_ticks; */
200:
201: 120, /* 1 min */ /* short p_x_ticks; */
202: 360, /* 3 min */ /* short p_cr_ticks;*/
203:
204: 360, /* 3 min */ /* short p_keepalive_ticks;*/
205: 20, /* 10 sec */ /* short p_sendack_ticks; */
206:
207: 600, /* 5 min */ /* short p_ref_ticks; */
208: 480, /* 4 min */ /* short p_inact_ticks; */
209:
210: (short) 100, /* short p_lcdtfract */
211: (short) TP0_SOCKBUFSIZE, /* short p_winsize */
212: TP0_TPDUSIZE, /* u_char p_tpdusize */
213:
214: TPACK_WINDOW, /* 4 bits p_ack_strat */
215: TPRX_USE_CW , /* No fast start */
216: /* 4 bits p_rx_strat*/
217: TP_CLASS_4 | TP_CLASS_0,/* 5 bits p_class */
218: 0, /* 1 bit xtd format */
219: 1, /* 1 bit xpd service */
220: 1, /* 1 bit use_checksum */
221: 0, /* 1 bit use net xpd */
222: 0, /* 1 bit use rcc */
223: 0, /* 1 bit use efc */
224: 0, /* no disc indications */
225: 0, /* don't change params */
226: ISO_COSNS, /* p_netservice */
227: },
228: };
229:
230: #ifdef INET
231: int in_putnetaddr();
232: int in_getnetaddr();
233: int in_cmpnetaddr();
234: int in_putsufx();
235: int in_getsufx();
236: int in_recycle_tsuffix();
237: int tpip_mtu();
238: int in_pcbbind();
239: int in_pcbconnect();
240: int in_pcbdisconnect();
241: int in_pcbdetach();
242: int in_pcballoc();
243: int tpip_output();
244: int tpip_output_dg();
245: struct inpcb tp_inpcb;
246: #endif INET
247: #ifdef ISO
248: int iso_putnetaddr();
249: int iso_getnetaddr();
250: int iso_cmpnetaddr();
251: int iso_putsufx();
252: int iso_getsufx();
253: int iso_recycle_tsuffix();
254: int tpclnp_mtu();
255: int iso_pcbbind();
256: int iso_pcbconnect();
257: int iso_pcbdisconnect();
258: int iso_pcbdetach();
259: int iso_pcballoc();
260: int tpclnp_output();
261: int tpclnp_output_dg();
262: int iso_nlctloutput();
263: struct isopcb tp_isopcb;
264: #endif ISO
265: #if NARGOXTWENTYFIVE > 0
266: int iso_putnetaddr();
267: int iso_getnetaddr();
268: int iso_cmpnetaddr();
269: int iso_putsufx();
270: int iso_getsufx();
271: int iso_recycle_tsuffix();
272: int tpcons_mtu();
273: int iso_pcbbind();
274: int iso_pcbconnect();
275: int iso_pcbdisconnect();
276: int iso_pcbdetach();
277: int iso_pcballoc();
278: int tpcons_output();
279: int tpcons_output_dg();
280: struct isopcb tp_isopcb;
281: #endif NARGOXTWENTYFIVE
282:
283:
284: struct nl_protosw nl_protosw[] = {
285: /* ISO_CLNS */
286: #ifdef ISO
287: { AF_ISO, iso_putnetaddr, iso_getnetaddr, iso_cmpnetaddr,
288: iso_putsufx, iso_getsufx,
289: iso_recycle_tsuffix,
290: tpclnp_mtu, iso_pcbbind, iso_pcbconnect,
291: iso_pcbdisconnect, iso_pcbdetach,
292: iso_pcballoc,
293: tpclnp_output, tpclnp_output_dg, iso_nlctloutput,
294: (caddr_t) &tp_isopcb,
295: },
296: #else
297: { 0 },
298: #endif ISO
299: /* IN_CLNS */
300: #ifdef INET
301: { AF_INET, in_putnetaddr, in_getnetaddr, in_cmpnetaddr,
302: in_putsufx, in_getsufx,
303: in_recycle_tsuffix,
304: tpip_mtu, in_pcbbind, in_pcbconnect,
305: in_pcbdisconnect, in_pcbdetach,
306: in_pcballoc,
307: tpip_output, tpip_output_dg, /* nl_ctloutput */ NULL,
308: (caddr_t) &tp_inpcb,
309: },
310: #else
311: { 0 },
312: #endif INET
313: /* ISO_CONS */
314: #if defined(ISO) && (NARGOXTWENTYFIVE > 0)
315: { AF_ISO, iso_putnetaddr, iso_getnetaddr, iso_cmpnetaddr,
316: iso_putsufx, iso_getsufx,
317: iso_recycle_tsuffix,
318: tpcons_mtu, iso_pcbbind, iso_pcbconnect,
319: iso_pcbdisconnect, iso_pcbdetach,
320: iso_pcballoc,
321: tpcons_output, tpcons_output_dg, iso_nlctloutput,
322: (caddr_t) &tp_isopcb,
323: },
324: #else
325: { 0 },
326: #endif ISO_CONS
327: /* End of protosw marker */
328: { 0 }
329: };
330:
331: /*
332: * NAME: tp_init()
333: *
334: * CALLED FROM:
335: * autoconf through the protosw structure
336: *
337: * FUNCTION:
338: * initialize tp machine
339: *
340: * RETURNS: Nada
341: *
342: * SIDE EFFECTS:
343: *
344: * NOTES:
345: */
346: int
347: tp_init()
348: {
349: static int init_done=0;
350: void tp_timerinit();
351:
352: if (init_done++)
353: return 0;
354:
355:
356: /* FOR INET */
357: tp_inpcb.inp_next = tp_inpcb.inp_prev = &tp_inpcb;
358: /* FOR ISO */
359: tp_isopcb.isop_next = tp_isopcb.isop_prev = &tp_isopcb;
360:
361: tp_start_win = 2;
362:
363: tp_timerinit();
364: bzero((caddr_t)&tp_stat, sizeof(struct tp_stat));
365: return 0;
366: }
367:
368: /*
369: * NAME: tp_soisdisconnecting()
370: *
371: * CALLED FROM:
372: * tp.trans
373: *
374: * FUNCTION and ARGUMENTS:
375: * Set state of the socket (so) to reflect that fact that we're disconnectING
376: *
377: * RETURNS: Nada
378: *
379: * SIDE EFFECTS:
380: *
381: * NOTES:
382: * This differs from the regular soisdisconnecting() in that the latter
383: * also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags.
384: * We don't want to set those flags because those flags will cause
385: * a SIGPIPE to be delivered in sosend() and we don't like that.
386: * If anyone else is sleeping on this socket, wake 'em up.
387: */
388: void
389: tp_soisdisconnecting(so)
390: register struct socket *so;
391: {
392: soisdisconnecting(so);
393: so->so_state &= ~SS_CANTSENDMORE;
394: IFPERF(sototpcb(so))
395: register struct tp_pcb *tpcb = sototpcb(so);
396: u_int fsufx, lsufx;
397:
398: bcopy ((caddr_t)tpcb->tp_fsuffix, (caddr_t)&fsufx, sizeof(u_int) );
399: bcopy ((caddr_t)tpcb->tp_lsuffix, (caddr_t)&lsufx, sizeof(u_int) );
400:
401: tpmeas(tpcb->tp_lref, TPtime_close, &time, fsufx, lsufx, tpcb->tp_fref);
402: tpcb->tp_perf_on = 0; /* turn perf off */
403: ENDPERF
404: }
405:
406:
407: /*
408: * NAME: tp_soisdisconnected()
409: *
410: * CALLED FROM:
411: * tp.trans
412: *
413: * FUNCTION and ARGUMENTS:
414: * Set state of the socket (so) to reflect that fact that we're disconnectED
415: * Set the state of the reference structure to closed, and
416: * recycle the suffix.
417: * Start a reference timer.
418: *
419: * RETURNS: Nada
420: *
421: * SIDE EFFECTS:
422: *
423: * NOTES:
424: * This differs from the regular soisdisconnected() in that the latter
425: * also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags.
426: * We don't want to set those flags because those flags will cause
427: * a SIGPIPE to be delivered in sosend() and we don't like that.
428: * If anyone else is sleeping on this socket, wake 'em up.
429: */
430: void
431: tp_soisdisconnected(tpcb)
432: register struct tp_pcb *tpcb;
433: {
434: register struct socket *so = tpcb->tp_sock;
435:
436: soisdisconnecting(so);
437: so->so_state &= ~SS_CANTSENDMORE;
438: IFPERF(sototpcb(so))
439: register struct tp_pcb *ttpcb = sototpcb(so);
440: u_int fsufx, lsufx;
441:
442: /* CHOKE */
443: bcopy ((caddr_t)ttpcb->tp_fsuffix, (caddr_t)&fsufx, sizeof(u_int) );
444: bcopy ((caddr_t)ttpcb->tp_lsuffix, (caddr_t)&lsufx, sizeof(u_int) );
445:
446: tpmeas(ttpcb->tp_lref, TPtime_close,
447: &time, &lsufx, &fsufx, ttpcb->tp_fref);
448: tpcb->tp_perf_on = 0; /* turn perf off */
449: ENDPERF
450:
451: tpcb->tp_refp->tpr_state = REF_FROZEN;
452: tp_recycle_tsuffix( tpcb );
453: tp_etimeout(tpcb->tp_refp, TM_reference, 0,0,0, (int)tpcb->tp_refer_ticks);
454: }
455:
456: int tp_maxrefopen; /* highest reference # of the set of open tp connections */
457:
458: /*
459: * NAME: tp_freeref()
460: *
461: * CALLED FROM:
462: * tp.trans when the reference timer goes off, and
463: * from tp_attach() and tp_detach() when a tpcb is partially set up but not
464: * set up enough to have a ref timer set for it, and it's discarded
465: * due to some sort of error or an early close()
466: *
467: * FUNCTION and ARGUMENTS:
468: * Frees the reference represented by (r) for re-use.
469: *
470: * RETURNS: Nothing
471: *
472: * SIDE EFFECTS:
473: *
474: * NOTES: better be called at clock priority !!!!!
475: */
476: void
477: tp_freeref(r)
478: register struct tp_ref *r;
479: {
480: IFDEBUG(D_TIMER)
481: printf("tp_freeref called for ref %d maxrefopen %d\n",
482: r - tp_ref, tp_maxrefopen);
483: ENDDEBUG
484: IFTRACE(D_TIMER)
485: tptrace(TPPTmisc, "tp_freeref ref tp_maxrefopen",
486: r - tp_ref, tp_maxrefopen, 0, 0);
487: ENDTRACE
488: r->tpr_state = REF_FREE;
489: IFDEBUG(D_CONN)
490: printf("tp_freeref: CLEARING tpr_pcb 0x%x\n", r->tpr_pcb);
491: ENDDEBUG
492: r->tpr_pcb = (struct tp_pcb *)0;
493:
494: r = &tp_ref[tp_maxrefopen];
495:
496: while( tp_maxrefopen > 0 ) {
497: if(r->tpr_state )
498: break;
499: tp_maxrefopen--;
500: r--;
501: }
502: IFDEBUG(D_TIMER)
503: printf("tp_freeref ends w/ maxrefopen %d\n", tp_maxrefopen);
504: ENDDEBUG
505: }
506:
507: /*
508: * NAME: tp_getref()
509: *
510: * CALLED FROM:
511: * tp_attach()
512: *
513: * FUNCTION and ARGUMENTS:
514: * obtains the next free reference and allocates the appropriate
515: * ref structure, links that structure to (tpcb)
516: *
517: * RETURN VALUE:
518: * a reference number
519: * or TP_ENOREF
520: *
521: * SIDE EFFECTS:
522: *
523: * NOTES:
524: */
525: static RefNum
526: tp_getref(tpcb)
527: register struct tp_pcb *tpcb;
528: {
529: register struct tp_ref *r = tp_ref;
530: register int i=1;
531:
532: r++; /* tp_ref[0] is never used */
533:
534: /* REF_FREE is zero */
535: while( r->tpr_state ) {
536: r++;
537: if ( i == N_TPREF ) {
538: return TP_ENOREF;
539: }
540: i++;
541: }
542: r->tpr_state = REF_OPENING;
543: if (tp_maxrefopen < i)
544: tp_maxrefopen = i;
545: r->tpr_pcb = tpcb;
546: tpcb->tp_refp = r;
547:
548: return i;
549: }
550:
551: /*
552: * NAME: tp_attach()
553: *
554: * CALLED FROM:
555: * tp_usrreq, PRU_ATTACH
556: *
557: * FUNCTION and ARGUMENTS:
558: * given a socket (so) and a protocol family (dom), allocate a tpcb
559: * and ref structure, initialize everything in the structures that
560: * needs to be initialized.
561: *
562: * RETURN VALUE:
563: * 0 ok
564: * EINVAL if DEBUG(X) in is on and a disaster has occurred
565: * ENOPROTOOPT if TP hasn't been configured or if the
566: * socket wasn't created with tp as its protocol
567: * EISCONN if this socket is already part of a connection
568: * ETOOMANYREFS if ran out of tp reference numbers.
569: * E* whatever error is returned from soreserve()
570: * for from the network-layer pcb allocation routine
571: *
572: * SIDE EFFECTS:
573: *
574: * NOTES:
575: */
576: tp_attach(so, dom)
577: struct socket *so;
578: int dom;
579: {
580: register struct tp_pcb *tpcb;
581: int error;
582: int protocol = so->so_proto->pr_protocol;
583: extern struct tp_conn_param tp_conn_param[];
584:
585: IFDEBUG(D_CONN)
586: printf("tp_attach:dom 0x%x so 0x%x ", dom, so);
587: ENDDEBUG
588: IFTRACE(D_CONN)
589: tptrace(TPPTmisc, "tp_attach:dom so", dom, so, 0, 0);
590: ENDTRACE
591: if ( ! tp_param.tpp_configed ) {
592: error = ENOPROTOOPT; /* protocol not available */
593: goto bad2;
594: }
595:
596: if (so->so_pcb != NULL) {
597: return EISCONN; /* socket already part of a connection*/
598: }
599:
600: error = soreserve(so, TP_SOCKBUFSIZE, TP_SOCKBUFSIZE);
601: /* later an ioctl will allow reallocation IF still in closed state */
602:
603: if (error)
604: goto bad2;
605:
606: MALLOC(tpcb, struct tp_pcb *, sizeof(*tpcb), M_PCB, M_NOWAIT);
607: if (tpcb == NULL) {
608: error = ENOBUFS;
609: goto bad2;
610: }
611: bzero( (caddr_t)tpcb, sizeof (struct tp_pcb) );
612:
613: if ( ((tpcb->tp_lref = tp_getref(tpcb)) & TP_ENOREF) != 0 ) {
614: error = ETOOMANYREFS;
615: goto bad3;
616: }
617: tpcb->tp_sock = so;
618: tpcb->tp_domain = dom;
619: if (protocol<ISOPROTO_TP4) {
620: tpcb->tp_netservice = ISO_CONS;
621: tpcb->tp_snduna = (SeqNum) -1;/* kludge so the pseudo-ack from the CR/CC
622: * will generate correct fake-ack values
623: */
624: } else {
625: tpcb->tp_netservice = (dom== AF_INET)?IN_CLNS:ISO_CLNS;
626: /* the default */
627: }
628: tpcb->_tp_param = tp_conn_param[tpcb->tp_netservice];
629:
630: tpcb->tp_cong_win = 1;
631: tpcb->tp_state = TP_CLOSED;
632: tpcb->tp_vers = TP_VERSION;
633:
634: /* Spec says default is 128 octets,
635: * that is, if the tpdusize argument never appears, use 128.
636: * As the initiator, we will always "propose" the 2048
637: * size, that is, we will put this argument in the CR
638: * always, but accept what the other side sends on the CC.
639: * If the initiator sends us something larger on a CR,
640: * we'll respond w/ this.
641: * Our maximum is 4096. See tp_chksum.c comments.
642: */
643: tpcb->tp_l_tpdusize = 1 << tpcb->tp_tpdusize;
644:
645: tpcb->tp_seqmask = TP_NML_FMT_MASK;
646: tpcb->tp_seqbit = TP_NML_FMT_BIT;
647: tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1;
648: tpcb->tp_sndhiwat = (SeqNum) - 1; /* a kludge but it works */
649: tpcb->tp_s_subseq = 0;
650:
651: /* attach to a network-layer protoswitch */
652: /* new way */
653: tpcb->tp_nlproto = & nl_protosw[tpcb->tp_netservice];
654: ASSERT( tpcb->tp_nlproto->nlp_afamily == tpcb->tp_domain);
655: #ifdef notdef
656: /* OLD WAY */
657: /* TODO: properly, this search would be on the basis of
658: * domain,netservice or just netservice only (if you have
659: * IN_CLNS, ISO_CLNS, and ISO_CONS)
660: */
661: tpcb->tp_nlproto = nl_protosw;
662: while(tpcb->tp_nlproto->nlp_afamily != tpcb->tp_domain ) {
663: if( tpcb->tp_nlproto->nlp_afamily == 0 ) {
664: error = EAFNOSUPPORT;
665: goto bad4;
666: }
667: tpcb->tp_nlproto ++;
668: }
669: #endif notdef
670:
671: /* xx_pcballoc sets so_pcb */
672: if ( error = (tpcb->tp_nlproto->nlp_pcballoc) (
673: so, tpcb->tp_nlproto->nlp_pcblist ) ) {
674: goto bad4;
675: }
676:
677: if( dom == AF_INET )
678: sotoinpcb(so)->inp_ppcb = (caddr_t) tpcb;
679: /* nothing to do for iso case */
680:
681: tpcb->tp_npcb = (caddr_t) so->so_pcb;
682: so->so_tpcb = (caddr_t) tpcb;
683:
684: return 0;
685:
686: bad4:
687: IFDEBUG(D_CONN)
688: printf("BAD4 in tp_attach, so 0x%x\n", so);
689: ENDDEBUG
690: tp_freeref(tpcb->tp_refp);
691:
692: bad3:
693: IFDEBUG(D_CONN)
694: printf("BAD3 in tp_attach, so 0x%x\n", so);
695: ENDDEBUG
696:
697: free((caddr_t)tpcb, M_PCB); /* never a cluster */
698:
699: bad2:
700: IFDEBUG(D_CONN)
701: printf("BAD2 in tp_attach, so 0x%x\n", so);
702: ENDDEBUG
703: so->so_pcb = 0;
704: so->so_tpcb = 0;
705: sofree(so);
706:
707: /*bad:*/
708: IFDEBUG(D_CONN)
709: printf("BAD in tp_attach, so 0x%x\n", so);
710: ENDDEBUG
711: return error;
712: }
713:
714: /*
715: * NAME: tp_detach()
716: *
717: * CALLED FROM:
718: * tp.trans, on behalf of a user close request
719: * and when the reference timer goes off
720: * (if the disconnect was initiated by the protocol entity
721: * rather than by the user)
722: *
723: * FUNCTION and ARGUMENTS:
724: * remove the tpcb structure from the list of active or
725: * partially active connections, recycle all the mbufs
726: * associated with the pcb, ref structure, sockbufs, etc.
727: * Only free the ref structure if you know that a ref timer
728: * wasn't set for this tpcb.
729: *
730: * RETURNS: Nada
731: *
732: * SIDE EFFECTS:
733: *
734: * NOTES:
735: * tp_soisdisconnected() was already when this is called
736: */
737: void
738: tp_detach(tpcb)
739: register struct tp_pcb *tpcb;
740: {
741: void tp_freeref();
742: register struct socket *so = tpcb->tp_sock;
743:
744: IFDEBUG(D_CONN)
745: printf("tp_detach(tpcb 0x%x, so 0x%x)\n",
746: tpcb,so);
747: ENDDEBUG
748: IFTRACE(D_CONN)
749: tptraceTPCB(TPPTmisc, "tp_detach tpcb so lsufx",
750: tpcb, so, *(u_short *)(tpcb->tp_lsuffix), 0);
751: ENDTRACE
752:
753: if (so->so_head) {
754: if (!soqremque(so, 0) && !soqremque(so, 1))
755: panic("sofree dq");
756: so->so_head = 0;
757: }
758:
759: IFDEBUG(D_CONN)
760: printf("tp_detach(freeing RTC list snduna 0x%x rcvnxt 0x%x)\n",
761: tpcb->tp_snduna_rtc,
762: tpcb->tp_rcvnxt_rtc);
763: ENDDEBUG
764:
765: #define FREE_RTC_LIST(XXX)\
766: { register struct tp_rtc *xxr = XXX, *xxs; while (xxr) {\
767: xxs = xxr->tprt_next;\
768: m_freem( xxr->tprt_data );\
769: m_free( dtom(xxr) ); xxr = xxs; }\
770: XXX = (struct tp_rtc *)0;\
771: }
772:
773: FREE_RTC_LIST( tpcb->tp_snduna_rtc );
774: tpcb->tp_sndhiwat_rtc = (struct tp_rtc *)0;
775:
776: FREE_RTC_LIST( tpcb->tp_rcvnxt_rtc );
777:
778: #undef FREE_RTC_LIST
779:
780: IFDEBUG(D_CONN)
781: printf("calling (...nlproto->...)(0x%x, so 0x%x)\n",
782: so->so_pcb, so);
783: printf("so 0x%x so_head 0x%x, qlen %d q0len %d qlimit %d\n",
784: so, so->so_head,
785: so->so_q0len, so->so_qlen, so->so_qlimit);
786: ENDDEBUG
787:
788: if ( tpcb->tp_flags & (TPF_DISC_DATA_OUT | TPF_CONN_DATA_OUT ) ) {
789: ASSERT( so->so_snd.sb_cc != 0 );
790: IFDEBUG(D_CONN)
791: printf(
792: "detach, flags 0x%x doing sbdrop on so_snd, mb 0x%x cc 0x%x\n",
793: tpcb->tp_flags, so->so_snd.sb_mb, so->so_snd.sb_cc);
794: dump_mbuf( so->so_snd.sb_mb, "detach so snd: \n");
795: ENDDEBUG
796: if ( so->so_snd.sb_cc != 0 )
797: sbflush(&so->so_snd);
798: tpcb->tp_flags &= ~(TPF_CONN_DATA_OUT | TPF_DISC_DATA_OUT);
799: }
800: if ( tpcb->tp_flags & (TPF_DISC_DATA_IN | TPF_CONN_DATA_IN ) ) {
801: ASSERT( tpcb->tp_Xrcv.sb_cc != 0 );
802: IFDEBUG(D_CONN)
803: printf(
804: "detach, flags 0x%x doing sbdrop on tp_Xrcv, mb 0x%x cc 0x%x\n",
805: tpcb->tp_flags, tpcb->tp_Xrcv.sb_mb, tpcb->tp_Xrcv.sb_cc);
806: dump_mbuf( tpcb->tp_Xrcv.sb_mb, "detach Xrcv: \n");
807: ENDDEBUG
808: if( tpcb->tp_Xrcv.sb_cc != 0 )
809: sbdrop(&tpcb->tp_Xrcv, (int)tpcb->tp_Xrcv.sb_cc);
810: tpcb->tp_flags &= ~(TPF_CONN_DATA_IN | TPF_DISC_DATA_IN);
811: }
812:
813: IFDEBUG(D_CONN)
814: printf("so_snd at 0x%x so_rcv at 0x%x\n", &so->so_snd, &so->so_rcv);
815: dump_mbuf(so->so_snd.sb_mb, "so_snd at detach ");
816: printf("about to call LL detach, nlproto 0x%x, nl_detach 0x%x\n",
817: tpcb->tp_nlproto, tpcb->tp_nlproto->nlp_pcbdetach);
818: ENDDEBUG
819:
820:
821:
822: (tpcb->tp_nlproto->nlp_pcbdetach)((struct inpcb *)so->so_pcb);
823: /* does an sofree(so) */
824:
825: IFDEBUG(D_CONN)
826: printf("after xxx_pcbdetach\n");
827: ENDDEBUG
828:
829: if( tpcb->tp_refp->tpr_state == REF_OPENING ) {
830: /* no connection existed here so no reference timer will be called */
831: IFDEBUG(D_CONN)
832: printf("SETTING ref %d, 0x%x to REF_FREE\n", tpcb->tp_lref,
833: tpcb->tp_refp - &tp_ref[0]);
834: ENDDEBUG
835:
836: tp_freeref(tpcb->tp_refp);
837: }
838:
839: if (tpcb->tp_Xsnd.sb_mb) {
840: printf("Unsent Xdata on detach; would panic");
841: sbflush(&tpcb->tp_Xsnd);
842: }
843: so->so_tpcb = (caddr_t)0;
844:
845: /*
846: * Get rid of the cluster mbuf allocated for performance measurements, if
847: * there is one. Note that tpcb->tp_perf_on says nothing about whether or
848: * not a cluster mbuf was allocated, so you have to check for a pointer
849: * to one (that is, we need the TP_PERF_MEASs around the following section
850: * of code, not the IFPERFs)
851: */
852: #ifdef TP_PERF_MEAS
853: if(tpcb->tp_p_mbuf) {
854: register struct mbuf *m = tpcb->tp_p_mbuf;
855: struct mbuf *n;
856: IFDEBUG(D_PERF_MEAS)
857: printf("freeing tp_p_meas 0x%x ", tpcb->tp_p_meas);
858: ENDDEBUG
859: do {
860: MFREE(m, n);
861: m = n;
862: } while (n);
863: tpcb->tp_p_meas = 0;
864: tpcb->tp_p_mbuf = 0;
865: }
866: #endif TP_PERF_MEAS
867:
868: IFDEBUG(D_CONN)
869: printf( "end of detach, NOT single, tpcb 0x%x\n", tpcb);
870: ENDDEBUG
871: /* free((caddr_t)tpcb, M_PCB); WHere to put this ? */
872: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.