Add infrastructure to allow all frames/packets received on an interface

to be assigned to a non-default FIB instance.

You may need to recompile world or ports due to the change of struct ifnet.

Submitted by:	cjsp
Submitted by:	Alexander V. Chernikov (melifaro ipfw.ru)
		(original versions)
Reviewed by:	julian
Reviewed by:	Alexander V. Chernikov (melifaro ipfw.ru)
MFC after:	2 weeks
X-MFC:		use spare in struct ifnet
This commit is contained in:
Bjoern A. Zeeb 2011-07-03 12:22:02 +00:00
parent 80788b2a27
commit 35fd7bc020
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=223735
11 changed files with 152 additions and 3 deletions

View File

@ -29,6 +29,7 @@ SRCS+= af_nd6.c # ND6 support
SRCS+= ifclone.c # clone device support
SRCS+= ifmac.c # MAC support
SRCS+= ifmedia.c # SIOC[GS]IFMEDIA support
SRCS+= iffib.c # non-default FIB support
SRCS+= ifvlan.c # SIOC[GS]ETVLAN support
SRCS+= ifgre.c # GRE keys etc
SRCS+= ifgif.c # GIF reversed header workaround

View File

@ -28,7 +28,7 @@
.\" From: @(#)ifconfig.8 8.3 (Berkeley) 1/5/94
.\" $FreeBSD$
.\"
.Dd May 31, 2011
.Dd July 3, 2011
.Dt IFCONFIG 8
.Os
.Sh NAME
@ -296,6 +296,19 @@ Remove the interface from the given
Fill interface index
(lowermost 64bit of an IPv6 address)
automatically.
.It Cm fib Ar fib_number
Specify interface FIB.
A FIB
.Ar fib_number
is assigned to all frames or packets received on that interface.
The FIB is not inherited, e.g. vlans or other sub-interfaces will use
the default FIB (0) irrespective of the parent interface's FIB.
The kernel needs to be tuned to support more than the default FIB
using the
.Va ROUTETABLES
kernel configuration option, or the
.Va net.fibs
tunable.
.It Cm ipdst
This is used to specify an Internet host who is willing to receive
IP packets encapsulating IPX packets bound for a remote network.

103
sbin/ifconfig/iffib.c Normal file
View File

@ -0,0 +1,103 @@
/*-
* Copyright (c) 2011 Alexander V. Chernikov
* Copyright (c) 2011 Christian S.J. Peron
* Copyright (c) 2011 Bjoern A. Zeeb
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <net/if.h>
#include <net/route.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <err.h>
#include "ifconfig.h"
static void
fib_status(int s)
{
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
if (ioctl(s, SIOCGIFFIB, (caddr_t)&ifr) < 0)
return;
/* Ignore if it is the default. */
if (ifr.ifr_fib == 0)
return;
printf("\tfib: %u\n", ifr.ifr_fib);
}
static void
setiffib(const char *val, int dummy __unused, int s,
const struct afswtch *afp)
{
unsigned long fib;
char *ep;
fib = strtoul(val, &ep, 0);
if (*ep != '\0' || fib > UINT_MAX) {
warn("fib %s not valid", val);
return;
}
strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
ifr.ifr_fib = fib;
if (ioctl(s, SIOCSIFFIB, (caddr_t)&ifr) < 0)
warn("ioctl (SIOCSIFFIB)");
}
static struct cmd fib_cmds[] = {
DEF_CMD_ARG("fib", setiffib),
};
static struct afswtch af_fib = {
.af_name = "af_fib",
.af_af = AF_UNSPEC,
.af_other_status = fib_status,
};
static __constructor void
fib_ctor(void)
{
#define N(a) (sizeof(a) / sizeof(a[0]))
size_t i;
for (i = 0; i < N(fib_cmds); i++)
cmd_register(&fib_cmds[i]);
af_register(&af_fib);
#undef N
}

View File

@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd December 1, 2009
.Dd July 3, 2011
.Dt IFNET 9
.Os
.Sh NAME
@ -1169,11 +1169,12 @@ list.
Caller must have appropriate privilege.
(No call-down to driver.)
.It Dv SIOCGIFCAP
.It Dv SIOCGIFFIB
.It Dv SIOCGIFFLAGS
.It Dv SIOCGIFMETRIC
.It Dv SIOCGIFMTU
.It Dv SIOCGIFPHYS
Get interface capabilities, flags, metric, MTU, medium selection.
Get interface capabilities, FIB, flags, metric, MTU, medium selection.
(No call-down to driver.)
.Pp
.It Dv SIOCSIFCAP
@ -1192,6 +1193,12 @@ and
.Va if_data.ifi_hwassist
appropriately.
.Pp
.It Dv SIOCSIFFIB
Sets interface FIB.
Caller must have appropriate privilege.
FIB values start at 0 and values greater or equals than
.Va net.fibs
are considered invalid.
.It Dv SIOCSIFFLAGS
Change interface flags.
Caller must have appropriate privilege.

View File

@ -3639,6 +3639,7 @@ prison_priv_check(struct ucred *cred, int priv)
case PRIV_NET_LAGG:
case PRIV_NET_GIF:
case PRIV_NET_SETIFVNET:
case PRIV_NET_SETIFFIB:
/*
* 802.11-related privileges.

View File

@ -58,6 +58,8 @@
#include <sys/taskqueue.h>
#include <sys/domain.h>
#include <sys/jail.h>
#include <sys/priv.h>
#include <machine/stdarg.h>
#include <vm/uma.h>
@ -2135,6 +2137,20 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
free(odescrbuf, M_IFDESCR);
break;
case SIOCGIFFIB:
ifr->ifr_fib = ifp->if_fib;
break;
case SIOCSIFFIB:
error = priv_check(td, PRIV_NET_SETIFFIB);
if (error)
return (error);
if (ifr->ifr_fib >= rt_numfibs)
return (EINVAL);
ifp->if_fib = ifr->ifr_fib;
break;
case SIOCSIFFLAGS:
error = priv_check(td, PRIV_NET_SETIFFLAGS);
if (error)

View File

@ -325,6 +325,7 @@ struct ifreq {
int ifru_media;
caddr_t ifru_data;
int ifru_cap[2];
u_int ifru_fib;
} ifr_ifru;
#define ifr_addr ifr_ifru.ifru_addr /* address */
#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */
@ -341,6 +342,7 @@ struct ifreq {
#define ifr_reqcap ifr_ifru.ifru_cap[0] /* requested capabilities */
#define ifr_curcap ifr_ifru.ifru_cap[1] /* current capabilities */
#define ifr_index ifr_ifru.ifru_index /* interface index */
#define ifr_fib ifr_ifru.ifru_fib /* interface fib */
};
#define _SIZEOF_ADDR_IFREQ(ifr) \

View File

@ -86,6 +86,7 @@ if_show_ifnet(struct ifnet *ifp)
IF_DB_PRINTF("%d", if_snd.ifq_drv_maxlen);
IF_DB_PRINTF("%d", if_snd.altq_type);
IF_DB_PRINTF("%x", if_snd.altq_flags);
IF_DB_PRINTF("%u", if_fib);
#undef IF_DB_PRINTF
}

View File

@ -196,6 +196,7 @@ struct ifnet {
void *if_pf_kif;
void *if_lagg; /* lagg glue */
u_char if_alloctype; /* if_type at time of allocation */
u_int if_fib; /* interface FIB */
/*
* Spare fields are added so that we can modify sensitive data

View File

@ -337,6 +337,7 @@
#define PRIV_NET_GIF 416 /* Administer gif interface. */
#define PRIV_NET_SETIFVNET 417 /* Move interface to vnet. */
#define PRIV_NET_SETIFDESCR 418 /* Set interface description. */
#define PRIV_NET_SETIFFIB 419 /* Set interface fib. */
/*
* 802.11-related privileges.

View File

@ -110,6 +110,9 @@
#define SIOCSIFVNET _IOWR('i', 90, struct ifreq) /* move IF jail/vnet */
#define SIOCSIFRVNET _IOWR('i', 91, struct ifreq) /* reclaim vnet IF */
#define SIOCGIFFIB _IOWR('i', 92, struct ifreq) /* get IF fib */
#define SIOCSIFFIB _IOW('i', 93, struct ifreq) /* set IF fib */
#define SIOCSDRVSPEC _IOW('i', 123, struct ifdrv) /* set driver-specific
parameters */
#define SIOCGDRVSPEC _IOWR('i', 123, struct ifdrv) /* get driver-specific