chiark / gitweb /
net-util: add inet address/family parsing
[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 <net/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                         const char *lvalue,
91                         int ltype,
92                         const char *rvalue,
93                         void *data,
94                         void *userdata) {
95
96         char **s = data;
97         char *n;
98
99         assert(filename);
100         assert(lvalue);
101         assert(rvalue);
102         assert(data);
103
104         n = strdup(rvalue);
105         if (!n)
106                 return log_oom();
107
108         if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) {
109                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
110                            "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
111                 free(n);
112                 return 0;
113         }
114
115         free(*s);
116         if (*n)
117                 *s = n;
118         else {
119                 free(n);
120                 *s = NULL;
121         }
122
123         return 0;
124 }
125
126 int config_parse_hwaddr(const char *unit,
127                         const char *filename,
128                         unsigned line,
129                         const char *section,
130                         const char *lvalue,
131                         int ltype,
132                         const char *rvalue,
133                         void *data,
134                         void *userdata) {
135         struct ether_addr **hwaddr = data;
136         struct ether_addr *n;
137         int r;
138
139         assert(filename);
140         assert(lvalue);
141         assert(rvalue);
142         assert(data);
143
144         n = new0(struct ether_addr, 1);
145         if (!n)
146                 return log_oom();
147
148         r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
149                    &n->ether_addr_octet[0],
150                    &n->ether_addr_octet[1],
151                    &n->ether_addr_octet[2],
152                    &n->ether_addr_octet[3],
153                    &n->ether_addr_octet[4],
154                    &n->ether_addr_octet[5]);
155         if (r != 6) {
156                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
157                            "Not a valid MAC address, ignoring assignment: %s", rvalue);
158                 free(n);
159                 return 0;
160         }
161
162         free(*hwaddr);
163         *hwaddr = n;
164
165         return 0;
166 }
167
168 int net_parse_inaddr(const char *address, unsigned char *family, void *dst) {
169         int r;
170
171         assert(address);
172         assert(family);
173         assert(dst);
174
175         /* IPv4 */
176         r = inet_pton(AF_INET, address, dst);
177         if (r > 0)
178                 *family = AF_INET; /* successfully parsed IPv4 address */
179         else  if (r < 0)
180                 return -errno;
181         else {
182                 /* not an IPv4 address, so let's try IPv6 */
183                 r = inet_pton(AF_INET6, address, dst);
184                 if (r > 0)
185                         *family = AF_INET6; /* successfully parsed IPv6 address */
186                 else if (r < 0)
187                         return -errno;
188                 else
189                         return -EINVAL;
190         }
191
192         return 0;
193 }