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