|
|
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: * @(#)if_cons.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: * cons.c - Connection Oriented Network Service:
88: * including support for a) user transport-level service,
89: * b) COSNS below CLNP, and c) CONS below TP.
90: */
91:
92: #if TPCONS
93: #ifdef _KERNEL
94: #ifdef ARGO_DEBUG
95: #define Static
96: unsigned LAST_CALL_PCB;
97: #else /* ARGO_DEBUG */
98: #define Static static
99: #endif /* ARGO_DEBUG */
100:
101: #ifndef SOCK_STREAM
102: #include <sys/param.h>
103: #include <sys/systm.h>
104: #include <sys/mbuf.h>
105: #include <sys/protosw.h>
106: #include <sys/socket.h>
107: #include <sys/socketvar.h>
108: #include <sys/errno.h>
109: #include <sys/ioctl.h>
110: #include <sys/tsleep.h>
111:
112: #include <net/if.h>
113: #include <net/netisr.h>
114: #include <net/route.h>
115:
116: #include <netiso/iso_errno.h>
117: #include <netiso/argo_debug.h>
118: #include <netiso/tp_trace.h>
119: #include <netiso/iso.h>
120: #include <netiso/cons.h>
121: #include <netiso/iso_pcb.h>
122:
123: #include <netccitt/x25.h>
124: #include <netccitt/pk.h>
125: #include <netccitt/pk_var.h>
126: #endif
127:
128: #ifdef ARGO_DEBUG
129: #define MT_XCONN 0x50
130: #define MT_XCLOSE 0x51
131: #define MT_XCONFIRM 0x52
132: #define MT_XDATA 0x53
133: #define MT_XHEADER 0x54
134: #else
135: #define MT_XCONN MT_DATA
136: #define MT_XCLOSE MT_DATA
137: #define MT_XCONFIRM MT_DATA
138: #define MT_XDATA MT_DATA
139: #define MT_XHEADER MT_HEADER
140: #endif /* ARGO_DEBUG */
141:
142: #define DONTCLEAR -1
143:
144: /*********************************************************************
145: * cons.c - CONS interface to the x.25 layer
146: *
147: * TODO: figure out what resources we might run out of besides mbufs.
148: * If we run out of any of them (including mbufs) close and recycle
149: * lru x% of the connections, for some parameter x.
150: *
151: * There are 2 interfaces from above:
152: * 1) from TP0:
153: * cons CO network service
154: * TP associates a transport connection with a network connection.
155: * cons_output( isop, m, len, isdgm==0 )
156: * co_flags == 0
157: * 2) from TP4:
158: * It's a datagram service, like clnp is. - even though it calls
159: * cons_output( isop, m, len, isdgm==1 )
160: * it eventually goes through
161: * cosns_output(ifp, m, dst).
162: * TP4 permits multiplexing (reuse, possibly simultaneously) of the
163: * network connections.
164: * This means that many sockets (many tpcbs) may be associated with
165: * this pklcd, hence cannot have a back ptr from pklcd to a tpcb.
166: * co_flags & CONSF_DGM
167: * co_socket is null since there may be many sockets that use this pklcd.
168: *
169: NOTE:
170: streams would really be nice. sigh.
171: NOTE:
172: PVCs could be handled by config-ing a cons with an address and with the
173: IFF_POINTTOPOINT flag on. This code would then have to skip the
174: connection setup stuff for pt-to-pt links.
175:
176:
177: *********************************************************************/
178:
179:
180: #define CONS_IFQMAXLEN 5
181:
182:
183: /* protosw pointers for getting to higher layer */
184: Static struct protosw *CLNP_proto;
185: Static struct protosw *TP_proto;
186: Static struct protosw *X25_proto;
187: Static int issue_clear_req();
188:
189: #ifndef PHASEONE
190: extern struct ifaddr *ifa_ifwithnet();
191: #endif /* PHASEONE */
192:
193: extern struct ifaddr *ifa_ifwithaddr();
194:
195: extern struct isopcb tp_isopcb; /* chain of all TP pcbs */
196:
197:
198: Static int parse_facil(), NSAPtoDTE(), make_partial_x25_packet();
199: Static int FACILtoNSAP(), DTEtoNSAP();
200: Static struct pklcd *cons_chan_to_pcb();
201:
202: #define HIGH_NIBBLE 1
203: #define LOW_NIBBLE 0
204:
205: /*
206: * NAME: nibble_copy()
207: * FUNCTION and ARGUMENTS:
208: * copies (len) nibbles from (src_octet), high or low nibble
209: * to (dst_octet), high or low nibble,
210: * src_nibble & dst_nibble should be:
211: * HIGH_NIBBLE (1) if leftmost 4 bits/ most significant nibble
212: * LOW_NIBBLE (0) if rightmost 4 bits/ least significant nibble
213: * RETURNS: VOID
214: */
215: void
216: nibble_copy(src_octet, src_nibble, dst_octet, dst_nibble, len)
217: register char *src_octet;
218: register char *dst_octet;
219: register unsigned src_nibble;
220: register unsigned dst_nibble;
221: int len;
222: {
223:
224: register i;
225: register unsigned dshift, sshift;
226:
227: IFDEBUG(D_CADDR)
228: printf("nibble_copy ( 0x%x, 0x%x, 0x%x, 0x%x 0x%x)\n",
229: src_octet, src_nibble, dst_octet, dst_nibble, len);
230: ENDDEBUG
231: #define SHIFT 0x4
232:
233: dshift = dst_nibble << 2;
234: sshift = src_nibble << 2;
235:
236: for (i=0; i<len; i++) {
237: /* clear dst_nibble */
238: *dst_octet &= ~(0xf<< dshift);
239:
240: /* set dst nibble */
241: *dst_octet |= ( 0xf & (*src_octet >> sshift))<< dshift;
242:
243: dshift ^= SHIFT;
244: sshift ^= SHIFT;
245: src_nibble = 1-src_nibble;
246: dst_nibble = 1-dst_nibble;
247: src_octet += src_nibble;
248: dst_octet += dst_nibble;
249: }
250: IFDEBUG(D_CADDR)
251: printf("nibble_copy DONE\n");
252: ENDDEBUG
253: }
254:
255: /*
256: * NAME: nibble_match()
257: * FUNCTION and ARGUMENTS:
258: * compares src_octet/src_nibble and dst_octet/dst_nibble for len nibbles.
259: * RETURNS: 0 if they differ, 1 if they are the same.
260: */
261: int
262: nibble_match( src_octet, src_nibble, dst_octet, dst_nibble, len)
263: register char *src_octet;
264: register char *dst_octet;
265: register unsigned src_nibble;
266: register unsigned dst_nibble;
267: int len;
268: {
269:
270: register i;
271: register unsigned dshift, sshift;
272: u_char nibble_a, nibble_b;
273:
274: IFDEBUG(D_CADDR)
275: printf("nibble_match ( 0x%x, 0x%x, 0x%x, 0x%x 0x%x)\n",
276: src_octet, src_nibble, dst_octet, dst_nibble, len);
277: ENDDEBUG
278: #define SHIFT 0x4
279:
280: dshift = dst_nibble << 2;
281: sshift = src_nibble << 2;
282:
283: for (i=0; i<len; i++) {
284: nibble_b = ((*dst_octet)>>dshift) & 0xf;
285: nibble_a = ( 0xf & (*src_octet >> sshift));
286: if (nibble_b != nibble_a)
287: return 0;
288:
289: dshift ^= SHIFT;
290: sshift ^= SHIFT;
291: src_nibble = 1-src_nibble;
292: dst_nibble = 1-dst_nibble;
293: src_octet += src_nibble;
294: dst_octet += dst_nibble;
295: }
296: IFDEBUG(D_CADDR)
297: printf("nibble_match DONE\n");
298: ENDDEBUG
299: return 1;
300: }
301:
302: /*
303: **************************** NET PROTOCOL cons ***************************
304: */
305: /*
306: * NAME: cons_init()
307: * CALLED FROM:
308: * autoconf
309: * FUNCTION:
310: * initialize the protocol
311: */
312: cons_init()
313: {
314: int tp_incoming(), clnp_incoming();
315:
316:
317: CLNP_proto = pffindproto(AF_ISO, ISOPROTO_CLNP, SOCK_DGRAM);
318: X25_proto = pffindproto(AF_ISO, ISOPROTO_X25, SOCK_STREAM);
319: TP_proto = pffindproto(AF_ISO, ISOPROTO_TP0, SOCK_SEQPACKET);
320: IFDEBUG(D_CCONS)
321: printf("cons_init end : cnlp_proto 0x%x cons proto 0x%x tp proto 0x%x\n",
322: CLNP_proto, X25_proto, TP_proto);
323: ENDDEBUG
324: #ifdef notdef
325: pk_protolisten(0x81, 0, clnp_incoming);
326: pk_protolisten(0x82, 0, esis_incoming);
327: pk_protolisten(0x84, 0, tp8878_A_incoming);
328: pk_protolisten(0, 0, tp_incoming);
329: #endif
330: }
331:
332: tp_incoming(lcp, m)
333: struct pklcd *lcp;
334: register struct mbuf *m;
335: {
336: register struct isopcb *isop;
337: int cons_tpinput();
338:
339: if (iso_pcballoc((struct socket *)0, &tp_isopcb)) {
340: pk_close(lcp);
341: return;
342: }
343: isop = tp_isopcb.isop_next;
344: lcp->lcd_upper = cons_tpinput;
345: lcp->lcd_upnext = (caddr_t)isop;
346: lcp->lcd_send(lcp); /* Confirms call */
347: isop->isop_chan = (caddr_t)lcp;
348: isop->isop_laddr = &isop->isop_sladdr;
349: isop->isop_faddr = &isop->isop_sfaddr;
350: DTEtoNSAP(isop->isop_laddr, &lcp->lcd_laddr);
351: DTEtoNSAP(isop->isop_faddr, &lcp->lcd_faddr);
352: parse_facil(lcp, isop, &(mtod(m, struct x25_packet *)->packet_data),
353: m->m_pkthdr.len - PKHEADERLN);
354: }
355:
356: cons_tpinput(lcp, m0)
357: struct mbuf *m0;
358: struct pklcd *lcp;
359: {
360: register struct isopcb *isop = (struct isopcb *)lcp->lcd_upnext;
361: register struct x25_packet *xp;
362: int cmd, ptype = CLEAR;
363:
364: if (isop == 0)
365: return;
366: if (m0 == 0)
367: goto dead;
368: switch(m0->m_type) {
369: case MT_DATA:
370: case MT_OOBDATA:
371: tpcons_input(m0, isop->isop_faddr, isop->isop_laddr, (caddr_t)lcp);
372: return;
373:
374: case MT_CONTROL:
375: switch (ptype = pk_decode(mtod(m0, struct x25_packet *))) {
376:
377: case RR:
378: cmd = PRC_CONS_SEND_DONE;
379: break;
380:
381: case CALL_ACCEPTED:
382: if (lcp->lcd_sb.sb_mb)
383: lcp->lcd_send(lcp); /* XXX - fix this */
384: /*FALLTHROUGH*/
385: default:
386: return;
387:
388: dead:
389: case CLEAR:
390: case CLEAR_CONF:
391: lcp->lcd_upper = 0;
392: lcp->lcd_upnext = 0;
393: isop->isop_chan = 0;
394: case RESET:
395: cmd = PRC_ROUTEDEAD;
396: }
397: tpcons_ctlinput(cmd, isop->isop_faddr, isop);
398: if (cmd = PRC_ROUTEDEAD && isop->isop_refcnt == 0)
399: iso_pcbdetach(isop);
400: }
401: }
402:
403: /*
404: * NAME: cons_connect()
405: * CALLED FROM:
406: * tpcons_pcbconnect() when opening a new connection.
407: * FUNCTION anD ARGUMENTS:
408: * Figures out which device to use, finding a route if one doesn't
409: * already exist.
410: * RETURN VALUE:
411: * returns E*
412: */
413: cons_connect(isop)
414: register struct isopcb *isop;
415: {
416: register struct pklcd *lcp = (struct pklcd *)isop->isop_chan;
417: register struct mbuf *m;
418: struct ifaddr *ifa;
419: int error;
420:
421: IFDEBUG(D_CCONN)
422: printf("cons_connect(0x%x): ", isop);
423: dump_isoaddr(isop->isop_faddr);
424: printf("myaddr: ");
425: dump_isoaddr(isop->isop_laddr);
426: printf("\n" );
427: ENDDEBUG
428: NSAPtoDTE(isop->isop_faddr, &lcp->lcd_faddr);
429: lcp->lcd_upper = cons_tpinput;
430: lcp->lcd_upnext = (caddr_t)isop;
431: IFDEBUG(D_CCONN)
432: printf(
433: "calling make_partial_x25_packet( 0x%x, 0x%x, 0x%x)\n",
434: &lcp->lcd_faddr, &lcp->lcd_laddr,
435: isop->isop_socket->so_proto->pr_protocol);
436: ENDDEBUG
437: if ((error = make_partial_x25_packet(isop, lcp, m)) == 0)
438: error = pk_connect(lcp, &lcp->lcd_faddr);
439: return error;
440: }
441:
442: /*
443: **************************** DEVICE cons ***************************
444: */
445:
446:
447: /*
448: * NAME: cons_ctlinput()
449: * CALLED FROM:
450: * lower layer when ECN_CLEAR occurs : this routine is here
451: * for consistency - cons subnet service calls its higher layer
452: * through the protosw entry.
453: * FUNCTION & ARGUMENTS:
454: * cmd is a PRC_* command, list found in ../sys/protosw.h
455: * copcb is the obvious.
456: * This serves the higher-layer cons service.
457: * NOTE: this takes 3rd arg. because cons uses it to inform itself
458: * of things (timeouts, etc) but has a pcb instead of an address.
459: */
460: cons_ctlinput(cmd, sa, copcb)
461: int cmd;
462: struct sockaddr *sa;
463: register struct pklcd *copcb;
464: {
465: }
466:
467:
468: find_error_reason( xp )
469: register struct x25_packet *xp;
470: {
471: extern u_char x25_error_stats[];
472: int error, cause;
473:
474: if (xp) {
475: cause = 4[(char *)xp];
476: switch (cause) {
477: case 0x00:
478: case 0x80:
479: /* DTE originated; look at the diagnostic */
480: error = (CONL_ERROR_MASK | cause);
481: goto done;
482:
483: case 0x01: /* number busy */
484: case 0x81:
485: case 0x09: /* Out of order */
486: case 0x89:
487: case 0x11: /* Remot Procedure Error */
488: case 0x91:
489: case 0x19: /* reverse charging accept not subscribed */
490: case 0x99:
491: case 0x21: /* Incampat destination */
492: case 0xa1:
493: case 0x29: /* fast select accept not subscribed */
494: case 0xa9:
495: case 0x39: /* ship absent */
496: case 0xb9:
497: case 0x03: /* invalid facil request */
498: case 0x83:
499: case 0x0b: /* access barred */
500: case 0x8b:
501: case 0x13: /* local procedure error */
502: case 0x93:
503: case 0x05: /* network congestion */
504: case 0x85:
505: case 0x8d: /* not obtainable */
506: case 0x0d:
507: case 0x95: /* RPOA out of order */
508: case 0x15:
509: /* take out bit 8
510: * so we don't have to have so many perror entries
511: */
512: error = (CONL_ERROR_MASK | 0x100 | (cause & ~0x80));
513: goto done;
514:
515: case 0xc1: /* gateway-detected proc error */
516: case 0xc3: /* gateway congestion */
517:
518: error = (CONL_ERROR_MASK | 0x100 | cause);
519: goto done;
520: }
521: }
522: /* otherwise, a *hopefully* valid perror exists in the e_reason field */
523: error = xp->packet_data;
524: if (error = 0) {
525: printf("Incoming PKT TYPE 0x%x with reason 0x%x\n",
526: pk_decode(xp),
527: cause);
528: error = E_CO_HLI_DISCA;
529: }
530:
531: done:
532: return error;
533: }
534:
535:
536:
537: #endif /* KERNEL */
538:
539: /*
540: * NAME: make_partial_x25_packet()
541: *
542: * FUNCTION and ARGUMENTS:
543: * Makes part of an X.25 call packet, for use by x25.
544: * (src) and (dst) are the NSAP-addresses of source and destination.
545: * (buf) is a ptr to a buffer into which to write this partial header.
546: *
547: * 0 Facility length (in octets)
548: * 1 Facility field, which is a set of:
549: * m facil code
550: * m+1 facil param len (for >2-byte facilities) in octets
551: * m+2..p facil param field
552: * q user data (protocol identification octet)
553: *
554: *
555: * RETURNS:
556: * 0 if OK
557: * E* if failed.
558: *
559: * SIDE EFFECTS:
560: * Stores facilites mbuf in X.25 control block, where the connect
561: * routine knows where to look for it.
562: */
563:
564: #ifdef X25_1984
565: int cons_use_facils = 1;
566: #else /* X25_1984 */
567: int cons_use_facils = 0;
568: #endif /* X25_1984 */
569:
570: int cons_use_udata = 1; /* KLUDGE FOR DEBUGGING */
571:
572: Static int
573: make_partial_x25_packet(isop, lcp)
574: struct isopcb *isop;
575: struct pklcd *lcp;
576: {
577: u_int proto;
578: int flag;
579: caddr_t buf;
580: register caddr_t ptr;
581: register int len = 0;
582: int buflen =0;
583: caddr_t facil_len;
584: int oddness = 0;
585: struct mbuf *m;
586:
587:
588: IFDEBUG(D_CCONN)
589: printf("make_partial_x25_packet(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
590: isop->isop_laddr, isop->isop_faddr, proto, m, flag);
591: ENDDEBUG
592: if (cons_use_udata) {
593: if (isop->isop_x25crud_len > 0) {
594: /*
595: * The user specified something. Stick it in
596: */
597: bcopy(isop->isop_x25crud, lcp->lcd_faddr.x25_udata,
598: isop->isop_x25crud_len);
599: lcp->lcd_faddr.x25_udlen = isop->isop_x25crud_len;
600: }
601: }
602:
603: if (cons_use_facils == 0) {
604: lcp->lcd_facilities = 0;
605: return 0;
606: }
607: MGETHDR(m, MT_DATA, M_WAITOK);
608: if (m == 0)
609: return ENOBUFS;
610: buf = mtod(m, caddr_t);
611: ptr = buf;
612:
613: /* ptr now points to facil length (len of whole facil field in OCTETS */
614: facil_len = ptr ++;
615: m->m_len = 0;
616: pk_build_facilities(m, &lcp->lcd_faddr, 0);
617:
618: IFDEBUG(D_CADDR)
619: printf("make_partial calling: ptr 0x%x, len 0x%x\n", ptr,
620: isop->isop_laddr->siso_addr.isoa_len);
621: ENDDEBUG
622: if (cons_use_facils) {
623: *ptr++ = 0; /* Marker to separate X.25 facitilies from CCITT ones */
624: *ptr++ = 0x0f;
625: *ptr = 0xcb; /* calling facility code */
626: ptr ++;
627: ptr ++; /* leave room for facil param len (in OCTETS + 1) */
628: ptr ++; /* leave room for the facil param len (in nibbles),
629: * high two bits of which indicate full/partial NSAP
630: */
631: len = isop->isop_laddr->siso_addr.isoa_len;
632: bcopy( isop->isop_laddr->siso_data, ptr, len);
633: *(ptr-2) = len+1; /* facil param len in octets */
634: *(ptr-1) = len<<1; /* facil param len in nibbles */
635: ptr += len;
636:
637: IFDEBUG(D_CADDR)
638: printf("make_partial called: ptr 0x%x, len 0x%x\n", ptr,
639: isop->isop_faddr->siso_addr.isoa_len);
640: ENDDEBUG
641: *ptr = 0xc9; /* called facility code */
642: ptr ++;
643: ptr ++; /* leave room for facil param len (in OCTETS + 1) */
644: ptr ++; /* leave room for the facil param len (in nibbles),
645: * high two bits of which indicate full/partial NSAP
646: */
647: len = isop->isop_faddr->siso_nlen;
648: bcopy(isop->isop_faddr->siso_data, ptr, len);
649: *(ptr-2) = len+1; /* facil param len = addr len + 1 for each of these
650: * two length fields, in octets */
651: *(ptr-1) = len<<1; /* facil param len in nibbles */
652: ptr += len;
653:
654: }
655: *facil_len = ptr - facil_len - 1;
656: if (*facil_len > MAX_FACILITIES)
657: return E_CO_PNA_LONG;
658:
659: buflen = (int)(ptr - buf);
660:
661: IFDEBUG(D_CDUMP_REQ)
662: register int i;
663:
664: printf("ECN_CONNECT DATA buf 0x%x len %d (0x%x)\n",
665: buf, buflen, buflen);
666: for( i=0; i < buflen; ) {
667: printf("+%d: %x %x %x %x %x %x %x %x\n",
668: i,
669: *(buf+i), *(buf+i+1), *(buf+i+2), *(buf+i+3),
670: *(buf+i+4), *(buf+i+5), *(buf+i+6), *(buf+i+7));
671: i+=8;
672: }
673: ENDDEBUG
674: IFDEBUG(D_CADDR)
675: printf("make_partial returns buf 0x%x size 0x%x bytes\n",
676: mtod(m, caddr_t), buflen);
677: ENDDEBUG
678:
679: if (buflen > MHLEN)
680: return E_CO_PNA_LONG;
681:
682: m->m_pkthdr.len = m->m_len = buflen;
683: lcp->lcd_facilities = m;
684: return 0;
685: }
686:
687: /*
688: * NAME: NSAPtoDTE()
689: * CALLED FROM:
690: * make_partial_x25_packet()
691: * FUNCTION and ARGUMENTS:
692: * get a DTE address from an NSAP-address (struct sockaddr_iso)
693: * (dst_octet) is the octet into which to begin stashing the DTE addr
694: * (dst_nibble) takes 0 or 1. 1 means begin filling in the DTE addr
695: * in the high-order nibble of dst_octet. 0 means low-order nibble.
696: * (addr) is the NSAP-address
697: * (flag) is true if the transport suffix is to become the
698: * last two digits of the DTE address
699: * A DTE address is a series of ASCII digits
700: *
701: * A DTE address may have leading zeros. The are significant.
702: * 1 digit per nibble, may be an odd number of nibbles.
703: *
704: * An NSAP-address has the DTE address in the IDI. Leading zeros are
705: * significant. Trailing hex f indicates the end of the DTE address.
706: * The IDI is a series of BCD digits, one per nibble.
707: *
708: * RETURNS
709: * # significant digits in the DTE address, -1 if error.
710: */
711:
712: Static int
713: NSAPtoDTE(siso, sx25)
714: register struct sockaddr_iso *siso;
715: register struct sockaddr_x25 *sx25;
716: {
717: int dtelen = -1;
718:
719: IFDEBUG(D_CADDR)
720: printf("NSAPtoDTE: nsap: %s\n", clnp_iso_addrp(&siso->siso_addr));
721: ENDDEBUG
722:
723: if (siso->siso_data[0] == AFI_37) {
724: register char *out = sx25->x25_addr;
725: register char *in = siso->siso_data + 1;
726: register int nibble;
727: char *lim = siso->siso_data + siso->siso_nlen;
728: char *olim = out+15;
729: int lowNibble = 0;
730:
731: while (in < lim) {
732: nibble = ((lowNibble ? *in++ : (*in >> 4)) & 0xf) | 0x30;
733: lowNibble ^= 1;
734: if (nibble != 0x3f && out < olim)
735: *out++ = nibble;
736: }
737: dtelen = out - sx25->x25_addr;
738: *out++ = 0;
739: } else {
740: /* error = iso_8208snparesolve(addr, x121string, &x121strlen);*/
741: register struct rtentry *rt;
742: extern struct sockaddr_iso blank_siso;
743: struct sockaddr_iso nsiso;
744:
745: nsiso = blank_siso;
746: bcopy(nsiso.siso_data, siso->siso_data,
747: nsiso.siso_nlen = siso->siso_nlen);
748: if (rt = rtalloc1(&nsiso, 1)) {
749: register struct sockaddr_x25 *sxx =
750: (struct sockaddr_x25 *)rt->rt_gateway;
751: register char *in = sxx->x25_addr;
752:
753: rt->rt_use--;
754: if (sxx && sxx->x25_family == AF_CCITT) {
755: bcopy(sx25->x25_addr, sxx->x25_addr, sizeof(sx25->x25_addr));
756: while (*in++) {}
757: dtelen = in - sxx->x25_addr;
758: }
759: }
760: }
761: return dtelen;
762: }
763:
764: /*
765: * NAME: FACILtoNSAP()
766: * CALLED FROM:
767: * parse_facil()
768: * FUNCTION and ARGUMENTS:
769: * Creates and NSAP in the sockaddr_iso (addr) from the
770: * x.25 facility found at buf - 1.
771: * RETURNS:
772: * 0 if ok, -1 if error.
773: */
774:
775: Static int
776: FACILtoNSAP(addr, buf)
777: register u_char *buf;
778: register struct sockaddr_iso *addr;
779: {
780: int len_in_nibbles = *++buf & 0x3f;
781: u_char buf_len = (len_in_nibbles + 1) >> 1;; /* in bytes */
782:
783: IFDEBUG(D_CADDR)
784: printf("FACILtoNSAP( 0x%x, 0x%x, 0x%x )\n",
785: buf, buf_len, addr );
786: ENDDEBUG
787:
788: len_in_nibbles = *buf & 0x3f;
789: /* despite the fact that X.25 makes us put a length in nibbles
790: * here, the NSAP-addrs are always in full octets
791: */
792: switch (*buf++ & 0xc0) {
793: case 0:
794: /* Entire OSI NSAP address */
795: bcopy((caddr_t)buf, addr->siso_data, addr->siso_nlen = buf_len);
796: break;
797:
798: case 40:
799: /* Partial OSI NSAP address, assume trailing */
800: if (buf_len + addr->siso_nlen > sizeof(addr->siso_addr))
801: return -1;
802: bcopy((caddr_t)buf, TSEL(addr), buf_len);
803: addr->siso_nlen += buf_len;
804: break;
805:
806: default:
807: /* Rather than blow away the connection, just ignore and use
808: NSAP from DTE */;
809: }
810: return 0;
811: }
812:
813: Static
814: init_siso(siso)
815: register struct sockaddr_iso *siso;
816: {
817: siso->siso_len = sizeof (*siso);
818: siso->siso_family = AF_ISO;
819: siso->siso_data[0] = AFI_37;
820: siso->siso_nlen = 8;
821: }
822:
823: /*
824: * NAME: DTEtoNSAP()
825: * CALLED FROM:
826: * parse_facil()
827: * FUNCTION and ARGUMENTS:
828: * Creates a type 37 NSAP in the sockaddr_iso (addr)
829: * from a DTE address found in a sockaddr_x25.
830: *
831: * RETURNS:
832: * 0 if ok; E* otherwise.
833: */
834:
835: Static int
836: DTEtoNSAP(addr, sx)
837: struct sockaddr_iso *addr;
838: struct sockaddr_x25 *sx;
839: {
840: register char *in, *out;
841: register int first;
842: int pad_tail = 0;
843: int src_len;
844:
845:
846: init_siso(addr);
847: in = sx->x25_addr;
848: src_len = strlen(in);
849: addr->siso_nlen = (src_len + 3) / 2;
850: out = addr->siso_data;
851: *out++ = 0x37;
852: if (src_len & 1) {
853: pad_tail = 0xf;
854: src_len++;
855: }
856: for (first = 0; src_len > 0; src_len--) {
857: first |= 0xf & *in++;
858: if (src_len & 1) {
859: *out++ = first;
860: first = 0;
861: }
862: else first <<= 4;
863: }
864: if (pad_tail)
865: out[-1] |= 0xf;
866: return 0; /* ok */
867: }
868:
869: /*
870: * FUNCTION and ARGUMENTS:
871: * parses (buf_len) bytes beginning at (buf) and finds
872: * a called nsap, a calling nsap, and protocol identifier.
873: * RETURNS:
874: * 0 if ok, E* otherwise.
875: */
876:
877: Static int
878: parse_facil(lcp, isop, buf, buf_len)
879: caddr_t buf;
880: u_char buf_len; /* in bytes */
881: struct isopcb *isop;
882: struct pklcd *lcp;
883: {
884: register int i;
885: register u_char *ptr = (u_char *)buf;
886: u_char *ptr_lim, *facil_lim;
887: int facil_param_len, facil_len;
888:
889: IFDEBUG(D_CADDR)
890: printf("parse_facil(0x%x, 0x%x, 0x%x, 0x%x)\n",
891: lcp, isop, buf, buf_len);
892: dump_buf(buf, buf_len);
893: ENDDEBUG
894:
895: /* find the beginnings of the facility fields in buf
896: * by skipping over the called & calling DTE addresses
897: * i <- # nibbles in called + # nibbles in calling
898: * i += 1 so that an odd nibble gets rounded up to even
899: * before dividing by 2, then divide by two to get # octets
900: */
901: i = (int)(*ptr >> 4) + (int)(*ptr&0xf);
902: i++;
903: ptr += i >> 1;
904: ptr ++; /* plus one for the DTE lengths byte */
905:
906: /* ptr now is at facil_length field */
907: facil_len = *ptr++;
908: facil_lim = ptr + facil_len;
909: IFDEBUG(D_CADDR)
910: printf("parse_facils: facil length is 0x%x\n", (int) facil_len);
911: ENDDEBUG
912:
913: while (ptr < facil_lim) {
914: /* get NSAP addresses from facilities */
915: switch (*ptr++) {
916: case 0xcb:
917: /* calling NSAP */
918: facil_param_len = FACILtoNSAP(isop->isop_faddr, ptr);
919: break;
920: case 0xc9:
921: /* called NSAP */
922: facil_param_len = FACILtoNSAP(isop->isop_laddr, ptr);
923: break;
924:
925: /* from here to default are legit cases that I ignore */
926: /* variable length */
927: case 0xca: /* end-to-end transit delay negot */
928: case 0xc6: /* network user id */
929: case 0xc5: /* charging info : indicating monetary unit */
930: case 0xc2: /* charging info : indicating segment count */
931: case 0xc1: /* charging info : indicating call duration */
932: case 0xc4: /* RPOA extended format */
933: case 0xc3: /* call redirection notification */
934: facil_param_len = 0;
935: break;
936:
937: /* 1 octet */
938: case 0x0a: /* min. throughput class negot */
939: case 0x02: /* throughput class */
940: case 0x03: case 0x47: /* CUG xxxx */
941: case 0x0b: /* expedited data negot */
942: case 0x01: /* Fast select or reverse charging
943: (example of intelligent protocol design) */
944: case 0x04: /* charging info : requesting service */
945: case 0x08: /* called line addr modified notification */
946: case 0x00: /* marker to indicate beginning of CCITT facils */
947: facil_param_len = 1;
948: break;
949:
950: /* any 2 octets */
951: case 0x42: /* pkt size */
952: case 0x43: /* win size */
953: case 0x44: /* RPOA basic format */
954: case 0x41: /* bilateral CUG xxxx */
955: case 0x49: /* transit delay selection and indication */
956: facil_param_len = 2;
957: break;
958:
959: default:
960: printf(
961: "BOGUS FACILITY CODE facil_lim 0x%x facil_len %d, ptr 0x%x *ptr 0x%x\n",
962: facil_lim, facil_len, ptr - 1, ptr[-1]);
963: /* facil that we don't handle
964: return E_CO_HLI_REJI; */
965: switch (ptr[-1] & 0xc0) {
966: case 0x00: facil_param_len = 1; break;
967: case 0x40: facil_param_len = 2; break;
968: case 0x80: facil_param_len = 3; break;
969: case 0xc0: facil_param_len = 0; break;
970: }
971: }
972: if (facil_param_len == -1)
973: return E_CO_REG_ICDA;
974: if (facil_param_len == 0) /* variable length */
975: facil_param_len = (int)*ptr++; /* 1 + the real facil param */
976: ptr += facil_param_len;
977: }
978: return 0;
979: }
980:
981: #endif /* TPCONS */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.