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