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

Cache object: 77fa461b00423a27f64222084be43e51


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