Date: Sun, 08 May 2011 17:09:16 +0400 From: "Alexander V. Chernikov" <melifaro@ipfw.ru> To: freebsd-net@freebsd.org, freebsd-current@freebsd.org Subject: [patch] permit fib to be set on interface Message-ID: <4DC695FC.3080700@ipfw.ru>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------000003040104050700090603 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit -----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----- --------------000003040104050700090603 Content-Type: text/plain; name="fibs_20110508-9.0-CURRENT-r221313M.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="fibs_20110508-9.0-CURRENT-r221313M.diff" 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. --------------000003040104050700090603 Content-Type: text/plain; name="abi_ifdata_20110502-9.0-CURRENT-r221313M.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="abi_ifdata_20110502-9.0-CURRENT-r221313M.diff" 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); --------------000003040104050700090603--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4DC695FC.3080700>