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/netiso/iso.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: iso.c,v 1.35 2004/04/19 05:16:45 matt Exp $    */
    2 
    3 /*-
    4  * Copyright (c) 1991, 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  *      @(#)iso.c       8.3 (Berkeley) 1/9/95
   32  */
   33 
   34 /***********************************************************
   35                 Copyright IBM Corporation 1987
   36 
   37                       All Rights Reserved
   38 
   39 Permission to use, copy, modify, and distribute this software and its
   40 documentation for any purpose and without fee is hereby granted,
   41 provided that the above copyright notice appear in all copies and that
   42 both that copyright notice and this permission notice appear in
   43 supporting documentation, and that the name of IBM not be
   44 used in advertising or publicity pertaining to distribution of the
   45 software without specific, written prior permission.
   46 
   47 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
   48 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
   49 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
   50 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
   51 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
   52 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
   53 SOFTWARE.
   54 
   55 ******************************************************************/
   56 
   57 /*
   58  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
   59  */
   60 /*
   61  * iso.c: miscellaneous routines to support the iso address family
   62  */
   63 
   64 #include <sys/cdefs.h>
   65 __KERNEL_RCSID(0, "$NetBSD: iso.c,v 1.35 2004/04/19 05:16:45 matt Exp $");
   66 
   67 #include <sys/param.h>
   68 #include <sys/systm.h>
   69 #include <sys/ioctl.h>
   70 #include <sys/mbuf.h>
   71 #include <sys/domain.h>
   72 #include <sys/protosw.h>
   73 #include <sys/socket.h>
   74 #include <sys/socketvar.h>
   75 #include <sys/errno.h>
   76 #include <sys/proc.h>
   77 
   78 #include <net/if.h>
   79 #include <net/if_types.h>
   80 #include <net/route.h>
   81 
   82 #include <netiso/iso.h>
   83 #include <netiso/iso_var.h>
   84 #include <netiso/iso_snpac.h>
   85 #include <netiso/iso_pcb.h>
   86 #include <netiso/clnp.h>
   87 #include <netiso/argo_debug.h>
   88 
   89 #include "opt_iso.h"
   90 #ifdef ISO
   91 
   92 int             iso_interfaces = 0;     /* number of external interfaces */
   93 
   94 /*
   95  * FUNCTION:            iso_addrmatch1
   96  *
   97  * PURPOSE:             decide if the two iso_addrs passed are equal
   98  *
   99  * RETURNS:             true if the addrs match, false if they do not
  100  *
  101  * SIDE EFFECTS:
  102  *
  103  * NOTES:
  104  */
  105 int
  106 iso_addrmatch1(const struct iso_addr *isoaa, const struct iso_addr *isoab)
  107 {
  108         u_int           compare_len;
  109 
  110 #ifdef ARGO_DEBUG
  111         if (argo_debug[D_ROUTE]) {
  112                 printf("iso_addrmatch1: comparing lengths: %d to %d\n", isoaa->isoa_len,
  113                     isoab->isoa_len);
  114                 printf("a:\n");
  115                 dump_buf(isoaa->isoa_genaddr, isoaa->isoa_len);
  116                 printf("b:\n");
  117                 dump_buf(isoab->isoa_genaddr, isoab->isoa_len);
  118         }
  119 #endif
  120 
  121         if ((compare_len = isoaa->isoa_len) != isoab->isoa_len) {
  122 #ifdef ARGO_DEBUG
  123                 if (argo_debug[D_ROUTE]) {
  124                         printf("iso_addrmatch1: returning false because of lengths\n");
  125                 }
  126 #endif
  127                 return 0;
  128         }
  129 #ifdef notdef
  130         /* TODO : generalize this to all afis with masks */
  131         if (isoaa->isoa_afi == AFI_37) {
  132                 /*
  133                  * must not compare 2 least significant digits, or for that
  134                  * matter, the DSP
  135                  */
  136                 compare_len = ADDR37_IDI_LEN - 1;
  137         }
  138 #endif
  139 
  140 #ifdef ARGO_DEBUG
  141         if (argo_debug[D_ROUTE]) {
  142                 int             i;
  143                 const char           *a, *b;
  144 
  145                 a = isoaa->isoa_genaddr;
  146                 b = isoab->isoa_genaddr;
  147 
  148                 for (i = 0; i < compare_len; i++) {
  149                         printf("<%x=%x>", a[i] & 0xff, b[i] & 0xff);
  150                         if (a[i] != b[i]) {
  151                                 printf("\naddrs are not equal at byte %d\n", i);
  152                                 return (0);
  153                         }
  154                 }
  155                 printf("\n");
  156                 printf("addrs are equal\n");
  157                 return (1);
  158         }
  159 #endif
  160         return (!bcmp(isoaa->isoa_genaddr, isoab->isoa_genaddr, compare_len));
  161 }
  162 
  163 /*
  164  * FUNCTION:            iso_addrmatch
  165  *
  166  * PURPOSE:             decide if the two sockadrr_isos passed are equal
  167  *
  168  * RETURNS:             true if the addrs match, false if they do not
  169  *
  170  * SIDE EFFECTS:
  171  *
  172  * NOTES:
  173  */
  174 int
  175 iso_addrmatch(const struct sockaddr_iso *sisoa,
  176         const struct sockaddr_iso *sisob)
  177 {
  178         return (iso_addrmatch1(&sisoa->siso_addr, &sisob->siso_addr));
  179 }
  180 #ifdef notdef
  181 /*
  182  * FUNCTION:            iso_netmatch
  183  *
  184  * PURPOSE:             similar to iso_addrmatch but takes sockaddr_iso
  185  *                      as argument.
  186  *
  187  * RETURNS:             true if same net, false if not
  188  *
  189  * SIDE EFFECTS:
  190  *
  191  * NOTES:
  192  */
  193 int
  194 iso_netmatch(const struct sockaddr_iso *sisoa,
  195         const struct sockaddr_iso *sisob)
  196 {
  197         u_char          bufa[sizeof(struct sockaddr_iso)];
  198         u_char          bufb[sizeof(struct sockaddr_iso)];
  199         int    lena, lenb;
  200 
  201         lena = iso_netof(&sisoa->siso_addr, bufa);
  202         lenb = iso_netof(&sisob->siso_addr, bufb);
  203 
  204 #ifdef ARGO_DEBUG
  205         if (argo_debug[D_ROUTE]) {
  206                 printf("iso_netmatch: comparing lengths: %d to %d\n", lena, lenb);
  207                 printf("a:\n");
  208                 dump_buf(bufa, lena);
  209                 printf("b:\n");
  210                 dump_buf(bufb, lenb);
  211         }
  212 #endif
  213 
  214         return ((lena == lenb) && (!bcmp(bufa, bufb, lena)));
  215 }
  216 #endif /* notdef */
  217 
  218 /*
  219  * FUNCTION:            iso_hashchar
  220  *
  221  * PURPOSE:             Hash all character in the buffer specified into
  222  *                      a long. Return the long.
  223  *
  224  * RETURNS:             The hash value.
  225  *
  226  * SIDE EFFECTS:
  227  *
  228  * NOTES:               The hash is achieved by exclusive ORing 4 byte
  229  *                      quantities.
  230  */
  231 u_long
  232 iso_hashchar(caddr_t buf, int len)
  233 {
  234         u_long h = 0;
  235         int    i;
  236 
  237         for (i = 0; i < len; i += 4) {
  238                 u_long l = 0;
  239 
  240                 if ((len - i) < 4) {
  241                         /* buffer not multiple of 4 */
  242                         switch (len - i) {
  243                         case 3:
  244                                 l |= buf[i + 2] << 8;
  245                         case 2:
  246                                 l |= buf[i + 1] << 16;
  247                         case 1:
  248                                 l |= buf[i] << 24;
  249                                 break;
  250                         default:
  251                                 printf("iso_hashchar: unexpected value x%x\n", len - i);
  252                                 break;
  253                         }
  254                 } else {
  255                         l |= buf[i] << 24;
  256                         l |= buf[i + 1] << 16;
  257                         l |= buf[i + 2] << 8;
  258                         l |= buf[i + 3];
  259                 }
  260 
  261                 h ^= l;
  262         }
  263 
  264         h ^= (u_long) (len % 4);
  265 
  266         return (h);
  267 }
  268 
  269 #ifdef notdef
  270 /*
  271  * FUNCTION:            iso_hash
  272  *
  273  * PURPOSE:             Fill in fields of afhash structure based upon addr
  274  *                      passed.
  275  *
  276  * RETURNS:             none
  277  *
  278  * SIDE EFFECTS:
  279  *
  280  * NOTES:
  281  */
  282 void
  283 iso_hash(
  284         struct sockaddr_iso *siso,      /* address to perform hash on */
  285         struct afhash  *hp)     /* RETURN: hash info here */
  286 {
  287         u_long buf[sizeof(struct sockaddr_iso) / 4 + 1];
  288         int    bufsize;
  289 
  290 
  291         bzero(buf, sizeof(buf));
  292 
  293         bufsize = iso_netof(&siso->siso_addr, buf);
  294         hp->afh_nethash = iso_hashchar((caddr_t) buf, bufsize);
  295 
  296 #ifdef ARGO_DEBUG
  297         if (argo_debug[D_ROUTE]) {
  298                 printf("iso_hash: iso_netof: bufsize = %d\n", bufsize);
  299         }
  300 #endif
  301 
  302         hp->afh_hosthash = iso_hashchar((caddr_t) & siso->siso_addr,
  303                                         siso->siso_addr.isoa_len);
  304 
  305 #ifdef ARGO_DEBUG
  306         if (argo_debug[D_ROUTE]) {
  307                 printf("iso_hash: %s: nethash = x%x, hosthash = x%x\n",
  308                     clnp_iso_addrp(&siso->siso_addr), hp->afh_nethash,
  309                     hp->afh_hosthash);
  310         }
  311 #endif
  312 }
  313 /*
  314  * FUNCTION:            iso_netof
  315  *
  316  * PURPOSE:             Extract the network portion of the iso address.
  317  *                      The network portion of the iso address varies depending
  318  *                      on the type of address. The network portion of the
  319  *                      address will include the IDP. The network portion is:
  320  *
  321  *                      TYPE                    DESC
  322  *                      t37                     The AFI and x.121 (IDI)
  323  *                      osinet                  The AFI, orgid, snetid
  324  *                      rfc986                  The AFI, vers and network part
  325  *                                              of internet address.
  326  *
  327  * RETURNS:             number of bytes placed into buf.
  328  *
  329  * SIDE EFFECTS:
  330  *
  331  * NOTES:               Buf is assumed to be big enough
  332  */
  333 u_int
  334 iso_netof(
  335         struct iso_addr *isoa,  /* address */
  336         caddr_t         buf)    /* RESULT: network portion of address here */
  337 {
  338         u_int           len = 1;/* length of afi */
  339 
  340         switch (isoa->isoa_afi) {
  341         case AFI_37:
  342                 /*
  343                  * Due to classic x.25 tunnel vision, there is no
  344                  * net portion of an x.121 address.  For our purposes
  345                  * the AFI will do, so that all x.25 -type addresses
  346                  * map to the single x.25 SNPA. (Cannot have more than
  347                  * one, obviously).
  348                  */
  349 
  350                 break;
  351 
  352                 /* case AFI_OSINET: */
  353         case AFI_RFC986:{
  354                         u_short         idi;    /* value of idi */
  355 
  356                         /* osinet and rfc986 have idi in the same place */
  357                         CTOH(isoa->rfc986_idi[0], isoa->rfc986_idi[1], idi);
  358 
  359                         if (idi == IDI_OSINET)
  360                                 /*
  361                                  * Network portion of OSINET address can only
  362                                  * be the IDI. Clearly, with one x25 interface,
  363                                  * one could get to several orgids, and
  364                                  * several snetids.
  365                                  */
  366 #if 0
  367                                 len += (ADDROSINET_IDI_LEN +
  368                                         OVLOSINET_ORGID_LEN +
  369                                         OVLOSINET_SNETID_LEN);
  370 #endif
  371                                 len += ADDROSINET_IDI_LEN;
  372                         else if (idi == IDI_RFC986) {
  373                                 struct ovl_rfc986 *o986 =
  374                                         (struct ovl_rfc986 *) isoa;
  375 
  376                                 /*
  377                                  * bump len to include idi and version (1
  378                                  * byte)
  379                                  */
  380                                 len += ADDRRFC986_IDI_LEN + 1;
  381 
  382 #ifdef ARGO_DEBUG
  383                                 if (argo_debug[D_ROUTE]) {
  384                                         printf("iso_netof: isoa ");
  385                                         dump_buf(isoa, sizeof(*isoa));
  386                                         printf("iso_netof: inetaddr 0x%x ",
  387                                             inetaddr);
  388                                 }
  389 #endif
  390 
  391                                 /*
  392                                  * bump len by size of network portion of
  393                                  * inet address
  394                                  */
  395                                 if (IN_CLASSA(o986->o986_inetaddr)) {
  396                                         len += 4 - IN_CLASSA_NSHIFT / 8;
  397 #ifdef ARGO_DEBUG
  398                                         if (argo_debug[D_ROUTE]) {
  399                                                 printf("iso_netof: class A net len is now %d\n", len);
  400                                         }
  401 #endif
  402                                 } else if (IN_CLASSB(o986->o986_inetaddr)) {
  403                                         len += 4 - IN_CLASSB_NSHIFT / 8;
  404 #ifdef ARGO_DEBUG
  405                                         if (argo_debug[D_ROUTE]) {
  406                                                 printf("iso_netof: class B net len is now %d\n", len);
  407                                         }
  408 #endif
  409                                 } else {
  410                                         len += 4 - IN_CLASSC_NSHIFT / 8;
  411 #ifdef ARGO_DEBUG
  412                                         if (argo_debug[D_ROUTE]) {
  413                                                 printf("iso_netof: class C net len is now %d\n", len);
  414                                         }
  415 #endif
  416                                 }
  417                         } else
  418                                 len = 0;
  419                 } break;
  420 
  421         default:
  422                 len = 0;
  423         }
  424 
  425         bcopy((caddr_t) isoa, buf, len);
  426 #ifdef ARGO_DEBUG
  427         if (argo_debug[D_ROUTE]) {
  428                 printf("iso_netof: isoa ");
  429                 dump_buf(isoa, len);
  430                 printf("iso_netof: net ");
  431                 dump_buf(buf, len);
  432         }
  433 #endif
  434         return len;
  435 }
  436 #endif                          /* notdef */
  437 /*
  438  * Generic iso control operations (ioctl's).
  439  * Ifp is 0 if not an interface-specific ioctl.
  440  */
  441 /* ARGSUSED */
  442 int
  443 iso_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
  444         struct proc *p)
  445 {
  446         struct iso_ifreq *ifr = (struct iso_ifreq *) data;
  447         struct iso_ifaddr *ia = 0;
  448         struct iso_aliasreq *ifra = (struct iso_aliasreq *) data;
  449         int             error, hostIsNew, maskIsNew;
  450 
  451         /*
  452          * Find address for this interface, if it exists.
  453          */
  454         if (ifp)
  455                 for (ia = iso_ifaddr.tqh_first; ia != 0; ia = ia->ia_list.tqe_next)
  456                         if (ia->ia_ifp == ifp)
  457                                 break;
  458 
  459         switch (cmd) {
  460 
  461         case SIOCAIFADDR_ISO:
  462         case SIOCDIFADDR_ISO:
  463                 if (ifra->ifra_addr.siso_family == AF_ISO)
  464                         for (; ia != 0; ia = ia->ia_list.tqe_next) {
  465                                 if (ia->ia_ifp == ifp &&
  466                                     SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr))
  467                                         break;
  468                         }
  469                 if (cmd == SIOCDIFADDR_ISO && ia == 0)
  470                         return (EADDRNOTAVAIL);
  471                 /* FALLTHROUGH */
  472 #if 0
  473         case SIOCSIFADDR:
  474         case SIOCSIFNETMASK:
  475         case SIOCSIFDSTADDR:
  476 #endif
  477                 if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag)))
  478                         return (EPERM);
  479 
  480                 if (ifp == 0)
  481                         panic("iso_control");
  482                 if (ia == 0) {
  483                         MALLOC(ia, struct iso_ifaddr *, sizeof(*ia),
  484                                M_IFADDR, M_WAITOK|M_ZERO);
  485                         if (ia == 0)
  486                                 return (ENOBUFS);
  487                         TAILQ_INSERT_TAIL(&iso_ifaddr, ia, ia_list);
  488                         IFAREF((struct ifaddr *)ia);
  489                         TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia,
  490                             ifa_list);
  491                         IFAREF((struct ifaddr *)ia);
  492                         ia->ia_ifa.ifa_addr = sisotosa(&ia->ia_addr);
  493                         ia->ia_ifa.ifa_dstaddr = sisotosa(&ia->ia_dstaddr);
  494                         ia->ia_ifa.ifa_netmask = sisotosa(&ia->ia_sockmask);
  495                         ia->ia_ifp = ifp;
  496                         if ((ifp->if_flags & IFF_LOOPBACK) == 0)
  497                                 iso_interfaces++;
  498                 }
  499                 break;
  500 
  501         case SIOCGIFADDR_ISO:
  502         case SIOCGIFNETMASK_ISO:
  503         case SIOCGIFDSTADDR_ISO:
  504                 if (ia == 0)
  505                         return (EADDRNOTAVAIL);
  506                 break;
  507         }
  508         switch (cmd) {
  509 
  510         case SIOCGIFADDR_ISO:
  511                 ifr->ifr_Addr = ia->ia_addr;
  512                 break;
  513 
  514         case SIOCGIFDSTADDR_ISO:
  515                 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
  516                         return (EINVAL);
  517                 ifr->ifr_Addr = ia->ia_dstaddr;
  518                 break;
  519 
  520         case SIOCGIFNETMASK_ISO:
  521                 ifr->ifr_Addr = ia->ia_sockmask;
  522                 break;
  523 
  524         case SIOCAIFADDR_ISO:
  525                 maskIsNew = 0;
  526                 hostIsNew = 1;
  527                 error = 0;
  528                 if (ia->ia_addr.siso_family == AF_ISO) {
  529                         if (ifra->ifra_addr.siso_len == 0) {
  530                                 ifra->ifra_addr = ia->ia_addr;
  531                                 hostIsNew = 0;
  532                         } else if (SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr))
  533                                 hostIsNew = 0;
  534                 }
  535                 if (ifra->ifra_mask.siso_len) {
  536                         iso_ifscrub(ifp, ia);
  537                         ia->ia_sockmask = ifra->ifra_mask;
  538                         maskIsNew = 1;
  539                 }
  540                 if ((ifp->if_flags & IFF_POINTOPOINT) &&
  541                     (ifra->ifra_dstaddr.siso_family == AF_ISO)) {
  542                         iso_ifscrub(ifp, ia);
  543                         ia->ia_dstaddr = ifra->ifra_dstaddr;
  544                         maskIsNew = 1;  /* We lie; but the effect's the same */
  545                 }
  546                 if (ifra->ifra_addr.siso_family == AF_ISO &&
  547                     (hostIsNew || maskIsNew))
  548                         error = iso_ifinit(ifp, ia, &ifra->ifra_addr, 0);
  549                 if (ifra->ifra_snpaoffset)
  550                         ia->ia_snpaoffset = ifra->ifra_snpaoffset;
  551                 return (error);
  552 
  553         case SIOCDIFADDR_ISO:
  554                 iso_purgeaddr(&ia->ia_ifa, ifp);
  555                 break;
  556 
  557 #define cmdbyte(x)      (((x) >> 8) & 0xff)
  558         default:
  559                 if (cmdbyte(cmd) == 'a')
  560                         return (snpac_ioctl(so, cmd, data, p));
  561                 if (ifp == 0 || ifp->if_ioctl == 0)
  562                         return (EOPNOTSUPP);
  563                 return ((*ifp->if_ioctl)(ifp, cmd, data));
  564         }
  565         return (0);
  566 }
  567 
  568 void
  569 iso_purgeaddr(struct ifaddr *ifa, struct ifnet *ifp)
  570 {
  571         struct iso_ifaddr *ia = (void *) ifa;
  572 
  573         iso_ifscrub(ifp, ia);
  574         TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
  575         IFAFREE(&ia->ia_ifa);
  576         TAILQ_REMOVE(&iso_ifaddr, ia, ia_list);
  577         IFAFREE((&ia->ia_ifa));
  578 }
  579 
  580 void
  581 iso_purgeif(struct ifnet *ifp)
  582 {
  583         struct ifaddr *ifa, *nifa;
  584 
  585         for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL; ifa = nifa) {
  586                 nifa = TAILQ_NEXT(ifa, ifa_list);
  587                 if (ifa->ifa_addr->sa_family != AF_ISO)
  588                         continue;
  589                 iso_purgeaddr(ifa, ifp);
  590         }
  591 }
  592 
  593 /*
  594  * Delete any existing route for an interface.
  595  */
  596 void
  597 iso_ifscrub(struct ifnet *ifp, struct iso_ifaddr *ia)
  598 {
  599         int             nsellength = ia->ia_addr.siso_tlen;
  600         if ((ia->ia_flags & IFA_ROUTE) == 0)
  601                 return;
  602         ia->ia_addr.siso_tlen = 0;
  603         if (ifp->if_flags & IFF_LOOPBACK)
  604                 rtinit(&(ia->ia_ifa), (int) RTM_DELETE, RTF_HOST);
  605         else if (ifp->if_flags & IFF_POINTOPOINT)
  606                 rtinit(&(ia->ia_ifa), (int) RTM_DELETE, RTF_HOST);
  607         else {
  608                 rtinit(&(ia->ia_ifa), (int) RTM_DELETE, 0);
  609         }
  610         ia->ia_addr.siso_tlen = nsellength;
  611         ia->ia_flags &= ~IFA_ROUTE;
  612 }
  613 
  614 /*
  615  * Initialize an interface's internet address
  616  * and routing table entry.
  617  */
  618 int
  619 iso_ifinit(struct ifnet *ifp, struct iso_ifaddr *ia, struct sockaddr_iso *siso,
  620         int scrub)
  621 {
  622         struct sockaddr_iso oldaddr;
  623         int             s = splnet(), error, nsellength;
  624 
  625         oldaddr = ia->ia_addr;
  626         ia->ia_addr = *siso;
  627         /*
  628          * Give the interface a chance to initialize
  629          * if this is its first address,
  630          * and to validate the address if necessary.
  631          */
  632         if (ifp->if_ioctl &&
  633             (error = (*ifp->if_ioctl) (ifp, SIOCSIFADDR, (caddr_t) ia))) {
  634                 splx(s);
  635                 ia->ia_addr = oldaddr;
  636                 return (error);
  637         }
  638         if (scrub) {
  639                 ia->ia_ifa.ifa_addr = sisotosa(&oldaddr);
  640                 iso_ifscrub(ifp, ia);
  641                 ia->ia_ifa.ifa_addr = sisotosa(&ia->ia_addr);
  642         }
  643         /*
  644          * XXX -- The following is here temporarily out of laziness in not
  645          * changing every ethernet driver's if_ioctl routine
  646          */
  647         if (ifp->if_type == IFT_ETHER || ifp->if_type == IFT_FDDI) {
  648                 ia->ia_ifa.ifa_rtrequest = llc_rtrequest;
  649                 ia->ia_ifa.ifa_flags |= RTF_CLONING;
  650         }
  651         /*
  652          * Add route for the network.
  653          */
  654         nsellength = ia->ia_addr.siso_tlen;
  655         ia->ia_addr.siso_tlen = 0;
  656         if (ifp->if_flags & IFF_LOOPBACK) {
  657                 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
  658                 error = rtinit(&(ia->ia_ifa), (int) RTM_ADD, RTF_HOST | RTF_UP);
  659         } else if (ifp->if_flags & IFF_POINTOPOINT &&
  660                    ia->ia_dstaddr.siso_family == AF_ISO)
  661                 error = rtinit(&(ia->ia_ifa), (int) RTM_ADD, RTF_HOST | RTF_UP);
  662         else {
  663                 rt_maskedcopy(ia->ia_ifa.ifa_addr, ia->ia_ifa.ifa_dstaddr,
  664                               ia->ia_ifa.ifa_netmask);
  665                 ia->ia_dstaddr.siso_nlen =
  666                         min(ia->ia_addr.siso_nlen, (ia->ia_sockmask.siso_len - 6));
  667                 error = rtinit(&(ia->ia_ifa), (int) RTM_ADD, RTF_UP);
  668         }
  669         ia->ia_addr.siso_tlen = nsellength;
  670         ia->ia_flags |= IFA_ROUTE;
  671         splx(s);
  672         return (error);
  673 }
  674 #ifdef notdef
  675 
  676 struct ifaddr  *
  677 iso_ifwithidi(struct sockaddr *addr)
  678 {
  679         struct ifnet *ifp;
  680         struct ifaddr *ifa;
  681         u_int  af = addr->sa_family;
  682 
  683         if (af != AF_ISO)
  684                 return (0);
  685 #ifdef ARGO_DEBUG
  686         if (argo_debug[D_ROUTE]) {
  687                 printf(">>> iso_ifwithidi addr\n");
  688                 dump_isoaddr(satosiso(addr));
  689                 printf("\n");
  690         }
  691 #endif
  692         for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) {
  693 #ifdef ARGO_DEBUG
  694                 if (argo_debug[D_ROUTE]) {
  695                         printf("iso_ifwithidi ifnet %s\n", ifp->if_name);
  696                 }
  697 #endif
  698                 for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;
  699                      ifa = ifa->ifa_list.tqe_next) {
  700 #ifdef ARGO_DEBUG
  701                         if (argo_debug[D_ROUTE]) {
  702                                 printf("iso_ifwithidi address ");
  703                                 dump_isoaddr(satosiso(ifa->ifa_addr));
  704                         }
  705 #endif
  706                         if (ifa->ifa_addr->sa_family != addr->sa_family)
  707                                 continue;
  708 
  709 #ifdef ARGO_DEBUG
  710                         if (argo_debug[D_ROUTE]) {
  711                                 printf(" af same, args to iso_eqtype:\n");
  712                                 printf("0x%x ", satosiso(ifa->ifa_addr)->siso_addr);
  713                                 printf(" 0x%x\n",
  714                                     &satosiso(addr)->siso_addr));
  715                         }
  716 #endif
  717 
  718                         if (iso_eqtype(&satosiso(ifa->ifa_addr)->siso_addr,
  719                                        &satosiso(addr)->siso_addr)) {
  720 #ifdef ARGO_DEBUG
  721                                 if (argo_debug[D_ROUTE]) {
  722                                         printf("ifa_ifwithidi: ifa found\n");
  723                                 }
  724 #endif
  725                                 return (ifa);
  726                         }
  727 #ifdef ARGO_DEBUG
  728                         if (argo_debug[D_ROUTE]) {
  729                                 printf(" iso_eqtype failed\n");
  730                         }
  731 #endif
  732                 }
  733         }
  734         return ((struct ifaddr *) 0);
  735 }
  736 
  737 #endif                          /* notdef */
  738 /*
  739  * FUNCTION:            iso_ck_addr
  740  *
  741  * PURPOSE:             return true if the iso_addr passed is
  742  *                      within the legal size limit for an iso address.
  743  *
  744  * RETURNS:             true or false
  745  *
  746  * SIDE EFFECTS:
  747  *
  748  */
  749 int
  750 iso_ck_addr(struct iso_addr *isoa)
  751 {
  752         return (isoa->isoa_len <= 20);
  753 
  754 }
  755 
  756 #ifdef notdef
  757 /*
  758  * FUNCTION:            iso_eqtype
  759  *
  760  * PURPOSE:             Determine if two iso addresses are of the same type.
  761  *                      This is flaky.  Really we should consider all type
  762  *                      47 addrs to be the same - but there do exist different
  763  *                      structures for 47 addrs. Gosip adds a 3rd.
  764  *
  765  * RETURNS:             true if the addresses are the same type
  766  *
  767  * SIDE EFFECTS:
  768  *
  769  * NOTES:               By type, I mean rfc986, t37, or osinet
  770  *
  771  *                      This will first compare afis. If they match, then
  772  *                      if the addr is not t37, the idis must be compared.
  773  */
  774 int
  775 iso_eqtype(
  776         struct iso_addr *isoaa, /* first addr to check */
  777         struct iso_addr *isoab) /* other addr to check */
  778 {
  779         if (isoaa->isoa_afi == isoab->isoa_afi) {
  780                 if (isoaa->isoa_afi == AFI_37)
  781                         return (1);
  782                 else
  783                         return (!bcmp(&isoaa->isoa_u, &isoab->isoa_u, 2));
  784         }
  785         return (0);
  786 }
  787 #endif /* notdef */
  788 /*
  789  * FUNCTION:            iso_localifa()
  790  *
  791  * PURPOSE:             Find an interface addresss having a given destination
  792  *                      or at least matching the net.
  793  *
  794  * RETURNS:             ptr to an interface address
  795  *
  796  * SIDE EFFECTS:
  797  *
  798  * NOTES:
  799  */
  800 struct iso_ifaddr *
  801 iso_localifa(struct sockaddr_iso *siso)
  802 {
  803         struct iso_ifaddr *ia;
  804         char  *cp1, *cp2, *cp3;
  805         struct ifnet *ifp;
  806         struct iso_ifaddr *ia_maybe = 0;
  807         /*
  808          * We make one pass looking for both net matches and an exact
  809          * dst addr.
  810          */
  811         for (ia = iso_ifaddr.tqh_first; ia != 0; ia = ia->ia_list.tqe_next) {
  812                 if ((ifp = ia->ia_ifp) == 0 || ((ifp->if_flags & IFF_UP) == 0))
  813                         continue;
  814                 if (ifp->if_flags & IFF_POINTOPOINT) {
  815                         if ((ia->ia_dstaddr.siso_family == AF_ISO) &&
  816                             SAME_ISOADDR(&ia->ia_dstaddr, siso))
  817                                 return (ia);
  818                         else if (SAME_ISOADDR(&ia->ia_addr, siso))
  819                                 ia_maybe = ia;
  820                         continue;
  821                 }
  822                 if (ia->ia_sockmask.siso_len) {
  823                         char *cplim = ia->ia_sockmask.siso_len +
  824                                       (char *) &ia->ia_sockmask;
  825                         cp1 = ia->ia_sockmask.siso_data;
  826                         cp2 = siso->siso_data;
  827                         cp3 = ia->ia_addr.siso_data;
  828                         while (cp1 < cplim)
  829                                 if (*cp1++ & (*cp2++ ^ *cp3++))
  830                                         goto next;
  831                         ia_maybe = ia;
  832                 }
  833                 if (SAME_ISOADDR(&ia->ia_addr, siso))
  834                         return ia;
  835 next:           ;
  836         }
  837         return ia_maybe;
  838 }
  839 
  840 #ifdef  TPCONS
  841 #include <netiso/cons.h>
  842 #endif  /* TPCONS */
  843 /*
  844  * FUNCTION:            iso_nlctloutput
  845  *
  846  * PURPOSE:             Set options at the network level
  847  *
  848  * RETURNS:             E*
  849  *
  850  * SIDE EFFECTS:
  851  *
  852  * NOTES:               This could embody some of the functions of
  853  *                              rclnp_ctloutput and cons_ctloutput.
  854  */
  855 int
  856 iso_nlctloutput(
  857         int             cmd,            /* command:set or get */
  858         int             optname,        /* option of interest */
  859         caddr_t         pcb,            /* nl pcb */
  860         struct mbuf    *m)              /* data for set, buffer for get */
  861 {
  862 #ifdef TPCONS
  863         struct isopcb  *isop = (struct isopcb *) pcb;
  864 #endif
  865         int             error = 0;      /* return value */
  866         caddr_t         data;   /* data for option */
  867         int             data_len;       /* data's length */
  868 
  869 #ifdef ARGO_DEBUG
  870         if (argo_debug[D_ISO]) {
  871                 printf("iso_nlctloutput: cmd %x, opt %x, pcb %p, m %p\n",
  872                     cmd, optname, pcb, m);
  873         }
  874 #endif
  875 
  876         if ((cmd != PRCO_GETOPT) && (cmd != PRCO_SETOPT))
  877                 return (EOPNOTSUPP);
  878 
  879         data = mtod(m, caddr_t);
  880         data_len = (m)->m_len;
  881 
  882 #ifdef ARGO_DEBUG
  883         if (argo_debug[D_ISO]) {
  884                 printf("iso_nlctloutput: data is:\n");
  885                 dump_buf(data, data_len);
  886         }
  887 #endif
  888 
  889         switch (optname) {
  890 
  891 #ifdef  TPCONS
  892         case CONSOPT_X25CRUD:
  893                 if (cmd == PRCO_GETOPT) {
  894                         error = EOPNOTSUPP;
  895                         break;
  896                 }
  897                 if (data_len > MAXX25CRUDLEN) {
  898                         error = EINVAL;
  899                         break;
  900                 }
  901 #ifdef ARGO_DEBUG
  902                 if (argo_debug[D_ISO]) {
  903                         printf("iso_nlctloutput: setting x25 crud\n");
  904                 }
  905 #endif
  906 
  907                 bcopy(data, (caddr_t) isop->isop_x25crud, (unsigned) data_len);
  908                 isop->isop_x25crud_len = data_len;
  909                 break;
  910 #endif                          /* TPCONS */
  911 
  912         default:
  913                 error = EOPNOTSUPP;
  914         }
  915         if (cmd == PRCO_SETOPT)
  916                 m_freem(m);
  917         return error;
  918 }
  919 #endif /* ISO */
  920 
  921 #ifdef ARGO_DEBUG
  922 
  923 /*
  924  * FUNCTION:            dump_isoaddr
  925  *
  926  * PURPOSE:             debugging
  927  *
  928  * RETURNS:             nada
  929  *
  930  */
  931 void
  932 dump_isoaddr(struct sockaddr_iso *s)
  933 {
  934         if (s->siso_family == AF_ISO) {
  935                 printf("ISO address: suffixlen %d, %s\n",
  936                        s->siso_tlen, clnp_saddr_isop(s));
  937         } else if (s->siso_family == AF_INET) {
  938                 /* hack */
  939                 struct sockaddr_in *sin = satosin(s);
  940 
  941                 printf("%d.%d.%d.%d: %d",
  942                        (sin->sin_addr.s_addr >> 24) & 0xff,
  943                        (sin->sin_addr.s_addr >> 16) & 0xff,
  944                        (sin->sin_addr.s_addr >> 8) & 0xff,
  945                        (sin->sin_addr.s_addr) & 0xff,
  946                        sin->sin_port);
  947         }
  948 }
  949 
  950 #endif /* ARGO_DEBUG */

Cache object: f662a867d1b94a87d6a8019d298965b2


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