aboutgitcodebugslistschat
diff options
context:
space:
mode:
-rw-r--r--conf.c63
-rw-r--r--dhcp.c6
-rw-r--r--passt.h4
-rw-r--r--pasta.c7
4 files changed, 47 insertions, 33 deletions
diff --git a/conf.c b/conf.c
index 4a622fc..c6d06ea 100644
--- a/conf.c
+++ b/conf.c
@@ -522,6 +522,31 @@ static int conf_pasta_ns(int *netns_only, char *userns, char *netns,
return 0;
}
+/** conf_ip4_prefix() - Parse an IPv4 prefix length or netmask
+ * @arg: Netmask in dotted decimal or prefix length
+ *
+ * Return: Validated prefix length on success, -1 on failure
+ */
+static int conf_ip4_prefix(const char *arg)
+{
+ struct in_addr mask;
+ unsigned long len;
+
+ if (inet_pton(AF_INET, arg, &mask)) {
+ in_addr_t hmask = ntohl(mask.s_addr);
+ len = __builtin_popcount(hmask);
+ if ((hmask << len) != 0)
+ return -1;
+ } else {
+ errno = 0;
+ len = strtoul(optarg, NULL, 0);
+ if (len > 32 || errno)
+ return -1;
+ }
+
+ return len;
+}
+
/**
* conf_ip4() - Verify or detect IPv4 support, get relevant addresses
* @ifi: Host interface to attempt (0 to determine one)
@@ -544,22 +569,18 @@ static unsigned int conf_ip4(unsigned int ifi,
if (!ip4->gw)
nl_route(0, ifi, AF_INET, &ip4->gw);
- if (!ip4->addr) {
- int mask_len = 0;
+ if (!ip4->addr)
+ nl_addr(0, ifi, AF_INET, &ip4->addr, &ip4->prefix_len, NULL);
- nl_addr(0, ifi, AF_INET, &ip4->addr, &mask_len, NULL);
- ip4->mask = htonl(0xffffffff << (32 - mask_len));
- }
-
- if (!ip4->mask) {
+ if (!ip4->prefix_len) {
if (IN_CLASSA(ntohl(ip4->addr)))
- ip4->mask = htonl(IN_CLASSA_NET);
+ ip4->prefix_len = (32 - IN_CLASSA_NSHIFT);
else if (IN_CLASSB(ntohl(ip4->addr)))
- ip4->mask = htonl(IN_CLASSB_NET);
+ ip4->prefix_len = (32 - IN_CLASSB_NSHIFT);
else if (IN_CLASSC(ntohl(ip4->addr)))
- ip4->mask = htonl(IN_CLASSC_NET);
+ ip4->prefix_len = (32 - IN_CLASSC_NSHIFT);
else
- ip4->mask = 0xffffffff;
+ ip4->prefix_len = 32;
}
memcpy(&ip4->addr_seen, &ip4->addr, sizeof(ip4->addr_seen));
@@ -819,11 +840,12 @@ static void conf_print(const struct ctx *c)
if (c->ifi4) {
if (!c->no_dhcp) {
+ uint32_t mask = htonl(0xffffffff << c->ip4.prefix_len);
info("DHCP:");
info(" assign: %s",
inet_ntop(AF_INET, &c->ip4.addr, buf4, sizeof(buf4)));
info(" mask: %s",
- inet_ntop(AF_INET, &c->ip4.mask, buf4, sizeof(buf4)));
+ inet_ntop(AF_INET, &mask, buf4, sizeof(buf4)));
info(" router: %s",
inet_ntop(AF_INET, &c->ip4.gw, buf4, sizeof(buf4)));
}
@@ -1067,9 +1089,9 @@ void conf(struct ctx *c, int argc, char **argv)
struct in6_addr *dns6 = c->ip6.dns;
struct fqdn *dnss = c->dns_search;
uint32_t *dns4 = c->ip4.dns;
- int name, ret, mask, b, i;
const char *optstring;
unsigned int ifi = 0;
+ int name, ret, b, i;
size_t logsize = 0;
uid_t uid;
gid_t gid;
@@ -1374,18 +1396,11 @@ void conf(struct ctx *c, int argc, char **argv)
usage(argv[0]);
break;
case 'n':
- if (inet_pton(AF_INET, optarg, &c->ip4.mask))
- break;
-
- errno = 0;
- mask = strtol(optarg, NULL, 0);
- if (mask > 0 && mask <= 32 && !errno) {
- c->ip4.mask = htonl(0xffffffff << (32 - mask));
- break;
+ c->ip4.prefix_len = conf_ip4_prefix(optarg);
+ if (c->ip4.prefix_len < 0) {
+ err("Invalid netmask: %s", optarg);
+ usage(argv[0]);
}
-
- err("Invalid netmask: %s", optarg);
- usage(argv[0]);
break;
case 'M':
for (i = 0; i < ETH_ALEN; i++) {
diff --git a/dhcp.c b/dhcp.c
index d22698a..076e9b6 100644
--- a/dhcp.c
+++ b/dhcp.c
@@ -268,6 +268,7 @@ static void opt_set_dns_search(const struct ctx *c, size_t max_len)
int dhcp(const struct ctx *c, const struct pool *p)
{
size_t mlen, len, offset = 0, opt_len, opt_off = 0;
+ struct in_addr mask;
struct ethhdr *eh;
struct iphdr *iph;
struct udphdr *uh;
@@ -334,14 +335,15 @@ int dhcp(const struct ctx *c, const struct pool *p)
m->chaddr[3], m->chaddr[4], m->chaddr[5]);
m->yiaddr = c->ip4.addr;
- memcpy(opts[1].s, &c->ip4.mask, sizeof(c->ip4.mask));
+ mask.s_addr = htonl(0xffffffff << c->ip4.prefix_len);
+ memcpy(opts[1].s, &mask, sizeof(mask));
memcpy(opts[3].s, &c->ip4.gw, sizeof(c->ip4.gw));
memcpy(opts[54].s, &c->ip4.gw, sizeof(c->ip4.gw));
/* If the gateway is not on the assigned subnet, send an option 121
* (Classless Static Routing) adding a dummy route to it.
*/
- if ((c->ip4.addr & c->ip4.mask) != (c->ip4.gw & c->ip4.mask)) {
+ if ((c->ip4.addr & mask.s_addr) != (c->ip4.gw & mask.s_addr)) {
/* a.b.c.d/32:0.0.0.0, 0:a.b.c.d */
opts[121].slen = 14;
opts[121].s[0] = 32;
diff --git a/passt.h b/passt.h
index 67281db..4cf6078 100644
--- a/passt.h
+++ b/passt.h
@@ -99,7 +99,7 @@ enum passt_modes {
* struct ip4_ctx - IPv4 execution context
* @addr: IPv4 address for external, routable interface
* @addr_seen: Latest IPv4 address seen as source from tap
- * @mask: IPv4 netmask, network order
+ * @prefixlen: IPv4 prefix length (netmask)
* @gw: Default IPv4 gateway, network order
* @dns: IPv4 DNS addresses, zero-terminated, network order
* @dns_fwd: Address forwarded (UDP) to first IPv4 DNS, network order
@@ -107,7 +107,7 @@ enum passt_modes {
struct ip4_ctx {
uint32_t addr;
uint32_t addr_seen;
- uint32_t mask;
+ int prefix_len;
uint32_t gw;
uint32_t dns[MAXNS + 1];
uint32_t dns_fwd;
diff --git a/pasta.c b/pasta.c
index ae695e2..db86317 100644
--- a/pasta.c
+++ b/pasta.c
@@ -249,19 +249,16 @@ void pasta_ns_conf(struct ctx *c)
nl_link(1, 1 /* lo */, MAC_ZERO, 1, 0);
if (c->pasta_conf_ns) {
- int prefix_len;
-
nl_link(1, c->pasta_ifi, c->mac_guest, 1, c->mtu);
if (c->ifi4) {
- prefix_len = __builtin_popcount(c->ip4.mask);
nl_addr(1, c->pasta_ifi, AF_INET, &c->ip4.addr,
- &prefix_len, NULL);
+ &c->ip4.prefix_len, NULL);
nl_route(1, c->pasta_ifi, AF_INET, &c->ip4.gw);
}
if (c->ifi6) {
- prefix_len = 64;
+ int prefix_len = 64;
nl_addr(1, c->pasta_ifi, AF_INET6, &c->ip6.addr,
&prefix_len, NULL);
nl_route(1, c->pasta_ifi, AF_INET6, &c->ip6.gw);