-/* $OpenBSD: config.c,v 1.78 2021/02/22 21:58:12 tobhe Exp $ */
+/* $OpenBSD: config.c,v 1.79 2021/05/13 15:20:48 tobhe Exp $ */
/*
* Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de>
int
config_getreset(struct iked *env, struct imsg *imsg)
{
- struct iked_policy *pol, *poltmp;
- struct iked_sa *sa;
- struct iked_user *usr;
unsigned int mode;
IMSG_SIZE_CHECK(imsg, &mode);
memcpy(&mode, imsg->data, sizeof(mode));
- if (mode == RESET_EXIT || mode == RESET_ALL || mode == RESET_POLICY) {
+ return (config_doreset(env, mode));
+}
+
+int
+config_doreset(struct iked *env, unsigned int mode)
+{
+ struct iked_policy *pol, *poltmp;
+ struct iked_sa *sa;
+ struct iked_user *usr;
+
+ if (mode == RESET_ALL || mode == RESET_POLICY) {
log_debug("%s: flushing policies", __func__);
TAILQ_FOREACH_SAFE(pol, &env->sc_policies, pol_entry, poltmp) {
config_free_policy(env, pol);
}
}
- if (mode == RESET_EXIT || mode == RESET_ALL || mode == RESET_SA) {
+ if (mode == RESET_ALL || mode == RESET_SA) {
log_debug("%s: flushing SAs", __func__);
while ((sa = RB_MIN(iked_sas, &env->sc_sas))) {
/* for RESET_SA we try send a DELETE */
}
}
- if (mode == RESET_EXIT || mode == RESET_ALL || mode == RESET_USER) {
+ if (mode == RESET_ALL || mode == RESET_USER) {
log_debug("%s: flushing users", __func__);
while ((usr = RB_MIN(iked_users, &env->sc_users))) {
RB_REMOVE(iked_users, &env->sc_users, usr);
}
}
- if (mode == RESET_EXIT)
- proc_compose(&env->sc_ps, PROC_PARENT, IMSG_CTL_EXIT, NULL, 0);
-
return (0);
}
-/* $OpenBSD: vroute.c,v 1.8 2021/04/03 21:29:14 tobhe Exp $ */
+/* $OpenBSD: vroute.c,v 1.9 2021/05/13 15:20:48 tobhe Exp $ */
/*
* Copyright (c) 2021 Tobias Heider <tobhe@openbsd.org>
int vroute_doroute(struct iked *, int, int, int, uint8_t, struct sockaddr *,
struct sockaddr *, struct sockaddr *, int *);
int vroute_doaddr(struct iked *, char *, struct sockaddr *, struct sockaddr *, int);
+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 *);
+
+struct vroute_addr {
+ int va_ifidx;
+ struct sockaddr_storage va_addr;
+ struct sockaddr_storage va_mask;
+ TAILQ_ENTRY(vroute_addr) va_entry;
+};
+TAILQ_HEAD(vroute_addrs, vroute_addr);
+
+struct vroute_route {
+ int vr_rdomain;
+ struct sockaddr_storage vr_dest;
+ TAILQ_ENTRY(vroute_route) vr_entry;
+};
+TAILQ_HEAD(vroute_routes, vroute_route);
struct iked_vroute_sc {
- int ivr_iosock;
- int ivr_iosock6;
- int ivr_rtsock;
- int ivr_rtseq;
- pid_t ivr_pid;
+ struct vroute_addrs ivr_addrs;
+ struct vroute_routes ivr_routes;
+ int ivr_iosock;
+ int ivr_iosock6;
+ int ivr_rtsock;
+ int ivr_rtseq;
+ pid_t ivr_pid;
};
struct vroute_msg {
if ((ivr->ivr_rtsock = socket(AF_ROUTE, SOCK_RAW, AF_UNSPEC)) == -1)
fatal("%s: failed to create routing socket", __func__);
+ TAILQ_INIT(&ivr->ivr_addrs);
+ TAILQ_INIT(&ivr->ivr_routes);
+
ivr->ivr_pid = getpid();
env->sc_vroute = ivr;
}
+void
+vroute_cleanup(struct iked *env)
+{
+ char ifname[IF_NAMESIZE];
+ struct iked_vroute_sc *ivr = env->sc_vroute;
+ struct vroute_addr *addr;
+ struct vroute_route *route;
+
+ while ((addr = TAILQ_FIRST(&ivr->ivr_addrs))) {
+ if_indextoname(addr->va_ifidx, ifname);
+ vroute_doaddr(env, ifname,
+ (struct sockaddr *)&addr->va_addr,
+ (struct sockaddr *)&addr->va_mask, 0);
+ TAILQ_REMOVE(&ivr->ivr_addrs, addr, va_entry);
+ free(addr);
+ }
+
+ 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);
+ TAILQ_REMOVE(&ivr->ivr_routes, route, vr_entry);
+ free(route);
+ }
+}
+
int
vroute_getaddr(struct iked *env, struct imsg *imsg)
{
struct sockaddr *addr, *mask;
uint8_t *ptr;
size_t left;
- int af;
+ int af, add;
unsigned int ifidx;
ptr = imsg->data;
ptr += sizeof(ifidx);
left -= sizeof(ifidx);
+ add = (imsg->hdr.type == IMSG_IF_ADDADDR);
+ /* Store address for cleanup */
+ if (add)
+ vroute_insertaddr(env, ifidx, addr, mask);
+ else
+ vroute_removeaddr(env, ifidx, addr, mask);
+
if_indextoname(ifidx, ifname);
+ return (vroute_doaddr(env, ifname, addr, mask, add));
+}
+
+void
+vroute_insertroute(struct iked *env, int rdomain, struct sockaddr *dest)
+{
+ struct iked_vroute_sc *ivr = env->sc_vroute;
+ struct vroute_route *route;
+
+ route = calloc(1, sizeof(*route));
+ if (route == NULL)
+ fatalx("%s: calloc.", __func__);
+
+ memcpy(&route->vr_dest, dest, dest->sa_len);
+ route->vr_rdomain = rdomain;
- return (vroute_doaddr(env, ifname, addr, mask,
- imsg->hdr.type == IMSG_IF_ADDADDR));
+ TAILQ_INSERT_TAIL(&ivr->ivr_routes, route, vr_entry);
+}
+
+void
+vroute_removeroute(struct iked *env, int rdomain, struct sockaddr *dest)
+{
+ struct iked_vroute_sc *ivr = env->sc_vroute;
+ struct vroute_route *route;
+
+ TAILQ_FOREACH(route, &ivr->ivr_routes, vr_entry) {
+ if (sockaddr_cmp(dest, (struct sockaddr *)&route->vr_dest, -1))
+ continue;
+ if (rdomain != route->vr_rdomain)
+ continue;
+ TAILQ_REMOVE(&ivr->ivr_routes, route, vr_entry);
+ }
+}
+
+void
+vroute_insertaddr(struct iked *env, int ifidx, struct sockaddr *addr,
+ struct sockaddr *mask)
+{
+ struct iked_vroute_sc *ivr = env->sc_vroute;
+ struct vroute_addr *vaddr;
+
+ vaddr = calloc(1, sizeof(*vaddr));
+ if (vaddr == NULL)
+ fatalx("%s: calloc.", __func__);
+
+ memcpy(&vaddr->va_addr, addr, addr->sa_len);
+ memcpy(&vaddr->va_mask, mask, mask->sa_len);
+ vaddr->va_ifidx = ifidx;
+
+ TAILQ_INSERT_TAIL(&ivr->ivr_addrs, vaddr, va_entry);
+}
+
+void
+vroute_removeaddr(struct iked *env, int ifidx, struct sockaddr *addr,
+ struct sockaddr *mask)
+{
+ struct iked_vroute_sc *ivr = env->sc_vroute;
+ struct vroute_addr *vaddr;
+
+ TAILQ_FOREACH(vaddr, &ivr->ivr_addrs, va_entry) {
+ if (sockaddr_cmp(addr, (struct sockaddr *)&vaddr->va_addr, -1))
+ continue;
+ if (sockaddr_cmp(mask, (struct sockaddr *)&vaddr->va_mask, -1))
+ continue;
+ if (ifidx != vaddr->va_ifidx)
+ continue;
+ TAILQ_REMOVE(&ivr->ivr_addrs, vaddr, va_entry);
+ }
}
int
type = RTM_ADD;
break;
case IMSG_VROUTE_DEL:
+ vroute_removeroute(env, rdomain, dest);
type = RTM_DELETE;
break;
}
if (need_gw)
flags |= RTF_GATEWAY;
+ vroute_insertroute(env, rdomain, (struct sockaddr *)&dest);
+
/* Set explicit route to peer with gateway addr*/
addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
return (vroute_doroute(env, flags, addrs, rdomain, RTM_ADD,