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