summaryrefslogtreecommitdiffhomepage
path: root/src/dhcpv4.c
diff options
context:
space:
mode:
authorHans Dedecker <dedeckeh@gmail.com>2018-05-07 15:49:13 +0200
committerHans Dedecker <dedeckeh@gmail.com>2018-05-15 22:14:42 +0200
commit4591b362e2435ea7ffcb6b02b1975d37b348268f (patch)
tree109db965f383891bf3a818b2d98738a0ba7b44f2 /src/dhcpv4.c
parent4983ee551a743e55bb2f2ec12ceab0ddba13eb2d (diff)
dhcpv4: improve error checking in dhcpv4_setup_interface()
Improve error checking fixing resource leakage detected by Coverity in CID 1433402 Signed-off-by: Hans Dedecker <dedeckeh@gmail.com>
Diffstat (limited to 'src/dhcpv4.c')
-rw-r--r--src/dhcpv4.c87
1 files changed, 65 insertions, 22 deletions
diff --git a/src/dhcpv4.c b/src/dhcpv4.c
index 35a3ad0..2b30307 100644
--- a/src/dhcpv4.c
+++ b/src/dhcpv4.c
@@ -71,6 +71,8 @@ int dhcpv4_init(void)
int dhcpv4_setup_interface(struct interface *iface, bool enable)
{
+ int ret = 0;
+
if (iface->dhcpv4_event.uloop.fd > 0) {
uloop_fd_delete(&iface->dhcpv4_event.uloop);
close(iface->dhcpv4_event.uloop.fd);
@@ -78,55 +80,96 @@ int dhcpv4_setup_interface(struct interface *iface, bool enable)
}
if (iface->dhcpv4 && enable) {
+ struct sockaddr_in bind_addr = {AF_INET, htons(DHCPV4_SERVER_PORT),
+ {INADDR_ANY}, {0}};
+ int val = 1;
+
if (!iface->dhcpv4_assignments.next)
INIT_LIST_HEAD(&iface->dhcpv4_assignments);
if (!iface->dhcpv4_fr_ips.next)
INIT_LIST_HEAD(&iface->dhcpv4_fr_ips);
- int sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
- if (sock < 0) {
- syslog(LOG_ERR, "Failed to create DHCPv4 server socket: %m");
- return -1;
+ iface->dhcpv4_event.uloop.fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
+ if (iface->dhcpv4_event.uloop.fd < 0) {
+ syslog(LOG_ERR, "socket(AF_INET): %m");
+ ret = -1;
+ goto out;
}
/* Basic IPv4 configuration */
- int val = 1;
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
- setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val));
- setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
+ if (setsockopt(iface->dhcpv4_event.uloop.fd, SOL_SOCKET, SO_REUSEADDR,
+ &val, sizeof(val)) < 0) {
+ syslog(LOG_ERR, "setsockopt(SO_REUSEADDR): %m");
+ ret = -1;
+ goto out;
+ }
+
+ if (setsockopt(iface->dhcpv4_event.uloop.fd, SOL_SOCKET, SO_BROADCAST,
+ &val, sizeof(val)) < 0) {
+ syslog(LOG_ERR, "setsockopt(SO_BROADCAST): %m");
+ ret = -1;
+ goto out;
+ }
+
+ if (setsockopt(iface->dhcpv4_event.uloop.fd, IPPROTO_IP, IP_PKTINFO,
+ &val, sizeof(val))) {
+ syslog(LOG_ERR, "setsockopt(IP_PKTINFO): %m");
+ ret = -1;
+ goto out;
+ }
val = IPTOS_PREC_INTERNETCONTROL;
- setsockopt(sock, IPPROTO_IP, IP_TOS, &val, sizeof(val));
+ if (setsockopt(iface->dhcpv4_event.uloop.fd, IPPROTO_IP, IP_TOS,
+ &val, sizeof(val))) {
+ syslog(LOG_ERR, "setsockopt(IP_TOS): %m");
+ ret = -1;
+ goto out;
+ }
val = IP_PMTUDISC_DONT;
- setsockopt(sock, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val));
+ if (setsockopt(iface->dhcpv4_event.uloop.fd, IPPROTO_IP, IP_MTU_DISCOVER,
+ &val, sizeof(val))) {
+ syslog(LOG_ERR, "setsockopt(IP_MTU_DISCOVER): %m");
+ ret = -1;
+ goto out;
+ }
- setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
- iface->ifname, strlen(iface->ifname));
+ if (setsockopt(iface->dhcpv4_event.uloop.fd, SOL_SOCKET, SO_BINDTODEVICE,
+ iface->ifname, strlen(iface->ifname))) {
+ syslog(LOG_ERR, "setsockopt(SO_BINDTODEVICE): %m");
+ ret = -1;
+ goto out;
+ }
- struct sockaddr_in bind_addr = {AF_INET, htons(DHCPV4_SERVER_PORT),
- {INADDR_ANY}, {0}};
+ if (bind(iface->dhcpv4_event.uloop.fd, (struct sockaddr*)&bind_addr, sizeof(bind_addr))) {
+ syslog(LOG_ERR, "bind(): %m");
+ ret = -1;
+ goto out;
+ }
- if (bind(sock, (struct sockaddr*)&bind_addr, sizeof(bind_addr))) {
- syslog(LOG_ERR, "Failed to open DHCPv4 server socket: %m");
- return -1;
+ if (setup_dhcpv4_addresses(iface) < 0) {
+ ret = -1;
+ goto out;
}
- iface->dhcpv4_event.uloop.fd = sock;
iface->dhcpv4_event.handle_dgram = handle_dhcpv4;
odhcpd_register(&iface->dhcpv4_event);
- if (setup_dhcpv4_addresses(iface) < 0)
- return -1;
-
update_static_assignments(iface);
} else if (iface->dhcpv4_assignments.next) {
while (!list_empty(&iface->dhcpv4_assignments))
free_dhcpv4_assignment(list_first_entry(&iface->dhcpv4_assignments,
struct dhcpv4_assignment, head));
}
- return 0;
+
+out:
+ if (ret < 0 && iface->dhcpv4_event.uloop.fd > 0) {
+ close(iface->dhcpv4_event.uloop.fd);
+ iface->dhcpv4_event.uloop.fd = -1;
+ }
+
+ return ret;
}