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

Cache object: 00f4376553fed427006a3814255d1c3f


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