chiark / gitweb /
networkd: link hash uses 64, not 32 bit keys
[elogind.git] / src / shared / net-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4  This file is part of systemd.
5
6  Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <netinet/ether.h>
23 #include <linux/if.h>
24 #include <arpa/inet.h>
25
26 #include "net-util.h"
27 #include "log.h"
28 #include "utf8.h"
29 #include "util.h"
30 #include "conf-parser.h"
31
32 bool net_match_config(const struct ether_addr *match_mac,
33                       const char *match_path,
34                       const char *match_driver,
35                       const char *match_type,
36                       const char *match_name,
37                       const char *dev_mac,
38                       const char *dev_path,
39                       const char *dev_driver,
40                       const char *dev_type,
41                       const char *dev_name) {
42
43         if (match_mac && (!dev_mac || memcmp(match_mac, ether_aton(dev_mac), ETH_ALEN)))
44                 return 0;
45
46         if (match_path && !streq_ptr(match_path, dev_path))
47                 return 0;
48
49         if (match_driver && !streq_ptr(match_driver, dev_driver))
50                 return 0;
51
52         if (match_type && !streq_ptr(match_type, dev_type))
53                 return 0;
54
55         if (match_name && !streq_ptr(match_name, dev_name))
56                 return 0;
57
58         return 1;
59 }
60
61 int config_parse_ifname(const char *unit,
62                         const char *filename,
63                         unsigned line,
64                         const char *section,
65                         unsigned section_line,
66                         const char *lvalue,
67                         int ltype,
68                         const char *rvalue,
69                         void *data,
70                         void *userdata) {
71
72         char **s = data;
73         char *n;
74
75         assert(filename);
76         assert(lvalue);
77         assert(rvalue);
78         assert(data);
79
80         n = strdup(rvalue);
81         if (!n)
82                 return log_oom();
83
84         if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) {
85                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
86                            "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
87                 free(n);
88                 return 0;
89         }
90
91         free(*s);
92         if (*n)
93                 *s = n;
94         else {
95                 free(n);
96                 *s = NULL;
97         }
98
99         return 0;
100 }
101
102 int config_parse_ifalias(const char *unit,
103                          const char *filename,
104                          unsigned line,
105                          const char *section,
106                          unsigned section_line,
107                          const char *lvalue,
108                          int ltype,
109                          const char *rvalue,
110                          void *data,
111                          void *userdata) {
112
113         char **s = data;
114         char *n;
115
116         assert(filename);
117         assert(lvalue);
118         assert(rvalue);
119         assert(data);
120
121         n = strdup(rvalue);
122         if (!n)
123                 return log_oom();
124
125         if (!ascii_is_valid(n) || strlen(n) >= IFALIASZ) {
126                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
127                            "Interface alias is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
128                 free(n);
129                 return 0;
130         }
131
132         free(*s);
133         if (*n)
134                 *s = n;
135         else {
136                 free(n);
137                 *s = NULL;
138         }
139
140         return 0;
141 }
142
143 int config_parse_hwaddr(const char *unit,
144                         const char *filename,
145                         unsigned line,
146                         const char *section,
147                         unsigned section_line,
148                         const char *lvalue,
149                         int ltype,
150                         const char *rvalue,
151                         void *data,
152                         void *userdata) {
153         struct ether_addr **hwaddr = data;
154         struct ether_addr *n;
155         int r;
156
157         assert(filename);
158         assert(lvalue);
159         assert(rvalue);
160         assert(data);
161
162         n = new0(struct ether_addr, 1);
163         if (!n)
164                 return log_oom();
165
166         r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
167                    &n->ether_addr_octet[0],
168                    &n->ether_addr_octet[1],
169                    &n->ether_addr_octet[2],
170                    &n->ether_addr_octet[3],
171                    &n->ether_addr_octet[4],
172                    &n->ether_addr_octet[5]);
173         if (r != 6) {
174                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
175                            "Not a valid MAC address, ignoring assignment: %s", rvalue);
176                 free(n);
177                 return 0;
178         }
179
180         free(*hwaddr);
181         *hwaddr = n;
182
183         return 0;
184 }
185
186 int net_parse_inaddr(const char *address, unsigned char *family, void *dst) {
187         int r;
188
189         assert(address);
190         assert(family);
191         assert(dst);
192
193         /* IPv4 */
194         r = inet_pton(AF_INET, address, dst);
195         if (r > 0)
196                 *family = AF_INET; /* successfully parsed IPv4 address */
197         else  if (r < 0)
198                 return -errno;
199         else {
200                 /* not an IPv4 address, so let's try IPv6 */
201                 r = inet_pton(AF_INET6, address, dst);
202                 if (r > 0)
203                         *family = AF_INET6; /* successfully parsed IPv6 address */
204                 else if (r < 0)
205                         return -errno;
206                 else
207                         return -EINVAL;
208         }
209
210         return 0;
211 }