2016-10-25 05:45:09 +03:00
|
|
|
/* $NetBSD: route.h,v 1.106 2016/10/25 02:45:09 ozaki-r Exp $ */
|
1994-06-29 10:29:24 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
1994-05-11 13:26:46 +04:00
|
|
|
* Copyright (c) 1980, 1986, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
|
|
|
* 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.
|
2003-08-07 20:26:28 +04:00
|
|
|
* 3. Neither the name of the University nor the names of its contributors
|
1993-03-21 12:45:37 +03:00
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
|
|
|
*
|
1997-04-03 01:17:28 +04:00
|
|
|
* @(#)route.h 8.5 (Berkeley) 2/8/95
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
|
|
|
|
1997-04-03 01:17:28 +04:00
|
|
|
#ifndef _NET_ROUTE_H_
|
|
|
|
#define _NET_ROUTE_H_
|
1998-04-29 21:49:58 +04:00
|
|
|
|
|
|
|
#include <sys/queue.h>
|
1998-05-03 01:19:03 +04:00
|
|
|
#include <sys/socket.h>
|
2006-11-13 08:13:38 +03:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <net/if.h>
|
1998-04-29 21:49:58 +04:00
|
|
|
|
2008-02-11 07:47:21 +03:00
|
|
|
#if !(defined(_KERNEL) || defined(_STANDALONE))
|
2008-01-21 23:25:33 +03:00
|
|
|
#include <stdbool.h>
|
|
|
|
#endif
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* Kernel resident routing tables.
|
2005-02-27 01:45:09 +03:00
|
|
|
*
|
1993-03-21 12:45:37 +03:00
|
|
|
* The routing tables are initialized when interface addresses
|
|
|
|
* are set by making entries for all directly connected interfaces.
|
|
|
|
*/
|
|
|
|
|
2008-01-21 23:25:33 +03:00
|
|
|
/*
|
|
|
|
* A route consists of a destination address and a reference
|
|
|
|
* to a routing entry. These are often held by protocols
|
|
|
|
* in their control blocks, e.g. inpcb.
|
|
|
|
*/
|
|
|
|
struct route {
|
|
|
|
struct rtentry *_ro_rt;
|
|
|
|
struct sockaddr *ro_sa;
|
|
|
|
LIST_ENTRY(route) ro_rtcache_next;
|
|
|
|
bool ro_invalid;
|
|
|
|
};
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* These numbers are used by reliable protocols for determining
|
|
|
|
* retransmission behavior and are included in the routing structure.
|
|
|
|
*/
|
|
|
|
struct rt_metrics {
|
2011-02-01 04:39:19 +03:00
|
|
|
uint64_t rmx_locks; /* Kernel must leave these values alone */
|
|
|
|
uint64_t rmx_mtu; /* MTU for this path */
|
|
|
|
uint64_t rmx_hopcount; /* max hops expected */
|
|
|
|
uint64_t rmx_recvpipe; /* inbound delay-bandwidth product */
|
|
|
|
uint64_t rmx_sendpipe; /* outbound delay-bandwidth product */
|
|
|
|
uint64_t rmx_ssthresh; /* outbound gateway buffer limit */
|
|
|
|
uint64_t rmx_rtt; /* estimated round trip time */
|
|
|
|
uint64_t rmx_rttvar; /* estimated rtt variance */
|
2009-01-11 05:45:45 +03:00
|
|
|
time_t rmx_expire; /* lifetime for route, e.g. redirect */
|
|
|
|
time_t rmx_pksent; /* packets sent using this route */
|
|
|
|
};
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* rmx_rtt and rmx_rttvar are stored as microseconds;
|
|
|
|
* RTTTOPRHZ(rtt) converts to a value suitable for use
|
|
|
|
* by a protocol slowtimo counter.
|
|
|
|
*/
|
|
|
|
#define RTM_RTTUNIT 1000000 /* units for rtt, rttvar, as units per sec */
|
|
|
|
#define RTTTOPRHZ(r) ((r) / (RTM_RTTUNIT / PR_SLOWHZ))
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We distinguish between routes to hosts and routes to networks,
|
|
|
|
* preferring the former if available. For each route we infer
|
|
|
|
* the interface to use from the gateway address supplied when
|
|
|
|
* the route was entered. Routes that forward packets through
|
|
|
|
* gateways are marked so that the output routines know to address the
|
|
|
|
* gateway rather than the ultimate destination.
|
|
|
|
*/
|
|
|
|
#ifndef RNF_NORMAL
|
1994-05-11 13:26:46 +04:00
|
|
|
#include <net/radix.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#endif
|
|
|
|
struct rtentry {
|
|
|
|
struct radix_node rt_nodes[2]; /* tree glue, and other values */
|
Take steps to hide the radix_node implementation of the forwarding table
from the forwarding table's users:
Introduce rt_walktree() for walking the routing table and
applying a function to each rtentry. Replace most
rn_walktree() calls with it.
Use rt_getkey()/rt_setkey() to get/set a route's destination.
Keep a pointer to the sockaddr key in the rtentry, so that
rtentry users do not have to grovel in the radix_node for
the key.
Add a RTM_GET method to rtrequest. Use that instead of
radix_node lookups in, e.g., carp(4).
Add sys/net/link_proto.c, which supplies sockaddr routines for
link-layer socket addresses (sockaddr_dl).
Cosmetic:
Constify. KNF. Stop open-coding LIST_FOREACH, TAILQ_FOREACH,
et cetera. Use NULL instead of 0 for null pointers. Use
__arraycount(). Reduce gratuitous parenthesization.
Stop using variadic arguments for rip6_output(), it is
unnecessary.
Remove the unnecessary rtentry member rt_genmask and the
code to maintain it, since nothing actually used it.
Make rt_maskedcopy() easier to read by using meaningful variable
names.
Extract a subroutine intern_netmask() for looking up a netmask in
the masks table.
Start converting backslash-ridden IPv6 macros in
sys/netinet6/in6_var.h into inline subroutines that one
can read without special eyeglasses.
One functional change: when the kernel serves an RTM_GET, RTM_LOCK,
or RTM_CHANGE request, it applies the netmask (if supplied) to a
destination before searching for it in the forwarding table.
I have changed sys/netinet/ip_carp.c, carp_setroute(), to remove
the unlawful radix_node knowledge.
Apart from the changes to carp(4), netiso, ATM, and strip(4), I
have run the changes on three nodes in my wireless routing testbed,
which involves IPv4 + IPv6 dynamic routing acrobatics, and it's
working beautifully so far.
2007-07-20 00:48:52 +04:00
|
|
|
#define rt_mask(r) ((const struct sockaddr *)((r)->rt_nodes->rn_mask))
|
1993-03-21 12:45:37 +03:00
|
|
|
struct sockaddr *rt_gateway; /* value */
|
2000-05-04 21:33:03 +04:00
|
|
|
int rt_flags; /* up/down?, host/net */
|
|
|
|
int rt_refcnt; /* # held references */
|
2011-02-01 04:39:19 +03:00
|
|
|
uint64_t rt_use; /* raw # packets forwarded */
|
1993-03-21 12:45:37 +03:00
|
|
|
struct ifnet *rt_ifp; /* the answer: interface to use */
|
|
|
|
struct ifaddr *rt_ifa; /* the answer: interface to use */
|
2006-11-13 08:13:38 +03:00
|
|
|
uint32_t rt_ifa_seqno;
|
2007-03-04 08:59:00 +03:00
|
|
|
void * rt_llinfo; /* pointer to link level info cache */
|
2011-02-01 04:39:19 +03:00
|
|
|
struct rt_metrics rt_rmx; /* metrics used by rx'ing protocols */
|
1994-05-11 13:26:46 +04:00
|
|
|
struct rtentry *rt_gwroute; /* implied entry for gatewayed routes */
|
1998-04-29 07:41:49 +04:00
|
|
|
LIST_HEAD(, rttimer) rt_timer; /* queue of timeouts for misc funcs */
|
2001-01-27 13:39:33 +03:00
|
|
|
struct rtentry *rt_parent; /* parent of cloned route */
|
2010-06-26 18:24:27 +04:00
|
|
|
struct sockaddr *_rt_key;
|
|
|
|
struct sockaddr *rt_tag; /* route tagging info */
|
1993-03-21 12:45:37 +03:00
|
|
|
};
|
|
|
|
|
Take steps to hide the radix_node implementation of the forwarding table
from the forwarding table's users:
Introduce rt_walktree() for walking the routing table and
applying a function to each rtentry. Replace most
rn_walktree() calls with it.
Use rt_getkey()/rt_setkey() to get/set a route's destination.
Keep a pointer to the sockaddr key in the rtentry, so that
rtentry users do not have to grovel in the radix_node for
the key.
Add a RTM_GET method to rtrequest. Use that instead of
radix_node lookups in, e.g., carp(4).
Add sys/net/link_proto.c, which supplies sockaddr routines for
link-layer socket addresses (sockaddr_dl).
Cosmetic:
Constify. KNF. Stop open-coding LIST_FOREACH, TAILQ_FOREACH,
et cetera. Use NULL instead of 0 for null pointers. Use
__arraycount(). Reduce gratuitous parenthesization.
Stop using variadic arguments for rip6_output(), it is
unnecessary.
Remove the unnecessary rtentry member rt_genmask and the
code to maintain it, since nothing actually used it.
Make rt_maskedcopy() easier to read by using meaningful variable
names.
Extract a subroutine intern_netmask() for looking up a netmask in
the masks table.
Start converting backslash-ridden IPv6 macros in
sys/netinet6/in6_var.h into inline subroutines that one
can read without special eyeglasses.
One functional change: when the kernel serves an RTM_GET, RTM_LOCK,
or RTM_CHANGE request, it applies the netmask (if supplied) to a
destination before searching for it in the forwarding table.
I have changed sys/netinet/ip_carp.c, carp_setroute(), to remove
the unlawful radix_node knowledge.
Apart from the changes to carp(4), netiso, ATM, and strip(4), I
have run the changes on three nodes in my wireless routing testbed,
which involves IPv4 + IPv6 dynamic routing acrobatics, and it's
working beautifully so far.
2007-07-20 00:48:52 +04:00
|
|
|
static inline const struct sockaddr *
|
|
|
|
rt_getkey(const struct rtentry *rt)
|
|
|
|
{
|
|
|
|
return rt->_rt_key;
|
|
|
|
}
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* Following structure necessary for 4.3 compatibility;
|
|
|
|
* We should eventually move it to a compat file.
|
|
|
|
*/
|
|
|
|
struct ortentry {
|
2008-02-20 20:05:52 +03:00
|
|
|
uint32_t rt_hash; /* to speed lookups */
|
1997-04-03 01:17:28 +04:00
|
|
|
struct sockaddr rt_dst; /* key */
|
|
|
|
struct sockaddr rt_gateway; /* value */
|
|
|
|
int16_t rt_flags; /* up/down?, host/net */
|
|
|
|
int16_t rt_refcnt; /* # held references */
|
2008-02-20 20:05:52 +03:00
|
|
|
uint32_t rt_use; /* raw # packets forwarded */
|
1997-04-03 01:17:28 +04:00
|
|
|
struct ifnet *rt_ifp; /* the answer: interface to use */
|
1993-03-21 12:45:37 +03:00
|
|
|
};
|
|
|
|
|
1994-05-11 13:26:46 +04:00
|
|
|
#define RTF_UP 0x1 /* route usable */
|
1993-03-21 12:45:37 +03:00
|
|
|
#define RTF_GATEWAY 0x2 /* destination is a gateway */
|
|
|
|
#define RTF_HOST 0x4 /* host entry (net otherwise) */
|
|
|
|
#define RTF_REJECT 0x8 /* host or net unreachable */
|
|
|
|
#define RTF_DYNAMIC 0x10 /* created dynamically (by redirect) */
|
|
|
|
#define RTF_MODIFIED 0x20 /* modified dynamically (by redirect) */
|
|
|
|
#define RTF_DONE 0x40 /* message confirmed */
|
|
|
|
#define RTF_MASK 0x80 /* subnet mask present */
|
2016-04-04 10:37:07 +03:00
|
|
|
// #define RTF_CLONING 0x100 /* generate new routes on use */
|
|
|
|
#define RTF_CONNECTED 0x100 /* hosts on this route are neighbours */
|
|
|
|
// #define RTF_XRESOLVE 0x200 /* external daemon resolves name */
|
|
|
|
// #define RTF_LLINFO 0x400 /* generated by ARP or NDP */
|
2015-08-31 11:02:44 +03:00
|
|
|
#define RTF_LLDATA 0x400 /* used by apps to add/del L2 entries */
|
1994-05-11 13:26:46 +04:00
|
|
|
#define RTF_STATIC 0x800 /* manually added */
|
|
|
|
#define RTF_BLACKHOLE 0x1000 /* just discard pkts (during updates) */
|
2016-04-04 10:37:07 +03:00
|
|
|
// #define RTF_CLONED 0x2000 /* this is a cloned route */
|
1993-03-21 12:45:37 +03:00
|
|
|
#define RTF_PROTO2 0x4000 /* protocol specific routing flag */
|
|
|
|
#define RTF_PROTO1 0x8000 /* protocol specific routing flag */
|
2006-11-13 08:13:38 +03:00
|
|
|
#define RTF_SRC 0x10000 /* route has fixed source address */
|
2015-02-24 23:06:09 +03:00
|
|
|
#define RTF_ANNOUNCE 0x20000 /* announce new ARP or NDP entry */
|
2015-02-26 12:54:46 +03:00
|
|
|
#define RTF_LOCAL 0x40000 /* route represents a local address */
|
2015-03-23 21:33:17 +03:00
|
|
|
#define RTF_BROADCAST 0x80000 /* route represents a bcast address */
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Routing statistics.
|
|
|
|
*/
|
|
|
|
struct rtstat {
|
2009-11-03 03:30:31 +03:00
|
|
|
uint64_t rts_badredirect; /* bogus redirect calls */
|
|
|
|
uint64_t rts_dynamic; /* routes created by redirects */
|
|
|
|
uint64_t rts_newgateway; /* routes modified by redirects */
|
|
|
|
uint64_t rts_unreach; /* lookups which failed */
|
|
|
|
uint64_t rts_wildcard; /* lookups satisfied by a wildcard */
|
1993-03-21 12:45:37 +03:00
|
|
|
};
|
2011-02-01 04:39:19 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Structures for routing messages. By forcing the first member to be aligned
|
|
|
|
* at a 64-bit boundary, we also force the size to be a multiple of 64-bits.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if !defined(_KERNEL) || !defined(COMPAT_RTSOCK)
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
2011-02-01 04:39:19 +03:00
|
|
|
* If we aren't being compiled for backwards compatiblity, enforce 64-bit
|
|
|
|
* alignment so any routing message is the same regardless if the kernel
|
|
|
|
* is an ILP32 or LP64 kernel.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
2011-02-01 04:39:19 +03:00
|
|
|
#define __align64 __aligned(sizeof(uint64_t))
|
|
|
|
#else
|
|
|
|
#define __align64
|
|
|
|
#endif
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
struct rt_msghdr {
|
2011-02-01 04:39:19 +03:00
|
|
|
u_short rtm_msglen __align64;
|
|
|
|
/* to skip over non-understood messages */
|
1994-05-11 13:26:46 +04:00
|
|
|
u_char rtm_version; /* future binary compatibility */
|
1993-03-21 12:45:37 +03:00
|
|
|
u_char rtm_type; /* message type */
|
|
|
|
u_short rtm_index; /* index for associated ifp */
|
1994-05-11 13:26:46 +04:00
|
|
|
int rtm_flags; /* flags, incl. kern & message, e.g. DONE */
|
1993-03-21 12:45:37 +03:00
|
|
|
int rtm_addrs; /* bitmask identifying sockaddrs in msg */
|
1994-05-11 13:26:46 +04:00
|
|
|
pid_t rtm_pid; /* identify sender */
|
1993-03-21 12:45:37 +03:00
|
|
|
int rtm_seq; /* for sender to identify action */
|
|
|
|
int rtm_errno; /* why failed */
|
|
|
|
int rtm_use; /* from rtentry */
|
2011-02-01 04:39:19 +03:00
|
|
|
int rtm_inits; /* which metrics we are initializing */
|
|
|
|
struct rt_metrics rtm_rmx __align64;
|
|
|
|
/* metrics themselves */
|
1993-03-21 12:45:37 +03:00
|
|
|
};
|
|
|
|
|
2011-02-01 04:39:19 +03:00
|
|
|
#undef __align64
|
|
|
|
|
|
|
|
#define RTM_VERSION 4 /* Up the ante and ignore older versions */
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
#define RTM_ADD 0x1 /* Add Route */
|
|
|
|
#define RTM_DELETE 0x2 /* Delete Route */
|
|
|
|
#define RTM_CHANGE 0x3 /* Change Metrics or flags */
|
|
|
|
#define RTM_GET 0x4 /* Report Metrics */
|
|
|
|
#define RTM_LOSING 0x5 /* Kernel Suspects Partitioning */
|
|
|
|
#define RTM_REDIRECT 0x6 /* Told to use different route */
|
|
|
|
#define RTM_MISS 0x7 /* Lookup failed on this address */
|
|
|
|
#define RTM_LOCK 0x8 /* fix specified metrics */
|
|
|
|
#define RTM_OLDADD 0x9 /* caused by SIOCADDRT */
|
|
|
|
#define RTM_OLDDEL 0xa /* caused by SIOCDELRT */
|
2016-04-04 10:37:07 +03:00
|
|
|
// #define RTM_RESOLVE 0xb /* req to resolve dst to LL addr */
|
2016-09-21 13:50:22 +03:00
|
|
|
#define RTM_ONEWADDR 0xc /* Old (pre-8.0) RTM_NEWADDR message */
|
|
|
|
#define RTM_ODELADDR 0xd /* Old (pre-8.0) RTM_DELADDR message */
|
2009-01-11 05:45:45 +03:00
|
|
|
#define RTM_OOIFINFO 0xe /* Old (pre-1.5) RTM_IFINFO message */
|
2011-02-01 04:39:19 +03:00
|
|
|
#define RTM_OIFINFO 0xf /* Old (pre-64bit time) RTM_IFINFO message */
|
2000-03-06 23:49:00 +03:00
|
|
|
#define RTM_IFANNOUNCE 0x10 /* iface arrival/departure */
|
2005-06-22 10:14:51 +04:00
|
|
|
#define RTM_IEEE80211 0x11 /* IEEE80211 wireless event */
|
2007-08-27 04:34:01 +04:00
|
|
|
#define RTM_SETGATE 0x12 /* set prototype gateway for clones
|
|
|
|
* (see example in arp_rtrequest).
|
|
|
|
*/
|
*** Summary ***
When a link-layer address changes (e.g., ifconfig ex0 link
02:de:ad:be:ef:02 active), send a gratuitous ARP and/or a Neighbor
Advertisement to update the network-/link-layer address bindings
on our LAN peers.
Refuse a change of ethernet address to the address 00:00:00:00:00:00
or to any multicast/broadcast address. (Thanks matt@.)
Reorder ifnet ioctl operations so that driver ioctls may inherit
the functions of their "class"---ether_ioctl(), fddi_ioctl(), et
cetera---and the class ioctls may inherit from the generic ioctl,
ifioctl_common(), but both driver- and class-ioctls may override
the generic behavior. Make network drivers share more code.
Distinguish a "factory" link-layer address from others for the
purposes of both protecting that address from deletion and computing
EUI64.
Return consistent, appropriate error codes from network drivers.
Improve readability. KNF.
*** Details ***
In if_attach(), always initialize the interface ioctl routine,
ifnet->if_ioctl, if the driver has not already initialized it.
Delete if_ioctl == NULL tests everywhere else, because it cannot
happen.
In the ioctl routines of network interfaces, inherit common ioctl
behaviors by calling either ifioctl_common() or whichever ioctl
routine is appropriate for the class of interface---e.g., ether_ioctl()
for ethernets.
Stop (ab)using SIOCSIFADDR and start to use SIOCINITIFADDR. In
the user->kernel interface, SIOCSIFADDR's argument was an ifreq,
but on the protocol->ifnet interface, SIOCSIFADDR's argument was
an ifaddr. That was confusing, and it would work against me as I
make it possible for a network interface to overload most ioctls.
On the protocol->ifnet interface, replace SIOCSIFADDR with
SIOCINITIFADDR. In ifioctl(), return EPERM if userland tries to
invoke SIOCINITIFADDR.
In ifioctl(), give the interface the first shot at handling most
interface ioctls, and give the protocol the second shot, instead
of the other way around. Finally, let compatibility code (COMPAT_OSOCK)
take a shot.
Pull device initialization out of switch statements under
SIOCINITIFADDR. For example, pull ..._init() out of any switch
statement that looks like this:
switch (...->sa_family) {
case ...:
..._init();
...
break;
...
default:
..._init();
...
break;
}
Rewrite many if-else clauses that handle all permutations of IFF_UP
and IFF_RUNNING to use a switch statement,
switch (x & (IFF_UP|IFF_RUNNING)) {
case 0:
...
break;
case IFF_RUNNING:
...
break;
case IFF_UP:
...
break;
case IFF_UP|IFF_RUNNING:
...
break;
}
unifdef lots of code containing #ifdef FreeBSD, #ifdef NetBSD, and
#ifdef SIOCSIFMTU, especially in fwip(4) and in ndis(4).
In ipw(4), remove an if_set_sadl() call that is out of place.
In nfe(4), reuse the jumbo MTU logic in ether_ioctl().
Let ethernets register a callback for setting h/w state such as
promiscuous mode and the multicast filter in accord with a change
in the if_flags: ether_set_ifflags_cb() registers a callback that
returns ENETRESET if the caller should reset the ethernet by calling
if_init(), 0 on success, != 0 on failure. Pull common code from
ex(4), gem(4), nfe(4), sip(4), tlp(4), vge(4) into ether_ioctl(),
and register if_flags callbacks for those drivers.
Return ENOTTY instead of EINVAL for inappropriate ioctls. In
zyd(4), use ENXIO instead of ENOTTY to indicate that the device is
not any longer attached.
Add to if_set_sadl() a boolean 'factory' argument that indicates
whether a link-layer address was assigned by the factory or some
other source. In a comment, recommend using the factory address
for generating an EUI64, and update in6_get_hw_ifid() to prefer a
factory address to any other link-layer address.
Add a routing message, RTM_LLINFO_UPD, that tells protocols to
update the binding of network-layer addresses to link-layer addresses.
Implement this message in IPv4 and IPv6 by sending a gratuitous
ARP or a neighbor advertisement, respectively. Generate RTM_LLINFO_UPD
messages on a change of an interface's link-layer address.
In ether_ioctl(), do not let SIOCALIFADDR set a link-layer address
that is broadcast/multicast or equal to 00:00:00:00:00:00.
Make ether_ioctl() call ifioctl_common() to handle ioctls that it
does not understand.
In gif(4), initialize if_softc and use it, instead of assuming that
the gif_softc and ifp overlap.
Let ifioctl_common() handle SIOCGIFADDR.
Sprinkle rtcache_invariants(), which checks on DIAGNOSTIC kernels
that certain invariants on a struct route are satisfied.
In agr(4), rewrite agr_ioctl_filter() to be a bit more explicit
about the ioctls that we do not allow on an agr(4) member interface.
bzero -> memset. Delete unnecessary casts to void *. Use
sockaddr_in_init() and sockaddr_in6_init(). Compare pointers with
NULL instead of "testing truth". Replace some instances of (type
*)0 with NULL. Change some K&R prototypes to ANSI C, and join
lines.
2008-11-07 03:20:01 +03:00
|
|
|
#define RTM_LLINFO_UPD 0x13 /* indication to ARP/NDP/etc. that link-layer
|
|
|
|
* address has changed
|
|
|
|
*/
|
2009-01-11 05:45:45 +03:00
|
|
|
#define RTM_IFINFO 0x14 /* iface/link going up/down etc. */
|
2016-09-21 13:50:22 +03:00
|
|
|
#define RTM_OCHGADDR 0x15 /* Old (pre-8.0) RTM_CHGADDR message */
|
|
|
|
#define RTM_NEWADDR 0x16 /* address being added to iface */
|
|
|
|
#define RTM_DELADDR 0x17 /* address being removed from iface */
|
|
|
|
#define RTM_CHGADDR 0x18 /* address properties changed */
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
#define RTV_MTU 0x1 /* init or lock _mtu */
|
|
|
|
#define RTV_HOPCOUNT 0x2 /* init or lock _hopcount */
|
2001-03-08 06:22:28 +03:00
|
|
|
#define RTV_EXPIRE 0x4 /* init or lock _expire */
|
1993-03-21 12:45:37 +03:00
|
|
|
#define RTV_RPIPE 0x8 /* init or lock _recvpipe */
|
|
|
|
#define RTV_SPIPE 0x10 /* init or lock _sendpipe */
|
|
|
|
#define RTV_SSTHRESH 0x20 /* init or lock _ssthresh */
|
|
|
|
#define RTV_RTT 0x40 /* init or lock _rtt */
|
|
|
|
#define RTV_RTTVAR 0x80 /* init or lock _rttvar */
|
|
|
|
|
1994-05-11 13:26:46 +04:00
|
|
|
/*
|
|
|
|
* Bitmask values for rtm_addr.
|
|
|
|
*/
|
1993-03-21 12:45:37 +03:00
|
|
|
#define RTA_DST 0x1 /* destination sockaddr present */
|
|
|
|
#define RTA_GATEWAY 0x2 /* gateway sockaddr present */
|
|
|
|
#define RTA_NETMASK 0x4 /* netmask sockaddr present */
|
|
|
|
#define RTA_GENMASK 0x8 /* cloning mask sockaddr present */
|
|
|
|
#define RTA_IFP 0x10 /* interface name sockaddr present */
|
|
|
|
#define RTA_IFA 0x20 /* interface addr sockaddr present */
|
|
|
|
#define RTA_AUTHOR 0x40 /* sockaddr for author of redirect */
|
1994-05-11 13:26:46 +04:00
|
|
|
#define RTA_BRD 0x80 /* for NEWADDR, broadcast or p-p dest addr */
|
2010-06-26 18:24:27 +04:00
|
|
|
#define RTA_TAG 0x100 /* route tag */
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1994-05-11 13:26:46 +04:00
|
|
|
/*
|
|
|
|
* Index offsets for sockaddr array for alternate internal encoding.
|
|
|
|
*/
|
|
|
|
#define RTAX_DST 0 /* destination sockaddr present */
|
|
|
|
#define RTAX_GATEWAY 1 /* gateway sockaddr present */
|
|
|
|
#define RTAX_NETMASK 2 /* netmask sockaddr present */
|
|
|
|
#define RTAX_GENMASK 3 /* cloning mask sockaddr present */
|
|
|
|
#define RTAX_IFP 4 /* interface name sockaddr present */
|
|
|
|
#define RTAX_IFA 5 /* interface addr sockaddr present */
|
|
|
|
#define RTAX_AUTHOR 6 /* sockaddr for author of redirect */
|
|
|
|
#define RTAX_BRD 7 /* for NEWADDR, broadcast or p-p dest addr */
|
2010-06-26 18:24:27 +04:00
|
|
|
#define RTAX_TAG 8 /* route tag */
|
|
|
|
#define RTAX_MAX 9 /* size of array to allocate */
|
1994-05-11 13:26:46 +04:00
|
|
|
|
2011-02-01 04:39:19 +03:00
|
|
|
#define RT_ROUNDUP2(a, n) ((a) > 0 ? (1 + (((a) - 1) | ((n) - 1))) : (n))
|
|
|
|
#define RT_ROUNDUP(a) RT_ROUNDUP2((a), sizeof(uint64_t))
|
|
|
|
#define RT_ADVANCE(x, n) (x += RT_ROUNDUP((n)->sa_len))
|
2009-04-03 01:02:06 +04:00
|
|
|
|
1994-05-11 13:26:46 +04:00
|
|
|
struct rt_addrinfo {
|
|
|
|
int rti_addrs;
|
2004-04-21 08:17:28 +04:00
|
|
|
const struct sockaddr *rti_info[RTAX_MAX];
|
2001-01-17 07:05:41 +03:00
|
|
|
int rti_flags;
|
|
|
|
struct ifaddr *rti_ifa;
|
|
|
|
struct ifnet *rti_ifp;
|
1994-05-11 13:26:46 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
struct route_cb {
|
|
|
|
int ip_count;
|
1999-07-01 12:12:45 +04:00
|
|
|
int ip6_count;
|
2013-03-01 22:25:13 +04:00
|
|
|
int unused1;
|
2010-06-26 18:24:27 +04:00
|
|
|
int mpls_count;
|
1994-05-11 13:26:46 +04:00
|
|
|
int any_count;
|
|
|
|
};
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2005-02-27 01:45:09 +03:00
|
|
|
/*
|
1998-04-29 07:41:49 +04:00
|
|
|
* This structure, and the prototypes for the rt_timer_{init,remove_all,
|
|
|
|
* add,timer} functions all used with the kind permission of BSDI.
|
|
|
|
* These allow functions to be called for routes at specific times.
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct rttimer {
|
1998-12-27 21:27:48 +03:00
|
|
|
TAILQ_ENTRY(rttimer) rtt_next; /* entry on timer queue */
|
|
|
|
LIST_ENTRY(rttimer) rtt_link; /* multiple timers per rtentry */
|
2004-04-22 01:03:43 +04:00
|
|
|
struct rttimer_queue *rtt_queue; /* back pointer to queue */
|
|
|
|
struct rtentry *rtt_rt; /* Back pointer to the route */
|
|
|
|
void (*rtt_func)(struct rtentry *, struct rttimer *);
|
|
|
|
time_t rtt_time; /* When this timer was registered */
|
1998-04-29 07:41:49 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
struct rttimer_queue {
|
|
|
|
long rtq_timeout;
|
2000-12-09 04:29:45 +03:00
|
|
|
unsigned long rtq_count;
|
1998-12-27 21:27:48 +03:00
|
|
|
TAILQ_HEAD(, rttimer) rtq_head;
|
1998-04-29 07:41:49 +04:00
|
|
|
LIST_ENTRY(rttimer_queue) rtq_link;
|
1998-12-27 21:27:48 +03:00
|
|
|
};
|
1998-04-29 07:41:49 +04:00
|
|
|
|
|
|
|
|
2011-03-31 23:40:51 +04:00
|
|
|
struct rtbl;
|
|
|
|
typedef struct rtbl rtbl_t;
|
|
|
|
|
1995-03-27 00:23:52 +04:00
|
|
|
#ifdef _KERNEL
|
2009-01-11 05:45:45 +03:00
|
|
|
|
2011-03-31 23:40:51 +04:00
|
|
|
struct rtbl {
|
|
|
|
struct radix_node_head t_rnh;
|
|
|
|
};
|
|
|
|
|
2009-01-11 05:45:45 +03:00
|
|
|
struct rt_walkarg {
|
|
|
|
int w_op;
|
|
|
|
int w_arg;
|
|
|
|
int w_given;
|
|
|
|
int w_needed;
|
|
|
|
void * w_where;
|
|
|
|
int w_tmemsize;
|
|
|
|
int w_tmemneeded;
|
|
|
|
void * w_tmem;
|
|
|
|
};
|
|
|
|
|
Take steps to hide the radix_node implementation of the forwarding table
from the forwarding table's users:
Introduce rt_walktree() for walking the routing table and
applying a function to each rtentry. Replace most
rn_walktree() calls with it.
Use rt_getkey()/rt_setkey() to get/set a route's destination.
Keep a pointer to the sockaddr key in the rtentry, so that
rtentry users do not have to grovel in the radix_node for
the key.
Add a RTM_GET method to rtrequest. Use that instead of
radix_node lookups in, e.g., carp(4).
Add sys/net/link_proto.c, which supplies sockaddr routines for
link-layer socket addresses (sockaddr_dl).
Cosmetic:
Constify. KNF. Stop open-coding LIST_FOREACH, TAILQ_FOREACH,
et cetera. Use NULL instead of 0 for null pointers. Use
__arraycount(). Reduce gratuitous parenthesization.
Stop using variadic arguments for rip6_output(), it is
unnecessary.
Remove the unnecessary rtentry member rt_genmask and the
code to maintain it, since nothing actually used it.
Make rt_maskedcopy() easier to read by using meaningful variable
names.
Extract a subroutine intern_netmask() for looking up a netmask in
the masks table.
Start converting backslash-ridden IPv6 macros in
sys/netinet6/in6_var.h into inline subroutines that one
can read without special eyeglasses.
One functional change: when the kernel serves an RTM_GET, RTM_LOCK,
or RTM_CHANGE request, it applies the netmask (if supplied) to a
destination before searching for it in the forwarding table.
I have changed sys/netinet/ip_carp.c, carp_setroute(), to remove
the unlawful radix_node knowledge.
Apart from the changes to carp(4), netiso, ATM, and strip(4), I
have run the changes on three nodes in my wireless routing testbed,
which involves IPv4 + IPv6 dynamic routing acrobatics, and it's
working beautifully so far.
2007-07-20 00:48:52 +04:00
|
|
|
#if 0
|
|
|
|
#define RT_DPRINTF(__fmt, ...) do { } while (/*CONSTCOND*/0)
|
|
|
|
#else
|
|
|
|
#define RT_DPRINTF(__fmt, ...) /* do nothing */
|
|
|
|
#endif
|
|
|
|
|
2007-06-09 07:07:21 +04:00
|
|
|
struct rtwalk {
|
|
|
|
int (*rw_f)(struct rtentry *, void *);
|
|
|
|
void *rw_v;
|
|
|
|
};
|
2011-02-01 04:39:19 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Global data specific to the routing socket.
|
|
|
|
*/
|
|
|
|
struct route_info {
|
|
|
|
struct sockaddr ri_dst;
|
|
|
|
struct sockaddr ri_src;
|
|
|
|
struct route_cb ri_cb;
|
|
|
|
int ri_maxqlen;
|
|
|
|
struct ifqueue ri_intrq;
|
|
|
|
void *ri_sih;
|
|
|
|
};
|
|
|
|
|
|
|
|
extern struct route_info route_info;
|
2002-05-13 00:40:11 +04:00
|
|
|
extern struct rtstat rtstat;
|
1994-05-11 13:26:46 +04:00
|
|
|
|
1997-04-03 01:17:28 +04:00
|
|
|
struct socket;
|
|
|
|
|
2015-04-06 12:45:58 +03:00
|
|
|
void rt_init(void);
|
|
|
|
|
|
|
|
int rt_timer_add(struct rtentry *,
|
|
|
|
void(*)(struct rtentry *, struct rttimer *),
|
|
|
|
struct rttimer_queue *);
|
|
|
|
unsigned long
|
|
|
|
rt_timer_count(struct rttimer_queue *);
|
|
|
|
void rt_timer_queue_change(struct rttimer_queue *, long);
|
1998-04-29 07:41:49 +04:00
|
|
|
struct rttimer_queue *
|
2015-04-06 12:45:58 +03:00
|
|
|
rt_timer_queue_create(u_int);
|
2016-10-25 05:45:09 +03:00
|
|
|
void rt_timer_queue_destroy(struct rttimer_queue *);
|
2015-04-06 12:45:58 +03:00
|
|
|
|
2016-03-24 09:18:27 +03:00
|
|
|
void rt_newmsg(const int, const struct rtentry *);
|
1994-05-11 13:26:46 +04:00
|
|
|
struct rtentry *
|
2015-04-06 12:45:58 +03:00
|
|
|
rtalloc1(const struct sockaddr *, int);
|
|
|
|
void rtfree(struct rtentry *);
|
|
|
|
int rtinit(struct ifaddr *, int, int);
|
|
|
|
void rtredirect(const struct sockaddr *, const struct sockaddr *,
|
2004-04-21 08:17:28 +04:00
|
|
|
const struct sockaddr *, int, const struct sockaddr *,
|
2004-04-22 01:03:43 +04:00
|
|
|
struct rtentry **);
|
2015-04-06 12:45:58 +03:00
|
|
|
int rtrequest(int, const struct sockaddr *,
|
2004-04-21 08:17:28 +04:00
|
|
|
const struct sockaddr *, const struct sockaddr *, int,
|
2004-04-22 01:03:43 +04:00
|
|
|
struct rtentry **);
|
2015-04-06 12:45:58 +03:00
|
|
|
int rtrequest1(int, struct rt_addrinfo *, struct rtentry **);
|
2015-07-17 05:21:08 +03:00
|
|
|
int rtrequest_newmsg(const int, const struct sockaddr *,
|
|
|
|
const struct sockaddr *, const struct sockaddr *, const int);
|
2006-11-13 08:13:38 +03:00
|
|
|
|
2015-04-06 12:45:58 +03:00
|
|
|
int rt_ifa_addlocal(struct ifaddr *);
|
|
|
|
int rt_ifa_remlocal(struct ifaddr *, struct ifaddr *);
|
|
|
|
struct ifaddr *
|
|
|
|
rt_get_ifa(struct rtentry *);
|
2016-08-01 06:15:30 +03:00
|
|
|
struct ifaddr *
|
|
|
|
rt_getifa(struct rt_addrinfo *, struct psref *);
|
|
|
|
struct ifnet *
|
|
|
|
rt_getifp(struct rt_addrinfo *, struct psref *);
|
2006-12-16 00:18:52 +03:00
|
|
|
void rt_replace_ifa(struct rtentry *, struct ifaddr *);
|
2015-04-06 12:45:58 +03:00
|
|
|
int rt_setgate(struct rtentry *, const struct sockaddr *);
|
2006-12-16 00:18:52 +03:00
|
|
|
|
2015-04-06 12:45:58 +03:00
|
|
|
const struct sockaddr *
|
|
|
|
rt_settag(struct rtentry *, const struct sockaddr *);
|
|
|
|
struct sockaddr *
|
2016-04-28 03:16:56 +03:00
|
|
|
rt_gettag(const struct rtentry *);
|
2010-06-26 18:24:27 +04:00
|
|
|
|
2016-04-28 03:16:56 +03:00
|
|
|
int rt_check_reject_route(const struct rtentry *, const struct ifnet *);
|
2015-09-02 14:35:11 +03:00
|
|
|
|
2015-08-31 09:25:15 +03:00
|
|
|
static inline void
|
|
|
|
rt_assert_referenced(const struct rtentry *rt)
|
|
|
|
{
|
|
|
|
|
|
|
|
KASSERT(rt->rt_refcnt > 0);
|
|
|
|
}
|
|
|
|
|
2015-04-06 12:45:58 +03:00
|
|
|
void rtcache_copy(struct route *, const struct route *);
|
2006-12-16 00:18:52 +03:00
|
|
|
void rtcache_free(struct route *);
|
2015-04-06 12:45:58 +03:00
|
|
|
struct rtentry *
|
|
|
|
rtcache_init(struct route *);
|
|
|
|
struct rtentry *
|
|
|
|
rtcache_init_noclone(struct route *);
|
|
|
|
struct rtentry *
|
|
|
|
rtcache_lookup2(struct route *, const struct sockaddr *, int,
|
|
|
|
int *);
|
Eliminate address family-specific route caches (struct route, struct
route_in6, struct route_iso), replacing all caches with a struct
route.
The principle benefit of this change is that all of the protocol
families can benefit from route cache-invalidation, which is
necessary for correct routing. Route-cache invalidation fixes an
ancient PR, kern/3508, at long last; it fixes various other PRs,
also.
Discussions with and ideas from Joerg Sonnenberger influenced this
work tremendously. Of course, all design oversights and bugs are
mine.
DETAILS
1 I added to each address family a pool of sockaddrs. I have
introduced routines for allocating, copying, and duplicating,
and freeing sockaddrs:
struct sockaddr *sockaddr_alloc(sa_family_t af, int flags);
struct sockaddr *sockaddr_copy(struct sockaddr *dst,
const struct sockaddr *src);
struct sockaddr *sockaddr_dup(const struct sockaddr *src, int flags);
void sockaddr_free(struct sockaddr *sa);
sockaddr_alloc() returns either a sockaddr from the pool belonging
to the specified family, or NULL if the pool is exhausted. The
returned sockaddr has the right size for that family; sa_family
and sa_len fields are initialized to the family and sockaddr
length---e.g., sa_family = AF_INET and sa_len = sizeof(struct
sockaddr_in). sockaddr_free() puts the given sockaddr back into
its family's pool.
sockaddr_dup() and sockaddr_copy() work analogously to strdup()
and strcpy(), respectively. sockaddr_copy() KASSERTs that the
family of the destination and source sockaddrs are alike.
The 'flags' argumet for sockaddr_alloc() and sockaddr_dup() is
passed directly to pool_get(9).
2 I added routines for initializing sockaddrs in each address
family, sockaddr_in_init(), sockaddr_in6_init(), sockaddr_iso_init(),
etc. They are fairly self-explanatory.
3 structs route_in6 and route_iso are no more. All protocol families
use struct route. I have changed the route cache, 'struct route',
so that it does not contain storage space for a sockaddr. Instead,
struct route points to a sockaddr coming from the pool the sockaddr
belongs to. I added a new method to struct route, rtcache_setdst(),
for setting the cache destination:
int rtcache_setdst(struct route *, const struct sockaddr *);
rtcache_setdst() returns 0 on success, or ENOMEM if no memory is
available to create the sockaddr storage.
It is now possible for rtcache_getdst() to return NULL if, say,
rtcache_setdst() failed. I check the return value for NULL
everywhere in the kernel.
4 Each routing domain (struct domain) has a list of live route
caches, dom_rtcache. rtflushall(sa_family_t af) looks up the
domain indicated by 'af', walks the domain's list of route caches
and invalidates each one.
2007-05-03 00:40:22 +04:00
|
|
|
int rtcache_setdst(struct route *, const struct sockaddr *);
|
2015-04-06 12:45:58 +03:00
|
|
|
struct rtentry *
|
|
|
|
rtcache_update(struct route *, int);
|
2006-12-16 00:18:52 +03:00
|
|
|
|
*** Summary ***
When a link-layer address changes (e.g., ifconfig ex0 link
02:de:ad:be:ef:02 active), send a gratuitous ARP and/or a Neighbor
Advertisement to update the network-/link-layer address bindings
on our LAN peers.
Refuse a change of ethernet address to the address 00:00:00:00:00:00
or to any multicast/broadcast address. (Thanks matt@.)
Reorder ifnet ioctl operations so that driver ioctls may inherit
the functions of their "class"---ether_ioctl(), fddi_ioctl(), et
cetera---and the class ioctls may inherit from the generic ioctl,
ifioctl_common(), but both driver- and class-ioctls may override
the generic behavior. Make network drivers share more code.
Distinguish a "factory" link-layer address from others for the
purposes of both protecting that address from deletion and computing
EUI64.
Return consistent, appropriate error codes from network drivers.
Improve readability. KNF.
*** Details ***
In if_attach(), always initialize the interface ioctl routine,
ifnet->if_ioctl, if the driver has not already initialized it.
Delete if_ioctl == NULL tests everywhere else, because it cannot
happen.
In the ioctl routines of network interfaces, inherit common ioctl
behaviors by calling either ifioctl_common() or whichever ioctl
routine is appropriate for the class of interface---e.g., ether_ioctl()
for ethernets.
Stop (ab)using SIOCSIFADDR and start to use SIOCINITIFADDR. In
the user->kernel interface, SIOCSIFADDR's argument was an ifreq,
but on the protocol->ifnet interface, SIOCSIFADDR's argument was
an ifaddr. That was confusing, and it would work against me as I
make it possible for a network interface to overload most ioctls.
On the protocol->ifnet interface, replace SIOCSIFADDR with
SIOCINITIFADDR. In ifioctl(), return EPERM if userland tries to
invoke SIOCINITIFADDR.
In ifioctl(), give the interface the first shot at handling most
interface ioctls, and give the protocol the second shot, instead
of the other way around. Finally, let compatibility code (COMPAT_OSOCK)
take a shot.
Pull device initialization out of switch statements under
SIOCINITIFADDR. For example, pull ..._init() out of any switch
statement that looks like this:
switch (...->sa_family) {
case ...:
..._init();
...
break;
...
default:
..._init();
...
break;
}
Rewrite many if-else clauses that handle all permutations of IFF_UP
and IFF_RUNNING to use a switch statement,
switch (x & (IFF_UP|IFF_RUNNING)) {
case 0:
...
break;
case IFF_RUNNING:
...
break;
case IFF_UP:
...
break;
case IFF_UP|IFF_RUNNING:
...
break;
}
unifdef lots of code containing #ifdef FreeBSD, #ifdef NetBSD, and
#ifdef SIOCSIFMTU, especially in fwip(4) and in ndis(4).
In ipw(4), remove an if_set_sadl() call that is out of place.
In nfe(4), reuse the jumbo MTU logic in ether_ioctl().
Let ethernets register a callback for setting h/w state such as
promiscuous mode and the multicast filter in accord with a change
in the if_flags: ether_set_ifflags_cb() registers a callback that
returns ENETRESET if the caller should reset the ethernet by calling
if_init(), 0 on success, != 0 on failure. Pull common code from
ex(4), gem(4), nfe(4), sip(4), tlp(4), vge(4) into ether_ioctl(),
and register if_flags callbacks for those drivers.
Return ENOTTY instead of EINVAL for inappropriate ioctls. In
zyd(4), use ENXIO instead of ENOTTY to indicate that the device is
not any longer attached.
Add to if_set_sadl() a boolean 'factory' argument that indicates
whether a link-layer address was assigned by the factory or some
other source. In a comment, recommend using the factory address
for generating an EUI64, and update in6_get_hw_ifid() to prefer a
factory address to any other link-layer address.
Add a routing message, RTM_LLINFO_UPD, that tells protocols to
update the binding of network-layer addresses to link-layer addresses.
Implement this message in IPv4 and IPv6 by sending a gratuitous
ARP or a neighbor advertisement, respectively. Generate RTM_LLINFO_UPD
messages on a change of an interface's link-layer address.
In ether_ioctl(), do not let SIOCALIFADDR set a link-layer address
that is broadcast/multicast or equal to 00:00:00:00:00:00.
Make ether_ioctl() call ifioctl_common() to handle ioctls that it
does not understand.
In gif(4), initialize if_softc and use it, instead of assuming that
the gif_softc and ifp overlap.
Let ifioctl_common() handle SIOCGIFADDR.
Sprinkle rtcache_invariants(), which checks on DIAGNOSTIC kernels
that certain invariants on a struct route are satisfied.
In agr(4), rewrite agr_ioctl_filter() to be a bit more explicit
about the ioctls that we do not allow on an agr(4) member interface.
bzero -> memset. Delete unnecessary casts to void *. Use
sockaddr_in_init() and sockaddr_in6_init(). Compare pointers with
NULL instead of "testing truth". Replace some instances of (type
*)0 with NULL. Change some K&R prototypes to ANSI C, and join
lines.
2008-11-07 03:20:01 +03:00
|
|
|
static inline void
|
|
|
|
rtcache_invariants(const struct route *ro)
|
|
|
|
{
|
|
|
|
KASSERT(ro->ro_sa != NULL || ro->_ro_rt == NULL);
|
|
|
|
KASSERT(!ro->ro_invalid || ro->_ro_rt != NULL);
|
2015-08-24 07:44:54 +03:00
|
|
|
KASSERT(ro->_ro_rt == NULL || ro->_ro_rt->rt_refcnt > 0);
|
*** Summary ***
When a link-layer address changes (e.g., ifconfig ex0 link
02:de:ad:be:ef:02 active), send a gratuitous ARP and/or a Neighbor
Advertisement to update the network-/link-layer address bindings
on our LAN peers.
Refuse a change of ethernet address to the address 00:00:00:00:00:00
or to any multicast/broadcast address. (Thanks matt@.)
Reorder ifnet ioctl operations so that driver ioctls may inherit
the functions of their "class"---ether_ioctl(), fddi_ioctl(), et
cetera---and the class ioctls may inherit from the generic ioctl,
ifioctl_common(), but both driver- and class-ioctls may override
the generic behavior. Make network drivers share more code.
Distinguish a "factory" link-layer address from others for the
purposes of both protecting that address from deletion and computing
EUI64.
Return consistent, appropriate error codes from network drivers.
Improve readability. KNF.
*** Details ***
In if_attach(), always initialize the interface ioctl routine,
ifnet->if_ioctl, if the driver has not already initialized it.
Delete if_ioctl == NULL tests everywhere else, because it cannot
happen.
In the ioctl routines of network interfaces, inherit common ioctl
behaviors by calling either ifioctl_common() or whichever ioctl
routine is appropriate for the class of interface---e.g., ether_ioctl()
for ethernets.
Stop (ab)using SIOCSIFADDR and start to use SIOCINITIFADDR. In
the user->kernel interface, SIOCSIFADDR's argument was an ifreq,
but on the protocol->ifnet interface, SIOCSIFADDR's argument was
an ifaddr. That was confusing, and it would work against me as I
make it possible for a network interface to overload most ioctls.
On the protocol->ifnet interface, replace SIOCSIFADDR with
SIOCINITIFADDR. In ifioctl(), return EPERM if userland tries to
invoke SIOCINITIFADDR.
In ifioctl(), give the interface the first shot at handling most
interface ioctls, and give the protocol the second shot, instead
of the other way around. Finally, let compatibility code (COMPAT_OSOCK)
take a shot.
Pull device initialization out of switch statements under
SIOCINITIFADDR. For example, pull ..._init() out of any switch
statement that looks like this:
switch (...->sa_family) {
case ...:
..._init();
...
break;
...
default:
..._init();
...
break;
}
Rewrite many if-else clauses that handle all permutations of IFF_UP
and IFF_RUNNING to use a switch statement,
switch (x & (IFF_UP|IFF_RUNNING)) {
case 0:
...
break;
case IFF_RUNNING:
...
break;
case IFF_UP:
...
break;
case IFF_UP|IFF_RUNNING:
...
break;
}
unifdef lots of code containing #ifdef FreeBSD, #ifdef NetBSD, and
#ifdef SIOCSIFMTU, especially in fwip(4) and in ndis(4).
In ipw(4), remove an if_set_sadl() call that is out of place.
In nfe(4), reuse the jumbo MTU logic in ether_ioctl().
Let ethernets register a callback for setting h/w state such as
promiscuous mode and the multicast filter in accord with a change
in the if_flags: ether_set_ifflags_cb() registers a callback that
returns ENETRESET if the caller should reset the ethernet by calling
if_init(), 0 on success, != 0 on failure. Pull common code from
ex(4), gem(4), nfe(4), sip(4), tlp(4), vge(4) into ether_ioctl(),
and register if_flags callbacks for those drivers.
Return ENOTTY instead of EINVAL for inappropriate ioctls. In
zyd(4), use ENXIO instead of ENOTTY to indicate that the device is
not any longer attached.
Add to if_set_sadl() a boolean 'factory' argument that indicates
whether a link-layer address was assigned by the factory or some
other source. In a comment, recommend using the factory address
for generating an EUI64, and update in6_get_hw_ifid() to prefer a
factory address to any other link-layer address.
Add a routing message, RTM_LLINFO_UPD, that tells protocols to
update the binding of network-layer addresses to link-layer addresses.
Implement this message in IPv4 and IPv6 by sending a gratuitous
ARP or a neighbor advertisement, respectively. Generate RTM_LLINFO_UPD
messages on a change of an interface's link-layer address.
In ether_ioctl(), do not let SIOCALIFADDR set a link-layer address
that is broadcast/multicast or equal to 00:00:00:00:00:00.
Make ether_ioctl() call ifioctl_common() to handle ioctls that it
does not understand.
In gif(4), initialize if_softc and use it, instead of assuming that
the gif_softc and ifp overlap.
Let ifioctl_common() handle SIOCGIFADDR.
Sprinkle rtcache_invariants(), which checks on DIAGNOSTIC kernels
that certain invariants on a struct route are satisfied.
In agr(4), rewrite agr_ioctl_filter() to be a bit more explicit
about the ioctls that we do not allow on an agr(4) member interface.
bzero -> memset. Delete unnecessary casts to void *. Use
sockaddr_in_init() and sockaddr_in6_init(). Compare pointers with
NULL instead of "testing truth". Replace some instances of (type
*)0 with NULL. Change some K&R prototypes to ANSI C, and join
lines.
2008-11-07 03:20:01 +03:00
|
|
|
}
|
|
|
|
|
2007-05-06 06:17:54 +04:00
|
|
|
static inline struct rtentry *
|
|
|
|
rtcache_lookup1(struct route *ro, const struct sockaddr *dst, int clone)
|
|
|
|
{
|
|
|
|
int hit;
|
|
|
|
|
|
|
|
return rtcache_lookup2(ro, dst, clone, &hit);
|
|
|
|
}
|
|
|
|
|
Eliminate address family-specific route caches (struct route, struct
route_in6, struct route_iso), replacing all caches with a struct
route.
The principle benefit of this change is that all of the protocol
families can benefit from route cache-invalidation, which is
necessary for correct routing. Route-cache invalidation fixes an
ancient PR, kern/3508, at long last; it fixes various other PRs,
also.
Discussions with and ideas from Joerg Sonnenberger influenced this
work tremendously. Of course, all design oversights and bugs are
mine.
DETAILS
1 I added to each address family a pool of sockaddrs. I have
introduced routines for allocating, copying, and duplicating,
and freeing sockaddrs:
struct sockaddr *sockaddr_alloc(sa_family_t af, int flags);
struct sockaddr *sockaddr_copy(struct sockaddr *dst,
const struct sockaddr *src);
struct sockaddr *sockaddr_dup(const struct sockaddr *src, int flags);
void sockaddr_free(struct sockaddr *sa);
sockaddr_alloc() returns either a sockaddr from the pool belonging
to the specified family, or NULL if the pool is exhausted. The
returned sockaddr has the right size for that family; sa_family
and sa_len fields are initialized to the family and sockaddr
length---e.g., sa_family = AF_INET and sa_len = sizeof(struct
sockaddr_in). sockaddr_free() puts the given sockaddr back into
its family's pool.
sockaddr_dup() and sockaddr_copy() work analogously to strdup()
and strcpy(), respectively. sockaddr_copy() KASSERTs that the
family of the destination and source sockaddrs are alike.
The 'flags' argumet for sockaddr_alloc() and sockaddr_dup() is
passed directly to pool_get(9).
2 I added routines for initializing sockaddrs in each address
family, sockaddr_in_init(), sockaddr_in6_init(), sockaddr_iso_init(),
etc. They are fairly self-explanatory.
3 structs route_in6 and route_iso are no more. All protocol families
use struct route. I have changed the route cache, 'struct route',
so that it does not contain storage space for a sockaddr. Instead,
struct route points to a sockaddr coming from the pool the sockaddr
belongs to. I added a new method to struct route, rtcache_setdst(),
for setting the cache destination:
int rtcache_setdst(struct route *, const struct sockaddr *);
rtcache_setdst() returns 0 on success, or ENOMEM if no memory is
available to create the sockaddr storage.
It is now possible for rtcache_getdst() to return NULL if, say,
rtcache_setdst() failed. I check the return value for NULL
everywhere in the kernel.
4 Each routing domain (struct domain) has a list of live route
caches, dom_rtcache. rtflushall(sa_family_t af) looks up the
domain indicated by 'af', walks the domain's list of route caches
and invalidates each one.
2007-05-03 00:40:22 +04:00
|
|
|
static inline struct rtentry *
|
|
|
|
rtcache_lookup(struct route *ro, const struct sockaddr *dst)
|
KNF: de-__P, bzero -> memset, bcmp -> memcmp. Remove extraneous
parentheses in return statements.
Cosmetic: don't open-code TAILQ_FOREACH().
Cosmetic: change types of variables to avoid oodles of casts: in
in6_src.c, avoid casts by changing several route_in6 pointers
to struct route pointers. Remove unnecessary casts to caddr_t
elsewhere.
Pave the way for eliminating address family-specific route caches:
soon, struct route will not embed a sockaddr, but it will hold
a reference to an external sockaddr, instead. We will set the
destination sockaddr using rtcache_setdst(). (I created a stub
for it, but it isn't used anywhere, yet.) rtcache_free() will
free the sockaddr. I have extracted from rtcache_free() a helper
subroutine, rtcache_clear(). rtcache_clear() will "forget" a
cached route, but it will not forget the destination by releasing
the sockaddr. I use rtcache_clear() instead of rtcache_free()
in rtcache_update(), because rtcache_update() is not supposed
to forget the destination.
Constify:
1 Introduce const accessor for route->ro_dst, rtcache_getdst().
2 Constify the 'dst' argument to ifnet->if_output(). This
led me to constify a lot of code called by output routines.
3 Constify the sockaddr argument to protosw->pr_ctlinput. This
led me to constify a lot of code called by ctlinput routines.
4 Introduce const macros for converting from a generic sockaddr
to family-specific sockaddrs, e.g., sockaddr_in: satocsin6,
satocsin, et cetera.
2007-02-18 01:34:07 +03:00
|
|
|
{
|
Eliminate address family-specific route caches (struct route, struct
route_in6, struct route_iso), replacing all caches with a struct
route.
The principle benefit of this change is that all of the protocol
families can benefit from route cache-invalidation, which is
necessary for correct routing. Route-cache invalidation fixes an
ancient PR, kern/3508, at long last; it fixes various other PRs,
also.
Discussions with and ideas from Joerg Sonnenberger influenced this
work tremendously. Of course, all design oversights and bugs are
mine.
DETAILS
1 I added to each address family a pool of sockaddrs. I have
introduced routines for allocating, copying, and duplicating,
and freeing sockaddrs:
struct sockaddr *sockaddr_alloc(sa_family_t af, int flags);
struct sockaddr *sockaddr_copy(struct sockaddr *dst,
const struct sockaddr *src);
struct sockaddr *sockaddr_dup(const struct sockaddr *src, int flags);
void sockaddr_free(struct sockaddr *sa);
sockaddr_alloc() returns either a sockaddr from the pool belonging
to the specified family, or NULL if the pool is exhausted. The
returned sockaddr has the right size for that family; sa_family
and sa_len fields are initialized to the family and sockaddr
length---e.g., sa_family = AF_INET and sa_len = sizeof(struct
sockaddr_in). sockaddr_free() puts the given sockaddr back into
its family's pool.
sockaddr_dup() and sockaddr_copy() work analogously to strdup()
and strcpy(), respectively. sockaddr_copy() KASSERTs that the
family of the destination and source sockaddrs are alike.
The 'flags' argumet for sockaddr_alloc() and sockaddr_dup() is
passed directly to pool_get(9).
2 I added routines for initializing sockaddrs in each address
family, sockaddr_in_init(), sockaddr_in6_init(), sockaddr_iso_init(),
etc. They are fairly self-explanatory.
3 structs route_in6 and route_iso are no more. All protocol families
use struct route. I have changed the route cache, 'struct route',
so that it does not contain storage space for a sockaddr. Instead,
struct route points to a sockaddr coming from the pool the sockaddr
belongs to. I added a new method to struct route, rtcache_setdst(),
for setting the cache destination:
int rtcache_setdst(struct route *, const struct sockaddr *);
rtcache_setdst() returns 0 on success, or ENOMEM if no memory is
available to create the sockaddr storage.
It is now possible for rtcache_getdst() to return NULL if, say,
rtcache_setdst() failed. I check the return value for NULL
everywhere in the kernel.
4 Each routing domain (struct domain) has a list of live route
caches, dom_rtcache. rtflushall(sa_family_t af) looks up the
domain indicated by 'af', walks the domain's list of route caches
and invalidates each one.
2007-05-03 00:40:22 +04:00
|
|
|
return rtcache_lookup1(ro, dst, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline const struct sockaddr *
|
|
|
|
rtcache_getdst(const struct route *ro)
|
|
|
|
{
|
*** Summary ***
When a link-layer address changes (e.g., ifconfig ex0 link
02:de:ad:be:ef:02 active), send a gratuitous ARP and/or a Neighbor
Advertisement to update the network-/link-layer address bindings
on our LAN peers.
Refuse a change of ethernet address to the address 00:00:00:00:00:00
or to any multicast/broadcast address. (Thanks matt@.)
Reorder ifnet ioctl operations so that driver ioctls may inherit
the functions of their "class"---ether_ioctl(), fddi_ioctl(), et
cetera---and the class ioctls may inherit from the generic ioctl,
ifioctl_common(), but both driver- and class-ioctls may override
the generic behavior. Make network drivers share more code.
Distinguish a "factory" link-layer address from others for the
purposes of both protecting that address from deletion and computing
EUI64.
Return consistent, appropriate error codes from network drivers.
Improve readability. KNF.
*** Details ***
In if_attach(), always initialize the interface ioctl routine,
ifnet->if_ioctl, if the driver has not already initialized it.
Delete if_ioctl == NULL tests everywhere else, because it cannot
happen.
In the ioctl routines of network interfaces, inherit common ioctl
behaviors by calling either ifioctl_common() or whichever ioctl
routine is appropriate for the class of interface---e.g., ether_ioctl()
for ethernets.
Stop (ab)using SIOCSIFADDR and start to use SIOCINITIFADDR. In
the user->kernel interface, SIOCSIFADDR's argument was an ifreq,
but on the protocol->ifnet interface, SIOCSIFADDR's argument was
an ifaddr. That was confusing, and it would work against me as I
make it possible for a network interface to overload most ioctls.
On the protocol->ifnet interface, replace SIOCSIFADDR with
SIOCINITIFADDR. In ifioctl(), return EPERM if userland tries to
invoke SIOCINITIFADDR.
In ifioctl(), give the interface the first shot at handling most
interface ioctls, and give the protocol the second shot, instead
of the other way around. Finally, let compatibility code (COMPAT_OSOCK)
take a shot.
Pull device initialization out of switch statements under
SIOCINITIFADDR. For example, pull ..._init() out of any switch
statement that looks like this:
switch (...->sa_family) {
case ...:
..._init();
...
break;
...
default:
..._init();
...
break;
}
Rewrite many if-else clauses that handle all permutations of IFF_UP
and IFF_RUNNING to use a switch statement,
switch (x & (IFF_UP|IFF_RUNNING)) {
case 0:
...
break;
case IFF_RUNNING:
...
break;
case IFF_UP:
...
break;
case IFF_UP|IFF_RUNNING:
...
break;
}
unifdef lots of code containing #ifdef FreeBSD, #ifdef NetBSD, and
#ifdef SIOCSIFMTU, especially in fwip(4) and in ndis(4).
In ipw(4), remove an if_set_sadl() call that is out of place.
In nfe(4), reuse the jumbo MTU logic in ether_ioctl().
Let ethernets register a callback for setting h/w state such as
promiscuous mode and the multicast filter in accord with a change
in the if_flags: ether_set_ifflags_cb() registers a callback that
returns ENETRESET if the caller should reset the ethernet by calling
if_init(), 0 on success, != 0 on failure. Pull common code from
ex(4), gem(4), nfe(4), sip(4), tlp(4), vge(4) into ether_ioctl(),
and register if_flags callbacks for those drivers.
Return ENOTTY instead of EINVAL for inappropriate ioctls. In
zyd(4), use ENXIO instead of ENOTTY to indicate that the device is
not any longer attached.
Add to if_set_sadl() a boolean 'factory' argument that indicates
whether a link-layer address was assigned by the factory or some
other source. In a comment, recommend using the factory address
for generating an EUI64, and update in6_get_hw_ifid() to prefer a
factory address to any other link-layer address.
Add a routing message, RTM_LLINFO_UPD, that tells protocols to
update the binding of network-layer addresses to link-layer addresses.
Implement this message in IPv4 and IPv6 by sending a gratuitous
ARP or a neighbor advertisement, respectively. Generate RTM_LLINFO_UPD
messages on a change of an interface's link-layer address.
In ether_ioctl(), do not let SIOCALIFADDR set a link-layer address
that is broadcast/multicast or equal to 00:00:00:00:00:00.
Make ether_ioctl() call ifioctl_common() to handle ioctls that it
does not understand.
In gif(4), initialize if_softc and use it, instead of assuming that
the gif_softc and ifp overlap.
Let ifioctl_common() handle SIOCGIFADDR.
Sprinkle rtcache_invariants(), which checks on DIAGNOSTIC kernels
that certain invariants on a struct route are satisfied.
In agr(4), rewrite agr_ioctl_filter() to be a bit more explicit
about the ioctls that we do not allow on an agr(4) member interface.
bzero -> memset. Delete unnecessary casts to void *. Use
sockaddr_in_init() and sockaddr_in6_init(). Compare pointers with
NULL instead of "testing truth". Replace some instances of (type
*)0 with NULL. Change some K&R prototypes to ANSI C, and join
lines.
2008-11-07 03:20:01 +03:00
|
|
|
rtcache_invariants(ro);
|
Eliminate address family-specific route caches (struct route, struct
route_in6, struct route_iso), replacing all caches with a struct
route.
The principle benefit of this change is that all of the protocol
families can benefit from route cache-invalidation, which is
necessary for correct routing. Route-cache invalidation fixes an
ancient PR, kern/3508, at long last; it fixes various other PRs,
also.
Discussions with and ideas from Joerg Sonnenberger influenced this
work tremendously. Of course, all design oversights and bugs are
mine.
DETAILS
1 I added to each address family a pool of sockaddrs. I have
introduced routines for allocating, copying, and duplicating,
and freeing sockaddrs:
struct sockaddr *sockaddr_alloc(sa_family_t af, int flags);
struct sockaddr *sockaddr_copy(struct sockaddr *dst,
const struct sockaddr *src);
struct sockaddr *sockaddr_dup(const struct sockaddr *src, int flags);
void sockaddr_free(struct sockaddr *sa);
sockaddr_alloc() returns either a sockaddr from the pool belonging
to the specified family, or NULL if the pool is exhausted. The
returned sockaddr has the right size for that family; sa_family
and sa_len fields are initialized to the family and sockaddr
length---e.g., sa_family = AF_INET and sa_len = sizeof(struct
sockaddr_in). sockaddr_free() puts the given sockaddr back into
its family's pool.
sockaddr_dup() and sockaddr_copy() work analogously to strdup()
and strcpy(), respectively. sockaddr_copy() KASSERTs that the
family of the destination and source sockaddrs are alike.
The 'flags' argumet for sockaddr_alloc() and sockaddr_dup() is
passed directly to pool_get(9).
2 I added routines for initializing sockaddrs in each address
family, sockaddr_in_init(), sockaddr_in6_init(), sockaddr_iso_init(),
etc. They are fairly self-explanatory.
3 structs route_in6 and route_iso are no more. All protocol families
use struct route. I have changed the route cache, 'struct route',
so that it does not contain storage space for a sockaddr. Instead,
struct route points to a sockaddr coming from the pool the sockaddr
belongs to. I added a new method to struct route, rtcache_setdst(),
for setting the cache destination:
int rtcache_setdst(struct route *, const struct sockaddr *);
rtcache_setdst() returns 0 on success, or ENOMEM if no memory is
available to create the sockaddr storage.
It is now possible for rtcache_getdst() to return NULL if, say,
rtcache_setdst() failed. I check the return value for NULL
everywhere in the kernel.
4 Each routing domain (struct domain) has a list of live route
caches, dom_rtcache. rtflushall(sa_family_t af) looks up the
domain indicated by 'af', walks the domain's list of route caches
and invalidates each one.
2007-05-03 00:40:22 +04:00
|
|
|
return ro->ro_sa;
|
KNF: de-__P, bzero -> memset, bcmp -> memcmp. Remove extraneous
parentheses in return statements.
Cosmetic: don't open-code TAILQ_FOREACH().
Cosmetic: change types of variables to avoid oodles of casts: in
in6_src.c, avoid casts by changing several route_in6 pointers
to struct route pointers. Remove unnecessary casts to caddr_t
elsewhere.
Pave the way for eliminating address family-specific route caches:
soon, struct route will not embed a sockaddr, but it will hold
a reference to an external sockaddr, instead. We will set the
destination sockaddr using rtcache_setdst(). (I created a stub
for it, but it isn't used anywhere, yet.) rtcache_free() will
free the sockaddr. I have extracted from rtcache_free() a helper
subroutine, rtcache_clear(). rtcache_clear() will "forget" a
cached route, but it will not forget the destination by releasing
the sockaddr. I use rtcache_clear() instead of rtcache_free()
in rtcache_update(), because rtcache_update() is not supposed
to forget the destination.
Constify:
1 Introduce const accessor for route->ro_dst, rtcache_getdst().
2 Constify the 'dst' argument to ifnet->if_output(). This
led me to constify a lot of code called by output routines.
3 Constify the sockaddr argument to protosw->pr_ctlinput. This
led me to constify a lot of code called by ctlinput routines.
4 Introduce const macros for converting from a generic sockaddr
to family-specific sockaddrs, e.g., sockaddr_in: satocsin6,
satocsin, et cetera.
2007-02-18 01:34:07 +03:00
|
|
|
}
|
|
|
|
|
2008-01-11 04:38:45 +03:00
|
|
|
/* If the cache is not empty, and the cached route is still present
|
|
|
|
* in the routing table, return the cached route. Otherwise, return
|
|
|
|
* NULL.
|
2007-05-06 06:17:54 +04:00
|
|
|
*/
|
2008-01-05 02:26:44 +03:00
|
|
|
static inline struct rtentry *
|
|
|
|
rtcache_validate(const struct route *ro)
|
2007-05-06 06:17:54 +04:00
|
|
|
{
|
2008-01-05 02:26:44 +03:00
|
|
|
struct rtentry *rt = ro->_ro_rt;
|
|
|
|
|
*** Summary ***
When a link-layer address changes (e.g., ifconfig ex0 link
02:de:ad:be:ef:02 active), send a gratuitous ARP and/or a Neighbor
Advertisement to update the network-/link-layer address bindings
on our LAN peers.
Refuse a change of ethernet address to the address 00:00:00:00:00:00
or to any multicast/broadcast address. (Thanks matt@.)
Reorder ifnet ioctl operations so that driver ioctls may inherit
the functions of their "class"---ether_ioctl(), fddi_ioctl(), et
cetera---and the class ioctls may inherit from the generic ioctl,
ifioctl_common(), but both driver- and class-ioctls may override
the generic behavior. Make network drivers share more code.
Distinguish a "factory" link-layer address from others for the
purposes of both protecting that address from deletion and computing
EUI64.
Return consistent, appropriate error codes from network drivers.
Improve readability. KNF.
*** Details ***
In if_attach(), always initialize the interface ioctl routine,
ifnet->if_ioctl, if the driver has not already initialized it.
Delete if_ioctl == NULL tests everywhere else, because it cannot
happen.
In the ioctl routines of network interfaces, inherit common ioctl
behaviors by calling either ifioctl_common() or whichever ioctl
routine is appropriate for the class of interface---e.g., ether_ioctl()
for ethernets.
Stop (ab)using SIOCSIFADDR and start to use SIOCINITIFADDR. In
the user->kernel interface, SIOCSIFADDR's argument was an ifreq,
but on the protocol->ifnet interface, SIOCSIFADDR's argument was
an ifaddr. That was confusing, and it would work against me as I
make it possible for a network interface to overload most ioctls.
On the protocol->ifnet interface, replace SIOCSIFADDR with
SIOCINITIFADDR. In ifioctl(), return EPERM if userland tries to
invoke SIOCINITIFADDR.
In ifioctl(), give the interface the first shot at handling most
interface ioctls, and give the protocol the second shot, instead
of the other way around. Finally, let compatibility code (COMPAT_OSOCK)
take a shot.
Pull device initialization out of switch statements under
SIOCINITIFADDR. For example, pull ..._init() out of any switch
statement that looks like this:
switch (...->sa_family) {
case ...:
..._init();
...
break;
...
default:
..._init();
...
break;
}
Rewrite many if-else clauses that handle all permutations of IFF_UP
and IFF_RUNNING to use a switch statement,
switch (x & (IFF_UP|IFF_RUNNING)) {
case 0:
...
break;
case IFF_RUNNING:
...
break;
case IFF_UP:
...
break;
case IFF_UP|IFF_RUNNING:
...
break;
}
unifdef lots of code containing #ifdef FreeBSD, #ifdef NetBSD, and
#ifdef SIOCSIFMTU, especially in fwip(4) and in ndis(4).
In ipw(4), remove an if_set_sadl() call that is out of place.
In nfe(4), reuse the jumbo MTU logic in ether_ioctl().
Let ethernets register a callback for setting h/w state such as
promiscuous mode and the multicast filter in accord with a change
in the if_flags: ether_set_ifflags_cb() registers a callback that
returns ENETRESET if the caller should reset the ethernet by calling
if_init(), 0 on success, != 0 on failure. Pull common code from
ex(4), gem(4), nfe(4), sip(4), tlp(4), vge(4) into ether_ioctl(),
and register if_flags callbacks for those drivers.
Return ENOTTY instead of EINVAL for inappropriate ioctls. In
zyd(4), use ENXIO instead of ENOTTY to indicate that the device is
not any longer attached.
Add to if_set_sadl() a boolean 'factory' argument that indicates
whether a link-layer address was assigned by the factory or some
other source. In a comment, recommend using the factory address
for generating an EUI64, and update in6_get_hw_ifid() to prefer a
factory address to any other link-layer address.
Add a routing message, RTM_LLINFO_UPD, that tells protocols to
update the binding of network-layer addresses to link-layer addresses.
Implement this message in IPv4 and IPv6 by sending a gratuitous
ARP or a neighbor advertisement, respectively. Generate RTM_LLINFO_UPD
messages on a change of an interface's link-layer address.
In ether_ioctl(), do not let SIOCALIFADDR set a link-layer address
that is broadcast/multicast or equal to 00:00:00:00:00:00.
Make ether_ioctl() call ifioctl_common() to handle ioctls that it
does not understand.
In gif(4), initialize if_softc and use it, instead of assuming that
the gif_softc and ifp overlap.
Let ifioctl_common() handle SIOCGIFADDR.
Sprinkle rtcache_invariants(), which checks on DIAGNOSTIC kernels
that certain invariants on a struct route are satisfied.
In agr(4), rewrite agr_ioctl_filter() to be a bit more explicit
about the ioctls that we do not allow on an agr(4) member interface.
bzero -> memset. Delete unnecessary casts to void *. Use
sockaddr_in_init() and sockaddr_in6_init(). Compare pointers with
NULL instead of "testing truth". Replace some instances of (type
*)0 with NULL. Change some K&R prototypes to ANSI C, and join
lines.
2008-11-07 03:20:01 +03:00
|
|
|
rtcache_invariants(ro);
|
|
|
|
|
2008-01-21 12:11:24 +03:00
|
|
|
if (ro->ro_invalid)
|
|
|
|
return NULL;
|
|
|
|
|
2008-01-05 02:26:44 +03:00
|
|
|
if (rt != NULL && (rt->rt_flags & RTF_UP) != 0 && rt->rt_ifp != NULL)
|
|
|
|
return rt;
|
|
|
|
return NULL;
|
|
|
|
|
2007-05-06 06:17:54 +04:00
|
|
|
}
|
|
|
|
|
2015-04-06 12:45:58 +03:00
|
|
|
/* rtsock */
|
|
|
|
void rt_ieee80211msg(struct ifnet *, int, void *, size_t);
|
|
|
|
void rt_ifannouncemsg(struct ifnet *, int);
|
|
|
|
void rt_ifmsg(struct ifnet *);
|
|
|
|
void rt_missmsg(int, const struct rt_addrinfo *, int, int);
|
|
|
|
struct mbuf *
|
|
|
|
rt_msg1(int, struct rt_addrinfo *, void *, int);
|
2016-04-04 10:37:07 +03:00
|
|
|
int rt_msg3(int, struct rt_addrinfo *, void *, struct rt_walkarg *, int *);
|
2015-04-06 12:45:58 +03:00
|
|
|
void rt_newaddrmsg(int, struct ifaddr *, int, struct rtentry *);
|
|
|
|
void route_enqueue(struct mbuf *, int);
|
|
|
|
|
|
|
|
/* rtbl */
|
|
|
|
int rt_addaddr(rtbl_t *, struct rtentry *, const struct sockaddr *);
|
|
|
|
void rt_assert_inactive(const struct rtentry *);
|
|
|
|
struct rtentry *
|
|
|
|
rt_deladdr(rtbl_t *, const struct sockaddr *,
|
|
|
|
const struct sockaddr *);
|
2011-03-31 23:40:51 +04:00
|
|
|
rtbl_t *rt_gettable(sa_family_t);
|
2015-04-06 12:45:58 +03:00
|
|
|
int rt_inithead(rtbl_t **, int);
|
|
|
|
struct rtentry *
|
|
|
|
rt_lookup(rtbl_t *, const struct sockaddr *,
|
|
|
|
const struct sockaddr *);
|
|
|
|
struct rtentry *
|
|
|
|
rt_matchaddr(rtbl_t *, const struct sockaddr *);
|
2016-04-11 12:21:18 +03:00
|
|
|
int rt_refines(const struct sockaddr *, const struct sockaddr *);
|
2015-04-06 12:45:58 +03:00
|
|
|
int rt_walktree(sa_family_t, int (*)(struct rtentry *, void *), void *);
|
|
|
|
void rtbl_init(void);
|
2007-06-09 07:07:21 +04:00
|
|
|
|
1995-03-27 00:23:52 +04:00
|
|
|
#endif /* _KERNEL */
|
2011-03-31 23:40:51 +04:00
|
|
|
|
2005-12-11 02:21:38 +03:00
|
|
|
#endif /* !_NET_ROUTE_H_ */
|