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