Consolidate adding/removing routes

into routesset and routes6set.
This commit is contained in:
Samuel Thibault 2023-04-23 18:47:44 +02:00
parent c7853de428
commit 8c04e26f3f
3 changed files with 79 additions and 121 deletions

186
l2tpns.c
View file

@ -263,6 +263,7 @@ static int netlink_handle_ack(struct nlmsghdr *nh, int gen, int min_initok_nlseq
static void rtnetlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen);
static void genetlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen);
static int genetlink_getattr(struct nlmsghdr *nh, int type, void *data, int alen);
static void routesset(sessionidt s, sessiont *sp, int add);
static void cache_ipmap(in_addr_t ip, sessionidt s);
static void uncache_ipmap(in_addr_t ip);
static void cache_ipv6map(struct in6_addr ip, int prefixlen, sessionidt s);
@ -1115,6 +1116,51 @@ static void routeset(sessionidt s, in_addr_t ip, int prefixlen, in_addr_t gw, in
}
}
//
// Add or remove the routes for a session
static void routesset(sessionidt s, sessiont *sp, int add)
{
int r;
int routed = 0;
// add/remove routes...
for (r = 0; r < MAXROUTE && sp->route[r].ip; r++)
{
if ((sp->ip >> (32-sp->route[r].prefixlen)) ==
(sp->route[r].ip >> (32-sp->route[r].prefixlen)))
routed++;
routeset(s, sp->route[r].ip, sp->route[r].prefixlen, 0, add);
}
// ...ip
if (sp->ip)
{
// Static IPs need to be routed if not already
// convered by a Framed-Route. Anything else is part
// of the IP address pool and is already routed, it
// just needs to be added to the IP cache.
// IPv6 route setup is done in ppp.c, when IPV6CP is acked.
if (sp->ip_pool_index == -1) // static ip
{
if (!routed) routeset(s, sp->ip, 0, 0, add);
}
else // It's part of the IP pool, add/remove it manually.
{
if (add)
cache_ipmap(sp->ip, s);
else
uncache_ipmap(sp->ip);
}
}
}
// Add an IPv6 route
//
// This adds it to the routing table, advertises it
// via BGP if enabled, and stuffs it into the
// 'sessionbyip' cache.
//
void route6set(sessionidt s, struct in6_addr ip, int prefixlen, int add)
{
struct {
@ -1184,6 +1230,25 @@ void route6set(sessionidt s, struct in6_addr ip, int prefixlen, int add)
return;
}
//
// Add or remove the IPv6 routes for a session
void routes6set(sessionidt s, sessiont *sp, int add)
{
int r;
for (r = 0; r < MAXROUTE6 && sp->route6[r].ipv6prefixlen; r++)
{
route6set(s, sp->route6[r].ipv6route, sp->route6[r].ipv6prefixlen, add);
}
if (sp->ipv6address.s6_addr[0])
{
// Check if included in prefix
if (!add || sessionbyipv6(sp->ipv6address) != s)
route6set(s, sp->ipv6address, 128, add);
}
}
//
// Get L2TP netlink id
static int16_t netlink_get_l2tp_id(void)
@ -3001,38 +3066,27 @@ void sessionshutdown(sessionidt s, char const *reason, int cdn_result, int cdn_e
if (session[s].ip)
{ // IP allocated, clear and unroute
int r;
int routed = 0;
for (r = 0; r < MAXROUTE && session[s].route[r].ip; r++)
{
if ((session[s].ip >> (32-session[s].route[r].prefixlen)) ==
(session[s].route[r].ip >> (32-session[s].route[r].prefixlen)))
routed++;
if (del_routes)
routesset(s, &session[s], 0);
if (del_routes) routeset(s, session[s].route[r].ip, session[s].route[r].prefixlen, 0, 0);
int r;
for (r = 0; r < MAXROUTE && session[s].route[r].ip; r++)
session[s].route[r].ip = 0;
}
if (session[s].ip_pool_index == -1) // static ip
{
if (!routed && del_routes) routeset(s, session[s].ip, 0, 0, 0);
session[s].ip = 0;
}
else
free_ip_address(s);
if (del_routes)
routes6set(s, &session[s], 0);
// unroute IPv6, if setup
for (r = 0; r < MAXROUTE6 && session[s].route6[r].ipv6route.s6_addr[0] && session[s].route6[r].ipv6prefixlen; r++)
{
if (del_routes) route6set(s, session[s].route6[r].ipv6route, session[s].route6[r].ipv6prefixlen, 0);
memset(&session[s].route6[r], 0, sizeof(session[s].route6[r]));
}
if (session[s].ipv6address.s6_addr[0] && del_routes)
{
route6set(s, session[s].ipv6address, 128, 0);
}
if (b)
{
// This session was part of a bundle
@ -3067,7 +3121,6 @@ void sessionshutdown(sessionidt s, char const *reason, int cdn_result, int cdn_e
{
sessionidt new_s = bundle[b].members[0];
routed = 0;
// Add the route for this session.
for (r = 0; r < MAXROUTE && session[new_s].route[r].ip; r++)
{
@ -6602,7 +6655,6 @@ int sessionsetup(sessionidt s, tunnelidt t)
in_addr_t ip;
char *user;
sessionidt i;
int r;
CSTAT(sessionsetup);
@ -6680,31 +6732,8 @@ int sessionsetup(sessionidt s, tunnelidt t)
// no need to set a route for the same IP address of the bundle
if (!session[s].bundle || (bundle[session[s].bundle].num_of_links == 1))
{
int routed = 0;
// Add the route for this session.
for (r = 0; r < MAXROUTE && session[s].route[r].ip; r++)
{
if ((session[s].ip >> (32-session[s].route[r].prefixlen)) ==
(session[s].route[r].ip >> (32-session[s].route[r].prefixlen)))
routed++;
routeset(s, session[s].route[r].ip, session[s].route[r].prefixlen, 0, 1);
}
// Static IPs need to be routed if not already
// convered by a Framed-Route. Anything else is part
// of the IP address pool and is already routed, it
// just needs to be added to the IP cache.
// IPv6 route setup is done in ppp.c, when IPV6CP is acked.
if (session[s].ip_pool_index == -1) // static ip
{
if (!routed) routeset(s, session[s].ip, 0, 0, 1);
}
else
cache_ipmap(session[s].ip, s);
}
routesset(s, &session[s], 1);
sess_local[s].lcp_authtype = 0; // RADIUS authentication complete
lcp_open(s, t); // transition to Network phase and send initial IPCP
@ -6767,80 +6796,19 @@ int load_session(sessionidt s, sessiont *new)
// needs update
if (newip)
{
int routed = 0;
// remove old routes...
for (i = 0; i < MAXROUTE && session[s].route[i].ip; i++)
{
if ((session[s].ip >> (32-session[s].route[i].prefixlen)) ==
(session[s].route[i].ip >> (32-session[s].route[i].prefixlen)))
routed++;
routeset(s, session[s].route[i].ip, session[s].route[i].prefixlen, 0, 0);
}
// ...ip
if (session[s].ip)
{
if (session[s].ip_pool_index == -1) // static IP
{
if (!routed) routeset(s, session[s].ip, 0, 0, 0);
}
else // It's part of the IP pool, remove it manually.
uncache_ipmap(session[s].ip);
}
routesset(s, &session[s], 0);
// remove old IPV6 routes...
for (i = 0; i < MAXROUTE6 && session[s].route6[i].ipv6route.s6_addr[0] && session[s].route6[i].ipv6prefixlen; i++)
{
route6set(s, session[s].route6[i].ipv6route, session[s].route6[i].ipv6prefixlen, 0);
}
if (session[s].ipv6address.s6_addr[0])
{
route6set(s, session[s].ipv6address, 128, 0);
}
routed = 0;
routes6set(s, &session[s], 0);
// add new routes...
for (i = 0; i < MAXROUTE && new->route[i].ip; i++)
{
if ((new->ip >> (32-new->route[i].prefixlen)) ==
(new->route[i].ip >> (32-new->route[i].prefixlen)))
routed++;
routeset(s, new->route[i].ip, new->route[i].prefixlen, 0, 1);
}
// ...ip
if (new->ip)
{
// If there's a new one, add it.
if (new->ip_pool_index == -1)
{
if (!routed) routeset(s, new->ip, 0, 0, 1);
}
else
cache_ipmap(new->ip, s);
}
routesset(s, new, 1);
}
// check v6 routing
if (new->ppp.ipv6cp == Opened && session[s].ppp.ipv6cp != Opened)
{
for (i = 0; i < MAXROUTE6 && new->route6[i].ipv6prefixlen; i++)
{
route6set(s, new->route6[i].ipv6route, new->route6[i].ipv6prefixlen, 1);
}
}
if (new->ipv6address.s6_addr[0] && new->ppp.ipv6cp == Opened && session[s].ppp.ipv6cp != Opened)
{
// Check if included in prefix
if (sessionbyipv6(new->ipv6address) != s)
route6set(s, new->ipv6address, 128, 1);
}
routes6set(s, new, 1);
// check filters
if (new->filter_in && (new->filter_in > MAXFILTER || !ip_filters[new->filter_in - 1].name[0]))

View file

@ -962,6 +962,7 @@ int rad_tunnel_pwdecode(uint8_t *pl2tpsecret, size_t *pl2tpsecretlen, const char
clockt backoff(uint8_t try);
void send_ipv6_ra(sessionidt s, tunnelidt t, struct in6_addr *ip);
void route6set(sessionidt s, struct in6_addr ip, int prefixlen, int add);
void routes6set(sessionidt s, sessiont *sp, int add);
sessionidt sessionbyip(in_addr_t ip);
sessionidt sessionbyipv6(struct in6_addr ip);
sessionidt sessionbyipv6new(struct in6_addr ip);

13
ppp.c
View file

@ -1479,21 +1479,10 @@ void processipcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
static void ipv6cp_open(sessionidt s, tunnelidt t)
{
int i;
LOG(3, s, t, "IPV6CP: Opened\n");
change_state(s, ipv6cp, Opened);
for (i = 0; i < MAXROUTE6 && session[s].route6[i].ipv6prefixlen; i++)
{
route6set(s, session[s].route6[i].ipv6route, session[s].route6[i].ipv6prefixlen, 1);
}
if (session[s].ipv6address.s6_addr[0])
{
// Check if included in prefix
if (sessionbyipv6(session[s].ipv6address) != s)
route6set(s, session[s].ipv6address, 128, 1);
}
routes6set(s, &session[s], 1);
// Send an initial RA
send_ipv6_ra(s, t, NULL);