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