[patch] permit fib to be set on interface

Alexander V. Chernikov melifaro at ipfw.ru
Sun May 8 13:09:41 UTC 2011


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

At the moment the only possible way to set packet fib from userland is
ipfw(8) setfib rule. Since no 'setfib tablearg' exists ruleset grows
with every fib.
Additionally, there is no way to set packet fib before netgraph
processing: L2 ipfw hook is called after ng_ether_input()

Those reasons (not mentioning kern/134931) makes it hard to use multiple
routing tables.

The following path:
* adds SIOCGIFIB/SIOCSIFIB ioctl(2) calls to get/set per-interface fib
* adds IFF_CUSTOMFIB interface flags
* adds ifi_fib field to if_data structure
* adds 'fib' keyword for ifconfig(8)

Example:
16:42 [0] zfscurr0# ifconfig vlan2 create inet 10.11.12.13/30 fib 15
vlan 2 vlandev em0
16:42 [0] zfscurr0# ifconfig vlan2
vlan2: flags=808843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST,CUSTOMFIB>
metric 0 mtu 1500 fib 15
        options=3<RXCSUM,TXCSUM>
        ether 08:00:27:c5:29:d4
        inet 10.11.12.13 netmask 0xfffffffc broadcast 10.11.12.15
        inet6 fe80::a00:27ff:fec5:29d4%vlan2 prefixlen 64 scopeid 0x4
        nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
        media: Ethernet autoselect (1000baseT <full-duplex>)
        status: active
        vlan: 2 parent interface: em0


Interface fib is applied on inbound only (for forwarded packets fib
decision should be done on inbound, for locally-originated packets there
is setfib(1))

How to install:
** WARNING - world (libc actually) rebuild required !! **
Apply both patches (abi first)
rebuild kernel (ROUTETABLES define required) && world
reboot (you should have console access)
use ifconfig(8) to set fib

Comments on source code:

Since we need fib to be set before ng_ether_input() we cannot set fib on
per-netisr basis which is easier.

Patch is split into 2 pieces.

struct if_data is exported to userland via:
* rtsock sysctl_iflist() sysctl (used by libc getifaddr(3) only)
* ifmib(4) interfaces (used by bsnmpd and others)

abi_ifdata patch permits if_data changes (actually, tail-adding) without
ABI breaking (and it doesn't break ABI by itself)

fibs patch does the rest described.


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.14 (FreeBSD)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk3GlfwACgkQwcJ4iSZ1q2ncmQCfYT01sjTLcuxZsYyJA/hH7lFb
sjIAn3r5aXIhtMK5zxyBWOLm+vKYehfY
=PvjZ
-----END PGP SIGNATURE-----
-------------- next part --------------
Index: sbin/ifconfig/ifconfig.8
===================================================================
--- sbin/ifconfig/ifconfig.8	(revision 221313)
+++ sbin/ifconfig/ifconfig.8	(working copy)
@@ -294,6 +294,17 @@
 Fill interface index
 (lowermost 64bit of an IPv6 address)
 automatically.
+.It Cm fib Ar fib_number
+Specify interface fib. Fib 
+.Ar fib_number
+is assigned to all frames received on that interface. Fib is not inherited,
+e.g. vlans or other sub-interfaces gets default fib (0) irrespective of parent
+interface fib.
+.Ar CUSTOMFIB
+flag is added to interface flags if non-zero fib is set. Kernel needs to be compiled 
+with the option
+.Cd "options ROUTETABLES"
+for this to work.
 .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.
Index: sbin/ifconfig/ifconfig.c
===================================================================
--- sbin/ifconfig/ifconfig.c	(revision 221313)
+++ sbin/ifconfig/ifconfig.c	(working copy)
@@ -823,6 +823,16 @@
 }
 
 static void
+setifib(const char *val, int dummy __unused, int s, 
+    const struct afswtch *afp)
+{
+	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
+	ifr.ifr_fib = atoi(val);
+	if (ioctl(s, SIOCSIFIB, (caddr_t)&ifr) < 0)
+		warn("ioctl (set fib)");
+}
+
+static void
 setifname(const char *val, int dummy __unused, int s, 
     const struct afswtch *afp)
 {
@@ -880,7 +890,7 @@
 #define	IFFBITS \
 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \
 "\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \
-"\20MULTICAST\22PPROMISC\23MONITOR\24STATICARP"
+"\20MULTICAST\22PPROMISC\23MONITOR\24STATICARP\30CUSTOMFIB"
 
 #define	IFCAPBITS \
 "\020\1RXCSUM\2TXCSUM\3NETCONS\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU\7POLLING" \
@@ -919,6 +929,8 @@
 		printf(" metric %d", ifr.ifr_metric);
 	if (ioctl(s, SIOCGIFMTU, &ifr) != -1)
 		printf(" mtu %d", ifr.ifr_mtu);
+	if (((ifa->ifa_flags & IFF_CUSTOMFIB) > 0) && (ioctl(s, SIOCGIFIB, &ifr) != -1))
+		printf(" fib %d", ifr.ifr_fib);
 	putchar('\n');
 
 	for (;;) {
@@ -1169,6 +1181,7 @@
 	DEF_CMD("compress",	IFF_LINK0,	setifflags),
 	DEF_CMD("noicmp",	IFF_LINK1,	setifflags),
 	DEF_CMD_ARG("mtu",			setifmtu),
+	DEF_CMD_ARG("fib",			setifib),
 	DEF_CMD_ARG("name",			setifname),
 };
 
Index: share/man/man9/ifnet.9
===================================================================
--- share/man/man9/ifnet.9	(revision 221313)
+++ share/man/man9/ifnet.9	(working copy)
@@ -522,6 +522,10 @@
 See
 .Sx Interface Capabilities Flags
 for details.
+.It Dv IFF_CUSTOMFIB
+.Aq D
+This interface has custom (non-zero) FIB set.
+Every packet received on that interface inherits interface fib.
 .El
 .Ss "Interface Capabilities Flags"
 Interface capabilities are specialized features an interface may
@@ -1172,8 +1176,9 @@
 .It Dv SIOCGIFFLAGS
 .It Dv SIOCGIFMETRIC
 .It Dv SIOCGIFMTU
+.It Dv SIOCGIFIB
 .It Dv SIOCGIFPHYS
-Get interface capabilities, flags, metric, MTU, medium selection.
+Get interface capabilities, flags, metric, MTU, fib, medium selection.
 (No call-down to driver.)
 .Pp
 .It Dv SIOCSIFCAP
@@ -1228,6 +1233,16 @@
 additional sanity checking and for actually modifying the MTU in the
 interface structure.
 .Pp
+.It Dv SIOCSIFIB
+Sets interface FIB.
+Caller must have appropriate privilege.
+FIB
+values greater than 
+.Va net.fibs
+are considered invalid.
+.Dv IFF_CUSTOMFIB
+flag is set if new fib is not set to 0.
+.Pp
 .It Dv SIOCADDMULTI
 .It Dv SIOCDELMULTI
 Add or delete permanent multicast group memberships on the interface.
Index: sys/kern/kern_jail.c
===================================================================
--- sys/kern/kern_jail.c	(revision 221313)
+++ sys/kern/kern_jail.c	(working copy)
@@ -3630,6 +3630,7 @@
 	case PRIV_NET_LAGG:
 	case PRIV_NET_GIF:
 	case PRIV_NET_SETIFVNET:
+	case PRIV_NET_SETIFIB:
 
 		/*
 		 * 802.11-related privileges.
Index: sys/netgraph/ng_iface.c
===================================================================
--- sys/netgraph/ng_iface.c	(revision 221313)
+++ sys/netgraph/ng_iface.c	(working copy)
@@ -56,6 +56,7 @@
 #include "opt_inet.h"
 #include "opt_inet6.h"
 #include "opt_ipx.h"
+#include "opt_route.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -777,6 +778,10 @@
 	/* First chunk of an mbuf contains good junk */
 	if (harvest.point_to_point)
 		random_harvest(m, 16, 3, 0, RANDOM_NET);
+#ifdef ROUTETABLES
+	/* Set mbuf fib from interface fib */
+	M_SETFIB(m, ifp->if_fib);
+#endif
 	netisr_dispatch(isr, m);
 	return (0);
 }
Index: sys/dev/ppbus/if_plip.c
===================================================================
--- sys/dev/ppbus/if_plip.c	(revision 221313)
+++ sys/dev/ppbus/if_plip.c	(working copy)
@@ -81,6 +81,7 @@
  */
 
 #include "opt_plip.h"
+#include "opt_route.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -585,6 +586,10 @@
 			if (bpf_peers_present(sc->sc_ifp->if_bpf))
 				lptap(sc->sc_ifp, top);
 
+#ifdef ROUTETABLES
+			/* Set mbuf fib from interface fib */
+			M_SETFIB(top, sc->sc_ifp->if_fib);
+#endif
 			/* mbuf is free'd on failure. */
 			netisr_queue(NETISR_IP, top);
 			ppb_lock(ppbus);
@@ -637,6 +642,10 @@
 			if (bpf_peers_present(sc->sc_ifp->if_bpf))
 				lptap(sc->sc_ifp, top);
 
+#ifdef ROUTETABLES
+			/* Set mbuf fib from interface fib */
+			M_SETFIB(top, sc->sc_ifp->if_fib);
+#endif
 			/* mbuf is free'd on failure. */
 			netisr_queue(NETISR_IP, top);
 			ppb_lock(ppbus);
Index: sys/dev/lmc/if_lmc.c
===================================================================
--- sys/dev/lmc/if_lmc.c	(revision 221313)
+++ sys/dev/lmc/if_lmc.c	(working copy)
@@ -77,6 +77,7 @@
 # include "opt_inet.h"	/* INET */
 # include "opt_inet6.h"	/* INET6 */
 # include "opt_netgraph.h" /* NETGRAPH */
+# include "opt_route.h" /* ROUTETABLES */
 # ifdef HAVE_KERNEL_OPTION_HEADERS
 # include "opt_device_polling.h" /* DEVICE_POLLING */
 # endif
@@ -2527,6 +2528,10 @@
   {
   softc_t *sc = IFP2SC(ifp);
 
+#ifdef ROUTETABLES
+  /* Set mbuf fib from interface fib */
+  M_SETFIB(mbuf, ifp->if_fib);
+#endif
 # if INET
   if (mbuf->m_data[0]>>4 == 4)
     netisr_dispatch(NETISR_IP,   mbuf);
Index: sys/dev/iicbus/if_ic.c
===================================================================
--- sys/dev/iicbus/if_ic.c	(revision 221313)
+++ sys/dev/iicbus/if_ic.c	(working copy)
@@ -30,6 +30,7 @@
 /*
  * I2C bus IP driver
  */
+#include "opt_route.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -311,6 +312,10 @@
 		top = m_devget(sc->ic_ifbuf + ICHDRLEN, len, 0, sc->ic_ifp, 0);
 		if (top) {
 			mtx_unlock(&sc->ic_lock);
+#ifdef ROUTETABLES
+			/* Set mbuf fib from interface fib */
+			M_SETFIB(top, sc->ic_ifp->if_fib);
+#endif
 			netisr_dispatch(NETISR_IP, top);
 			mtx_lock(&sc->ic_lock);
 		}
Index: sys/dev/usb/net/uhso.c
===================================================================
--- sys/dev/usb/net/uhso.c	(revision 221313)
+++ sys/dev/usb/net/uhso.c	(working copy)
@@ -26,6 +26,8 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include "opt_route.h"
+
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/sockio.h>
@@ -1754,6 +1756,10 @@
 
 		/* Dispatch to IP layer */
 		BPF_MTAP(sc->sc_ifp, m);
+#ifdef ROUTETABLES
+		/* Set mbuf fib from interface fib */
+		M_SETFIB(m, ifp->if_fib);
+#endif
 		netisr_dispatch(isr, m);
 		m = m0 != NULL ? m0 : NULL;
 		mtx_lock(&sc->sc_mtx);
Index: sys/net/if.c
===================================================================
--- sys/net/if.c	(revision 221313)
+++ sys/net/if.c	(working copy)
@@ -33,6 +33,7 @@
 #include "opt_compat.h"
 #include "opt_inet6.h"
 #include "opt_inet.h"
+#include "opt_route.h"
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -2078,6 +2079,12 @@
 		ifr->ifr_mtu = ifp->if_mtu;
 		break;
 
+#ifdef ROUTETABLES
+	case SIOCGIFIB:
+		ifr->ifr_fib = ifp->if_fib;
+		break;
+#endif
+
 	case SIOCGIFPHYS:
 		ifr->ifr_phys = ifp->if_physical;
 		break;
@@ -2307,6 +2314,28 @@
 		break;
 	}
 
+#ifdef ROUTETABLES
+	case SIOCSIFIB:
+	{
+		error = priv_check(td, PRIV_NET_SETIFIB);
+		if (error)
+			return (error);
+		if (ifr->ifr_fib > rt_numfibs)
+			return (EINVAL);
+
+		ifp->if_fib = ifr->ifr_fib;
+
+		if (ifp->if_fib == 0)
+			ifp->if_flags &= ~IFF_CUSTOMFIB;
+		else
+			ifp->if_flags |= IFF_CUSTOMFIB;
+
+		/* XXX we should generate rt_ifmsg here */
+
+		break;
+	}
+#endif
+
 	case SIOCADDMULTI:
 	case SIOCDELMULTI:
 		if (cmd == SIOCADDMULTI)
Index: sys/net/if.h
===================================================================
--- sys/net/if.h	(revision 221313)
+++ sys/net/if.h	(working copy)
@@ -104,6 +104,7 @@
 	u_long	ifi_hwassist;		/* HW offload capabilities, see IFCAP */
 	time_t	ifi_epoch;		/* uptime at attach or stat reset */
 	struct	timeval ifi_lastchange;	/* time of last administrative change */
+	u_short ifi_fib;		/* interface fib */
 };
 
 /*-
@@ -151,6 +152,7 @@
 #define	IFF_STATICARP	0x80000		/* (n) static ARP */
 #define	IFF_DYING	0x200000	/* (n) interface is winding down */
 #define	IFF_RENAMING	0x400000	/* (n) interface is being renamed */
+#define IFF_CUSTOMFIB	0x800000	/* (n) interface belongs to custom FIB */
 
 /*
  * Old names for driver flags so that user space tools can continue to use
@@ -240,6 +242,7 @@
 	int	ifm_addrs;	/* like rtm_addrs */
 	int	ifm_flags;	/* value of if_flags */
 	u_short	ifm_index;	/* index for associated ifp */
+	u_short	ifm_datalen;	/* length of ifm_data */
 	struct	if_data ifm_data;/* statistics and other data about if */
 };
 
@@ -315,6 +318,7 @@
 		int	ifru_media;
 		caddr_t	ifru_data;
 		int	ifru_cap[2];
+		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 */
@@ -331,6 +335,7 @@
 #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 index */
 };
 
 #define	_SIZEOF_ADDR_IFREQ(ifr) \
Index: sys/net/if_stf.c
===================================================================
--- sys/net/if_stf.c	(revision 221313)
+++ sys/net/if_stf.c	(working copy)
@@ -76,6 +76,7 @@
 
 #include "opt_inet.h"
 #include "opt_inet6.h"
+#include "opt_route.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -781,6 +782,10 @@
 	 */
 	ifp->if_ipackets++;
 	ifp->if_ibytes += m->m_pkthdr.len;
+#ifdef ROUTETABLES
+	/* Set mbuf fib from interface fib */
+	M_SETFIB(m, ifp->if_fib);
+#endif
 	netisr_dispatch(NETISR_IPV6, m);
 }
 
Index: sys/net/if_atmsubr.c
===================================================================
--- sys/net/if_atmsubr.c	(revision 221313)
+++ sys/net/if_atmsubr.c	(working copy)
@@ -40,6 +40,7 @@
 #include "opt_inet.h"
 #include "opt_inet6.h"
 #include "opt_natm.h"
+#include "opt_route.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -332,6 +333,10 @@
 			return;
 		}
 	}
+#ifdef ROUTETABLES
+	/* Set mbuf fib from interface fib */
+	M_SETFIB(m, ifp->if_fib);
+#endif
 	netisr_dispatch(isr, m);
 }
 
Index: sys/net/if_fwsubr.c
===================================================================
--- sys/net/if_fwsubr.c	(revision 221313)
+++ sys/net/if_fwsubr.c	(working copy)
@@ -32,6 +32,7 @@
 
 #include "opt_inet.h"
 #include "opt_inet6.h"
+#include "opt_route.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -626,7 +627,10 @@
 		m_freem(m);
 		return;
 	}
-
+#ifdef ROUTETABLES
+	/* Set mbuf fib from interface fib */
+	M_SETFIB(m, ifp->if_fib);
+#endif
 	netisr_dispatch(isr, m);
 }
 
Index: sys/net/if_arcsubr.c
===================================================================
--- sys/net/if_arcsubr.c	(revision 221313)
+++ sys/net/if_arcsubr.c	(working copy)
@@ -41,6 +41,7 @@
 #include "opt_inet.h"
 #include "opt_inet6.h"
 #include "opt_ipx.h"
+#include "opt_route.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -608,6 +609,10 @@
 		m_freem(m);
 		return;
 	}
+#ifdef ROUTETABLES
+	/* Set mbuf fib from interface fib */
+	M_SETFIB(m, ifp->if_fib);
+#endif
 	netisr_dispatch(isr, m);
 }
 
Index: sys/net/if_ethersubr.c
===================================================================
--- sys/net/if_ethersubr.c	(revision 221313)
+++ sys/net/if_ethersubr.c	(working copy)
@@ -691,7 +691,10 @@
 		    ETHER_HDR_LEN - ETHER_TYPE_LEN);
 		m_adj(m, ETHER_VLAN_ENCAP_LEN);
 	}
-
+#ifdef ROUTETABLES
+	/* Set mbuf fib from interface fib */
+	M_SETFIB(m, ifp->if_fib);
+#endif
 	/* Allow ng_ether(4) to claim this frame. */
 	if (IFP2AC(ifp)->ac_netgraph != NULL) {
 		KASSERT(ng_ether_input_p != NULL,
Index: sys/net/if_gif.c
===================================================================
--- sys/net/if_gif.c	(revision 221313)
+++ sys/net/if_gif.c	(working copy)
@@ -32,6 +32,7 @@
 
 #include "opt_inet.h"
 #include "opt_inet6.h"
+#include "opt_route.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -609,6 +610,10 @@
 
 	ifp->if_ipackets++;
 	ifp->if_ibytes += m->m_pkthdr.len;
+#ifdef ROUTETABLES
+	/* Set mbuf fib from interface fib */
+	M_SETFIB(m, ifp->if_fib);
+#endif
 	netisr_dispatch(isr, m);
 }
 
Index: sys/net/if_iso88025subr.c
===================================================================
--- sys/net/if_iso88025subr.c	(revision 221313)
+++ sys/net/if_iso88025subr.c	(working copy)
@@ -43,6 +43,7 @@
 #include "opt_inet.h"
 #include "opt_inet6.h"
 #include "opt_ipx.h"
+#include "opt_route.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -679,7 +680,10 @@
 		goto dropanyway;
 		break;
 	}
-
+#ifdef ROUTETABLES
+	/* Set mbuf fib from interface fib */
+	M_SETFIB(m, ifp->if_fib);
+#endif
 	netisr_dispatch(isr, m);
 	return;
 
Index: sys/net/if_var.h
===================================================================
--- sys/net/if_var.h	(revision 221313)
+++ sys/net/if_var.h	(working copy)
@@ -215,6 +215,7 @@
  * to anything.
  */
 #define	if_mtu		if_data.ifi_mtu
+#define	if_fib		if_data.ifi_fib
 #define	if_type		if_data.ifi_type
 #define if_physical	if_data.ifi_physical
 #define	if_addrlen	if_data.ifi_addrlen
Index: sys/net/if_fddisubr.c
===================================================================
--- sys/net/if_fddisubr.c	(revision 221313)
+++ sys/net/if_fddisubr.c	(working copy)
@@ -40,6 +40,7 @@
 #include "opt_inet.h"
 #include "opt_inet6.h"
 #include "opt_ipx.h"
+#include "opt_route.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -550,6 +551,10 @@
 		ifp->if_noproto++;
 		goto dropanyway;
 	}
+#ifdef ROUTETABLES
+	/* Set mbuf fib from interface fib */
+	M_SETFIB(m, ifp->if_fib);
+#endif
 	netisr_dispatch(isr, m);
 	return;
 
Index: sys/net/if_tun.c
===================================================================
--- sys/net/if_tun.c	(revision 221313)
+++ sys/net/if_tun.c	(working copy)
@@ -20,6 +20,7 @@
 #include "opt_inet.h"
 #include "opt_inet6.h"
 #include "opt_ipx.h"
+#include "opt_route.h"
 
 #include <sys/param.h>
 #include <sys/priv.h>
@@ -936,6 +937,10 @@
 	ifp->if_ibytes += m->m_pkthdr.len;
 	ifp->if_ipackets++;
 	CURVNET_SET(ifp->if_vnet);
+#ifdef ROUTETABLES
+	/* Set mbuf fib from interface fib */
+	M_SETFIB(m, ifp->if_fib);
+#endif
 	netisr_dispatch(isr, m);
 	CURVNET_RESTORE();
 	return (0);
Index: sys/net/if_spppfr.c
===================================================================
--- sys/net/if_spppfr.c	(revision 221313)
+++ sys/net/if_spppfr.c	(working copy)
@@ -29,6 +29,7 @@
 #include "opt_inet.h"
 #include "opt_inet6.h"
 #include "opt_ipx.h"
+#include "opt_route.h"
 #endif
 
 #ifdef NetBSD1_3
@@ -280,6 +281,10 @@
 	if (! (ifp->if_flags & IFF_UP))
 		goto drop;
 
+#ifdef ROUTETABLES
+	/* Set mbuf fib from interface fib */
+	M_SETFIB(m, ifp->if_fib);
+#endif
 	/* Check queue. */
 	if (netisr_queue(isr, m)) {	/* (0) on success. */
 		if (debug)
Index: sys/net/if_spppsubr.c
===================================================================
--- sys/net/if_spppsubr.c	(revision 221313)
+++ sys/net/if_spppsubr.c	(working copy)
@@ -26,6 +26,7 @@
 #include "opt_inet.h"
 #include "opt_inet6.h"
 #include "opt_ipx.h"
+#include "opt_route.h"
 
 #include <sys/systm.h>
 #include <sys/kernel.h>
@@ -737,6 +738,11 @@
 		goto drop;
 
 	SPPP_UNLOCK(sp);
+
+#ifdef ROUTETABLES
+	/* Set mbuf fib from interface fib */
+	M_SETFIB(m, ifp->if_fib);
+#endif
 	/* Check queue. */
 	if (netisr_queue(isr, m)) {	/* (0) on success. */
 		if (debug)
Index: sys/sys/sockio.h
===================================================================
--- sys/sys/sockio.h	(revision 221313)
+++ sys/sys/sockio.h	(working copy)
@@ -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	SIOCGIFIB	_IOWR('i', 92, struct ifreq)	/* get IF fib */
+#define	SIOCSIFIB	_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
Index: sys/sys/priv.h
===================================================================
--- sys/sys/priv.h	(revision 221313)
+++ sys/sys/priv.h	(working copy)
@@ -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_SETIFIB	419	/* Set interface fib */
 
 /*
  * 802.11-related privileges.
-------------- next part --------------
Index: lib/libc/net/getifaddrs.c
===================================================================
--- lib/libc/net/getifaddrs.c	(revision 221313)
+++ lib/libc/net/getifaddrs.c	(working copy)
@@ -163,11 +163,11 @@
 			if (ifm->ifm_addrs & RTA_IFP) {
 				idx = ifm->ifm_index;
 				++icnt;
-				dl = (struct sockaddr_dl *)(void *)(ifm + 1);
+				dl = (struct sockaddr_dl *)((void *)&ifm->ifm_data + ifm->ifm_datalen);
 				dcnt += SA_RLEN((struct sockaddr *)(void*)dl) +
 				    ALIGNBYTES;
 #ifdef	HAVE_IFM_DATA
-				dcnt += sizeof(ifm->ifm_data);
+				dcnt += ifm->ifm_datalen;
 #endif	/* HAVE_IFM_DATA */
 				ncnt += dl->sdl_nlen + 1;
 			} else
@@ -274,7 +274,7 @@
 			ifm = (struct if_msghdr *)(void *)rtm;
 			if (ifm->ifm_addrs & RTA_IFP) {
 				idx = ifm->ifm_index;
-				dl = (struct sockaddr_dl *)(void *)(ifm + 1);
+				dl = (struct sockaddr_dl *)((void *)&ifm->ifm_data + ifm->ifm_datalen);
 
 				cif = ift;
 				ift->ifa_name = names;
Index: sys/net/if.h
===================================================================
--- sys/net/if.h	(revision 221313)
+++ sys/net/if.h	(working copy)
@@ -240,6 +240,7 @@
 	int	ifm_addrs;	/* like rtm_addrs */
 	int	ifm_flags;	/* value of if_flags */
 	u_short	ifm_index;	/* index for associated ifp */
+	u_short	ifm_datalen;	/* length of ifm_data */
 	struct	if_data ifm_data;/* statistics and other data about if */
 };
 
Index: sys/net/if_mib.c
===================================================================
--- sys/net/if_mib.c	(revision 221313)
+++ sys/net/if_mib.c	(working copy)
@@ -107,7 +107,15 @@
 		ifmd.ifmd_snd_maxlen = ifp->if_snd.ifq_maxlen;
 		ifmd.ifmd_snd_drops = ifp->if_snd.ifq_drops;
 
-		error = SYSCTL_OUT(req, &ifmd, sizeof ifmd);
+		/*
+		 * If requested length is less than sizeof(struct ifmibdata) this
+		 * possible means that struct if_data has changed (since ifmibdata
+		 * has 16 bytes free for additional fields) and userland program 
+		 * uses older struct if_data version. We return minimum of requested 
+		 * length and actual legth to make SYSCTL_OUT() return 0 istead of 
+		 * ENOMEM
+		 */
+		error = SYSCTL_OUT(req, &ifmd, MIN(sizeof(ifmd), req->oldlen));
 		if (error || !req->newptr)
 			goto out;
 
Index: sys/net/rtsock.c
===================================================================
--- sys/net/rtsock.c	(revision 221313)
+++ sys/net/rtsock.c	(working copy)
@@ -112,6 +112,7 @@
 	int32_t	ifm_addrs;
 	int32_t	ifm_flags;
 	uint16_t ifm_index;
+	uint16_t ifm_datalen;
 	struct	if_data32 ifm_data;
 };
 #endif
@@ -1165,6 +1166,7 @@
 	ifm = mtod(m, struct if_msghdr *);
 	ifm->ifm_index = ifp->if_index;
 	ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
+	ifm->ifm_datalen = sizeof(struct if_data);
 	ifm->ifm_data = ifp->if_data;
 	ifm->ifm_addrs = 0;
 	rt_dispatch(m, NULL);
@@ -1491,6 +1493,7 @@
 				ifm32->ifm_index = ifp->if_index;
 				ifm32->ifm_flags = ifp->if_flags |
 				    ifp->if_drv_flags;
+				ifm32->ifm_datalen = sizeof(struct if_data32);
 				copy_ifdata32(&ifp->if_data, &ifm32->ifm_data);
 				ifm32->ifm_addrs = info.rti_addrs;
 				error = SYSCTL_OUT(w->w_req, (caddr_t)ifm32,
@@ -1501,6 +1504,7 @@
 			ifm = (struct if_msghdr *)w->w_tmem;
 			ifm->ifm_index = ifp->if_index;
 			ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags;
+			ifm->ifm_datalen = sizeof(struct if_data);
 			ifm->ifm_data = ifp->if_data;
 			ifm->ifm_addrs = info.rti_addrs;
 			error = SYSCTL_OUT(w->w_req, (caddr_t)ifm, len);


More information about the freebsd-current mailing list