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

Cache object: 6d8b50947c961607824e71b34856ce45


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