From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp11.migadu.com ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms9.migadu.com with LMTPS id eMH7LrtMbmTBjAAASxT56A (envelope-from ) for ; Wed, 24 May 2023 19:43:23 +0200 Received: from aspmx1.migadu.com ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp11.migadu.com with LMTPS id EG7pLrtMbmT+UgEA9RJhRA (envelope-from ) for ; Wed, 24 May 2023 19:43:23 +0200 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 570F217A5D for ; Wed, 24 May 2023 19:43:23 +0200 (CEST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1q1sW1-0001Im-1n; Wed, 24 May 2023 13:43:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1q1sVz-0001Id-25 for guix-patches@gnu.org; Wed, 24 May 2023 13:43:11 -0400 Received: from debbugs.gnu.org ([209.51.188.43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1q1sVq-0003D9-7g for guix-patches@gnu.org; Wed, 24 May 2023 13:43:10 -0400 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1q1sVp-0000nD-SY for guix-patches@gnu.org; Wed, 24 May 2023 13:43:01 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#63402] [PATCH v5 2/5] services: wireguard: Implement a dynamic IP monitoring feature. Resent-From: Bruno Victal Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Wed, 24 May 2023 17:43:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 63402 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Maxim Cournoyer Cc: 63402@debbugs.gnu.org Received: via spool by 63402-submit@debbugs.gnu.org id=B63402.16849501252981 (code B ref 63402); Wed, 24 May 2023 17:43:01 +0000 Received: (at 63402) by debbugs.gnu.org; 24 May 2023 17:42:05 +0000 Received: from localhost ([127.0.0.1]:45053 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1q1sUv-0000m0-4T for submit@debbugs.gnu.org; Wed, 24 May 2023 13:42:05 -0400 Received: from smtpm2.myservices.hosting ([185.26.105.233]:42752) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1q1sUq-0000lX-BF for 63402@debbugs.gnu.org; Wed, 24 May 2023 13:42:03 -0400 Received: from mail1.netim.hosting (unknown [185.26.106.173]) by smtpm2.myservices.hosting (Postfix) with ESMTP id 3951020E8C; Wed, 24 May 2023 19:41:57 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by mail1.netim.hosting (Postfix) with ESMTP id 80F7C800AD; Wed, 24 May 2023 19:25:28 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at mail1.netim.hosting Received: from mail1.netim.hosting ([127.0.0.1]) by localhost (mail1-2.netim.hosting [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id 0C_a8Rq-fZO6; Wed, 24 May 2023 19:25:27 +0200 (CEST) Received: from [192.168.1.239] (unknown [10.192.1.83]) (Authenticated sender: lumen@makinata.eu) by mail1.netim.hosting (Postfix) with ESMTPSA id A97E9800A7; Wed, 24 May 2023 19:25:27 +0200 (CEST) Message-ID: Date: Wed, 24 May 2023 18:25:27 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.10.1 Content-Language: en-US References: From: Bruno Victal In-Reply-To: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+larch=yhetil.org@gnu.org Sender: guix-patches-bounces+larch=yhetil.org@gnu.org X-Migadu-Country: US X-Migadu-Flow: FLOW_IN ARC-Seal: i=1; s=key1; d=yhetil.org; t=1684950203; a=rsa-sha256; cv=none; b=mh8n69pTMNC/5IpUTKlS5RW2kRBLOujl3YrYpKaVTw/4Fmgds0Z+gFlER0OIOEwCeVqynz RDY8c3ogjnJmOtz8gJGDd4B39ZLZ1rbfD0kymccutoERiAidu5E6Gii6RtG0Y9r483O7sH QBv5GettTSm/gJUD0h+iQHWw8nJ+wXlGUHJv9P6HP0PN9zWgYnaafJBbGeavw3KdpVcOPB 5PwOX9eKZNlgiDdjCFRq7y6SQk4lCBD9hL8Ia6Q143UBkFHFVDew4jMOMmHUmJMa6qy1YD FcSIpAUYoW6kwZv2i5VueonCQIIExwRvDaY2HGauQnPnvwQLr1g6UrtF8OKEjA== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=none; dmarc=none; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org" ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1684950203; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding:resent-cc: resent-from:resent-sender:resent-message-id:in-reply-to:in-reply-to: references:references:list-id:list-help:list-unsubscribe: list-subscribe:list-post; bh=GDG8eIn3pZyo/SlopG9ok1FRVq5WPi5+xjT/DYxbRgU=; b=j4rM5r00fHypMh4zT7mc0SZ4K1zIrT/wicLqhMPa9E/Zt1zV7BMxFwy+k2r9iq2MhafNYZ TzMmpuqMGCYMWREfMpibKB5Ka5S4k44GpOqC2ZJob1VF+r+s0y5RO/jHOKFEQD3GRMABNH fUYmU7JiFsjxTVgKG60stEDxa2UUPFrnD8xmkxiYmEGpTmzcbVt9lj23v5Z1IBhXaAn5S5 1T/4u+AiP7GRmzvkDSSLWjFEb6fYyWhmd3RL23mNxn0t3tcK8Cga2NVG4bn4rXx497oC92 3BICtjzBT3ponJ6ZErytt3aBXv5Hc6jxSvQeym0kOKBQDQ7LsBXUq7DgzAx1uA== X-Migadu-Spam-Score: -4.01 X-Spam-Score: -4.01 X-Migadu-Queue-Id: 570F217A5D X-Migadu-Scanner: scn0.migadu.com Authentication-Results: aspmx1.migadu.com; dkim=none; dmarc=none; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org" X-TUID: KvoTmTjbXSlS On 2023-05-19 02:59, Maxim Cournoyer wrote: > +;;; XXX: Copied from (guix scripts pack), changing define to define*. > +(define-syntax-rule (define-with-source (variable args ...) body body* ...) > + "Bind VARIABLE to a procedure accepting ARGS defined as BODY, also setting > +its source property." > + (begin > + (define* (variable args ...) > + body body* ...) > + (eval-when (load eval) > + (set-procedure-property! variable 'source > + '(define* (variable args ...) body body* ...))))) > + > +(define (wireguard-service-name interface) > + "Return the WireGuard service name (a symbol) configured to use INTERFACE." > + (symbol-append 'wireguard- (string->symbol interface))) > + > +(define-with-source (strip-port/maybe endpoint #:key ipv6?) > + "Strip the colon and port, if present in ENDPOINT, a string." > + (if ipv6? > + (if (string-prefix? "[" endpoint) > + (first (string-split (string-drop endpoint 1) #\])) ;ipv6 > + endpoint) > + (first (string-split endpoint #\:)))) ;ipv4 [...] > + > +(define (ipv4-address? str) > + "Return true if STR denotes an IPv4 address." > + (false-if-exception > + (->bool (inet-pton AF_INET (strip-port/maybe str))))) [...] > + > +(define (ipv6-address? str) > + "Return true if STR denotes an IPv6 address." > + (false-if-exception > + (->bool (inet-pton AF_INET6 (strip-port/maybe str #:ipv6? #t))))) You should use getaddrinfo instead, reason being that inet-pton does not work with zone-indexes or interface names in IPv6 addresses. I expect that this snippet would get cloned and reused often which makes it important to get it right even if zone-indexes don't happen to be of particular interest here. I have this snippet that you could adapt to your liking (or use as-is): --8<---------------cut here---------------start------------->8--- (define* (ip-address? s #:optional family) "Check if @var{s} is a valid IP address. It optionally accepts a @var{family} argument, either AF_INET or AF_INET6, which can be used to exclusively check for IPv4 or IPv6 addresses." ;; Regrettably square brackets aren't accepted by getaddrinfo() and ;; must be removed beforehand. (let ((address (string-trim-both s (char-set #\[ #\]))) (false-if-exception (->bool (getaddrinfo address #f AI_NUMERICHOST family)))))) --8<---------------cut here---------------end--------------->8--- I'd also harmonize the ipv4 check to use getaddrinfo in case you specialize the snippet above for IPv6 only. (keeps things simpler) > + > +(define (host-name? name) > + "Predicate to check whether NAME is a host name, i.e. not an IP address." > + (not (or (ipv6-address? name) (ipv4-address? name)))) I'd craft an artificial uri string and extract this information from a uri record instead, since the above check is likely to reveal insufficient: --8<---------------cut here---------------start------------->8--- scheme@(guile-user)> (use-modules (web uri)) scheme@(guile-user)> (define s "example.tld:9999") scheme@(guile-user)> (uri-host (string->uri (string-append "dummy://" s))) $5 = "example.tld" scheme@(guile-user)> (define s "[2001:db8::1234]:9999") scheme@(guile-user)> (uri-host (string->uri (string-append "dummy://" s))) $6 = "2001:db8::1234" --8<---------------cut here---------------end--------------->8--- > (define wireguard-service-type > (service-type > (name 'wireguard) > @@ -898,6 +1036,8 @@ (define wireguard-service-type > wireguard-activation) > (service-extension profile-service-type > (compose list > - wireguard-configuration-wireguard)))) > + wireguard-configuration-wireguard)) > + (service-extension mcron-service-type > + wireguard-monitoring-jobs))) > (description "Set up Wireguard @acronym{VPN, Virtual Private Network} > tunnels."))) > diff --git a/tests/services/vpn.scm b/tests/services/vpn.scm > new file mode 100644 > index 0000000000..a7f4bec26b > --- /dev/null > +++ b/tests/services/vpn.scm > @@ -0,0 +1,83 @@ > +;;; GNU Guix --- Functional package management for GNU > +;;; Copyright © 2023 Maxim Cournoyer > +;;; > +;;; This file is part of GNU Guix. > +;;; > +;;; GNU Guix is free software; you can redistribute it and/or modify it > +;;; under the terms of the GNU General Public License as published by > +;;; the Free Software Foundation; either version 3 of the License, or (at > +;;; your option) any later version. > +;;; > +;;; GNU Guix is distributed in the hope that it will be useful, but > +;;; WITHOUT ANY WARRANTY; without even the implied warranty of > +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +;;; GNU General Public License for more details. > +;;; > +;;; You should have received a copy of the GNU General Public License > +;;; along with GNU Guix. If not, see . > + > +(define-module (tests services vpn) > + #:use-module (gnu packages vpn) > + #:use-module (gnu services vpn) > + #:use-module (guix gexp) > + #:use-module (ice-9 match) > + #:use-module (srfi srfi-1) > + #:use-module (srfi srfi-64)) > + > +;;; Commentary: > +;;; > +;;; Unit tests for the (gnu services vpn) module. > +;;; > +;;; Code: > + > +;;; Access some internals for whitebox testing. > +(define ipv4-address? (@@ (gnu services vpn) ipv4-address?)) > +(define ipv6-address? (@@ (gnu services vpn) ipv6-address?)) > +(define host-name? (@@ (gnu services vpn) host-name?)) IMO, these kind of utility procedures seem useful enough that they should go into either: * (gnu services configuration) * (gnu services network) * or a new module consisting of useful predicates perhaps? ** (gnu services configuration predicates) ** (gnu services configuration utils) > +(define endpoint-host-names > + (@@ (gnu services vpn) endpoint-host-names)) > + > +(test-begin "vpn-services") > + > +(test-assert "ipv4-address?" > + (every ipv4-address? > + (list "192.95.5.67:1234" > + "10.0.0.1"))) > + > +(test-assert "ipv6-address?" > + (every ipv6-address? > + (list "[2607:5300:60:6b0::c05f:543]:2468" > + "2607:5300:60:6b0::c05f:543" > + "2345:0425:2CA1:0000:0000:0567:5673:23b5" > + "2345:0425:2CA1::0567:5673:23b5"))) Are these addresses special? If not, I'd recommend (properly) generating a random ULA prefix and use it instead. > + > +(define %wireguard-peers > + (list (wireguard-peer > + (name "dummy1") > + (public-key "VlesLiEB5BFd//OD2ILKXviolfz+hodG6uZ+XjoalC8=") > + (endpoint "some.dynamic-dns.service:53281") > + (allowed-ips '())) > + (wireguard-peer > + (name "dummy2") > + (public-key "AlesLiEB5BFd//OD2ILKXviolfz+hodG6uZ+XgoalC9=") > + (endpoint "example.org") > + (allowed-ips '())) > + (wireguard-peer > + (name "dummy3") > + (public-key "BlesLiEB5BFd//OD2ILKXviolfz+hodG6uZ+XgoalC7=") > + (endpoint "10.0.0.7:7777") > + (allowed-ips '())) > + (wireguard-peer > + (name "dummy4") > + (public-key "ClesLiEB5BFd//OD2ILKXviolfz+hodG6uZ+XgoalC6=") > + (endpoint "[2345:0425:2CA1::0567:5673:23b5]:44444") > + (allowed-ips '())))) > + > +(test-equal "endpoint-host-names" > + '(("VlesLiEB5BFd//OD2ILKXviolfz+hodG6uZ+XjoalC8=" . > + "some.dynamic-dns.service:53281") > + ("AlesLiEB5BFd//OD2ILKXviolfz+hodG6uZ+XgoalC9=" . > + "example.org")) I think a comment that explains where these values were obtained from (or how they were generated) would be helpful for anyone looking at this in the future. -- Furthermore, I consider that nonfree software must be eradicated. Cheers, Bruno.