1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include "alloc-util.h"
4 #include "netif-naming-scheme.h"
5 #include "proc-cmdline.h"
6 #include "string-util.h"
7 #include "string-table.h"
8 
9 #ifdef _DEFAULT_NET_NAMING_SCHEME_TEST
10 /* The primary purpose of this check is to verify that _DEFAULT_NET_NAMING_SCHEME_TEST
11  * is a valid identifier. If an invalid name is given during configuration, this will
12  * fail with a name error. */
13 assert_cc(_DEFAULT_NET_NAMING_SCHEME_TEST >= 0);
14 #endif
15 
16 static const NamingScheme naming_schemes[] = {
17         { "v238", NAMING_V238 },
18         { "v239", NAMING_V239 },
19         { "v240", NAMING_V240 },
20         { "v241", NAMING_V241 },
21         { "v243", NAMING_V243 },
22         { "v245", NAMING_V245 },
23         { "v247", NAMING_V247 },
24         { "v249", NAMING_V249 },
25         { "v250", NAMING_V250 },
26         { "v251", NAMING_V251 },
27         /* … add more schemes here, as the logic to name devices is updated … */
28 
29         EXTRA_NET_NAMING_MAP
30 };
31 
naming_scheme_from_name(const char * name)32 const NamingScheme* naming_scheme_from_name(const char *name) {
33         /* "latest" may either be defined explicitly by the extra map, in which case we will find it in
34          * the table like any other name. After iterating through the table, we check for "latest" again,
35          * which means that if not mapped explicitly, it maps to the last defined entry, whatever that is. */
36 
37         for (size_t i = 0; i < ELEMENTSOF(naming_schemes); i++)
38                 if (streq(naming_schemes[i].name, name))
39                         return naming_schemes + i;
40 
41         if (streq(name, "latest"))
42                 return naming_schemes + ELEMENTSOF(naming_schemes) - 1;
43 
44         return NULL;
45 }
46 
naming_scheme(void)47 const NamingScheme* naming_scheme(void) {
48         static const NamingScheme *cache = NULL;
49         _cleanup_free_ char *buffer = NULL;
50         const char *e, *k;
51 
52         if (cache)
53                 return cache;
54 
55         /* Acquire setting from the kernel command line */
56         (void) proc_cmdline_get_key("net.naming-scheme", 0, &buffer);
57 
58         /* Also acquire it from an env var */
59         e = getenv("NET_NAMING_SCHEME");
60         if (e) {
61                 if (*e == ':') {
62                         /* If prefixed with ':' the kernel cmdline takes precedence */
63                         k = buffer ?: e + 1;
64                 } else
65                         k = e; /* Otherwise the env var takes precedence */
66         } else
67                 k = buffer;
68 
69         if (k) {
70                 cache = naming_scheme_from_name(k);
71                 if (cache) {
72                         log_info("Using interface naming scheme '%s'.", cache->name);
73                         return cache;
74                 }
75 
76                 log_warning("Unknown interface naming scheme '%s' requested, ignoring.", k);
77         }
78 
79         cache = naming_scheme_from_name(DEFAULT_NET_NAMING_SCHEME);
80         assert(cache);
81         log_info("Using default interface naming scheme '%s'.", cache->name);
82 
83         return cache;
84 }
85 
86 static const char* const name_policy_table[_NAMEPOLICY_MAX] = {
87         [NAMEPOLICY_KERNEL] = "kernel",
88         [NAMEPOLICY_KEEP] = "keep",
89         [NAMEPOLICY_DATABASE] = "database",
90         [NAMEPOLICY_ONBOARD] = "onboard",
91         [NAMEPOLICY_SLOT] = "slot",
92         [NAMEPOLICY_PATH] = "path",
93         [NAMEPOLICY_MAC] = "mac",
94 };
95 
96 DEFINE_STRING_TABLE_LOOKUP(name_policy, NamePolicy);
97 
98 static const char* const alternative_names_policy_table[_NAMEPOLICY_MAX] = {
99         [NAMEPOLICY_DATABASE] = "database",
100         [NAMEPOLICY_ONBOARD] = "onboard",
101         [NAMEPOLICY_SLOT] = "slot",
102         [NAMEPOLICY_PATH] = "path",
103         [NAMEPOLICY_MAC] = "mac",
104 };
105 
106 DEFINE_STRING_TABLE_LOOKUP(alternative_names_policy, NamePolicy);
107