Make substructures for IPv4 and IPv6 specific context information
The context structure contains a batch of fields specific to IPv4 and to IPv6 connectivity. Split those out into a sub-structure. This allows the conf_ip4() and conf_ip6() functions, which take the entire context but touch very little of it, to be given more specific parameters, making it clearer what it affects without stepping through the code. Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
parent
5e12d23acb
commit
16f5586bb8
12 changed files with 232 additions and 212 deletions
2
arp.c
2
arp.c
|
@ -66,7 +66,7 @@ int arp(const struct ctx *c, const struct pool *p)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* Don't resolve our own address, either. */
|
/* Don't resolve our own address, either. */
|
||||||
if (!memcmp(am->tip, &c->addr4, sizeof(am->tip)))
|
if (!memcmp(am->tip, &c->ip4.addr, sizeof(am->tip)))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
ah->ar_op = htons(ARPOP_REPLY);
|
ah->ar_op = htons(ARPOP_REPLY);
|
||||||
|
|
184
conf.c
184
conf.c
|
@ -404,9 +404,9 @@ overlap:
|
||||||
static void get_dns(struct ctx *c)
|
static void get_dns(struct ctx *c)
|
||||||
{
|
{
|
||||||
int dns4_set, dns6_set, dnss_set, dns_set, fd;
|
int dns4_set, dns6_set, dnss_set, dns_set, fd;
|
||||||
struct in6_addr *dns6 = &c->dns6[0];
|
struct in6_addr *dns6 = &c->ip6.dns[0];
|
||||||
struct fqdn *s = c->dns_search;
|
struct fqdn *s = c->dns_search;
|
||||||
uint32_t *dns4 = &c->dns4[0];
|
uint32_t *dns4 = &c->ip4.dns[0];
|
||||||
struct lineread resolvconf;
|
struct lineread resolvconf;
|
||||||
int line_len;
|
int line_len;
|
||||||
char *line, *p, *end;
|
char *line, *p, *end;
|
||||||
|
@ -434,7 +434,7 @@ static void get_dns(struct ctx *c)
|
||||||
*end = 0;
|
*end = 0;
|
||||||
|
|
||||||
if (!dns4_set &&
|
if (!dns4_set &&
|
||||||
dns4 - &c->dns4[0] < ARRAY_SIZE(c->dns4) - 1 &&
|
dns4 - &c->ip4.dns[0] < ARRAY_SIZE(c->ip4.dns) - 1 &&
|
||||||
inet_pton(AF_INET, p + 1, dns4)) {
|
inet_pton(AF_INET, p + 1, dns4)) {
|
||||||
/* We can only access local addresses via the gw redirect */
|
/* We can only access local addresses via the gw redirect */
|
||||||
if (ntohl(*dns4) >> IN_CLASSA_NSHIFT == IN_LOOPBACKNET) {
|
if (ntohl(*dns4) >> IN_CLASSA_NSHIFT == IN_LOOPBACKNET) {
|
||||||
|
@ -442,14 +442,14 @@ static void get_dns(struct ctx *c)
|
||||||
*dns4 = 0;
|
*dns4 = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
*dns4 = c->gw4;
|
*dns4 = c->ip4.gw;
|
||||||
}
|
}
|
||||||
dns4++;
|
dns4++;
|
||||||
*dns4 = 0;
|
*dns4 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dns6_set &&
|
if (!dns6_set &&
|
||||||
dns6 - &c->dns6[0] < ARRAY_SIZE(c->dns6) - 1 &&
|
dns6 - &c->ip6.dns[0] < ARRAY_SIZE(c->ip6.dns) - 1 &&
|
||||||
inet_pton(AF_INET6, p + 1, dns6)) {
|
inet_pton(AF_INET6, p + 1, dns6)) {
|
||||||
/* We can only access local addresses via the gw redirect */
|
/* We can only access local addresses via the gw redirect */
|
||||||
if (IN6_IS_ADDR_LOOPBACK(dns6)) {
|
if (IN6_IS_ADDR_LOOPBACK(dns6)) {
|
||||||
|
@ -457,7 +457,7 @@ static void get_dns(struct ctx *c)
|
||||||
memset(dns6, 0, sizeof(*dns6));
|
memset(dns6, 0, sizeof(*dns6));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
memcpy(dns6, &c->gw6, sizeof(*dns6));
|
memcpy(dns6, &c->ip6.gw, sizeof(*dns6));
|
||||||
}
|
}
|
||||||
dns6++;
|
dns6++;
|
||||||
memset(dns6, 0, sizeof(*dns6));
|
memset(dns6, 0, sizeof(*dns6));
|
||||||
|
@ -485,7 +485,7 @@ static void get_dns(struct ctx *c)
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (!dns_set && dns4 == c->dns4 && dns6 == c->dns6)
|
if (!dns_set && dns4 == c->ip4.dns && dns6 == c->ip6.dns)
|
||||||
warn("Couldn't get any nameserver address");
|
warn("Couldn't get any nameserver address");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,12 +612,14 @@ static int conf_ns_opt(struct ctx *c,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* conf_ip4() - Verify or detect IPv4 support, get relevant addresses
|
* conf_ip4() - Verify or detect IPv4 support, get relevant addresses
|
||||||
* @c: Execution context
|
|
||||||
* @ifi: Host interface to attempt (0 to determine one)
|
* @ifi: Host interface to attempt (0 to determine one)
|
||||||
|
* @ip4: IPv4 context (will be written)
|
||||||
|
* @mac: MAC address to use (written if unset)
|
||||||
*
|
*
|
||||||
* Return: Interface index for IPv4, or 0 on failure.
|
* Return: Interface index for IPv4, or 0 on failure.
|
||||||
*/
|
*/
|
||||||
static unsigned int conf_ip4(struct ctx *c, unsigned int ifi)
|
static unsigned int conf_ip4(unsigned int ifi,
|
||||||
|
struct ip4_ctx *ip4, unsigned char *mac)
|
||||||
{
|
{
|
||||||
if (!ifi)
|
if (!ifi)
|
||||||
ifi = nl_get_ext_if(AF_INET);
|
ifi = nl_get_ext_if(AF_INET);
|
||||||
|
@ -627,33 +629,33 @@ static unsigned int conf_ip4(struct ctx *c, unsigned int ifi)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!c->gw4)
|
if (!ip4->gw)
|
||||||
nl_route(0, ifi, AF_INET, &c->gw4);
|
nl_route(0, ifi, AF_INET, &ip4->gw);
|
||||||
|
|
||||||
if (!c->addr4) {
|
if (!ip4->addr) {
|
||||||
int mask_len = 0;
|
int mask_len = 0;
|
||||||
|
|
||||||
nl_addr(0, ifi, AF_INET, &c->addr4, &mask_len, NULL);
|
nl_addr(0, ifi, AF_INET, &ip4->addr, &mask_len, NULL);
|
||||||
c->mask4 = htonl(0xffffffff << (32 - mask_len));
|
ip4->mask = htonl(0xffffffff << (32 - mask_len));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!c->mask4) {
|
if (!ip4->mask) {
|
||||||
if (IN_CLASSA(ntohl(c->addr4)))
|
if (IN_CLASSA(ntohl(ip4->addr)))
|
||||||
c->mask4 = htonl(IN_CLASSA_NET);
|
ip4->mask = htonl(IN_CLASSA_NET);
|
||||||
else if (IN_CLASSB(ntohl(c->addr4)))
|
else if (IN_CLASSB(ntohl(ip4->addr)))
|
||||||
c->mask4 = htonl(IN_CLASSB_NET);
|
ip4->mask = htonl(IN_CLASSB_NET);
|
||||||
else if (IN_CLASSC(ntohl(c->addr4)))
|
else if (IN_CLASSC(ntohl(ip4->addr)))
|
||||||
c->mask4 = htonl(IN_CLASSC_NET);
|
ip4->mask = htonl(IN_CLASSC_NET);
|
||||||
else
|
else
|
||||||
c->mask4 = 0xffffffff;
|
ip4->mask = 0xffffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&c->addr4_seen, &c->addr4, sizeof(c->addr4_seen));
|
memcpy(&ip4->addr_seen, &ip4->addr, sizeof(ip4->addr_seen));
|
||||||
|
|
||||||
if (MAC_IS_ZERO(c->mac))
|
if (MAC_IS_ZERO(mac))
|
||||||
nl_link(0, ifi, c->mac, 0, 0);
|
nl_link(0, ifi, mac, 0, 0);
|
||||||
|
|
||||||
if (!c->gw4 || !c->addr4 || MAC_IS_ZERO(c->mac))
|
if (!ip4->gw || !ip4->addr || MAC_IS_ZERO(mac))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return ifi;
|
return ifi;
|
||||||
|
@ -661,12 +663,14 @@ static unsigned int conf_ip4(struct ctx *c, unsigned int ifi)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* conf_ip6() - Verify or detect IPv6 support, get relevant addresses
|
* conf_ip6() - Verify or detect IPv6 support, get relevant addresses
|
||||||
* @c: Execution context
|
|
||||||
* @ifi: Host interface to attempt (0 to determine one)
|
* @ifi: Host interface to attempt (0 to determine one)
|
||||||
|
* @ip6: IPv6 context (will be written)
|
||||||
|
* @mac: MAC address to use (written if unset)
|
||||||
*
|
*
|
||||||
* Return: Interface index for IPv6, or 0 on failure.
|
* Return: Interface index for IPv6, or 0 on failure.
|
||||||
*/
|
*/
|
||||||
static unsigned int conf_ip6(struct ctx *c, unsigned int ifi)
|
static unsigned int conf_ip6(unsigned int ifi,
|
||||||
|
struct ip6_ctx *ip6, unsigned char *mac)
|
||||||
{
|
{
|
||||||
int prefix_len = 0;
|
int prefix_len = 0;
|
||||||
|
|
||||||
|
@ -678,23 +682,23 @@ static unsigned int conf_ip6(struct ctx *c, unsigned int ifi)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IN6_IS_ADDR_UNSPECIFIED(&c->gw6))
|
if (IN6_IS_ADDR_UNSPECIFIED(&ip6->gw))
|
||||||
nl_route(0, ifi, AF_INET6, &c->gw6);
|
nl_route(0, ifi, AF_INET6, &ip6->gw);
|
||||||
|
|
||||||
nl_addr(0, ifi, AF_INET6,
|
nl_addr(0, ifi, AF_INET6,
|
||||||
IN6_IS_ADDR_UNSPECIFIED(&c->addr6) ? &c->addr6 : NULL,
|
IN6_IS_ADDR_UNSPECIFIED(&ip6->addr) ? &ip6->addr : NULL,
|
||||||
&prefix_len, &c->addr6_ll);
|
&prefix_len, &ip6->addr_ll);
|
||||||
|
|
||||||
memcpy(&c->addr6_seen, &c->addr6, sizeof(c->addr6));
|
memcpy(&ip6->addr_seen, &ip6->addr, sizeof(ip6->addr));
|
||||||
memcpy(&c->addr6_ll_seen, &c->addr6_ll, sizeof(c->addr6_ll));
|
memcpy(&ip6->addr_ll_seen, &ip6->addr_ll, sizeof(ip6->addr_ll));
|
||||||
|
|
||||||
if (MAC_IS_ZERO(c->mac))
|
if (MAC_IS_ZERO(mac))
|
||||||
nl_link(0, ifi, c->mac, 0, 0);
|
nl_link(0, ifi, mac, 0, 0);
|
||||||
|
|
||||||
if (IN6_IS_ADDR_UNSPECIFIED(&c->gw6) ||
|
if (IN6_IS_ADDR_UNSPECIFIED(&ip6->gw) ||
|
||||||
IN6_IS_ADDR_UNSPECIFIED(&c->addr6) ||
|
IN6_IS_ADDR_UNSPECIFIED(&ip6->addr) ||
|
||||||
IN6_IS_ADDR_UNSPECIFIED(&c->addr6_ll) ||
|
IN6_IS_ADDR_UNSPECIFIED(&ip6->addr_ll) ||
|
||||||
MAC_IS_ZERO(c->mac))
|
MAC_IS_ZERO(mac))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return ifi;
|
return ifi;
|
||||||
|
@ -899,17 +903,17 @@ static void conf_print(const struct ctx *c)
|
||||||
if (!c->no_dhcp) {
|
if (!c->no_dhcp) {
|
||||||
info("DHCP:");
|
info("DHCP:");
|
||||||
info(" assign: %s",
|
info(" assign: %s",
|
||||||
inet_ntop(AF_INET, &c->addr4, buf4, sizeof(buf4)));
|
inet_ntop(AF_INET, &c->ip4.addr, buf4, sizeof(buf4)));
|
||||||
info(" mask: %s",
|
info(" mask: %s",
|
||||||
inet_ntop(AF_INET, &c->mask4, buf4, sizeof(buf4)));
|
inet_ntop(AF_INET, &c->ip4.mask, buf4, sizeof(buf4)));
|
||||||
info(" router: %s",
|
info(" router: %s",
|
||||||
inet_ntop(AF_INET, &c->gw4, buf4, sizeof(buf4)));
|
inet_ntop(AF_INET, &c->ip4.gw, buf4, sizeof(buf4)));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; c->dns4[i]; i++) {
|
for (i = 0; c->ip4.dns[i]; i++) {
|
||||||
if (!i)
|
if (!i)
|
||||||
info("DNS:");
|
info("DNS:");
|
||||||
inet_ntop(AF_INET, &c->dns4[i], buf4, sizeof(buf4));
|
inet_ntop(AF_INET, &c->ip4.dns[i], buf4, sizeof(buf4));
|
||||||
info(" %s", buf4);
|
info(" %s", buf4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -933,17 +937,17 @@ static void conf_print(const struct ctx *c)
|
||||||
goto dns6;
|
goto dns6;
|
||||||
|
|
||||||
info(" assign: %s",
|
info(" assign: %s",
|
||||||
inet_ntop(AF_INET6, &c->addr6, buf6, sizeof(buf6)));
|
inet_ntop(AF_INET6, &c->ip6.addr, buf6, sizeof(buf6)));
|
||||||
info(" router: %s",
|
info(" router: %s",
|
||||||
inet_ntop(AF_INET6, &c->gw6, buf6, sizeof(buf6)));
|
inet_ntop(AF_INET6, &c->ip6.gw, buf6, sizeof(buf6)));
|
||||||
info(" our link-local: %s",
|
info(" our link-local: %s",
|
||||||
inet_ntop(AF_INET6, &c->addr6_ll, buf6, sizeof(buf6)));
|
inet_ntop(AF_INET6, &c->ip6.addr_ll, buf6, sizeof(buf6)));
|
||||||
|
|
||||||
dns6:
|
dns6:
|
||||||
for (i = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->dns6[i]); i++) {
|
for (i = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[i]); i++) {
|
||||||
if (!i)
|
if (!i)
|
||||||
info("DNS:");
|
info("DNS:");
|
||||||
inet_ntop(AF_INET6, &c->dns6[i], buf6, sizeof(buf6));
|
inet_ntop(AF_INET6, &c->ip6.dns[i], buf6, sizeof(buf6));
|
||||||
info(" %s", buf6);
|
info(" %s", buf6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1065,10 +1069,10 @@ void conf(struct ctx *c, int argc, char **argv)
|
||||||
enum conf_port_type tcp_tap = 0, tcp_init = 0;
|
enum conf_port_type tcp_tap = 0, tcp_init = 0;
|
||||||
enum conf_port_type udp_tap = 0, udp_init = 0;
|
enum conf_port_type udp_tap = 0, udp_init = 0;
|
||||||
bool v4_only = false, v6_only = false;
|
bool v4_only = false, v6_only = false;
|
||||||
|
struct in6_addr *dns6 = c->ip6.dns;
|
||||||
struct fqdn *dnss = c->dns_search;
|
struct fqdn *dnss = c->dns_search;
|
||||||
struct in6_addr *dns6 = c->dns6;
|
uint32_t *dns4 = c->ip4.dns;
|
||||||
int name, ret, mask, b, i;
|
int name, ret, mask, b, i;
|
||||||
uint32_t *dns4 = c->dns4;
|
|
||||||
unsigned int ifi = 0;
|
unsigned int ifi = 0;
|
||||||
|
|
||||||
if (c->mode == MODE_PASTA)
|
if (c->mode == MODE_PASTA)
|
||||||
|
@ -1167,17 +1171,17 @@ void conf(struct ctx *c, int argc, char **argv)
|
||||||
c->no_dhcp_dns_search = 1;
|
c->no_dhcp_dns_search = 1;
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
if (IN6_IS_ADDR_UNSPECIFIED(&c->dns6_fwd) &&
|
if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_fwd) &&
|
||||||
inet_pton(AF_INET6, optarg, &c->dns6_fwd) &&
|
inet_pton(AF_INET6, optarg, &c->ip6.dns_fwd) &&
|
||||||
!IN6_IS_ADDR_UNSPECIFIED(&c->dns6_fwd) &&
|
!IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_fwd) &&
|
||||||
!IN6_IS_ADDR_LOOPBACK(&c->dns6_fwd))
|
!IN6_IS_ADDR_LOOPBACK(&c->ip6.dns_fwd))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (c->dns4_fwd == INADDR_ANY &&
|
if (c->ip4.dns_fwd == INADDR_ANY &&
|
||||||
inet_pton(AF_INET, optarg, &c->dns4_fwd) &&
|
inet_pton(AF_INET, optarg, &c->ip4.dns_fwd) &&
|
||||||
c->dns4_fwd != INADDR_ANY &&
|
c->ip4.dns_fwd != INADDR_ANY &&
|
||||||
c->dns4_fwd != INADDR_BROADCAST &&
|
c->ip4.dns_fwd != INADDR_BROADCAST &&
|
||||||
c->dns4_fwd != INADDR_LOOPBACK)
|
c->ip4.dns_fwd != INADDR_LOOPBACK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
err("Invalid DNS forwarding address: %s", optarg);
|
err("Invalid DNS forwarding address: %s", optarg);
|
||||||
|
@ -1334,34 +1338,34 @@ void conf(struct ctx *c, int argc, char **argv)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
if (IN6_IS_ADDR_UNSPECIFIED(&c->addr6) &&
|
if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.addr) &&
|
||||||
inet_pton(AF_INET6, optarg, &c->addr6) &&
|
inet_pton(AF_INET6, optarg, &c->ip6.addr) &&
|
||||||
!IN6_IS_ADDR_UNSPECIFIED(&c->addr6) &&
|
!IN6_IS_ADDR_UNSPECIFIED(&c->ip6.addr) &&
|
||||||
!IN6_IS_ADDR_LOOPBACK(&c->addr6) &&
|
!IN6_IS_ADDR_LOOPBACK(&c->ip6.addr) &&
|
||||||
!IN6_IS_ADDR_V4MAPPED(&c->addr6) &&
|
!IN6_IS_ADDR_V4MAPPED(&c->ip6.addr) &&
|
||||||
!IN6_IS_ADDR_V4COMPAT(&c->addr6) &&
|
!IN6_IS_ADDR_V4COMPAT(&c->ip6.addr) &&
|
||||||
!IN6_IS_ADDR_MULTICAST(&c->addr6))
|
!IN6_IS_ADDR_MULTICAST(&c->ip6.addr))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (c->addr4 == INADDR_ANY &&
|
if (c->ip4.addr == INADDR_ANY &&
|
||||||
inet_pton(AF_INET, optarg, &c->addr4) &&
|
inet_pton(AF_INET, optarg, &c->ip4.addr) &&
|
||||||
c->addr4 != INADDR_ANY &&
|
c->ip4.addr != INADDR_ANY &&
|
||||||
c->addr4 != INADDR_BROADCAST &&
|
c->ip4.addr != INADDR_BROADCAST &&
|
||||||
c->addr4 != INADDR_LOOPBACK &&
|
c->ip4.addr != INADDR_LOOPBACK &&
|
||||||
!IN_MULTICAST(c->addr4))
|
!IN_MULTICAST(c->ip4.addr))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
err("Invalid address: %s", optarg);
|
err("Invalid address: %s", optarg);
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
if (inet_pton(AF_INET, optarg, &c->mask4))
|
if (inet_pton(AF_INET, optarg, &c->ip4.mask))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
mask = strtol(optarg, NULL, 0);
|
mask = strtol(optarg, NULL, 0);
|
||||||
if (mask > 0 && mask <= 32 && !errno) {
|
if (mask > 0 && mask <= 32 && !errno) {
|
||||||
c->mask4 = htonl(0xffffffff << (32 - mask));
|
c->ip4.mask = htonl(0xffffffff << (32 - mask));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1380,17 +1384,17 @@ void conf(struct ctx *c, int argc, char **argv)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
if (IN6_IS_ADDR_UNSPECIFIED(&c->gw6) &&
|
if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.gw) &&
|
||||||
inet_pton(AF_INET6, optarg, &c->gw6) &&
|
inet_pton(AF_INET6, optarg, &c->ip6.gw) &&
|
||||||
!IN6_IS_ADDR_UNSPECIFIED(&c->gw6) &&
|
!IN6_IS_ADDR_UNSPECIFIED(&c->ip6.gw) &&
|
||||||
!IN6_IS_ADDR_LOOPBACK(&c->gw6))
|
!IN6_IS_ADDR_LOOPBACK(&c->ip6.gw))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (c->gw4 == INADDR_ANY &&
|
if (c->ip4.gw == INADDR_ANY &&
|
||||||
inet_pton(AF_INET, optarg, &c->gw4) &&
|
inet_pton(AF_INET, optarg, &c->ip4.gw) &&
|
||||||
c->gw4 != INADDR_ANY &&
|
c->ip4.gw != INADDR_ANY &&
|
||||||
c->gw4 != INADDR_BROADCAST &&
|
c->ip4.gw != INADDR_BROADCAST &&
|
||||||
c->gw4 != INADDR_LOOPBACK)
|
c->ip4.gw != INADDR_LOOPBACK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
err("Invalid gateway address: %s", optarg);
|
err("Invalid gateway address: %s", optarg);
|
||||||
|
@ -1410,7 +1414,7 @@ void conf(struct ctx *c, int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
if (c->no_dns ||
|
if (c->no_dns ||
|
||||||
(!optarg && (dns4 - c->dns4 || dns6 - c->dns6))) {
|
(!optarg && (dns4 - c->ip4.dns || dns6 - c->ip6.dns))) {
|
||||||
err("Empty and non-empty DNS options given");
|
err("Empty and non-empty DNS options given");
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
}
|
}
|
||||||
|
@ -1420,13 +1424,13 @@ void conf(struct ctx *c, int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dns4 - &c->dns4[0] < ARRAY_SIZE(c->dns4) &&
|
if (dns4 - &c->ip4.dns[0] < ARRAY_SIZE(c->ip4.dns) &&
|
||||||
inet_pton(AF_INET, optarg, dns4)) {
|
inet_pton(AF_INET, optarg, dns4)) {
|
||||||
dns4++;
|
dns4++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dns6 - &c->dns6[0] < ARRAY_SIZE(c->dns6) &&
|
if (dns6 - &c->ip6.dns[0] < ARRAY_SIZE(c->ip6.dns) &&
|
||||||
inet_pton(AF_INET6, optarg, dns6)) {
|
inet_pton(AF_INET6, optarg, dns6)) {
|
||||||
dns6++;
|
dns6++;
|
||||||
break;
|
break;
|
||||||
|
@ -1511,9 +1515,9 @@ void conf(struct ctx *c, int argc, char **argv)
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
}
|
}
|
||||||
if (!v6_only)
|
if (!v6_only)
|
||||||
c->ifi4 = conf_ip4(c, ifi);
|
c->ifi4 = conf_ip4(ifi, &c->ip4, c->mac);
|
||||||
if (!v4_only)
|
if (!v4_only)
|
||||||
c->ifi6 = conf_ip6(c, ifi);
|
c->ifi6 = conf_ip6(ifi, &c->ip6, c->mac);
|
||||||
if (!c->ifi4 && !c->ifi6) {
|
if (!c->ifi4 && !c->ifi6) {
|
||||||
err("External interface not usable");
|
err("External interface not usable");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
22
dhcp.c
22
dhcp.c
|
@ -332,20 +332,20 @@ int dhcp(const struct ctx *c, const struct pool *p)
|
||||||
m->chaddr[0], m->chaddr[1], m->chaddr[2],
|
m->chaddr[0], m->chaddr[1], m->chaddr[2],
|
||||||
m->chaddr[3], m->chaddr[4], m->chaddr[5]);
|
m->chaddr[3], m->chaddr[4], m->chaddr[5]);
|
||||||
|
|
||||||
m->yiaddr = c->addr4;
|
m->yiaddr = c->ip4.addr;
|
||||||
memcpy(opts[1].s, &c->mask4, sizeof(c->mask4));
|
memcpy(opts[1].s, &c->ip4.mask, sizeof(c->ip4.mask));
|
||||||
memcpy(opts[3].s, &c->gw4, sizeof(c->gw4));
|
memcpy(opts[3].s, &c->ip4.gw, sizeof(c->ip4.gw));
|
||||||
memcpy(opts[54].s, &c->gw4, sizeof(c->gw4));
|
memcpy(opts[54].s, &c->ip4.gw, sizeof(c->ip4.gw));
|
||||||
|
|
||||||
/* If the gateway is not on the assigned subnet, send an option 121
|
/* If the gateway is not on the assigned subnet, send an option 121
|
||||||
* (Classless Static Routing) adding a dummy route to it.
|
* (Classless Static Routing) adding a dummy route to it.
|
||||||
*/
|
*/
|
||||||
if ((c->addr4 & c->mask4) != (c->gw4 & c->mask4)) {
|
if ((c->ip4.addr & c->ip4.mask) != (c->ip4.gw & c->ip4.mask)) {
|
||||||
/* a.b.c.d/32:0.0.0.0, 0:a.b.c.d */
|
/* a.b.c.d/32:0.0.0.0, 0:a.b.c.d */
|
||||||
opts[121].slen = 14;
|
opts[121].slen = 14;
|
||||||
opts[121].s[0] = 32;
|
opts[121].s[0] = 32;
|
||||||
memcpy(opts[121].s + 1, &c->gw4, sizeof(c->gw4));
|
memcpy(opts[121].s + 1, &c->ip4.gw, sizeof(c->ip4.gw));
|
||||||
memcpy(opts[121].s + 10, &c->gw4, sizeof(c->gw4));
|
memcpy(opts[121].s + 10, &c->ip4.gw, sizeof(c->ip4.gw));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->mtu != -1) {
|
if (c->mtu != -1) {
|
||||||
|
@ -354,8 +354,8 @@ int dhcp(const struct ctx *c, const struct pool *p)
|
||||||
opts[26].s[1] = c->mtu % 256;
|
opts[26].s[1] = c->mtu % 256;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0, opts[6].slen = 0; !c->no_dhcp_dns && c->dns4[i]; i++) {
|
for (i = 0, opts[6].slen = 0; !c->no_dhcp_dns && c->ip4.dns[i]; i++) {
|
||||||
((uint32_t *)opts[6].s)[i] = c->dns4[i];
|
((uint32_t *)opts[6].s)[i] = c->ip4.dns[i];
|
||||||
opts[6].slen += sizeof(uint32_t);
|
opts[6].slen += sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,8 +368,8 @@ int dhcp(const struct ctx *c, const struct pool *p)
|
||||||
uh->dest = htons(68);
|
uh->dest = htons(68);
|
||||||
|
|
||||||
iph->tot_len = htons(len += sizeof(*iph));
|
iph->tot_len = htons(len += sizeof(*iph));
|
||||||
iph->daddr = c->addr4;
|
iph->daddr = c->ip4.addr;
|
||||||
iph->saddr = c->gw4;
|
iph->saddr = c->ip4.gw;
|
||||||
iph->check = 0;
|
iph->check = 0;
|
||||||
iph->check = csum_unaligned(iph, (intptr_t)(iph->ihl * 4), 0);
|
iph->check = csum_unaligned(iph, (intptr_t)(iph->ihl * 4), 0);
|
||||||
|
|
||||||
|
|
18
dhcpv6.c
18
dhcpv6.c
|
@ -390,7 +390,7 @@ static size_t dhcpv6_dns_fill(const struct ctx *c, char *buf, int offset)
|
||||||
if (c->no_dhcp_dns)
|
if (c->no_dhcp_dns)
|
||||||
goto search;
|
goto search;
|
||||||
|
|
||||||
for (i = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->dns6[i]); i++) {
|
for (i = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[i]); i++) {
|
||||||
if (!i) {
|
if (!i) {
|
||||||
srv = (struct opt_dns_servers *)(buf + offset);
|
srv = (struct opt_dns_servers *)(buf + offset);
|
||||||
offset += sizeof(struct opt_hdr);
|
offset += sizeof(struct opt_hdr);
|
||||||
|
@ -398,7 +398,7 @@ static size_t dhcpv6_dns_fill(const struct ctx *c, char *buf, int offset)
|
||||||
srv->hdr.l = 0;
|
srv->hdr.l = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&srv->addr[i], &c->dns6[i], sizeof(srv->addr[i]));
|
memcpy(&srv->addr[i], &c->ip6.dns[i], sizeof(srv->addr[i]));
|
||||||
srv->hdr.l += sizeof(srv->addr[i]);
|
srv->hdr.l += sizeof(srv->addr[i]);
|
||||||
offset += sizeof(srv->addr[i]);
|
offset += sizeof(srv->addr[i]);
|
||||||
}
|
}
|
||||||
|
@ -473,12 +473,12 @@ int dhcpv6(struct ctx *c, const struct pool *p,
|
||||||
if (mlen + sizeof(*uh) != ntohs(uh->len) || mlen < sizeof(*mh))
|
if (mlen + sizeof(*uh) != ntohs(uh->len) || mlen < sizeof(*mh))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
c->addr6_ll_seen = *saddr;
|
c->ip6.addr_ll_seen = *saddr;
|
||||||
|
|
||||||
if (IN6_IS_ADDR_LINKLOCAL(&c->gw6))
|
if (IN6_IS_ADDR_LINKLOCAL(&c->ip6.gw))
|
||||||
src = &c->gw6;
|
src = &c->ip6.gw;
|
||||||
else
|
else
|
||||||
src = &c->addr6_ll;
|
src = &c->ip6.addr_ll;
|
||||||
|
|
||||||
mh = packet_get(p, 0, sizeof(*uh), sizeof(*mh), NULL);
|
mh = packet_get(p, 0, sizeof(*uh), sizeof(*mh), NULL);
|
||||||
if (!mh)
|
if (!mh)
|
||||||
|
@ -508,7 +508,7 @@ int dhcpv6(struct ctx *c, const struct pool *p,
|
||||||
if (mh->type == TYPE_CONFIRM && server_id)
|
if (mh->type == TYPE_CONFIRM && server_id)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if ((bad_ia = dhcpv6_ia_notonlink(p, &c->addr6))) {
|
if ((bad_ia = dhcpv6_ia_notonlink(p, &c->ip6.addr))) {
|
||||||
info("DHCPv6: received CONFIRM with inappropriate IA,"
|
info("DHCPv6: received CONFIRM with inappropriate IA,"
|
||||||
" sending NotOnLink status in REPLY");
|
" sending NotOnLink status in REPLY");
|
||||||
|
|
||||||
|
@ -580,7 +580,7 @@ int dhcpv6(struct ctx *c, const struct pool *p,
|
||||||
resp.hdr.xid = mh->xid;
|
resp.hdr.xid = mh->xid;
|
||||||
|
|
||||||
tap_ip_send(c, src, IPPROTO_UDP, (char *)&resp, n, mh->xid);
|
tap_ip_send(c, src, IPPROTO_UDP, (char *)&resp, n, mh->xid);
|
||||||
c->addr6_seen = c->addr6;
|
c->ip6.addr_seen = c->ip6.addr;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -602,5 +602,5 @@ void dhcpv6_init(const struct ctx *c)
|
||||||
memcpy(resp.server_id.duid_lladdr, c->mac, sizeof(c->mac));
|
memcpy(resp.server_id.duid_lladdr, c->mac, sizeof(c->mac));
|
||||||
memcpy(resp_not_on_link.server_id.duid_lladdr, c->mac, sizeof(c->mac));
|
memcpy(resp_not_on_link.server_id.duid_lladdr, c->mac, sizeof(c->mac));
|
||||||
|
|
||||||
resp.ia_addr.addr = c->addr6;
|
resp.ia_addr.addr = c->ip6.addr;
|
||||||
}
|
}
|
||||||
|
|
16
ndp.c
16
ndp.c
|
@ -107,7 +107,7 @@ int ndp(struct ctx *c, const struct icmp6hdr *ih,
|
||||||
p += 4;
|
p += 4;
|
||||||
*(uint32_t *)p = htonl(3600); /* preferred lifetime */
|
*(uint32_t *)p = htonl(3600); /* preferred lifetime */
|
||||||
p += 8;
|
p += 8;
|
||||||
memcpy(p, &c->addr6, 8); /* prefix */
|
memcpy(p, &c->ip6.addr, 8); /* prefix */
|
||||||
p += 16;
|
p += 16;
|
||||||
|
|
||||||
if (c->mtu != -1) {
|
if (c->mtu != -1) {
|
||||||
|
@ -121,7 +121,7 @@ int ndp(struct ctx *c, const struct icmp6hdr *ih,
|
||||||
if (c->no_dhcp_dns)
|
if (c->no_dhcp_dns)
|
||||||
goto dns_done;
|
goto dns_done;
|
||||||
|
|
||||||
for (n = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->dns6[n]); n++);
|
for (n = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[n]); n++);
|
||||||
if (n) {
|
if (n) {
|
||||||
*p++ = 25; /* RDNSS */
|
*p++ = 25; /* RDNSS */
|
||||||
*p++ = 1 + 2 * n; /* length */
|
*p++ = 1 + 2 * n; /* length */
|
||||||
|
@ -130,7 +130,7 @@ int ndp(struct ctx *c, const struct icmp6hdr *ih,
|
||||||
p += 4;
|
p += 4;
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
memcpy(p, &c->dns6[i], 16); /* address */
|
memcpy(p, &c->ip6.dns[i], 16); /* address */
|
||||||
p += 16;
|
p += 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,15 +177,15 @@ dns_done:
|
||||||
len = (uintptr_t)p - (uintptr_t)ihr - sizeof(*ihr);
|
len = (uintptr_t)p - (uintptr_t)ihr - sizeof(*ihr);
|
||||||
|
|
||||||
if (IN6_IS_ADDR_LINKLOCAL(saddr))
|
if (IN6_IS_ADDR_LINKLOCAL(saddr))
|
||||||
c->addr6_ll_seen = *saddr;
|
c->ip6.addr_ll_seen = *saddr;
|
||||||
else
|
else
|
||||||
c->addr6_seen = *saddr;
|
c->ip6.addr_seen = *saddr;
|
||||||
|
|
||||||
ip6hr->daddr = *saddr;
|
ip6hr->daddr = *saddr;
|
||||||
if (IN6_IS_ADDR_LINKLOCAL(&c->gw6))
|
if (IN6_IS_ADDR_LINKLOCAL(&c->ip6.gw))
|
||||||
ip6hr->saddr = c->gw6;
|
ip6hr->saddr = c->ip6.gw;
|
||||||
else
|
else
|
||||||
ip6hr->saddr = c->addr6_ll;
|
ip6hr->saddr = c->ip6.addr_ll;
|
||||||
|
|
||||||
ip6hr->payload_len = htons(sizeof(*ihr) + len);
|
ip6hr->payload_len = htons(sizeof(*ihr) + len);
|
||||||
ip6hr->hop_limit = IPPROTO_ICMPV6;
|
ip6hr->hop_limit = IPPROTO_ICMPV6;
|
||||||
|
|
2
passt.c
2
passt.c
|
@ -363,7 +363,7 @@ int main(int argc, char **argv)
|
||||||
if ((!c.no_udp && udp_init(&c)) || (!c.no_tcp && tcp_init(&c)))
|
if ((!c.no_udp && udp_init(&c)) || (!c.no_tcp && tcp_init(&c)))
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
proto_update_l2_buf(c.mac_guest, c.mac, &c.addr4);
|
proto_update_l2_buf(c.mac_guest, c.mac, &c.ip4.addr);
|
||||||
|
|
||||||
if (c.ifi4 && !c.no_dhcp)
|
if (c.ifi4 && !c.no_dhcp)
|
||||||
dhcp_init();
|
dhcp_init();
|
||||||
|
|
68
passt.h
68
passt.h
|
@ -94,6 +94,44 @@ enum passt_modes {
|
||||||
MODE_PASTA,
|
MODE_PASTA,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
struct ip4_ctx {
|
||||||
|
uint32_t addr;
|
||||||
|
uint32_t addr_seen;
|
||||||
|
uint32_t mask;
|
||||||
|
uint32_t gw;
|
||||||
|
uint32_t dns[MAXNS + 1];
|
||||||
|
uint32_t dns_fwd;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ip6_ctx - IPv6 execution context
|
||||||
|
* @addr: IPv6 address for external, routable interface
|
||||||
|
* @addr_ll: Link-local IPv6 address on external, routable interface
|
||||||
|
* @addr_seen: Latest IPv6 global/site address seen as source from tap
|
||||||
|
* @addr_ll_seen: Latest IPv6 link-local address seen as source from tap
|
||||||
|
* @gw: Default IPv6 gateway
|
||||||
|
* @dns: IPv6 DNS addresses, zero-terminated
|
||||||
|
* @dns_fwd: Address forwarded (UDP) to first IPv6 DNS, network order
|
||||||
|
*/
|
||||||
|
struct ip6_ctx {
|
||||||
|
struct in6_addr addr;
|
||||||
|
struct in6_addr addr_ll;
|
||||||
|
struct in6_addr addr_seen;
|
||||||
|
struct in6_addr addr_ll_seen;
|
||||||
|
struct in6_addr gw;
|
||||||
|
struct in6_addr dns[MAXNS + 1];
|
||||||
|
struct in6_addr dns_fwd;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct ctx - Execution context
|
* struct ctx - Execution context
|
||||||
* @mode: Operation mode, qemu/UNIX domain socket or namespace/tap
|
* @mode: Operation mode, qemu/UNIX domain socket or namespace/tap
|
||||||
|
@ -122,21 +160,10 @@ enum passt_modes {
|
||||||
* @mac: Host MAC address
|
* @mac: Host MAC address
|
||||||
* @mac_guest: MAC address of guest or namespace, seen or configured
|
* @mac_guest: MAC address of guest or namespace, seen or configured
|
||||||
* @ifi4: Index of routable interface for IPv4, 0 if IPv4 disabled
|
* @ifi4: Index of routable interface for IPv4, 0 if IPv4 disabled
|
||||||
* @addr4: IPv4 address for external, routable interface
|
* @ip: IPv4 configuration
|
||||||
* @addr4_seen: Latest IPv4 address seen as source from tap
|
|
||||||
* @mask4: IPv4 netmask, network order
|
|
||||||
* @gw4: Default IPv4 gateway, network order
|
|
||||||
* @dns4: IPv4 DNS addresses, zero-terminated, network order
|
|
||||||
* @dns4_fwd: Address forwarded (UDP) to first IPv4 DNS, network order
|
|
||||||
* @dns_search: DNS search list
|
* @dns_search: DNS search list
|
||||||
* @ifi6: Index of routable interface for IPv6, 0 if IPv6 disabled
|
* @ifi6: Index of routable interface for IPv6, 0 if IPv6 disabled
|
||||||
* @addr6: IPv6 address for external, routable interface
|
* @ip6: IPv6 configuration
|
||||||
* @addr6_ll: Link-local IPv6 address on external, routable interface
|
|
||||||
* @addr6_seen: Latest IPv6 global/site address seen as source from tap
|
|
||||||
* @addr6_ll_seen: Latest IPv6 link-local address seen as source from tap
|
|
||||||
* @gw6: Default IPv6 gateway
|
|
||||||
* @dns6: IPv6 DNS addresses, zero-terminated
|
|
||||||
* @dns6_fwd: Address forwarded (UDP) to first IPv6 DNS, network order
|
|
||||||
* @pasta_ifn: Name of namespace interface for pasta
|
* @pasta_ifn: Name of namespace interface for pasta
|
||||||
* @pasta_ifn: Index of namespace interface for pasta
|
* @pasta_ifn: Index of namespace interface for pasta
|
||||||
* @pasta_conf_ns: Configure namespace interface after creating it
|
* @pasta_conf_ns: Configure namespace interface after creating it
|
||||||
|
@ -192,23 +219,12 @@ struct ctx {
|
||||||
unsigned char mac_guest[ETH_ALEN];
|
unsigned char mac_guest[ETH_ALEN];
|
||||||
|
|
||||||
unsigned int ifi4;
|
unsigned int ifi4;
|
||||||
uint32_t addr4;
|
struct ip4_ctx ip4;
|
||||||
uint32_t addr4_seen;
|
|
||||||
uint32_t mask4;
|
|
||||||
uint32_t gw4;
|
|
||||||
uint32_t dns4[MAXNS + 1];
|
|
||||||
uint32_t dns4_fwd;
|
|
||||||
|
|
||||||
struct fqdn dns_search[MAXDNSRCH];
|
struct fqdn dns_search[MAXDNSRCH];
|
||||||
|
|
||||||
unsigned int ifi6;
|
unsigned int ifi6;
|
||||||
struct in6_addr addr6;
|
struct ip6_ctx ip6;
|
||||||
struct in6_addr addr6_ll;
|
|
||||||
struct in6_addr addr6_seen;
|
|
||||||
struct in6_addr addr6_ll_seen;
|
|
||||||
struct in6_addr gw6;
|
|
||||||
struct in6_addr dns6[MAXNS + 1];
|
|
||||||
struct in6_addr dns6_fwd;
|
|
||||||
|
|
||||||
char pasta_ifn[IF_NAMESIZE];
|
char pasta_ifn[IF_NAMESIZE];
|
||||||
unsigned int pasta_ifi;
|
unsigned int pasta_ifi;
|
||||||
|
|
10
pasta.c
10
pasta.c
|
@ -196,17 +196,17 @@ void pasta_ns_conf(struct ctx *c)
|
||||||
nl_link(1, c->pasta_ifi, c->mac_guest, 1, c->mtu);
|
nl_link(1, c->pasta_ifi, c->mac_guest, 1, c->mtu);
|
||||||
|
|
||||||
if (c->ifi4) {
|
if (c->ifi4) {
|
||||||
prefix_len = __builtin_popcount(c->mask4);
|
prefix_len = __builtin_popcount(c->ip4.mask);
|
||||||
nl_addr(1, c->pasta_ifi, AF_INET, &c->addr4,
|
nl_addr(1, c->pasta_ifi, AF_INET, &c->ip4.addr,
|
||||||
&prefix_len, NULL);
|
&prefix_len, NULL);
|
||||||
nl_route(1, c->pasta_ifi, AF_INET, &c->gw4);
|
nl_route(1, c->pasta_ifi, AF_INET, &c->ip4.gw);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->ifi6) {
|
if (c->ifi6) {
|
||||||
prefix_len = 64;
|
prefix_len = 64;
|
||||||
nl_addr(1, c->pasta_ifi, AF_INET6, &c->addr6,
|
nl_addr(1, c->pasta_ifi, AF_INET6, &c->ip6.addr,
|
||||||
&prefix_len, NULL);
|
&prefix_len, NULL);
|
||||||
nl_route(1, c->pasta_ifi, AF_INET6, &c->gw6);
|
nl_route(1, c->pasta_ifi, AF_INET6, &c->ip6.gw);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nl_link(1, c->pasta_ifi, c->mac_guest, 0, 0);
|
nl_link(1, c->pasta_ifi, c->mac_guest, 0, 0);
|
||||||
|
|
22
tap.c
22
tap.c
|
@ -130,7 +130,7 @@ void tap_ip_send(const struct ctx *c, const struct in6_addr *src, uint8_t proto,
|
||||||
iph->frag_off = 0;
|
iph->frag_off = 0;
|
||||||
iph->ttl = 255;
|
iph->ttl = 255;
|
||||||
iph->protocol = proto;
|
iph->protocol = proto;
|
||||||
iph->daddr = c->addr4_seen;
|
iph->daddr = c->ip4.addr_seen;
|
||||||
memcpy(&iph->saddr, &src->s6_addr[12], 4);
|
memcpy(&iph->saddr, &src->s6_addr[12], 4);
|
||||||
|
|
||||||
iph->check = 0;
|
iph->check = 0;
|
||||||
|
@ -165,9 +165,9 @@ void tap_ip_send(const struct ctx *c, const struct in6_addr *src, uint8_t proto,
|
||||||
|
|
||||||
ip6h->saddr = *src;
|
ip6h->saddr = *src;
|
||||||
if (IN6_IS_ADDR_LINKLOCAL(src))
|
if (IN6_IS_ADDR_LINKLOCAL(src))
|
||||||
ip6h->daddr = c->addr6_ll_seen;
|
ip6h->daddr = c->ip6.addr_ll_seen;
|
||||||
else
|
else
|
||||||
ip6h->daddr = c->addr6_seen;
|
ip6h->daddr = c->ip6.addr_seen;
|
||||||
|
|
||||||
memcpy(data, in, len);
|
memcpy(data, in, len);
|
||||||
|
|
||||||
|
@ -354,9 +354,9 @@ resume:
|
||||||
|
|
||||||
l4_len = l3_len - hlen;
|
l4_len = l3_len - hlen;
|
||||||
|
|
||||||
if (iph->saddr && c->addr4_seen != iph->saddr) {
|
if (iph->saddr && c->ip4.addr_seen != iph->saddr) {
|
||||||
c->addr4_seen = iph->saddr;
|
c->ip4.addr_seen = iph->saddr;
|
||||||
proto_update_l2_buf(NULL, NULL, &c->addr4_seen);
|
proto_update_l2_buf(NULL, NULL, &c->ip4.addr_seen);
|
||||||
}
|
}
|
||||||
|
|
||||||
l4h = packet_get(in, i, sizeof(*eh) + hlen, l4_len, NULL);
|
l4h = packet_get(in, i, sizeof(*eh) + hlen, l4_len, NULL);
|
||||||
|
@ -504,13 +504,13 @@ resume:
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (IN6_IS_ADDR_LINKLOCAL(saddr)) {
|
if (IN6_IS_ADDR_LINKLOCAL(saddr)) {
|
||||||
c->addr6_ll_seen = *saddr;
|
c->ip6.addr_ll_seen = *saddr;
|
||||||
|
|
||||||
if (IN6_IS_ADDR_UNSPECIFIED(&c->addr6_seen)) {
|
if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.addr_seen)) {
|
||||||
c->addr6_seen = *saddr;
|
c->ip6.addr_seen = *saddr;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
c->addr6_seen = *saddr;
|
c->ip6.addr_seen = *saddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proto == IPPROTO_ICMPV6) {
|
if (proto == IPPROTO_ICMPV6) {
|
||||||
|
@ -545,7 +545,7 @@ resume:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
*saddr = c->addr6;
|
*saddr = c->ip6.addr;
|
||||||
|
|
||||||
if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
|
if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
|
||||||
tap_packet_debug(NULL, ip6h, NULL, proto, NULL, 1);
|
tap_packet_debug(NULL, ip6h, NULL, proto, NULL, 1);
|
||||||
|
|
34
tcp.c
34
tcp.c
|
@ -1700,9 +1700,9 @@ do { \
|
||||||
b->ip6h.payload_len = htons(plen + sizeof(struct tcphdr));
|
b->ip6h.payload_len = htons(plen + sizeof(struct tcphdr));
|
||||||
b->ip6h.saddr = conn->a.a6;
|
b->ip6h.saddr = conn->a.a6;
|
||||||
if (IN6_IS_ADDR_LINKLOCAL(&b->ip6h.saddr))
|
if (IN6_IS_ADDR_LINKLOCAL(&b->ip6h.saddr))
|
||||||
b->ip6h.daddr = c->addr6_ll_seen;
|
b->ip6h.daddr = c->ip6.addr_ll_seen;
|
||||||
else
|
else
|
||||||
b->ip6h.daddr = c->addr6_seen;
|
b->ip6h.daddr = c->ip6.addr_seen;
|
||||||
|
|
||||||
memset(b->ip6h.flow_lbl, 0, 3);
|
memset(b->ip6h.flow_lbl, 0, 3);
|
||||||
|
|
||||||
|
@ -1723,7 +1723,7 @@ do { \
|
||||||
ip_len = plen + sizeof(struct iphdr) + sizeof(struct tcphdr);
|
ip_len = plen + sizeof(struct iphdr) + sizeof(struct tcphdr);
|
||||||
b->iph.tot_len = htons(ip_len);
|
b->iph.tot_len = htons(ip_len);
|
||||||
b->iph.saddr = conn->a.a4.a.s_addr;
|
b->iph.saddr = conn->a.a4.a.s_addr;
|
||||||
b->iph.daddr = c->addr4_seen;
|
b->iph.daddr = c->ip4.addr_seen;
|
||||||
|
|
||||||
if (check)
|
if (check)
|
||||||
b->iph.check = *check;
|
b->iph.check = *check;
|
||||||
|
@ -2069,7 +2069,7 @@ static uint32_t tcp_seq_init(const struct ctx *c, int af, const void *addr,
|
||||||
} __attribute__((__packed__)) in = {
|
} __attribute__((__packed__)) in = {
|
||||||
.src = *(struct in_addr *)addr,
|
.src = *(struct in_addr *)addr,
|
||||||
.srcport = srcport,
|
.srcport = srcport,
|
||||||
.dst = { c->addr4 },
|
.dst = { c->ip4.addr },
|
||||||
.dstport = dstport,
|
.dstport = dstport,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2083,7 +2083,7 @@ static uint32_t tcp_seq_init(const struct ctx *c, int af, const void *addr,
|
||||||
} __attribute__((__packed__)) in = {
|
} __attribute__((__packed__)) in = {
|
||||||
.src = *(struct in6_addr *)addr,
|
.src = *(struct in6_addr *)addr,
|
||||||
.srcport = srcport,
|
.srcport = srcport,
|
||||||
.dst = c->addr6,
|
.dst = c->ip6.addr,
|
||||||
.dstport = dstport,
|
.dstport = dstport,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2197,16 +2197,16 @@ static void tcp_conn_from_tap(struct ctx *c, int af, const void *addr,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!c->no_map_gw) {
|
if (!c->no_map_gw) {
|
||||||
if (af == AF_INET && addr4.sin_addr.s_addr == c->gw4)
|
if (af == AF_INET && addr4.sin_addr.s_addr == c->ip4.gw)
|
||||||
addr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
addr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||||
if (af == AF_INET6 && IN6_ARE_ADDR_EQUAL(addr, &c->gw6))
|
if (af == AF_INET6 && IN6_ARE_ADDR_EQUAL(addr, &c->ip6.gw))
|
||||||
addr6.sin6_addr = in6addr_loopback;
|
addr6.sin6_addr = in6addr_loopback;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (af == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr)) {
|
if (af == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr)) {
|
||||||
struct sockaddr_in6 addr6_ll = {
|
struct sockaddr_in6 addr6_ll = {
|
||||||
.sin6_family = AF_INET6,
|
.sin6_family = AF_INET6,
|
||||||
.sin6_addr = c->addr6_ll,
|
.sin6_addr = c->ip6.addr_ll,
|
||||||
.sin6_scope_id = c->ifi6,
|
.sin6_scope_id = c->ifi6,
|
||||||
};
|
};
|
||||||
if (bind(s, (struct sockaddr *)&addr6_ll, sizeof(addr6_ll))) {
|
if (bind(s, (struct sockaddr *)&addr6_ll, sizeof(addr6_ll))) {
|
||||||
|
@ -2894,14 +2894,14 @@ static void tcp_conn_from_sock(struct ctx *c, union epoll_ref ref,
|
||||||
memcpy(&sa6, &sa, sizeof(sa6));
|
memcpy(&sa6, &sa, sizeof(sa6));
|
||||||
|
|
||||||
if (IN6_IS_ADDR_LOOPBACK(&sa6.sin6_addr) ||
|
if (IN6_IS_ADDR_LOOPBACK(&sa6.sin6_addr) ||
|
||||||
IN6_ARE_ADDR_EQUAL(&sa6.sin6_addr, &c->addr6_seen) ||
|
IN6_ARE_ADDR_EQUAL(&sa6.sin6_addr, &c->ip6.addr_seen) ||
|
||||||
IN6_ARE_ADDR_EQUAL(&sa6.sin6_addr, &c->addr6)) {
|
IN6_ARE_ADDR_EQUAL(&sa6.sin6_addr, &c->ip6.addr)) {
|
||||||
struct in6_addr *src;
|
struct in6_addr *src;
|
||||||
|
|
||||||
if (IN6_IS_ADDR_LINKLOCAL(&c->gw6))
|
if (IN6_IS_ADDR_LINKLOCAL(&c->ip6.gw))
|
||||||
src = &c->gw6;
|
src = &c->ip6.gw;
|
||||||
else
|
else
|
||||||
src = &c->addr6_ll;
|
src = &c->ip6.addr_ll;
|
||||||
|
|
||||||
memcpy(&sa6.sin6_addr, src, sizeof(*src));
|
memcpy(&sa6.sin6_addr, src, sizeof(*src));
|
||||||
}
|
}
|
||||||
|
@ -2928,8 +2928,8 @@ static void tcp_conn_from_sock(struct ctx *c, union epoll_ref ref,
|
||||||
memset(&conn->a.a4.one, 0xff, sizeof(conn->a.a4.one));
|
memset(&conn->a.a4.one, 0xff, sizeof(conn->a.a4.one));
|
||||||
|
|
||||||
if (s_addr >> IN_CLASSA_NSHIFT == IN_LOOPBACKNET ||
|
if (s_addr >> IN_CLASSA_NSHIFT == IN_LOOPBACKNET ||
|
||||||
s_addr == INADDR_ANY || htonl(s_addr) == c->addr4_seen)
|
s_addr == INADDR_ANY || htonl(s_addr) == c->ip4.addr_seen)
|
||||||
s_addr = ntohl(c->gw4);
|
s_addr = ntohl(c->ip4.gw);
|
||||||
|
|
||||||
s_addr = htonl(s_addr);
|
s_addr = htonl(s_addr);
|
||||||
memcpy(&conn->a.a4.a, &s_addr, sizeof(conn->a.a4.a));
|
memcpy(&conn->a.a4.a, &s_addr, sizeof(conn->a.a4.a));
|
||||||
|
@ -3118,7 +3118,7 @@ void tcp_sock_init(const struct ctx *c, int ns, sa_family_t af,
|
||||||
|
|
||||||
if (af == AF_INET || af == AF_UNSPEC) {
|
if (af == AF_INET || af == AF_UNSPEC) {
|
||||||
if (!addr && c->mode == MODE_PASTA)
|
if (!addr && c->mode == MODE_PASTA)
|
||||||
bind_addr = &c->addr4;
|
bind_addr = &c->ip4.addr;
|
||||||
else
|
else
|
||||||
bind_addr = addr;
|
bind_addr = addr;
|
||||||
|
|
||||||
|
@ -3159,7 +3159,7 @@ void tcp_sock_init(const struct ctx *c, int ns, sa_family_t af,
|
||||||
|
|
||||||
if (af == AF_INET6 || af == AF_UNSPEC) {
|
if (af == AF_INET6 || af == AF_UNSPEC) {
|
||||||
if (!addr && c->mode == MODE_PASTA)
|
if (!addr && c->mode == MODE_PASTA)
|
||||||
bind_addr = &c->addr6;
|
bind_addr = &c->ip6.addr;
|
||||||
else
|
else
|
||||||
bind_addr = addr;
|
bind_addr = addr;
|
||||||
|
|
||||||
|
|
62
udp.c
62
udp.c
|
@ -690,20 +690,20 @@ static void udp_sock_fill_data_v4(const struct ctx *c, int n,
|
||||||
src_port = htons(b->s_in.sin_port);
|
src_port = htons(b->s_in.sin_port);
|
||||||
|
|
||||||
if (src >> IN_CLASSA_NSHIFT == IN_LOOPBACKNET ||
|
if (src >> IN_CLASSA_NSHIFT == IN_LOOPBACKNET ||
|
||||||
src == INADDR_ANY || src == ntohl(c->addr4_seen)) {
|
src == INADDR_ANY || src == ntohl(c->ip4.addr_seen)) {
|
||||||
b->iph.saddr = c->gw4;
|
b->iph.saddr = c->ip4.gw;
|
||||||
udp_tap_map[V4][src_port].ts = now->tv_sec;
|
udp_tap_map[V4][src_port].ts = now->tv_sec;
|
||||||
udp_tap_map[V4][src_port].flags |= PORT_LOCAL;
|
udp_tap_map[V4][src_port].flags |= PORT_LOCAL;
|
||||||
|
|
||||||
if (b->s_in.sin_addr.s_addr == c->addr4_seen)
|
if (b->s_in.sin_addr.s_addr == c->ip4.addr_seen)
|
||||||
udp_tap_map[V4][src_port].flags &= ~PORT_LOOPBACK;
|
udp_tap_map[V4][src_port].flags &= ~PORT_LOOPBACK;
|
||||||
else
|
else
|
||||||
udp_tap_map[V4][src_port].flags |= PORT_LOOPBACK;
|
udp_tap_map[V4][src_port].flags |= PORT_LOOPBACK;
|
||||||
|
|
||||||
bitmap_set(udp_act[V4][UDP_ACT_TAP], src_port);
|
bitmap_set(udp_act[V4][UDP_ACT_TAP], src_port);
|
||||||
} else if (c->dns4_fwd &&
|
} else if (c->ip4.dns_fwd &&
|
||||||
src == ntohl(c->dns4[0]) && ntohs(src_port) == 53) {
|
src == ntohl(c->ip4.dns[0]) && ntohs(src_port) == 53) {
|
||||||
b->iph.saddr = c->dns4_fwd;
|
b->iph.saddr = c->ip4.dns_fwd;
|
||||||
} else {
|
} else {
|
||||||
b->iph.saddr = b->s_in.sin_addr.s_addr;
|
b->iph.saddr = b->s_in.sin_addr.s_addr;
|
||||||
}
|
}
|
||||||
|
@ -768,17 +768,17 @@ static void udp_sock_fill_data_v6(const struct ctx *c, int n,
|
||||||
b->ip6h.payload_len = htons(udp6_l2_mh_sock[n].msg_len + sizeof(b->uh));
|
b->ip6h.payload_len = htons(udp6_l2_mh_sock[n].msg_len + sizeof(b->uh));
|
||||||
|
|
||||||
if (IN6_IS_ADDR_LINKLOCAL(src)) {
|
if (IN6_IS_ADDR_LINKLOCAL(src)) {
|
||||||
b->ip6h.daddr = c->addr6_ll_seen;
|
b->ip6h.daddr = c->ip6.addr_ll_seen;
|
||||||
b->ip6h.saddr = b->s_in6.sin6_addr;
|
b->ip6h.saddr = b->s_in6.sin6_addr;
|
||||||
} else if (IN6_IS_ADDR_LOOPBACK(src) ||
|
} else if (IN6_IS_ADDR_LOOPBACK(src) ||
|
||||||
IN6_ARE_ADDR_EQUAL(src, &c->addr6_seen) ||
|
IN6_ARE_ADDR_EQUAL(src, &c->ip6.addr_seen) ||
|
||||||
IN6_ARE_ADDR_EQUAL(src, &c->addr6)) {
|
IN6_ARE_ADDR_EQUAL(src, &c->ip6.addr)) {
|
||||||
b->ip6h.daddr = c->addr6_ll_seen;
|
b->ip6h.daddr = c->ip6.addr_ll_seen;
|
||||||
|
|
||||||
if (IN6_IS_ADDR_LINKLOCAL(&c->gw6))
|
if (IN6_IS_ADDR_LINKLOCAL(&c->ip6.gw))
|
||||||
b->ip6h.saddr = c->gw6;
|
b->ip6h.saddr = c->ip6.gw;
|
||||||
else
|
else
|
||||||
b->ip6h.saddr = c->addr6_ll;
|
b->ip6h.saddr = c->ip6.addr_ll;
|
||||||
|
|
||||||
udp_tap_map[V6][src_port].ts = now->tv_sec;
|
udp_tap_map[V6][src_port].ts = now->tv_sec;
|
||||||
udp_tap_map[V6][src_port].flags |= PORT_LOCAL;
|
udp_tap_map[V6][src_port].flags |= PORT_LOCAL;
|
||||||
|
@ -788,18 +788,18 @@ static void udp_sock_fill_data_v6(const struct ctx *c, int n,
|
||||||
else
|
else
|
||||||
udp_tap_map[V6][src_port].flags &= ~PORT_LOOPBACK;
|
udp_tap_map[V6][src_port].flags &= ~PORT_LOOPBACK;
|
||||||
|
|
||||||
if (IN6_ARE_ADDR_EQUAL(src, &c->addr6))
|
if (IN6_ARE_ADDR_EQUAL(src, &c->ip6.addr))
|
||||||
udp_tap_map[V6][src_port].flags |= PORT_GUA;
|
udp_tap_map[V6][src_port].flags |= PORT_GUA;
|
||||||
else
|
else
|
||||||
udp_tap_map[V6][src_port].flags &= ~PORT_GUA;
|
udp_tap_map[V6][src_port].flags &= ~PORT_GUA;
|
||||||
|
|
||||||
bitmap_set(udp_act[V6][UDP_ACT_TAP], src_port);
|
bitmap_set(udp_act[V6][UDP_ACT_TAP], src_port);
|
||||||
} else if (!IN6_IS_ADDR_UNSPECIFIED(&c->dns6_fwd) &&
|
} else if (!IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_fwd) &&
|
||||||
IN6_ARE_ADDR_EQUAL(src, &c->dns6_fwd) && src_port == 53) {
|
IN6_ARE_ADDR_EQUAL(src, &c->ip6.dns_fwd) && src_port == 53) {
|
||||||
b->ip6h.daddr = c->addr6_seen;
|
b->ip6h.daddr = c->ip6.addr_seen;
|
||||||
b->ip6h.saddr = c->dns6_fwd;
|
b->ip6h.saddr = c->ip6.dns_fwd;
|
||||||
} else {
|
} else {
|
||||||
b->ip6h.daddr = c->addr6_seen;
|
b->ip6h.daddr = c->ip6.addr_seen;
|
||||||
b->ip6h.saddr = b->s_in6.sin6_addr;
|
b->ip6h.saddr = b->s_in6.sin6_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1015,15 +1015,15 @@ int udp_tap_handler(struct ctx *c, int af, const void *addr,
|
||||||
|
|
||||||
udp_tap_map[V4][src].ts = now->tv_sec;
|
udp_tap_map[V4][src].ts = now->tv_sec;
|
||||||
|
|
||||||
if (s_in.sin_addr.s_addr == c->gw4 && !c->no_map_gw) {
|
if (s_in.sin_addr.s_addr == c->ip4.gw && !c->no_map_gw) {
|
||||||
if (!(udp_tap_map[V4][dst].flags & PORT_LOCAL) ||
|
if (!(udp_tap_map[V4][dst].flags & PORT_LOCAL) ||
|
||||||
(udp_tap_map[V4][dst].flags & PORT_LOOPBACK))
|
(udp_tap_map[V4][dst].flags & PORT_LOOPBACK))
|
||||||
s_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
s_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||||
else
|
else
|
||||||
s_in.sin_addr.s_addr = c->addr4_seen;
|
s_in.sin_addr.s_addr = c->ip4.addr_seen;
|
||||||
} else if (s_in.sin_addr.s_addr == c->dns4_fwd &&
|
} else if (s_in.sin_addr.s_addr == c->ip4.dns_fwd &&
|
||||||
ntohs(s_in.sin_port) == 53) {
|
ntohs(s_in.sin_port) == 53) {
|
||||||
s_in.sin_addr.s_addr = c->dns4[0];
|
s_in.sin_addr.s_addr = c->ip4.dns[0];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s_in6 = (struct sockaddr_in6) {
|
s_in6 = (struct sockaddr_in6) {
|
||||||
|
@ -1036,19 +1036,19 @@ int udp_tap_handler(struct ctx *c, int af, const void *addr,
|
||||||
sa = (struct sockaddr *)&s_in6;
|
sa = (struct sockaddr *)&s_in6;
|
||||||
sl = sizeof(s_in6);
|
sl = sizeof(s_in6);
|
||||||
|
|
||||||
if (IN6_ARE_ADDR_EQUAL(addr, &c->gw6) && !c->no_map_gw) {
|
if (IN6_ARE_ADDR_EQUAL(addr, &c->ip6.gw) && !c->no_map_gw) {
|
||||||
if (!(udp_tap_map[V6][dst].flags & PORT_LOCAL) ||
|
if (!(udp_tap_map[V6][dst].flags & PORT_LOCAL) ||
|
||||||
(udp_tap_map[V6][dst].flags & PORT_LOOPBACK))
|
(udp_tap_map[V6][dst].flags & PORT_LOOPBACK))
|
||||||
s_in6.sin6_addr = in6addr_loopback;
|
s_in6.sin6_addr = in6addr_loopback;
|
||||||
else if (udp_tap_map[V6][dst].flags & PORT_GUA)
|
else if (udp_tap_map[V6][dst].flags & PORT_GUA)
|
||||||
s_in6.sin6_addr = c->addr6;
|
s_in6.sin6_addr = c->ip6.addr;
|
||||||
else
|
else
|
||||||
s_in6.sin6_addr = c->addr6_seen;
|
s_in6.sin6_addr = c->ip6.addr_seen;
|
||||||
} else if (IN6_ARE_ADDR_EQUAL(addr, &c->dns6_fwd) &&
|
} else if (IN6_ARE_ADDR_EQUAL(addr, &c->ip6.dns_fwd) &&
|
||||||
ntohs(s_in6.sin6_port) == 53) {
|
ntohs(s_in6.sin6_port) == 53) {
|
||||||
s_in6.sin6_addr = c->dns6[0];
|
s_in6.sin6_addr = c->ip6.dns[0];
|
||||||
} else if (IN6_IS_ADDR_LINKLOCAL(&s_in6.sin6_addr)) {
|
} else if (IN6_IS_ADDR_LINKLOCAL(&s_in6.sin6_addr)) {
|
||||||
bind_addr = &c->addr6_ll;
|
bind_addr = &c->ip6.addr_ll;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(s = udp_tap_map[V6][src].sock)) {
|
if (!(s = udp_tap_map[V6][src].sock)) {
|
||||||
|
@ -1122,7 +1122,7 @@ void udp_sock_init(const struct ctx *c, int ns, sa_family_t af,
|
||||||
|
|
||||||
if (af == AF_INET || af == AF_UNSPEC) {
|
if (af == AF_INET || af == AF_UNSPEC) {
|
||||||
if (!addr && c->mode == MODE_PASTA)
|
if (!addr && c->mode == MODE_PASTA)
|
||||||
bind_addr = &c->addr4;
|
bind_addr = &c->ip4.addr;
|
||||||
else
|
else
|
||||||
bind_addr = addr;
|
bind_addr = addr;
|
||||||
|
|
||||||
|
@ -1155,7 +1155,7 @@ void udp_sock_init(const struct ctx *c, int ns, sa_family_t af,
|
||||||
|
|
||||||
if (af == AF_INET6 || af == AF_UNSPEC) {
|
if (af == AF_INET6 || af == AF_UNSPEC) {
|
||||||
if (!addr && c->mode == MODE_PASTA)
|
if (!addr && c->mode == MODE_PASTA)
|
||||||
bind_addr = &c->addr6;
|
bind_addr = &c->ip6.addr;
|
||||||
else
|
else
|
||||||
bind_addr = addr;
|
bind_addr = addr;
|
||||||
|
|
||||||
|
|
4
util.c
4
util.c
|
@ -278,8 +278,8 @@ int sock_l4(const struct ctx *c, int af, uint8_t proto,
|
||||||
if (bind_addr) {
|
if (bind_addr) {
|
||||||
addr6.sin6_addr = *(struct in6_addr *)bind_addr;
|
addr6.sin6_addr = *(struct in6_addr *)bind_addr;
|
||||||
|
|
||||||
if (!memcmp(bind_addr, &c->addr6_ll,
|
if (!memcmp(bind_addr, &c->ip6.addr_ll,
|
||||||
sizeof(c->addr6_ll)))
|
sizeof(c->ip6.addr_ll)))
|
||||||
addr6.sin6_scope_id = c->ifi6;
|
addr6.sin6_scope_id = c->ifi6;
|
||||||
} else {
|
} else {
|
||||||
addr6.sin6_addr = in6addr_any;
|
addr6.sin6_addr = in6addr_any;
|
||||||
|
|
Loading…
Reference in a new issue