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