-----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-----
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.
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);
_______________________________________________
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "freebsd-current-unsubscr...@freebsd.org"

Reply via email to