From patchwork Thu Jun 16 00:02:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12883085 Received: from mail-wr1-f51.google.com (mail-wr1-f51.google.com [209.85.221.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5F95B7E for ; Thu, 16 Jun 2022 00:02:40 +0000 (UTC) Received: by mail-wr1-f51.google.com with SMTP id c21so17347574wrb.1 for ; Wed, 15 Jun 2022 17:02:40 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=HeUk5YNtIO9TeLXsTOkL/ZW/66PCg3ok0c0E8E/QVV8=; b=i8S4TMzCV/aNEVLCjr3qCfcQHHXQgCBld52FSb+i797M8rz1myX3TJqmqzKWzqMWsp eG34wrDHuiA5/44huTsPR/mlhIYQ++cmDX2Lzcmz6CyT9kztbsCiQ6X2NGH2BnML6RiL 1nlOr9N2KTQQ1MVqJpgQp8oKBA5OqT+FqSCVkZgSpH08uIMwdxcdEeC9kPEsLDHoykpR Xh/RVahfTShghkuJNZZAhdYHzS5ww9TlMDfy//IW4wcVTGLMe0GiNaCZaEpVmIq1032M 39eDELcULtuNk2W02RxmYivZzCue+Rv7RXhTau1A8JVFyW69nXsQTdfnNcDIEp9j1kGW z6ZQ== X-Gm-Message-State: AJIora/7pm0v+6paT46Jxy4dAD05aFeDeUUKHDA+4OiPP0BuAtsWyQZq GOK/DIkCsAhdYrRdkmHKgZ0XYvhhJgU= X-Google-Smtp-Source: AGRyM1t94Gvnv4yjWU9eLRAmGzPDaBx8wDm0pmepV6p8ojaGpE3qhhQAyPrLvJf3+16LyoxTuIL5hA== X-Received: by 2002:adf:d205:0:b0:213:b49a:9fc7 with SMTP id j5-20020adfd205000000b00213b49a9fc7mr1991770wrh.589.1655337758266; Wed, 15 Jun 2022 17:02:38 -0700 (PDT) Received: from iss.Home ([82.213.231.20]) by smtp.gmail.com with ESMTPSA id az10-20020adfe18a000000b00210396b2eaesm337452wrb.45.2022.06.15.17.02.37 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Jun 2022 17:02:37 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 01/15] netconfig: Fix address format validation Date: Thu, 16 Jun 2022 02:02:17 +0200 Message-Id: <20220616000231.1966008-1-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Drop the wrong negation in the error check. Check that there are no extra characters after prefix length suffix. Reset errno 0 before the strtoul call, as recommended by the manpage. --- src/netconfig.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/netconfig.c b/src/netconfig.c index 2ab03b90..4a70b0ca 100644 --- a/src/netconfig.c +++ b/src/netconfig.c @@ -515,6 +515,7 @@ static struct l_rtnl_address *netconfig_get_static6_address( { L_AUTO_FREE_VAR(char *, ip); char *p; + char *endp; struct l_rtnl_address *ret; uint32_t prefix_len = 128; @@ -530,8 +531,9 @@ static struct l_rtnl_address *netconfig_get_static6_address( if (*++p == '\0') goto no_prefix_len; - prefix_len = strtoul(p, NULL, 10); - if (!unlikely(errno == EINVAL || errno == ERANGE || + errno = 0; + prefix_len = strtoul(p, &endp, 10); + if (unlikely(*endp != '\0' || errno || !prefix_len || prefix_len > 128)) { l_error("netconfig: Invalid prefix '%s' provided in network" " configuration file", p); From patchwork Thu Jun 16 00:02:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12883086 Received: from mail-wr1-f44.google.com (mail-wr1-f44.google.com [209.85.221.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 92AC429A0 for ; Thu, 16 Jun 2022 00:02:41 +0000 (UTC) Received: by mail-wr1-f44.google.com with SMTP id h19so14087557wrc.12 for ; Wed, 15 Jun 2022 17:02:41 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Mhi2SEFsuruUlqjs9YbwvTp6i79tBx2IFd/EfMwbNxo=; b=3lNqrcyOW35c8RGlhYNmnDmB9jsottW15S6+V8hTqwCz6tiMKyLfOtN5TsXcVEygEj XgM7rLoZ1gOwkDhFA6hQZOLOIieokmPjnELnXWQGzmb7ZxjcEwhddetT7yrhja7yMfN6 njlnIu3VIzvftCI7hUFvePX5VoTL8bok6Xn3GKfLPlfiJ5qKFOFmZLB5fRdj2D2FntNg 64dKboAydwXoW3qUkDb7GykdV3Yjoqy1tLjCPIWh/dDwLkqVpyhcmNkf7rUL4eAyBOQr VAT+Kb0QHaHnLQ9l0Vf2Ux963lV7UYV0Ne8tcbdVScZTbGOQKWzbsKBZzU/wUvU6DBdD xdTQ== X-Gm-Message-State: AJIora9p8xi/1fImJgw4jJYuWuneL6B8pXftOpjKh5mMp388NpsTPF9M 0zPTDt/xMdbEP0WuVnTKcMbrymki+6Y= X-Google-Smtp-Source: AGRyM1t/P+bcerePEzuD1zdKy/z7HAPFoAynBW/AmDpx7nblTTy2CY7+GyvBav37oi59C7sNLVXteA== X-Received: by 2002:a05:6000:242:b0:210:354e:c89a with SMTP id m2-20020a056000024200b00210354ec89amr2118629wrz.136.1655337759522; Wed, 15 Jun 2022 17:02:39 -0700 (PDT) Received: from iss.Home ([82.213.231.20]) by smtp.gmail.com with ESMTPSA id az10-20020adfe18a000000b00210396b2eaesm337452wrb.45.2022.06.15.17.02.38 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Jun 2022 17:02:39 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 02/15] storage: Log a message on network file parse errors Date: Thu, 16 Jun 2022 02:02:18 +0200 Message-Id: <20220616000231.1966008-2-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220616000231.1966008-1-andrew.zaborowski@intel.com> References: <20220616000231.1966008-1-andrew.zaborowski@intel.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Most users of storage_network_open don't log errors when the function returns a NULL and fall back to defaults (empty l_settings). storage_network_open() itself only logs errors if the flie is encrypted. Now also log an error when l_settings_load_from_file() fails to help track down potential syntax errors. --- src/storage.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/storage.c b/src/storage.c index 2100d08d..77be36c8 100644 --- a/src/storage.c +++ b/src/storage.c @@ -597,8 +597,10 @@ struct l_settings *storage_network_open(enum security type, const char *ssid) settings = l_settings_new(); - if (!l_settings_load_from_file(settings, path)) + if (!l_settings_load_from_file(settings, path)) { + l_error("Error loading %s", path); goto error; + } if (type != SECURITY_NONE && !storage_decrypt(settings, path, ssid)) goto error; From patchwork Thu Jun 16 00:02:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12883087 Received: from mail-wm1-f53.google.com (mail-wm1-f53.google.com [209.85.128.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F221829A0 for ; Thu, 16 Jun 2022 00:02:42 +0000 (UTC) Received: by mail-wm1-f53.google.com with SMTP id m16-20020a7bca50000000b0039c8a224c95so15845wml.2 for ; Wed, 15 Jun 2022 17:02:42 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=8D2nmdzMJrBSrgVyQQtDZV0hCeQKevElCAaw6IG/wKQ=; b=ZMni95/VFH8cZ3j3FR65hAmGK6HkJIJ0oYqLb6bIV13mwWHkgkKAo9Xhnki+r3L6PA k7luiNaGS8oYH81W/t53vzH1/SKny4WTCBHlRZRwIzHcjSDuEJ2vsHaioRF3iggtKOP6 ZUMoLojucer1hHsp/7bzd8HsEDavPuh9tUAW09tN3+XKEUaUSx9ZwD/jkmmHmVozPCmE 29XtqCdwRXtfMACR/NzmeyGlrpW5apVQXNfch4HXTihJyubhnczA+aQagmu8JbCqp3oC c0+9HafqImvYlIn7nhBjWZf+I/9qc7ZXZ4iTG91Ui+pfPhf9UpMNGIEZLRSSpuV4TmfE HZiQ== X-Gm-Message-State: AJIora8g3paCwoN9m/X3+1w1yGuG5pHIY1cWXM1X+Xsxpk2jSjgllF4+ Dx1c2tO5C6mcNOo+kaSSed6mCEh8uMc= X-Google-Smtp-Source: AGRyM1tMT9eHuK3qgYEHGilyPVxRqPqVt7qOhMrbySoLK/RB0GeF3bDbgT4Qoulyj5ePfylTNyGNdg== X-Received: by 2002:a7b:c389:0:b0:39c:49fe:25df with SMTP id s9-20020a7bc389000000b0039c49fe25dfmr1981588wmj.164.1655337760918; Wed, 15 Jun 2022 17:02:40 -0700 (PDT) Received: from iss.Home ([82.213.231.20]) by smtp.gmail.com with ESMTPSA id az10-20020adfe18a000000b00210396b2eaesm337452wrb.45.2022.06.15.17.02.39 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Jun 2022 17:02:40 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 03/15] station: Move netconfig_reset() to common path Date: Thu, 16 Jun 2022 02:02:19 +0200 Message-Id: <20220616000231.1966008-3-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220616000231.1966008-1-andrew.zaborowski@intel.com> References: <20220616000231.1966008-1-andrew.zaborowski@intel.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To avoid repetition, call netconfig_reset in station_reset_connection_state. --- src/station.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/station.c b/src/station.c index 7c88f266..e5972269 100644 --- a/src/station.c +++ b/src/station.c @@ -1623,6 +1623,9 @@ static void station_reset_connection_state(struct station *station) station_roam_state_clear(station); + if (station->netconfig) + netconfig_reset(station->netconfig); + /* Refresh the ordered network list */ network_rank_update(station->connected_network, false); l_queue_remove(station->networks_sorted, station->connected_network); @@ -1655,9 +1658,6 @@ static void station_disassociated(struct station *station) { l_debug("%u", netdev_get_ifindex(station->netdev)); - if (station->netconfig) - netconfig_reset(station->netconfig); - station_reset_connection_state(station); station_enter_state(station, STATION_STATE_DISCONNECTED); @@ -3096,9 +3096,6 @@ static void station_disconnect_onconnect(struct station *station, return; } - if (station->netconfig) - netconfig_reset(station->netconfig); - station_reset_connection_state(station); station_enter_state(station, STATION_STATE_DISCONNECTING); @@ -3402,9 +3399,6 @@ int station_disconnect(struct station *station) if (!station->connected_bss) return -ENOTCONN; - if (station->netconfig) - netconfig_reset(station->netconfig); - /* * If the disconnect somehow fails we won't know if we're still * connected so we may as well indicate now that we're no longer From patchwork Thu Jun 16 00:02:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12883088 Received: from mail-wm1-f42.google.com (mail-wm1-f42.google.com [209.85.128.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D975C7E for ; Thu, 16 Jun 2022 00:02:43 +0000 (UTC) Received: by mail-wm1-f42.google.com with SMTP id m39-20020a05600c3b2700b0039c511ebbacso1971128wms.3 for ; Wed, 15 Jun 2022 17:02:43 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=IcX2R8FklC2JIsP5sECfz8s5rM4VE3SuVHPK/uFGlwI=; b=oxDO6+e5hBduP9FpAv2wEQiHkWvgSOGkxQDA+tYpb0bIzNshzuu0BiJcjcDLVfPW8b GZ85Sevzxfwzr2W0KwvrRMhQQ3SP1Nv9OYnbKtiQcpyQgdDTnmyqVBZKS7mBXMtbpuI6 6JnVpH6gJvAG2M9gTE0R6KdAkGA+jRdMNqJ/LEQJ3AsDF2MaEra+g7FpCYtM3uAF/ouI iNw35WViqQHCasF9gBf3gjLoSGT6LMsEA36ALfFM3Bq8SVY6Le9MSIFUjgfgW4mQWaf0 LDntEVMu8x5Tpl6YIwhuaAveEum59tLyibWjX+b8m6F4YgdW7wh6Vjk3mNWGbnH2Tuu+ FKeA== X-Gm-Message-State: AOAM533Ie2D2z7mHj03WN7ZxvOMdNJjVdmxIuppBDyjZZWMK4jDp1xxR 0eBG60qLVHx7a8cE8O7+hBYc8WwB/G4= X-Google-Smtp-Source: ABdhPJx/mK4QIJ/TgiqAjNCGccGQfD2oXQ13/Vr2tMQKOnMdeX+bGpAa5MZGYHxJxEj575dtQJjPbQ== X-Received: by 2002:a1c:4c12:0:b0:39c:6750:be17 with SMTP id z18-20020a1c4c12000000b0039c6750be17mr12588942wmf.21.1655337761897; Wed, 15 Jun 2022 17:02:41 -0700 (PDT) Received: from iss.Home ([82.213.231.20]) by smtp.gmail.com with ESMTPSA id az10-20020adfe18a000000b00210396b2eaesm337452wrb.45.2022.06.15.17.02.41 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Jun 2022 17:02:41 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 04/15] monitor: Print netlink errors from Extended ACKs if available Date: Thu, 16 Jun 2022 02:02:20 +0200 Message-Id: <20220616000231.1966008-4-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220616000231.1966008-1-andrew.zaborowski@intel.com> References: <20220616000231.1966008-1-andrew.zaborowski@intel.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 --- monitor/nlmon.c | 55 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 17 deletions(-) diff --git a/monitor/nlmon.c b/monitor/nlmon.c index 34c5eed6..ff23140d 100644 --- a/monitor/nlmon.c +++ b/monitor/nlmon.c @@ -50,6 +50,7 @@ #include "linux/nl80211.h" #include "ell/useful.h" +#include "ell/netlink-private.h" #include "src/ie.h" #include "src/mpdu.h" #include "src/eapol.h" @@ -5332,15 +5333,7 @@ static const struct attr_entry rekey_table[] = { { } }; -#define NLA_OK(nla,len) ((len) >= (int) sizeof(struct nlattr) && \ - (nla)->nla_len >= sizeof(struct nlattr) && \ - (nla)->nla_len <= (len)) -#define NLA_NEXT(nla,attrlen) ((attrlen) -= NLA_ALIGN((nla)->nla_len), \ - (struct nlattr*)(((char*)(nla)) + \ - NLA_ALIGN((nla)->nla_len))) - -#define NLA_LENGTH(len) (NLA_ALIGN(sizeof(struct nlattr)) + (len)) -#define NLA_DATA(nla) ((void*)(((char*)(nla)) + NLA_LENGTH(0))) +#undef NLA_PAYLOAD #define NLA_PAYLOAD(nla) ((int)((nla)->nla_len - NLA_LENGTH(0))) static void print_supported_commands(unsigned int level, const char *label, @@ -6835,7 +6828,7 @@ static void netlink_str(char *str, size_t size, } } -static void print_message(struct nlmon *nlmon, const struct timeval *tv, +static bool print_message(struct nlmon *nlmon, const struct timeval *tv, enum msg_type type, uint16_t flags, int status, uint8_t cmd, uint8_t version, @@ -6848,11 +6841,11 @@ static void print_message(struct nlmon *nlmon, const struct timeval *tv, bool out = false; if (nlmon->nowiphy && (cmd == NL80211_CMD_NEW_WIPHY)) - return; + return false; if (nlmon->noscan && ((cmd == NL80211_CMD_NEW_SCAN_RESULTS) || (cmd == NL80211_CMD_TRIGGER_SCAN))) - return; + return false; switch (type) { case MSG_REQUEST: @@ -6911,6 +6904,8 @@ static void print_message(struct nlmon *nlmon, const struct timeval *tv, print_field("Status: %d", status); break; } + + return true; } struct nlmon_req_match { @@ -6978,12 +6973,17 @@ static void nlmon_message(struct nlmon *nlmon, const struct timeval *tv, enum msg_type type; struct nlmsgerr *err; int status; + bool print; + const char *err_str = NULL; + uint32_t err_offset = -1U; switch (nlmsg->nlmsg_type) { case NLMSG_ERROR: type = MSG_RESPONSE; err = NLMSG_DATA(nlmsg); status = -err->error; + netlink_parse_ext_ack_error(nlmsg, &err_str, + &err_offset); break; case NLMSG_DONE: type = MSG_COMPLETE; @@ -6994,10 +6994,18 @@ static void nlmon_message(struct nlmon *nlmon, const struct timeval *tv, } store_message(nlmon, tv, nlmsg); - print_message(nlmon, tv, type, nlmsg->nlmsg_flags, status, + print = print_message(nlmon, tv, type, + nlmsg->nlmsg_flags, status, req->cmd, req->version, NULL, sizeof(status)); nlmon_req_free(req); + + if (err_str && print) + print_field("Extended error: %s", err_str); + + if (err_offset != -1U && print) + print_field("Offending element offset: %i " + "bytes", (int) err_offset); } return; } @@ -7795,6 +7803,8 @@ static void print_nlmsg(const struct timeval *tv, const struct nlmsghdr *nlmsg) { struct nlmsgerr *err; int status; + const char *err_str = NULL; + uint32_t err_offset = -1U; print_nlmsghdr(tv, nlmsg); @@ -7802,11 +7812,22 @@ static void print_nlmsg(const struct timeval *tv, const struct nlmsghdr *nlmsg) case NLMSG_ERROR: err = NLMSG_DATA(nlmsg); status = err->error; - if (status < 0) - print_field("Error: %d (%s)", - status, strerror(-status)); - else + if (status >= 0) { print_field("ACK: %d", status); + break; + } + + print_field("Error: %d (%s)", status, strerror(-status)); + + netlink_parse_ext_ack_error(nlmsg, &err_str, &err_offset); + + if (err_str) + print_field("Extended error: %s", err_str); + + if (err_offset != -1U) + print_field("Offending element offset: %i bytes", + (int) err_offset); + break; case NLMSG_DONE: From patchwork Thu Jun 16 00:02:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12883089 Received: from mail-wm1-f42.google.com (mail-wm1-f42.google.com [209.85.128.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0D45A29A0 for ; Thu, 16 Jun 2022 00:02:45 +0000 (UTC) Received: by mail-wm1-f42.google.com with SMTP id m32-20020a05600c3b2000b0039756bb41f2so10813wms.3 for ; Wed, 15 Jun 2022 17:02:44 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=QECsvCHahf32Qu/R/woSAdr0zJ9HCFgUpWMx5sX8YPI=; b=IlokYRFa/0lcOUTHq5FjSkhyges3ZbQ5KnDkJVUg/El0opa0+QpZvY7WrFh9pB0m3u XvrHtDtpZ9XE/2otBnhi1mblN45YORhV28G4gRljFoF2WhGriccFM/JwANQKu8J9NKz5 3Gz/h1eiDVzuKlxKSD6pWGpYpEJdeNoD36Uhbb7XRkZ6Xm6o63hgWqbY1WOcDjjSWmE5 mEP+Rt62B3kKKMOqw/yit3dIS7/ucMynNX28KXRCPCPAQwd5BC+bu+68QWQdzkoa4kba DkenNqtjvnsGGDQcZIbI+NLB30wEX/RNwiUhtrUItl8XCOZ+PtY/t/ndGib4lC+8688f I80w== X-Gm-Message-State: AOAM531rBKlzkuYwHYO1OvbrpbgGOJyCcmhlC/Uv1mUTwompXFktMWZe xzCciQdUx6XMFqGdYn3FMwN/5Z6c7K8= X-Google-Smtp-Source: ABdhPJySAPYwNwkmGcH5FD4AOphgCy08T/XA1OCd9jiGnXvmwsgAc7d9LI1GP1/ZSIgpNvyeuabGcA== X-Received: by 2002:a7b:ce0f:0:b0:39c:8217:1a5d with SMTP id m15-20020a7bce0f000000b0039c82171a5dmr12483267wmc.101.1655337762997; Wed, 15 Jun 2022 17:02:42 -0700 (PDT) Received: from iss.Home ([82.213.231.20]) by smtp.gmail.com with ESMTPSA id az10-20020adfe18a000000b00210396b2eaesm337452wrb.45.2022.06.15.17.02.42 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Jun 2022 17:02:42 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 05/15] testrunner: Fix parsing for some arguments Date: Thu, 16 Jun 2022 02:02:21 +0200 Message-Id: <20220616000231.1966008-5-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220616000231.1966008-1-andrew.zaborowski@intel.com> References: <20220616000231.1966008-1-andrew.zaborowski@intel.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Currently the parameter values reach run-tests by first being parsed by runner.py's RunnerArgParser, then the resulting object members being encoded as a commandline string, then as environment variables, then the environment being converted to a python string list and passed to RunnerCoreArgParser again. Where argument names (like --sub-tests) had dashes, the object members had underscores (.sub_tests), this wasn't taken into account when building the python string list from environment variables so convert all underscores to dashes and hope that all the names match now. Additionally some arguments used nargs='1' or nargs='*' which resulted in their python values becoming lists. They were converted back to command line arguments such as: --sub_tests ['static_test.py'], and when parsed by RunnerCoreArgParser again, the values ended up being lists of lists. In all three cases it seems the actual user of the parsed value actually expects a single string with comma-separated substrings in it so just drop the nargs= uses. --- tools/runner.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tools/runner.py b/tools/runner.py index 2ce26de0..b018a0ad 100644 --- a/tools/runner.py +++ b/tools/runner.py @@ -108,7 +108,7 @@ class RunnerCoreArgParse(ArgumentParser): help='Enables iwmon output to file') self.add_argument('--sub-tests', '-S', metavar='', - type=str, nargs=1, help='List of subtests to run', + type=str, help='List of subtests to run', default=None, dest='sub_tests') self.add_argument('--result', '-e', type=os.path.abspath, @@ -131,8 +131,6 @@ class RunnerCoreArgParse(ArgumentParser): auto_unit_group.add_argument('--unit-tests', '-U', metavar='', type=str, - nargs='?', - const='*', help='List of unit tests to run', dest='unit_tests') @@ -141,7 +139,6 @@ class RunnerCoreArgParse(ArgumentParser): valgrind_gdb_group.add_argument('--gdb', '-g', metavar='', type=str, - nargs=1, help='Run gdb on specified executable', dest='gdb') valgrind_gdb_group.add_argument('--valgrind', '-V', @@ -156,7 +153,7 @@ class RunnerCoreArgParse(ArgumentParser): options = [] for k, v in os.environ.items(): - options.append('--' + k) + options.append('--' + k.replace('_', '-')) options.append(v) return self.parse_known_args(args=options, namespace=RunnerNamespace())[0] From patchwork Thu Jun 16 00:02:22 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12883090 Received: from mail-wr1-f51.google.com (mail-wr1-f51.google.com [209.85.221.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3D92029A3 for ; Thu, 16 Jun 2022 00:02:45 +0000 (UTC) Received: by mail-wr1-f51.google.com with SMTP id c21so17347574wrb.1 for ; Wed, 15 Jun 2022 17:02:45 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=MSWzVlDker448CV4TWfee9AAFefOasVI4lEZAi8V5Vw=; b=n56u5IFkYCiEjNH2lqJ2zQU+Q4r4lxKo6Mr0wH3d4jPThd/iEMtZe3i6sCA/cPU7pI X8YqSox1fTr7qMWJSElnlwcrlYxSkz1xHvUBgVuacX3I5cJyqKpCygJY9ctnZRWH0nTe LR/8j0WVsyWWkF7CD729MiJRJT/ZelfgesAVq7QiN9NjYbZyQyFMakjhSaGQzuOF/PYi CmlyPqizNOzzkxszD9RNwwwBM6g2ZPRP1ZK1va8kot9lFOMQLe1Dpdzjc1aPAL1S3HDd mGeUSmOI6HqIC0kY9i6LywMY3GJEDUBqCGbxGm0VC8xXbwPKtSk6qLt+dUHdxH4fmNOJ sgwg== X-Gm-Message-State: AJIora9GJQtyANEotwMKAum4TCdzJQr6MaGEbZS15vROyuA4Az7Xx8k5 M1kXaPiTt9iGigjk2RN9PKk4O8BX/O0= X-Google-Smtp-Source: AGRyM1tdJLzvFlWAFLaXYM+jhNW2+xEt7LF/C1rslH9OZlyxwnyV9uWZJfC2A8dN5n8hSQXUCopLig== X-Received: by 2002:a5d:6348:0:b0:213:3a8e:e75d with SMTP id b8-20020a5d6348000000b002133a8ee75dmr2002729wrw.55.1655337764426; Wed, 15 Jun 2022 17:02:44 -0700 (PDT) Received: from iss.Home ([82.213.231.20]) by smtp.gmail.com with ESMTPSA id az10-20020adfe18a000000b00210396b2eaesm337452wrb.45.2022.06.15.17.02.43 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Jun 2022 17:02:43 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 06/15] test-runner: Support iwd-rtnl as a --verbose value Date: Thu, 16 Jun 2022 02:02:22 +0200 Message-Id: <20220616000231.1966008-6-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220616000231.1966008-1-andrew.zaborowski@intel.com> References: <20220616000231.1966008-1-andrew.zaborowski@intel.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 --- tools/utils.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/utils.py b/tools/utils.py index d16f221f..3cee9a22 100644 --- a/tools/utils.py +++ b/tools/utils.py @@ -405,6 +405,9 @@ class Namespace: if Process.is_verbose('iwd-acd'): env['IWD_ACD_DEBUG'] = '1' + if Process.is_verbose('iwd-rtnl'): + env['IWD_RTNL_DEBUG'] = '1' + return self.start_process(args, env=env) @staticmethod From patchwork Thu Jun 16 00:02:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12883091 Received: from mail-wr1-f51.google.com (mail-wr1-f51.google.com [209.85.221.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 65EE07E for ; Thu, 16 Jun 2022 00:02:47 +0000 (UTC) Received: by mail-wr1-f51.google.com with SMTP id s1so17299631wra.9 for ; Wed, 15 Jun 2022 17:02:47 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=r4vRxVU2FW4g4w9ahnql53sfkKtfO+xQM6sqepg0z/Q=; b=jf6hVDQm5EXOCl++XxP+eVOvVFI2d4Z2HvkKpIjkxF/4BCXVwOhWnBY6mMu7AneXxv jVn3qH++L9WCPKUrMR7Y4FeOq5ZRO3+FEdTQJdnIp7r75vIcbTLqkqt5PeScLxEAgz1f lGv4DAHMxLncOsUN0iU789g1W5L8/fDF9xS/LESz8SN06oslQvZa+XPyUxqCd/bpDKXp tvds+5lKw+p8lFp2XVrJPs4lKUCewEXMJknlrIZrJbQY/uqD2sPOl1NWfpXw0IW8KFsv XZYuEnyvukWVIOLPguYOViZwpaFmGfn+WH3qpXt0lYsla6MC+6/abpNrQepO0XvoxxpC ot5w== X-Gm-Message-State: AJIora979Xs0BkWt9QZibgC+Qc3gXWhLCox6OXdtABHN/EK8rIOgdG/K 0ZTe5kNuorQWPPFMRuBOuWbVs4IKYZ0= X-Google-Smtp-Source: AGRyM1uCV+pNEFQ+JnZRub843G5xTH9fq6UysHqolJsQVRiuTSCe0B4+4FpANTs69017bPNLs5nKzA== X-Received: by 2002:a05:6000:85:b0:213:b57a:ea74 with SMTP id m5-20020a056000008500b00213b57aea74mr2070568wrx.69.1655337765360; Wed, 15 Jun 2022 17:02:45 -0700 (PDT) Received: from iss.Home ([82.213.231.20]) by smtp.gmail.com with ESMTPSA id az10-20020adfe18a000000b00210396b2eaesm337452wrb.45.2022.06.15.17.02.44 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Jun 2022 17:02:44 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 07/15] autotests: Drop unused file+directory Date: Thu, 16 Jun 2022 02:02:23 +0200 Message-Id: <20220616000231.1966008-7-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220616000231.1966008-1-andrew.zaborowski@intel.com> References: <20220616000231.1966008-1-andrew.zaborowski@intel.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 --- autotests/testNetconfig/storage/ssidTKIP.psk | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 autotests/testNetconfig/storage/ssidTKIP.psk diff --git a/autotests/testNetconfig/storage/ssidTKIP.psk b/autotests/testNetconfig/storage/ssidTKIP.psk deleted file mode 100644 index f15724a3..00000000 --- a/autotests/testNetconfig/storage/ssidTKIP.psk +++ /dev/null @@ -1,3 +0,0 @@ -[IPv4] -Address=192.168.1.10 -Gateway=192.168.1.1 From patchwork Thu Jun 16 00:02:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12883092 Received: from mail-wr1-f44.google.com (mail-wr1-f44.google.com [209.85.221.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7B98B29A0 for ; Thu, 16 Jun 2022 00:02:47 +0000 (UTC) Received: by mail-wr1-f44.google.com with SMTP id h19so14087557wrc.12 for ; Wed, 15 Jun 2022 17:02:47 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=CCYbkT8Y/GcGOjj+CdSKeM1RT2zg8l3iTRDTSvBYA0s=; b=Xjd1eLFOSSfq7Hf9ont9USu1TIDjkd66vJE9c3iLfgx/5vap/aX8N/CHE02b2MZ4lF x6I0tlBJKOiSega+Ty4g3ElPm9/9OBIA9IJDAbQY0f7QRwCll5Lb/roYgkiyzYTQwSnr Sf2C7d+ZQL8ZlkRIExELl0ixMWe9qjFqhQ5NJckYh3SAIse/Eiq4B7F2EfI1dvbaHl0l tTwLcbZc+On52BWXLPzehVqKvrwE7m5pFKjuS2guVHH9ZfDnTtqnt/p9KI/D/d/HcjY+ +dX7KzN9l9KzQSU//xB7Bc2VMp1OthAqsiaphhHPVJ3AMGgWx3xjPkrTgAUQxcy5mVS+ 57lg== X-Gm-Message-State: AJIora+hxx0tFkex97tbfpjQ9ssQO+LXeG/Em2fSrth1FqRhjrchNyEZ 9T4k9vnxkERBQMG+37fjViwD8+MSn/I= X-Google-Smtp-Source: AGRyM1vCzWBsTQ1TefI07SazyBGIZ/X/s6AefsWbL4S8yQMeyr2SOSAbPFpgb7ukLlopXIWKmcs6nA== X-Received: by 2002:a5d:598e:0:b0:219:ea16:5a2a with SMTP id n14-20020a5d598e000000b00219ea165a2amr2079644wri.343.1655337766539; Wed, 15 Jun 2022 17:02:46 -0700 (PDT) Received: from iss.Home ([82.213.231.20]) by smtp.gmail.com with ESMTPSA id az10-20020adfe18a000000b00210396b2eaesm337452wrb.45.2022.06.15.17.02.45 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Jun 2022 17:02:46 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 08/15] autotests: Validate netmasks in testNetconfig, add utility Date: Thu, 16 Jun 2022 02:02:24 +0200 Message-Id: <20220616000231.1966008-8-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220616000231.1966008-1-andrew.zaborowski@intel.com> References: <20220616000231.1966008-1-andrew.zaborowski@intel.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Extend test_ip_address_match to support IPv6 and to test the netmask/prefix length while it reads the local address since those are retrieved using the same API. Modify testNetconfig to validate the prefix lengths, change the prefix lengths to be less common values (not 24 bits for IPv4 or 64 for IPv6), minor cleanup. --- autotests/testNetconfig/connection_test.py | 12 ++-- autotests/testNetconfig/dhcpd-v6.conf | 2 +- autotests/testNetconfig/dhcpd.conf | 8 +-- autotests/testNetconfig/ssidTKIP.psk | 1 + autotests/testNetconfig/static_test.py | 6 +- autotests/util/testutil.py | 75 ++++++++++++++++++---- 6 files changed, 79 insertions(+), 25 deletions(-) diff --git a/autotests/testNetconfig/connection_test.py b/autotests/testNetconfig/connection_test.py index 672efb72..0334267b 100644 --- a/autotests/testNetconfig/connection_test.py +++ b/autotests/testNetconfig/connection_test.py @@ -11,7 +11,7 @@ from iwd import NetworkType from hostapd import HostapdCLI import testutil from config import ctx -import os, time +import os import subprocess class Test(unittest.TestCase): @@ -19,8 +19,9 @@ class Test(unittest.TestCase): def test_connection_success(self): def check_addr(device): try: - subprocess.check_output('ip addr show ' + device.name + \ - ' | grep \'inet6 3ffe:501:ffff:100::\'', shell=True) + # DHCPv6 addresses always have a prefix length of 128 bits, the actual + # subnet's prefix length is in the route. + testutil.test_ip_address_match(device.name, '3ffe:501:ffff:100::1', 128, 112) except: return False @@ -49,6 +50,7 @@ class Test(unittest.TestCase): testutil.test_iface_operstate() testutil.test_ifaces_connected() + testutil.test_ip_address_match(device.name, '192.168.1.10', 17, 24) ctx.non_block_wait(check_addr, 10, device, exception=Exception("IPv6 address was not set")) @@ -78,14 +80,14 @@ class Test(unittest.TestCase): # TODO: This could be moved into test-runner itself if other tests ever # require this functionality (p2p, FILS, etc.). Since its simple # enough it can stay here for now. - ctx.start_process(['ip', 'addr','add', '192.168.1.1/255.255.255.0', + ctx.start_process(['ip', 'addr','add', '192.168.1.1/255.255.128.0', 'dev', hapd.ifname,]).wait() ctx.start_process(['touch', '/tmp/dhcpd.leases']).wait() cls.dhcpd_pid = ctx.start_process(['dhcpd', '-f', '-cf', '/tmp/dhcpd.conf', '-lf', '/tmp/dhcpd.leases', hapd.ifname], cleanup=remove_lease4) - ctx.start_process(['ip', 'addr', 'add', '3ffe:501:ffff:100::1/64', + ctx.start_process(['ip', 'addr', 'add', '3ffe:501:ffff:100::1/72', 'dev', hapd.ifname]).wait() ctx.start_process(['touch', '/tmp/dhcpd6.leases']).wait() cls.dhcpd6_pid = ctx.start_process(['dhcpd', '-6', '-f', '-cf', '/tmp/dhcpd-v6.conf', diff --git a/autotests/testNetconfig/dhcpd-v6.conf b/autotests/testNetconfig/dhcpd-v6.conf index 7a22cc65..917ee8a3 100644 --- a/autotests/testNetconfig/dhcpd-v6.conf +++ b/autotests/testNetconfig/dhcpd-v6.conf @@ -1,4 +1,4 @@ -subnet6 3ffe:501:ffff:100::/64 +subnet6 3ffe:501:ffff:100::/72 { option dhcp6.name-servers 3ffe:501:ffff:100::1; range6 3ffe:501:ffff:100::10 3ffe:501:ffff:100::20; diff --git a/autotests/testNetconfig/dhcpd.conf b/autotests/testNetconfig/dhcpd.conf index 0c4fe9b9..ea9957a3 100644 --- a/autotests/testNetconfig/dhcpd.conf +++ b/autotests/testNetconfig/dhcpd.conf @@ -1,14 +1,14 @@ default-lease-time 600; # 10 minutes max-lease-time 7200; # 2 hours -option broadcast-address 192.168.1.255; +option broadcast-address 192.168.127.255; option routers 192.168.1.254; -option subnet-mask 255.255.255.0; +option subnet-mask 255.255.128.0; -subnet 192.168.1.0 netmask 255.255.255.0 +subnet 192.168.0.0 netmask 255.255.128.0 { option routers 192.168.1.1; - option subnet-mask 255.255.255.0; + option subnet-mask 255.255.128.0; option domain-name-servers 192.168.1.1; range 192.168.1.10 192.168.1.20; range 192.168.1.100 192.168.1.200; diff --git a/autotests/testNetconfig/ssidTKIP.psk b/autotests/testNetconfig/ssidTKIP.psk index 64e84f12..eea59cda 100644 --- a/autotests/testNetconfig/ssidTKIP.psk +++ b/autotests/testNetconfig/ssidTKIP.psk @@ -1,5 +1,6 @@ [IPv4] Address=192.168.1.10 +Netmask=255.255.255.128 Gateway=192.168.1.1 [Settings] diff --git a/autotests/testNetconfig/static_test.py b/autotests/testNetconfig/static_test.py index bba2c644..e82dbaeb 100644 --- a/autotests/testNetconfig/static_test.py +++ b/autotests/testNetconfig/static_test.py @@ -45,7 +45,7 @@ class Test(unittest.TestCase): testutil.test_iface_operstate() testutil.test_ifaces_connected() - testutil.test_ip_address_match(dev1.name, '192.168.1.10') + testutil.test_ip_address_match(dev1.name, '192.168.1.10', 25) ordered_network = dev2.get_ordered_network('ssidTKIP') @@ -79,9 +79,9 @@ class Test(unittest.TestCase): hapd = HostapdCLI() # TODO: This could be moved into test-runner itself if other tests ever - # require this functionality (p2p, FILS, etc.). Since its simple + # require this functionality (p2p, FILS, etc.). Since it's simple # enough it can stay here for now. - ctx.start_process(['ip', 'addr','add', '192.168.1.1/255.255.255.0', + ctx.start_process(['ip', 'addr','add', '192.168.1.1/255.255.128.0', 'dev', hapd.ifname]).wait() ctx.start_process(['touch', '/tmp/dhcpd.leases']).wait() cls.dhcpd_pid = ctx.start_process(['dhcpd', '-f', '-cf', '/tmp/dhcpd.conf', diff --git a/autotests/util/testutil.py b/autotests/util/testutil.py index 01c42654..99cd58f0 100644 --- a/autotests/util/testutil.py +++ b/autotests/util/testutil.py @@ -4,6 +4,7 @@ import socket import fcntl import struct import select +import codecs import iwd from config import ctx @@ -131,6 +132,7 @@ def test_ifaces_connected(if0=None, if1=None, group=True, expect_fail=False): SIOCGIFFLAGS = 0x8913 SIOCGIFADDR = 0x8915 +SIOCGIFNETMASK = 0x891b IFF_UP = 1 << 0 IFF_RUNNING = 1 << 6 @@ -156,19 +158,68 @@ def test_iface_operstate(intf=None): ctx.non_block_wait(_test_operstate, 10, intf, exception=Exception(intf + ' operstate wrong')) -def test_ip_address_match(intf, ip): - try: - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - addr = fcntl.ioctl(s.fileno(), SIOCGIFADDR, struct.pack('256s', intf.encode('utf-8'))) - addr = socket.inet_ntoa(addr[20:24]) - except OSError as e: - if e.errno != 99 or ip != None: - raise Exception('SIOCGIFADDR failed with %d' % e.errno) - - return +def get_addrs6(ifname): + f = open('/proc/net/if_inet6', 'r') + lines = f.readlines() + f.close() + for line in lines: + addr_str, _, plen, _, _, addr_ifname = line.split() + if ifname is not None and addr_ifname != ifname: + continue + + yield (codecs.decode(addr_str, 'hex'), int(plen, 16), addr_ifname) + +def test_ip_address_match(intf, expected_addr_str, expected_plen=None, match_plen=None): + def mask_addr(addr, plen): + if plen is None or len(addr) * 8 <= plen: + return addr + bytelen = int(plen / 8) + return addr[0:bytelen] + bytes([addr[bytelen] & (0xff00 >> (plen & 7))]) + b'\0' * (len(addr) - bytelen - 1) + if expected_addr_str is not None: + try: + expected_addr = socket.inet_pton(socket.AF_INET, expected_addr_str) + family = socket.AF_INET + except OSError as e: + try: + expected_addr = socket.inet_pton(socket.AF_INET6, expected_addr_str) + family = socket.AF_INET6 + except OSError as e2: + raise e2 from None + expected_addr = mask_addr(expected_addr, match_plen) + else: + expected_addr = None + family = socket.AF_INET - if ip != addr: - raise Exception('IP for %s did not match %s (was %s)' % (intf, ip, addr)) + if family == socket.AF_INET: + try: + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + out = fcntl.ioctl(s.fileno(), SIOCGIFADDR, struct.pack('256s', intf.encode('utf-8'))) + actual_addr = mask_addr(out[20:24], match_plen) + out = fcntl.ioctl(s.fileno(), SIOCGIFNETMASK, struct.pack('256s', intf.encode('utf-8'))) + actual_plen = sum([sum([(byte >> bit) & 1 for bit in range(0, 8)]) for byte in out[20:24]]) # count bits + except OSError as e: + if e.errno == 99 and expected_addr is None: + return + + raise Exception('SIOCGIFADDR/SIOCGIFNETMASK failed with %d' % e.errno) + else: + # The "get" ioctls don't work for IPv6, netdevice(7) recommends reading /proc/net instead, + # which on the other hand works *only* for IPv6 + actual_addr = None + actual_plen = None + for addr, plen, _ in get_addrs6(intf): + actual_addr = mask_addr(addr, match_plen) + actual_plen = plen + if actual_addr == expected_addr: + break + + if expected_addr != actual_addr: + raise Exception('IP for %s did not match %s (was %s)' % + (intf, expected_addr_str, socket.inet_ntop(family, actual_addr))) + + if expected_plen is not None and expected_plen != actual_plen: + raise Exception('Prefix Length for %s did not match %i (was %i)' % + (intf, expected_plen, actual_plen)) def test_ip_connected(tup0, tup1): ip0, ns0 = tup0 From patchwork Thu Jun 16 00:02:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12883093 Received: from mail-wm1-f45.google.com (mail-wm1-f45.google.com [209.85.128.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D2649161 for ; Thu, 16 Jun 2022 00:02:49 +0000 (UTC) Received: by mail-wm1-f45.google.com with SMTP id c130-20020a1c3588000000b0039c6fd897b4so1967378wma.4 for ; Wed, 15 Jun 2022 17:02:49 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=2dDbwvFgz76PsafAvHmieGDJCVxo8ZlIG5n+Gj5BMRg=; b=MUv+sXjjZENGkkbEQXEpu5FDx0ss2e3B5BTnqvOpe/MuCs36yIKSZvx4QsCFBQcxy8 9YJ8TyxnK9lwjgGVYQs5sKGfXK40D8q92VtSxiebGiCz9Ms71zn98D8Oy9OcXB/CDS53 JEAkCyZLmL34yefBBTadTm0Qzfb9t/qY17n7FxwzpoAH8cQyWFlEgzx4OXnv9ceX9n/S qHobpJhsgF6SbZkSgv5DIgXVNYzr+qHi+wuHLa5n43eZGhiPR81ZKHcPReBDsP/vyTYt mC5Oy8wqvfLD8TnIaBnpc23+tjbOo1VA7n0RE1iJE/AZe9QqX8MZ0hG46oxYniuedFjb iN6g== X-Gm-Message-State: AOAM532dRf+x7PKwNF4zzkG9ykEBsL0fkDMtMURU24sk8O2yVkzpXKwL gH5tYXLyOfdGGlkUp/Blp1OAPrdb16Y= X-Google-Smtp-Source: ABdhPJzFpQKMpoDQ2lxDUelfUe6xsofXdcjQBye9xG14nHgthHSOVJL5MDME6Q/NlTbcGp4WyAj4dw== X-Received: by 2002:a05:600c:358c:b0:39c:97ed:baa5 with SMTP id p12-20020a05600c358c00b0039c97edbaa5mr12724779wmq.77.1655337767755; Wed, 15 Jun 2022 17:02:47 -0700 (PDT) Received: from iss.Home ([82.213.231.20]) by smtp.gmail.com with ESMTPSA id az10-20020adfe18a000000b00210396b2eaesm337452wrb.45.2022.06.15.17.02.46 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Jun 2022 17:02:47 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 09/15] autotests: Ensure storage_dir exists, clean up Date: Thu, 16 Jun 2022 02:02:25 +0200 Message-Id: <20220616000231.1966008-9-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220616000231.1966008-1-andrew.zaborowski@intel.com> References: <20220616000231.1966008-1-andrew.zaborowski@intel.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In iwd.py make sure all the static methods that touch IWD storage take the storage_dir parameter instead of hardcoding IWD_STORAGE_DIR, and make sure that parameter is actually used. Create the directory if it doesn't exist before copying files into it. This fixes a problem in testNetconfig where `IWD.copy_to_storage('ssidTKIP.psk', '/tmp/storage')` would result in /tmp/storage being created as a file, rather than a directory containing a file, and resulting in IWD failing to start with: `Failed to create /tmp/storage` runner.py creates /tmp/iwd but that doesn't account for IWD sessions with a custom storage dir path. --- autotests/testNetconfig/static_test.py | 2 +- autotests/util/iwd.py | 39 ++++++++++++++++---------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/autotests/testNetconfig/static_test.py b/autotests/testNetconfig/static_test.py index e82dbaeb..8d5710c1 100644 --- a/autotests/testNetconfig/static_test.py +++ b/autotests/testNetconfig/static_test.py @@ -91,7 +91,7 @@ class Test(unittest.TestCase): @classmethod def tearDownClass(cls): - IWD.clear_storage() + IWD.clear_storage(storage_dir='/tmp/storage') cls.dhcpd_pid.kill() if __name__ == '__main__': diff --git a/autotests/util/iwd.py b/autotests/util/iwd.py index 6cee1e07..f609e37e 100755 --- a/autotests/util/iwd.py +++ b/autotests/util/iwd.py @@ -1086,7 +1086,7 @@ class IWD(AsyncOpAbstract): psk_agent = None def __init__(self, start_iwd_daemon = False, iwd_config_dir = '/tmp', - iwd_storage_dir = '/tmp/iwd', namespace=ctx): + iwd_storage_dir = IWD_STORAGE_DIR, namespace=ctx): self.namespace = namespace self._bus = namespace.get_bus() @@ -1197,40 +1197,49 @@ class IWD(AsyncOpAbstract): os.system('rm -rf ' + storage_dir + '/ap/*') @staticmethod - def create_in_storage(file_name, file_content): - fo = open(IWD_STORAGE_DIR + '/' + file_name, 'w') + def create_in_storage(file_name, file_content, storage_dir=IWD_STORAGE_DIR): + fo = open(storage_dir + '/' + file_name, 'w') fo.write(file_content) fo.close() + @staticmethod + def _ensure_storage_dir_exists(storage_dir): + if not os.path.exists(storage_dir): + os.mkdir(storage_dir) + @staticmethod def copy_to_storage(source, storage_dir=IWD_STORAGE_DIR, name=None): import shutil assert not os.path.isabs(source) + target = storage_dir if name: - storage_dir += '/%s' % name + target += '/%s' % name - shutil.copy(source, storage_dir) + IWD._ensure_storage_dir_exists(storage_dir) + shutil.copy(source, target) @staticmethod - def copy_to_hotspot(source): - if not os.path.exists(IWD_STORAGE_DIR + "/hotspot"): - os.mkdir(IWD_STORAGE_DIR + "/hotspot") + def copy_to_hotspot(source, storage_dir=IWD_STORAGE_DIR): + IWD._ensure_storage_dir_exists(storage_dir) + + if not os.path.exists(storage_dir + "/hotspot"): + os.mkdir(storage_dir + "/hotspot") - IWD.copy_to_storage(source, IWD_STORAGE_DIR + "/hotspot") + IWD.copy_to_storage(source, storage_dir + "/hotspot") @staticmethod - def copy_to_ap(source): - if not os.path.exists(IWD_STORAGE_DIR + "/ap"): - os.mkdir(IWD_STORAGE_DIR + "/ap") + def copy_to_ap(source, storage_dir=IWD_STORAGE_DIR): + if not os.path.exists(storage_dir + "/ap"): + os.mkdir(storage_dir + "/ap") - IWD.copy_to_storage(source, IWD_STORAGE_DIR + '/ap/') + IWD.copy_to_storage(source, storage_dir + '/ap/') @staticmethod - def remove_from_storage(file_name): - os.system('rm -rf ' + IWD_STORAGE_DIR + '/\'' + file_name + '\'') + def remove_from_storage(file_name, storage_dir=IWD_STORAGE_DIR): + os.system('rm -rf ' + storage_dir + '/\'' + file_name + '\'') def list_devices(self, wait_to_appear = 0, max_wait = 50, p2p = False): if not wait_to_appear: From patchwork Thu Jun 16 00:02:26 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12883095 Received: from mail-wr1-f41.google.com (mail-wr1-f41.google.com [209.85.221.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3008D161 for ; Thu, 16 Jun 2022 00:02:51 +0000 (UTC) Received: by mail-wr1-f41.google.com with SMTP id o8so17334263wro.3 for ; Wed, 15 Jun 2022 17:02:50 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=O0sR9/tzsW65TSQaduxKmzndHRSeunmPPlcf5mdr3AI=; b=KfEDs+PJfIex2UM9DyaPM9iXAc6LZQCxiIpBEOVBkeYyqAP+k4z49a0N0w5SkFknuD bjemgIFjWBDZnC/C9RYbdJXKXEXJL8w/nqJ5wH6xXu4Lc9f8SWk2Dne5yF3coqA54enS OxpK8NVYMEyFlf9lg5DdGWunkhKJLa12RIcEkks0+RJS+h4DUfi62Eqe+SGwIygbouMM Pl8MvmLknfChwre+13bNNDbCAOyY91Da83H2y+VlNOL6t0uRkNGSV2rejctgRCXPBpvB Wv8bEB+UL4YrQm43/j4IIeTfS6I9nwDMIirBfjOhJSI3veXjYffVIpoQdNevhVTQFLNU dwuw== X-Gm-Message-State: AJIora8pHfm0O3h6/3MhjX5zBYdmReaJYdZRoWMO7Cjujn1QgiLEuf6G sXHxccrle5XZNCr6hlri+s7DUx9XrFo= X-Google-Smtp-Source: AGRyM1v8QXc6s0ZV3058xI1061gzYW1Get+zUEdklN5kJGM9xBvAzniK1ZrBmnB4doBd6aGUoreD7A== X-Received: by 2002:a05:6000:1789:b0:219:2aa8:7159 with SMTP id e9-20020a056000178900b002192aa87159mr2050202wrg.474.1655337769101; Wed, 15 Jun 2022 17:02:49 -0700 (PDT) Received: from iss.Home ([82.213.231.20]) by smtp.gmail.com with ESMTPSA id az10-20020adfe18a000000b00210396b2eaesm337452wrb.45.2022.06.15.17.02.47 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Jun 2022 17:02:48 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 10/15] autotests: In testNetconfig add static IPv6, add comments Date: Thu, 16 Jun 2022 02:02:26 +0200 Message-Id: <20220616000231.1966008-10-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220616000231.1966008-1-andrew.zaborowski@intel.com> References: <20220616000231.1966008-1-andrew.zaborowski@intel.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In static_test.py add IPv6. Add comments on what we're actually testing since it wasn't very clear. After the expected ACD conflict detection, succeed if either the lost address was removed or the client disconnected from the AP since this seems like a correct action for netconfig to implement. --- autotests/testNetconfig/ssidTKIP.psk | 7 +++++++ autotests/testNetconfig/static_test.py | 11 ++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/autotests/testNetconfig/ssidTKIP.psk b/autotests/testNetconfig/ssidTKIP.psk index eea59cda..72a71ce9 100644 --- a/autotests/testNetconfig/ssidTKIP.psk +++ b/autotests/testNetconfig/ssidTKIP.psk @@ -1,7 +1,14 @@ [IPv4] +# Use a different netmask than DHCP on purpose, but use the same address +# as DHCP would assign us to produce a conflict and test ACD Address=192.168.1.10 Netmask=255.255.255.128 Gateway=192.168.1.1 +[IPv6] +# Use a different subnet than DHCP on purpose +Address=3ffe:501:ffff:200::10/80 +Gateway=3ffe:501:ffff:200::1 + [Settings] AutoConnect=false diff --git a/autotests/testNetconfig/static_test.py b/autotests/testNetconfig/static_test.py index 8d5710c1..a3b294a2 100644 --- a/autotests/testNetconfig/static_test.py +++ b/autotests/testNetconfig/static_test.py @@ -16,6 +16,7 @@ import os class Test(unittest.TestCase): def test_connection_success(self): + # Use a non-default storage_dir for one of the instances, the default for the other one wd = IWD(True, iwd_storage_dir='/tmp/storage') ns0 = ctx.get_namespace('ns0') @@ -46,19 +47,27 @@ class Test(unittest.TestCase): testutil.test_ifaces_connected() testutil.test_ip_address_match(dev1.name, '192.168.1.10', 25) + testutil.test_ip_address_match(dev1.name, '3ffe:501:ffff:200::10', 80) ordered_network = dev2.get_ordered_network('ssidTKIP') condition = 'not obj.connected' wd_ns0.wait_for_object_condition(ordered_network.network_object, condition) + # Connect to the same network from a dynamically configured client. The + # DHCP server doesn't know (even though dev1 announced itself) that + # 192.168.1.10 is already in use and if it assigns dev2 the lowest + # available address, that's going to be 192.168.1.10. dev1's ACD + # implementation should then stop using this address. ordered_network.network_object.connect() condition = 'obj.state == DeviceState.connected' wd_ns0.wait_for_object_condition(dev2, condition) wd.wait(1) - testutil.test_ip_address_match(dev1.name, None) + # Check dev1 is now disconnected or without its IPv4 address + if dev1.state == iwd.DeviceState.connected: + testutil.test_ip_address_match(dev1.name, None) dev1.disconnect() dev2.disconnect() From patchwork Thu Jun 16 00:02:27 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12883096 Received: from mail-wm1-f54.google.com (mail-wm1-f54.google.com [209.85.128.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 728CC7E for ; Thu, 16 Jun 2022 00:02:52 +0000 (UTC) Received: by mail-wm1-f54.google.com with SMTP id j5-20020a05600c1c0500b0039c5dbbfa48so1962533wms.5 for ; Wed, 15 Jun 2022 17:02:52 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=6neVS8Y7XadG0t7GyDUY1ZqNEW6EvnmhpKjuIamiTpI=; b=ZSFbIVfra+sFrFbmyi7ot2XAqjj0oXJo5omxbg0XT3reNLaTJPWn+tH2qYmGE66oRh omHRx69RM4SnF9qh/vhS7Za5aShcYUpW/cOdBdo9NpWmIvY0nfkG05M+u4jqWIgvsjYo 69G9G1YYMDcS4KoneWBEHJiuoc55KqDkOSYWEC4+8P8QpzYzTSjD81BVMwYi9QD6pkQA GTjuusxf18Xr/86g160yb+SS0vOwtwWCUYHx2myNRYuY++cxvHqlHy72KWxZ1eerAqge Mkjc+AabVAu8ytcMXorTi1iFeWLGvXmKFezXaIIiMkZ/7B5q0+Ra9XDPQAp0ddVlPBfN 5YyQ== X-Gm-Message-State: AJIora9zgkt3Px8D4PWbD3LKP/0wyG/Bq8/3qKDbidLiNDlQ84tpuCiP R2lM67gFxgYYDYTAvlkjsgOwmbsOhuA= X-Google-Smtp-Source: AGRyM1vuqYb37p+X5VSx0NS3GvC2u+ZPcwWEOQ1f9cbQf3T+5XBg+Zn43FilvShUYo4u6pTz55Dlig== X-Received: by 2002:a05:600c:501f:b0:39d:a3d:e919 with SMTP id n31-20020a05600c501f00b0039d0a3de919mr2018816wmr.132.1655337770166; Wed, 15 Jun 2022 17:02:50 -0700 (PDT) Received: from iss.Home ([82.213.231.20]) by smtp.gmail.com with ESMTPSA id az10-20020adfe18a000000b00210396b2eaesm337452wrb.45.2022.06.15.17.02.49 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Jun 2022 17:02:49 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 11/15] autotests: In testNetconfig verify routes created Date: Thu, 16 Jun 2022 02:02:27 +0200 Message-Id: <20220616000231.1966008-11-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220616000231.1966008-1-andrew.zaborowski@intel.com> References: <20220616000231.1966008-1-andrew.zaborowski@intel.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Check that the right set of routes is being added for IPv4 and IPv6. Chane gateway addresses to differ from the AP or dhcpd addresses. --- autotests/testNetconfig/connection_test.py | 39 +++++++++++++-- autotests/testNetconfig/ssidTKIP.psk | 4 +- autotests/testNetconfig/static_test.py | 23 +++++++++ autotests/util/testutil.py | 57 ++++++++++++++++++++++ 4 files changed, 118 insertions(+), 5 deletions(-) diff --git a/autotests/testNetconfig/connection_test.py b/autotests/testNetconfig/connection_test.py index 0334267b..db3327ef 100644 --- a/autotests/testNetconfig/connection_test.py +++ b/autotests/testNetconfig/connection_test.py @@ -12,7 +12,7 @@ from hostapd import HostapdCLI import testutil from config import ctx import os -import subprocess +import socket class Test(unittest.TestCase): @@ -54,6 +54,29 @@ class Test(unittest.TestCase): ctx.non_block_wait(check_addr, 10, device, exception=Exception("IPv6 address was not set")) + ifname = str(device.name) + router_ll_addr = [addr for addr, _, _ in testutil.get_addrs6(self.hapd.ifname) if addr[0:2] == b'\xfe\x80'][0] + # Since we're in an isolated VM with freshly created interfaces we know any routes + # will have been created by IWD and don't have to allow for pre-existing routes + # in the table. + # Flags: 1=RTF_UP, 2=RTF_GATEWAY + expected_routes4 = { + testutil.RouteInfo(gw=socket.inet_pton(socket.AF_INET, '192.168.1.1'), + flags=3, ifname=ifname), + testutil.RouteInfo(dst=socket.inet_pton(socket.AF_INET, '192.168.0.0'), plen=17, + flags=1, ifname=ifname) + } + expected_routes6 = { + # Default router + testutil.RouteInfo(gw=router_ll_addr, flags=3, ifname=ifname), + # On-link prefix + testutil.RouteInfo(dst=socket.inet_pton(socket.AF_INET6, '3ffe:501:ffff:100::'), plen=72, + flags=1, ifname=ifname), + } + self.maxDiff = None + self.assertEqual(expected_routes4, set(testutil.get_routes4(ifname))) + self.assertEqual(expected_routes6, set(testutil.get_routes6(ifname))) + device.disconnect() condition = 'not obj.connected' @@ -77,6 +100,7 @@ class Test(unittest.TestCase): pass hapd = HostapdCLI() + cls.hapd = hapd # TODO: This could be moved into test-runner itself if other tests ever # require this functionality (p2p, FILS, etc.). Since its simple # enough it can stay here for now. @@ -94,9 +118,18 @@ class Test(unittest.TestCase): '-lf', '/tmp/dhcpd6.leases', hapd.ifname], cleanup=remove_lease6) ctx.start_process(['sysctl', 'net.ipv6.conf.' + hapd.ifname + '.forwarding=1']).wait() - # Tell clients to use DHCPv6 + # Send out Router Advertisements telling clients to use DHCPv6. + # Note trying to send the RAs from the router's global IPv6 address by adding a + # "AdvRASrcAddress { 3ffe:501:ffff:100::1; };" line will fail because the client + # and the router interfaces are in the same namespace and Linux won't allow routes + # with a non-link-local gateway address that is present on another interface in the + # same namespace. config = open('/tmp/radvd.conf', 'w') - config.write('interface ' + hapd.ifname + ' { AdvSendAdvert on; AdvManagedFlag on; };') + config.write('interface ' + hapd.ifname + ''' { + AdvSendAdvert on; + AdvManagedFlag on; + prefix 3ffe:501:ffff:100::/72 { AdvAutonomous off; }; + };''') config.close() cls.radvd_pid = ctx.start_process(['radvd', '-n', '-d5', '-p', '/tmp/radvd.pid', '-C', '/tmp/radvd.conf']) diff --git a/autotests/testNetconfig/ssidTKIP.psk b/autotests/testNetconfig/ssidTKIP.psk index 72a71ce9..e371c97f 100644 --- a/autotests/testNetconfig/ssidTKIP.psk +++ b/autotests/testNetconfig/ssidTKIP.psk @@ -3,12 +3,12 @@ # as DHCP would assign us to produce a conflict and test ACD Address=192.168.1.10 Netmask=255.255.255.128 -Gateway=192.168.1.1 +Gateway=192.168.1.3 [IPv6] # Use a different subnet than DHCP on purpose Address=3ffe:501:ffff:200::10/80 -Gateway=3ffe:501:ffff:200::1 +Gateway=3ffe:501:ffff:200::3 [Settings] AutoConnect=false diff --git a/autotests/testNetconfig/static_test.py b/autotests/testNetconfig/static_test.py index a3b294a2..cd147894 100644 --- a/autotests/testNetconfig/static_test.py +++ b/autotests/testNetconfig/static_test.py @@ -12,6 +12,7 @@ from hostapd import HostapdCLI import testutil from config import ctx import os +import socket class Test(unittest.TestCase): @@ -49,6 +50,28 @@ class Test(unittest.TestCase): testutil.test_ip_address_match(dev1.name, '192.168.1.10', 25) testutil.test_ip_address_match(dev1.name, '3ffe:501:ffff:200::10', 80) + ifname = str(dev1.name) + # Since we're in an isolated VM with freshly created interfaces we know any routes + # will have been created by IWD and don't have to allow for pre-existing routes + # in the table. + # Flags: 1=RTF_UP, 2=RTF_GATEWAY + expected_routes4 = { + testutil.RouteInfo(gw=socket.inet_pton(socket.AF_INET, '192.168.1.3'), + flags=3, ifname=ifname), + testutil.RouteInfo(dst=socket.inet_pton(socket.AF_INET, '192.168.1.0'), plen=25, + flags=1, ifname=ifname) + } + expected_routes6 = { + testutil.RouteInfo(gw=socket.inet_pton(socket.AF_INET6, '3ffe:501:ffff:200::3'), + flags=3, ifname=ifname), + testutil.RouteInfo(dst=socket.inet_pton(socket.AF_INET6, '3ffe:501:ffff:200::'), plen=80, + flags=1, ifname=ifname), + } + + self.maxDiff = None + self.assertEqual(expected_routes4, set(testutil.get_routes4(ifname))) + self.assertEqual(expected_routes6, set(testutil.get_routes6(ifname))) + ordered_network = dev2.get_ordered_network('ssidTKIP') condition = 'not obj.connected' diff --git a/autotests/util/testutil.py b/autotests/util/testutil.py index 99cd58f0..eae4dd89 100644 --- a/autotests/util/testutil.py +++ b/autotests/util/testutil.py @@ -5,6 +5,7 @@ import fcntl import struct import select import codecs +import collections import iwd from config import ctx @@ -230,3 +231,59 @@ def test_ip_connected(tup0, tup1): ns1.start_process(['ping', '-c', '5', '-i', '0.2', ip0], check=True) except: raise Exception('Could not ping between %s and %s' % (ip0, ip1)) + +RouteInfo = collections.namedtuple('RouteInfo', 'dst plen gw flags ifname', + defaults=(None, None, None, 0, '')) + +def get_routes4(ifname=None): + f = open('/proc/net/route', 'r') + lines = f.readlines() + f.close() + for line in lines[1:]: # Skip header line + route_ifname, dst_str, gw_str, flags, ref_cnt, use_cnt, metric, mask_str, \ + mtu = line.strip().split(maxsplit=8) + if ifname is not None and route_ifname != ifname: + continue + + dst = codecs.decode(dst_str, 'hex')[::-1] + mask = int(mask_str, 16) + plen = sum([(mask >> bit) & 1 for bit in range(0, 32)]) # count bits + gw = codecs.decode(gw_str, 'hex')[::-1] + + if dst == b'\0\0\0\0': + dst = None + plen = None + if gw == b'\0\0\0\0': + gw = None + yield RouteInfo(dst, plen, gw, int(flags, 16), route_ifname) + +def get_routes6(ifname=None): + f = open('/proc/net/ipv6_route', 'r') + lines = f.readlines() + f.close() + for line in lines: + dst_str, dst_plen_str, src_str, src_plen_str, gw_str, metric, ref_cnt, \ + use_cnt, flags, route_ifname = line.strip().split(maxsplit=9) + if ifname is not None and route_ifname != ifname: + continue + + dst = codecs.decode(dst_str, 'hex') + plen = int(dst_plen_str, 16) + gw = codecs.decode(gw_str, 'hex') + + if dst[0] == 0xff or dst[:2] == b'\xfe\x80': # Skip link-local and multicast + continue + + # Skip RTN_LOCAL-type routes, we don't need to validate them since they're added by + # the kernel and we can't simply add them to the expected list (the list that we + # validate against) because they're added a short time after an address (due to DAD?) + # and would create race conditions + if int(flags, 16) & (1 << 31): + continue + + if dst == b'\0' * 16: + dst = None + plen = None + if gw == b'\0' * 16: + gw = None + yield RouteInfo(dst, plen, gw, int(flags, 16) & 0xf, route_ifname) From patchwork Thu Jun 16 00:02:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12883097 Received: from mail-wm1-f50.google.com (mail-wm1-f50.google.com [209.85.128.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D278B15A0 for ; Thu, 16 Jun 2022 00:02:53 +0000 (UTC) Received: by mail-wm1-f50.google.com with SMTP id x6-20020a1c7c06000000b003972dfca96cso9538wmc.4 for ; Wed, 15 Jun 2022 17:02:53 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=AkbwY8/c+df1aRVshFiXh8qlXNAD1mDhwJM9TaBejzc=; b=6AdSc2W/5l3HywKZZY6dFm/VnEBWg1QNAEdu/zmpg5srghJyzjDeYscLydGlVUjM0D UtD/tgXOyd4BszTLOljHkzoFImhOj7cWmnggMu86G1KhFjScyl2J/KNsCGdJvh6o4S3h UyRuIEeG0/ce1E28zIydU0U49hGnvwLY9wDD5tXYiI5gELrFdIw0dFYssv1E0jeP58pO sIH6wPB51mPevXK9ccKWW3EORYjewvKH+T7/kPBw7DOq1oeBfXIqybUqgFopKvnda/Dl /EKO6ofyMBPbWim5rfRm6i4D68vakyykGdSKmMpTp8e8T8LT3XkCoAOCH4H3STUiH31f 0HBA== X-Gm-Message-State: AOAM532m1w4oTh99JLtVdUZtzkLBNkm3M/dAp+04Xlz15Y0QvkCQlm9d IrOpx5VFYu4LFH9wviH3xUK6Vkwm5TE= X-Google-Smtp-Source: ABdhPJz7z1RDVCezNOmULzjr5zQG8C6fPSCs++oPdbPpc/9EE/YWQ0Q1cxg55oIa0akMLuSYiZp0Cg== X-Received: by 2002:a05:600c:19d4:b0:39c:7ec6:c7cc with SMTP id u20-20020a05600c19d400b0039c7ec6c7ccmr12503855wmq.141.1655337771669; Wed, 15 Jun 2022 17:02:51 -0700 (PDT) Received: from iss.Home ([82.213.231.20]) by smtp.gmail.com with ESMTPSA id az10-20020adfe18a000000b00210396b2eaesm337452wrb.45.2022.06.15.17.02.50 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Jun 2022 17:02:51 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 12/15] autotests: Verify DNS entries added from DHCP/static Date: Thu, 16 Jun 2022 02:02:28 +0200 Message-Id: <20220616000231.1966008-12-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220616000231.1966008-1-andrew.zaborowski@intel.com> References: <20220616000231.1966008-1-andrew.zaborowski@intel.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add a fake resolvconf executable to verify that the right nameserver addresses were actually committed by iwd. Again use unique nameserver addresses to reduce the possibility that the test succeeds by pure luck. --- autotests/testNetconfig/connection_test.py | 15 ++++++++++++++- autotests/testNetconfig/dhcpd-v6.conf | 2 +- autotests/testNetconfig/dhcpd.conf | 2 +- autotests/testNetconfig/main.conf | 2 +- autotests/testNetconfig/resolvconf | 2 ++ autotests/testNetconfig/ssidTKIP.psk | 2 ++ autotests/testNetconfig/static_test.py | 15 ++++++++++++++- 7 files changed, 35 insertions(+), 5 deletions(-) create mode 100755 autotests/testNetconfig/resolvconf diff --git a/autotests/testNetconfig/connection_test.py b/autotests/testNetconfig/connection_test.py index db3327ef..4b05c745 100644 --- a/autotests/testNetconfig/connection_test.py +++ b/autotests/testNetconfig/connection_test.py @@ -77,6 +77,14 @@ class Test(unittest.TestCase): self.assertEqual(expected_routes4, set(testutil.get_routes4(ifname))) self.assertEqual(expected_routes6, set(testutil.get_routes6(ifname))) + rclog = open('/tmp/resolvconf.log', 'r') + entries = rclog.readlines() + rclog.close() + expected_rclog = ['-a wlan1.dns\n', 'nameserver 192.168.1.2\n', 'nameserver 3ffe:501:ffff:100::2\n'] + # Every real resolvconf -a run overwrites the previous settings. Check the last three lines + # of our log since we care about the end result here. + self.assertEqual(expected_rclog, entries[-3:]) + device.disconnect() condition = 'not obj.connected' @@ -133,6 +141,10 @@ class Test(unittest.TestCase): config.close() cls.radvd_pid = ctx.start_process(['radvd', '-n', '-d5', '-p', '/tmp/radvd.pid', '-C', '/tmp/radvd.conf']) + cls.orig_path = os.environ['PATH'] + os.environ['PATH'] = '/tmp/test-bin:' + os.environ['PATH'] + IWD.copy_to_storage('resolvconf', '/tmp/test-bin') + @classmethod def tearDownClass(cls): IWD.clear_storage() @@ -142,7 +154,8 @@ class Test(unittest.TestCase): cls.dhcpd6_pid = None ctx.stop_process(cls.radvd_pid) cls.radvd_pid = None - os.remove('/tmp/radvd.conf') + os.system('rm -rf /tmp/radvd.conf /tmp/resolvconf.log /tmp/test-bin') + os.environ['PATH'] = cls.orig_path if __name__ == '__main__': unittest.main(exit=True) diff --git a/autotests/testNetconfig/dhcpd-v6.conf b/autotests/testNetconfig/dhcpd-v6.conf index 917ee8a3..45057ab8 100644 --- a/autotests/testNetconfig/dhcpd-v6.conf +++ b/autotests/testNetconfig/dhcpd-v6.conf @@ -1,6 +1,6 @@ subnet6 3ffe:501:ffff:100::/72 { - option dhcp6.name-servers 3ffe:501:ffff:100::1; + option dhcp6.name-servers 3ffe:501:ffff:100::2; range6 3ffe:501:ffff:100::10 3ffe:501:ffff:100::20; range6 3ffe:501:ffff:100::100 3ffe:501:ffff:100::200; } diff --git a/autotests/testNetconfig/dhcpd.conf b/autotests/testNetconfig/dhcpd.conf index ea9957a3..d8a9d24c 100644 --- a/autotests/testNetconfig/dhcpd.conf +++ b/autotests/testNetconfig/dhcpd.conf @@ -9,7 +9,7 @@ subnet 192.168.0.0 netmask 255.255.128.0 { option routers 192.168.1.1; option subnet-mask 255.255.128.0; - option domain-name-servers 192.168.1.1; + option domain-name-servers 192.168.1.2; range 192.168.1.10 192.168.1.20; range 192.168.1.100 192.168.1.200; } diff --git a/autotests/testNetconfig/main.conf b/autotests/testNetconfig/main.conf index 1ffe2be1..8641a390 100644 --- a/autotests/testNetconfig/main.conf +++ b/autotests/testNetconfig/main.conf @@ -3,4 +3,4 @@ EnableNetworkConfiguration=true [Network] EnableIPv6=true -NameResolvingService=none +NameResolvingService=resolvconf diff --git a/autotests/testNetconfig/resolvconf b/autotests/testNetconfig/resolvconf new file mode 100755 index 00000000..7c56c616 --- /dev/null +++ b/autotests/testNetconfig/resolvconf @@ -0,0 +1,2 @@ +#! /bin/sh +(echo "$*" ; [ "$1" = -a ] && cat) >> /tmp/resolvconf.log 2> /dev/null diff --git a/autotests/testNetconfig/ssidTKIP.psk b/autotests/testNetconfig/ssidTKIP.psk index e371c97f..032e2185 100644 --- a/autotests/testNetconfig/ssidTKIP.psk +++ b/autotests/testNetconfig/ssidTKIP.psk @@ -4,11 +4,13 @@ Address=192.168.1.10 Netmask=255.255.255.128 Gateway=192.168.1.3 +DNS=192.168.1.4 [IPv6] # Use a different subnet than DHCP on purpose Address=3ffe:501:ffff:200::10/80 Gateway=3ffe:501:ffff:200::3 +DNS=3ffe:501:ffff:200::4 [Settings] AutoConnect=false diff --git a/autotests/testNetconfig/static_test.py b/autotests/testNetconfig/static_test.py index cd147894..ac525b28 100644 --- a/autotests/testNetconfig/static_test.py +++ b/autotests/testNetconfig/static_test.py @@ -72,6 +72,14 @@ class Test(unittest.TestCase): self.assertEqual(expected_routes4, set(testutil.get_routes4(ifname))) self.assertEqual(expected_routes6, set(testutil.get_routes6(ifname))) + rclog = open('/tmp/resolvconf.log', 'r') + entries = rclog.readlines() + rclog.close() + expected_rclog = ['-a wlan1.dns\n', 'nameserver 192.168.1.4\n', 'nameserver 3ffe:501:ffff:200::4\n'] + # Every resolvconf -a run overwrites the previous settings. Check the last three lines + # of the log since we care about the end result here. + self.assertEqual(expected_rclog, entries[-3:]) + ordered_network = dev2.get_ordered_network('ssidTKIP') condition = 'not obj.connected' @@ -121,10 +129,15 @@ class Test(unittest.TestCase): hapd.ifname], cleanup=remove_lease) IWD.copy_to_storage('ssidTKIP.psk', '/tmp/storage') + cls.orig_path = os.environ['PATH'] + os.environ['PATH'] = '/tmp/test-bin:' + os.environ['PATH'] + IWD.copy_to_storage('resolvconf', '/tmp/test-bin') + @classmethod def tearDownClass(cls): - IWD.clear_storage(storage_dir='/tmp/storage') cls.dhcpd_pid.kill() + os.system('rm -rf /tmp/resolvconf.log /tmp/test-bin /tmp/storage') + os.environ['PATH'] = cls.orig_path if __name__ == '__main__': unittest.main(exit=True) From patchwork Thu Jun 16 00:02:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12883100 Received: from mail-wm1-f41.google.com (mail-wm1-f41.google.com [209.85.128.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8AE01161 for ; Thu, 16 Jun 2022 00:02:56 +0000 (UTC) Received: by mail-wm1-f41.google.com with SMTP id a10so7097897wmj.5 for ; Wed, 15 Jun 2022 17:02:56 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=/8r9dezGYyqj74cqcr8GcjkrEdTFkwLFlSbbMvDgRZc=; b=xOvlwx2QgalwvW5GjRx+wQf2aMGS9B5eZ6vhP+5jr+yeouhppz/oBuHChixjDwUkC7 DIx7giUzBns98aOSADtrs2hhEQ/8znTEH/IQZaDq40Wt/63knbGOUF6/EqsJLlZPmlLr VSApQkcSJvDWcFb4hk7IR/qkxhTvY7PhzcH5XdYzZaw5BRVLuY9QfaZwUgyA+wRucMxH oQbssODMJONt+R4+CcqEM0Lz8tCr/JkPlTHTOGrGua4zB/ZX5UsQ4pJ93MFyBYeqWeFA j2Rx+0DBuxHuPyDjF/CtDMho1XF1AwEXqxHuK+j99hhoZSvZRUOM4wB8/s2Eog14ubtX eyUQ== X-Gm-Message-State: AJIora93fLniZeiDoyidndvjCq6zIvt32CGG7bUKQ9u+K/e/4f0Oa2Yf ozY6V6lv4M28+Ujv0Z8tE4vRUG1tbJM= X-Google-Smtp-Source: AGRyM1v33uCvnW/Ny0pEf7goXigS+6DyzrYx6+PJBCnnyOSyVUcmtEpzncXi1NLURmZbDRzdYF4yLw== X-Received: by 2002:a05:600c:3ba8:b0:39c:5bba:5406 with SMTP id n40-20020a05600c3ba800b0039c5bba5406mr1986136wms.120.1655337773161; Wed, 15 Jun 2022 17:02:53 -0700 (PDT) Received: from iss.Home ([82.213.231.20]) by smtp.gmail.com with ESMTPSA id az10-20020adfe18a000000b00210396b2eaesm337452wrb.45.2022.06.15.17.02.51 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Jun 2022 17:02:52 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 13/15][RFC] netconfig: Switch to l_netconfig Date: Thu, 16 Jun 2022 02:02:29 +0200 Message-Id: <20220616000231.1966008-13-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220616000231.1966008-1-andrew.zaborowski@intel.com> References: <20220616000231.1966008-1-andrew.zaborowski@intel.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Posting this for early review only. This leaves IWD's netconfig.h mostly unchanged but the implementation is switched over to use l_netconfig. The struct netconfig declaration is nearly empty now but contains the resolver client, the data received from FILS and some state that mirrors l_netconfig state and could be replaced by using l_netconfig getters for the settings which have only setters at this time. A minor behaviour change is that a netconfig failure, such as DHCP error or timeout, would now cause station to signal an DBus error and continue with autoconnect instead of being stuck in netconfig. --- Makefile.am | 6 +- src/netconfig.c | 1685 +++++++++++------------------------------------ src/netconfig.h | 1 + src/station.c | 134 ++-- 4 files changed, 497 insertions(+), 1329 deletions(-) diff --git a/Makefile.am b/Makefile.am index 80377613..bcb313d7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -62,7 +62,8 @@ ell_headers = ell/util.h \ ell/icmp6.h \ ell/dhcp6.h \ ell/acd.h \ - ell/cleanup.h + ell/cleanup.h \ + ell/netconfig.h ell_sources = ell/private.h \ ell/missing.h \ @@ -141,7 +142,8 @@ ell_sources = ell/private.h \ ell/icmp6-private.h \ ell/dhcp6-lease.c \ ell/dhcp6-transport.c \ - ell/acd.c + ell/acd.c \ + ell/netconfig.c ell_shared = ell/useful.h ell/asn1-private.h diff --git a/src/netconfig.c b/src/netconfig.c index 4a70b0ca..2f41b79f 100644 --- a/src/netconfig.c +++ b/src/netconfig.c @@ -53,23 +53,16 @@ #include "src/sysfs.h" struct netconfig { - uint32_t ifindex; - struct l_dhcp_client *dhcp_client; - struct l_dhcp6_client *dhcp6_client; - uint8_t rtm_protocol; - uint8_t rtm_v6_protocol; - struct l_rtnl_address *v4_address; - struct l_rtnl_address *v6_address; - char **dns4_overrides; - char **dns6_overrides; - char **dns4_list; - char **dns6_list; + struct l_netconfig *nc; + struct netdev *netdev; + char *mdns; struct ie_fils_ip_addr_response_info *fils_override; - char *v4_gateway_str; - char *v6_gateway_str; - char *v4_domain; - char **v6_domains; + bool enabled[2]; + bool static_config[2]; + bool gateway_overridden[2]; + bool dns_overridden[2]; + bool connected[2]; const struct l_settings *active_settings; @@ -77,17 +70,12 @@ struct netconfig { void *user_data; struct resolve *resolve; - - struct l_acd *acd; - - uint32_t addr4_add_cmd_id; - uint32_t addr6_add_cmd_id; - uint32_t route4_add_gateway_cmd_id; - uint32_t route6_add_cmd_id; }; +/* 0 for AF_INET, 1 for AF_INET6 */ +#define INDEX_FOR_AF(af) ((af) != AF_INET) + static struct l_netlink *rtnl; -static struct l_queue *netconfig_list; /* * Routing priority offset, configurable in main.conf. The route with lower @@ -105,172 +93,65 @@ static void do_debug(const char *str, void *user_data) static void netconfig_free_settings(struct netconfig *netconfig) { - l_rtnl_address_free(netconfig->v4_address); - netconfig->v4_address = NULL; - l_rtnl_address_free(netconfig->v6_address); - netconfig->v6_address = NULL; - - l_strfreev(netconfig->dns4_overrides); - netconfig->dns4_overrides = NULL; - l_strfreev(netconfig->dns6_overrides); - netconfig->dns6_overrides = NULL; + netconfig->enabled[0] = true; + netconfig->enabled[1] = false; + netconfig->static_config[0] = false; + netconfig->static_config[1] = false; + netconfig->gateway_overridden[0] = false; + netconfig->gateway_overridden[1] = false; + netconfig->dns_overridden[0] = false; + netconfig->dns_overridden[1] = false; + l_netconfig_reset_config(netconfig->nc); l_free(netconfig->mdns); netconfig->mdns = NULL; + + l_free(l_steal_ptr(netconfig->fils_override)); } static void netconfig_free(void *data) { struct netconfig *netconfig = data; - l_dhcp_client_destroy(netconfig->dhcp_client); - l_dhcp6_client_destroy(netconfig->dhcp6_client); - + l_netconfig_destroy(netconfig->nc); l_free(netconfig); } -static struct netconfig *netconfig_find(uint32_t ifindex) -{ - const struct l_queue_entry *entry; - - for (entry = l_queue_get_entries(netconfig_list); entry; - entry = entry->next) { - struct netconfig *netconfig = entry->data; - - if (netconfig->ifindex != ifindex) - continue; - - return netconfig; - } - - return NULL; -} - -static inline char *netconfig_ipv4_to_string(uint32_t addr) +static bool netconfig_addr_to_str(uint8_t af, const void *v4_addr, + const void *v6_addr, char *out_str, + bool *out_is_zero) { - struct in_addr in_addr = { .s_addr = addr }; - char *addr_str = l_malloc(INET_ADDRSTRLEN); + const void *addr = (af == AF_INET ? v4_addr : v6_addr); + uint8_t bytes = (af == AF_INET ? 4 : 16); - if (L_WARN_ON(unlikely(!inet_ntop(AF_INET, &in_addr, addr_str, - INET_ADDRSTRLEN)))) { - l_free(addr_str); - return NULL; + if (l_memeqzero(addr, bytes)) { + *out_is_zero = true; + return true; } - return addr_str; -} - -static inline char *netconfig_ipv6_to_string(const uint8_t *addr) -{ - struct in6_addr in6_addr; - char *addr_str = l_malloc(INET6_ADDRSTRLEN); - - memcpy(in6_addr.s6_addr, addr, 16); + *out_is_zero = false; - if (L_WARN_ON(unlikely(!inet_ntop(AF_INET6, &in6_addr, addr_str, - INET6_ADDRSTRLEN)))) { - l_free(addr_str); - return NULL; - } + if (L_WARN_ON(!inet_ntop(af, addr, out_str, INET6_ADDRSTRLEN))) + return false; - return addr_str; + return true; } static bool netconfig_use_fils_addr(struct netconfig *netconfig, int af) { - if ((af == AF_INET ? netconfig->rtm_protocol : - netconfig->rtm_v6_protocol) != RTPROT_DHCP) + if (!netconfig->enabled[INDEX_FOR_AF(af)]) return false; - if (!netconfig->fils_override) - return false; - - if (af == AF_INET) - return !!netconfig->fils_override->ipv4_addr; - - return !l_memeqzero(netconfig->fils_override->ipv6_addr, 16); -} - -static bool netconfig_use_fils_gateway(struct netconfig *netconfig, int af) -{ - if ((af == AF_INET ? netconfig->rtm_protocol : - netconfig->rtm_v6_protocol) != RTPROT_DHCP) + if (netconfig->static_config[INDEX_FOR_AF(af)]) return false; if (!netconfig->fils_override) return false; if (af == AF_INET) - return !!netconfig->fils_override->ipv4_gateway; - - return !l_memeqzero(netconfig->fils_override->ipv6_gateway, 16); -} - -static char **netconfig_get_dns_list(struct netconfig *netconfig, int af, - const uint8_t **out_dns_mac) -{ - const struct ie_fils_ip_addr_response_info *fils = - netconfig->fils_override; - - if (af == AF_INET) { - const struct l_dhcp_lease *lease; - - if (netconfig->dns4_overrides) - return l_strv_copy(netconfig->dns4_overrides); - - if (netconfig->rtm_protocol != RTPROT_DHCP) - return NULL; - - if (fils && fils->ipv4_dns) { - char **dns_list = l_new(char *, 2); - - if (!l_memeqzero(fils->ipv4_dns_mac, 6) && - out_dns_mac && - util_ip_subnet_match( - fils->ipv4_prefix_len, - &fils->ipv4_addr, - &fils->ipv4_dns)) - *out_dns_mac = fils->ipv4_dns_mac; - - dns_list[0] = netconfig_ipv4_to_string(fils->ipv4_dns); - return dns_list; - } - - lease = l_dhcp_client_get_lease(netconfig->dhcp_client); - if (!lease) - return NULL; - - return l_dhcp_lease_get_dns(lease); - } else { - const struct l_dhcp6_lease *lease; - - if (netconfig->dns6_overrides) - return l_strv_copy(netconfig->dns6_overrides); - - if (netconfig->rtm_v6_protocol != RTPROT_DHCP) - return NULL; - - if (fils && !l_memeqzero(fils->ipv6_dns, 16)) { - char **dns_list = l_new(char *, 2); - - if (!l_memeqzero(fils->ipv6_dns_mac, 6) && - out_dns_mac && - util_ip_subnet_match( - fils->ipv6_prefix_len, - fils->ipv6_addr, - fils->ipv6_dns)) - *out_dns_mac = fils->ipv6_dns_mac; - - dns_list[0] = netconfig_ipv6_to_string(fils->ipv6_dns); - return dns_list; - } - - lease = l_dhcp6_client_get_lease(netconfig->dhcp6_client); - if (!lease) - return NULL; + return !!netconfig->fils_override->ipv4_addr; - return l_dhcp6_lease_get_dns(lease); - } + return !l_memeqzero(netconfig->fils_override->ipv6_addr, 16); } static void netconfig_set_neighbor_entry_cb(int error, @@ -282,150 +163,28 @@ static void netconfig_set_neighbor_entry_cb(int error, strerror(-error), error); } -static void netconfig_set_dns(struct netconfig *netconfig) +static void netconfig_dns_list_update(struct netconfig *netconfig) { - if (!netconfig->dns4_list && !netconfig->dns6_list) - return; - - if (netconfig->dns4_list && netconfig->dns6_list) { - unsigned int n_entries4 = l_strv_length(netconfig->dns4_list); - unsigned int n_entries6 = l_strv_length(netconfig->dns6_list); - char **dns_list = l_malloc(sizeof(char *) * - (n_entries4 + n_entries6 + 1)); + _auto_(l_strv_free) char **dns_list = + l_netconfig_get_dns_list(netconfig->nc); - memcpy(dns_list, netconfig->dns4_list, - sizeof(char *) * n_entries4); - memcpy(dns_list + n_entries4, netconfig->dns6_list, - sizeof(char *) * (n_entries6 + 1)); + if (netconfig->resolve && dns_list) resolve_set_dns(netconfig->resolve, dns_list); - l_free(dns_list); - return; - } - - resolve_set_dns(netconfig->resolve, - netconfig->dns4_list ?: netconfig->dns6_list); -} - -static bool netconfig_dns_list_update(struct netconfig *netconfig, uint8_t af) -{ - const uint8_t *fils_dns_mac = NULL; - char ***dns_list_ptr = af == AF_INET ? - &netconfig->dns4_list : &netconfig->dns6_list; - char **new_dns_list = netconfig_get_dns_list(netconfig, af, - &fils_dns_mac); - - if (l_strv_eq(*dns_list_ptr, new_dns_list)) { - l_strv_free(new_dns_list); - return false; - } - - l_strv_free(*dns_list_ptr); - *dns_list_ptr = new_dns_list; - - if (fils_dns_mac) { - const struct ie_fils_ip_addr_response_info *fils = - netconfig->fils_override; - const void *dns_ip = af == AF_INET ? - (const void *) &fils->ipv4_dns : - (const void *) &fils->ipv6_dns; - - if (!l_rtnl_neighbor_set_hwaddr(rtnl, netconfig->ifindex, af, - dns_ip, fils_dns_mac, 6, - netconfig_set_neighbor_entry_cb, - NULL, NULL)) - l_debug("l_rtnl_neighbor_set_hwaddr failed"); - } - - return true; } -static void append_domain(char **domains, unsigned int *n_domains, - size_t max, char *domain) +static void netconfig_domains_update(struct netconfig *netconfig) { - unsigned int i; + _auto_(l_strv_free) char **domains = + l_netconfig_get_domain_names(netconfig->nc); - if (*n_domains == max) - return; - - for (i = 0; i < *n_domains; i++) - if (!strcmp(domains[i], domain)) - return; - - domains[*n_domains] = domain; - *n_domains += 1; -} - -static void netconfig_set_domains(struct netconfig *netconfig) -{ - char *domains[31]; - unsigned int n_domains = 0; - char **p; - - memset(domains, 0, sizeof(domains)); - - append_domain(domains, &n_domains, - L_ARRAY_SIZE(domains) - 1, netconfig->v4_domain); - - for (p = netconfig->v6_domains; p && *p; p++) - append_domain(domains, &n_domains, - L_ARRAY_SIZE(domains) - 1, *p); - - resolve_set_domains(netconfig->resolve, domains); -} - -static bool netconfig_domains_update(struct netconfig *netconfig, uint8_t af) -{ - bool changed = false; - - if (af == AF_INET) { - /* Allow to override the DHCP domain name with setting entry. */ - char *v4_domain = l_settings_get_string( - netconfig->active_settings, - "IPv4", "DomainName"); - - if (!v4_domain && netconfig->rtm_protocol == RTPROT_DHCP) { - const struct l_dhcp_lease *lease = - l_dhcp_client_get_lease(netconfig->dhcp_client); - - if (lease) - v4_domain = l_dhcp_lease_get_domain_name(lease); - } - - if (l_streq0(v4_domain, netconfig->v4_domain)) - l_free(v4_domain); - else { - l_free(netconfig->v4_domain); - netconfig->v4_domain = v4_domain; - changed = true; - } - } else { - char **v6_domains = NULL; - - if (netconfig->rtm_v6_protocol == RTPROT_DHCP) { - const struct l_dhcp6_lease *lease = - l_dhcp6_client_get_lease( - netconfig->dhcp6_client); - - if (lease) - v6_domains = l_dhcp6_lease_get_domains(lease); - } - - if (l_strv_eq(netconfig->v6_domains, v6_domains)) - l_strv_free(v6_domains); - else { - l_strv_free(netconfig->v6_domains); - netconfig->v6_domains = v6_domains; - changed = true; - } - } - - return changed; + if (netconfig->resolve && domains) + resolve_set_domains(netconfig->resolve, domains); } static struct l_rtnl_address *netconfig_get_static4_address( const struct l_settings *active_settings) { - struct l_rtnl_address *ifaddr = NULL; + _auto_(l_rtnl_address_free) struct l_rtnl_address *ifaddr = NULL; L_AUTO_FREE_VAR(char *, ip) = NULL; L_AUTO_FREE_VAR(char *, netmask) = NULL; struct in_addr in_addr; @@ -433,13 +192,22 @@ static struct l_rtnl_address *netconfig_get_static4_address( uint32_t prefix_len; ip = l_settings_get_string(active_settings, "IPv4", "Address"); - if (!ip) + if (unlikely(!ip)) { + l_error("netconfig: Can't load IPv4.Address"); + return NULL; + } + + if (l_settings_has_key(active_settings, "IPv4", "Netmask") && + !(netmask = l_settings_get_string(active_settings, + "IPv4", + "Netmask"))) { + l_error("netconfig: Can't load IPv4.Netmask"); return NULL; + } - netmask = l_settings_get_string(active_settings, "IPv4", "Netmask"); if (netmask) { if (inet_pton(AF_INET, netmask, &in_addr) != 1) { - l_error("netconfig: Can't parse IPv4 Netmask"); + l_error("netconfig: Can't parse IPv4.Netmask"); return NULL; } @@ -447,14 +215,14 @@ static struct l_rtnl_address *netconfig_get_static4_address( if (ntohl(in_addr.s_addr) != util_netmask_from_prefix(prefix_len)) { - l_error("netconfig: Invalid IPv4 Netmask"); + l_error("netconfig: Invalid IPv4.Netmask"); return NULL; } } else prefix_len = 24; ifaddr = l_rtnl_address_new(ip, prefix_len); - if (!ifaddr) { + if (!ifaddr || l_rtnl_address_get_family(ifaddr) != AF_INET) { l_error("netconfig: Unable to parse IPv4.Address"); return NULL; } @@ -462,52 +230,10 @@ static struct l_rtnl_address *netconfig_get_static4_address( broadcast = l_settings_get_string(active_settings, "IPv4", "Broadcast"); if (broadcast && !l_rtnl_address_set_broadcast(ifaddr, broadcast)) { l_error("netconfig: Unable to parse IPv4.Broadcast"); - l_rtnl_address_free(ifaddr); return NULL; } - l_rtnl_address_set_noprefixroute(ifaddr, true); - return ifaddr; -} - -static char *netconfig_ipv4_get_gateway(struct netconfig *netconfig, - const uint8_t **out_mac) -{ - const struct l_dhcp_lease *lease; - char *gateway; - const struct ie_fils_ip_addr_response_info *fils = - netconfig->fils_override; - - switch (netconfig->rtm_protocol) { - case RTPROT_STATIC: - gateway = l_settings_get_string(netconfig->active_settings, - "IPv4", "Gateway"); - if (!gateway) - gateway = l_settings_get_string( - netconfig->active_settings, - "IPv4", "gateway"); - - return gateway; - - case RTPROT_DHCP: - if (netconfig_use_fils_gateway(netconfig, AF_INET)) { - gateway = netconfig_ipv4_to_string(fils->ipv4_gateway); - - if (gateway && out_mac && - !l_memeqzero(fils->ipv4_gateway_mac, 6)) - *out_mac = fils->ipv4_gateway_mac; - - return gateway; - } - - lease = l_dhcp_client_get_lease(netconfig->dhcp_client); - if (!lease) - return NULL; - - return l_dhcp_lease_get_gateway(lease); - } - - return NULL; + return l_steal_ptr(ifaddr); } static struct l_rtnl_address *netconfig_get_static6_address( @@ -516,12 +242,14 @@ static struct l_rtnl_address *netconfig_get_static6_address( L_AUTO_FREE_VAR(char *, ip); char *p; char *endp; - struct l_rtnl_address *ret; - uint32_t prefix_len = 128; + _auto_(l_rtnl_address_free) struct l_rtnl_address *ret = NULL; + uint32_t prefix_len = 64; ip = l_settings_get_string(active_settings, "IPv6", "Address"); - if (!ip) + if (unlikely(!ip)) { + l_error("netconfig: Can't load IPv6.Address"); return NULL; + } p = strrchr(ip, '/'); if (!p) @@ -535,100 +263,38 @@ static struct l_rtnl_address *netconfig_get_static6_address( prefix_len = strtoul(p, &endp, 10); if (unlikely(*endp != '\0' || errno || !prefix_len || prefix_len > 128)) { - l_error("netconfig: Invalid prefix '%s' provided in network" - " configuration file", p); + l_error("netconfig: Invalid prefix '%s' is provided in network" + " configuration file", p); return NULL; } no_prefix_len: ret = l_rtnl_address_new(ip, prefix_len); - if (!ret) - l_error("netconfig: Invalid IPv6 address %s is " - "provided in network configuration file.", ip); - - return ret; -} - -static struct l_rtnl_route *netconfig_get_static6_gateway( - struct netconfig *netconfig, - char **out_str, - const uint8_t **out_mac) -{ - L_AUTO_FREE_VAR(char *, gateway); - struct l_rtnl_route *ret; - const uint8_t *mac = NULL; - - gateway = l_settings_get_string(netconfig->active_settings, - "IPv6", "Gateway"); - if (!gateway && netconfig_use_fils_gateway(netconfig, AF_INET6)) { - gateway = netconfig_ipv6_to_string( - netconfig->fils_override->ipv6_gateway); - - if (!l_memeqzero(netconfig->fils_override->ipv6_gateway_mac, 6)) - mac = netconfig->fils_override->ipv6_gateway_mac; - } else if (!gateway) + if (!ret || l_rtnl_address_get_family(ret) != AF_INET6) { + l_error("netconfig: Invalid IPv6 address %s is provided in " + "network configuration file.", ip); return NULL; - - ret = l_rtnl_route_new_gateway(gateway); - if (!ret) { - l_error("netconfig: Invalid IPv6 gateway address %s is " - "provided in network configuration file.", - gateway); - return ret; } - l_rtnl_route_set_priority(ret, ROUTE_PRIORITY_OFFSET); - l_rtnl_route_set_protocol(ret, RTPROT_STATIC); - *out_str = l_steal_ptr(gateway); - *out_mac = mac; - - return ret; + return l_steal_ptr(ret); } -static struct l_rtnl_address *netconfig_get_dhcp4_address( - struct netconfig *netconfig) -{ - const struct l_dhcp_lease *lease = - l_dhcp_client_get_lease(netconfig->dhcp_client); - L_AUTO_FREE_VAR(char *, ip) = NULL; - L_AUTO_FREE_VAR(char *, broadcast) = NULL; - uint32_t prefix_len; - struct l_rtnl_address *ret; - - if (L_WARN_ON(!lease)) - return NULL; - - ip = l_dhcp_lease_get_address(lease); - broadcast = l_dhcp_lease_get_broadcast(lease); - - prefix_len = l_dhcp_lease_get_prefix_length(lease); - if (!prefix_len) - prefix_len = 24; - - ret = l_rtnl_address_new(ip, prefix_len); - if (!ret) - return ret; - - if (broadcast) - l_rtnl_address_set_broadcast(ret, broadcast); - - l_rtnl_address_set_noprefixroute(ret, true); - return ret; -} - -static void netconfig_gateway_to_arp(struct netconfig *netconfig) +static void netconfig_dhcp_gateway_to_arp(struct netconfig *netconfig) { + struct l_dhcp_client *dhcp = l_netconfig_get_dhcp_client(netconfig->nc); const struct l_dhcp_lease *lease; _auto_(l_free) char *server_id = NULL; _auto_(l_free) char *gw = NULL; const uint8_t *server_mac; struct in_addr in_gw; + uint32_t ifindex = netdev_get_ifindex(netconfig->netdev); /* Can only do this for DHCP in certain network setups */ - if (netconfig->rtm_protocol != RTPROT_DHCP) + if (netconfig->static_config[INDEX_FOR_AF(AF_INET)] || + netconfig->fils_override) return; - lease = l_dhcp_client_get_lease(netconfig->dhcp_client); + lease = l_dhcp_client_get_lease(dhcp); if (!lease) return; @@ -642,844 +308,379 @@ static void netconfig_gateway_to_arp(struct netconfig *netconfig) l_debug("Gateway MAC is known, setting into ARP cache"); in_gw.s_addr = l_dhcp_lease_get_gateway_u32(lease); - if (!l_rtnl_neighbor_set_hwaddr(rtnl, netconfig->ifindex, AF_INET, + if (!l_rtnl_neighbor_set_hwaddr(rtnl, ifindex, AF_INET, &in_gw, server_mac, ETH_ALEN, netconfig_set_neighbor_entry_cb, NULL, NULL)) l_debug("l_rtnl_neighbor_set_hwaddr failed"); } -static void netconfig_ifaddr_added(struct netconfig *netconfig, - const struct ifaddrmsg *ifa, - uint32_t len) -{ - L_AUTO_FREE_VAR(char *, label) = NULL; - L_AUTO_FREE_VAR(char *, ip) = NULL; - L_AUTO_FREE_VAR(char *, broadcast) = NULL; - - l_rtnl_ifaddr4_extract(ifa, len, &label, &ip, &broadcast); - l_debug("%s: ifaddr %s/%u broadcast %s", label, - ip, ifa->ifa_prefixlen, broadcast); -} - -static void netconfig_ifaddr_deleted(struct netconfig *netconfig, - const struct ifaddrmsg *ifa, - uint32_t len) -{ - L_AUTO_FREE_VAR(char *, ip); - - l_rtnl_ifaddr4_extract(ifa, len, NULL, &ip, NULL); - l_debug("ifaddr %s/%u", ip, ifa->ifa_prefixlen); -} - -static void netconfig_ifaddr_notify(uint16_t type, const void *data, - uint32_t len, void *user_data) +static void netconfig_commit_fils_macs(struct netconfig *netconfig, uint8_t af) { - const struct ifaddrmsg *ifa = data; - struct netconfig *netconfig; - uint32_t bytes; + const struct ie_fils_ip_addr_response_info *fils = + netconfig->fils_override; + const void *addr; + const void *hwaddr; + size_t addr_len = (af == AF_INET ? 4 : 16); + uint32_t ifindex = netdev_get_ifindex(netconfig->netdev); - netconfig = netconfig_find(ifa->ifa_index); - if (!netconfig) - /* Ignore the interfaces which aren't managed by iwd. */ + if (!fils) return; - bytes = len - NLMSG_ALIGN(sizeof(struct ifaddrmsg)); + /* + * Attempt to use the gateway/DNS MAC addressed received from the AP + * by writing the mapping directly into the netdev's ARP table so as + * to save one data frame roundtrip before first IP connections are + * established. This is very low-priority but print error messages + * just because they may indicate bigger problems. + */ - switch (type) { - case RTM_NEWADDR: - netconfig_ifaddr_added(netconfig, ifa, bytes); - break; - case RTM_DELADDR: - netconfig_ifaddr_deleted(netconfig, ifa, bytes); - break; - } -} + addr = (af == AF_INET ? (void *) &fils->ipv4_gateway : + (void *) &fils->ipv6_gateway); + hwaddr = (af == AF_INET ? + &fils->ipv4_gateway_mac : &fils->ipv6_gateway_mac); -static void netconfig_ifaddr_cmd_cb(int error, uint16_t type, - const void *data, uint32_t len, - void *user_data) -{ - if (error) { - l_error("netconfig: ifaddr command failure. " - "Error %d: %s", error, strerror(-error)); - return; - } + if (!l_memeqzero(addr, addr_len) && !l_memeqzero(hwaddr, ETH_ALEN) && + unlikely(!l_rtnl_neighbor_set_hwaddr(rtnl, ifindex, af, + addr, hwaddr, ETH_ALEN, + netconfig_set_neighbor_entry_cb, + NULL, NULL))) + l_debug("l_rtnl_neighbor_set_hwaddr(%s, gateway) failed", + af == AF_INET ? "AF_INET" : "AF_INET6"); - if (type != RTM_NEWADDR) - return; + addr = (af == AF_INET ? (void *) &fils->ipv4_dns : + (void *) &fils->ipv6_dns); + hwaddr = (af == AF_INET ? &fils->ipv4_dns_mac : &fils->ipv6_dns_mac); - netconfig_ifaddr_notify(type, data, len, user_data); + if (!l_memeqzero(addr, addr_len) && !l_memeqzero(hwaddr, ETH_ALEN) && + unlikely(!l_rtnl_neighbor_set_hwaddr(rtnl, ifindex, af, + addr, hwaddr, ETH_ALEN, + netconfig_set_neighbor_entry_cb, + NULL, NULL))) + l_debug("l_rtnl_neighbor_set_hwaddr(%s, DNS) failed", + af == AF_INET ? "AF_INET" : "AF_INET6"); } -static void netconfig_ifaddr_ipv6_added(struct netconfig *netconfig, - const struct ifaddrmsg *ifa, - uint32_t len) +static void netconfig_event_handler(struct l_netconfig *nc, uint8_t family, + enum l_netconfig_event event, + void *user_data) { - struct in6_addr in6; - L_AUTO_FREE_VAR(char *, ip) = NULL; - - if (ifa->ifa_flags & IFA_F_TENTATIVE) - return; - - l_rtnl_ifaddr6_extract(ifa, len, &ip); - - l_debug("ifindex %u: ifaddr %s/%u", netconfig->ifindex, - ip, ifa->ifa_prefixlen); - - if (netconfig->rtm_v6_protocol != RTPROT_DHCP || - netconfig_use_fils_addr(netconfig, AF_INET6)) - return; - - inet_pton(AF_INET6, ip, &in6); - if (!IN6_IS_ADDR_LINKLOCAL(&in6)) - return; - - l_dhcp6_client_set_link_local_address(netconfig->dhcp6_client, ip); - - if (l_dhcp6_client_start(netconfig->dhcp6_client)) - return; + struct netconfig *netconfig = user_data; - l_error("netconfig: Failed to start DHCPv6 client for " - "interface %u", netconfig->ifindex); -} + l_debug("l_netconfig event %d", event); -static void netconfig_ifaddr_ipv6_deleted(struct netconfig *netconfig, - const struct ifaddrmsg *ifa, - uint32_t len) -{ - L_AUTO_FREE_VAR(char *, ip); + l_netconfig_apply_rtnl(nc); - l_rtnl_ifaddr6_extract(ifa, len, &ip); - l_debug("ifindex %u: ifaddr %s/%u", netconfig->ifindex, - ip, ifa->ifa_prefixlen); -} + switch (event) { + case L_NETCONFIG_EVENT_CONFIGURE: + netconfig_dns_list_update(netconfig); + netconfig_domains_update(netconfig); -static void netconfig_ifaddr_ipv6_notify(uint16_t type, const void *data, - uint32_t len, void *user_data) -{ - const struct ifaddrmsg *ifa = data; - struct netconfig *netconfig; - uint32_t bytes; + if (family == AF_INET && + !netconfig->static_config[INDEX_FOR_AF(family)]) + netconfig_dhcp_gateway_to_arp(netconfig); - netconfig = netconfig_find(ifa->ifa_index); - if (!netconfig) - /* Ignore the interfaces which aren't managed by iwd. */ - return; + if (!netconfig->connected[INDEX_FOR_AF(family)] && + netconfig_use_fils_addr(netconfig, family)) + netconfig_commit_fils_macs(netconfig, family); - bytes = len - NLMSG_ALIGN(sizeof(struct ifaddrmsg)); + if (family == AF_INET && + !netconfig->connected[INDEX_FOR_AF(family)] && + netconfig->notify) + netconfig->notify(NETCONFIG_EVENT_CONNECTED, + netconfig->user_data); - switch (type) { - case RTM_NEWADDR: - netconfig_ifaddr_ipv6_added(netconfig, ifa, bytes); - break; - case RTM_DELADDR: - netconfig_ifaddr_ipv6_deleted(netconfig, ifa, bytes); + netconfig->connected[INDEX_FOR_AF(family)] = true; break; - } -} -static void netconfig_ifaddr_ipv6_cmd_cb(int error, uint16_t type, - const void *data, uint32_t len, - void *user_data) -{ - if (error) { - l_error("netconfig: ifaddr IPv6 command failure. " - "Error %d: %s", error, strerror(-error)); - return; - } - - if (type != RTM_NEWADDR) - return; - - netconfig_ifaddr_ipv6_notify(type, data, len, user_data); -} - -static void netconfig_route_generic_cb(int error, uint16_t type, - const void *data, uint32_t len, - void *user_data) -{ - if (error) { - l_error("netconfig: Failed to add route. Error %d: %s", - error, strerror(-error)); - return; - } -} - -static void netconfig_route_add_cmd_cb(int error, uint16_t type, - const void *data, uint32_t len, - void *user_data) -{ - struct netconfig *netconfig = user_data; - - netconfig->route4_add_gateway_cmd_id = 0; - - if (error) { - l_error("netconfig: Failed to add route. Error %d: %s", - error, strerror(-error)); - return; - } - - if (!netconfig->notify) - return; - - netconfig->notify(NETCONFIG_EVENT_CONNECTED, netconfig->user_data); - netconfig->notify = NULL; -} + case L_NETCONFIG_EVENT_UPDATE: + case L_NETCONFIG_EVENT_UNCONFIGURE: + break; -static void netconfig_route6_add_cb(int error, uint16_t type, - const void *data, uint32_t len, - void *user_data) -{ - struct netconfig *netconfig = user_data; + case L_NETCONFIG_EVENT_FAILED: + /* + * l_netconfig might have emitted an UNCONFIGURE before this + * but now it tells us it's given up on (re)establishing the + * IP setup. + */ + if (family == AF_INET && netconfig->notify) + netconfig->notify(NETCONFIG_EVENT_FAILED, + netconfig->user_data); - netconfig->route6_add_cmd_id = 0; + break; - if (error) { - l_error("netconfig: Failed to add route. Error %d: %s", - error, strerror(-error)); - return; + default: + l_error("netconfig: Received unsupported l_netconfig event: %d", + event); } } -static bool netconfig_ipv4_subnet_route_install(struct netconfig *netconfig) +static bool netconfig_load_dns(struct netconfig *netconfig, + const struct l_settings *active_settings, + const char *group_name, uint8_t family) { - struct in_addr in_addr; - char ip[INET_ADDRSTRLEN]; - char network[INET_ADDRSTRLEN]; - unsigned int prefix_len = - l_rtnl_address_get_prefix_length(netconfig->v4_address); - - if (!l_rtnl_address_get_address(netconfig->v4_address, ip) || - inet_pton(AF_INET, ip, &in_addr) < 1) - return false; + _auto_(l_strv_free) char **dns_str_list = NULL; - in_addr.s_addr = in_addr.s_addr & - htonl(0xFFFFFFFFLU << (32 - prefix_len)); + if (!l_settings_has_key(active_settings, group_name, "DNS")) + return true; - if (!inet_ntop(AF_INET, &in_addr, network, INET_ADDRSTRLEN)) + dns_str_list = l_settings_get_string_list(active_settings, + group_name, "DNS", ' '); + if (unlikely(!dns_str_list)) { + l_error("netconfig: Can't load [%s].DNS", group_name); return false; + } - if (!l_rtnl_route4_add_connected(rtnl, netconfig->ifindex, - prefix_len, network, ip, - netconfig->rtm_protocol, - netconfig_route_generic_cb, - netconfig, NULL)) { - l_error("netconfig: Failed to add subnet route."); + if (unlikely(!l_netconfig_set_dns_override(netconfig->nc, family, + dns_str_list))) { + l_error("netconfig: l_netconfig_set_dns_override(%s) failed", + family == AF_INET ? "AF_INET" : "AF_INET6"); return false; } + netconfig->dns_overridden[INDEX_FOR_AF(family)] = true; return true; } -static bool netconfig_ipv4_gateway_route_install(struct netconfig *netconfig) +static bool netconfig_load_gateway(struct netconfig *netconfig, + const struct l_settings *active_settings, + const char *group_name, uint8_t family) { - L_AUTO_FREE_VAR(char *, gateway) = NULL; - const uint8_t *gateway_mac = NULL; - struct in_addr in_addr; - char ip[INET_ADDRSTRLEN]; - - gateway = netconfig_ipv4_get_gateway(netconfig, &gateway_mac); - if (!gateway) { - l_debug("No gateway obtained from %s.", - netconfig->rtm_protocol == RTPROT_STATIC ? - "setting file" : "DHCPv4 lease"); - - if (netconfig->notify) { - netconfig->notify(NETCONFIG_EVENT_CONNECTED, - netconfig->user_data); - netconfig->notify = NULL; - } + _auto_(l_free) char *gateway_str = NULL; + if (!l_settings_has_key(active_settings, group_name, "Gateway")) return true; - } - if (!l_rtnl_address_get_address(netconfig->v4_address, ip) || - inet_pton(AF_INET, ip, &in_addr) < 1) + gateway_str = l_settings_get_string(active_settings, group_name, + "Gateway"); + if (unlikely(!gateway_str)) { + l_error("netconfig: Can't load [%s].Gateway", group_name); return false; + } - netconfig->route4_add_gateway_cmd_id = - l_rtnl_route4_add_gateway(rtnl, netconfig->ifindex, gateway, ip, - ROUTE_PRIORITY_OFFSET, - netconfig->rtm_protocol, - netconfig_route_add_cmd_cb, - netconfig, NULL); - if (!netconfig->route4_add_gateway_cmd_id) { - l_error("netconfig: Failed to add route for: %s gateway.", - gateway); - + if (unlikely(!l_netconfig_set_gateway_override(netconfig->nc, family, + gateway_str))) { + l_error("netconfig: l_netconfig_set_gateway_override(%s) " + "failed", family == AF_INET ? "AF_INET" : "AF_INET6"); return false; } - /* - * Attempt to use the gateway MAC address received from the AP by - * writing the mapping directly into the netdev's ARP table so as - * to save one data frame roundtrip before first IP connections - * are established. This is very low-priority but print error - * messages just because they may indicate bigger problems. - */ - if (gateway_mac && !l_rtnl_neighbor_set_hwaddr(rtnl, netconfig->ifindex, - AF_INET, - &netconfig->fils_override->ipv4_gateway, - gateway_mac, 6, - netconfig_set_neighbor_entry_cb, NULL, - NULL)) - l_debug("l_rtnl_neighbor_set_hwaddr failed"); - + netconfig->gateway_overridden[INDEX_FOR_AF(family)] = true; return true; } -static void netconfig_ipv4_ifaddr_add_cmd_cb(int error, uint16_t type, - const void *data, uint32_t len, - void *user_data) -{ - struct netconfig *netconfig = user_data; - - netconfig->addr4_add_cmd_id = 0; - - if (error && error != -EEXIST) { - l_error("netconfig: Failed to add IP address. " - "Error %d: %s", error, strerror(-error)); - return; - } - - netconfig_gateway_to_arp(netconfig); - - if (!netconfig_ipv4_subnet_route_install(netconfig) || - !netconfig_ipv4_gateway_route_install(netconfig)) - return; - - netconfig_set_dns(netconfig); - netconfig_set_domains(netconfig); -} - -static void netconfig_ipv6_ifaddr_add_cmd_cb(int error, uint16_t type, - const void *data, uint32_t len, - void *user_data) -{ - struct netconfig *netconfig = user_data; - struct l_rtnl_route *gateway; - const uint8_t *gateway_mac; - - netconfig->addr6_add_cmd_id = 0; - - if (error && error != -EEXIST) { - l_error("netconfig: Failed to add IPv6 address. " - "Error %d: %s", error, strerror(-error)); - return; - } - - gateway = netconfig_get_static6_gateway(netconfig, - &netconfig->v6_gateway_str, - &gateway_mac); - if (gateway) { - netconfig->route6_add_cmd_id = l_rtnl_route_add(rtnl, - netconfig->ifindex, - gateway, - netconfig_route6_add_cb, - netconfig, NULL); - L_WARN_ON(unlikely(!netconfig->route6_add_cmd_id)); - l_rtnl_route_free(gateway); - - if (gateway_mac && !l_rtnl_neighbor_set_hwaddr(rtnl, - netconfig->ifindex, AF_INET6, - netconfig->fils_override->ipv6_gateway, - gateway_mac, 6, - netconfig_set_neighbor_entry_cb, NULL, - NULL)) - l_debug("l_rtnl_neighbor_set_hwaddr failed"); - } - - netconfig_set_dns(netconfig); - netconfig_set_domains(netconfig); -} - -static void netconfig_ifaddr_del_cmd_cb(int error, uint16_t type, - const void *data, uint32_t len, - void *user_data) +bool netconfig_load_settings(struct netconfig *netconfig, + const struct l_settings *active_settings) { - if (error == -ENODEV) - /* The device is unplugged, we are done. */ - return; - - if (!error) - /* - * The kernel removes all of the routes associated with the - * deleted IP on its own. There is no need to explicitly remove - * them. - */ - return; + bool send_hostname = false; + char hostname[HOST_NAME_MAX + 1]; + _auto_(l_free) char *mdns = NULL; + bool success = true; + bool static_ipv4 = false; + bool static_ipv6 = false; + bool enable_ipv4 = true; + bool enable_ipv6 = ipv6_enabled; - l_error("netconfig: Failed to delete IP address. " - "Error %d: %s", error, strerror(-error)); -} + netconfig_free_settings(netconfig); -static void netconfig_ipv4_dhcp_event_handler(struct l_dhcp_client *client, - enum l_dhcp_client_event event, - void *userdata) -{ - struct netconfig *netconfig = userdata; + /* + * Note we try to print errors and continue validating the + * configuration until we've gone through all the settings so + * as to make fixing the settings more efficient for the user. + */ - l_debug("DHCPv4 event %d", event); + if (l_settings_has_key(active_settings, "IPv4", "Address")) { + _auto_(l_rtnl_address_free) struct l_rtnl_address *addr = + netconfig_get_static4_address(active_settings); - switch (event) { - case L_DHCP_CLIENT_EVENT_IP_CHANGED: - L_WARN_ON(!l_rtnl_ifaddr_delete(rtnl, netconfig->ifindex, - netconfig->v4_address, - netconfig_ifaddr_del_cmd_cb, - netconfig, NULL)); - /* Fall through. */ - case L_DHCP_CLIENT_EVENT_LEASE_OBTAINED: - { - char *gateway_str; - struct l_rtnl_address *address; - - gateway_str = netconfig_ipv4_get_gateway(netconfig, NULL); - if (l_streq0(netconfig->v4_gateway_str, gateway_str)) - l_free(gateway_str); - else { - l_free(netconfig->v4_gateway_str); - netconfig->v4_gateway_str = gateway_str; + if (unlikely(!addr)) { + success = false; + goto ipv6_addr; } - address = netconfig_get_dhcp4_address(netconfig); - l_rtnl_address_free(netconfig->v4_address); - netconfig->v4_address = address; - - if (!netconfig->v4_address) { - l_error("netconfig: Failed to obtain IP addresses from " - "DHCPv4 lease."); - return; + if (!l_netconfig_set_static_addr(netconfig->nc, AF_INET, + addr)) { + l_error("netconfig: l_netconfig_set_static_addr(" + "AF_INET) failed"); + success = false; + goto ipv6_addr; } - netconfig_dns_list_update(netconfig, AF_INET); - netconfig_domains_update(netconfig, AF_INET); - - L_WARN_ON(!(netconfig->addr4_add_cmd_id = - l_rtnl_ifaddr_add(rtnl, netconfig->ifindex, - netconfig->v4_address, - netconfig_ipv4_ifaddr_add_cmd_cb, - netconfig, NULL))); - break; - } - case L_DHCP_CLIENT_EVENT_LEASE_RENEWED: - break; - case L_DHCP_CLIENT_EVENT_LEASE_EXPIRED: - L_WARN_ON(!l_rtnl_ifaddr_delete(rtnl, netconfig->ifindex, - netconfig->v4_address, - netconfig_ifaddr_del_cmd_cb, - netconfig, NULL)); - l_rtnl_address_free(netconfig->v4_address); - netconfig->v4_address = NULL; - l_free(l_steal_ptr(netconfig->v4_gateway_str)); - - /* Fall through. */ - case L_DHCP_CLIENT_EVENT_NO_LEASE: - /* - * The requested address is no longer available, try to restart - * the client. - */ - if (!l_dhcp_client_start(client)) - l_error("netconfig: Failed to re-start DHCPv4 client " - "for interface %u", netconfig->ifindex); - - break; - default: - l_error("netconfig: Received unsupported DHCPv4 event: %d", - event); + static_ipv4 = true; } -} -static void netconfig_dhcp6_event_handler(struct l_dhcp6_client *client, - enum l_dhcp6_client_event event, - void *userdata) -{ - struct netconfig *netconfig = userdata; +ipv6_addr: + if (l_settings_has_key(active_settings, "IPv6", "Address")) { + _auto_(l_rtnl_address_free) struct l_rtnl_address *addr = + netconfig_get_static6_address(active_settings); - switch (event) { - case L_DHCP6_CLIENT_EVENT_IP_CHANGED: - case L_DHCP6_CLIENT_EVENT_LEASE_OBTAINED: - case L_DHCP6_CLIENT_EVENT_LEASE_RENEWED: - { - const struct l_dhcp6_lease *lease = - l_dhcp6_client_get_lease(netconfig->dhcp6_client); - _auto_(l_free) char *addr_str = - l_dhcp6_lease_get_address(lease); - struct l_rtnl_address *address; - struct l_icmp6_client *icmp6 = - l_dhcp6_client_get_icmp6(netconfig->dhcp6_client); - const struct l_icmp6_router *router = - l_icmp6_client_get_router(icmp6); - char *gateway_str = l_icmp6_router_get_address(router); - - if (l_streq0(netconfig->v6_gateway_str, gateway_str)) - l_free(gateway_str); - else { - l_free(netconfig->v6_gateway_str); - netconfig->v6_gateway_str = gateway_str; + if (unlikely(!addr)) { + success = false; + goto gateway; } - address = l_rtnl_address_new(addr_str, - l_dhcp6_lease_get_prefix_length(lease)); - l_rtnl_address_free(netconfig->v6_address); - netconfig->v6_address = address; + if (!l_netconfig_set_static_addr(netconfig->nc, AF_INET6, + addr)) { + l_error("netconfig: l_netconfig_set_static_addr(" + "AF_INET6) failed"); + success = false; + goto gateway; + } - netconfig_dns_list_update(netconfig, AF_INET6); - netconfig_domains_update(netconfig, AF_INET6); - netconfig_set_dns(netconfig); - netconfig_set_domains(netconfig); - break; - } - case L_DHCP6_CLIENT_EVENT_LEASE_EXPIRED: - l_debug("Lease for interface %u expired", netconfig->ifindex); - netconfig_dns_list_update(netconfig, AF_INET6); - netconfig_domains_update(netconfig, AF_INET6); - netconfig_set_dns(netconfig); - netconfig_set_domains(netconfig); - l_rtnl_address_free(netconfig->v6_address); - netconfig->v6_address = NULL; - l_free(l_steal_ptr(netconfig->v6_gateway_str)); - - /* Fall through */ - case L_DHCP6_CLIENT_EVENT_NO_LEASE: - if (!l_dhcp6_client_start(netconfig->dhcp6_client)) - l_error("netconfig: Failed to re-start DHCPv6 client " - "for interface %u", netconfig->ifindex); - break; + static_ipv6 = true; } -} -static void netconfig_remove_v4_address(struct netconfig *netconfig) -{ - if (!netconfig->v4_address) - return; +gateway: + if (!netconfig_load_gateway(netconfig, active_settings, + "IPv4", AF_INET)) + success = false; - L_WARN_ON(!l_rtnl_ifaddr_delete(rtnl, netconfig->ifindex, - netconfig->v4_address, - netconfig_ifaddr_del_cmd_cb, - netconfig, NULL)); - l_rtnl_address_free(netconfig->v4_address); - netconfig->v4_address = NULL; -} + if (!netconfig_load_gateway(netconfig, active_settings, + "IPv6", AF_INET6)) + success = false; -static void netconfig_reset_v4(struct netconfig *netconfig) -{ - if (netconfig->rtm_protocol) { - netconfig_remove_v4_address(netconfig); - - l_strv_free(l_steal_ptr(netconfig->dns4_overrides)); - l_strv_free(l_steal_ptr(netconfig->dns4_list)); - - l_dhcp_client_stop(netconfig->dhcp_client); - netconfig->rtm_protocol = 0; - - l_acd_destroy(netconfig->acd); - netconfig->acd = NULL; + if (!netconfig_load_dns(netconfig, active_settings, "IPv4", AF_INET)) + success = false; - l_free(l_steal_ptr(netconfig->v4_gateway_str)); + if (!netconfig_load_dns(netconfig, active_settings, "IPv6", AF_INET6)) + success = false; - l_free(l_steal_ptr(netconfig->v4_domain)); + if (l_settings_has_key(active_settings, "IPv6", "Enabled") && + !l_settings_get_bool(active_settings, "IPv6", "Enabled", + &enable_ipv6)) { + l_error("netconfig: Can't load IPv6.Enabled"); + success = false; + goto send_hostname; } -} - -static void netconfig_ipv4_acd_event(enum l_acd_event event, void *user_data) -{ - struct netconfig *netconfig = user_data; - switch (event) { - case L_ACD_EVENT_AVAILABLE: - L_WARN_ON(!(netconfig->addr4_add_cmd_id = - l_rtnl_ifaddr_add(rtnl, netconfig->ifindex, - netconfig->v4_address, - netconfig_ipv4_ifaddr_add_cmd_cb, - netconfig, NULL))); - return; - case L_ACD_EVENT_CONFLICT: - /* - * Conflict found, no IP was actually set so just free/unset - * anything we set prior to starting ACD. - */ - l_error("netconfig: statically configured address conflict!"); - l_rtnl_address_free(netconfig->v4_address); - netconfig->v4_address = NULL; - netconfig->rtm_protocol = 0; - break; - case L_ACD_EVENT_LOST: - /* - * Set IP but lost it some time after. Full (IPv4) reset in this - * case. - */ - l_error("netconfig: statically configured address was lost"); - netconfig_remove_v4_address(netconfig); - break; + if (!l_netconfig_set_family_enabled(netconfig->nc, AF_INET, + enable_ipv4) || + !l_netconfig_set_family_enabled(netconfig->nc, AF_INET6, + enable_ipv6)) { + l_error("netconfig: l_netconfig_set_family_enabled() failed"); + success = false; } -} - -static bool netconfig_ipv4_select_and_install(struct netconfig *netconfig) -{ - struct netdev *netdev = netdev_find(netconfig->ifindex); - bool set_address = (netconfig->rtm_protocol == RTPROT_STATIC); - - if (netconfig_use_fils_addr(netconfig, AF_INET)) { - L_AUTO_FREE_VAR(char *, addr_str) = netconfig_ipv4_to_string( - netconfig->fils_override->ipv4_addr); - uint8_t prefix_len = netconfig->fils_override->ipv4_prefix_len; - - if (unlikely(!addr_str)) - return false; - netconfig->v4_address = l_rtnl_address_new(addr_str, - prefix_len); - if (L_WARN_ON(!netconfig->v4_address)) - return false; - - l_rtnl_address_set_noprefixroute(netconfig->v4_address, true); - set_address = true; - - /* - * TODO: If netconfig->fils_override->ipv4_lifetime is set, - * start a timeout to renew the address using FILS IP Address - * Assignment or perhaps just start the DHCP client at that - * time. - */ +send_hostname: + if (l_settings_has_key(active_settings, "IPv4", "SendHostname") && + !l_settings_get_bool(active_settings, "IPv4", + "SendHostname", + &send_hostname)) { + l_error("netconfig: Can't load [IPv4].SendHostname"); + success = false; + goto mdns; } - if (set_address) { - char ip[INET6_ADDRSTRLEN]; - - if (L_WARN_ON(!netconfig->v4_address || - !l_rtnl_address_get_address( - netconfig->v4_address, - ip))) - return false; - - netconfig_dns_list_update(netconfig, AF_INET); - netconfig_domains_update(netconfig, AF_INET); - - netconfig->acd = l_acd_new(netconfig->ifindex); - l_acd_set_event_handler(netconfig->acd, - netconfig_ipv4_acd_event, netconfig, - NULL); - if (getenv("IWD_ACD_DEBUG")) - l_acd_set_debug(netconfig->acd, do_debug, - "[ACD] ", NULL); - - if (!l_acd_start(netconfig->acd, ip)) { - l_error("failed to start ACD, continuing anyways"); - l_acd_destroy(netconfig->acd); - netconfig->acd = NULL; - - L_WARN_ON(!(netconfig->addr4_add_cmd_id = - l_rtnl_ifaddr_add(rtnl, netconfig->ifindex, - netconfig->v4_address, - netconfig_ipv4_ifaddr_add_cmd_cb, - netconfig, NULL))); - } - - return true; + if (send_hostname && gethostname(hostname, sizeof(hostname)) != 0) { + /* Warning only */ + l_warn("netconfig: Unable to get hostname. " + "Error %d: %s", errno, strerror(errno)); + goto mdns; } - l_dhcp_client_set_address(netconfig->dhcp_client, ARPHRD_ETHER, - netdev_get_address(netdev), ETH_ALEN); - - if (l_dhcp_client_start(netconfig->dhcp_client)) - return true; - - l_error("netconfig: Failed to start DHCPv4 client for interface %u", - netconfig->ifindex); - return false; -} - -static bool netconfig_ipv6_select_and_install(struct netconfig *netconfig) -{ - struct netdev *netdev = netdev_find(netconfig->ifindex); - - if (netconfig->rtm_v6_protocol == RTPROT_UNSPEC) { - l_debug("IPV6 configuration disabled"); - return true; + if (send_hostname && + !l_netconfig_set_hostname(netconfig->nc, hostname)) { + l_error("netconfig: l_netconfig_set_hostname() failed"); + success = false; + goto mdns; } - sysfs_write_ipv6_setting(netdev_get_name(netdev), "disable_ipv6", "0"); - - if (netconfig_use_fils_addr(netconfig, AF_INET6)) { - uint8_t prefix_len = netconfig->fils_override->ipv6_prefix_len; - L_AUTO_FREE_VAR(char *, addr_str) = netconfig_ipv6_to_string( - netconfig->fils_override->ipv6_addr); - - if (unlikely(!addr_str)) - return false; - - netconfig->v6_address = l_rtnl_address_new(addr_str, - prefix_len); - if (L_WARN_ON(unlikely(!netconfig->v6_address))) - return false; - - l_rtnl_address_set_noprefixroute(netconfig->v6_address, true); - - /* - * TODO: If netconfig->fils_override->ipv6_lifetime is set, - * start a timeout to renew the address using FILS IP Address - * Assignment or perhaps just start the DHCP client at that - * time. - */ +mdns: + if (l_settings_has_key(active_settings, "Network", "MulticastDNS") && + !(mdns = l_settings_get_string(active_settings, + "Network", + "MulticastDNS"))) { + l_error("netconfig: Can't load Network.MulticastDNS"); + success = false; } - if (netconfig->v6_address) { - netconfig_dns_list_update(netconfig, AF_INET6); - - L_WARN_ON(!(netconfig->addr6_add_cmd_id = - l_rtnl_ifaddr_add(rtnl, netconfig->ifindex, - netconfig->v6_address, - netconfig_ipv6_ifaddr_add_cmd_cb, - netconfig, NULL))); - return true; + if (!l_netconfig_check_config(netconfig->nc)) { + l_error("netconfig: Invalid configuration"); + success = false; } - /* DHCPv6 or RA, update MAC */ - l_dhcp6_client_set_address(netconfig->dhcp6_client, ARPHRD_ETHER, - netdev_get_address(netdev), ETH_ALEN); - - return true; -} - -static int validate_dns_list(int family, char **dns_list) -{ - unsigned int n_valid = 0; - struct in_addr in_addr; - struct in6_addr in6_addr; - char **p; - - for (p = dns_list; *p; p++) { - int r; - - if (family == AF_INET) - r = inet_pton(AF_INET, *p, &in_addr); - else if (family == AF_INET6) - r = inet_pton(AF_INET6, *p, &in6_addr); - else - r = -EAFNOSUPPORT; - - if (r > 0) { - n_valid += 1; - continue; - } - - l_error("netconfig: Invalid DNS address '%s'.", *p); - return -EINVAL; + if (success) { + netconfig->active_settings = active_settings; + netconfig->static_config[INDEX_FOR_AF(AF_INET)] = static_ipv4; + netconfig->static_config[INDEX_FOR_AF(AF_INET6)] = static_ipv6; + netconfig->enabled[INDEX_FOR_AF(AF_INET)] = enable_ipv4; + netconfig->enabled[INDEX_FOR_AF(AF_INET6)] = enable_ipv6; + netconfig->mdns = l_steal_ptr(mdns); + return true; } - return n_valid; + l_netconfig_reset_config(netconfig->nc); + return false; } -bool netconfig_load_settings(struct netconfig *netconfig, - const struct l_settings *active_settings) +static bool netconfig_load_fils_settings(struct netconfig *netconfig, + uint8_t af) { - _auto_(l_free) char *mdns = NULL; - bool send_hostname; - bool v6_enabled; - char hostname[HOST_NAME_MAX + 1]; - _auto_(l_strv_free) char **dns4_overrides = NULL; - _auto_(l_strv_free) char **dns6_overrides = NULL; - _auto_(l_rtnl_address_free) struct l_rtnl_address *v4_address = NULL; - _auto_(l_rtnl_address_free) struct l_rtnl_address *v6_address = NULL; - - dns4_overrides = l_settings_get_string_list(active_settings, - "IPv4", "DNS", ' '); - if (dns4_overrides) { - int r = validate_dns_list(AF_INET, dns4_overrides); - - if (unlikely(r <= 0)) { - l_strfreev(dns4_overrides); - dns4_overrides = NULL; - - if (r < 0) - return false; - } - - if (r == 0) - l_error("netconfig: Empty IPv4.DNS entry, skipping..."); - } + struct ie_fils_ip_addr_response_info *fils = netconfig->fils_override; + char addr_str[INET6_ADDRSTRLEN]; + char gw_addr_str[INET6_ADDRSTRLEN]; + char dns_addr_str[INET6_ADDRSTRLEN]; + _auto_(l_rtnl_address_free) struct l_rtnl_address *rtnl_addr = NULL; + bool is_zero = false; + uint8_t prefix_len; - dns6_overrides = l_settings_get_string_list(active_settings, - "IPv6", "DNS", ' '); + if (!netconfig_addr_to_str(af, &fils->ipv4_addr, &fils->ipv6_addr, + addr_str, &is_zero) || is_zero) + return is_zero; - if (dns6_overrides) { - int r = validate_dns_list(AF_INET6, dns6_overrides); + prefix_len = (af == AF_INET ? fils->ipv4_prefix_len : + fils->ipv6_prefix_len); - if (unlikely(r <= 0)) { - l_strfreev(dns6_overrides); - dns6_overrides = NULL; + if (L_WARN_ON(!(rtnl_addr = l_rtnl_address_new(addr_str, prefix_len)))) + return false; - if (r < 0) - return false; - } + if (L_WARN_ON(!l_netconfig_set_static_addr(netconfig->nc, af, + rtnl_addr))) + return false; - if (r == 0) - l_error("netconfig: Empty IPv6.DNS entry, skipping..."); - } + /* + * Done with local address, move on to gateway and DNS. + * + * Since load_settings is called early, generally before the actual + * connection setup starts, and load_fils_settings is called after + * 802.11 Authentication & Association, we need to check if either + * the gateway or DNS settings were overridden in load_settings so + * as not to overwrite the user-provided values. Values received + * with FILS are expected to have the same weight as those from + * DHCP/SLAAC. + * + * TODO: If netconfig->fils_override->ipv{4,6}_lifetime is set, + * start a timeout to renew the address using FILS IP Address + * Assignment or perhaps just start the DHCP client after that + * time. + * + * TODO: validate gateway and/or DNS on local subnet, link-local, + * etc.? + */ - if (!l_settings_get_bool(active_settings, - "IPv4", "SendHostname", &send_hostname)) - send_hostname = false; + if (!netconfig_addr_to_str(af, &fils->ipv4_gateway, &fils->ipv6_gateway, + gw_addr_str, &is_zero)) + return false; - if (send_hostname) { - if (gethostname(hostname, sizeof(hostname)) != 0) { - l_warn("netconfig: Unable to get hostname. " - "Error %d: %s", errno, strerror(errno)); - send_hostname = false; - } - } + if (!netconfig->gateway_overridden[INDEX_FOR_AF(af)] && !is_zero && + L_WARN_ON(!l_netconfig_set_gateway_override( + netconfig->nc, + af, + gw_addr_str))) + return false; - mdns = l_settings_get_string(active_settings, - "Network", "MulticastDNS"); + if (!netconfig_addr_to_str(af, &fils->ipv4_dns, &fils->ipv6_dns, + dns_addr_str, &is_zero)) + return is_zero; - if (l_settings_has_key(active_settings, "IPv4", "Address")) { - v4_address = netconfig_get_static4_address(active_settings); + if (!netconfig->dns_overridden[INDEX_FOR_AF(af)] && !is_zero) { + char *dns_list[2] = { dns_addr_str, NULL }; - if (unlikely(!v4_address)) { - l_error("netconfig: Can't parse IPv4 address"); + if (L_WARN_ON(!l_netconfig_set_dns_override(netconfig->nc, + af, dns_list))) return false; - } } - if (!l_settings_get_bool(active_settings, "IPv6", - "Enabled", &v6_enabled)) - v6_enabled = ipv6_enabled; - - if (l_settings_has_key(active_settings, "IPv6", "Address")) { - v6_address = netconfig_get_static6_address(active_settings); - - if (unlikely(!v6_address)) { - l_error("netconfig: Can't parse IPv6 address"); - return false; - } - } - - /* No more validation steps for now, commit new values */ - netconfig->rtm_protocol = v4_address ? RTPROT_STATIC : RTPROT_DHCP; - - if (!v6_enabled) - netconfig->rtm_v6_protocol = RTPROT_UNSPEC; - else if (v6_address) - netconfig->rtm_v6_protocol = RTPROT_STATIC; - else - netconfig->rtm_v6_protocol = RTPROT_DHCP; - - if (send_hostname) - l_dhcp_client_set_hostname(netconfig->dhcp_client, hostname); - - netconfig_free_settings(netconfig); - - if (netconfig->rtm_protocol == RTPROT_STATIC) - netconfig->v4_address = l_steal_ptr(v4_address); - - if (netconfig->rtm_v6_protocol == RTPROT_STATIC) - netconfig->v6_address = l_steal_ptr(v6_address); - - netconfig->active_settings = active_settings; - netconfig->dns4_overrides = l_steal_ptr(dns4_overrides); - netconfig->dns6_overrides = l_steal_ptr(dns6_overrides); - netconfig->mdns = l_steal_ptr(mdns); return true; } @@ -1489,10 +690,15 @@ bool netconfig_configure(struct netconfig *netconfig, netconfig->notify = notify; netconfig->user_data = user_data; - if (unlikely(!netconfig_ipv4_select_and_install(netconfig))) + if (netconfig_use_fils_addr(netconfig, AF_INET) && + !netconfig_load_fils_settings(netconfig, AF_INET)) return false; - if (unlikely(!netconfig_ipv6_select_and_install(netconfig))) + if (netconfig_use_fils_addr(netconfig, AF_INET6) && + !netconfig_load_fils_settings(netconfig, AF_INET6)) + return false; + + if (unlikely(!l_netconfig_start(netconfig->nc))) return false; resolve_set_mdns(netconfig->resolve, netconfig->mdns); @@ -1509,14 +715,23 @@ bool netconfig_reconfigure(struct netconfig *netconfig, bool set_arp_gw) * lost or delayed. Try to force the gateway into the ARP cache * to alleviate this */ - if (set_arp_gw) - netconfig_gateway_to_arp(netconfig); + if (set_arp_gw) { + netconfig_dhcp_gateway_to_arp(netconfig); - if (netconfig->rtm_protocol == RTPROT_DHCP) { + if (netconfig->connected[INDEX_FOR_AF(AF_INET)] && + netconfig_use_fils_addr(netconfig, AF_INET)) + netconfig_commit_fils_macs(netconfig, AF_INET); + + if (netconfig->connected[INDEX_FOR_AF(AF_INET6)] && + netconfig_use_fils_addr(netconfig, AF_INET6)) + netconfig_commit_fils_macs(netconfig, AF_INET6); + } + + if (!netconfig->static_config[INDEX_FOR_AF(AF_INET)]) { /* TODO l_dhcp_client sending a DHCP inform request */ } - if (netconfig->rtm_v6_protocol == RTPROT_DHCP) { + if (!netconfig->static_config[INDEX_FOR_AF(AF_INET6)]) { /* TODO l_dhcp_v6_client sending a DHCP inform request */ } @@ -1525,64 +740,27 @@ bool netconfig_reconfigure(struct netconfig *netconfig, bool set_arp_gw) bool netconfig_reset(struct netconfig *netconfig) { - struct netdev *netdev = netdev_find(netconfig->ifindex); - - if (netconfig->route4_add_gateway_cmd_id) { - l_netlink_cancel(rtnl, netconfig->route4_add_gateway_cmd_id); - netconfig->route4_add_gateway_cmd_id = 0; - } + l_netconfig_stop(netconfig->nc); - if (netconfig->route6_add_cmd_id) { - l_netlink_cancel(rtnl, netconfig->route6_add_cmd_id); - netconfig->route6_add_cmd_id = 0; - } - - if (netconfig->addr4_add_cmd_id) { - l_netlink_cancel(rtnl, netconfig->addr4_add_cmd_id); - netconfig->addr4_add_cmd_id = 0; - } - - if (netconfig->addr6_add_cmd_id) { - l_netlink_cancel(rtnl, netconfig->addr6_add_cmd_id); - netconfig->addr6_add_cmd_id = 0; - } - - if (netconfig->rtm_protocol || netconfig->rtm_v6_protocol) - resolve_revert(netconfig->resolve); - - netconfig_reset_v4(netconfig); - - if (netconfig->rtm_v6_protocol) { - l_rtnl_address_free(netconfig->v6_address); - netconfig->v6_address = NULL; - - l_strv_free(l_steal_ptr(netconfig->dns6_overrides)); - l_strv_free(l_steal_ptr(netconfig->dns6_list)); - - l_dhcp6_client_stop(netconfig->dhcp6_client); - netconfig->rtm_v6_protocol = 0; - - sysfs_write_ipv6_setting(netdev_get_name(netdev), - "disable_ipv6", "1"); - - l_free(l_steal_ptr(netconfig->v6_gateway_str)); - - l_strv_free(l_steal_ptr(netconfig->v6_domains)); - } + resolve_revert(netconfig->resolve); - l_free(l_steal_ptr(netconfig->fils_override)); + netconfig->connected[0] = false; + netconfig->connected[1] = false; + netconfig_free_settings(netconfig); return true; } char *netconfig_get_dhcp_server_ipv4(struct netconfig *netconfig) { + struct l_dhcp_client *client = + l_netconfig_get_dhcp_client(netconfig->nc); const struct l_dhcp_lease *lease; - if (!netconfig->dhcp_client) + if (!client) return NULL; - lease = l_dhcp_client_get_lease(netconfig->dhcp_client); + lease = l_dhcp_client_get_lease(client); if (!lease) return NULL; @@ -1598,15 +776,16 @@ bool netconfig_get_fils_ip_req(struct netconfig *netconfig, * configuration (usually DHCP). If we're configured with static * values return false to mean the IE should not be sent. */ - if (netconfig->rtm_protocol != RTPROT_DHCP && - netconfig->rtm_v6_protocol != RTPROT_DHCP) + if (netconfig->static_config[0] && netconfig->static_config[1]) return false; memset(info, 0, sizeof(*info)); - info->ipv4 = (netconfig->rtm_protocol == RTPROT_DHCP); - info->ipv6 = (netconfig->rtm_v6_protocol == RTPROT_DHCP); - info->dns = (info->ipv4 && !netconfig->dns4_overrides) || - (info->ipv6 && !netconfig->dns6_overrides); + info->ipv4 = !netconfig->static_config[INDEX_FOR_AF(AF_INET)]; + info->ipv6 = !netconfig->static_config[INDEX_FOR_AF(AF_INET6)]; + info->dns = (info->ipv4 && + !netconfig->dns_overridden[INDEX_FOR_AF(AF_INET)]) || + (info->ipv6 && + !netconfig->dns_overridden[INDEX_FOR_AF(AF_INET)]); return true; } @@ -1622,28 +801,17 @@ struct netconfig *netconfig_new(uint32_t ifindex) { struct netdev *netdev = netdev_find(ifindex); struct netconfig *netconfig; - struct l_icmp6_client *icmp6; const char *debug_level = NULL; int dhcp_priority = L_LOG_INFO; + struct l_dhcp6_client *dhcp6; - if (!netconfig_list) - return NULL; - - l_debug("Starting netconfig for interface: %d", ifindex); - - netconfig = netconfig_find(ifindex); - if (netconfig) - return netconfig; + l_debug("Creating netconfig for interface: %d", ifindex); netconfig = l_new(struct netconfig, 1); - netconfig->ifindex = ifindex; + netconfig->nc = l_netconfig_new(ifindex); + netconfig->netdev = netdev; netconfig->resolve = resolve_new(ifindex); - netconfig->dhcp_client = l_dhcp_client_new(ifindex); - l_dhcp_client_set_event_handler(netconfig->dhcp_client, - netconfig_ipv4_dhcp_event_handler, - netconfig, NULL); - debug_level = getenv("IWD_DHCP_DEBUG"); if (debug_level != NULL) { if (!strcmp("debug", debug_level)) @@ -1658,42 +826,28 @@ struct netconfig *netconfig_new(uint32_t ifindex) dhcp_priority = L_LOG_DEBUG; } - l_dhcp_client_set_debug(netconfig->dhcp_client, do_debug, - "[DHCPv4] ", NULL, dhcp_priority); - - netconfig->dhcp6_client = l_dhcp6_client_new(ifindex); - l_dhcp6_client_set_event_handler(netconfig->dhcp6_client, - netconfig_dhcp6_event_handler, - netconfig, NULL); - l_dhcp6_client_set_lla_randomized(netconfig->dhcp6_client, true); - l_dhcp6_client_set_nodelay(netconfig->dhcp6_client, true); - l_dhcp6_client_set_rtnl(netconfig->dhcp6_client, rtnl); + l_netconfig_set_event_handler(netconfig->nc, netconfig_event_handler, + netconfig, NULL); - if (getenv("IWD_DHCP_DEBUG")) - l_dhcp6_client_set_debug(netconfig->dhcp6_client, do_debug, - "[DHCPv6] ", NULL); + l_dhcp_client_set_debug(l_netconfig_get_dhcp_client(netconfig->nc), + do_debug, "[DHCPv4] ", NULL, dhcp_priority); - icmp6 = l_dhcp6_client_get_icmp6(netconfig->dhcp6_client); - l_icmp6_client_set_rtnl(icmp6, rtnl); - l_icmp6_client_set_route_priority(icmp6, ROUTE_PRIORITY_OFFSET); + dhcp6 = l_netconfig_get_dhcp6_client(netconfig->nc); + l_dhcp6_client_set_lla_randomized(dhcp6, true); + l_dhcp6_client_set_nodelay(dhcp6, true); - l_queue_push_tail(netconfig_list, netconfig); + if (debug_level) + l_dhcp6_client_set_debug(dhcp6, do_debug, "[DHCPv6] ", NULL); - sysfs_write_ipv6_setting(netdev_get_name(netdev), "accept_ra", "0"); - sysfs_write_ipv6_setting(netdev_get_name(netdev), "disable_ipv6", "1"); + l_netconfig_set_route_priority(netconfig->nc, ROUTE_PRIORITY_OFFSET); return netconfig; } void netconfig_destroy(struct netconfig *netconfig) { - if (!netconfig_list) - return; - l_debug(""); - l_queue_remove(netconfig_list, netconfig); - netconfig_reset(netconfig); resolve_free(netconfig->resolve); netconfig_free(netconfig); @@ -1710,43 +864,8 @@ bool netconfig_enabled(void) static int netconfig_init(void) { - uint32_t r; - - if (netconfig_list) - return -EALREADY; - rtnl = iwd_get_rtnl(); - r = l_netlink_register(rtnl, RTNLGRP_IPV4_IFADDR, - netconfig_ifaddr_notify, NULL, NULL); - if (!r) { - l_error("netconfig: Failed to register for RTNL link address" - " notifications."); - goto error; - } - - r = l_rtnl_ifaddr4_dump(rtnl, netconfig_ifaddr_cmd_cb, NULL, NULL); - if (!r) { - l_error("netconfig: Failed to get addresses from RTNL link."); - goto error; - } - - r = l_netlink_register(rtnl, RTNLGRP_IPV6_IFADDR, - netconfig_ifaddr_ipv6_notify, NULL, NULL); - if (!r) { - l_error("netconfig: Failed to register for RTNL link IPv6 " - "address notifications."); - goto error; - } - - r = l_rtnl_ifaddr6_dump(rtnl, netconfig_ifaddr_ipv6_cmd_cb, NULL, - NULL); - if (!r) { - l_error("netconfig: Failed to get IPv6 addresses from RTNL" - " link."); - goto error; - } - if (!l_settings_get_uint(iwd_get_config(), "Network", "RoutePriorityOffset", &ROUTE_PRIORITY_OFFSET)) @@ -1757,24 +876,12 @@ static int netconfig_init(void) &ipv6_enabled)) ipv6_enabled = false; - netconfig_list = l_queue_new(); - return 0; - -error: - rtnl = NULL; - - return r; } static void netconfig_exit(void) { - if (!netconfig_list) - return; - rtnl = NULL; - - l_queue_destroy(netconfig_list, netconfig_free); } IWD_MODULE(netconfig, netconfig_init, netconfig_exit) diff --git a/src/netconfig.h b/src/netconfig.h index c9ac6f8f..b42e9cc8 100644 --- a/src/netconfig.h +++ b/src/netconfig.h @@ -26,6 +26,7 @@ struct ie_fils_ip_addr_response_info; enum netconfig_event { NETCONFIG_EVENT_CONNECTED, + NETCONFIG_EVENT_FAILED, }; typedef void (*netconfig_notify_func_t)(enum netconfig_event event, diff --git a/src/station.c b/src/station.c index e5972269..e02b68f8 100644 --- a/src/station.c +++ b/src/station.c @@ -2011,6 +2011,73 @@ delayed_retry: station_roam_retry(station); } +static void station_connect_failed(struct station *station, int error, + bool during_eapol) +{ + bool continue_autoconnect; + + if (station->connect_pending) { + struct l_dbus_message *reply; + + if (error == -ECANCELED) + reply = dbus_error_aborted(station->connect_pending); + else + reply = dbus_error_failed(station->connect_pending); + + dbus_pending_reply(&station->connect_pending, reply); + } + + if (error == -ECANCELED) + return; + + continue_autoconnect = station->state == STATION_STATE_CONNECTING_AUTO; + + if (station->state == STATION_STATE_CONNECTING) + network_connect_failed(station->connected_network, + during_eapol); + + station_reset_connection_state(station); + station_enter_state(station, STATION_STATE_DISCONNECTED); + + if (continue_autoconnect) { + if (station_autoconnect_next(station) < 0) { + l_debug("Nothing left on autoconnect list"); + station_enter_state(station, + STATION_STATE_AUTOCONNECT_FULL); + } + + return; + } + + if (station->autoconnect) + station_enter_state(station, STATION_STATE_AUTOCONNECT_QUICK); +} + +static void station_disconnect_on_error_cb(struct netdev *netdev, bool success, + void *user_data) +{ + struct station *station = user_data; + bool continue_autoconnect; + + station_enter_state(station, STATION_STATE_DISCONNECTED); + + continue_autoconnect = station->state == STATION_STATE_CONNECTING_AUTO; + + if (continue_autoconnect) { + if (station_autoconnect_next(station) < 0) { + l_debug("Nothing left on autoconnect list"); + station_enter_state(station, + STATION_STATE_AUTOCONNECT_FULL); + } + + return; + } + + if (station->autoconnect) + station_enter_state(station, STATION_STATE_AUTOCONNECT_QUICK); +} + + static void station_netconfig_event_handler(enum netconfig_event event, void *user_data) { @@ -2019,7 +2086,32 @@ static void station_netconfig_event_handler(enum netconfig_event event, switch (event) { case NETCONFIG_EVENT_CONNECTED: station_enter_state(station, STATION_STATE_CONNECTED); + break; + case NETCONFIG_EVENT_FAILED: + if (station->connect_pending) { + struct l_dbus_message *reply = dbus_error_failed( + station->connect_pending); + dbus_pending_reply(&station->connect_pending, reply); + } + + if (L_IN_SET(station->state, STATION_STATE_CONNECTING, + STATION_STATE_CONNECTING_AUTO)) + network_connect_failed(station->connected_network, + false); + + /* + * TODO: if in STATION_STATE_CONNECTING_AUTO, continue with + * the previous autoconnect list after disconnect completes. + */ + + netdev_disconnect(station->netdev, + station_disconnect_on_error_cb, + station); + + station_reset_connection_state(station); + + station_enter_state(station, STATION_STATE_DISCONNECTING); break; default: l_error("station: Unsupported netconfig event: %d.", event); @@ -2899,7 +2991,6 @@ static void station_connect_cb(struct netdev *netdev, enum netdev_result result, void *event_data, void *user_data) { struct station *station = user_data; - bool continue_autoconnect; l_debug("%u, result: %d", netdev_get_ifindex(station->netdev), result); @@ -2925,43 +3016,10 @@ static void station_connect_cb(struct netdev *netdev, enum netdev_result result, break; } - if (station->connect_pending) { - struct l_dbus_message *reply; - - if (result == NETDEV_RESULT_ABORTED) - reply = dbus_error_aborted(station->connect_pending); - else - reply = dbus_error_failed(station->connect_pending); - - dbus_pending_reply(&station->connect_pending, reply); - } - - if (result == NETDEV_RESULT_ABORTED) - return; - - continue_autoconnect = station->state == STATION_STATE_CONNECTING_AUTO; - - if (station->state == STATION_STATE_CONNECTING) { - bool during_eapol = result == NETDEV_RESULT_HANDSHAKE_FAILED; - network_connect_failed(station->connected_network, - during_eapol); - } - - station_reset_connection_state(station); - station_enter_state(station, STATION_STATE_DISCONNECTED); - - if (continue_autoconnect) { - if (station_autoconnect_next(station) < 0) { - l_debug("Nothing left on autoconnect list"); - station_enter_state(station, - STATION_STATE_AUTOCONNECT_FULL); - } - - return; - } - - if (station->autoconnect) - station_enter_state(station, STATION_STATE_AUTOCONNECT_QUICK); + station_connect_failed(station, + result == NETDEV_RESULT_ABORTED ? + -ECANCELED : -EIO, + result == NETDEV_RESULT_HANDSHAKE_FAILED); } static void station_disconnect_event(struct station *station, void *event_data) From patchwork Thu Jun 16 00:02:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12883098 Received: from mail-wm1-f49.google.com (mail-wm1-f49.google.com [209.85.128.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 484187E for ; Thu, 16 Jun 2022 00:02:56 +0000 (UTC) Received: by mail-wm1-f49.google.com with SMTP id i17-20020a7bc951000000b0039c4760ec3fso2788560wml.0 for ; Wed, 15 Jun 2022 17:02:56 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=WfIu77EE2skJlGFtHb5T0jhAelHy2rS2ES8KAplz1mg=; b=mnSLCc9N1E/M8DzMiRaIPowItFHFOX4lieXiXOOnzdhC4g9VRjPk8f3NYJ6Br7kuVn CbZc2h43bm/wFncFqxtxMEEPCN/17u6NFfZXkTlCaTEyRZlyeO063/AbNSX1A03klgxh wDetGknzPb1NOz0QCUT+aMUXstgEnoCFz4dow+KsYOmMWe3jHukCSNp5pCZ3S08rP/Up JwfIyPllTRAlnv4J9uFGn/4yviXPIJtFuqiv5AGz5eKI8CPXp4MQIX5+ShN9gjjpUjwZ oCCmNIvUnVKKVzzZBCycMFGbWyEEgXqBZ5Fog3TGJAB3oN9xv0mjxuq/nAbjdXnvG8UT Qr2Q== X-Gm-Message-State: AOAM530Tmc+5mK65EepbQ+Se5cR4C+NEy3oUs17ZqBfawCY9NIlqdpZu X9NcCY5nFSUgz4A1WL/7fY37S20P0Hk= X-Google-Smtp-Source: ABdhPJzdjUYrr2lGZWY7h3YAAnsgeYuXYhZl6y1nFNTrtEJ9uNMFi0ZRQIwhrc/sHwSlfuWdZt4/7Q== X-Received: by 2002:a05:600c:4e88:b0:39c:7c53:d7ff with SMTP id f8-20020a05600c4e8800b0039c7c53d7ffmr13029665wmq.176.1655337774166; Wed, 15 Jun 2022 17:02:54 -0700 (PDT) Received: from iss.Home ([82.213.231.20]) by smtp.gmail.com with ESMTPSA id az10-20020adfe18a000000b00210396b2eaesm337452wrb.45.2022.06.15.17.02.53 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Jun 2022 17:02:53 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 14/15] autotests: Add bad netconfig settings scenario Date: Thu, 16 Jun 2022 02:02:30 +0200 Message-Id: <20220616000231.1966008-14-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220616000231.1966008-1-andrew.zaborowski@intel.com> References: <20220616000231.1966008-1-andrew.zaborowski@intel.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 --- autotests/testNetconfig/connection_test.py | 30 +++++++++++++++++++++- autotests/testNetconfig/mismatch.psk | 7 +++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 autotests/testNetconfig/mismatch.psk diff --git a/autotests/testNetconfig/connection_test.py b/autotests/testNetconfig/connection_test.py index 4b05c745..837b19ec 100644 --- a/autotests/testNetconfig/connection_test.py +++ b/autotests/testNetconfig/connection_test.py @@ -92,6 +92,35 @@ class Test(unittest.TestCase): wd.unregister_psk_agent(psk_agent) + def test_addr_type_error(self): + IWD.copy_to_storage('mismatch.psk', name='ssidTKIP.psk') + wd = IWD(True) + + psk_agent = PSKAgent("secret123") + wd.register_psk_agent(psk_agent) + + devices = wd.list_devices(1) + device = devices[0] + + ordered_network = device.get_ordered_network('ssidTKIP') + + self.assertEqual(ordered_network.type, NetworkType.psk) + + condition = 'not obj.connected' + wd.wait_for_object_condition(ordered_network.network_object, condition) + + # Ideally we want to check that this errors out at an early phase, especially + # before any radio operations, due to netconfig setting validation, but this is + # tricky to ensure. Also ideally this would happen even before asking the user + # for the passphrase which is easier to ensure in the tests, but currently IWD + # asks for the PSK before control reaches station.c. + self.assertRaises(iwd.InvalidArgumentsEx, ordered_network.network_object.connect) + + wd.unregister_psk_agent(psk_agent) + + def tearDown(self): + IWD.clear_storage() + @classmethod def setUpClass(cls): def remove_lease4(): @@ -147,7 +176,6 @@ class Test(unittest.TestCase): @classmethod def tearDownClass(cls): - IWD.clear_storage() ctx.stop_process(cls.dhcpd_pid) cls.dhcpd_pid = None ctx.stop_process(cls.dhcpd6_pid) diff --git a/autotests/testNetconfig/mismatch.psk b/autotests/testNetconfig/mismatch.psk new file mode 100644 index 00000000..f8920b7c --- /dev/null +++ b/autotests/testNetconfig/mismatch.psk @@ -0,0 +1,7 @@ +[IPv6] +# IPv4 addresses where IPv6 are expected +Address=192.168.1.10 +Gateway=192.168.1.1 + +[Settings] +AutoConnect=false From patchwork Thu Jun 16 00:02:31 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Zaborowski X-Patchwork-Id: 12883099 Received: from mail-wm1-f44.google.com (mail-wm1-f44.google.com [209.85.128.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E04F57E for ; Thu, 16 Jun 2022 00:02:57 +0000 (UTC) Received: by mail-wm1-f44.google.com with SMTP id z17so7114295wmi.1 for ; Wed, 15 Jun 2022 17:02:57 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=bZoN4Uk55zDRkTMTx/ixyAGwGOM3Q/TwB11S0OKmWVA=; b=3TzF6YWZsqqRLVtf0MaWv4Wdi1NvP6KOodbHqlKW7SYceCk8jwKTBOh5Y4AG3jGO8g 7ey6UWfM1r6dyB5m6zYVSQjnb1qsRGtkbJ6gKMwp5BSI7xDDlPFe/qo+asDC5jNUptnP rU34e7wvs2pOtWdsPSn1Ur8CRw+C7vfQ6PUizWWLes0AFQXweDPesKl1PQ+9s6uPZgFV 2I5W6uPLyH0lsIMmZgp9ambYCK9k+I28bdc2XKk0190FuGF6hVngR2Ug+fYoXtLbTBHg Qw1Fknr8inAuhXkvmL4048oWlj2HtfeNbz+KhFM8GmJtl5TtRnaPFHZINAzS/d9vpvzt 6+2A== X-Gm-Message-State: AJIora9SYS3UUzDjLCPi62yGc3Heb4pRYPKkpnUc97oJ9A/Zmb/CYCrC w1GGgRN+cM3jyifo2a7pak2yvJOAoU0= X-Google-Smtp-Source: AGRyM1uSxEayM2qLJCC7k6MjHB5IttfVY7gcokbbk3GIqyO9QZm2upwPBNC6ZAPQ+WfbQymlooNg/A== X-Received: by 2002:a05:600c:3553:b0:39c:63a3:f54a with SMTP id i19-20020a05600c355300b0039c63a3f54amr2019977wmq.61.1655337775835; Wed, 15 Jun 2022 17:02:55 -0700 (PDT) Received: from iss.Home ([82.213.231.20]) by smtp.gmail.com with ESMTPSA id az10-20020adfe18a000000b00210396b2eaesm337452wrb.45.2022.06.15.17.02.54 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Jun 2022 17:02:55 -0700 (PDT) From: Andrew Zaborowski To: iwd@lists.linux.dev Subject: [PATCH 15/15] autotests: In testNetconfig verify routes from RIOs Date: Thu, 16 Jun 2022 02:02:31 +0200 Message-Id: <20220616000231.1966008-15-andrew.zaborowski@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220616000231.1966008-1-andrew.zaborowski@intel.com> References: <20220616000231.1966008-1-andrew.zaborowski@intel.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Verify that IWD with NetworkConfigurationEnabled creates the off-link routes for Route Information Options in the Router Advertisements. Sending this last because these options are not supported by current netconfig code and the test should fail without the l_netconfig patch. --- autotests/testNetconfig/connection_test.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/autotests/testNetconfig/connection_test.py b/autotests/testNetconfig/connection_test.py index 837b19ec..9c1d2efa 100644 --- a/autotests/testNetconfig/connection_test.py +++ b/autotests/testNetconfig/connection_test.py @@ -72,6 +72,15 @@ class Test(unittest.TestCase): # On-link prefix testutil.RouteInfo(dst=socket.inet_pton(socket.AF_INET6, '3ffe:501:ffff:100::'), plen=72, flags=1, ifname=ifname), + # Router for an off-link prefix, medium preference + testutil.RouteInfo(dst=socket.inet_pton(socket.AF_INET6, '3ffe:501:ffff:300::'), plen=64, + gw=router_ll_addr, flags=3, ifname=ifname), + # Router for an off-link prefix, high preference + testutil.RouteInfo(dst=socket.inet_pton(socket.AF_INET6, '3ffe:501:ffff:400::'), plen=65, + gw=router_ll_addr, flags=3, ifname=ifname), + # Router for an off-link prefix, low preference + testutil.RouteInfo(dst=socket.inet_pton(socket.AF_INET6, '3ffe:501:ffff:500::'), plen=66, + gw=router_ll_addr, flags=3, ifname=ifname) } self.maxDiff = None self.assertEqual(expected_routes4, set(testutil.get_routes4(ifname))) @@ -166,6 +175,9 @@ class Test(unittest.TestCase): AdvSendAdvert on; AdvManagedFlag on; prefix 3ffe:501:ffff:100::/72 { AdvAutonomous off; }; + route 3ffe:501:ffff:300::/64 {}; + route 3ffe:501:ffff:400::/65 { AdvRoutePreference low; }; + route 3ffe:501:ffff:500::/66 { AdvRoutePreference high; }; };''') config.close() cls.radvd_pid = ctx.start_process(['radvd', '-n', '-d5', '-p', '/tmp/radvd.pid', '-C', '/tmp/radvd.conf'])