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

Cache object: c148883bf848f31d701a5f72a1a74766


[ 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.