#include <arpa/inet.h>
#include <errno.h>
-#include <stdio.h>
-#include <stdio_ext.h>
#include <stdlib.h>
-#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
#include "sd-dhcp-lease.h"
#include "dhcp-lease-internal.h"
#include "dhcp-protocol.h"
#include "dns-domain.h"
+#include "env-file.h"
#include "fd-util.h"
#include "fileio.h"
#include "hexdecoct.h"
#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
+#include "tmpfile-util.h"
#include "unaligned.h"
int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) {
return (int) lease->ntp_size;
}
+int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr) {
+ assert_return(lease, -EINVAL);
+ assert_return(addr, -EINVAL);
+
+ if (lease->sip_size <= 0)
+ return -ENODATA;
+
+ *addr = lease->sip;
+ return (int) lease->sip_size;
+}
+
+int sd_dhcp_lease_get_pop3_server(sd_dhcp_lease *lease, const struct in_addr **addr) {
+ assert_return(lease, -EINVAL);
+ assert_return(addr, -EINVAL);
+
+ if (lease->pop3_server_size <= 0)
+ return -ENODATA;
+
+ *addr = lease->pop3_server;
+ return (int) lease->pop3_server_size;
+}
+
+int sd_dhcp_lease_get_smtp_server(sd_dhcp_lease *lease, const struct in_addr **addr) {
+ assert_return(lease, -EINVAL);
+ assert_return(addr, -EINVAL);
+
+ if (lease->smtp_server_size <= 0)
+ return -ENODATA;
+
+ *addr = lease->smtp_server;
+ return (int) lease->smtp_server_size;
+}
+
int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) {
assert_return(lease, -EINVAL);
assert_return(domainname, -EINVAL);
return 0;
}
-int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, struct in_addr *addr) {
+int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, const struct in_addr **addr) {
assert_return(lease, -EINVAL);
assert_return(addr, -EINVAL);
- if (lease->router == 0)
+ if (lease->router_size <= 0)
return -ENODATA;
- addr->s_addr = lease->router;
- return 0;
+ *addr = lease->router;
+ return (int) lease->router_size;
}
int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr) {
}
free(lease->root_path);
+ free(lease->router);
free(lease->timezone);
free(lease->hostname);
free(lease->domainname);
free(lease->dns);
free(lease->ntp);
+ free(lease->sip);
+ free(lease->pop3_server);
+ free(lease->smtp_server);
free(lease->static_route);
free(lease->client_id);
free(lease->vendor_specific);
if (memchr(option, 0, len - 1))
return -EINVAL;
- string = strndup((const char *) option, len);
+ string = memdup_suffix0((const char *) option, len);
if (!string)
return -ENOMEM;
return 0;
}
- r = dns_name_normalize(name, &normalized);
+ r = dns_name_normalize(name, 0, &normalized);
if (r < 0)
return r;
return 0;
}
-static void filter_bogus_addresses(struct in_addr *addresses, size_t *n) {
- size_t i, j;
+static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) {
+ assert(option);
+ assert(ret);
+ assert(n_ret);
- /* Silently filter DNS/NTP servers supplied to us that do not make outside of the local scope. */
+ if (len <= 0) {
+ *ret = mfree(*ret);
+ *n_ret = 0;
+ } else {
+ size_t n_addresses;
+ struct in_addr *addresses;
- for (i = 0, j = 0; i < *n; i ++) {
+ if (len % 4 != 0)
+ return -EINVAL;
- if (in4_addr_is_null(addresses+i) ||
- in4_addr_is_localhost(addresses+i))
- continue;
+ n_addresses = len / 4;
+
+ addresses = newdup(struct in_addr, option, n_addresses);
+ if (!addresses)
+ return -ENOMEM;
- addresses[j++] = addresses[i];
+ free(*ret);
+ *ret = addresses;
+ *n_ret = n_addresses;
}
- *n = j;
+ return 0;
}
-static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) {
+static int lease_parse_sip_server(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) {
assert(option);
assert(ret);
assert(n_ret);
} else {
size_t n_addresses;
struct in_addr *addresses;
+ int l = len - 1;
- if (len % 4 != 0)
+ if (l % 4 != 0)
return -EINVAL;
- n_addresses = len / 4;
+ n_addresses = l / 4;
- addresses = newdup(struct in_addr, option, n_addresses);
+ addresses = newdup(struct in_addr, option + 1, n_addresses);
if (!addresses)
return -ENOMEM;
- filter_bogus_addresses(addresses, &n_addresses);
-
free(*ret);
*ret = addresses;
*n_ret = n_addresses;
break;
case SD_DHCP_OPTION_ROUTER:
- if (len >= 4) {
- r = lease_parse_be32(option, 4, &lease->router);
- if (r < 0)
- log_debug_errno(r, "Failed to parse router address, ignoring: %m");
- }
+ r = lease_parse_in_addrs(option, len, &lease->router, &lease->router_size);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse router addresses, ignoring: %m");
break;
case SD_DHCP_OPTION_DOMAIN_NAME_SERVER:
log_debug_errno(r, "Failed to parse NTP server, ignoring: %m");
break;
+ case SD_DHCP_OPTION_SIP_SERVER:
+ r = lease_parse_sip_server(option, len, &lease->sip, &lease->sip_size);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse SIP server, ignoring: %m");
+ break;
+
+ case SD_DHCP_OPTION_POP3_SERVER:
+ r = lease_parse_in_addrs(option, len, &lease->pop3_server, &lease->pop3_server_size);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse POP3 server, ignoring: %m");
+ break;
+
+ case SD_DHCP_OPTION_SMTP_SERVER:
+ r = lease_parse_in_addrs(option, len, &lease->smtp_server, &lease->smtp_server_size);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse SMTP server, ignoring: %m");
+ break;
+
case SD_DHCP_OPTION_STATIC_ROUTE:
r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size, &lease->static_route_allocated);
if (r < 0)
if (!lease)
return -ENOMEM;
- lease->router = INADDR_ANY;
lease->n_ref = 1;
*ret = lease;
const struct in_addr *addresses;
const void *client_id, *data;
size_t client_id_len, data_len;
+ char sbuf[INET_ADDRSTRLEN];
const char *string;
uint16_t mtu;
_cleanup_free_ sd_dhcp_route **routes = NULL;
if (r < 0)
goto fail;
- (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
(void) fchmod(fileno(f), 0644);
fprintf(f,
r = sd_dhcp_lease_get_address(lease, &address);
if (r >= 0)
- fprintf(f, "ADDRESS=%s\n", inet_ntoa(address));
+ fprintf(f, "ADDRESS=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf)));
r = sd_dhcp_lease_get_netmask(lease, &address);
if (r >= 0)
- fprintf(f, "NETMASK=%s\n", inet_ntoa(address));
+ fprintf(f, "NETMASK=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf)));
- r = sd_dhcp_lease_get_router(lease, &address);
- if (r >= 0)
- fprintf(f, "ROUTER=%s\n", inet_ntoa(address));
+ r = sd_dhcp_lease_get_router(lease, &addresses);
+ if (r > 0) {
+ fputs("ROUTER=", f);
+ serialize_in_addrs(f, addresses, r, false, NULL);
+ fputc('\n', f);
+ }
r = sd_dhcp_lease_get_server_identifier(lease, &address);
if (r >= 0)
- fprintf(f, "SERVER_ADDRESS=%s\n", inet_ntoa(address));
+ fprintf(f, "SERVER_ADDRESS=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf)));
r = sd_dhcp_lease_get_next_server(lease, &address);
if (r >= 0)
- fprintf(f, "NEXT_SERVER=%s\n", inet_ntoa(address));
+ fprintf(f, "NEXT_SERVER=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf)));
r = sd_dhcp_lease_get_broadcast(lease, &address);
if (r >= 0)
- fprintf(f, "BROADCAST=%s\n", inet_ntoa(address));
+ fprintf(f, "BROADCAST=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf)));
r = sd_dhcp_lease_get_mtu(lease, &mtu);
if (r >= 0)
r = sd_dhcp_lease_get_dns(lease, &addresses);
if (r > 0) {
fputs("DNS=", f);
- serialize_in_addrs(f, addresses, r);
- fputs("\n", f);
+ serialize_in_addrs(f, addresses, r, false, NULL);
+ fputc('\n', f);
}
r = sd_dhcp_lease_get_ntp(lease, &addresses);
if (r > 0) {
fputs("NTP=", f);
- serialize_in_addrs(f, addresses, r);
- fputs("\n", f);
+ serialize_in_addrs(f, addresses, r, false, NULL);
+ fputc('\n', f);
+ }
+
+ r = sd_dhcp_lease_get_sip(lease, &addresses);
+ if (r > 0) {
+ fputs("SIP=", f);
+ serialize_in_addrs(f, addresses, r, false, NULL);
+ fputc('\n', f);
}
r = sd_dhcp_lease_get_domainname(lease, &string);
if (r > 0) {
fputs("DOMAIN_SEARCH_LIST=", f);
fputstrv(f, search_domains, NULL, NULL);
- fputs("\n", f);
+ fputc('\n', f);
}
r = sd_dhcp_lease_get_hostname(lease, &string);
*broadcast = NULL,
*dns = NULL,
*ntp = NULL,
+ *sip = NULL,
+ *pop3_server = NULL,
+ *smtp_server = NULL,
*mtu = NULL,
*routes = NULL,
*domains = NULL,
if (r < 0)
return r;
- r = parse_env_file(NULL, lease_file, NEWLINE,
+ r = parse_env_file(NULL, lease_file,
"ADDRESS", &address,
"ROUTER", &router,
"NETMASK", &netmask,
"BROADCAST", &broadcast,
"DNS", &dns,
"NTP", &ntp,
+ "SIP", &sip,
+ "POP3_SERVERS", &pop3_server,
+ "SMTP_SERVERS", &smtp_server,
"MTU", &mtu,
"DOMAINNAME", &lease->domainname,
"HOSTNAME", &lease->hostname,
"OPTION_251", &options[27],
"OPTION_252", &options[28],
"OPTION_253", &options[29],
- "OPTION_254", &options[30],
- NULL);
+ "OPTION_254", &options[30]);
if (r < 0)
return r;
}
if (router) {
- r = inet_pton(AF_INET, router, &lease->router);
- if (r <= 0)
- log_debug("Failed to parse router %s, ignoring.", router);
+ r = deserialize_in_addrs(&lease->router, router);
+ if (r < 0)
+ log_debug_errno(r, "Failed to deserialize router addresses %s, ignoring: %m", router);
+ else
+ lease->router_size = r;
}
if (netmask) {
lease->ntp_size = r;
}
+ if (sip) {
+ r = deserialize_in_addrs(&lease->sip, sip);
+ if (r < 0)
+ log_debug_errno(r, "Failed to deserialize SIP servers %s, ignoring: %m", sip);
+ else
+ lease->sip_size = r;
+ }
+
+ if (pop3_server) {
+ r = deserialize_in_addrs(&lease->pop3_server, pop3_server);
+ if (r < 0)
+ log_debug_errno(r, "Failed to deserialize POP3 server %s, ignoring: %m", pop3_server);
+ else
+ lease->pop3_server_size = r;
+ }
+
+ if (smtp_server) {
+ r = deserialize_in_addrs(&lease->smtp_server, smtp_server);
+ if (r < 0)
+ log_debug_errno(r, "Failed to deserialize SMTP server %s, ignoring: %m", smtp_server);
+ else
+ lease->smtp_server_size = r;
+ }
+
if (mtu) {
r = safe_atou16(mtu, &lease->mtu);
if (r < 0)
*gateway = route->gw_addr;
return 0;
}
+
+int sd_dhcp_route_get_option(sd_dhcp_route *route) {
+ assert_return(route, -EINVAL);
+
+ return route->option;
+}