diff options
-rw-r--r-- | src/tools/ipc.c | 246 |
1 files changed, 120 insertions, 126 deletions
diff --git a/src/tools/ipc.c b/src/tools/ipc.c index e499eb3..811350c 100644 --- a/src/tools/ipc.c +++ b/src/tools/ipc.c @@ -957,7 +957,6 @@ static int openbsd_get_wireguard_interfaces(struct inflatable_buffer *buffer) if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) return errno; - len = ifgr.ifgr_len / sizeof(ifgr.ifgr_groups) - 1; if ((ifgr.ifgr_groups = calloc(sizeof(ifgr.ifgr_groups), len)) == NULL) return (-1); @@ -981,130 +980,120 @@ out: static int openbsd_get_device(struct wgdevice **device, const char *interface) { - size_t num; - struct wg_serv_get wgs; - struct wg_peer_get wgp; - struct ifreq ifr; - - strlcpy(wgs.gs_name, interface, sizeof(wgs.gs_name)); - strlcpy(wgp.gp_name, interface, sizeof(wgp.gp_name)); - strlcpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name)); + size_t num_peers = 0, num_cidrs = 0; + struct wg_device_io bdev; + struct wg_peer_io *bpeer; + struct wg_cidr_io *bcidr; + struct wgdevice *dev; + struct wgpeer *peer; + struct wgallowedip *aip; getsock(); - /* Load peers and interface stuff */ - wgs.gs_peers = NULL; - wgs.gs_num_peers = 8; - do { - num = wgs.gs_num_peers; - /* wgs.gs_num_peers will be updated in the ioctl */ - wgs.gs_peers = reallocarray(wgs.gs_peers, wgs.gs_num_peers, - sizeof(*wgs.gs_peers)); - if (ioctl(s, SIOCGWGSERV, (caddr_t)&wgs) == -1) - return -1; - } while (wgs.gs_num_peers > num); - - struct wgdevice *dev = calloc(1, sizeof(*dev)); + bzero(&bdev, sizeof(bdev)); + strlcpy(bdev.d_name, interface, sizeof(bdev.d_name)); + + if (ioctl(s, SIOCGWG, (caddr_t)&bdev) == -1 && errno == ENOTTY) + return -1; + + while (num_peers < bdev.d_num_peers || num_cidrs < bdev.d_num_cidrs) { + bdev.d_peers = recallocarray(bdev.d_peers, num_peers, + bdev.d_num_peers, sizeof(struct wg_peer_io)); + bdev.d_cidrs = recallocarray(bdev.d_cidrs, num_cidrs, + bdev.d_num_cidrs, sizeof(struct wg_cidr_io)); + num_peers = bdev.d_num_peers; + num_cidrs = bdev.d_num_cidrs; + if (ioctl(s, SIOCGWG, (caddr_t)&bdev) == -1) + printf("TODO SIOCGWG\n"); + //TODO errx(1, "SIOCGWG"); + } + + dev = calloc(1, sizeof(*dev)); strlcpy(dev->name, interface, sizeof(dev->name)); - if (ioctl(s, SIOCGIFRDOMAIN, (caddr_t)&ifr) != -1) { - dev->fwmark = ifr.ifr_rdomainid; + if (bdev.d_flags & WG_DEVICE_HAS_RDOMAIN) { + dev->fwmark = bdev.d_rdomain; dev->flags |= WGDEVICE_HAS_FWMARK; } - if (wgs.gs_port != 0) { - dev->listen_port = wgs.gs_port; + if (bdev.d_flags & WG_DEVICE_HAS_PORT) { + dev->listen_port = bdev.d_port; dev->flags |= WGDEVICE_HAS_LISTEN_PORT; } - if (!IS_NULL_KEY(wgs.gs_keypair.pub.k)) { - if (IS_MASKED_KEY(wgs.gs_keypair.pub.k)) - bzero(dev->public_key, WG_KEY_SIZE); - else - memcpy(dev->public_key, wgs.gs_keypair.pub.k, - WG_KEY_SIZE); + if (bdev.d_flags & WG_DEVICE_HAS_PUBKEY) { + memcpy(dev->public_key, bdev.d_pubkey, WG_KEY_SIZE); dev->flags |= WGDEVICE_HAS_PUBLIC_KEY; } - if (!IS_NULL_KEY(wgs.gs_keypair.priv.k)) { - if (IS_MASKED_KEY(wgs.gs_keypair.priv.k)) - bzero(dev->private_key, WG_KEY_SIZE); - else - memcpy(dev->private_key, wgs.gs_keypair.priv.k, - WG_KEY_SIZE); + if (bdev.d_flags & WG_DEVICE_HAS_PRIVKEY) { + memcpy(dev->private_key, bdev.d_privkey, WG_KEY_SIZE); + dev->flags |= WGDEVICE_HAS_PRIVATE_KEY; + } + + if (bdev.d_flags & WG_DEVICE_HAS_MASKED_PRIVKEY) { + bzero(dev->private_key, WG_KEY_SIZE); dev->flags |= WGDEVICE_HAS_PRIVATE_KEY; } dev->first_peer = dev->last_peer = NULL; - for (size_t i = 0; i < wgs.gs_num_peers; i++) { - memcpy(wgp.gp_pubkey.k, wgs.gs_peers[i].k, WG_KEY_SIZE); - wgp.gp_routes = NULL; - wgp.gp_num_routes = 16; - do { - num = wgp.gp_num_routes; - wgp.gp_routes = reallocarray(wgp.gp_routes, - wgp.gp_num_routes, sizeof(*wgp.gp_routes)); - if (ioctl(s, SIOCGWGPEER, (caddr_t)&wgp) == -1) - return -1; - } while (wgp.gp_num_routes > num); + WG_PEERS_FOREACH(bpeer, &bdev) { + peer = calloc(1, sizeof(*peer)); - struct wgpeer *peer = calloc(1, sizeof(*peer)); if (dev->first_peer == NULL) dev->first_peer = peer; else dev->last_peer->next_peer = peer; dev->last_peer = peer; - if (!IS_NULL_KEY(wgp.gp_pubkey.k)) { - memcpy(peer->public_key, wgp.gp_pubkey.k, WG_KEY_SIZE); + if (bpeer->p_flags & WG_PEER_HAS_PUBKEY) { + memcpy(peer->public_key, bpeer->p_pubkey, WG_KEY_SIZE); peer->flags |= WGPEER_HAS_PUBLIC_KEY; } - if (!IS_NULL_KEY(wgp.gp_shared.k)) { - if (IS_MASKED_KEY(wgp.gp_shared.k)) - bzero(peer->preshared_key, WG_KEY_SIZE); - else - memcpy(peer->preshared_key, wgp.gp_shared.k, - WG_KEY_SIZE); + if (bpeer->p_flags & WG_PEER_HAS_SHAREDKEY) { + memcpy(peer->preshared_key, bpeer->p_sharedkey, WG_KEY_SIZE); + peer->flags |= WGPEER_HAS_PRESHARED_KEY; + } + + if (bpeer->p_flags & WG_PEER_HAS_MASKED_SHAREDKEY) { + bzero(peer->preshared_key, WG_KEY_SIZE); peer->flags |= WGPEER_HAS_PRESHARED_KEY; } - if (wgp.gp_pka != 0) { - peer->persistent_keepalive_interval = wgp.gp_pka; + if (bpeer->p_flags & WG_PEER_HAS_PERSISTENTKEEPALIVE) { + peer->persistent_keepalive_interval = + bpeer->p_persistentkeepalive; peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL; } - if (wgp.gp_ip.sa.sa_family != AF_UNSPEC) - memcpy(&peer->endpoint.addr, &wgp.gp_ip.sa, - wgp.gp_ip.sa.sa_len); + if (bpeer->p_flags & WG_PEER_HAS_ENDPOINT) + memcpy(&peer->endpoint.addr, &bpeer->p_sa, bpeer->p_sa.sa_len); - peer->last_handshake_time.tv_sec = - wgp.gp_last_handshake.tv_sec; - peer->last_handshake_time.tv_nsec = - wgp.gp_last_handshake.tv_nsec; + peer->last_handshake_time.tv_sec = bpeer->p_last_handshake.tv_sec; + peer->last_handshake_time.tv_nsec = bpeer->p_last_handshake.tv_nsec; - peer->rx_bytes = wgp.gp_rx_bytes; - peer->tx_bytes = wgp.gp_tx_bytes; + peer->rx_bytes = bpeer->p_rx_bytes; + peer->tx_bytes = bpeer->p_tx_bytes; - struct wg_cidr *ip = wgp.gp_routes; - for (size_t j = 0; j < wgp.gp_num_routes; j++) { - struct wgallowedip *aip = calloc(1, sizeof(*aip)); + WG_CIDRS_FOREACH(bcidr, bpeer) { + aip = calloc(1, sizeof(*aip)); if (peer->first_allowedip == NULL) peer->first_allowedip = aip; else peer->last_allowedip->next_allowedip = aip; peer->last_allowedip = aip; - aip->family = ip[j].c_af; - if (ip[j].c_af == AF_INET) { - memcpy(&aip->ip4, &ip[j].c_ip.ipv4, + aip->family = bcidr->c_af; + if (bcidr->c_af == AF_INET) { + memcpy(&aip->ip4, &bcidr->c_ip.ipv4, sizeof(aip->ip4)); - aip->cidr = ip[j].c_mask; - } else if (ip[j].c_af == AF_INET6) { - memcpy(&aip->ip6, &ip[j].c_ip.ipv6, + aip->cidr = bcidr->c_mask; + } else if (bcidr->c_af == AF_INET6) { + memcpy(&aip->ip6, &bcidr->c_ip.ipv6, sizeof(aip->ip6)); - aip->cidr = ip[j].c_mask; + aip->cidr = bcidr->c_mask; } } } @@ -1115,93 +1104,98 @@ static int openbsd_get_device(struct wgdevice **device, const char *interface) static int openbsd_set_device(struct wgdevice *dev) { - struct wg_serv_set wss; - struct wg_peer_set wsp; - struct ifreq ifr; + struct wg_device_io bdev; + struct wg_peer_io *bpeer; + struct wg_cidr_io *bcidr; struct wgpeer *peer; struct wgallowedip *aip; - strlcpy(wss.ss_name, dev->name, sizeof(wss.ss_name)); - strlcpy(wsp.sp_name, dev->name, sizeof(wsp.sp_name)); - strlcpy(ifr.ifr_name, dev->name, sizeof(ifr.ifr_name)); - getsock(); + bzero(&bdev, sizeof(bdev)); + strlcpy(bdev.d_name, dev->name, sizeof(bdev.d_name)); + if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY) { - memcpy(wss.ss_privkey.k, dev->private_key, WG_KEY_SIZE); - if (ioctl(s, SIOCSWGSERVKEY, (caddr_t)&wss) == -1) - return -1; + memcpy(bdev.d_privkey, dev->private_key, WG_KEY_SIZE); + bdev.d_flags |= WG_DEVICE_HAS_PRIVKEY; } if (dev->flags & WGDEVICE_HAS_LISTEN_PORT) { - wss.ss_port = dev->listen_port; - if (ioctl(s, SIOCSWGSERVPORT, (caddr_t)&wss) == -1) - return -1; + bdev.d_port = dev->listen_port; + bdev.d_flags |= WG_DEVICE_HAS_PORT; } if (dev->flags & WGDEVICE_HAS_FWMARK) { - ifr.ifr_rdomainid = dev->fwmark; - if (ioctl(s, SIOCSLIFPHYRTABLE, (caddr_t)&ifr) == -1) - return -1; + bdev.d_rdomain = dev->fwmark; + bdev.d_flags |= WG_DEVICE_HAS_RDOMAIN; } if (dev->flags & WGDEVICE_REPLACE_PEERS) - if (ioctl(s, SIOCCWGPEERS, (caddr_t)&wss) == -1) - return -1; + bdev.d_flags |= WG_DEVICE_REPLACE_PEERS; for_each_wgpeer(dev, peer) { - memcpy(wsp.sp_pubkey.k, peer->public_key, WG_KEY_SIZE); - if (peer->flags & WGPEER_REMOVE_ME) { - if (ioctl(s, SIOCDWGPEER, (caddr_t)&wsp) == -1) - return -1; - continue; + bdev.d_num_peers++; + for_each_wgallowedip(peer, aip) { + bdev.d_num_cidrs++; } + } + + bdev.d_peers = calloc(bdev.d_num_peers, sizeof(*bdev.d_peers)); + bdev.d_cidrs = calloc(bdev.d_num_cidrs, sizeof(*bdev.d_cidrs)); + + bpeer = bdev.d_peers; + bcidr = bdev.d_cidrs; + for_each_wgpeer(dev, peer) { + bpeer->p_flags = WG_PEER_HAS_PUBKEY; + memcpy(bpeer->p_pubkey, peer->public_key, WG_KEY_SIZE); + + if (peer->flags & WGPEER_REMOVE_ME) + bpeer->p_flags |= WG_PEER_REMOVE; if (peer->flags & WGPEER_HAS_PRESHARED_KEY) { - memcpy(wsp.sp_shared.k, peer->preshared_key, - WG_KEY_SIZE); - if (ioctl(s, SIOCSWGPEERPSK, (caddr_t)&wsp) == -1) - return -1; + memcpy(bpeer->p_sharedkey, peer->preshared_key, WG_KEY_SIZE); + bpeer->p_flags |= WG_PEER_REMOVE; } if (peer->endpoint.addr.sa_family == AF_INET || peer->endpoint.addr.sa_family == AF_INET6) { - memcpy(&wsp.sp_ip.sa, &peer->endpoint.addr, - peer->endpoint.addr.sa_len); - - if (ioctl(s, SIOCSWGPEERIP, (caddr_t)&wsp) == -1) - return -1; + memcpy(&bpeer->p_sa, &peer->endpoint.addr, peer->endpoint.addr.sa_len); + bpeer->p_flags |= WG_PEER_HAS_ENDPOINT; } if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL) { - wsp.sp_pka = peer->persistent_keepalive_interval; - if (ioctl(s, SIOCSWGPEERPKA, (caddr_t)&wsp) == -1) - return -1; + bpeer->p_persistentkeepalive = peer->persistent_keepalive_interval; + bpeer->p_flags |= WG_PEER_HAS_PERSISTENTKEEPALIVE; } if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS) - if (ioctl(s, SIOCCWGPEERAIP, (caddr_t)&wsp) == -1) - return -1; + bpeer->p_flags |= WG_PEER_REPLACE_CIDRS; + bpeer->p_num_cidrs = 0; + bpeer->p_cidrs = bcidr; for_each_wgallowedip(peer, aip) { - wsp.sp_route.c_af = aip->family; + bcidr->c_af = aip->family; if (aip->family == AF_INET) { - memcpy(&wsp.sp_route.c_ip, &aip->ip4, - sizeof(aip->ip4)); - wsp.sp_route.c_mask = aip->cidr; + memcpy(&bcidr->c_ip, &aip->ip4, + sizeof(aip->ip4)); + bcidr->c_mask = aip->cidr; } else if (aip->family == AF_INET6) { - memcpy(&wsp.sp_route.c_ip, &aip->ip6, - sizeof(aip->ip6)); - wsp.sp_route.c_mask = aip->cidr; + memcpy(&bcidr->c_ip, &aip->ip6, + sizeof(aip->ip6)); + bcidr->c_mask = aip->cidr; } else { return -1; } - - if (ioctl(s, SIOCSWGPEERAIP, (caddr_t)&wsp) == -1) - return -1; + bcidr++; + bpeer->p_num_cidrs++; } + bpeer++; } + + if (ioctl(s, SIOCSWG, (caddr_t)&bdev) == -1) + return -1; + return 0; } #endif /* OpenBSD */ |