]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-address.c
networkd: store netmask and mac address explicitly
[thirdparty/systemd.git] / src / network / networkd-address.c
CommitLineData
f579559b
TG
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 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 <net/if.h>
23
24#include "networkd.h"
25
26#include "utf8.h"
27#include "util.h"
28#include "conf-parser.h"
29#include "net-util.h"
30
31int address_new(Network *network, Address **ret) {
32 _cleanup_address_free_ Address *address = NULL;
33
34 address = new0(Address, 1);
35 if (!address)
36 return -ENOMEM;
37
38 address->network = network;
39
40 LIST_PREPEND(addresses, network->addresses, address);
41
42 *ret = address;
43 address = NULL;
44
45 return 0;
46}
47
48void address_free(Address *address) {
49 if (!address)
50 return;
51
52 LIST_REMOVE(addresses, address->network->addresses, address);
53
54 free(address->label);
55 free(address);
56}
57
58int address_configure(Manager *manager, Address *address, Link *link) {
59 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
60 int r;
61
62 r = sd_rtnl_message_addr_new(RTM_NEWADDR, link->ifindex,
63 address->family, address->prefixlen,
64 IFA_F_PERMANENT, RT_SCOPE_UNIVERSE, &req);
65 if (r < 0) {
66 log_error("Could not allocate RTM_NEWADDR message: %s",
67 strerror(-r));
68 return r;
69 }
70
71 r = sd_rtnl_message_append(req, IFA_LOCAL, &address->in_addr);
72 if (r < 0) {
73 log_error("Could not append IFA_LOCAL attribute: %s",
74 strerror(-r));
75 return r;
76 }
77
78 if (address->family == AF_INET) {
79 struct in_addr broadcast;
80
8cd11a0f 81 broadcast.s_addr = address->in_addr.in.s_addr | address->netmask.s_addr;
f579559b
TG
82
83 r = sd_rtnl_message_append(req, IFA_BROADCAST, &broadcast);
84 if (r < 0) {
85 log_error("Could not append IFA_BROADCAST attribute: %s",
86 strerror(-r));
87 return r;
88 }
89 }
90
91 if (address->label) {
92 r = sd_rtnl_message_append(req, IFA_LABEL, address->label);
93 if (r < 0) {
94 log_error("Could not append IFA_LABEL attribute: %s",
95 strerror(-r));
96 return r;
97 }
98 }
99
fe4824e0 100 r = sd_rtnl_call(manager->rtnl, req, 0, NULL);
f579559b
TG
101 if (r < 0) {
102 log_error("Could not configure address: %s", strerror(-r));
103 return r != -EEXIST ? r : 0;
104 }
105
106 log_info("Configured interface address");
107
108 return 0;
109}
110
111int config_parse_address(const char *unit,
112 const char *filename,
113 unsigned line,
114 const char *section,
115 const char *lvalue,
116 int ltype,
117 const char *rvalue,
118 void *data,
119 void *userdata) {
120 _cleanup_address_free_ Address *n = NULL;
121 _cleanup_free_ char *address = NULL;
122 const char *e;
123 int r;
124
125 assert(filename);
126 assert(lvalue);
127 assert(rvalue);
128 assert(data);
129
130 r = address_new(userdata, &n);
131 if (r < 0)
132 return r;
133
134 /* Address=address/prefixlen */
135
136 /* prefixlen */
137 e = strchr(rvalue, '/');
138 if (e) {
139 unsigned i;
140 r = safe_atou(e + 1, &i);
141 if (r < 0) {
142 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
143 "Interface prefix length is invalid, "
144 "ignoring assignment: %s", e + 1);
145 return 0;
146 }
147
148 n->prefixlen = (unsigned char) i;
8cd11a0f
TG
149 n->netmask.s_addr = htonl(0xfffffffflu >> n->prefixlen);
150
f579559b
TG
151 address = strndup(rvalue, e - rvalue);
152 if (!address)
153 return log_oom();
154 } else {
155 address = strdup(rvalue);
156 if (!address)
157 return log_oom();
158 }
159
160 r = net_parse_inaddr(address, &n->family, &n->in_addr);
161 if (r < 0) {
162 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
163 "Address is invalid, ignoring assignment: %s", address);
164 return 0;
165 }
166
167 n = NULL;
168
169 return 0;
170}