xref: /csrg-svn/sys/netccitt/if_x25subr.c (revision 43362)
141598Ssklower /*
241707Ssklower  * Copyright (c) 1990 The Regents of the University of California.
341598Ssklower  * All rights reserved.
441598Ssklower  *
541707Ssklower  * %sccs.include.redist.c%
641598Ssklower  *
7*43362Ssklower  *	@(#)if_x25subr.c	7.5 (Berkeley) 06/21/90
841598Ssklower  */
941598Ssklower 
1041598Ssklower #include "param.h"
1141598Ssklower #include "systm.h"
1241598Ssklower #include "malloc.h"
1341598Ssklower #include "mbuf.h"
1441598Ssklower #include "protosw.h"
1541598Ssklower #include "socket.h"
1641598Ssklower #include "ioctl.h"
1741598Ssklower #include "errno.h"
1841598Ssklower #include "syslog.h"
1941598Ssklower 
2042140Ssklower #include "../net/if.h"
2142140Ssklower #include "../net/netisr.h"
2242140Ssklower #include "../net/route.h"
2341598Ssklower 
2442140Ssklower #include "x25.h"
2542140Ssklower #include "x25error.h"
2642140Ssklower #include "pk_var.h"
2742140Ssklower 
2841598Ssklower #include "machine/mtpr.h"
2941598Ssklower 
3041598Ssklower #ifdef INET
3141598Ssklower #include "../netinet/in.h"
3241598Ssklower #include "../netinet/in_var.h"
3341598Ssklower #endif
3441598Ssklower 
3541598Ssklower #ifdef NS
3641598Ssklower #include "../netns/ns.h"
3741598Ssklower #include "../netns/ns_if.h"
3841598Ssklower #endif
3941598Ssklower 
4041598Ssklower #ifdef ISO
4141598Ssklower #include "../netiso/argo_debug.h"
4241598Ssklower #include "../netiso/iso.h"
4341598Ssklower #include "../netiso/iso_var.h"
4441598Ssklower #endif
4541598Ssklower 
4641598Ssklower extern	struct ifnet loif;
4741598Ssklower 
4841598Ssklower #define senderr(x) {error = x; goto bad;}
4941598Ssklower /*
5041598Ssklower  * X.25 output routine.
5141598Ssklower  */
5242140Ssklower x25_ifoutput(ifp, m0, dst, rt)
5342140Ssklower struct	ifnet *ifp;
5441598Ssklower struct	mbuf *m0;
5541598Ssklower struct	sockaddr *dst;
5641598Ssklower register struct	rtentry *rt;
5741598Ssklower {
5842140Ssklower 	register struct mbuf *m;
5942277Ssklower 	register struct rtextension_x25 *rtx;
6042277Ssklower 	register struct pq *pq;
6142140Ssklower 	struct pklcd *lcp;
6242140Ssklower 	struct x25_ifaddr *ia;
6341598Ssklower 	struct mbuf    *prev;
6441598Ssklower 	int             s, error = 0, flags = 0;
6541598Ssklower 	union imp_addr  imp_addr;
6641598Ssklower 	int flags = 0;
6741598Ssklower 
6842140Ssklower 	if ((ifp->if_flags & IFF_UP) == 0)
6941598Ssklower 		return (ENETDOWN);
7041598Ssklower 	if (rt == 0 ||
7141598Ssklower 	    ((rt->rt_flags & RTF_GATEWAY) && (dst = rt->rt_gateway))) {
7241598Ssklower 		if ((rt = rtalloc1(dst, 1)) == 0)
7341598Ssklower 			return (EHOSTUNREACH);
7441598Ssklower 		rt->rt_refcnt++;
7542140Ssklower 		flags = XRF_RTHELD;
7641598Ssklower 	}
7741598Ssklower 	/*
7841598Ssklower 	 * Sanity checks.
7941598Ssklower 	 */
8042140Ssklower 	if ((rt->rt_ifp != ifp) ||
8141598Ssklower 	    (rt->rt_flags & (RTF_CLONING | RTF_GATEWAY)) ||
8242140Ssklower 	    ((rtx = (struct rtextension_x25 *)rt->rt_llinfo) == 0)) {
8341598Ssklower 		printf("Inconsistent call to x25_output, should panic\n");
8441598Ssklower 		senderr(ENETUNREACH);
8541598Ssklower 	}
8642140Ssklower     {
8742140Ssklower 	register struct ifaddr *ifa;
8842140Ssklower 	for (ifa = ifp->if_addrlist; ; ifa = ifa->ifa_next) {
8942140Ssklower 		if (ifa == 0)
9042140Ssklower 			senderr(ENETDOWN);
9142140Ssklower 		if (ifa->ifa_addr->sa_family == AF_CCITT)
9242140Ssklower 			break;
9342140Ssklower 	}
9442140Ssklower 	ia = (struct x25_ifaddr *)ifa;
9542140Ssklower     }
9642140Ssklower 	if (rtx->rtx_lcd == 0) {
9742140Ssklower 		int x25_ifinput();
9841598Ssklower 
9942277Ssklower 		lcp = pk_attach((struct socket *)0);
10042277Ssklower 		if (lcp == 0)
10142140Ssklower 			senderr(ENOBUFS);
10242277Ssklower 		rtx->rtx_lcd = lcp;
10342140Ssklower 		rtx->rtx_rt = rt;
10442140Ssklower 		rtx->rtx_ia = ia;
105*43362Ssklower 		lcp->lcd_upnext = (caddr_t)rtx;
106*43362Ssklower 		lcp->lcd_upper = x25_ifinput;
10742140Ssklower 	}
10842140Ssklower 	switch (rtx->rtx_state) {
10942140Ssklower 
11042140Ssklower 	case XRS_CONNECTED:
11142140Ssklower 		lcd->lcd_dg_timer = ia->ia_xc.xc_dg_idletimo;
11241598Ssklower 		/* FALLTHROUGH */
11342140Ssklower 	case XRS_CONNECTING:
114*43362Ssklower 		if (sbspace(&lcp->lcd_sb) < 0)
11541598Ssklower 			senderr(ENOBUFS);
116*43362Ssklower 		lcp->lcd_send(lcp, m);
11741598Ssklower 		break;
11841598Ssklower 
11942140Ssklower 	case XRS_NEWBORN:
12041598Ssklower 		if (dst->sa_family == AF_INET &&
12142140Ssklower 		    ia->xc_if.if_type == IFT_DDN &&
12241598Ssklower 		    rt->rt_gateway->sa_family != AF_CCITT)
12341598Ssklower 			x25_ddnip_to_ccitt(dst, rt->rt_gateway);
12442140Ssklower 		lcp->lcd_flags |= X25_DG_CIRCUIT;
12542140Ssklower 		rtx->rtx_state = XRS_FREE;
12641598Ssklower 		if (rt->rt_gateway->sa_family != AF_CCITT) {
12741598Ssklower 			/*
12841598Ssklower 			 * Need external resolution of dst
12941598Ssklower 			 */
13041598Ssklower 			if ((rt->rt_flags & RTF_XRESOLVE) == 0)
13141598Ssklower 				senderr(ENETUNREACH);
13242140Ssklower 			rtx->rtx_flags |= flags;
13341598Ssklower 			flags = 0;
13441598Ssklower 			rt_missmsg(RTM_RESOLVE, dst,
13541598Ssklower 			    (struct sockaddr *)0, (struct sockaddr *)0,
13641598Ssklower 			    (struct sockaddr *)0, 0, 0);
13742140Ssklower 			rtx->rtx_state = XRS_RESOLVING;
13841598Ssklower 			/* FALLTHROUGH */
13942140Ssklower 	case XRS_RESOLVING:
140*43362Ssklower 			if (sbspace(&lcp->lcd_sb) < 0)
14141598Ssklower 				senderr(ENOBUFS);
142*43362Ssklower 			sbappendrecord(&lcp->lcd_sb, m);
14341598Ssklower 			break;
14441598Ssklower 		}
14541598Ssklower 		/* FALLTHROUGH */
14642140Ssklower 	case XRS_FREE:
147*43362Ssklower 		sbappendrecord(&lcp->lcd_sb, m);
14842140Ssklower 		lcp->lcd_pkcb = &(rtx->rtx_ia->ia_pkcb);
14942277Ssklower 		pk_connect(lcp, (struct mbuf *)0,
15042277Ssklower 				(struct sockaddr_x25 *)rt->rt_gateway);
15142140Ssklower 		break;
15241598Ssklower 		/* FALLTHROUGH */
15341598Ssklower 	default:
15441598Ssklower 		/*
15541598Ssklower 		 * We count on the timer routine to close idle
15641598Ssklower 		 * connections, if there are not enough circuits to go
15741598Ssklower 		 * around.
15841598Ssklower 		 *
15941598Ssklower 		 * So throw away data for now.
16041598Ssklower 		 * After we get it all working, we'll rewrite to handle
16141598Ssklower 		 * actively closing connections (other than by timers),
16241598Ssklower 		 * when circuits get tight.
16341598Ssklower 		 *
16441598Ssklower 		 * In the DDN case, the imp itself closes connections
16541598Ssklower 		 * under heavy load.
16641598Ssklower 		 */
16741598Ssklower 		error = ENOBUFS;
16841598Ssklower 	bad:
16941598Ssklower 		if (m)
17041598Ssklower 			m_freem(m);
17141598Ssklower 	}
17241598Ssklower out:
17342140Ssklower 	if (flags & XRF_RTHELD)
17441598Ssklower 		RTFREE(rt);
17541598Ssklower 	return (error);
17641598Ssklower }
17741598Ssklower 
17841598Ssklower /*
17942140Ssklower  * Simpleminded timer routine.
18041598Ssklower  */
18142140Ssklower x25_iftimeout(ifp)
18242140Ssklower struct ifnet *ifp;
18341598Ssklower {
18442140Ssklower 	register struct pkcb *pkcb = 0;
18542140Ssklower 	register struct ifaddr *ifa;
18642140Ssklower 	register struct pklcd **lcpp, *lcp;
18741598Ssklower 	int s = splimp();
18841598Ssklower 
18942140Ssklower 	for (ifa = ifp->if_addrlist; ; ifa = ifa->ifa_next) {
19042140Ssklower 		if (ifa->ifa_addr->sa_family == AF_CCITT)
19142140Ssklower 			break;
19242140Ssklower 	}
19342140Ssklower 	if (ifa)
19442140Ssklower 		pkcb = &((struct x25_ifaddr *)ifa)->ia_pkcb;
19542140Ssklower 	if (pkcb)
19642140Ssklower 		for (lcpp = pkcb->pk_chan + pkcb->pk_maxlcn;
19742140Ssklower 		     --lcpp >= pkcb->pk_chan;)
19842140Ssklower 			if ((lcp = *lcpp) &&
19942140Ssklower 			    lcp->lcd_state == DATA_TRANSFER &&
20042140Ssklower 			    (lcp->lcd_flags & X25_DG_CICRUIT) &&
20142140Ssklower 			    (--(lcp->lcd_dg_timer) <= 0)) {
20242140Ssklower 				register struct rtextension_x25 *rtx;
20342140Ssklower 				pk_disconnect(lcp);
20442140Ssklower 				rtx = (struct rtextension_x25 *)
205*43362Ssklower 						lcp->lcp_upnext;
20642140Ssklower 				if (rtx)
20742140Ssklower 					rtx->rtx_state = XRS_DISCONNECTING;
20842140Ssklower 			    }
20941598Ssklower 	splx(s);
21041598Ssklower }
21141598Ssklower 
21241598Ssklower /*
21341598Ssklower  * Process a x25 packet as datagram;
21441598Ssklower  */
215*43362Ssklower x25_ifinput(lcp, m)
216*43362Ssklower struct pklcd *lcp;
21741598Ssklower struct mbuf *m;
21841598Ssklower {
219*43362Ssklower 	struct rtextension *rtx = (struct rtentry *)lcp->lcd_upnext;
220*43362Ssklower 	register struct ifnet *ifp = &rtx->rtx_rt->rt_ifp;
22141598Ssklower 	int s;
22241598Ssklower 
22341598Ssklower 	ifp->if_lastchange = time;
22441598Ssklower 
22541598Ssklower 	switch (rt_dst(rt)->sa_family) {
22641598Ssklower #ifdef INET
22741598Ssklower 	case AF_INET:
22841598Ssklower 		schednetisr(NETISR_IP);
22941598Ssklower 		inq = &ipintrq;
23041598Ssklower 		break;
23141598Ssklower 
23241598Ssklower #endif
23341598Ssklower #ifdef NS
23441598Ssklower 	case AF_NS:
23541598Ssklower 		schednetisr(NETISR_NS);
23641598Ssklower 		inq = &nsintrq;
23741598Ssklower 		break;
23841598Ssklower 
23941598Ssklower #endif
24041598Ssklower #ifdef	ISO
24141598Ssklower 	case AF_ISO:
24241598Ssklower 		/* XXXX need to find out about tearing off COSNS
24341598Ssklower 		   headers if any */
24441598Ssklower 		schednetisr(NETISR_ISO);
24541598Ssklower 		inq = &clnlintrq;
24641598Ssklower 		break;
24741598Ssklower #endif
24841598Ssklower 	default:
24941598Ssklower 		m_freem(m);
25041598Ssklower 		ifp->if_noproto++;
25141598Ssklower 		return;
25241598Ssklower 	}
25341598Ssklower 	s = splimp();
25441598Ssklower 	if (IF_QFULL(inq)) {
25541598Ssklower 		IF_DROP(inq);
25641598Ssklower 		m_freem(m);
25741598Ssklower 	} else {
25841598Ssklower 		IF_ENQUEUE(inq, m);
25941598Ssklower 		ifp->if_ibytes += m->m_pkthdr.len;
26041598Ssklower 	}
26141598Ssklower 	splx(s);
26241598Ssklower }
26341598Ssklower 
26441598Ssklower union imp_addr {
26541598Ssklower 	struct in_addr  ip;
26641598Ssklower 	struct imp {
26741598Ssklower 		u_char		s_net;
26841598Ssklower 		u_char		s_host;
26941598Ssklower 		u_char		s_lh;
27041598Ssklower 		u_char		s_impno;
27141598Ssklower 	}		    imp;
27241598Ssklower };
27341598Ssklower static struct sockaddr_x25 blank_x25 = {sizeof blank_x25, AF_CCITT};
27441598Ssklower /*
27541598Ssklower  * IP to X25 address routine copyright ACC, used by permission.
27641598Ssklower  */
27741598Ssklower x25_ddnip_to_ccitt(src, dst)
27841598Ssklower struct sockaddr_in *src;
27941598Ssklower register struct sockaddr_x25 *dst;
28041598Ssklower {
28141598Ssklower 	union imp_addr imp_addr;
28241598Ssklower 	int             imp_no, imp_port;
28341598Ssklower 	char *x25addr = dst->x25_x25addr;
28441598Ssklower 
28541598Ssklower 
28641598Ssklower 	imp_addr.ip = src->sin_addr.s_addr;
28741598Ssklower 	*dst = blank_x25;
28841598Ssklower 	if ((imp_addr.imp.s_net & 0x80) == 0x00) {	/* class A */
28941598Ssklower 	    imp_no = imp_addr.imp.s_impno;
29041598Ssklower 	    imp_port = imp_addr.imp.s_host;
29141598Ssklower 	} else if ((imp_addr.imp.s_net & 0xc0) == 0x80) {	/* class B */
29241598Ssklower 	    imp_no = imp_addr.imp.s_impno;
29341598Ssklower 	    imp_port = imp_addr.imp.s_lh;
29441598Ssklower 	} else {		/* class C */
29541598Ssklower 	    imp_no = imp_addr.imp.s_impno / 32;
29641598Ssklower 	    imp_port = imp_addr.imp.s_impno % 32;
29741598Ssklower 	}
29841598Ssklower 
29941598Ssklower 	x25addr[0] = 12; /* length */
30041598Ssklower 	/* DNIC is cleared by struct copy above */
30141598Ssklower 
30241598Ssklower 	if (imp_port < 64) {	/* Physical:  0000 0 IIIHH00 [SS] *//* s_impno
30341598Ssklower 				 *  -> III, s_host -> HH */
30441598Ssklower 	    x25addr[5] = 0;	/* set flag bit */
30541598Ssklower 	    x25addr[6] = imp_no / 100;
30641598Ssklower 	    x25addr[7] = (imp_no % 100) / 10;
30741598Ssklower 	    x25addr[8] = imp_no % 10;
30841598Ssklower 	    x25addr[9] = imp_port / 10;
30941598Ssklower 	    x25addr[10] = imp_port % 10;
31041598Ssklower 	} else {		/* Logical:   0000 1 RRRRR00 [SS]	 *//* s
31141598Ssklower 				 * _host * 256 + s_impno -> RRRRR */
31241598Ssklower 	    temp = (imp_port << 8) + imp_no;
31341598Ssklower 	    x25addr[5] = 1;
31441598Ssklower 	    x25addr[6] = temp / 10000;
31541598Ssklower 	    x25addr[7] = (temp % 10000) / 1000;
31641598Ssklower 	    x25addr[8] = (temp % 1000) / 100;
31741598Ssklower 	    x25addr[9] = (temp % 100) / 10;
31841598Ssklower 	    x25addr[10] = temp % 10;
31941598Ssklower 	}
32041598Ssklower }
32141598Ssklower 
32241598Ssklower #ifdef caseof
32341598Ssklower #undef caseof
32441598Ssklower #endif
32541598Ssklower #define caseof(a, b) (b + 8 * a)
32641598Ssklower #define SA(p) ((struct sockaddr *)(p))
32741598Ssklower 
32841598Ssklower /*
32941598Ssklower  * This routine gets called when validing new routes or deletions of old
33041598Ssklower  * ones.
33141598Ssklower  */
33241598Ssklower x25_ifrtchange(cmd, rt, dst)
33341598Ssklower register struct rtentry *rt;
33441598Ssklower struct sockaddr *dst;
33541598Ssklower {
33642140Ssklower 	register struct rtextension_x25 *rtx = (struct pklcd *)rt->rt_llinfo;
33741598Ssklower 	register struct sockaddr_x25 *sa =(struct sockaddr_x25 *)rt->rt_gateway;
33842140Ssklower 	register struct pklcd *lcp;
33942140Ssklower 	register struct x25_ifaddr *ia;
34041598Ssklower 	register struct sockaddr *sa2;
34141598Ssklower 	struct mbuf *m, *mold;
342*43362Ssklower 	int x25_ifrtfree();
34341598Ssklower 
34442140Ssklower 	if (rtx == 0)
34541598Ssklower 		return;
34642140Ssklower 	ia = rtx->rtx_ia;
34742140Ssklower 	lcp = rtx->rtx_lcd;
34842140Ssklower 
34941598Ssklower 	switch (caseof(xl->xl_state, cmd)) {
35042140Ssklower 
35142140Ssklower 	case caseof(XRS_CONNECTED, RTM_DELETE):
35242140Ssklower 	case caseof(XRS_CONNECTED, RTM_CHANGE):
35342140Ssklower 	case caseof(XRS_CONNECTING, RTM_DELETE):
35442140Ssklower 	case caseof(XRS_CONNECTING, RTM_CHANGE):
35542140Ssklower 		pk_disconnect(lcp);
356*43362Ssklower 		lcp->lcd_upper = x25_ifrtfree;
35742140Ssklower 		rt->rt_refcnt++;
35841598Ssklower 		break;
35941598Ssklower 
36042140Ssklower 	case caseof(XRS_CONNECTED, RTM_ADD):
36142140Ssklower 	case caseof(XRS_CONNECTING, RTM_ADD):
36242140Ssklower 	case caseof(XRS_RESOLVING, RTM_ADD):
36341598Ssklower 		printf("ifrtchange: impossible transition, should panic\n");
36441598Ssklower 		break;
36541598Ssklower 
36642140Ssklower 	case caseof(XRS_RESOLVING, RTM_DELETE):
367*43362Ssklower 		sbflush(&(rtx->rtx_lcd->lcd_sb));
368*43362Ssklower 		free((caddr_t)rtx->rtx_lcd, M_PCB);
36942140Ssklower 		rtx->rtx_lcd = 0;
37041598Ssklower 		break;
37141598Ssklower 
37242140Ssklower 	case caseof(XRS_RESOLVING, RTM_CHANGE):
37342140Ssklower 		lcp->lcd_pkcb = &(ia->ia_pkcb);
37442277Ssklower 		pk_connect(lcp, (struct mbuf *)0, sa);
37541598Ssklower 		break;
37641598Ssklower 	}
37742140Ssklower 	if (rt->rt_ifp->if_type == IFT_DDN)
37842140Ssklower 		return;
37941598Ssklower 	sa2 = SA(rt->rt_key);
38041598Ssklower 	if (cmd == RTM_CHANGE) {
38141598Ssklower 		if (sa->sa_family == AF_CCITT) {
382*43362Ssklower 			sa->x25_opts.op_speed = sa2->sa_family;
38341598Ssklower 			(void) rtrequest(RTM_DELETE, SA(sa), sa2,
38441598Ssklower 			       SA(0), RTF_HOST, (struct rtentry **)0);
38541598Ssklower 		}
38641598Ssklower 		sa = (struct sockaddr_x25 *)dst;
38741598Ssklower 		cmd = RTM_ADD;
38841598Ssklower 	}
38941598Ssklower 	if (sa->sa_family == AF_CCITT) {
390*43362Ssklower 		sa->x25_opts.op_speed = sa2->sa_family;
39141598Ssklower 		(void) rtrequest(cmd, SA(sa), sa2, SA(0), RTF_HOST,
39241598Ssklower 							(struct rtentry **)0);
393*43362Ssklower 		sa->x25_opts.op_speed = 0;
39441598Ssklower 	}
39541598Ssklower }
396*43362Ssklower 
39741598Ssklower static struct sockaddr sin = {sizeof(sin), AF_INET};
39841598Ssklower /*
39941598Ssklower  * This is a utility routine to be called by x25 devices when a
40041598Ssklower  * call request is honored with the intent of starting datagram forwarding.
40141598Ssklower  */
40242140Ssklower x25_dg_rtinit(dst, ia, af)
40341598Ssklower struct sockaddr_x25 *dst;
40442140Ssklower register struct x25com *ia;
40541598Ssklower {
40641598Ssklower 	struct sockaddr *sa = 0;
40742140Ssklower 	if (ia->xc_if.if_type == IFT_DDN && af == AF_INET) {
40841598Ssklower 	/*
40941598Ssklower 	 * Inverse X25 to IPP mapping copyright and courtesy ACC.
41041598Ssklower 	 */
41141598Ssklower 		int             imp_no, imp_port, temp;
41241598Ssklower 		union imp_addr imp_addr;
41341598Ssklower 	    {
41441598Ssklower 		/*
41541598Ssklower 		 * First determine our IP addr for network
41641598Ssklower 		 */
41741598Ssklower 		register struct in_ifaddr *ia;
41841598Ssklower 		extern struct in_ifaddr *in_ifaddr;
41941598Ssklower 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
42042140Ssklower 			if (ia->ia_ifp == &ia->xc_if) {
42141598Ssklower 				imp_addr.ip = ia->ia_addr.sin_addr;
42241598Ssklower 				break;
42341598Ssklower 			}
42441598Ssklower 	    }
42541598Ssklower 	    {
42641598Ssklower 
42741598Ssklower 		register char *x25addr = dst->x25_addr;
42841598Ssklower 
42941598Ssklower 		switch (x25addr[5] & 0x0f) {
43041598Ssklower 		  case 0:	/* Physical:  0000 0 IIIHH00 [SS]	 */
43141598Ssklower 		    imp_no =
43241598Ssklower 			((int) (x25addr[6] & 0x0f) * 100) +
43341598Ssklower 			((int) (x25addr[7] & 0x0f) * 10) +
43441598Ssklower 			((int) (x25addr[8] & 0x0f));
43541598Ssklower 
43641598Ssklower 
43741598Ssklower 		    imp_port =
43841598Ssklower 			((int) (x25addr[9] & 0x0f) * 10) +
43941598Ssklower 			((int) (x25addr[10] & 0x0f));
44041598Ssklower 		    break;
44141598Ssklower 		  case 1:	/* Logical:   0000 1 RRRRR00 [SS]	 */
44241598Ssklower 		    temp = ((int) (x25addr[6] & 0x0f) * 10000)
44341598Ssklower 			+ ((int) (x25addr[7] & 0x0f) * 1000)
44441598Ssklower 			+ ((int) (x25addr[8] & 0x0f) * 100)
44541598Ssklower 			+ ((int) (x25addr[9] & 0x0f) * 10)
44641598Ssklower 			+ ((int) (x25addr[10] & 0x0f));
44741598Ssklower 
44841598Ssklower 		    imp_port = temp >> 8;
44941598Ssklower 		    imp_no = temp & 0xff;
45041598Ssklower 		    break;
45141598Ssklower 		  default:
45241598Ssklower 		    return (0L);
45341598Ssklower 		}
45441598Ssklower 		imp_addr.ip.s_addr = my_addr;
45541598Ssklower 		if ((imp_addr.imp.s_net & 0x80) == 0x00) {
45641598Ssklower 		/* class A */
45741598Ssklower 		    imp_addr.imp.s_host = imp_port;
45841598Ssklower 		    imp_addr.imp.s_impno = imp_no;
45941598Ssklower 		    imp_addr.imp.s_lh = 0;
46041598Ssklower 		} else if ((imp_addr.imp.s_net & 0xc0) == 0x80) {
46141598Ssklower 		/* class B */
46241598Ssklower 		    imp_addr.imp.s_lh = imp_port;
46341598Ssklower 		    imp_addr.imp.s_impno = imp_no;
46441598Ssklower 		} else {
46541598Ssklower 		/* class C */
46641598Ssklower 		    imp_addr.imp.s_impno = (imp_no << 5) + imp_port;
46741598Ssklower 		}
46841598Ssklower 	    }
46941598Ssklower 		sin.sin_addr = imp_addr.ip;
47041598Ssklower 		sa = (struct sockaddr *)&sin;
47141598Ssklower 	} else {
47241598Ssklower 		/*
47341598Ssklower 		 * This uses the X25 routing table to do inverse
47441598Ssklower 		 * lookup of x25 address to sockaddr.
47541598Ssklower 		 */
476*43362Ssklower 		dst->x25_opts.op_speed = af;
47741598Ssklower 		if (rt = rtalloc1(dst, 0)) {
47841598Ssklower 			sa = rt->rt_gateway;
47941598Ssklower 			rt->rt_refcnt--;
48041598Ssklower 		}
481*43362Ssklower 		dst->x25_opts.op_speed = 0;
48241598Ssklower 	}
48341598Ssklower 	/*
48441598Ssklower 	 * Call to rtalloc1 will create rtentry for reverse path
48541598Ssklower 	 * to callee by virtue of cloning magic and will allocate
48641598Ssklower 	 * space for local control block.
48741598Ssklower 	 */
48841598Ssklower 	if (sa && rt = rtalloc1(sa, 1))
48941598Ssklower 		rt->rt_refcnt--;
49041598Ssklower }
491*43362Ssklower 
492*43362Ssklower struct radix_tree_head *x25_rnhead;
493*43362Ssklower 
494*43362Ssklower pk_init()
495*43362Ssklower {
496*43362Ssklower 	/*
497*43362Ssklower 	 * warning, sizeof (struct sockaddr_x25) > 32,
498*43362Ssklower 	 * but contains no data of interest beyond 32
499*43362Ssklower 	 */
500*43362Ssklower 	rn_inithead(&x25_rnhead, 16, AF_CCITT);
501*43362Ssklower }
502