]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: Rename ModemManager .network section WRT tech, not project...
authorOleksandr Andrushchenko <andr2000@gmail.com>
Mon, 2 Mar 2026 15:01:31 +0000 (17:01 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 4 Mar 2026 11:42:19 +0000 (12:42 +0100)
and use dedicated knobs for every option used in
former SimpleConnectProperties.
New section is [MobileNetwork] with the following configuration options:

APN=
AllowedAuthenticationMechanisms==
User=
Password=
IPFamily=
AllowRoaming=
PIN=
OperatorId=

NEWS
man/systemd.network.xml
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
src/network/networkd-wwan-bus.c
src/network/networkd-wwan.c
src/network/networkd-wwan.h

diff --git a/NEWS b/NEWS
index 792aee47617b97b831967c155daa9eb37214a4a2..2862a224350f85c6a07a9ff922f666837ff718f6 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -241,11 +241,11 @@ CHANGES WITH 260 in spe:
         * MultiPathRoute= option now supports interface-bound ECMP routes.
 
         * systemd-networkd gained integration with ModemManager via the "simple
-          connect" protocol. A new [ModemManager] section has been added with
-          SimpleConnectProperties= (currently apn=, allowed-auth=, user=,
-          password=, ip-type=, allow-roaming=, pin=, and operator-id=),
-          RouteMetric=, and UseGateway= settings. This allows systemd-networkd
-          to establish a cellular modem connection to a broadband network.
+          connect" protocol. A new [MobileNetwork] section has been added with
+          APN=, AllowedAuthenticationMechanisms=, User=, Password=, IPFamily=,
+          AllowRoaming=, PIN=, OperatorId=, RouteMetric=, and UseGateway=
+          settings. This allows systemd-networkd to establish a cellular modem
+          connection to a broadband network.
 
         * systemd-networkd gained a pair of varlink methods
           io.systemd.Network.Link.Up()/Down(). 'networkctl up/down' now
index 3b08a292e0df0833bb1436458db0f23ed30f5216..58dae4f948c7e171617682f9221a8a5c445352d1 100644 (file)
@@ -6445,12 +6445,12 @@ ServerAddress=192.168.0.1/24</programlisting>
   </refsect1>
 
   <refsect1>
-    <title>[ModemManager] Section Options</title>
+    <title>[MobileNetwork] Section Options</title>
 
     <para>This section configures the default setting of the ModemManager integration. See
     <ulink url="https://modemmanager.org/docs/modemmanager/" /> for more information about ModemManager.</para>
 
-    <para>Regardless of the [ModemManager] section settings consider using the following for LTE modems (take into account
+    <para>Regardless of the [MobileNetwork] section settings consider using the following for LTE modems (take into account
     that LTE modems do not typically support LLDP because LLDP is a Layer 2 protocol for Ethernet networks and an LTE
     modem connects to a cellular network, not a local Ethernet LAN):
       <programlisting>[Network]
@@ -6460,75 +6460,89 @@ IPv6AcceptRA=no
       </programlisting>
     </para>
 
-    <para>The following options are available in the [ModemManager] section:</para>
+    <para>The following options are available in the [MobileNetwork] section:</para>
     <variablelist class='network-directives'>
       <varlistentry>
-        <term><varname>SimpleConnectProperties=</varname></term>
+        <term><varname>APN=</varname></term>
         <listitem>
-          <para>Specifies the white-space separated list of simple connect properties used to connect a modem. See
-          <ulink url="https://www.freedesktop.org/software/ModemManager/man/latest/mmcli.1.html" /> for more
-          information about simple connect. If no properties provided then the connection is not initiated.</para>
+          <para>An Access Point Name (APN) is the name of a gateway between a mobile network
+          (GSM, GPRS, 3G, 4G and 5G) and another computer network. Required in 3GPP.
+          Defaults to unset and no attempt to establish the connection is made.</para>
 
-          <varlistentry>
-            <term><option>apn</option>=<replaceable>NAME</replaceable></term>
-            <listitem><para>An Access Point Name (APN) is the name of a gateway between a mobile network
-            (GSM, GPRS, 3G, 4G and 5G) and another computer network. Required in 3GPP.</para>
-
-            <xi:include href="version-info.xml" xpointer="v260"/></listitem>
-          </varlistentry>
-
-          <varlistentry>
-            <term><option>allowed-auth</option>=<replaceable>METHOD</replaceable></term>
-            <listitem><para>Authentication method to use. Takes one of "none", "pap", "chap", "mschap", "mschapv2" or "eap".
-            Optional in 3GPP.</para>
+          <xi:include href="version-info.xml" xpointer="v260"/>
+        </listitem>
+      </varlistentry>
 
-            <xi:include href="version-info.xml" xpointer="v260"/></listitem>
-          </varlistentry>
+      <varlistentry>
+        <term><varname>AllowedAuthenticationMechanisms=</varname></term>
+        <listitem>
+          <para>Authentication method to use. Specifies the white-space separated list of
+          <literal>none</literal>, <literal>pap</literal>, <literal>chap</literal>,
+          <literal>mschap</literal>, <literal>mschapv2</literal>, or <literal>eap</literal>
+          methods. Optional in 3GPP. Defaults to unset and an automatically picked
+          authentication method will be used.</para>
 
-          <varlistentry>
-            <term><option>user</option>=<replaceable>NAME</replaceable></term>
-            <listitem><para>User name (if any) required by the network. Optional in 3GPP.</para>
+          <xi:include href="version-info.xml" xpointer="v260"/>
+        </listitem>
+      </varlistentry>
 
-            <xi:include href="version-info.xml" xpointer="v260"/></listitem>
-          </varlistentry>
+      <varlistentry>
+        <term><varname>User=</varname></term>
+        <listitem>
+          <para>User name (if any) required by the network. Optional in 3GPP.
+          Defaults to unset.</para>
 
-          <varlistentry>
-            <term><option>password</option>=<replaceable>PASSWORD</replaceable></term>
-            <listitem><para>Password (if any) required by the network. Optional in 3GPP.</para>
+          <xi:include href="version-info.xml" xpointer="v260"/>
+        </listitem>
+      </varlistentry>
 
-            <xi:include href="version-info.xml" xpointer="v260"/></listitem>
-          </varlistentry>
+      <varlistentry>
+        <term><varname>Password=</varname></term>
+        <listitem>
+          <para>Password (if any) required by the network. Optional in 3GPP.
+          Defaults to unset.</para>
 
-          <varlistentry>
-            <term><option>ip-type</option>=<replaceable>TYPE</replaceable></term>
-            <listitem><para>Addressing type. Takes one of "none", "ipv4", "ipv6", "ipv4v6" or "any".
-            Optional in 3GPP and CDMA.</para>
+          <xi:include href="version-info.xml" xpointer="v260"/>
+        </listitem>
+      </varlistentry>
 
-            <xi:include href="version-info.xml" xpointer="v260"/></listitem>
-          </varlistentry>
+      <varlistentry>
+        <term><varname>IPFamily=</varname></term>
+        <listitem>
+          <para>Addressing type. Takes one of <literal>ipv4</literal>, <literal>ipv6</literal>,
+          <literal>both</literal>, or <literal>any</literal>. Optional in 3GPP and CDMA.
+          Defaults to unset and automatically selected.</para>
 
-          <varlistentry>
-            <term><option>allow-roaming</option>=<replaceable>BOOL</replaceable></term>
-            <listitem><para>A boolean. When true, connection is allowed during roaming. When false,
-            connection is not allowed during roaming. Optional in 3GPP.</para>
+          <xi:include href="version-info.xml" xpointer="v260"/>
+        </listitem>
+      </varlistentry>
 
-            <xi:include href="version-info.xml" xpointer="v260"/></listitem>
-          </varlistentry>
+      <varlistentry>
+        <term><varname>AllowRoaming=</varname></term>
+        <listitem>
+          <para>A boolean. When true, connection is allowed during roaming. When false,
+          connection is not allowed during roaming.
+          Optional in 3GPP. Defaults to <literal>yes</literal>.</para>
 
-          <varlistentry>
-            <term><option>pin</option>=<replaceable>PIN</replaceable></term>
-            <listitem><para>SIM-PIN unlock code.</para>
+          <xi:include href="version-info.xml" xpointer="v260"/>
+        </listitem>
+      </varlistentry>
 
-            <xi:include href="version-info.xml" xpointer="v260"/></listitem>
-          </varlistentry>
+      <varlistentry>
+        <term><varname>PIN=</varname></term>
+        <listitem>
+          <para>SIM-PIN unlock code. Defaults to unset.</para>
 
-          <varlistentry>
-            <term><option>operator-id</option>=<replaceable>ID</replaceable></term>
-            <listitem><para>ETSI MCC-MNC of a network to force registration.</para>
+          <xi:include href="version-info.xml" xpointer="v260"/>
+        </listitem>
+      </varlistentry>
 
-            <xi:include href="version-info.xml" xpointer="v260"/></listitem>
-          </varlistentry>
+      <varlistentry>
+        <term><varname>OperatorId=</varname></term>
+        <listitem>
+          <para>ETSI MCC-MNC of a network to force registration. Defaults to unset.</para>
 
+          <xi:include href="version-info.xml" xpointer="v260"/>
         </listitem>
       </varlistentry>
 
@@ -6896,14 +6910,23 @@ LLDP=no
 LinkLocalAddressing=no
 IPv6AcceptRA=no
 
-[ModemManager]
-SimpleConnectProperties=apn=internet pin=1111
+[MobileNetwork]
+APN=internet
+AllowedAuthenticationMechanisms=none pap chap
+User=user
+Password=pass
+IPFamily=both
+AllowRoaming=no
+PIN=1111
+OperatorId=25503
 RouteMetric=30
 UseGateway=yes</programlisting>
 
       <para>This connects a cellular modem to a broadband network matched with the network interface <literal>wwan0</literal>,
-      with APN name <literal>internet</literal>, SIM card pin unlock code <literal>1111</literal> and sets up a default
-      gateway with route metric of 30.
+      with APN name <literal>internet</literal>, allowed authentication <literal>none</literal>, <literal>pcap</literal>, or
+      <literal>chap</literal>, user name <literal>user</literal>, their password <literal>pass</literal>, allows both IPv4 and IPv6,
+      does not allow roaming, SIM card pin unlock code <literal>1111</literal>, only allows connecting to operator with
+      MCC <literal>25503</literal>, and sets up a default gateway with route metric of 30.
       </para>
     </example>
   </refsect1>
index 10566b7a4ed8541c34d4f48461c72546ae645e4f..f1049cc7cc260f75aa942d70b396bdf261e0049e 100644 (file)
@@ -493,9 +493,16 @@ CAN.ClassicDataLengthCode,                       config_parse_can_control_mode,
 CAN.Termination,                                 config_parse_can_termination,                   0,                                      0
 IPoIB.Mode,                                      config_parse_ipoib_mode,                        0,                                      offsetof(Network, ipoib_mode)
 IPoIB.IgnoreUserspaceMulticastGroups,            config_parse_tristate,                          0,                                      offsetof(Network, ipoib_umcast)
-ModemManager.SimpleConnectProperties,            config_parse_strv,                              0,                                      offsetof(Network, mm_simple_connect_props)
-ModemManager.RouteMetric,                        config_parse_mm_route_metric,                   0,                                      0
-ModemManager.UseGateway,                         config_parse_tristate,                          0,                                      offsetof(Network, mm_use_gateway)
+MobileNetwork.APN,                               config_parse_string,                            CONFIG_PARSE_STRING_SAFE_AND_ASCII,     offsetof(Network, mm_apn)
+MobileNetwork.AllowRoaming,                      config_parse_bool,                              0,                                      offsetof(Network, mm_allow_roaming)
+MobileNetwork.AllowedAuthenticationMechanisms,   config_parse_mm_allowed_auth,                   0,                                      offsetof(Network, mm_allowed_auth)
+MobileNetwork.IPFamily,                          config_parse_mm_ip_family,                      0,                                      offsetof(Network, mm_ip_family)
+MobileNetwork.OperatorId,                        config_parse_string,                            CONFIG_PARSE_STRING_SAFE_AND_ASCII,     offsetof(Network, mm_operator_id)
+MobileNetwork.User,                              config_parse_string,                            CONFIG_PARSE_STRING_SAFE_AND_ASCII,     offsetof(Network, mm_user)
+MobileNetwork.Password,                          config_parse_string,                            CONFIG_PARSE_STRING_SAFE_AND_ASCII,     offsetof(Network, mm_password)
+MobileNetwork.PIN,                               config_parse_string,                            CONFIG_PARSE_STRING_SAFE_AND_ASCII,     offsetof(Network, mm_pin)
+MobileNetwork.RouteMetric,                       config_parse_mm_route_metric,                   0,                                      0
+MobileNetwork.UseGateway,                        config_parse_tristate,                          0,                                      offsetof(Network, mm_use_gateway)
 QDisc.Parent,                                    config_parse_qdisc_parent,                      _QDISC_KIND_INVALID,                    0
 QDisc.Handle,                                    config_parse_qdisc_handle,                      _QDISC_KIND_INVALID,                    0
 BFIFO.Parent,                                    config_parse_qdisc_parent,                      QDISC_KIND_BFIFO,                       0
index 8141a45432e45ff9570cec27b7569e72982b1773..1e159fa31027d1ba08f48ec09524fb519256a492 100644 (file)
@@ -513,6 +513,9 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
                 .ipoib_mode = _IP_OVER_INFINIBAND_MODE_INVALID,
                 .ipoib_umcast = -1,
 
+                .mm_allow_roaming = true,
+                .mm_allowed_auth = MM_BEARER_ALLOWED_AUTH_UNKNOWN,
+                .mm_ip_family = MM_BEARER_IP_FAMILY_NONE,
                 .mm_use_gateway = -1,
         };
 
@@ -553,7 +556,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
                         "LLDP\0"
                         "TrafficControlQueueingDiscipline\0"
                         "CAN\0"
-                        "ModemManager\0"
+                        "MobileNetwork\0"
                         "QDisc\0"
                         "BFIFO\0"
                         "CAKE\0"
@@ -851,7 +854,11 @@ static Network *network_free(Network *network) {
         hashmap_free(network->tclasses_by_section);
 
         /* ModemManager */
-        strv_free(network->mm_simple_connect_props);
+        free(network->mm_apn);
+        free(network->mm_operator_id);
+        free(network->mm_user);
+        free(network->mm_password);
+        free(network->mm_pin);
 
         return mfree(network);
 }
index dcd9f68e781971d4ca35f77b54c901f1e917133f..923828b2ea1e9b1a69ccb4f92c3b394b2475581f 100644 (file)
@@ -21,6 +21,7 @@
 #include "networkd-ndisc.h"
 #include "networkd-radv.h"
 #include "networkd-sysctl.h"
+#include "networkd-wwan-bus.h"
 #include "resolve-util.h"
 
 typedef enum KeepConfiguration {
@@ -416,7 +417,14 @@ typedef struct Network {
         char **ntp;
 
         /* ModemManager support */
-        char **mm_simple_connect_props;
+        char *mm_apn;
+        bool mm_allow_roaming;
+        MMBearerAllowedAuth mm_allowed_auth;
+        MMBearerIpFamily mm_ip_family;
+        char *mm_operator_id;
+        char *mm_user;
+        char *mm_password;
+        char *mm_pin;
         int mm_use_gateway;
         uint32_t mm_route_metric;
         bool mm_route_metric_set;
index d87cdd3441185e924f9decefe262cd4c508d5af4..5d9818987522e4016471fc37cb7bf295d1b34a07 100644 (file)
@@ -59,7 +59,6 @@
 #include "networkd-manager.h"
 #include "networkd-wwan.h"
 #include "networkd-wwan-bus.h"
-#include "parse-util.h"
 #include "string-util.h"
 #include "strv.h"
 
@@ -507,78 +506,6 @@ static int modem_connect_handler(sd_bus_message *message, void *userdata, sd_bus
         return 0;
 }
 
-static MMBearerIpFamily prop_iptype_lookup(const char *key) {
-        static const struct {
-                MMBearerIpFamily family;
-                const char *str;
-        } table[] = {
-                { MM_BEARER_IP_FAMILY_NONE,   "none"   },
-                { MM_BEARER_IP_FAMILY_IPV4,   "ipv4"   },
-                { MM_BEARER_IP_FAMILY_IPV6,   "ipv6"   },
-                { MM_BEARER_IP_FAMILY_IPV4V6, "ipv4v6" },
-                { MM_BEARER_IP_FAMILY_ANY,    "any"    },
-                {}
-        };
-
-        assert(key);
-
-        FOREACH_ELEMENT(item, table)
-                if (streq(item->str, key))
-                        return item->family;
-
-        log_warning("ModemManager: ignoring unknown ip-type: %s, using any", key);
-        return MM_BEARER_IP_FAMILY_ANY;
-}
-
-static MMBearerAllowedAuth prop_auth_lookup(const char *key) {
-        static const struct {
-                MMBearerAllowedAuth auth;
-                const char *str;
-        } table[] = {
-                { MM_BEARER_ALLOWED_AUTH_NONE,     "none"     },
-                { MM_BEARER_ALLOWED_AUTH_PAP,      "pap"      },
-                { MM_BEARER_ALLOWED_AUTH_CHAP,     "chap"     },
-                { MM_BEARER_ALLOWED_AUTH_MSCHAP,   "mschap"   },
-                { MM_BEARER_ALLOWED_AUTH_MSCHAPV2, "mschapv2" },
-                { MM_BEARER_ALLOWED_AUTH_EAP,      "eap"      },
-                {}
-        };
-
-        assert(key);
-
-        FOREACH_ELEMENT(item, table)
-                if (streq(item->str, key))
-                        return item->auth;
-
-        log_warning("ModemManager: ignoring unknown allowed-auth: %s, using none", key);
-        return MM_BEARER_ALLOWED_AUTH_NONE;
-}
-
-static const char* prop_type_lookup(const char *key) {
-        static const struct {
-                const char *prop;
-                const char *type;
-        } table[] = {
-                { "apn",           "s" },
-                { "allowed-auth",  "u" },
-                { "user",          "s" },
-                { "password",      "s" },
-                { "ip-type",       "u" },
-                { "allow-roaming", "b" },
-                { "pin",           "s" },
-                { "operator-id",   "s" },
-                {}
-        };
-
-        if (!key)
-                return NULL;
-
-        FOREACH_ELEMENT(item, table)
-                if (streq(item->prop, key))
-                        return item->type;
-        return NULL;
-}
-
 static int bus_call_method_async_props(
                 sd_bus *bus,
                 sd_bus_slot **slot,
@@ -591,6 +518,7 @@ static int bus_call_method_async_props(
                 Link *link) {
 
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+        Network *network = ASSERT_PTR(ASSERT_PTR(link)->network);
         int r;
 
         assert(bus);
@@ -603,38 +531,48 @@ static int bus_call_method_async_props(
         if (r < 0)
                 return bus_log_create_error(r);
 
-        STRV_FOREACH(prop, link->network->mm_simple_connect_props) {
-                const char *type;
-                _cleanup_free_ char *left = NULL, *right = NULL;
+        if (network->mm_apn) {
+                r = sd_bus_message_append(m, "{sv}", "apn", "s", network->mm_apn);
+                if (r < 0)
+                        return bus_log_create_error(r);
+        }
 
-                r = split_pair(*prop, "=", &left, &right);
+        r = sd_bus_message_append(m, "{sv}", "allow-roaming", "b", network->mm_allow_roaming);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        if (network->mm_allowed_auth != MM_BEARER_ALLOWED_AUTH_UNKNOWN) {
+                r = sd_bus_message_append(m, "{sv}", "allowed-auth", "u", (uint32_t) network->mm_allowed_auth);
                 if (r < 0)
-                        return log_warning_errno(SYNTHETIC_ERRNO(r),
-                                                 "ModemManager: failed to parse simple connect option: %s, file: %s",
-                                                 *prop, link->network->filename);
-
-                type = prop_type_lookup(left);
-                if (!type)
-                        return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
-                                                 "ModemManager: unknown simple connect option: %s, file: %s",
-                                                 *prop, link->network->filename);
-
-                if (streq(left, "ip-type")) {
-                        MMBearerIpFamily ip_type = prop_iptype_lookup(right);
-
-                        r = sd_bus_message_append(m, "{sv}", left, type, (uint32_t)ip_type);
-                } if (streq(left, "allowed-auth")) {
-                        MMBearerAllowedAuth auth = prop_auth_lookup(right);
-
-                        r = sd_bus_message_append(m, "{sv}", left, type, (uint32_t)auth);
-                } else if (streq(type, "b")) {
-                        r = parse_boolean(right);
-                        if (r < 0)
-                                return -EINVAL;
-                        r = sd_bus_message_append(m, "{sv}", left, type, r);
-                } else if (streq(type, "s"))
-                        r = sd_bus_message_append(m, "{sv}", left, type, right);
+                        return bus_log_create_error(r);
+        }
+
+        if (network->mm_ip_family != MM_BEARER_IP_FAMILY_NONE) {
+                r = sd_bus_message_append(m, "{sv}", "ip-type", "u", (uint32_t) network->mm_ip_family);
+                if (r < 0)
+                        return bus_log_create_error(r);
+        }
+
+        if (network->mm_operator_id) {
+                r = sd_bus_message_append(m, "{sv}", "operator-id", "s", network->mm_operator_id);
+                if (r < 0)
+                        return bus_log_create_error(r);
+        }
+
+        if (network->mm_user) {
+                r = sd_bus_message_append(m, "{sv}", "user", "s", network->mm_user);
+                if (r < 0)
+                        return bus_log_create_error(r);
+        }
+
+        if (network->mm_password) {
+                r = sd_bus_message_append(m, "{sv}", "password", "s", network->mm_password);
+                if (r < 0)
+                        return bus_log_create_error(r);
+        }
 
+        if (network->mm_pin) {
+                r = sd_bus_message_append(m, "{sv}", "pin", "s", network->mm_pin);
                 if (r < 0)
                         return bus_log_create_error(r);
         }
@@ -675,9 +613,9 @@ static void modem_simple_connect(Modem *modem) {
                 return (void) log_debug("ModemManager: no .network file provided for %s",
                                         modem->port_name);
 
-        /* Check if we are provided with simple connection properties */
-        if (!link->network->mm_simple_connect_props)
-                return (void) log_debug("ModemManager: no simple connect properties provided for %s",
+        /* Check if we are provided with at least APN which is required. */
+        if (!link->network->mm_apn)
+                return (void) log_debug("ModemManager: not enough simple connect properties provided for %s",
                                         modem->port_name);
 
         log_info("ModemManager: starting simple connect on %s %s interface %s",
index 2b10eb3e4ee960118d928000c15ebab30796c8cd..ccd72d0ee31b3581c188dddde685b47a40a78c97 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "alloc-util.h"
 #include "bus-util.h"
+#include "extract-word.h"
 #include "hashmap.h"
 #include "networkd-address.h"
 #include "networkd-dhcp4.h"
@@ -620,7 +621,7 @@ int config_parse_mm_route_metric(
                 void *data,
                 void *userdata) {
 
-        Network *network = userdata;
+        Network *network = ASSERT_PTR(userdata);
         int r;
 
         assert(filename);
@@ -639,3 +640,102 @@ int config_parse_mm_route_metric(
         network->mm_route_metric_set = true;
         return 0;
 }
+
+int config_parse_mm_allowed_auth(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        static const struct {
+                MMBearerAllowedAuth auth;
+                const char *str;
+        } allowed_auth_map[] = {
+                { MM_BEARER_ALLOWED_AUTH_NONE,     "none"     },
+                { MM_BEARER_ALLOWED_AUTH_PAP,      "pap"      },
+                { MM_BEARER_ALLOWED_AUTH_CHAP,     "chap"     },
+                { MM_BEARER_ALLOWED_AUTH_MSCHAP,   "mschap"   },
+                { MM_BEARER_ALLOWED_AUTH_MSCHAPV2, "mschapv2" },
+                { MM_BEARER_ALLOWED_AUTH_EAP,      "eap"      },
+        };
+        MMBearerAllowedAuth *allowed_auth = ASSERT_PTR(data);
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+
+        if (isempty(rvalue)) {
+                *allowed_auth = MM_BEARER_ALLOWED_AUTH_UNKNOWN;
+                return 0;
+        }
+
+        for (const char *p = rvalue;;) {
+                _cleanup_free_ char *auth = NULL;
+
+                r = extract_first_word(&p, &auth, /* separators */ NULL, /* flags */ 0);
+                if (r < 0)
+                        return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
+                if (r == 0)
+                        return 0;
+
+                bool found = false;
+                FOREACH_ELEMENT(i, allowed_auth_map)
+                        if (streq(auth, i->str)) {
+                                *allowed_auth |= i->auth;
+                                found = true;
+                                break;
+                        }
+
+                if (!found)
+                        log_syntax(unit, LOG_WARNING, filename, line, -EINVAL,
+                                   "Unknown auth value '%s', ignoring", auth);
+        }
+}
+
+int config_parse_mm_ip_family(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        static const struct {
+                MMBearerIpFamily family;
+                const char *str;
+        } ip_family_map[] = {
+                { MM_BEARER_IP_FAMILY_IPV4,   "ipv4" },
+                { MM_BEARER_IP_FAMILY_IPV6,   "ipv6" },
+                { MM_BEARER_IP_FAMILY_IPV4V6, "both" },
+                { MM_BEARER_IP_FAMILY_ANY,    "any"  },
+        };
+        MMBearerIpFamily *ip_family = ASSERT_PTR(data);
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+
+        if (isempty(rvalue)) {
+                *ip_family = MM_BEARER_IP_FAMILY_NONE;
+                return 0;
+        }
+
+        FOREACH_ELEMENT(i, ip_family_map)
+                if (streq(rvalue, i->str)) {
+                        *ip_family = i->family;
+                        return 0;
+                }
+
+        return log_syntax_parse_error(unit, filename, line, -EINVAL, lvalue, rvalue);
+}
index 962f76be2ec4008bf71726e085d580ec34e2d221..0542ac174d29dc8415017bd83bad884b3ac034c8 100644 (file)
@@ -77,4 +77,6 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Modem*, modem_free);
 int modem_get_by_path(Manager *m, const char *path, Modem **ret);
 int link_get_modem(Link *link, Modem **ret);
 
+CONFIG_PARSER_PROTOTYPE(config_parse_mm_allowed_auth);
+CONFIG_PARSER_PROTOTYPE(config_parse_mm_ip_family);
 CONFIG_PARSER_PROTOTYPE(config_parse_mm_route_metric);