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/netlink/route/iface_drivers.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 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2022 Alexander V. Chernikov <melifaro@FreeBSD.org>
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 #include "opt_inet.h"
   31 #include "opt_inet6.h"
   32 #include <sys/types.h>
   33 #include <sys/malloc.h>
   34 #include <sys/socket.h>
   35 #include <sys/sockio.h>
   36 #include <sys/syslog.h>
   37 #include <sys/socketvar.h>
   38 
   39 #include <net/ethernet.h>
   40 #include <net/if.h>
   41 #include <net/if_dl.h>
   42 #include <net/if_media.h>
   43 #include <net/if_var.h>
   44 #include <net/if_clone.h>
   45 #include <net/if_vlan_var.h>
   46 #include <net/route.h>
   47 #include <net/route/nhop.h>
   48 #include <net/route/route_ctl.h>
   49 #include <netlink/netlink.h>
   50 #include <netlink/netlink_ctl.h>
   51 #include <netlink/netlink_route.h>
   52 #include <netlink/route/route_var.h>
   53 
   54 #include <netinet6/scope6_var.h> /* scope deembedding */
   55 
   56 #define DEBUG_MOD_NAME  nl_iface_drivers
   57 #define DEBUG_MAX_LEVEL LOG_DEBUG3
   58 #include <netlink/netlink_debug.h>
   59 _DECLARE_DEBUG(LOG_DEBUG);
   60 
   61 /*
   62  * Generic modification interface handler.
   63  * Responsible for changing network stack interface attributes
   64  * such as state, mtu or description.
   65  */
   66 static int
   67 modify_generic(struct ifnet *ifp, struct nl_parsed_link *lattrs,
   68     const struct nlattr_bmask *bm, struct nlpcb *nlp, struct nl_pstate *npt)
   69 {
   70         int error;
   71 
   72         if (lattrs->ifla_ifalias != NULL) {
   73                 if (nlp_has_priv(nlp, PRIV_NET_SETIFDESCR)) {
   74                         int len = strlen(lattrs->ifla_ifalias) + 1;
   75                         char *buf = if_allocdescr(len, true);
   76 
   77                         memcpy(buf, lattrs->ifla_ifalias, len);
   78                         if_setdescr(ifp, buf);
   79                         getmicrotime(&ifp->if_lastchange);
   80                 } else {
   81                         nlmsg_report_err_msg(npt, "Not enough privileges to set descr");
   82                         return (EPERM);
   83                 }
   84         }
   85 
   86         if ((lattrs->ifi_change & IFF_UP) && (lattrs->ifi_flags & IFF_UP) == 0) {
   87                 /* Request to down the interface */
   88                 if_down(ifp);
   89         }
   90 
   91         if (lattrs->ifla_mtu > 0) {
   92                 if (nlp_has_priv(nlp, PRIV_NET_SETIFMTU)) {
   93                         struct ifreq ifr = { .ifr_mtu = lattrs->ifla_mtu };
   94                         error = ifhwioctl(SIOCSIFMTU, ifp, (char *)&ifr, curthread);
   95                 } else {
   96                         nlmsg_report_err_msg(npt, "Not enough privileges to set mtu");
   97                         return (EPERM);
   98                 }
   99         }
  100 
  101         if (lattrs->ifi_change & IFF_PROMISC) {
  102                 error = ifpromisc(ifp, lattrs->ifi_flags & IFF_PROMISC);
  103                 if (error != 0) {
  104                         nlmsg_report_err_msg(npt, "unable to set promisc");
  105                         return (error);
  106                 }
  107         }
  108 
  109         return (0);
  110 }
  111 
  112 /*
  113  * Generic creation interface handler.
  114  * Responsible for creating interfaces w/o parameters and setting
  115  * misc attributes such as state, mtu or description.
  116  */
  117 static int
  118 create_generic(struct nl_parsed_link *lattrs, const struct nlattr_bmask *bm,
  119     struct nlpcb *nlp, struct nl_pstate *npt)
  120 {
  121         int error = 0;
  122 
  123         struct ifc_data ifd = {};
  124         struct ifnet *ifp = NULL;
  125         error = ifc_create_ifp(lattrs->ifla_ifname, &ifd, &ifp);
  126 
  127         NLP_LOG(LOG_DEBUG2, nlp, "clone for %s returned %d", lattrs->ifla_ifname, error);
  128 
  129         if (error == 0) {
  130                 struct epoch_tracker et;
  131 
  132                 NET_EPOCH_ENTER(et);
  133                 bool success = if_try_ref(ifp);
  134                 NET_EPOCH_EXIT(et);
  135                 if (!success)
  136                         return (EINVAL);
  137                 error = modify_generic(ifp, lattrs, bm, nlp, npt);
  138                 if_rele(ifp);
  139         }
  140 
  141         return (error);
  142 }
  143 
  144 struct nl_cloner generic_cloner = {
  145         .name = "_default_",
  146         .create_f = create_generic,
  147         .modify_f = modify_generic,
  148 };
  149 
  150 /*
  151  *
  152  * {len=76, type=RTM_NEWLINK, flags=NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL|NLM_F_CREATE, seq=1662892737, pid=0},
  153  *  {ifi_family=AF_UNSPEC, ifi_type=ARPHRD_NETROM, ifi_index=0, ifi_flags=0, ifi_change=0},
  154  *   [
  155  *    {{nla_len=8, nla_type=IFLA_LINK}, 2},
  156  *    {{nla_len=12, nla_type=IFLA_IFNAME}, "xvlan22"},
  157  *    {{nla_len=24, nla_type=IFLA_LINKINFO},
  158  *     [
  159  *      {{nla_len=8, nla_type=IFLA_INFO_KIND}, "vlan"...},
  160  *      {{nla_len=12, nla_type=IFLA_INFO_DATA}, "\x06\x00\x01\x00\x16\x00\x00\x00"}]}]}, iov_len=76}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 76
  161  */
  162 
  163 struct nl_parsed_vlan {
  164         uint16_t vlan_id;
  165         uint16_t vlan_proto;
  166         struct ifla_vlan_flags vlan_flags;
  167 };
  168 
  169 #define _OUT(_field)    offsetof(struct nl_parsed_vlan, _field)
  170 static const struct nlattr_parser nla_p_vlan[] = {
  171         { .type = IFLA_VLAN_ID, .off = _OUT(vlan_id), .cb = nlattr_get_uint16 },
  172         { .type = IFLA_VLAN_FLAGS, .off = _OUT(vlan_flags), .cb = nlattr_get_nla },
  173         { .type = IFLA_VLAN_PROTOCOL, .off = _OUT(vlan_proto), .cb = nlattr_get_uint16 },
  174 };
  175 #undef _OUT
  176 NL_DECLARE_ATTR_PARSER(vlan_parser, nla_p_vlan);
  177 
  178 static int
  179 create_vlan(struct nl_parsed_link *lattrs, const struct nlattr_bmask *bm,
  180     struct nlpcb *nlp, struct nl_pstate *npt)
  181 {
  182         struct epoch_tracker et;
  183         struct ifnet *ifp;
  184         int error;
  185 
  186         /*
  187          * lattrs.ifla_ifname is the new interface name
  188          * lattrs.ifi_index contains parent interface index
  189          * lattrs.ifla_idata contains un-parsed vlan data
  190          */
  191 
  192         struct nl_parsed_vlan attrs = {
  193                 .vlan_id = 0xFEFE,
  194                 .vlan_proto = ETHERTYPE_VLAN
  195         };
  196         NLP_LOG(LOG_DEBUG3, nlp, "nested: %p len %d", lattrs->ifla_idata, lattrs->ifla_idata->nla_len);
  197 
  198         if (lattrs->ifla_idata == NULL) {
  199                 NLMSG_REPORT_ERR_MSG(npt, "vlan id is required, guessing not supported");
  200                 return (ENOTSUP);
  201         }
  202 
  203         error = nl_parse_nested(lattrs->ifla_idata, &vlan_parser, npt, &attrs);
  204         if (error != 0)
  205                 return (error);
  206         if (attrs.vlan_id > 4095) {
  207                 NLMSG_REPORT_ERR_MSG(npt, "Invalid VID: %d", attrs.vlan_id);
  208                 return (EINVAL);
  209         }
  210         if (attrs.vlan_proto != ETHERTYPE_VLAN && attrs.vlan_proto != ETHERTYPE_QINQ) {
  211                 NLMSG_REPORT_ERR_MSG(npt, "Unsupported ethertype: 0x%04X", attrs.vlan_proto);
  212                 return (ENOTSUP);
  213         }
  214 
  215         NET_EPOCH_ENTER(et);
  216         ifp = ifnet_byindex_ref(lattrs->ifi_index);
  217         NET_EPOCH_EXIT(et);
  218         if (ifp == NULL) {
  219                 NLP_LOG(LOG_DEBUG, nlp, "unable to find parent interface %u",
  220                     lattrs->ifi_index);
  221                 return (ENOENT);
  222         }
  223 
  224         /* Waiting till if_clone changes lands */
  225 /*
  226         struct vlanreq params = {
  227                 .vlr_tag = attrs.vlan_id,
  228                 .vlr_proto = attrs.vlan_proto,
  229         };
  230 */
  231         int ifname_len = strlen(lattrs->ifla_ifname) + 1;
  232         error = if_clone_create(lattrs->ifla_ifname, ifname_len, (char *)NULL);
  233 
  234         NLP_LOG(LOG_DEBUG2, nlp, "clone for %s returned %d", lattrs->ifla_ifname, error);
  235 
  236         if_rele(ifp);
  237         return (error);
  238 }
  239 
  240 static int
  241 dump_vlan(struct ifnet *ifp, struct nl_writer *nw)
  242 {
  243         return (0);
  244 }
  245 
  246 static struct nl_cloner vlan_cloner = {
  247         .name = "vlan",
  248         .create_f = create_vlan,
  249         .modify_f = modify_generic,
  250         .dump_f = dump_vlan,
  251 
  252 };
  253 
  254 static const struct nlhdr_parser *all_parsers[] = { &vlan_parser };
  255 
  256 void
  257 rtnl_iface_drivers_register(void)
  258 {
  259         rtnl_iface_add_cloner(&vlan_cloner);
  260         NL_VERIFY_PARSERS(all_parsers);
  261 }
  262 
  263 

Cache object: a70421ca3771f7584fd915ff9237c482


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