diff options
author | Guillaume Nault <g.nault@alphalink.fr> | 2018-02-20 18:50:25 +0100 |
---|---|---|
committer | Dmitry Kozlov <xeb@mail.ru> | 2018-02-21 22:25:20 +0300 |
commit | 8ab2f623fa1d11a2aaec35226cb7a1456fc257d8 (patch) | |
tree | 093d82941fa97d7726bd5e1870c69b1e346aa8a1 | |
parent | c99e2092e9ad048e61110fd094d72e3d55cb49bc (diff) | |
download | accel-ppp-8ab2f623fa1d11a2aaec35226cb7a1456fc257d8.tar.gz accel-ppp-8ab2f623fa1d11a2aaec35226cb7a1456fc257d8.zip |
radius: add support for route priority (metric) in Framed-Route
Let an optional route priority (aka metric) be defined in RADIUS
Framed-Route attributes.
The priority is an integer placed at the end of the route string. This
is backward compatible with the previous format and also conforms with
the recommended format defined by RFC 2865 (although we don't allow
multiple metrics).
Framed-Route format is:
<network> [<gateway> [<priority>]]
For example, 'Framed-Route = "192.0.2.0/24 203.0.113.1 8"' will let
the following route be installed (assuming 203.0.113.1 is routed
through eth0):
$ ip route show
[...]
192.0.2.0/24 via 203.0.113.1 dev eth0 metric 8
It's possible to use the unspecified gateway (0.0.0.0) if one wants to
set a priority without specifying a gateway address.
Finally, route deletion now also takes the priority into account, in
order to avoid removing a different route accidentally.
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
-rw-r--r-- | accel-pppd/ctrl/ipoe/ipoe.c | 10 | ||||
-rw-r--r-- | accel-pppd/libnetlink/iputils.c | 8 | ||||
-rw-r--r-- | accel-pppd/libnetlink/iputils.h | 4 | ||||
-rw-r--r-- | accel-pppd/radius/radius.c | 16 | ||||
-rw-r--r-- | accel-pppd/radius/radius_p.h | 1 |
5 files changed, 27 insertions, 12 deletions
diff --git a/accel-pppd/ctrl/ipoe/ipoe.c b/accel-pppd/ctrl/ipoe/ipoe.c index 35f97d8..5fd64e2 100644 --- a/accel-pppd/ctrl/ipoe/ipoe.c +++ b/accel-pppd/ctrl/ipoe/ipoe.c @@ -977,9 +977,9 @@ static void __ipoe_session_activate(struct ipoe_session *ses) if (ses->ifindex == -1) { if (!conf_ip_unnumbered) - iproute_add(serv->ifindex, ses->router, ses->yiaddr, 0, conf_proto, ses->mask); + iproute_add(serv->ifindex, ses->router, ses->yiaddr, 0, conf_proto, ses->mask, 0); else if (!serv->opt_ifcfg) - iproute_add(serv->ifindex, serv->opt_src ?: ses->router, ses->yiaddr, 0, conf_proto, 32); + iproute_add(serv->ifindex, serv->opt_src ?: ses->router, ses->yiaddr, 0, conf_proto, 32, 0); } if (ses->l4_redirect) @@ -1078,7 +1078,7 @@ static void ipoe_session_started(struct ap_session *s) if (ses->ses.ipv4->peer_addr != ses->yiaddr) //ipaddr_add_peer(ses->ses.ifindex, ses->router, ses->yiaddr); // breaks quagga - iproute_add(ses->ses.ifindex, ses->router, ses->yiaddr, 0, conf_proto, 32); + iproute_add(ses->ses.ifindex, ses->router, ses->yiaddr, 0, conf_proto, 32, 0); if (ses->ifindex != -1 && ses->xid) { ses->dhcpv4 = dhcpv4_create(ses->ctrl.ctx, ses->ses.ifname, ""); @@ -1163,9 +1163,9 @@ static void ipoe_session_finished(struct ap_session *s) if (serv->opt_ifcfg) ipaddr_del(serv->ifindex, ses->router, conf_ip_unnumbered ? 32 : ses->mask); else if (conf_ip_unnumbered) - iproute_del(serv->ifindex, ses->yiaddr, conf_proto, 32); + iproute_del(serv->ifindex, ses->yiaddr, conf_proto, 32, 0); else - iproute_del(serv->ifindex, ses->yiaddr, conf_proto, ses->mask); + iproute_del(serv->ifindex, ses->yiaddr, conf_proto, ses->mask, 0); } if (ses->dhcp_addr) diff --git a/accel-pppd/libnetlink/iputils.c b/accel-pppd/libnetlink/iputils.c index 7d20f67..ad6005f 100644 --- a/accel-pppd/libnetlink/iputils.c +++ b/accel-pppd/libnetlink/iputils.c @@ -457,7 +457,7 @@ int __export ipaddr_del_peer(int ifindex, in_addr_t addr, in_addr_t peer) return r; } -int __export iproute_add(int ifindex, in_addr_t src, in_addr_t dst, in_addr_t gw, int proto, int mask) +int __export iproute_add(int ifindex, in_addr_t src, in_addr_t dst, in_addr_t gw, int proto, int mask, uint32_t prio) { struct ipaddr_req { struct nlmsghdr n; @@ -488,6 +488,8 @@ int __export iproute_add(int ifindex, in_addr_t src, in_addr_t dst, in_addr_t gw addattr32(&req.n, sizeof(req), RTA_PREFSRC, src); if (gw) addattr32(&req.n, sizeof(req), RTA_GATEWAY, gw); + if (prio) + addattr32(&req.n, sizeof(req), RTA_PRIORITY, prio); addattr32(&req.n, sizeof(req), RTA_DST, dst); if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) @@ -498,7 +500,7 @@ int __export iproute_add(int ifindex, in_addr_t src, in_addr_t dst, in_addr_t gw return r; } -int __export iproute_del(int ifindex, in_addr_t dst, int proto, int mask) +int __export iproute_del(int ifindex, in_addr_t dst, int proto, int mask, uint32_t prio) { struct ipaddr_req { struct nlmsghdr n; @@ -527,6 +529,8 @@ int __export iproute_del(int ifindex, in_addr_t dst, int proto, int mask) if (ifindex) addattr32(&req.n, sizeof(req), RTA_OIF, ifindex); + if (prio) + addattr32(&req.n, sizeof(req), RTA_PRIORITY, prio); if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0) r = -1; diff --git a/accel-pppd/libnetlink/iputils.h b/accel-pppd/libnetlink/iputils.h index 3211cfb..66aa974 100644 --- a/accel-pppd/libnetlink/iputils.h +++ b/accel-pppd/libnetlink/iputils.h @@ -18,8 +18,8 @@ int ipaddr_add_peer(int ifindex, in_addr_t addr, in_addr_t peer_addr); int ipaddr_del(int ifindex, in_addr_t addr, int mask); int ipaddr_del_peer(int ifindex, in_addr_t addr, in_addr_t peer); -int iproute_add(int ifindex, in_addr_t src, in_addr_t dst, in_addr_t gw, int proto, int mask); -int iproute_del(int ifindex, in_addr_t dst, int proto, int mask); +int iproute_add(int ifindex, in_addr_t src, in_addr_t dst, in_addr_t gw, int proto, int mask, uint32_t prio); +int iproute_del(int ifindex, in_addr_t dst, int proto, int mask, uint32_t prio); in_addr_t iproute_get(in_addr_t dst, in_addr_t *gw); int ip6route_add(int ifindex, struct in6_addr *dst, int prefix_len, int proto); diff --git a/accel-pppd/radius/radius.c b/accel-pppd/radius/radius.c index b870601..5c650b2 100644 --- a/accel-pppd/radius/radius.c +++ b/accel-pppd/radius/radius.c @@ -62,6 +62,7 @@ static void parse_framed_route(struct radius_pd_t *rpd, const char *attr) { char str[32]; char *ptr; + long int prio = 0; in_addr_t dst; in_addr_t gw; int mask; @@ -118,6 +119,14 @@ static void parse_framed_route(struct radius_pd_t *rpd, const char *attr) gw = 0; else goto out_err; + + /* Parse priority, if any */ + if (*ptr) { + for (++ptr; *ptr && *ptr != ' '; ptr++); + if (*ptr == ' ') + if (u_readlong(&prio, ptr + 1, 0, UINT32_MAX) < 0) + goto out_err; + } } else { mask = 32; gw = 0; @@ -127,6 +136,7 @@ static void parse_framed_route(struct radius_pd_t *rpd, const char *attr) fr->dst = dst; fr->mask = mask; fr->gw = gw; + fr->prio = prio; fr->next = rpd->fr; rpd->fr = fr; @@ -444,11 +454,11 @@ static void ses_started(struct ap_session *ses) } for (fr = rpd->fr; fr; fr = fr->next) { - if (iproute_add(fr->gw ? 0 : rpd->ses->ifindex, 0, fr->dst, fr->gw, 3, fr->mask)) { + if (iproute_add(fr->gw ? 0 : rpd->ses->ifindex, 0, fr->dst, fr->gw, 3, fr->mask, fr->prio)) { char dst[17], gw[17]; u_inet_ntoa(fr->dst, dst); u_inet_ntoa(fr->gw, gw); - log_ppp_warn("radius: failed to add route %s/%i%s\n", dst, fr->mask, gw); + log_ppp_warn("radius: failed to add route %s/%i %s %u\n", dst, fr->mask, gw, fr->prio); } } @@ -472,7 +482,7 @@ static void ses_finishing(struct ap_session *ses) for (fr = rpd->fr; fr; fr = fr->next) { if (fr->gw) - iproute_del(0, fr->dst, 3, fr->mask); + iproute_del(0, fr->dst, 3, fr->mask, fr->prio); } if (rpd->acct_started || rpd->acct_req) diff --git a/accel-pppd/radius/radius_p.h b/accel-pppd/radius/radius_p.h index cdbb57b..1ce31c0 100644 --- a/accel-pppd/radius/radius_p.h +++ b/accel-pppd/radius/radius_p.h @@ -29,6 +29,7 @@ struct framed_route { in_addr_t dst; int mask; in_addr_t gw; + uint32_t prio; struct framed_route *next; }; |