diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2010-05-19 13:09:10 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2010-05-19 13:09:10 +0000 |
commit | a5b90350387baa303cd9c624c294afc310b07e50 (patch) | |
tree | e419d0a02c48b5abad16c5220db8193b74925f47 /sys/net/rtsock.c | |
parent | 4c3903cd45cda5f0ec7b5cc3335eedd86187a60f (diff) |
Require RTF_MPLS to be set when a mpls route is added or changed. To remove
only the MPLS bits from a route set rtm_fmask to RTF_MPLS. Additionally check
if the nexthop is modified and in that case always remove the MPLS info since
the path changed. This change makes life in userland a lot easier since the
routing daemons normaly don't know about MPLS and until now they destroyed
MPLS information when issuing RTM_CHANGEs.
OK michele@
Diffstat (limited to 'sys/net/rtsock.c')
-rw-r--r-- | sys/net/rtsock.c | 87 |
1 files changed, 45 insertions, 42 deletions
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index ac5cfdad10d..4dff661d0b3 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtsock.c,v 1.99 2010/04/21 11:52:46 claudio Exp $ */ +/* $OpenBSD: rtsock.c,v 1.100 2010/05/19 13:09:09 claudio Exp $ */ /* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */ /* @@ -79,7 +79,7 @@ #ifdef MPLS #include <netmpls/mpls.h> -#endif /* MPLS */ +#endif #include <sys/stdarg.h> @@ -158,7 +158,7 @@ route_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, #ifdef MPLS else if (af == AF_MPLS) route_cb.mpls_count++; -#endif /* MPLS */ +#endif rp->rcb_faddr = &route_src; route_cb.any_count++; soisconnected(so); @@ -175,7 +175,7 @@ route_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, #ifdef MPLS else if (af == AF_MPLS) route_cb.mpls_count--; -#endif /* MPLS */ +#endif route_cb.any_count--; } /* FALLTHROUGH */ @@ -321,7 +321,7 @@ route_output(struct mbuf *m, ...) struct rtentry *saved_nrt = NULL; struct radix_node_head *rnh; struct rt_addrinfo info; - int len, error = 0; + int len, newgate, error = 0; struct ifnet *ifp = NULL; struct ifaddr *ifa = NULL; struct socket *so; @@ -454,8 +454,9 @@ route_output(struct mbuf *m, ...) saved_nrt->rt_refcnt--; saved_nrt->rt_genmask = genmask; /* write back the priority the kernel used */ - rtm->rtm_index = saved_nrt->rt_ifp->if_index; rtm->rtm_priority = saved_nrt->rt_priority & RTP_MASK; + rtm->rtm_index = saved_nrt->rt_ifp->if_index; + rtm->rtm_flags = saved_nrt->rt_flags; } break; case RTM_DELETE: @@ -615,6 +616,11 @@ report: */ if ((error = rt_getifa(&info, tableid)) != 0) goto flush; + newgate = 0; + if (gate) + if (rt->rt_gateway == NULL || + bcmp(rt->rt_gateway, gate, gate->sa_len)) + newgate = 1; if (gate && rt_setgate(rt, rt_key(rt), gate, tableid)) { error = EDQUOT; goto flush; @@ -646,31 +652,18 @@ report: #endif } } - - /* XXX Hack to allow some flags to be toggled */ - if (rtm->rtm_fmask & RTF_FMASK) - rt->rt_flags = (rt->rt_flags & - ~rtm->rtm_fmask) | - (rtm->rtm_flags & rtm->rtm_fmask); - - rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, - &rt->rt_rmx); - rtm->rtm_index = rt->rt_ifp->if_index; - rtm->rtm_priority = rt->rt_priority & RTP_MASK; - rtm->rtm_flags = rt->rt_flags; - if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) - rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &info); - if (genmask) - rt->rt_genmask = genmask; - if (info.rti_info[RTAX_LABEL] != NULL) { - char *rtlabel = ((struct sockaddr_rtlabel *) - info.rti_info[RTAX_LABEL])->sr_label; - rtlabel_unref(rt->rt_labelid); - rt->rt_labelid = - rtlabel_name2id(rtlabel); - } #ifdef MPLS - if (info.rti_info[RTAX_SRC] != NULL) { + /* if gateway changed remove MPLS information */ + if (newgate || ((rtm->rtm_fmask & RTF_MPLS) && + !(rtm->rtm_flags & RTF_MPLS))) { + if (rt->rt_llinfo != NULL && + rt->rt_flags & RTF_MPLS) { + free(rt->rt_llinfo, M_TEMP); + rt->rt_llinfo = NULL; + rt->rt_flags &= ~RTF_MPLS; + } + } else if ((rtm->rtm_flags & RTF_MPLS) && + info.rti_info[RTAX_SRC] != NULL) { struct rt_mpls *rt_mpls; psa_mpls = (struct sockaddr_mpls *) @@ -698,16 +691,30 @@ report: /* XXX: set experimental bits */ rt->rt_flags |= RTF_MPLS; - } else { - if (rt->rt_llinfo != NULL && - rt->rt_flags & RTF_MPLS) { - free(rt->rt_llinfo, M_TEMP); - rt->rt_llinfo = NULL; - - rt->rt_flags &= (~RTF_MPLS); - } } #endif + /* Hack to allow some flags to be toggled */ + if (rtm->rtm_fmask & RTF_FMASK) + rt->rt_flags = (rt->rt_flags & + ~rtm->rtm_fmask) | + (rtm->rtm_flags & rtm->rtm_fmask); + + rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, + &rt->rt_rmx); + rtm->rtm_index = rt->rt_ifp->if_index; + rtm->rtm_priority = rt->rt_priority & RTP_MASK; + rtm->rtm_flags = rt->rt_flags; + if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) + rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &info); + if (genmask) + rt->rt_genmask = genmask; + if (info.rti_info[RTAX_LABEL] != NULL) { + char *rtlabel = ((struct sockaddr_rtlabel *) + info.rti_info[RTAX_LABEL])->sr_label; + rtlabel_unref(rt->rt_labelid); + rt->rt_labelid = + rtlabel_name2id(rtlabel); + } if_group_routechange(dst, netmask); /* FALLTHROUGH */ case RTM_LOCK: @@ -729,10 +736,6 @@ flush: if (error) rtm->rtm_errno = error; else { -#ifdef MPLS - if (rt && rt->rt_flags & RTF_MPLS) - rtm->rtm_flags |= RTF_MPLS; -#endif rtm->rtm_flags |= RTF_DONE; } } |