summaryrefslogtreecommitdiff
path: root/sbin/iked/vroute.c
diff options
context:
space:
mode:
authortobhe <tobhe@cvs.openbsd.org>2021-06-01 20:57:13 +0000
committertobhe <tobhe@cvs.openbsd.org>2021-06-01 20:57:13 +0000
commitf18ed4d0bf28964d6248f7bb5545ff2a1a5a8be4 (patch)
tree3972877e8e47dc93d69831e04c41bef4ac1961cc /sbin/iked/vroute.c
parent74b95618c7d4bde1dd05452b9fec1352db9b5345 (diff)
Remember flow routes in addition to host routes and delete
them explicitly on shutdown. Store netmask in route queue to fix cleanup of 0/1 routes. Sending delete messages without mask doesn't work reliably. ok patrick@
Diffstat (limited to 'sbin/iked/vroute.c')
-rw-r--r--sbin/iked/vroute.c48
1 files changed, 36 insertions, 12 deletions
diff --git a/sbin/iked/vroute.c b/sbin/iked/vroute.c
index 650f6e111e0..cd2e3990190 100644
--- a/sbin/iked/vroute.c
+++ b/sbin/iked/vroute.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vroute.c,v 1.9 2021/05/13 15:20:48 tobhe Exp $ */
+/* $OpenBSD: vroute.c,v 1.10 2021/06/01 20:57:12 tobhe Exp $ */
/*
* Copyright (c) 2021 Tobias Heider <tobhe@openbsd.org>
@@ -48,8 +48,8 @@ void vroute_cleanup(struct iked *);
void vroute_insertaddr(struct iked *, int, struct sockaddr *, struct sockaddr *);
void vroute_removeaddr(struct iked *, int, struct sockaddr *, struct sockaddr *);
-void vroute_insertroute(struct iked *, int, struct sockaddr *);
-void vroute_removeroute(struct iked *, int, struct sockaddr *);
+void vroute_insertroute(struct iked *, int, struct sockaddr *, struct sockaddr *);
+void vroute_removeroute(struct iked *, int, struct sockaddr *, struct sockaddr *);
struct vroute_addr {
int va_ifidx;
@@ -61,7 +61,9 @@ TAILQ_HEAD(vroute_addrs, vroute_addr);
struct vroute_route {
int vr_rdomain;
+ int vr_flags;
struct sockaddr_storage vr_dest;
+ struct sockaddr_storage vr_mask;
TAILQ_ENTRY(vroute_route) vr_entry;
};
TAILQ_HEAD(vroute_routes, vroute_route);
@@ -129,8 +131,10 @@ vroute_cleanup(struct iked *env)
while ((route = TAILQ_FIRST(&ivr->ivr_routes))) {
vroute_doroute(env, RTF_UP | RTF_GATEWAY | RTF_STATIC,
- RTA_DST, route->vr_rdomain, RTM_DELETE,
- (struct sockaddr *)&route->vr_dest, NULL, NULL, NULL);
+ route->vr_flags, route->vr_rdomain, RTM_DELETE,
+ (struct sockaddr *)&route->vr_dest,
+ (struct sockaddr *)&route->vr_mask,
+ NULL, NULL);
TAILQ_REMOVE(&ivr->ivr_routes, route, vr_entry);
free(route);
}
@@ -189,7 +193,8 @@ vroute_getaddr(struct iked *env, struct imsg *imsg)
}
void
-vroute_insertroute(struct iked *env, int rdomain, struct sockaddr *dest)
+vroute_insertroute(struct iked *env, int rdomain, struct sockaddr *dest,
+ struct sockaddr *mask)
{
struct iked_vroute_sc *ivr = env->sc_vroute;
struct vroute_route *route;
@@ -198,14 +203,22 @@ vroute_insertroute(struct iked *env, int rdomain, struct sockaddr *dest)
if (route == NULL)
fatalx("%s: calloc.", __func__);
- memcpy(&route->vr_dest, dest, dest->sa_len);
+ if (dest != NULL) {
+ route->vr_flags |= RTA_DST;
+ memcpy(&route->vr_dest, dest, dest->sa_len);
+ }
+ if (mask != NULL) {
+ route->vr_flags |= RTA_NETMASK;
+ memcpy(&route->vr_mask, mask, mask->sa_len);
+ }
route->vr_rdomain = rdomain;
TAILQ_INSERT_TAIL(&ivr->ivr_routes, route, vr_entry);
}
void
-vroute_removeroute(struct iked *env, int rdomain, struct sockaddr *dest)
+vroute_removeroute(struct iked *env, int rdomain, struct sockaddr *dest,
+ struct sockaddr *mask)
{
struct iked_vroute_sc *ivr = env->sc_vroute;
struct vroute_route *route;
@@ -213,6 +226,11 @@ vroute_removeroute(struct iked *env, int rdomain, struct sockaddr *dest)
TAILQ_FOREACH(route, &ivr->ivr_routes, vr_entry) {
if (sockaddr_cmp(dest, (struct sockaddr *)&route->vr_dest, -1))
continue;
+ if (mask && !(route->vr_flags & RTA_NETMASK))
+ continue;
+ if (mask &&
+ sockaddr_cmp(mask, (struct sockaddr *)&route->vr_mask, -1))
+ continue;
if (rdomain != route->vr_rdomain)
continue;
TAILQ_REMOVE(&ivr->ivr_routes, route, vr_entry);
@@ -393,11 +411,14 @@ vroute_getroute(struct iked *env, struct imsg *imsg)
type = RTM_ADD;
break;
case IMSG_VROUTE_DEL:
- vroute_removeroute(env, rdomain, dest);
type = RTM_DELETE;
break;
}
+ if (type == RTM_ADD)
+ vroute_insertroute(env, rdomain, dest, mask);
+ else
+ vroute_removeroute(env, rdomain, dest, mask);
return (vroute_doroute(env, flags, addrs, rdomain, type,
dest, mask, gateway, NULL));
}
@@ -434,7 +455,7 @@ vroute_getcloneroute(struct iked *env, struct imsg *imsg)
dst = (struct sockaddr *)ptr;
if (left < dst->sa_len)
return (-1);
- memcpy(&dest, ptr, dst->sa_len);
+ memcpy(&dest, dst, dst->sa_len);
ptr += dst->sa_len;
left -= dst->sa_len;
@@ -448,12 +469,15 @@ vroute_getcloneroute(struct iked *env, struct imsg *imsg)
if (need_gw)
flags |= RTF_GATEWAY;
- vroute_insertroute(env, rdomain, (struct sockaddr *)&dest);
+ memcpy(&dest, dst, dst->sa_len);
+ socket_setport((struct sockaddr *)&dest, 0);
+ vroute_insertroute(env, rdomain, (struct sockaddr *)&dest, NULL);
/* Set explicit route to peer with gateway addr*/
addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
return (vroute_doroute(env, flags, addrs, rdomain, RTM_ADD,
- dst, (struct sockaddr *)&mask, (struct sockaddr *)&addr, NULL));
+ (struct sockaddr *)&dest, (struct sockaddr *)&mask,
+ (struct sockaddr *)&addr, NULL));
}
int