The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netccitt/if_x25subr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: if_x25subr.c,v 1.33 2003/11/11 20:25:26 jonathan Exp $ */
    2 
    3 /*
    4  * Copyright (c) 1990, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the University nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  *      @(#)if_x25subr.c        8.1 (Berkeley) 6/10/93
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __KERNEL_RCSID(0, "$NetBSD: if_x25subr.c,v 1.33 2003/11/11 20:25:26 jonathan Exp $");
   36 
   37 #include "opt_inet.h"
   38 #include "opt_iso.h"
   39 #include "opt_ns.h"
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/malloc.h>
   44 #include <sys/mbuf.h>
   45 #include <sys/protosw.h>
   46 #include <sys/socket.h>
   47 #include <sys/socketvar.h>
   48 #include <sys/ioctl.h>
   49 #include <sys/errno.h>
   50 #include <sys/syslog.h>
   51 
   52 #include <machine/cpu.h>        /* XXX for setsoftnet().  This must die. */
   53 
   54 #include <net/if.h>
   55 #include <net/if_types.h>
   56 #include <net/netisr.h>
   57 #include <net/route.h>
   58 
   59 #include <netccitt/x25.h>
   60 #include <netccitt/x25err.h>
   61 #include <netccitt/pk.h>
   62 #include <netccitt/pk_var.h>
   63 #include <netccitt/pk_extern.h>
   64 
   65 #ifdef INET
   66 #include <netinet/in.h>
   67 #include <netinet/in_var.h>
   68 #else
   69 #ifdef _KERNEL
   70 #error options CCITT assumes options INET
   71 #endif
   72 #endif
   73 
   74 #ifdef NS
   75 #include <netns/ns.h>
   76 #include <netns/ns_if.h>
   77 #endif
   78 
   79 #ifdef ISO
   80 #include <netiso/argo_debug.h>
   81 #include <netiso/iso.h>
   82 #include <netiso/iso_var.h>
   83 #ifdef TPCONS
   84 #include <netiso/tp_param.h>
   85 #include <netiso/tp_var.h>
   86 #endif
   87 #endif
   88 
   89 
   90 LIST_HEAD(, llinfo_x25) llinfo_x25;
   91 struct sockaddr *x25_dgram_sockmask;
   92 struct sockaddr_x25 x25_dgmask = {
   93         offsetof(struct sockaddr_x25, x25_udata[1]),    /* _len */
   94         0,              /* _family */
   95         0,              /* _net */
   96         {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},       /* _addr */
   97         {0, 0, 0, 0},           /* opts [flags, psize, wsize, speed] */
   98         -1,             /* _udlen */
   99         {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},       /* _udata */
  100 };
  101 
  102 struct if_x25stats {
  103         int             ifx_wrongplen;
  104         int             ifx_nophdr;
  105 } if_x25stats;
  106 int x25_autoconnect = 0;
  107 
  108 #define senderr(x) {error = x; goto bad;}
  109 
  110 static struct llinfo_x25 *x25_lxalloc __P((struct rtentry *));
  111 
  112 /*
  113  * Ancillary routines
  114  */
  115 static struct llinfo_x25 *
  116 x25_lxalloc(rt)
  117         struct rtentry *rt;
  118 {
  119         struct llinfo_x25 *lx;
  120         struct sockaddr *dst = rt_key(rt);
  121         struct ifaddr *ifa;
  122 
  123         MALLOC(lx, struct llinfo_x25 *, sizeof(*lx), M_PCB, M_NOWAIT);
  124         if (lx == 0)
  125                 return lx;
  126         Bzero(lx, sizeof(*lx));
  127         lx->lx_rt = rt;
  128         lx->lx_family = dst->sa_family;
  129         rt->rt_refcnt++;
  130         if (rt->rt_llinfo) {
  131                 LIST_INSERT_AFTER(
  132                           (struct llinfo_x25 *) rt->rt_llinfo, lx, lx_list);
  133         } else {
  134                 rt->rt_llinfo = (caddr_t) lx;
  135                 LIST_INSERT_HEAD(&llinfo_x25, lx, lx_list);
  136         }
  137         for (ifa = rt->rt_ifp->if_addrlist.tqh_first; ifa != 0;
  138              ifa = ifa->ifa_list.tqe_next) {
  139                 if (ifa->ifa_addr->sa_family == AF_CCITT)
  140                         lx->lx_ia = (struct x25_ifaddr *) ifa;
  141         }
  142         return lx;
  143 }
  144 
  145 void
  146 x25_lxfree(lx)
  147         struct llinfo_x25 *lx;
  148 {
  149         struct rtentry *rt = lx->lx_rt;
  150         struct pklcd *lcp = lx->lx_lcd;
  151 
  152         if (lcp) {
  153                 lcp->lcd_upper = 0;
  154                 pk_disconnect(lcp);
  155         }
  156         if ((rt->rt_llinfo == (caddr_t) lx) && (lx->lx_list.le_next->lx_rt == rt))
  157                 rt->rt_llinfo = (caddr_t) lx->lx_list.le_next;
  158         else
  159                 rt->rt_llinfo = 0;
  160         RTFREE(rt);
  161         LIST_REMOVE(lx, lx_list);
  162         FREE(lx, M_PCB);
  163 }
  164 /*
  165  * Process a x25 packet as datagram;
  166  */
  167 int
  168 x25_ifinput(m, v)
  169         struct mbuf *m;
  170         void *v;
  171 {
  172         struct pklcd   *lcp = v;
  173         struct llinfo_x25 *lx = (struct llinfo_x25 *) lcp->lcd_upnext;
  174         struct ifnet *ifp;
  175         struct ifqueue *inq;
  176         int             s, isr;
  177 
  178         if (m == 0 || lcp->lcd_state != DATA_TRANSFER)
  179                 return x25_connect_callback(NULL, lcp);
  180 
  181         pk_flowcontrol(lcp, 0, 1);      /* Generate RR */
  182         ifp = m->m_pkthdr.rcvif;
  183         switch (m->m_type) {
  184         default:
  185                 if (m)
  186                         m_freem(m);
  187                 return 0;
  188 
  189         case MT_DATA:
  190                  /* FALLTHROUGH */ ;
  191         }
  192         switch (lx->lx_family) {
  193 #ifdef INET
  194         case AF_INET:
  195                 isr = NETISR_IP;
  196                 inq = &ipintrq;
  197                 break;
  198 
  199 #endif
  200 #ifdef NS
  201         case AF_NS:
  202                 isr = NETISR_NS;
  203                 inq = &nsintrq;
  204                 break;
  205 
  206 #endif
  207 #ifdef  ISO
  208         case AF_ISO:
  209                 isr = NETISR_ISO;
  210                 inq = &clnlintrq;
  211                 break;
  212 #endif
  213         default:
  214                 m_freem(m);
  215                 ifp->if_noproto++;
  216                 return 0;
  217         }
  218         s = splnet();
  219         schednetisr(isr);
  220         if (IF_QFULL(inq)) {
  221                 IF_DROP(inq);
  222                 m_freem(m);
  223         } else {
  224                 IF_ENQUEUE(inq, m);
  225                 ifp->if_ibytes += m->m_pkthdr.len;
  226         }
  227         splx(s);
  228         return 0;
  229 }
  230 
  231 int
  232 x25_connect_callback(m, v)
  233         struct mbuf *m;
  234         void *v;
  235 {
  236         struct pklcd *lcp = v;
  237         struct llinfo_x25 *lx = (struct llinfo_x25 *) lcp->lcd_upnext;
  238         int             do_clear = 1;
  239         if (m == 0)
  240                 goto refused;
  241         if (m->m_type != MT_CONTROL) {
  242                 printf("x25_connect_callback: should panic\n");
  243                 goto refused;
  244         }
  245         switch (pk_decode(mtod(m, struct x25_packet *))) {
  246         case PK_CALL_ACCEPTED:
  247                 lcp->lcd_upper = x25_ifinput;
  248                 if (lcp->lcd_sb.sb_mb)
  249                         lcp->lcd_send(lcp);     /* XXX start queued packets */
  250                 return 0;
  251         default:
  252                 do_clear = 0;
  253 refused:
  254                 lcp->lcd_upper = 0;
  255                 lx->lx_lcd = 0;
  256                 if (do_clear)
  257                         pk_disconnect(lcp);
  258                 return 0;
  259         }
  260 }
  261 
  262 
  263 #define SA(p) ((struct sockaddr *)(p))
  264 #define RT(p) ((struct rtentry *)(p))
  265 
  266 int
  267 x25_dgram_incoming(m0, v)
  268         struct mbuf    *m0;
  269         void *v;
  270 {
  271         struct pklcd *lcp = v;
  272         struct rtentry *rt, *nrt;
  273         struct mbuf *m = m0->m_next;    /* m0 has calling
  274                                                  * sockaddr_x25 */
  275         rt = rtalloc1(SA(&lcp->lcd_faddr), 0);
  276         if (rt == 0) {
  277 refuse:         lcp->lcd_upper = 0;
  278                 pk_close(lcp);
  279                 return 0;
  280         }
  281         rt->rt_refcnt--;
  282         if ((nrt = RT(rt->rt_llinfo)) == 0 || rt_mask(rt) != x25_dgram_sockmask)
  283                 goto refuse;
  284         if ((nrt->rt_flags & RTF_UP) == 0) {
  285                 rt->rt_llinfo = (caddr_t) rtalloc1(rt->rt_gateway, 0);
  286                 rtfree(nrt);
  287                 if ((nrt = RT(rt->rt_llinfo)) == 0)
  288                         goto refuse;
  289                 nrt->rt_refcnt--;
  290         }
  291         if (nrt->rt_ifa == 0 || nrt->rt_ifa->ifa_rtrequest != x25_rtrequest)
  292                 goto refuse;
  293         lcp->lcd_send(lcp);     /* confirm call */
  294         x25_rtattach(lcp, nrt);
  295         m_freem(m);
  296         return 0;
  297 }
  298 
  299 /*
  300  * X.25 output routine.
  301  */
  302 int
  303 x25_ifoutput(ifp, m0, dst, rt)
  304         struct ifnet   *ifp;
  305         struct mbuf    *m0;
  306         struct sockaddr *dst;
  307         struct rtentry *rt;
  308 {
  309         struct mbuf *m = m0;
  310         struct llinfo_x25 *lx;
  311         struct pklcd   *lcp;
  312         int             error = 0;
  313 
  314         int             plen;
  315         for (plen = 0; m; m = m->m_next)
  316                 plen += m->m_len;
  317         m = m0;
  318 
  319         if ((ifp->if_flags & IFF_UP) == 0)
  320                 senderr(ENETDOWN);
  321         while (rt == 0 || (rt->rt_flags & RTF_GATEWAY)) {
  322                 if (rt) {
  323                         if (rt->rt_llinfo) {
  324                                 rt = (struct rtentry *) rt->rt_llinfo;
  325                                 continue;
  326                         }
  327                         dst = rt->rt_gateway;
  328                 }
  329                 if ((rt = rtalloc1(dst, 1)) == 0)
  330                         senderr(EHOSTUNREACH);
  331                 rt->rt_refcnt--;
  332         }
  333         /*
  334          * Sanity checks.
  335          */
  336         if ((rt->rt_ifp != ifp) ||
  337             (rt->rt_flags & (RTF_CLONING | RTF_GATEWAY)) ||
  338             ((lx = (struct llinfo_x25 *) rt->rt_llinfo) == 0)) {
  339                 senderr(ENETUNREACH);
  340         }
  341         if ((m->m_flags & M_PKTHDR) == 0) {
  342                 if_x25stats.ifx_nophdr++;
  343                 m = m_gethdr(M_NOWAIT, MT_HEADER);
  344                 if (m == 0)
  345                         senderr(ENOBUFS);
  346                 m->m_pkthdr.len = plen;
  347                 m->m_next = m0;
  348         }
  349         if (plen != m->m_pkthdr.len) {
  350                 if_x25stats.ifx_wrongplen++;
  351                 m->m_pkthdr.len = plen;
  352         }
  353 next_circuit:
  354         lcp = lx->lx_lcd;
  355         if (lcp == 0) {
  356                 lx->lx_lcd = lcp = pk_attach((struct socket *) 0);
  357                 if (lcp == 0)
  358                         senderr(ENOBUFS);
  359                 lcp->lcd_upper = x25_connect_callback;
  360                 lcp->lcd_upnext = (caddr_t) lx;
  361                 lcp->lcd_packetsize = lx->lx_ia->ia_xc.xc_psize;
  362                 lcp->lcd_flags = X25_MBS_HOLD;
  363         }
  364         switch (lcp->lcd_state) {
  365         case READY:
  366                 if (dst->sa_family == AF_INET &&
  367                     ifp->if_type == IFT_X25DDN &&
  368                     rt->rt_gateway->sa_family != AF_CCITT)
  369                         x25_ddnip_to_ccitt(dst, rt);
  370                 if (rt->rt_gateway->sa_family != AF_CCITT) {
  371                         if ((rt->rt_flags & RTF_XRESOLVE) == 0)
  372                                 senderr(EHOSTUNREACH);
  373                 } else if (x25_autoconnect)
  374                         error = pk_connect(lcp,
  375                                     (struct sockaddr_x25 *) rt->rt_gateway);
  376                 if (error)
  377                         senderr(error);
  378                 /* FALLTHROUGH */
  379         case SENT_CALL:
  380         case DATA_TRANSFER:
  381                 if (sbspace(&lcp->lcd_sb) < 0) {
  382                         lx = lx->lx_list.le_next;
  383                         if (lx->lx_rt != rt)
  384                                 senderr(ENOSPC);
  385                         goto next_circuit;
  386                 }
  387                 if (lx->lx_ia)
  388                         lcp->lcd_dg_timer =
  389                                 lx->lx_ia->ia_xc.xc_dg_idletimo;
  390                 pk_send(m, lcp);
  391                 break;
  392         default:
  393                 /*
  394                  * We count on the timer routine to close idle
  395                  * connections, if there are not enough circuits to go
  396                  * around.
  397                  *
  398                  * So throw away data for now.
  399                  * After we get it all working, we'll rewrite to handle
  400                  * actively closing connections (other than by timers),
  401                  * when circuits get tight.
  402                  *
  403                  * In the DDN case, the imp itself closes connections
  404                  * under heavy load.
  405                  */
  406                 error = ENOBUFS;
  407 bad:
  408                 if (m)
  409                         m_freem(m);
  410         }
  411         return (error);
  412 }
  413 
  414 /*
  415  * Simpleminded timer routine.
  416  */
  417 void
  418 x25_iftimeout(ifp)
  419         struct ifnet   *ifp;
  420 {
  421         struct pkcb *pkcb = 0;
  422         struct pklcd **lcpp, *lcp;
  423         int             s = splnet();
  424 
  425         FOR_ALL_PKCBS(pkcb)
  426                 if (pkcb->pk_ia->ia_ifp == ifp)
  427                 for (lcpp = pkcb->pk_chan + pkcb->pk_maxlcn;
  428                      --lcpp > pkcb->pk_chan;)
  429                         if ((lcp = *lcpp) &&
  430                             lcp->lcd_state == DATA_TRANSFER &&
  431                             (lcp->lcd_flags & X25_DG_CIRCUIT) &&
  432                           (lcp->lcd_dg_timer && --lcp->lcd_dg_timer == 0)) {
  433                                 (*lcp->lcd_upper)(NULL, lcp);
  434                         }
  435         splx(s);
  436 }
  437 /*
  438  * This routine gets called when validating additions of new routes
  439  * or deletions of old ones.
  440  */
  441 void
  442 x25_rtrequest(cmd, rt, info)
  443         int cmd;
  444         struct rtentry *rt;
  445         struct rt_addrinfo *info;
  446 {
  447         struct llinfo_x25 *lx = (struct llinfo_x25 *) rt->rt_llinfo;
  448         struct pklcd *lcp;
  449 
  450         /*
  451          * would put this pk_init, except routing table doesn't exist yet.
  452          */
  453         if (x25_dgram_sockmask == 0) {
  454                 x25_dgram_sockmask =
  455                         SA(rn_addmask((caddr_t) & x25_dgmask, 0, 4)->rn_key);
  456         }
  457         if (rt->rt_flags & RTF_GATEWAY) {
  458                 if (rt->rt_llinfo)
  459                         RTFREE((struct rtentry *) rt->rt_llinfo);
  460                 rt->rt_llinfo = (cmd == RTM_ADD) ?
  461                         (caddr_t) rtalloc1(rt->rt_gateway, 1) : 0;
  462                 return;
  463         }
  464         if ((rt->rt_flags & RTF_HOST) == 0)
  465                 return;
  466         if (cmd == RTM_DELETE) {
  467                 while (rt->rt_llinfo)
  468                         x25_lxfree((struct llinfo_x25 *) rt->rt_llinfo);
  469                 x25_rtinvert(RTM_DELETE, rt->rt_gateway, rt);
  470                 return;
  471         }
  472         if (lx == 0 && (lx = x25_lxalloc(rt)) == 0)
  473                 return;
  474         if ((lcp = lx->lx_lcd) && lcp->lcd_state != READY) {
  475                 /*
  476                  * This can only happen on a RTM_CHANGE operation
  477                  * though cmd will be RTM_ADD.
  478                  */
  479                 if (lcp->lcd_ceaddr &&
  480                     Bcmp(rt->rt_gateway, lcp->lcd_ceaddr,
  481                          lcp->lcd_ceaddr->x25_len) != 0) {
  482                         x25_rtinvert(RTM_DELETE,
  483                                      (struct sockaddr *) lcp->lcd_ceaddr, rt);
  484                         lcp->lcd_upper = 0;
  485                         pk_disconnect(lcp);
  486                 }
  487                 lcp = 0;
  488         }
  489         x25_rtinvert(RTM_ADD, rt->rt_gateway, rt);
  490 }
  491 
  492 int x25_dont_rtinvert = 0;
  493 
  494 void
  495 x25_rtinvert(cmd, sa, rt)
  496         int cmd;
  497         struct sockaddr *sa;
  498         struct rtentry *rt;
  499 {
  500         struct rtentry *rt2 = 0;
  501         /*
  502          * rt_gateway contains PID indicating which proto
  503          * family on the other end, so will be different
  504          * from general host route via X.25.
  505          */
  506         if (rt->rt_ifp->if_type == IFT_X25DDN || x25_dont_rtinvert)
  507                 return;
  508         if (sa->sa_family != AF_CCITT)
  509                 return;
  510         if (cmd != RTM_DELETE) {
  511                 rtrequest(RTM_ADD, sa, rt_key(rt), x25_dgram_sockmask,
  512                           RTF_PROTO2, &rt2);
  513                 if (rt2) {
  514                         rt2->rt_llinfo = (caddr_t) rt;
  515                         rt->rt_refcnt++;
  516                 }
  517                 return;
  518         }
  519         rt2 = rt;
  520         if ((rt = rtalloc1(sa, 0)) == 0 ||
  521             (rt->rt_flags & RTF_PROTO2) == 0 ||
  522             rt->rt_llinfo != (caddr_t) rt2) {
  523                 printf("x25_rtchange: inverse route screwup\n");
  524                 return;
  525         } else
  526                 rt2->rt_refcnt--;
  527         rtrequest(RTM_DELETE, sa, rt_key(rt2), x25_dgram_sockmask,
  528                   0, (struct rtentry **) 0);
  529 }
  530 
  531 static struct sockaddr_x25 blank_x25 = {sizeof blank_x25, AF_CCITT};
  532 /*
  533  * IP to X25 address routine copyright ACC, used by permission.
  534  */
  535 union imp_addr {
  536         struct in_addr  ip;
  537         struct imp {
  538                 u_char          s_net;
  539                 u_char          s_host;
  540                 u_char          s_lh;
  541                 u_char          s_impno;
  542         } imp;
  543 };
  544 
  545 /*
  546  * The following is totally bogus and here only to preserve
  547  * the IP to X.25 translation.
  548  */
  549 void
  550 x25_ddnip_to_ccitt(src, rt)
  551         struct sockaddr *src;
  552         struct rtentry *rt;
  553 {
  554         struct sockaddr_x25 *dst = (struct sockaddr_x25 *) rt->rt_gateway;
  555         union imp_addr  imp_addr;
  556         int             imp_no, imp_port, temp;
  557         char           *x25addr = dst->x25_addr;
  558 
  559 
  560         imp_addr.ip = ((struct sockaddr_in *) src)->sin_addr;
  561         *dst = blank_x25;
  562         if ((imp_addr.imp.s_net & 0x80) == 0x00) {      /* class A */
  563                 imp_no = imp_addr.imp.s_impno;
  564                 imp_port = imp_addr.imp.s_host;
  565         } else if ((imp_addr.imp.s_net & 0xc0) == 0x80) {       /* class B */
  566                 imp_no = imp_addr.imp.s_impno;
  567                 imp_port = imp_addr.imp.s_lh;
  568         } else {                /* class C */
  569                 imp_no = imp_addr.imp.s_impno / 32;
  570                 imp_port = imp_addr.imp.s_impno % 32;
  571         }
  572 
  573         x25addr[0] = 12;        /* length */
  574         /* DNIC is cleared by struct copy above */
  575 
  576         if (imp_port < 64) {    /* Physical:  0000 0 IIIHH00 [SS] *//* s_impno
  577                                  * -> III, s_host -> HH */
  578                 x25addr[5] = 0; /* set flag bit */
  579                 x25addr[6] = imp_no / 100;
  580                 x25addr[7] = (imp_no % 100) / 10;
  581                 x25addr[8] = imp_no % 10;
  582                 x25addr[9] = imp_port / 10;
  583                 x25addr[10] = imp_port % 10;
  584         } else {                /* Logical:   0000 1 RRRRR00 [SS]        *//* s
  585                                  * _host * 256 + s_impno -> RRRRR */
  586                 temp = (imp_port << 8) + imp_no;
  587                 x25addr[5] = 1;
  588                 x25addr[6] = temp / 10000;
  589                 x25addr[7] = (temp % 10000) / 1000;
  590                 x25addr[8] = (temp % 1000) / 100;
  591                 x25addr[9] = (temp % 100) / 10;
  592                 x25addr[10] = temp % 10;
  593         }
  594 }
  595 
  596 /*
  597  * This routine is a sketch and is not to be believed!!!!!
  598  *
  599  * This is a utility routine to be called by x25 devices when a
  600  * call request is honored with the intent of starting datagram forwarding.
  601  */
  602 void
  603 x25_dg_rtinit(dst, ia, af)
  604         struct sockaddr_x25 *dst;
  605         struct x25_ifaddr *ia;
  606         int af;
  607 {
  608         struct sockaddr *sa = 0;
  609         struct rtentry *rt;
  610         struct in_addr  my_addr;
  611         static struct sockaddr_in sin = {sizeof(sin), AF_INET};
  612 
  613         if (ia->ia_ifp->if_type == IFT_X25DDN && af == AF_INET) {
  614                 /*
  615                  * Inverse X25 to IP mapping copyright and courtesy ACC.
  616                  */
  617                 int             imp_no, imp_port, temp;
  618                 union imp_addr  imp_addr;
  619                 {
  620                         /*
  621                          * First determine our IP addr for network
  622                          */
  623                         struct in_ifaddr *ina;
  624 
  625                         for (ina = in_ifaddrhead.tqh_first; ina != 0;
  626                              ina = ina->ia_list.tqe_next)
  627                                 if (ina->ia_ifp == ia->ia_ifp) {
  628                                         my_addr = ina->ia_addr.sin_addr;
  629                                         break;
  630                                 }
  631                 }
  632                 {
  633 
  634                         char  *x25addr = dst->x25_addr;
  635 
  636                         switch (x25addr[5] & 0x0f) {
  637                         case 0:/* Physical:  0000 0 IIIHH00 [SS]         */
  638                                 imp_no =
  639                                         ((int) (x25addr[6] & 0x0f) * 100) +
  640                                         ((int) (x25addr[7] & 0x0f) * 10) +
  641                                         ((int) (x25addr[8] & 0x0f));
  642 
  643 
  644                                 imp_port =
  645                                         ((int) (x25addr[9] & 0x0f) * 10) +
  646                                         ((int) (x25addr[10] & 0x0f));
  647                                 break;
  648                         case 1:/* Logical:   0000 1 RRRRR00 [SS]         */
  649                                 temp = ((int) (x25addr[6] & 0x0f) * 10000)
  650                                         + ((int) (x25addr[7] & 0x0f) * 1000)
  651                                         + ((int) (x25addr[8] & 0x0f) * 100)
  652                                         + ((int) (x25addr[9] & 0x0f) * 10)
  653                                         + ((int) (x25addr[10] & 0x0f));
  654 
  655                                 imp_port = temp >> 8;
  656                                 imp_no = temp & 0xff;
  657                                 break;
  658                         default:
  659                                 return;
  660                         }
  661                         imp_addr.ip = my_addr;
  662                         if ((imp_addr.imp.s_net & 0x80) == 0x00) {
  663                                 /* class A */
  664                                 imp_addr.imp.s_host = imp_port;
  665                                 imp_addr.imp.s_impno = imp_no;
  666                                 imp_addr.imp.s_lh = 0;
  667                         } else if ((imp_addr.imp.s_net & 0xc0) == 0x80) {
  668                                 /* class B */
  669                                 imp_addr.imp.s_lh = imp_port;
  670                                 imp_addr.imp.s_impno = imp_no;
  671                         } else {
  672                                 /* class C */
  673                                 imp_addr.imp.s_impno = (imp_no << 5) + imp_port;
  674                         }
  675                 }
  676                 sin.sin_addr = imp_addr.ip;
  677                 sa = (struct sockaddr *) & sin;
  678         } else {
  679                 /*
  680                  * This uses the X25 routing table to do inverse
  681                  * lookup of x25 address to sockaddr.
  682                  */
  683                 if ((rt = rtalloc1(SA(dst), 0)) != NULL) {
  684                         sa = rt->rt_gateway;
  685                         rt->rt_refcnt--;
  686                 }
  687         }
  688         /*
  689          * Call to rtalloc1 will create rtentry for reverse path to callee by
  690          * virtue of cloning magic and will allocate space for local control
  691          * block.
  692          */
  693         if (sa && (rt = rtalloc1(sa, 1)))
  694                 rt->rt_refcnt--;
  695 }
  696 
  697 
  698 int x25_startproto = 1;
  699 struct pklcdhead pk_listenhead;
  700 
  701 void
  702 pk_init()
  703 {
  704         TAILQ_INIT(&pk_listenhead);
  705         if (x25_startproto) {
  706                 pk_protolisten(0xcc, 1, x25_dgram_incoming);
  707                 pk_protolisten(0x81, 1, x25_dgram_incoming);
  708         }
  709 }
  710 
  711 struct x25_dgproto {
  712         u_char          spi;
  713         u_char          spilen;
  714         int             (*f) __P((struct mbuf *, void *));
  715 } x25_dgprototab[] = {
  716 #if defined(ISO) && defined(TPCONS)
  717         { 0x0, 0, tp_incoming },
  718 #endif
  719         { 0xcc, 1, x25_dgram_incoming },
  720         { 0xcd, 1, x25_dgram_incoming },
  721         { 0x81, 1, x25_dgram_incoming },
  722 };
  723 
  724 int
  725 pk_user_protolisten(info)
  726         u_char *info;
  727 {
  728         struct x25_dgproto *dp = x25_dgprototab
  729         + ((sizeof x25_dgprototab) / (sizeof *dp));
  730         struct pklcd *lcp;
  731 
  732         while (dp > x25_dgprototab)
  733                 if ((--dp)->spi == info[0])
  734                         goto gotspi;
  735         return ESRCH;
  736 
  737 gotspi:if (info[1])
  738                 return pk_protolisten(dp->spi, dp->spilen, dp->f);
  739         for (lcp = pk_listenhead.tqh_first; lcp; lcp = lcp->lcd_listen.tqe_next)
  740                 if (lcp->lcd_laddr.x25_udlen == dp->spilen &&
  741                 Bcmp(&dp->spi, lcp->lcd_laddr.x25_udata, dp->spilen) == 0) {
  742                         pk_disconnect(lcp);
  743                         return 0;
  744                 }
  745         return ESRCH;
  746 }
  747 
  748 /*
  749  * This routine transfers an X.25 circuit to or from a routing entry.
  750  * If the supplied circuit is * in DATA_TRANSFER state, it is added to the
  751  * routing entry.  If freshly allocated, it glues back the vc from
  752  * the rtentry to the socket.
  753  */
  754 int
  755 pk_rtattach(so, m0)
  756         struct socket *so;
  757         struct mbuf    *m0;
  758 {
  759         struct pklcd *lcp = (struct pklcd *) so->so_pcb;
  760         struct mbuf *m = m0;
  761         struct sockaddr *dst = mtod(m, struct sockaddr *);
  762         struct rtentry *rt = rtalloc1(dst, 0);
  763         struct llinfo_x25 *lx;
  764         caddr_t         cp;
  765 #define ROUNDUP(a) \
  766         ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
  767 #define transfer_sockbuf(s, f, l) \
  768         while ((m = (s)->sb_mb) != NULL) \
  769                 { \
  770                         (s)->sb_mb = m->m_nextpkt; \
  771                         SB_EMPTY_FIXUP((s)); \
  772                         m->m_nextpkt = 0; \
  773                         sbfree((s), m); \
  774                         f; \
  775                 }
  776 
  777         if (rt)
  778                 rt->rt_refcnt--;
  779         cp = (dst->sa_len < m->m_len) ? ROUNDUP(dst->sa_len) + (caddr_t) dst : 0;
  780         while (rt &&
  781                ((cp == 0 && rt_mask(rt) != 0) ||
  782                 (cp != 0 && (rt_mask(rt) == 0 ||
  783                          Bcmp(cp, rt_mask(rt), rt_mask(rt)->sa_len)) != 0)))
  784                 rt = (struct rtentry *) rt->rt_nodes->rn_dupedkey;
  785         if (rt == 0 || (rt->rt_flags & RTF_GATEWAY) ||
  786             (lx = (struct llinfo_x25 *) rt->rt_llinfo) == 0)
  787                 return ESRCH;
  788         if (lcp == 0)
  789                 return ENOTCONN;
  790         switch (lcp->lcd_state) {
  791         default:
  792                 return ENOTCONN;
  793 
  794         case READY:
  795                 /* Detach VC from rtentry */
  796                 if (lx->lx_lcd == 0)
  797                         return ENOTCONN;
  798                 lcp->lcd_so = 0;
  799                 pk_close(lcp);
  800                 lcp = lx->lx_lcd;
  801                 if (lx->lx_list.le_next->lx_rt == rt)
  802                         x25_lxfree(lx);
  803                 lcp->lcd_so = so;
  804                 lcp->lcd_upper = 0;
  805                 lcp->lcd_upnext = 0;
  806                 transfer_sockbuf(&lcp->lcd_sb, sbappendrecord(&so->so_snd, m),
  807                                  &so->so_snd);
  808                 soisconnected(so);
  809                 return 0;
  810 
  811         case DATA_TRANSFER:
  812                 /* Add VC to rtentry */
  813                 lcp->lcd_so = 0;
  814                 lcp->lcd_sb = so->so_snd;       /* structure copy */
  815                 bzero((caddr_t) & so->so_snd, sizeof(so->so_snd));      /* XXXXXX */
  816                 so->so_pcb = 0;
  817                 x25_rtattach(lcp, rt);
  818                 transfer_sockbuf(&so->so_rcv, x25_ifinput(m, lcp), lcp);
  819                 soisdisconnected(so);
  820         }
  821         return 0;
  822 }
  823 
  824 int
  825 x25_rtattach(lcp0, rt)
  826         struct pklcd *lcp0;
  827         struct rtentry *rt;
  828 {
  829         struct llinfo_x25 *lx = (struct llinfo_x25 *) rt->rt_llinfo;
  830         struct pklcd *lcp;
  831         struct mbuf *m;
  832         if ((lcp = lx->lx_lcd) != NULL) {       /* adding an additional VC */
  833                 if (lcp->lcd_state == READY) {
  834                         transfer_sockbuf(&lcp->lcd_sb, pk_output(lcp0), lcp0);
  835                         lcp->lcd_upper = 0;
  836                         pk_close(lcp);
  837                 } else {
  838                         lx = x25_lxalloc(rt);
  839                         if (lx == 0)
  840                                 return ENOBUFS;
  841                 }
  842         }
  843         lx->lx_lcd = lcp = lcp0;
  844         lcp->lcd_upper = x25_ifinput;
  845         lcp->lcd_upnext = (caddr_t) lx;
  846         return 0;
  847 }

Cache object: c471e8f72269a28043346ac50154c5cf


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.