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