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/altq/altq_afmap.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: altq_afmap.c,v 1.8 2005/02/26 23:04:16 perry Exp $     */
    2 /*      $KAME: altq_afmap.c,v 1.7 2000/12/14 08:12:45 thorpej Exp $     */
    3 
    4 /*
    5  * Copyright (C) 1997-2000
    6  *      Sony Computer Science Laboratories Inc.  All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 /*
   31  * experimental:
   32  * mapping an ip flow to atm vpi/vci.
   33  * this module is not related to queueing at all, but uses the altq
   34  * flowinfo mechanism.  it's just put in the altq framework since
   35  * it is easy to add devices to altq.
   36  */
   37 
   38 #include <sys/cdefs.h>
   39 __KERNEL_RCSID(0, "$NetBSD: altq_afmap.c,v 1.8 2005/02/26 23:04:16 perry Exp $");
   40 
   41 #ifdef _KERNEL_OPT
   42 #include "opt_altq.h"
   43 #include "opt_inet.h"
   44 #endif
   45 
   46 #include <sys/param.h>
   47 #include <sys/malloc.h>
   48 #include <sys/mbuf.h>
   49 #include <sys/uio.h>
   50 #include <sys/socket.h>
   51 #include <sys/systm.h>
   52 #include <sys/proc.h>
   53 #include <sys/errno.h>
   54 #include <sys/time.h>
   55 #include <sys/kernel.h>
   56 
   57 #include <net/if.h>
   58 #include <net/if_types.h>
   59 #include <netinet/in.h>
   60 
   61 #include <altq/altq.h>
   62 #include <altq/altq_conf.h>
   63 #include <altq/altq_afmap.h>
   64 
   65 LIST_HEAD(, afm_head) afhead_chain;
   66 
   67 static struct afm *afm_match4 __P((struct afm_head *, struct flowinfo_in *));
   68 #ifdef INET6
   69 static struct afm *afm_match6 __P((struct afm_head *, struct flowinfo_in6 *));
   70 #endif
   71 
   72 /*
   73  * rules to block interrupts: afm_match can be called from a net
   74  * level interrupt so that other routines handling the lists should
   75  * be called in splnet().
   76  */
   77 int
   78 afm_alloc(ifp)
   79         struct ifnet *ifp;
   80 {
   81         struct afm_head *head;
   82 
   83         MALLOC(head, struct afm_head *, sizeof(struct afm_head),
   84                M_DEVBUF, M_WAITOK);
   85         if (head == NULL)
   86                 panic("afm_alloc: malloc failed!");
   87         (void)memset(head, 0, sizeof(struct afm_head));
   88 
   89         /* initialize per interface afmap list */
   90         LIST_INIT(&head->afh_head);
   91 
   92         head->afh_ifp = ifp;
   93 
   94         /* add this afm_head to the chain */
   95         LIST_INSERT_HEAD(&afhead_chain, head, afh_chain);
   96 
   97         return (0);
   98 }
   99 
  100 int
  101 afm_dealloc(ifp)
  102         struct ifnet *ifp;
  103 {
  104         struct afm_head *head;
  105 
  106         for (head = afhead_chain.lh_first; head != NULL;
  107              head = head->afh_chain.le_next)
  108                 if (head->afh_ifp == ifp)
  109                         break;
  110         if (head == NULL)
  111                 return (-1);
  112 
  113         afm_removeall(ifp);
  114 
  115         LIST_REMOVE(head, afh_chain);
  116 
  117         FREE(head, M_DEVBUF);
  118         return 0;
  119 }
  120 
  121 struct afm *
  122 afm_top(ifp)
  123         struct ifnet *ifp;
  124 {
  125         struct afm_head *head;
  126 
  127         for (head = afhead_chain.lh_first; head != NULL;
  128              head = head->afh_chain.le_next)
  129                 if (head->afh_ifp == ifp)
  130                         break;
  131         if (head == NULL)
  132                 return NULL;
  133 
  134         return (head->afh_head.lh_first);
  135 }
  136 
  137 int afm_add(ifp, flowmap)
  138         struct ifnet *ifp;
  139         struct atm_flowmap *flowmap;
  140 {
  141         struct afm_head *head;
  142         struct afm *afm;
  143 
  144         for (head = afhead_chain.lh_first; head != NULL;
  145              head = head->afh_chain.le_next)
  146                 if (head->afh_ifp == ifp)
  147                         break;
  148         if (head == NULL)
  149                 return (-1);
  150 
  151         if (flowmap->af_flowinfo.fi_family == AF_INET) {
  152                 if (flowmap->af_flowinfo.fi_len != sizeof(struct flowinfo_in))
  153                         return (EINVAL);
  154 #ifdef INET6
  155         } else if (flowmap->af_flowinfo.fi_family == AF_INET6) {
  156                 if (flowmap->af_flowinfo.fi_len != sizeof(struct flowinfo_in6))
  157                         return (EINVAL);
  158 #endif
  159         } else
  160                 return (EINVAL);
  161 
  162         MALLOC(afm, struct afm *, sizeof(struct afm),
  163                M_DEVBUF, M_WAITOK);
  164         if (afm == NULL)
  165                 return (ENOMEM);
  166         (void)memset(afm, 0, sizeof(struct afm));
  167 
  168         afm->afm_vci = flowmap->af_vci;
  169         afm->afm_vpi = flowmap->af_vpi;
  170         (void)memcpy(&afm->afm_flowinfo, &flowmap->af_flowinfo,
  171               flowmap->af_flowinfo.fi_len);
  172 
  173         LIST_INSERT_HEAD(&head->afh_head, afm, afm_list);
  174         return 0;
  175 }
  176 
  177 int
  178 afm_remove(afm)
  179         struct afm *afm;
  180 {
  181         LIST_REMOVE(afm, afm_list);
  182         FREE(afm, M_DEVBUF);
  183         return (0);
  184 }
  185 
  186 int
  187 afm_removeall(ifp)
  188         struct ifnet *ifp;
  189 {
  190         struct afm_head *head;
  191         struct afm *afm;
  192 
  193         for (head = afhead_chain.lh_first; head != NULL;
  194              head = head->afh_chain.le_next)
  195                 if (head->afh_ifp == ifp)
  196                         break;
  197         if (head == NULL)
  198                 return (-1);
  199 
  200         while ((afm = head->afh_head.lh_first) != NULL)
  201                 afm_remove(afm);
  202         return (0);
  203 }
  204 
  205 struct afm *
  206 afm_lookup(ifp, vpi, vci)
  207         struct ifnet *ifp;
  208         int vpi, vci;
  209 {
  210         struct afm_head *head;
  211         struct afm *afm;
  212 
  213         for (head = afhead_chain.lh_first; head != NULL;
  214              head = head->afh_chain.le_next)
  215                 if (head->afh_ifp == ifp)
  216                         break;
  217         if (head == NULL)
  218                 return NULL;
  219 
  220         for (afm = head->afh_head.lh_first; afm != NULL;
  221              afm = afm->afm_list.le_next)
  222                 if (afm->afm_vpi == vpi && afm->afm_vci == vci)
  223                         break;
  224         return afm;
  225 }
  226 
  227 static struct afm *
  228 afm_match4(head, fp)
  229         struct afm_head *head;
  230         struct flowinfo_in *fp;
  231 {
  232         struct afm *afm;
  233 
  234         for (afm = head->afh_head.lh_first; afm != NULL;
  235              afm = afm->afm_list.le_next) {
  236                 if (afm->afm_flowinfo4.fi_dst.s_addr != 0 &&
  237                     afm->afm_flowinfo4.fi_dst.s_addr != fp->fi_dst.s_addr)
  238                         continue;
  239                 if (afm->afm_flowinfo4.fi_dport != 0 &&
  240                     afm->afm_flowinfo4.fi_dport != fp->fi_dport)
  241                         continue;
  242                 if (afm->afm_flowinfo4.fi_src.s_addr != 0 &&
  243                     afm->afm_flowinfo4.fi_src.s_addr != fp->fi_src.s_addr)
  244                         continue;
  245                 if (afm->afm_flowinfo4.fi_sport != 0 &&
  246                     afm->afm_flowinfo4.fi_sport != fp->fi_sport)
  247                         continue;
  248                 if (afm->afm_flowinfo4.fi_proto != 0 &&
  249                     afm->afm_flowinfo4.fi_proto != fp->fi_proto)
  250                         continue;
  251                 /* match found! */
  252                 return (afm);
  253         }
  254         return NULL;
  255 }
  256 
  257 #ifdef INET6
  258 static struct afm *
  259 afm_match6(head, fp)
  260         struct afm_head *head;
  261         struct flowinfo_in6 *fp;
  262 {
  263         struct afm *afm;
  264 
  265         for (afm = head->afh_head.lh_first; afm != NULL;
  266              afm = afm->afm_list.le_next) {
  267                 if (afm->afm_flowinfo6.fi6_flowlabel != 0 &&
  268                     afm->afm_flowinfo6.fi6_flowlabel != fp->fi6_flowlabel)
  269                         continue;
  270 #ifdef notyet
  271                 if (!IN6_IS_ADDR_UNSPECIFIED(&afm->afm_flowinfo6.fi6_dst) &&
  272                     !IN6_ARE_ADDR_EQUAL(&afm->afm_flowinfo6.fi6_dst,
  273                                         &fp->fi6_dst))
  274                         continue;
  275                 if (afm->afm_flowinfo6.fi6_dport != 0 &&
  276                     afm->afm_flowinfo6.fi6_dport != fp->fi6_dport)
  277                         continue;
  278 #endif
  279                 if (!IN6_IS_ADDR_UNSPECIFIED(&afm->afm_flowinfo6.fi6_src) &&
  280                     !IN6_ARE_ADDR_EQUAL(&afm->afm_flowinfo6.fi6_src,
  281                                         &fp->fi6_src))
  282                         continue;
  283 #ifdef notyet
  284                 if (afm->afm_flowinfo6.fi6_sport != 0 &&
  285                     afm->afm_flowinfo6.fi6_sport != fp->fi6_sport)
  286                         continue;
  287 #endif
  288                 if (afm->afm_flowinfo6.fi6_proto != 0 &&
  289                     afm->afm_flowinfo6.fi6_proto != fp->fi6_proto)
  290                         continue;
  291                 /* match found! */
  292                 return (afm);
  293         }
  294         return NULL;
  295 }
  296 #endif
  297 
  298 /* should be called in splnet() */
  299 struct afm *
  300 afm_match(ifp, flow)
  301         struct ifnet *ifp;
  302         struct flowinfo *flow;
  303 {
  304         struct afm_head *head;
  305 
  306         for (head = afhead_chain.lh_first; head != NULL;
  307              head = head->afh_chain.le_next)
  308                 if (head->afh_ifp == ifp)
  309                         break;
  310         if (head == NULL)
  311                 return NULL;
  312 
  313         switch (flow->fi_family) {
  314         case AF_INET:
  315                 return (afm_match4(head, (struct flowinfo_in *)flow));
  316 
  317 #ifdef INET6
  318         case AF_INET6:
  319                 return (afm_match6(head, (struct flowinfo_in6 *)flow));
  320 #endif
  321 
  322         default:
  323                 return NULL;
  324         }
  325 }
  326 
  327 /*
  328  * afm device interface
  329  */
  330 altqdev_decl(afm);
  331 
  332 int
  333 afmopen(dev, flag, fmt, p)
  334         dev_t dev;
  335         int flag, fmt;
  336         struct proc *p;
  337 {
  338         return 0;
  339 }
  340 
  341 int
  342 afmclose(dev, flag, fmt, p)
  343         dev_t dev;
  344         int flag, fmt;
  345         struct proc *p;
  346 {
  347         int err, error = 0;
  348         struct atm_flowmap fmap;
  349         struct afm_head *head;
  350 
  351         for (head = afhead_chain.lh_first; head != NULL;
  352              head = head->afh_chain.le_next) {
  353 
  354                 /* call interface to clean up maps */
  355 #if defined(__NetBSD__) || defined(__OpenBSD__)
  356                 sprintf(fmap.af_ifname, "%s", head->afh_ifp->if_xname);
  357 #else
  358                 sprintf(fmap.af_ifname, "%s%d",
  359                         head->afh_ifp->if_name, head->afh_ifp->if_unit);
  360 #endif
  361                 err = afmioctl(dev, AFM_CLEANFMAP, (caddr_t)&fmap, flag, p);
  362                 if (err && error == 0)
  363                         error = err;
  364         }
  365 
  366         return error;
  367 }
  368 
  369 int
  370 afmioctl(dev, cmd, addr, flag, p)
  371         dev_t dev;
  372         ioctlcmd_t cmd;
  373         caddr_t addr;
  374         int flag;
  375         struct proc *p;
  376 {
  377         int     error = 0;
  378         struct atm_flowmap *flowmap;
  379         struct ifnet *ifp;
  380 
  381         /* check cmd for superuser only */
  382         switch (cmd) {
  383         case AFM_GETFMAP:
  384                 break;
  385         default:
  386 #if (__FreeBSD_version > 400000)
  387                 error = suser(p);
  388 #else
  389                 error = suser(p->p_ucred, &p->p_acflag);
  390 #endif
  391                 if (error)
  392                         return (error);
  393                 break;
  394         }
  395 
  396         /* lookup interface */
  397         flowmap = (struct atm_flowmap *)addr;
  398         flowmap->af_ifname[IFNAMSIZ-1] = '\0';
  399         ifp = ifunit(flowmap->af_ifname);
  400         if (ifp == NULL || ifp->if_ioctl == NULL ||
  401             (ifp->if_flags & IFF_RUNNING) == 0)
  402                 error = ENXIO;
  403         else
  404                 error = ifp->if_ioctl(ifp, cmd, addr);
  405 
  406         return error;
  407 }

Cache object: 408d1bf8009bd66ab28c6e5c2a4405ce


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