chiark / gitweb /
util: unify SO_PEERCRED/SO_PEERSEC invocations
[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) {
44                 if (!dev_mac || memcmp(match_mac, ether_aton(dev_mac), ETH_ALEN)) {
45                         log_debug("Interface MAC address (%s) did not match MACAddress=%s",
46                                   dev_mac, ether_ntoa(match_mac));
47                         return 0;
48                 }
49         }
50
51         if (match_path) {
52                 if (!streq_ptr(match_path, dev_path)) {
53                         log_debug("Interface persistent path (%s) did not match Path=%s",
54                                   dev_path, match_path);
55                         return 0;
56                 }
57         }
58
59         if (match_driver) {
60                 if (!streq_ptr(match_driver, dev_driver)) {
61                         log_debug("Interface device driver (%s) did not match Driver=%s",
62                                   dev_driver, match_driver);
63                         return 0;
64                 }
65         }
66
67         if (match_type) {
68                 if (!streq_ptr(match_type, dev_type)) {
69                         log_debug("Interface type (%s) did not match Type=%s",
70                                   dev_type, match_type);
71                         return 0;
72                 }
73         }
74
75         if (match_name) {
76                 if (!streq_ptr(match_name, dev_name)) {
77                         log_debug("Interface name (%s) did not match Name=%s",
78                                   dev_name, match_name);
79                         return 0;
80                 }
81         }
82
83         return 1;
84 }
85
86 int config_parse_ifname(const char *unit,
87                         const char *filename,
88                         unsigned line,
89                         const char *section,
90                         unsigned section_line,
91                         const char *lvalue,
92                         int ltype,
93                         const char *rvalue,
94                         void *data,
95                         void *userdata) {
96
97         char **s = data;
98         char *n;
99
100         assert(filename);
101         assert(lvalue);
102         assert(rvalue);
103         assert(data);
104
105         n = strdup(rvalue);
106         if (!n)
107                 return log_oom();
108
109         if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) {
110                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
111                            "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
112                 free(n);
113                 return 0;
114         }
115
116         free(*s);
117         if (*n)
118                 *s = n;
119         else {
120                 free(n);
121                 *s = NULL;
122         }
123
124         return 0;
125 }
126
127 int config_parse_ifalias(const char *unit,
128                          const char *filename,
129                          unsigned line,
130                          const char *section,
131                          unsigned section_line,
132                          const char *lvalue,
133                          int ltype,
134                          const char *rvalue,
135                          void *data,
136                          void *userdata) {
137
138         char **s = data;
139         char *n;
140
141         assert(filename);
142         assert(lvalue);
143         assert(rvalue);
144         assert(data);
145
146         n = strdup(rvalue);
147         if (!n)
148                 return log_oom();
149
150         if (!ascii_is_valid(n) || strlen(n) >= IFALIASZ) {
151                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
152                            "Interface alias is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
153                 free(n);
154                 return 0;
155         }
156
157         free(*s);
158         if (*n)
159                 *s = n;
160         else {
161                 free(n);
162                 *s = NULL;
163         }
164
165         return 0;
166 }
167
168 int config_parse_hwaddr(const char *unit,
169                         const char *filename,
170                         unsigned line,
171                         const char *section,
172                         unsigned section_line,
173                         const char *lvalue,
174                         int ltype,
175                         const char *rvalue,
176                         void *data,
177                         void *userdata) {
178         struct ether_addr **hwaddr = data;
179         struct ether_addr *n;
180         int r;
181
182         assert(filename);
183         assert(lvalue);
184         assert(rvalue);
185         assert(data);
186
187         n = new0(struct ether_addr, 1);
188         if (!n)
189                 return log_oom();
190
191         r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
192                    &n->ether_addr_octet[0],
193                    &n->ether_addr_octet[1],
194                    &n->ether_addr_octet[2],
195                    &n->ether_addr_octet[3],
196                    &n->ether_addr_octet[4],
197                    &n->ether_addr_octet[5]);
198         if (r != 6) {
199                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
200                            "Not a valid MAC address, ignoring assignment: %s", rvalue);
201                 free(n);
202                 return 0;
203         }
204
205         free(*hwaddr);
206         *hwaddr = n;
207
208         return 0;
209 }
210
211 int net_parse_inaddr(const char *address, unsigned char *family, void *dst) {
212         int r;
213
214         assert(address);
215         assert(family);
216         assert(dst);
217
218         /* IPv4 */
219         r = inet_pton(AF_INET, address, dst);
220         if (r > 0)
221                 *family = AF_INET; /* successfully parsed IPv4 address */
222         else  if (r < 0)
223                 return -errno;
224         else {
225                 /* not an IPv4 address, so let's try IPv6 */
226                 r = inet_pton(AF_INET6, address, dst);
227                 if (r > 0)
228                         *family = AF_INET6; /* successfully parsed IPv6 address */
229                 else if (r < 0)
230                         return -errno;
231                 else
232                         return -EINVAL;
233         }
234
235         return 0;
236 }