-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "sd-netlink.h"
+#include "af-list.h"
#include "alloc-util.h"
#include "fd-util.h"
#include "firewall-util.h"
memcpy(v, e, split - e);
v[split - e] = 0;
- r = safe_atou16(v, &host_port);
- if (r < 0 || host_port <= 0)
+ r = parse_ip_port(v, &host_port);
+ if (r < 0)
return -EINVAL;
- r = safe_atou16(split + 1, &container_port);
+ r = parse_ip_port(split + 1, &container_port);
} else {
- r = safe_atou16(e, &container_port);
+ r = parse_ip_port(e, &container_port);
host_port = container_port;
}
- if (r < 0 || container_port <= 0)
- return -EINVAL;
+ if (r < 0)
+ return r;
LIST_FOREACH(ports, p, *l)
if (p->protocol == protocol && p->host_port == host_port)
if (!p)
return -ENOMEM;
- p->protocol = protocol;
- p->host_port = host_port;
- p->container_port = container_port;
+ *p = (ExposePort) {
+ .protocol = protocol,
+ .host_port = host_port,
+ .container_port = container_port,
+ };
LIST_PREPEND(ports, *l, p);
}
}
-int expose_port_flush(ExposePort* l, union in_addr_union *exposed) {
+int expose_port_flush(FirewallContext **fw_ctx, ExposePort* l, int af, union in_addr_union *exposed) {
ExposePort *p;
- int r, af = AF_INET;
+ int r;
assert(exposed);
if (!l)
return 0;
- if (in_addr_is_null(af, exposed))
+ if (!in_addr_is_set(af, exposed))
return 0;
log_debug("Lost IP address.");
LIST_FOREACH(ports, p, l) {
- r = fw_add_local_dnat(false,
+ r = fw_add_local_dnat(fw_ctx,
+ false,
af,
p->protocol,
- NULL,
- NULL, 0,
- NULL, 0,
p->host_port,
exposed,
p->container_port,
NULL);
if (r < 0)
- log_warning_errno(r, "Failed to modify firewall: %m");
+ log_warning_errno(r, "Failed to modify %s firewall: %m", af_to_name(af));
}
*exposed = IN_ADDR_NULL;
return 0;
}
-int expose_port_execute(sd_netlink *rtnl, ExposePort *l, union in_addr_union *exposed) {
+int expose_port_execute(sd_netlink *rtnl, FirewallContext **fw_ctx, ExposePort *l, int af, union in_addr_union *exposed) {
_cleanup_free_ struct local_address *addresses = NULL;
- _cleanup_free_ char *pretty = NULL;
union in_addr_union new_exposed;
ExposePort *p;
bool add;
- int af = AF_INET, r;
+ int r;
assert(exposed);
addresses[0].scope < RT_SCOPE_LINK;
if (!add)
- return expose_port_flush(l, exposed);
+ return expose_port_flush(fw_ctx, l, af, exposed);
new_exposed = addresses[0].address;
if (in_addr_equal(af, exposed, &new_exposed))
return 0;
- in_addr_to_string(af, &new_exposed, &pretty);
- log_debug("New container IP is %s.", strna(pretty));
+ if (DEBUG_LOGGING) {
+ _cleanup_free_ char *pretty = NULL;
+ in_addr_to_string(af, &new_exposed, &pretty);
+ log_debug("New container IP is %s.", strna(pretty));
+ }
LIST_FOREACH(ports, p, l) {
- r = fw_add_local_dnat(true,
+ r = fw_add_local_dnat(fw_ctx,
+ true,
af,
p->protocol,
- NULL,
- NULL, 0,
- NULL, 0,
p->host_port,
&new_exposed,
p->container_port,
- in_addr_is_null(af, exposed) ? NULL : exposed);
+ in_addr_is_set(af, exposed) ? exposed : NULL);
if (r < 0)
- log_warning_errno(r, "Failed to modify firewall: %m");
+ log_warning_errno(r, "Failed to modify %s firewall: %m", af_to_name(af));
}
*exposed = new_exposed;
sd_event *event,
int recv_fd,
sd_netlink_message_handler_t handler,
- union in_addr_union *exposed,
+ void *userdata,
sd_netlink **ret) {
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
int fd, r;
assert(event);
return log_error_errno(r, "Failed to create rtnl object: %m");
}
- r = sd_netlink_add_match(rtnl, RTM_NEWADDR, handler, exposed);
+ r = sd_netlink_add_match(rtnl, NULL, RTM_NEWADDR, handler, NULL, userdata, "nspawn-NEWADDR");
if (r < 0)
return log_error_errno(r, "Failed to subscribe to RTM_NEWADDR messages: %m");
- r = sd_netlink_add_match(rtnl, RTM_DELADDR, handler, exposed);
+ r = sd_netlink_add_match(rtnl, NULL, RTM_DELADDR, handler, NULL, userdata, "nspawn-DELADDR");
if (r < 0)
return log_error_errno(r, "Failed to subscribe to RTM_DELADDR messages: %m");
r = sd_netlink_attach_event(rtnl, event, 0);
if (r < 0)
- return log_error_errno(r, "Failed to add to even loop: %m");
+ return log_error_errno(r, "Failed to add to event loop: %m");
- *ret = rtnl;
- rtnl = NULL;
+ *ret = TAKE_PTR(rtnl);
return 0;
}