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.23 2021/12/31 14:25:47 riastradh Exp $        */
    2 /*      $KAME: altq_afmap.c,v 1.12 2005/04/13 03:44:24 suz Exp $        */
    3 
    4 /*
    5  * Copyright (C) 1997-2002
    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.23 2021/12/31 14:25:47 riastradh Exp $");
   40 
   41 #ifdef _KERNEL_OPT
   42 #include "opt_altq.h"
   43 #include "opt_inet.h"
   44 #endif
   45 
   46 #ifdef ALTQ_AFMAP
   47 
   48 #include <sys/param.h>
   49 #include <sys/malloc.h>
   50 #include <sys/mbuf.h>
   51 #include <sys/uio.h>
   52 #include <sys/socket.h>
   53 #include <sys/systm.h>
   54 #include <sys/proc.h>
   55 #include <sys/errno.h>
   56 #include <sys/time.h>
   57 #include <sys/kernel.h>
   58 #include <sys/kauth.h>
   59 
   60 #include <net/if.h>
   61 #include <net/if_types.h>
   62 #include <netinet/in.h>
   63 
   64 #include <altq/altq.h>
   65 #include <altq/altq_conf.h>
   66 #include <altq/altq_afmap.h>
   67 
   68 #ifdef ALTQ3_COMPAT
   69 
   70 LIST_HEAD(, afm_head) afhead_chain;
   71 
   72 static struct afm *afm_match4(struct afm_head *, struct flowinfo_in *);
   73 #ifdef INET6
   74 static struct afm *afm_match6(struct afm_head *, struct flowinfo_in6 *);
   75 #endif
   76 
   77 /*
   78  * rules to block interrupts: afm_match can be called from a net
   79  * level interrupt so that other routines handling the lists should
   80  * be called in splnet().
   81  */
   82 int
   83 afm_alloc(struct ifnet *ifp)
   84 {
   85         struct afm_head *head;
   86 
   87         head = malloc(sizeof(struct afm_head), M_DEVBUF, M_WAITOK|M_ZERO);
   88         if (head == NULL)
   89                 panic("afm_alloc: malloc failed!");
   90 
   91         /* initialize per interface afmap list */
   92         LIST_INIT(&head->afh_head);
   93 
   94         head->afh_ifp = ifp;
   95 
   96         /* add this afm_head to the chain */
   97         LIST_INSERT_HEAD(&afhead_chain, head, afh_chain);
   98 
   99         return (0);
  100 }
  101 
  102 int
  103 afm_dealloc(struct ifnet *ifp)
  104 {
  105         struct afm_head *head;
  106 
  107         for (head = afhead_chain.lh_first; head != NULL;
  108              head = head->afh_chain.le_next)
  109                 if (head->afh_ifp == ifp)
  110                         break;
  111         if (head == NULL)
  112                 return (-1);
  113 
  114         afm_removeall(ifp);
  115 
  116         LIST_REMOVE(head, afh_chain);
  117 
  118         free(head, M_DEVBUF);
  119         return 0;
  120 }
  121 
  122 struct afm *
  123 afm_top(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
  138 afm_add(struct ifnet *ifp, struct atm_flowmap *flowmap)
  139 {
  140         struct afm_head *head;
  141         struct afm *afm;
  142 
  143         for (head = afhead_chain.lh_first; head != NULL;
  144              head = head->afh_chain.le_next)
  145                 if (head->afh_ifp == ifp)
  146                         break;
  147         if (head == NULL)
  148                 return (-1);
  149 
  150         if (flowmap->af_flowinfo.fi_family == AF_INET) {
  151                 if (flowmap->af_flowinfo.fi_len != sizeof(struct flowinfo_in))
  152                         return (EINVAL);
  153 #ifdef INET6
  154         } else if (flowmap->af_flowinfo.fi_family == AF_INET6) {
  155                 if (flowmap->af_flowinfo.fi_len != sizeof(struct flowinfo_in6))
  156                         return (EINVAL);
  157 #endif
  158         } else
  159                 return (EINVAL);
  160 
  161         afm = malloc(sizeof(struct afm), M_DEVBUF, M_WAITOK|M_ZERO);
  162         if (afm == NULL)
  163                 return (ENOMEM);
  164 
  165         afm->afm_vci = flowmap->af_vci;
  166         afm->afm_vpi = flowmap->af_vpi;
  167         (void)memcpy(&afm->afm_flowinfo, &flowmap->af_flowinfo,
  168               flowmap->af_flowinfo.fi_len);
  169 
  170         LIST_INSERT_HEAD(&head->afh_head, afm, afm_list);
  171         return 0;
  172 }
  173 
  174 int
  175 afm_remove(struct afm *afm)
  176 {
  177         LIST_REMOVE(afm, afm_list);
  178         free(afm, M_DEVBUF);
  179         return (0);
  180 }
  181 
  182 int
  183 afm_removeall(struct ifnet *ifp)
  184 {
  185         struct afm_head *head;
  186         struct afm *afm;
  187 
  188         for (head = afhead_chain.lh_first; head != NULL;
  189              head = head->afh_chain.le_next)
  190                 if (head->afh_ifp == ifp)
  191                         break;
  192         if (head == NULL)
  193                 return (-1);
  194 
  195         while ((afm = head->afh_head.lh_first) != NULL)
  196                 afm_remove(afm);
  197         return (0);
  198 }
  199 
  200 struct afm *
  201 afm_lookup(struct ifnet *ifp, int vpi, int vci)
  202 {
  203         struct afm_head *head;
  204         struct afm *afm;
  205 
  206         for (head = afhead_chain.lh_first; head != NULL;
  207              head = head->afh_chain.le_next)
  208                 if (head->afh_ifp == ifp)
  209                         break;
  210         if (head == NULL)
  211                 return NULL;
  212 
  213         for (afm = head->afh_head.lh_first; afm != NULL;
  214              afm = afm->afm_list.le_next)
  215                 if (afm->afm_vpi == vpi && afm->afm_vci == vci)
  216                         break;
  217         return afm;
  218 }
  219 
  220 static struct afm *
  221 afm_match4(struct afm_head *head, struct flowinfo_in *fp)
  222 {
  223         struct afm *afm;
  224 
  225         for (afm = head->afh_head.lh_first; afm != NULL;
  226              afm = afm->afm_list.le_next) {
  227                 if (afm->afm_flowinfo4.fi_dst.s_addr != 0 &&
  228                     afm->afm_flowinfo4.fi_dst.s_addr != fp->fi_dst.s_addr)
  229                         continue;
  230                 if (afm->afm_flowinfo4.fi_dport != 0 &&
  231                     afm->afm_flowinfo4.fi_dport != fp->fi_dport)
  232                         continue;
  233                 if (afm->afm_flowinfo4.fi_src.s_addr != 0 &&
  234                     afm->afm_flowinfo4.fi_src.s_addr != fp->fi_src.s_addr)
  235                         continue;
  236                 if (afm->afm_flowinfo4.fi_sport != 0 &&
  237                     afm->afm_flowinfo4.fi_sport != fp->fi_sport)
  238                         continue;
  239                 if (afm->afm_flowinfo4.fi_proto != 0 &&
  240                     afm->afm_flowinfo4.fi_proto != fp->fi_proto)
  241                         continue;
  242                 /* match found! */
  243                 return (afm);
  244         }
  245         return NULL;
  246 }
  247 
  248 #ifdef INET6
  249 static struct afm *
  250 afm_match6(struct afm_head *head, struct flowinfo_in6 *fp)
  251 {
  252         struct afm *afm;
  253 
  254         for (afm = head->afh_head.lh_first; afm != NULL;
  255              afm = afm->afm_list.le_next) {
  256                 if (afm->afm_flowinfo6.fi6_flowlabel != 0 &&
  257                     afm->afm_flowinfo6.fi6_flowlabel != fp->fi6_flowlabel)
  258                         continue;
  259 #ifdef notyet
  260                 if (!IN6_IS_ADDR_UNSPECIFIED(&afm->afm_flowinfo6.fi6_dst) &&
  261                     !IN6_ARE_ADDR_EQUAL(&afm->afm_flowinfo6.fi6_dst,
  262                                         &fp->fi6_dst))
  263                         continue;
  264                 if (afm->afm_flowinfo6.fi6_dport != 0 &&
  265                     afm->afm_flowinfo6.fi6_dport != fp->fi6_dport)
  266                         continue;
  267 #endif
  268                 if (!IN6_IS_ADDR_UNSPECIFIED(&afm->afm_flowinfo6.fi6_src) &&
  269                     !IN6_ARE_ADDR_EQUAL(&afm->afm_flowinfo6.fi6_src,
  270                                         &fp->fi6_src))
  271                         continue;
  272 #ifdef notyet
  273                 if (afm->afm_flowinfo6.fi6_sport != 0 &&
  274                     afm->afm_flowinfo6.fi6_sport != fp->fi6_sport)
  275                         continue;
  276 #endif
  277                 if (afm->afm_flowinfo6.fi6_proto != 0 &&
  278                     afm->afm_flowinfo6.fi6_proto != fp->fi6_proto)
  279                         continue;
  280                 /* match found! */
  281                 return (afm);
  282         }
  283         return NULL;
  284 }
  285 #endif
  286 
  287 /* should be called in splnet() */
  288 struct afm *
  289 afm_match(struct ifnet *ifp, struct flowinfo *flow)
  290 {
  291         struct afm_head *head;
  292 
  293         for (head = afhead_chain.lh_first; head != NULL;
  294              head = head->afh_chain.le_next)
  295                 if (head->afh_ifp == ifp)
  296                         break;
  297         if (head == NULL)
  298                 return NULL;
  299 
  300         switch (flow->fi_family) {
  301         case AF_INET:
  302                 return (afm_match4(head, (struct flowinfo_in *)flow));
  303 
  304 #ifdef INET6
  305         case AF_INET6:
  306                 return (afm_match6(head, (struct flowinfo_in6 *)flow));
  307 #endif
  308 
  309         default:
  310                 return NULL;
  311         }
  312 }
  313 
  314 /*
  315  * afm device interface
  316  */
  317 altqdev_decl(afm);
  318 
  319 int
  320 afmopen(dev_t dev, int flag, int fmt,
  321     struct lwp *l)
  322 {
  323         return 0;
  324 }
  325 
  326 int
  327 afmclose(dev_t dev, int flag, int fmt, struct lwp *l)
  328 {
  329         int err, error = 0;
  330         struct atm_flowmap fmap;
  331         struct afm_head *head;
  332 
  333         for (head = afhead_chain.lh_first; head != NULL;
  334              head = head->afh_chain.le_next) {
  335 
  336                 /* call interface to clean up maps */
  337                 snprintf(fmap.af_ifname, sizeof(fmap.af_ifname),
  338                     "%s", head->afh_ifp->if_xname);
  339                 err = afmioctl(dev, AFM_CLEANFMAP, (void *)&fmap, flag, l);
  340                 if (err && error == 0)
  341                         error = err;
  342         }
  343 
  344         return error;
  345 }
  346 
  347 int
  348 afmioctl(dev_t dev, ioctlcmd_t cmd, void *addr, int flag,
  349     struct lwp *l)
  350 {
  351         int     error = 0;
  352         struct atm_flowmap *flowmap;
  353         struct ifnet *ifp;
  354 
  355         /* check cmd for superuser only */
  356         switch (cmd) {
  357         case AFM_GETFMAP:
  358                 break;
  359         default:
  360                 error = kauth_authorize_network(l->l_cred,
  361                     KAUTH_NETWORK_ALTQ, KAUTH_REQ_NETWORK_ALTQ_AFMAP, NULL,
  362                     NULL, NULL);
  363                 if (error)
  364                         return (error);
  365                 break;
  366         }
  367 
  368         /* lookup interface */
  369         flowmap = (struct atm_flowmap *)addr;
  370         flowmap->af_ifname[IFNAMSIZ-1] = '\0';
  371         ifp = ifunit(flowmap->af_ifname);
  372         if (ifp == NULL)
  373                 return ENXIO;
  374 
  375         IFNET_LOCK(ifp);
  376         if ((ifp->if_flags & IFF_RUNNING) == 0)
  377                 error = ENXIO;
  378         else
  379                 error = if_ioctl(ifp, cmd, addr);
  380         IFNET_UNLOCK(ifp);
  381 
  382         return error;
  383 }
  384 
  385 #endif /* ALTQ3_COMPAT */
  386 #endif /* ALTQ_AFMAP */

Cache object: 634509cfe1a89231c5e68df9668a41fc


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