Fix long-standing issue with interface routes being unprotected:
Use RTM_PINNED flag to mark route as immutable. Forbid deleting immutable routes without special rtrequest1_fib() flag. Adding interface address with prefix already in route table is handled by atomically deleting old prefix and adding interface one. Discussed with: andre, eri MFC after: 3 weeks
This commit is contained in:
parent
5cda6006e4
commit
3034f43f2f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=248070
@ -1357,7 +1357,8 @@ if_rtdel(struct radix_node *rn, void *arg)
|
||||
return (0);
|
||||
|
||||
err = rtrequest_fib(RTM_DELETE, rt_key(rt), rt->rt_gateway,
|
||||
rt_mask(rt), rt->rt_flags|RTF_RNH_LOCKED,
|
||||
rt_mask(rt),
|
||||
rt->rt_flags|RTF_RNH_LOCKED|RTF_PINNED,
|
||||
(struct rtentry **) NULL, rt->rt_fibnum);
|
||||
if (err) {
|
||||
log(LOG_WARNING, "if_rtdel: error %d\n", err);
|
||||
|
@ -1112,6 +1112,14 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
|
||||
error = 0;
|
||||
}
|
||||
#endif
|
||||
if ((flags & RTF_PINNED) == 0) {
|
||||
/* Check if target route can be deleted */
|
||||
rt = (struct rtentry *)rnh->rnh_lookup(dst,
|
||||
netmask, rnh);
|
||||
if ((rt != NULL) && (rt->rt_flags & RTF_PINNED))
|
||||
senderr(EADDRINUSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the item from the tree and return it.
|
||||
* Complain if it is not there and do no more processing.
|
||||
@ -1430,6 +1438,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
|
||||
int didwork = 0;
|
||||
int a_failure = 0;
|
||||
static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
|
||||
struct radix_node_head *rnh;
|
||||
|
||||
if (flags & RTF_HOST) {
|
||||
dst = ifa->ifa_dstaddr;
|
||||
@ -1488,7 +1497,6 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
|
||||
*/
|
||||
for ( fibnum = startfib; fibnum <= endfib; fibnum++) {
|
||||
if (cmd == RTM_DELETE) {
|
||||
struct radix_node_head *rnh;
|
||||
struct radix_node *rn;
|
||||
/*
|
||||
* Look up an rtentry that is in the routing tree and
|
||||
@ -1538,7 +1546,8 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
|
||||
*/
|
||||
bzero((caddr_t)&info, sizeof(info));
|
||||
info.rti_ifa = ifa;
|
||||
info.rti_flags = flags | (ifa->ifa_flags & ~IFA_RTSELF);
|
||||
info.rti_flags = flags |
|
||||
(ifa->ifa_flags & ~IFA_RTSELF) | RTF_PINNED;
|
||||
info.rti_info[RTAX_DST] = dst;
|
||||
/*
|
||||
* doing this for compatibility reasons
|
||||
@ -1550,6 +1559,33 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
|
||||
info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
|
||||
info.rti_info[RTAX_NETMASK] = netmask;
|
||||
error = rtrequest1_fib(cmd, &info, &rt, fibnum);
|
||||
|
||||
if ((error == EEXIST) && (cmd == RTM_ADD)) {
|
||||
/*
|
||||
* Interface route addition failed.
|
||||
* Atomically delete current prefix generating
|
||||
* RTM_DELETE message, and retry adding
|
||||
* interface prefix.
|
||||
*/
|
||||
rnh = rt_tables_get_rnh(fibnum, dst->sa_family);
|
||||
RADIX_NODE_HEAD_LOCK(rnh);
|
||||
|
||||
/* Delete old prefix */
|
||||
info.rti_ifa = NULL;
|
||||
info.rti_flags = RTF_RNH_LOCKED;
|
||||
|
||||
error = rtrequest1_fib(RTM_DELETE, &info, &rt, fibnum);
|
||||
if (error == 0) {
|
||||
info.rti_ifa = ifa;
|
||||
info.rti_flags = flags | RTF_RNH_LOCKED |
|
||||
(ifa->ifa_flags & ~IFA_RTSELF) | RTF_PINNED;
|
||||
error = rtrequest1_fib(cmd, &info, &rt, fibnum);
|
||||
}
|
||||
|
||||
RADIX_NODE_HEAD_UNLOCK(rnh);
|
||||
}
|
||||
|
||||
|
||||
if (error == 0 && rt != NULL) {
|
||||
/*
|
||||
* notify any listening routing agents of the change
|
||||
|
@ -176,7 +176,7 @@ struct ortentry {
|
||||
/* 0x20000 unused, was RTF_WASCLONED */
|
||||
#define RTF_PROTO3 0x40000 /* protocol specific routing flag */
|
||||
/* 0x80000 unused */
|
||||
#define RTF_PINNED 0x100000 /* future use */
|
||||
#define RTF_PINNED 0x100000 /* route is immutable */
|
||||
#define RTF_LOCAL 0x200000 /* route represents a local address */
|
||||
#define RTF_BROADCAST 0x400000 /* route represents a bcast address */
|
||||
#define RTF_MULTICAST 0x800000 /* route represents a mcast address */
|
||||
|
Loading…
Reference in New Issue
Block a user