|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*-
26: * Copyright (c) 1991, 1993
27: * The Regents of the University of California. All rights reserved.
28: *
29: * Redistribution and use in source and binary forms, with or without
30: * modification, are permitted provided that the following conditions
31: * are met:
32: * 1. Redistributions of source code must retain the above copyright
33: * notice, this list of conditions and the following disclaimer.
34: * 2. Redistributions in binary form must reproduce the above copyright
35: * notice, this list of conditions and the following disclaimer in the
36: * documentation and/or other materials provided with the distribution.
37: * 3. All advertising materials mentioning features or use of this software
38: * must display the following acknowledgement:
39: * This product includes software developed by the University of
40: * California, Berkeley and its contributors.
41: * 4. Neither the name of the University nor the names of its contributors
42: * may be used to endorse or promote products derived from this software
43: * without specific prior written permission.
44: *
45: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55: * SUCH DAMAGE.
56: *
57: * @(#)tp_pcb.c 8.1 (Berkeley) 6/10/93
58: */
59:
60: /***********************************************************
61: Copyright IBM Corporation 1987
62:
63: All Rights Reserved
64:
65: Permission to use, copy, modify, and distribute this software and its
66: documentation for any purpose and without fee is hereby granted,
67: provided that the above copyright notice appear in all copies and that
68: both that copyright notice and this permission notice appear in
69: supporting documentation, and that the name of IBM not be
70: used in advertising or publicity pertaining to distribution of the
71: software without specific, written prior permission.
72:
73: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
74: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
75: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
76: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
77: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
78: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
79: SOFTWARE.
80:
81: ******************************************************************/
82:
83: /*
84: * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
85: */
86: /*
87: * ARGO TP
88: *
89: * This is the initialization and cleanup stuff -
90: * for the tp machine in general as well as for the individual pcbs.
91: * tp_init() is called at system startup. tp_attach() and tp_getref() are
92: * called when a socket is created. tp_detach() and tp_freeref()
93: * are called during the closing stage and/or when the reference timer
94: * goes off.
95: * tp_soisdisconnecting() and tp_soisdisconnected() are tp-specific
96: * versions of soisconnect*
97: * and are called (obviously) during the closing phase.
98: *
99: */
100:
101: #include <sys/param.h>
102: #include <sys/systm.h>
103: #include <sys/mbuf.h>
104: #include <sys/socket.h>
105: #include <sys/socketvar.h>
106: #include <sys/domain.h>
107: #include <sys/protosw.h>
108: #include <sys/errno.h>
109: #include <sys/time.h>
110:
111: #include <netiso/argo_debug.h>
112: #include <netiso/tp_param.h>
113: #include <netiso/tp_timer.h>
114: #include <netiso/tp_ip.h>
115: #include <netiso/tp_stat.h>
116: #include <netiso/tp_pcb.h>
117: #include <netiso/tp_tpdu.h>
118: #include <netiso/tp_trace.h>
119: #include <netiso/tp_meas.h>
120: #include <netiso/tp_seq.h>
121: #include <netiso/tp_clnp.h>
122:
123: /* ticks are in units of:
124: * 500 nano-fortnights ;-) or
125: * 500 ms or
126: * 1/2 second
127: */
128:
129: struct tp_conn_param tp_conn_param[] = {
130: /* ISO_CLNS: TP4 CONNECTION LESS */
131: {
132: TP_NRETRANS, /* short p_Nretrans; */
133: 20, /* 10 sec */ /* short p_dr_ticks; */
134:
135: 20, /* 10 sec */ /* short p_cc_ticks; */
136: 20, /* 10 sec */ /* short p_dt_ticks; */
137:
138: 40, /* 20 sec */ /* short p_x_ticks; */
139: 80, /* 40 sec */ /* short p_cr_ticks;*/
140:
141: 240, /* 2 min */ /* short p_keepalive_ticks;*/
142: 10, /* 5 sec */ /* short p_sendack_ticks; */
143:
144: 600, /* 5 min */ /* short p_ref_ticks; */
145: 360, /* 3 min */ /* short p_inact_ticks; */
146:
147: (short) 100, /* short p_lcdtfract */
148: (short) TP_SOCKBUFSIZE, /* short p_winsize */
149: TP_TPDUSIZE, /* u_char p_tpdusize */
150:
151: TPACK_WINDOW, /* 4 bits p_ack_strat */
152: TPRX_USE_CW | TPRX_FASTSTART,
153: /* 4 bits p_rx_strat*/
154: TP_CLASS_4 | TP_CLASS_0,/* 5 bits p_class */
155: 1, /* 1 bit xtd format */
156: 1, /* 1 bit xpd service */
157: 1, /* 1 bit use_checksum */
158: 0, /* 1 bit use net xpd */
159: 0, /* 1 bit use rcc */
160: 0, /* 1 bit use efc */
161: 1, /* no disc indications */
162: 0, /* don't change params */
163: ISO_CLNS, /* p_netservice */
164: },
165: /* IN_CLNS: TP4 CONNECTION LESS */
166: {
167: TP_NRETRANS, /* short p_Nretrans; */
168: 20, /* 10 sec */ /* short p_dr_ticks; */
169:
170: 20, /* 10 sec */ /* short p_cc_ticks; */
171: 20, /* 10 sec */ /* short p_dt_ticks; */
172:
173: 40, /* 20 sec */ /* short p_x_ticks; */
174: 80, /* 40 sec */ /* short p_cr_ticks;*/
175:
176: 240, /* 2 min */ /* short p_keepalive_ticks;*/
177: 10, /* 5 sec */ /* short p_sendack_ticks; */
178:
179: 600, /* 5 min */ /* short p_ref_ticks; */
180: 360, /* 3 min */ /* short p_inact_ticks; */
181:
182: (short) 100, /* short p_lcdtfract */
183: (short) TP_SOCKBUFSIZE, /* short p_winsize */
184: TP_TPDUSIZE, /* u_char p_tpdusize */
185:
186: TPACK_WINDOW, /* 4 bits p_ack_strat */
187: TPRX_USE_CW | TPRX_FASTSTART,
188: /* 4 bits p_rx_strat*/
189: TP_CLASS_4, /* 5 bits p_class */
190: 1, /* 1 bit xtd format */
191: 1, /* 1 bit xpd service */
192: 1, /* 1 bit use_checksum */
193: 0, /* 1 bit use net xpd */
194: 0, /* 1 bit use rcc */
195: 0, /* 1 bit use efc */
196: 1, /* no disc indications */
197: 0, /* don't change params */
198: IN_CLNS, /* p_netservice */
199: },
200: /* ISO_CONS: TP0 CONNECTION MODE */
201: {
202: TP_NRETRANS, /* short p_Nretrans; */
203: 0, /* n/a */ /* short p_dr_ticks; */
204:
205: 40, /* 20 sec */ /* short p_cc_ticks; */
206: 0, /* n/a */ /* short p_dt_ticks; */
207:
208: 0, /* n/a */ /* short p_x_ticks; */
209: 360, /* 3 min */ /* short p_cr_ticks;*/
210:
211: 0, /* n/a */ /* short p_keepalive_ticks;*/
212: 0, /* n/a */ /* short p_sendack_ticks; */
213:
214: 600, /* for cr/cc to clear *//* short p_ref_ticks; */
215: 0, /* n/a */ /* short p_inact_ticks; */
216:
217: /* Use tp4 defaults just in case the user changes ONLY
218: * the class
219: */
220: (short) 100, /* short p_lcdtfract */
221: (short) TP0_SOCKBUFSIZE, /* short p_winsize */
222: TP0_TPDUSIZE, /* 8 bits p_tpdusize */
223:
224: 0, /* 4 bits p_ack_strat */
225: 0, /* 4 bits p_rx_strat*/
226: TP_CLASS_0, /* 5 bits p_class */
227: 0, /* 1 bit xtd format */
228: 0, /* 1 bit xpd service */
229: 0, /* 1 bit use_checksum */
230: 0, /* 1 bit use net xpd */
231: 0, /* 1 bit use rcc */
232: 0, /* 1 bit use efc */
233: 0, /* no disc indications */
234: 0, /* don't change params */
235: ISO_CONS, /* p_netservice */
236: },
237: /* ISO_COSNS: TP4 CONNECTION LESS SERVICE over CONSNS */
238: {
239: TP_NRETRANS, /* short p_Nretrans; */
240: 40, /* 20 sec */ /* short p_dr_ticks; */
241:
242: 40, /* 20 sec */ /* short p_cc_ticks; */
243: 80, /* 40 sec */ /* short p_dt_ticks; */
244:
245: 120, /* 1 min */ /* short p_x_ticks; */
246: 360, /* 3 min */ /* short p_cr_ticks;*/
247:
248: 360, /* 3 min */ /* short p_keepalive_ticks;*/
249: 20, /* 10 sec */ /* short p_sendack_ticks; */
250:
251: 600, /* 5 min */ /* short p_ref_ticks; */
252: 480, /* 4 min */ /* short p_inact_ticks; */
253:
254: (short) 100, /* short p_lcdtfract */
255: (short) TP0_SOCKBUFSIZE, /* short p_winsize */
256: TP0_TPDUSIZE, /* u_char p_tpdusize */
257:
258: TPACK_WINDOW, /* 4 bits p_ack_strat */
259: TPRX_USE_CW , /* No fast start */
260: /* 4 bits p_rx_strat*/
261: TP_CLASS_4 | TP_CLASS_0,/* 5 bits p_class */
262: 0, /* 1 bit xtd format */
263: 1, /* 1 bit xpd service */
264: 1, /* 1 bit use_checksum */
265: 0, /* 1 bit use net xpd */
266: 0, /* 1 bit use rcc */
267: 0, /* 1 bit use efc */
268: 0, /* no disc indications */
269: 0, /* don't change params */
270: ISO_COSNS, /* p_netservice */
271: },
272: };
273:
274: #if INET
275: int in_putnetaddr();
276: int in_getnetaddr();
277: int in_cmpnetaddr();
278: int in_putsufx();
279: int in_getsufx();
280: int in_recycle_tsuffix();
281: int tpip_mtu();
282: int in_pcbbind();
283: int in_pcbconnect();
284: int in_pcbdisconnect();
285: int in_pcbdetach();
286: int in_pcballoc();
287: int tpip_output();
288: int tpip_output_dg();
289: struct inpcb tp_inpcb;
290: #endif /* INET */
291: #if ISO
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 tpclnp_mtu();
299: int iso_pcbbind();
300: int iso_pcbconnect();
301: int iso_pcbdisconnect();
302: int iso_pcbdetach();
303: int iso_pcballoc();
304: int tpclnp_output();
305: int tpclnp_output_dg();
306: int iso_nlctloutput();
307: struct isopcb tp_isopcb;
308: #endif /* ISO */
309: #if TPCONS
310: int iso_putnetaddr();
311: int iso_getnetaddr();
312: int iso_cmpnetaddr();
313: int iso_putsufx();
314: int iso_getsufx();
315: int iso_recycle_tsuffix();
316: int iso_pcbbind();
317: int tpcons_pcbconnect();
318: int tpclnp_mtu();
319: int iso_pcbdisconnect();
320: int iso_pcbdetach();
321: int iso_pcballoc();
322: int tpcons_output();
323: struct isopcb tp_isopcb;
324: #endif /* TPCONS */
325:
326:
327: struct nl_protosw nl_protosw[] = {
328: /* ISO_CLNS */
329: #if ISO
330: { AF_ISO, iso_putnetaddr, iso_getnetaddr, iso_cmpnetaddr,
331: iso_putsufx, iso_getsufx,
332: iso_recycle_tsuffix,
333: tpclnp_mtu, iso_pcbbind, iso_pcbconnect,
334: iso_pcbdisconnect, iso_pcbdetach,
335: iso_pcballoc,
336: tpclnp_output, tpclnp_output_dg, iso_nlctloutput,
337: (caddr_t) &tp_isopcb,
338: },
339: #else
340: { 0 },
341: #endif /* ISO */
342: /* IN_CLNS */
343: #if INET
344: { AF_INET, in_putnetaddr, in_getnetaddr, in_cmpnetaddr,
345: in_putsufx, in_getsufx,
346: in_recycle_tsuffix,
347: tpip_mtu, in_pcbbind, in_pcbconnect,
348: in_pcbdisconnect, in_pcbdetach,
349: in_pcballoc,
350: tpip_output, tpip_output_dg, /* nl_ctloutput */ NULL,
351: (caddr_t) &tp_inpcb,
352: },
353: #else
354: { 0 },
355: #endif /* INET */
356: /* ISO_CONS */
357: #if defined(ISO) && defined(TPCONS)
358: { AF_ISO, iso_putnetaddr, iso_getnetaddr, iso_cmpnetaddr,
359: iso_putsufx, iso_getsufx,
360: iso_recycle_tsuffix,
361: tpclnp_mtu, iso_pcbbind, tpcons_pcbconnect,
362: iso_pcbdisconnect, iso_pcbdetach,
363: iso_pcballoc,
364: tpcons_output, tpcons_output, iso_nlctloutput,
365: (caddr_t) &tp_isopcb,
366: },
367: #else
368: { 0 },
369: #endif /* ISO_CONS */
370: /* End of protosw marker */
371: { 0 }
372: };
373:
374: u_long tp_sendspace = 1024 * 4;
375: u_long tp_recvspace = 1024 * 4;
376:
377: /*
378: * NAME: tp_init()
379: *
380: * CALLED FROM:
381: * autoconf through the protosw structure
382: *
383: * FUNCTION:
384: * initialize tp machine
385: *
386: * RETURNS: Nada
387: *
388: * SIDE EFFECTS:
389: *
390: * NOTES:
391: */
392: int
393: tp_init()
394: {
395: static int init_done=0;
396: void tp_timerinit();
397:
398: if (init_done++)
399: return 0;
400:
401:
402: /* FOR INET */
403: tp_inpcb.inp_next = tp_inpcb.inp_prev = &tp_inpcb;
404: /* FOR ISO */
405: tp_isopcb.isop_next = tp_isopcb.isop_prev = &tp_isopcb;
406:
407: tp_start_win = 2;
408:
409: tp_timerinit();
410: bzero((caddr_t)&tp_stat, sizeof(struct tp_stat));
411: return 0;
412: }
413:
414: /*
415: * NAME: tp_soisdisconnecting()
416: *
417: * CALLED FROM:
418: * tp.trans
419: *
420: * FUNCTION and ARGUMENTS:
421: * Set state of the socket (so) to reflect that fact that we're disconnectING
422: *
423: * RETURNS: Nada
424: *
425: * SIDE EFFECTS:
426: *
427: * NOTES:
428: * This differs from the regular soisdisconnecting() in that the latter
429: * also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags.
430: * We don't want to set those flags because those flags will cause
431: * a SIGPIPE to be delivered in sosend() and we don't like that.
432: * If anyone else is sleeping on this socket, wake 'em up.
433: */
434: void
435: tp_soisdisconnecting(so)
436: register struct socket *so;
437: {
438: soisdisconnecting(so);
439: so->so_state &= ~SS_CANTSENDMORE;
440: IFPERF(sototpcb(so))
441: register struct tp_pcb *tpcb = sototpcb(so);
442: u_int fsufx, lsufx;
443:
444: bcopy ((caddr_t)tpcb->tp_fsuffix, (caddr_t)&fsufx, sizeof(u_int) );
445: bcopy ((caddr_t)tpcb->tp_lsuffix, (caddr_t)&lsufx, sizeof(u_int) );
446:
447: tpmeas(tpcb->tp_lref, TPtime_close, &time, fsufx, lsufx, tpcb->tp_fref);
448: tpcb->tp_perf_on = 0; /* turn perf off */
449: ENDPERF
450: }
451:
452:
453: /*
454: * NAME: tp_soisdisconnected()
455: *
456: * CALLED FROM:
457: * tp.trans
458: *
459: * FUNCTION and ARGUMENTS:
460: * Set state of the socket (so) to reflect that fact that we're disconnectED
461: * Set the state of the reference structure to closed, and
462: * recycle the suffix.
463: * Start a reference timer.
464: *
465: * RETURNS: Nada
466: *
467: * SIDE EFFECTS:
468: *
469: * NOTES:
470: * This differs from the regular soisdisconnected() in that the latter
471: * also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags.
472: * We don't want to set those flags because those flags will cause
473: * a SIGPIPE to be delivered in sosend() and we don't like that.
474: * If anyone else is sleeping on this socket, wake 'em up.
475: */
476: void
477: tp_soisdisconnected(tpcb)
478: register struct tp_pcb *tpcb;
479: {
480: register struct socket *so = tpcb->tp_sock;
481:
482: soisdisconnecting(so);
483: so->so_state &= ~SS_CANTSENDMORE;
484: IFPERF(tpcb)
485: register struct tp_pcb *ttpcb = sototpcb(so);
486: u_int fsufx, lsufx;
487:
488: /* CHOKE */
489: bcopy ((caddr_t)ttpcb->tp_fsuffix, (caddr_t)&fsufx, sizeof(u_int) );
490: bcopy ((caddr_t)ttpcb->tp_lsuffix, (caddr_t)&lsufx, sizeof(u_int) );
491:
492: tpmeas(ttpcb->tp_lref, TPtime_close,
493: &time, &lsufx, &fsufx, ttpcb->tp_fref);
494: tpcb->tp_perf_on = 0; /* turn perf off */
495: ENDPERF
496:
497: tpcb->tp_refstate = REF_FROZEN;
498: tp_recycle_tsuffix(tpcb);
499: tp_etimeout(tpcb, TM_reference, (int)tpcb->tp_refer_ticks);
500: }
501:
502: /*
503: * NAME: tp_freeref()
504: *
505: * CALLED FROM:
506: * tp.trans when the reference timer goes off, and
507: * from tp_attach() and tp_detach() when a tpcb is partially set up but not
508: * set up enough to have a ref timer set for it, and it's discarded
509: * due to some sort of error or an early close()
510: *
511: * FUNCTION and ARGUMENTS:
512: * Frees the reference represented by (r) for re-use.
513: *
514: * RETURNS: Nothing
515: *
516: * SIDE EFFECTS:
517: *
518: * NOTES: better be called at clock priority !!!!!
519: */
520: void
521: tp_freeref(n)
522: RefNum n;
523: {
524: register struct tp_ref *r = tp_ref + n;
525: register struct tp_pcb *tpcb;
526:
527: tpcb = r->tpr_pcb;
528: IFDEBUG(D_TIMER)
529: printf("tp_freeref called for ref %d pcb %x maxrefopen %d\n",
530: n, tpcb, tp_refinfo.tpr_maxopen);
531: ENDDEBUG
532: IFTRACE(D_TIMER)
533: tptrace(TPPTmisc, "tp_freeref ref maxrefopen pcb",
534: n, tp_refinfo.tpr_maxopen, tpcb, 0);
535: ENDTRACE
536: if (tpcb == 0)
537: return;
538: IFDEBUG(D_CONN)
539: printf("tp_freeref: CLEARING tpr_pcb 0x%x\n", tpcb);
540: ENDDEBUG
541: r->tpr_pcb = (struct tp_pcb *)0;
542: tpcb->tp_refstate = REF_FREE;
543:
544: for (r = tp_ref + tp_refinfo.tpr_maxopen; r > tp_ref; r--)
545: if (r->tpr_pcb)
546: break;
547: tp_refinfo.tpr_maxopen = r - tp_ref;
548: tp_refinfo.tpr_numopen--;
549:
550: IFDEBUG(D_TIMER)
551: printf("tp_freeref ends w/ maxrefopen %d\n", tp_refinfo.tpr_maxopen);
552: ENDDEBUG
553: }
554:
555: /*
556: * NAME: tp_getref()
557: *
558: * CALLED FROM:
559: * tp_attach()
560: *
561: * FUNCTION and ARGUMENTS:
562: * obtains the next free reference and allocates the appropriate
563: * ref structure, links that structure to (tpcb)
564: *
565: * RETURN VALUE:
566: * a reference number
567: * or TP_ENOREF
568: *
569: * SIDE EFFECTS:
570: *
571: * NOTES:
572: */
573: u_long
574: tp_getref(tpcb)
575: register struct tp_pcb *tpcb;
576: {
577: register struct tp_ref *r, *rlim;
578: register int i;
579: caddr_t obase;
580: unsigned size;
581:
582: if (++tp_refinfo.tpr_numopen < tp_refinfo.tpr_size)
583: for (r = tp_refinfo.tpr_base, rlim = r + tp_refinfo.tpr_size;
584: ++r < rlim; ) /* tp_ref[0] is never used */
585: if (r->tpr_pcb == 0)
586: goto got_one;
587: /* else have to allocate more space */
588:
589: obase = (caddr_t)tp_refinfo.tpr_base;
590: size = tp_refinfo.tpr_size * sizeof(struct tp_ref);
591: // r = (struct tp_ref *) malloc(size + size, M_PCB, M_NOWAIT);
592: MALLOC(r, struct tp_ref *, size + size, M_PCB, M_NOWAIT);
593: if (r == 0)
594: return (--tp_refinfo.tpr_numopen, TP_ENOREF);
595: tp_refinfo.tpr_base = tp_ref = r;
596: tp_refinfo.tpr_size *= 2;
597: bcopy(obase, (caddr_t)r, size);
598: free(obase, M_PCB);
599: r = (struct tp_ref *)(size + (caddr_t)r);
600: bzero((caddr_t)r, size);
601:
602: got_one:
603: r->tpr_pcb = tpcb;
604: tpcb->tp_refstate = REF_OPENING;
605: i = r - tp_refinfo.tpr_base;
606: if (tp_refinfo.tpr_maxopen < i)
607: tp_refinfo.tpr_maxopen = i;
608: return (u_long)i;
609: }
610:
611: /*
612: * NAME: tp_set_npcb()
613: *
614: * CALLED FROM:
615: * tp_attach(), tp_route_to()
616: *
617: * FUNCTION and ARGUMENTS:
618: * given a tpcb, allocate an appropriate lower-lever npcb, freeing
619: * any old ones that might need re-assigning.
620: */
621: tp_set_npcb(tpcb)
622: register struct tp_pcb *tpcb;
623: {
624: register struct socket *so = tpcb->tp_sock;
625: int error;
626:
627: if (tpcb->tp_nlproto && tpcb->tp_npcb) {
628: short so_state = so->so_state;
629: so->so_state &= ~SS_NOFDREF;
630: tpcb->tp_nlproto->nlp_pcbdetach(tpcb->tp_npcb);
631: so->so_state = so_state;
632: }
633: tpcb->tp_nlproto = &nl_protosw[tpcb->tp_netservice];
634: /* xx_pcballoc sets so_pcb */
635: error = tpcb->tp_nlproto->nlp_pcballoc(so, tpcb->tp_nlproto->nlp_pcblist);
636: tpcb->tp_npcb = so->so_pcb;
637: so->so_pcb = (caddr_t)tpcb;
638: return (error);
639: }
640: /*
641: * NAME: tp_attach()
642: *
643: * CALLED FROM:
644: * tp_usrreq, PRU_ATTACH
645: *
646: * FUNCTION and ARGUMENTS:
647: * given a socket (so) and a protocol family (dom), allocate a tpcb
648: * and ref structure, initialize everything in the structures that
649: * needs to be initialized.
650: *
651: * RETURN VALUE:
652: * 0 ok
653: * EINVAL if DEBUG(X) in is on and a disaster has occurred
654: * ENOPROTOOPT if TP hasn't been configured or if the
655: * socket wasn't created with tp as its protocol
656: * EISCONN if this socket is already part of a connection
657: * ETOOMANYREFS if ran out of tp reference numbers.
658: * E* whatever error is returned from soreserve()
659: * for from the network-layer pcb allocation routine
660: *
661: * SIDE EFFECTS:
662: *
663: * NOTES:
664: */
665: tp_attach(so, protocol)
666: struct socket *so;
667: int protocol;
668: {
669: register struct tp_pcb *tpcb;
670: int error = 0;
671: int dom = so->so_proto->pr_domain->dom_family;
672: u_long lref;
673: extern struct tp_conn_param tp_conn_param[];
674:
675: IFDEBUG(D_CONN)
676: printf("tp_attach:dom 0x%x so 0x%x ", dom, so);
677: ENDDEBUG
678: IFTRACE(D_CONN)
679: tptrace(TPPTmisc, "tp_attach:dom so", dom, so, 0, 0);
680: ENDTRACE
681:
682: if (so->so_pcb != NULL) {
683: return EISCONN; /* socket already part of a connection*/
684: }
685:
686: if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0)
687: error = soreserve(so, tp_sendspace, tp_recvspace);
688: /* later an ioctl will allow reallocation IF still in closed state */
689:
690: if (error)
691: goto bad2;
692:
693: MALLOC(tpcb, struct tp_pcb *, sizeof(*tpcb), M_PCB, M_NOWAIT);
694: if (tpcb == NULL) {
695: error = ENOBUFS;
696: goto bad2;
697: }
698: bzero( (caddr_t)tpcb, sizeof (struct tp_pcb) );
699:
700: if ( ((lref = tp_getref(tpcb)) & TP_ENOREF) != 0 ) {
701: error = ETOOMANYREFS;
702: goto bad3;
703: }
704: tpcb->tp_lref = lref;
705: tpcb->tp_sock = so;
706: tpcb->tp_domain = dom;
707: tpcb->tp_rhiwat = so->so_rcv.sb_hiwat;
708: /* tpcb->tp_proto = protocol; someday maybe? */
709: if (protocol && protocol<ISOPROTO_TP4) {
710: tpcb->tp_netservice = ISO_CONS;
711: tpcb->tp_snduna = (SeqNum) -1;/* kludge so the pseudo-ack from the CR/CC
712: * will generate correct fake-ack values
713: */
714: } else {
715: tpcb->tp_netservice = (dom== AF_INET)?IN_CLNS:ISO_CLNS;
716: /* the default */
717: }
718: tpcb->_tp_param = tp_conn_param[tpcb->tp_netservice];
719:
720: tpcb->tp_state = TP_CLOSED;
721: tpcb->tp_vers = TP_VERSION;
722: tpcb->tp_notdetached = 1;
723:
724: /* Spec says default is 128 octets,
725: * that is, if the tpdusize argument never appears, use 128.
726: * As the initiator, we will always "propose" the 2048
727: * size, that is, we will put this argument in the CR
728: * always, but accept what the other side sends on the CC.
729: * If the initiator sends us something larger on a CR,
730: * we'll respond w/ this.
731: * Our maximum is 4096. See tp_chksum.c comments.
732: */
733: tpcb->tp_cong_win =
734: tpcb->tp_l_tpdusize = 1 << tpcb->tp_tpdusize;
735:
736: tpcb->tp_seqmask = TP_NML_FMT_MASK;
737: tpcb->tp_seqbit = TP_NML_FMT_BIT;
738: tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1;
739:
740: /* attach to a network-layer protoswitch */
741: if ( error = tp_set_npcb(tpcb))
742: goto bad4;
743: ASSERT( tpcb->tp_nlproto->nlp_afamily == tpcb->tp_domain);
744:
745: /* nothing to do for iso case */
746: if( dom == AF_INET )
747: sotoinpcb(so)->inp_ppcb = (caddr_t) tpcb;
748:
749: return 0;
750:
751: bad4:
752: IFDEBUG(D_CONN)
753: printf("BAD4 in tp_attach, so 0x%x\n", so);
754: ENDDEBUG
755: tp_freeref(tpcb->tp_lref);
756:
757: bad3:
758: IFDEBUG(D_CONN)
759: printf("BAD3 in tp_attach, so 0x%x\n", so);
760: ENDDEBUG
761:
762: free((caddr_t)tpcb, M_PCB); /* never a cluster */
763:
764: bad2:
765: IFDEBUG(D_CONN)
766: printf("BAD2 in tp_attach, so 0x%x\n", so);
767: ENDDEBUG
768: so->so_pcb = 0;
769:
770: /*bad:*/
771: IFDEBUG(D_CONN)
772: printf("BAD in tp_attach, so 0x%x\n", so);
773: ENDDEBUG
774: return error;
775: }
776:
777: /*
778: * NAME: tp_detach()
779: *
780: * CALLED FROM:
781: * tp.trans, on behalf of a user close request
782: * and when the reference timer goes off
783: * (if the disconnect was initiated by the protocol entity
784: * rather than by the user)
785: *
786: * FUNCTION and ARGUMENTS:
787: * remove the tpcb structure from the list of active or
788: * partially active connections, recycle all the mbufs
789: * associated with the pcb, ref structure, sockbufs, etc.
790: * Only free the ref structure if you know that a ref timer
791: * wasn't set for this tpcb.
792: *
793: * RETURNS: Nada
794: *
795: * SIDE EFFECTS:
796: *
797: * NOTES:
798: * tp_soisdisconnected() was already when this is called
799: */
800: void
801: tp_detach(tpcb)
802: register struct tp_pcb *tpcb;
803: {
804: void tp_freeref(), tp_rsyflush();
805: register struct socket *so = tpcb->tp_sock;
806:
807: IFDEBUG(D_CONN)
808: printf("tp_detach(tpcb 0x%x, so 0x%x)\n",
809: tpcb,so);
810: ENDDEBUG
811: IFTRACE(D_CONN)
812: tptraceTPCB(TPPTmisc, "tp_detach tpcb so lsufx",
813: tpcb, so, *(u_short *)(tpcb->tp_lsuffix), 0);
814: ENDTRACE
815:
816: IFDEBUG(D_CONN)
817: printf("so_snd at 0x%x so_rcv at 0x%x\n", &so->so_snd, &so->so_rcv);
818: dump_mbuf(so->so_snd.sb_mb, "so_snd at detach ");
819: printf("about to call LL detach, nlproto 0x%x, nl_detach 0x%x\n",
820: tpcb->tp_nlproto, tpcb->tp_nlproto->nlp_pcbdetach);
821: ENDDEBUG
822:
823: if (tpcb->tp_Xsnd.sb_mb) {
824: printf("Unsent Xdata on detach; would panic");
825: sbflush(&tpcb->tp_Xsnd);
826: }
827: if (tpcb->tp_ucddata)
828: m_freem(tpcb->tp_ucddata);
829:
830: IFDEBUG(D_CONN)
831: printf("reassembly info cnt %d rsyq 0x%x\n",
832: tpcb->tp_rsycnt, tpcb->tp_rsyq);
833: ENDDEBUG
834: if (tpcb->tp_rsyq)
835: tp_rsyflush(tpcb);
836:
837: if (tpcb->tp_next) {
838: remque(tpcb);
839: tpcb->tp_next = tpcb->tp_prev = 0;
840: }
841: tpcb->tp_notdetached = 0;
842:
843: IFDEBUG(D_CONN)
844: printf("calling (...nlproto->...)(0x%x, so 0x%x)\n",
845: tpcb->tp_npcb, so);
846: printf("so 0x%x so_head 0x%x, qlen %d q0len %d qlimit %d\n",
847: so, so->so_head,
848: so->so_q0len, so->so_qlen, so->so_qlimit);
849: ENDDEBUG
850:
851: (tpcb->tp_nlproto->nlp_pcbdetach)(tpcb->tp_npcb);
852: /* does an so->so_pcb = 0; sofree(so) */
853:
854: IFDEBUG(D_CONN)
855: printf("after xxx_pcbdetach\n");
856: ENDDEBUG
857:
858: if (tpcb->tp_state == TP_LISTENING) {
859: register struct tp_pcb **tt;
860: for (tt = &tp_listeners; *tt; tt = &((*tt)->tp_nextlisten))
861: if (*tt == tpcb)
862: break;
863: if (*tt)
864: *tt = tpcb->tp_nextlisten;
865: else
866: printf("tp_detach from listen: should panic\n");
867: }
868: if (tpcb->tp_refstate == REF_OPENING ) {
869: /* no connection existed here so no reference timer will be called */
870: IFDEBUG(D_CONN)
871: printf("SETTING ref %d to REF_FREE\n", tpcb->tp_lref);
872: ENDDEBUG
873:
874: tp_freeref(tpcb->tp_lref);
875: }
876: #ifdef TP_PERF_MEAS
877: /*
878: * Get rid of the cluster mbuf allocated for performance measurements, if
879: * there is one. Note that tpcb->tp_perf_on says nothing about whether or
880: * not a cluster mbuf was allocated, so you have to check for a pointer
881: * to one (that is, we need the TP_PERF_MEASs around the following section
882: * of code, not the IFPERFs)
883: */
884: if (tpcb->tp_p_mbuf) {
885: register struct mbuf *m = tpcb->tp_p_mbuf;
886: struct mbuf *n;
887: IFDEBUG(D_PERF_MEAS)
888: printf("freeing tp_p_meas 0x%x ", tpcb->tp_p_meas);
889: ENDDEBUG
890: do {
891: MFREE(m, n);
892: m = n;
893: } while (n);
894: tpcb->tp_p_meas = 0;
895: tpcb->tp_p_mbuf = 0;
896: }
897: #endif /* TP_PERF_MEAS */
898:
899: IFDEBUG(D_CONN)
900: printf( "end of detach, NOT single, tpcb 0x%x\n", tpcb);
901: ENDDEBUG
902: /* free((caddr_t)tpcb, M_PCB); WHere to put this ? */
903: }
904:
905: struct que {
906: struct tp_pcb *next;
907: struct tp_pcb *prev;
908: } tp_bound_pcbs =
909: {(struct tp_pcb *)&tp_bound_pcbs, (struct tp_pcb *)&tp_bound_pcbs};
910:
911: u_short tp_unique;
912:
913: tp_tselinuse(tlen, tsel, siso, reuseaddr)
914: caddr_t tsel;
915: register struct sockaddr_iso *siso;
916: {
917: struct tp_pcb *b = tp_bound_pcbs.next, *l = tp_listeners;
918: register struct tp_pcb *t;
919:
920: for (;;) {
921: if (b != (struct tp_pcb *)&tp_bound_pcbs) {
922: t = b; b = t->tp_next;
923: } else if (l) {
924: t = l; l = t->tp_nextlisten;
925: } else
926: break;
927: if (tlen == t->tp_lsuffixlen && bcmp(tsel, t->tp_lsuffix, tlen) == 0) {
928: if (t->tp_flags & TPF_GENERAL_ADDR) {
929: if (siso == 0 || reuseaddr == 0)
930: return 1;
931: } else if (siso) {
932: if (siso->siso_family == t->tp_domain &&
933: t->tp_nlproto->nlp_cmpnetaddr(t->tp_npcb, siso, TP_LOCAL))
934: return 1;
935: } else if (reuseaddr == 0)
936: return 1;
937: }
938: }
939: return 0;
940:
941: }
942:
943:
944: tp_pcbbind(tpcb, nam)
945: register struct tp_pcb *tpcb;
946: register struct mbuf *nam;
947: {
948: register struct sockaddr_iso *siso = 0;
949: int tlen = 0, wrapped = 0;
950: caddr_t tsel;
951: u_short tutil;
952:
953: if (tpcb->tp_state != TP_CLOSED)
954: return (EINVAL);
955: if (nam) {
956: siso = mtod(nam, struct sockaddr_iso *);
957: switch (siso->siso_family) {
958: default:
959: return (EAFNOSUPPORT);
960: #if ISO
961: case AF_ISO:
962: tlen = siso->siso_tlen;
963: tsel = TSEL(siso);
964: if (siso->siso_nlen == 0)
965: siso = 0;
966: break;
967: #endif
968: #if INET
969: case AF_INET:
970: tsel = (caddr_t)&tutil;
971: if (tutil = ((struct sockaddr_in *)siso)->sin_port) {
972: tlen = 2;
973: }
974: if (((struct sockaddr_in *)siso)->sin_addr.s_addr == 0)
975: siso = 0;
976: }
977: #endif
978: }
979: if (tpcb->tp_lsuffixlen == 0) {
980: if (tlen) {
981: if (tp_tselinuse(tlen, tsel, siso,
982: tpcb->tp_sock->so_options & SO_REUSEADDR))
983: return (EINVAL);
984: } else {
985: for (tsel = (caddr_t)&tutil, tlen = 2;;){
986: if (tp_unique++ < ISO_PORT_RESERVED ||
987: tp_unique > ISO_PORT_USERRESERVED) {
988: if (wrapped++)
989: return ESRCH;
990: tp_unique = ISO_PORT_RESERVED;
991: }
992: tutil = htons(tp_unique);
993: if (tp_tselinuse(tlen, tsel, siso, 0) == 0)
994: break;
995: }
996: if (siso) switch (siso->siso_family) {
997: #if ISO
998: case AF_ISO:
999: bcopy(tsel, TSEL(siso), tlen);
1000: siso->siso_tlen = tlen;
1001: break;
1002: #endif
1003: #if INET
1004: case AF_INET:
1005: ((struct sockaddr_in *)siso)->sin_port = tutil;
1006: #endif
1007: }
1008: }
1009: bcopy(tsel, tpcb->tp_lsuffix, (tpcb->tp_lsuffixlen = tlen));
1010: insque(tpcb, &tp_bound_pcbs);
1011: } else {
1012: if (tlen || siso == 0)
1013: return (EINVAL);
1014: }
1015: if (siso == 0) {
1016: tpcb->tp_flags |= TPF_GENERAL_ADDR;
1017: return (0);
1018: }
1019: return tpcb->tp_nlproto->nlp_pcbbind(tpcb->tp_npcb, nam);
1020: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.