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