diff options
-rw-r--r-- | checksum.c | 7 | ||||
-rw-r--r-- | checksum.h | 3 | ||||
-rw-r--r-- | conf.c | 55 | ||||
-rw-r--r-- | dhcp.c | 11 | ||||
-rw-r--r-- | icmp.c | 3 | ||||
-rw-r--r-- | passt.c | 2 | ||||
-rw-r--r-- | passt.h | 12 | ||||
-rw-r--r-- | tap.c | 18 | ||||
-rw-r--r-- | tap.h | 8 | ||||
-rw-r--r-- | tcp.c | 48 | ||||
-rw-r--r-- | tcp.h | 2 | ||||
-rw-r--r-- | udp.c | 30 | ||||
-rw-r--r-- | udp.h | 2 | ||||
-rw-r--r-- | util.h | 12 |
14 files changed, 113 insertions, 100 deletions
@@ -133,7 +133,8 @@ void csum_ip4_header(struct iphdr *ip4h) * @payload: ICMPv4 packet payload * @len: Length of @payload (not including UDP) */ -void csum_udp4(struct udphdr *udp4hr, in_addr_t saddr, in_addr_t daddr, +void csum_udp4(struct udphdr *udp4hr, + struct in_addr saddr, struct in_addr daddr, const void *payload, size_t len) { /* UDP checksums are optional, so don't bother */ @@ -142,8 +143,8 @@ void csum_udp4(struct udphdr *udp4hr, in_addr_t saddr, in_addr_t daddr, if (UDP4_REAL_CHECKSUMS) { /* UNTESTED: if we did want real UDPv4 checksums, this * is roughly what we'd need */ - uint32_t psum = csum_fold(htonl(saddr)) - + csum_fold(htonl(daddr)) + uint32_t psum = csum_fold(saddr.s_addr) + + csum_fold(daddr.s_addr) + htons(len + sizeof(*udp4hr)) + htons(IPPROTO_UDP); /* Add in partial checksum for the UDP header alone */ @@ -14,7 +14,8 @@ uint32_t sum_16b(const void *buf, size_t len); uint16_t csum_fold(uint32_t sum); uint16_t csum_unaligned(const void *buf, size_t len, uint32_t init); void csum_ip4_header(struct iphdr *ip4h); -void csum_udp4(struct udphdr *udp4hr, in_addr_t saddr, in_addr_t daddr, +void csum_udp4(struct udphdr *udp4hr, + struct in_addr saddr, struct in_addr daddr, const void *payload, size_t len); void csum_icmp4(struct icmphdr *ih, const void *payload, size_t len); void csum_udp6(struct udphdr *udp6hr, @@ -358,12 +358,12 @@ static void get_dns(struct ctx *c) int dns4_set, dns6_set, dnss_set, dns_set, fd; struct in6_addr *dns6 = &c->ip6.dns[0]; struct fqdn *s = c->dns_search; - uint32_t *dns4 = &c->ip4.dns[0]; + struct in_addr *dns4 = &c->ip4.dns[0]; struct lineread resolvconf; int line_len; char *line, *p, *end; - dns4_set = !c->ifi4 || !!*dns4; + dns4_set = !c->ifi4 || !IN4_IS_ADDR_UNSPECIFIED(dns4); dns6_set = !c->ifi6 || !IN6_IS_ADDR_UNSPECIFIED(dns6); dnss_set = !!*s->n || c->no_dns_search; dns_set = (dns4_set && dns6_set) || c->no_dns; @@ -389,15 +389,15 @@ static void get_dns(struct ctx *c) dns4 - &c->ip4.dns[0] < ARRAY_SIZE(c->ip4.dns) - 1 && inet_pton(AF_INET, p + 1, dns4)) { /* We can only access local addresses via the gw redirect */ - if (IPV4_IS_LOOPBACK(ntohl(*dns4))) { + if (IN4_IS_ADDR_LOOPBACK(dns4)) { if (c->no_map_gw) { - *dns4 = 0; + dns4->s_addr = htonl(INADDR_ANY); continue; } *dns4 = c->ip4.gw; } dns4++; - *dns4 = 0; + dns4->s_addr = htonl(INADDR_ANY); } if (!dns6_set && @@ -566,18 +566,19 @@ static unsigned int conf_ip4(unsigned int ifi, return 0; } - if (!ip4->gw) + if (IN4_IS_ADDR_UNSPECIFIED(&ip4->gw)) nl_route(0, ifi, AF_INET, &ip4->gw); - if (!ip4->addr) + if (IN4_IS_ADDR_UNSPECIFIED(&ip4->addr)) nl_addr(0, ifi, AF_INET, &ip4->addr, &ip4->prefix_len, NULL); if (!ip4->prefix_len) { - if (IN_CLASSA(ntohl(ip4->addr))) + in_addr_t addr = ntohl(ip4->addr.s_addr); + if (IN_CLASSA(addr)) ip4->prefix_len = (32 - IN_CLASSA_NSHIFT); - else if (IN_CLASSB(ntohl(ip4->addr))) + else if (IN_CLASSB(addr)) ip4->prefix_len = (32 - IN_CLASSB_NSHIFT); - else if (IN_CLASSC(ntohl(ip4->addr))) + else if (IN_CLASSC(addr)) ip4->prefix_len = (32 - IN_CLASSC_NSHIFT); else ip4->prefix_len = 32; @@ -588,7 +589,9 @@ static unsigned int conf_ip4(unsigned int ifi, if (MAC_IS_ZERO(mac)) nl_link(0, ifi, mac, 0, 0); - if (!ip4->gw || !ip4->addr || MAC_IS_ZERO(mac)) + if (IN4_IS_ADDR_UNSPECIFIED(&ip4->gw) || + IN4_IS_ADDR_UNSPECIFIED(&ip4->addr) || + MAC_IS_ZERO(mac)) return 0; return ifi; @@ -850,7 +853,7 @@ static void conf_print(const struct ctx *c) inet_ntop(AF_INET, &c->ip4.gw, buf4, sizeof(buf4))); } - for (i = 0; c->ip4.dns[i]; i++) { + for (i = 0; !IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns[i]); i++) { if (!i) info("DNS:"); inet_ntop(AF_INET, &c->ip4.dns[i], buf4, sizeof(buf4)); @@ -1088,7 +1091,7 @@ void conf(struct ctx *c, int argc, char **argv) char *runas = NULL, *logfile = NULL; struct in6_addr *dns6 = c->ip6.dns; struct fqdn *dnss = c->dns_search; - uint32_t *dns4 = c->ip4.dns; + struct in_addr *dns4 = c->ip4.dns; const char *optstring; unsigned int ifi = 0; int name, ret, b, i; @@ -1186,11 +1189,11 @@ void conf(struct ctx *c, int argc, char **argv) !IN6_IS_ADDR_LOOPBACK(&c->ip6.dns_fwd)) break; - if (c->ip4.dns_fwd == htonl(INADDR_ANY) && + if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_fwd) && inet_pton(AF_INET, optarg, &c->ip4.dns_fwd) && - c->ip4.dns_fwd != htonl(INADDR_ANY) && - c->ip4.dns_fwd != htonl(INADDR_BROADCAST) && - !IPV4_IS_LOOPBACK(ntohl(c->ip4.dns_fwd))) + !IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_fwd) && + !IN4_IS_ADDR_BROADCAST(&c->ip4.dns_fwd) && + !IN4_IS_ADDR_LOOPBACK(&c->ip4.dns_fwd)) break; err("Invalid DNS forwarding address: %s", optarg); @@ -1384,12 +1387,12 @@ void conf(struct ctx *c, int argc, char **argv) !IN6_IS_ADDR_MULTICAST(&c->ip6.addr)) break; - if (c->ip4.addr == htonl(INADDR_ANY) && + if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.addr) && inet_pton(AF_INET, optarg, &c->ip4.addr) && - c->ip4.addr != htonl(INADDR_ANY) && - c->ip4.addr != htonl(INADDR_BROADCAST) && - !IPV4_IS_LOOPBACK(ntohl(c->ip4.addr)) && - !IN_MULTICAST(ntohl(c->ip4.addr))) + !IN4_IS_ADDR_UNSPECIFIED(&c->ip4.addr) && + !IN4_IS_ADDR_BROADCAST(&c->ip4.addr) && + !IN4_IS_ADDR_LOOPBACK(&c->ip4.addr) && + !IN4_IS_ADDR_MULTICAST(&c->ip4.addr)) break; err("Invalid address: %s", optarg); @@ -1420,11 +1423,11 @@ void conf(struct ctx *c, int argc, char **argv) !IN6_IS_ADDR_LOOPBACK(&c->ip6.gw)) break; - if (c->ip4.gw == htonl(INADDR_ANY) && + if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.gw) && inet_pton(AF_INET, optarg, &c->ip4.gw) && - c->ip4.gw != htonl(INADDR_ANY) && - c->ip4.gw != htonl(INADDR_BROADCAST) && - !IPV4_IS_LOOPBACK(ntohl(c->ip4.gw))) + !IN4_IS_ADDR_UNSPECIFIED(&c->ip4.gw) && + !IN4_IS_ADDR_BROADCAST(&c->ip4.gw) && + !IN4_IS_ADDR_LOOPBACK(&c->ip4.gw)) break; err("Invalid gateway address: %s", optarg); @@ -107,7 +107,7 @@ struct msg { uint16_t secs; uint16_t flags; uint32_t ciaddr; - uint32_t yiaddr; + struct in_addr yiaddr; uint32_t siaddr; uint32_t giaddr; uint8_t chaddr[16]; @@ -343,7 +343,8 @@ int dhcp(const struct ctx *c, const struct pool *p) /* 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 & mask.s_addr) != (c->ip4.gw & mask.s_addr)) { + if ((c->ip4.addr.s_addr & mask.s_addr) + != (c->ip4.gw.s_addr & 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; @@ -357,8 +358,10 @@ int dhcp(const struct ctx *c, const struct pool *p) opts[26].s[1] = c->mtu % 256; } - for (i = 0, opts[6].slen = 0; !c->no_dhcp_dns && c->ip4.dns[i]; i++) { - ((uint32_t *)opts[6].s)[i] = c->ip4.dns[i]; + for (i = 0, opts[6].slen = 0; + !c->no_dhcp_dns && !IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns[i]); + i++) { + ((struct in_addr *)opts[6].s)[i] = c->ip4.dns[i]; opts[6].slen += sizeof(uint32_t); } @@ -130,8 +130,7 @@ void icmp_sock_handler(const struct ctx *c, union epoll_ref ref, debug("ICMP: echo %s to tap, ID: %i, seq: %i", (ih->type == ICMP_ECHO) ? "request" : "reply", id, seq); - tap_icmp4_send(c, sr4->sin_addr.s_addr, tap_ip4_daddr(c), - buf, n); + tap_icmp4_send(c, sr4->sin_addr, tap_ip4_daddr(c), buf, n); } } @@ -136,7 +136,7 @@ static void timer_init(struct ctx *c, const struct timespec *now) * @ip_da: Pointer to IPv4 destination address, NULL if unchanged */ void proto_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s, - const uint32_t *ip_da) + const struct in_addr *ip_da) { tcp_update_l2_buf(eth_d, eth_s, ip_da); udp_update_l2_buf(eth_d, eth_s, ip_da); @@ -105,12 +105,12 @@ enum passt_modes { * @dns_fwd: Address forwarded (UDP) to first IPv4 DNS, network order */ struct ip4_ctx { - uint32_t addr; - uint32_t addr_seen; + struct in_addr addr; + struct in_addr addr_seen; int prefix_len; - uint32_t gw; - uint32_t dns[MAXNS + 1]; - uint32_t dns_fwd; + struct in_addr gw; + struct in_addr dns[MAXNS + 1]; + struct in_addr dns_fwd; }; /** @@ -248,6 +248,6 @@ struct ctx { }; void proto_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s, - const uint32_t *ip_da); + const struct in_addr *ip_da); #endif /* PASST_H */ @@ -92,7 +92,7 @@ int tap_send(const struct ctx *c, const void *data, size_t len) * * Returns: IPv4 address, network order */ -in_addr_t tap_ip4_daddr(const struct ctx *c) +struct in_addr tap_ip4_daddr(const struct ctx *c) { return c->ip4.addr_seen; } @@ -141,7 +141,7 @@ static void *tap_push_l2h(const struct ctx *c, void *buf, uint16_t proto) * * Return: pointer at which to write the packet's payload */ -static void *tap_push_ip4h(char *buf, in_addr_t src, in_addr_t dst, +static void *tap_push_ip4h(char *buf, struct in_addr src, struct in_addr dst, size_t len, uint8_t proto) { struct iphdr *ip4h = (struct iphdr *)buf; @@ -154,8 +154,8 @@ static void *tap_push_ip4h(char *buf, in_addr_t src, in_addr_t dst, ip4h->frag_off = 0; ip4h->ttl = 255; ip4h->protocol = proto; - ip4h->saddr = src; - ip4h->daddr = dst; + ip4h->saddr = src.s_addr; + ip4h->daddr = dst.s_addr; csum_ip4_header(ip4h); return ip4h + 1; } @@ -170,8 +170,8 @@ static void *tap_push_ip4h(char *buf, in_addr_t src, in_addr_t dst, * @in: UDP payload contents (not including UDP header) * @len: UDP payload length (not including UDP header) */ -void tap_udp4_send(const struct ctx *c, in_addr_t src, in_port_t sport, - in_addr_t dst, in_port_t dport, +void tap_udp4_send(const struct ctx *c, struct in_addr src, in_port_t sport, + struct in_addr dst, in_port_t dport, const void *in, size_t len) { size_t udplen = len + sizeof(struct udphdr); @@ -199,7 +199,7 @@ void tap_udp4_send(const struct ctx *c, in_addr_t src, in_port_t sport, * @in: ICMP packet, including ICMP header * @len: ICMP packet length, including ICMP header */ -void tap_icmp4_send(const struct ctx *c, in_addr_t src, in_addr_t dst, +void tap_icmp4_send(const struct ctx *c, struct in_addr src, struct in_addr dst, void *in, size_t len) { char buf[USHRT_MAX]; @@ -448,8 +448,8 @@ resume: l4_len = l3_len - hlen; - if (iph->saddr && c->ip4.addr_seen != iph->saddr) { - c->ip4.addr_seen = iph->saddr; + if (iph->saddr && c->ip4.addr_seen.s_addr != iph->saddr) { + c->ip4.addr_seen.s_addr = iph->saddr; proto_update_l2_buf(NULL, NULL, &c->ip4.addr_seen); } @@ -6,11 +6,11 @@ #ifndef TAP_H #define TAP_H -in_addr_t tap_ip4_daddr(const struct ctx *c); -void tap_udp4_send(const struct ctx *c, in_addr_t src, in_port_t sport, - in_addr_t dst, in_port_t dport, +struct in_addr tap_ip4_daddr(const struct ctx *c); +void tap_udp4_send(const struct ctx *c, struct in_addr src, in_port_t sport, + struct in_addr dst, in_port_t dport, const void *in, size_t len); -void tap_icmp4_send(const struct ctx *c, in_addr_t src, in_addr_t dst, +void tap_icmp4_send(const struct ctx *c, struct in_addr src, struct in_addr dst, void *in, size_t len); const struct in6_addr *tap_ip6_daddr(const struct ctx *c, const struct in6_addr *src); @@ -1107,7 +1107,7 @@ static void tcp_update_check_tcp6(struct tcp6_l2_buf_t *buf) * @ip_da: Pointer to IPv4 destination address, NULL if unchanged */ void tcp_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s, - const uint32_t *ip_da) + const struct in_addr *ip_da) { int i; @@ -1134,16 +1134,16 @@ void tcp_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s, } if (ip_da) { - b4f->iph.daddr = b4->iph.daddr = *ip_da; + b4f->iph.daddr = b4->iph.daddr = ip_da->s_addr; if (!i) { b4f->iph.saddr = b4->iph.saddr = 0; b4f->iph.tot_len = b4->iph.tot_len = 0; b4f->iph.check = b4->iph.check = 0; b4f->psum = b4->psum = sum_16b(&b4->iph, 20); - b4->tsum = ((*ip_da >> 16) & 0xffff) + - (*ip_da & 0xffff) + - htons(IPPROTO_TCP); + b4->tsum = ((ip_da->s_addr >> 16) & 0xffff) + + (ip_da->s_addr & 0xffff) + + htons(IPPROTO_TCP); b4f->tsum = b4->tsum; } else { b4f->psum = b4->psum = tcp4_l2_buf[0].psum; @@ -1701,7 +1701,7 @@ do { \ ip_len = plen + sizeof(struct iphdr) + sizeof(struct tcphdr); b->iph.tot_len = htons(ip_len); b->iph.saddr = conn->a.a4.a.s_addr; - b->iph.daddr = c->ip4.addr_seen; + b->iph.daddr = c->ip4.addr_seen.s_addr; if (check) b->iph.check = *check; @@ -2048,7 +2048,7 @@ static uint32_t tcp_seq_init(const struct ctx *c, int af, const void *addr, } __attribute__((__packed__)) in = { .src = *(struct in_addr *)addr, .srcport = srcport, - .dst = { c->ip4.addr }, + .dst = c->ip4.addr, .dstport = dstport, }; @@ -2176,10 +2176,10 @@ static void tcp_conn_from_tap(struct ctx *c, int af, const void *addr, return; if (!c->no_map_gw) { - if (af == AF_INET && addr4.sin_addr.s_addr == c->ip4.gw) - addr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + if (af == AF_INET && IN4_ARE_ADDR_EQUAL(addr, &c->ip4.gw)) + addr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 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)) { @@ -2899,30 +2899,28 @@ static void tcp_conn_from_sock(struct ctx *c, union epoll_ref ref, tcp_hash_insert(c, conn, AF_INET6, &sa6.sin6_addr); } else { struct sockaddr_in sa4; - in_addr_t s_addr; memcpy(&sa4, &sa, sizeof(sa4)); - s_addr = ntohl(sa4.sin_addr.s_addr); memset(&conn->a.a4.zero, 0, sizeof(conn->a.a4.zero)); memset(&conn->a.a4.one, 0xff, sizeof(conn->a.a4.one)); - if (IPV4_IS_LOOPBACK(s_addr) || s_addr == INADDR_ANY || - htonl(s_addr) == c->ip4.addr_seen) - s_addr = ntohl(c->ip4.gw); + if (IN4_IS_ADDR_LOOPBACK(&sa4.sin_addr) || + IN4_IS_ADDR_UNSPECIFIED(&sa4.sin_addr) || + IN4_ARE_ADDR_EQUAL(&sa4.sin_addr, &c->ip4.addr_seen)) + sa4.sin_addr = c->ip4.gw; - s_addr = htonl(s_addr); - memcpy(&conn->a.a4.a, &s_addr, sizeof(conn->a.a4.a)); + conn->a.a4.a = sa4.sin_addr; conn->sock_port = ntohs(sa4.sin_port); conn->tap_port = ref.r.p.tcp.tcp.index; - conn->seq_to_tap = tcp_seq_init(c, AF_INET, &s_addr, + conn->seq_to_tap = tcp_seq_init(c, AF_INET, &sa4.sin_addr, conn->sock_port, conn->tap_port, now); - tcp_hash_insert(c, conn, AF_INET, &s_addr); + tcp_hash_insert(c, conn, AF_INET, &sa4.sin_addr); } conn->seq_ack_from_tap = conn->seq_to_tap + 1; @@ -3081,7 +3079,7 @@ void tcp_sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events, * @ifname: Name of interface to bind to, NULL if not configured * @port: Port, host order */ -static void tcp_sock_init4(const struct ctx *c, int ns, const in_addr_t *addr, +static void tcp_sock_init4(const struct ctx *c, int ns, const struct in_addr *addr, const char *ifname, in_port_t port) { union tcp_epoll_ref tref = { .tcp.listen = 1, .tcp.outbound = ns }; @@ -3089,14 +3087,13 @@ static void tcp_sock_init4(const struct ctx *c, int ns, const in_addr_t *addr, int s; if (c->mode == MODE_PASTA) { - spliced = !addr || - ntohl(*addr) == INADDR_ANY || - IPV4_IS_LOOPBACK(ntohl(*addr)); + spliced = !addr || IN4_IS_ADDR_UNSPECIFIED(addr) || + IN4_IS_ADDR_LOOPBACK(addr); if (!addr) addr = &c->ip4.addr; - tap = !ns && !IPV4_IS_LOOPBACK(ntohl(*addr)); + tap = !ns && !IN4_IS_ADDR_LOOPBACK(addr); } if (ns) @@ -3117,9 +3114,10 @@ static void tcp_sock_init4(const struct ctx *c, int ns, const in_addr_t *addr, } if (spliced) { + struct in_addr loopback = { htonl(INADDR_LOOPBACK) }; tref.tcp.splice = 1; - addr = &(uint32_t){ htonl(INADDR_LOOPBACK) }; + addr = &loopback; s = sock_l4(c, AF_INET, IPPROTO_TCP, addr, ifname, port, tref.u32); @@ -28,7 +28,7 @@ void tcp_defer_handler(struct ctx *c); void tcp_sock_set_bufsize(const struct ctx *c, int s); void tcp_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s, - const uint32_t *ip_da); + const struct in_addr *ip_da); /** * union tcp_epoll_ref - epoll reference portion for TCP connections @@ -298,7 +298,7 @@ static void udp_update_check4(struct udp4_l2_buf_t *buf) * @ip_da: Pointer to IPv4 destination address, NULL if unchanged */ void udp_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s, - const uint32_t *ip_da) + const struct in_addr *ip_da) { int i; @@ -317,7 +317,7 @@ void udp_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s, } if (ip_da) { - b4->iph.daddr = *ip_da; + b4->iph.daddr = ip_da->s_addr; if (!i) { b4->iph.saddr = 0; b4->iph.tot_len = 0; @@ -671,30 +671,30 @@ static void udp_sock_fill_data_v4(const struct ctx *c, int n, struct udp4_l2_buf_t *b = &udp4_l2_buf[n]; size_t ip_len, buf_len; in_port_t src_port; - in_addr_t src; ip_len = udp4_l2_mh_sock[n].msg_len + sizeof(b->iph) + sizeof(b->uh); b->iph.tot_len = htons(ip_len); - src = ntohl(b->s_in.sin_addr.s_addr); src_port = ntohs(b->s_in.sin_port); - if (IPV4_IS_LOOPBACK(src) || - src == INADDR_ANY || src == ntohl(c->ip4.addr_seen)) { - b->iph.saddr = c->ip4.gw; + if (IN4_IS_ADDR_LOOPBACK(&b->s_in.sin_addr) || + IN4_IS_ADDR_UNSPECIFIED(&b->s_in.sin_addr)|| + IN4_ARE_ADDR_EQUAL(&b->s_in.sin_addr, &c->ip4.addr_seen)) { + b->iph.saddr = c->ip4.gw.s_addr; udp_tap_map[V4][src_port].ts = now->tv_sec; udp_tap_map[V4][src_port].flags |= PORT_LOCAL; - if (b->s_in.sin_addr.s_addr == c->ip4.addr_seen) + if (IN4_ARE_ADDR_EQUAL(&b->s_in.sin_addr.s_addr, &c->ip4.addr_seen)) udp_tap_map[V4][src_port].flags &= ~PORT_LOOPBACK; else udp_tap_map[V4][src_port].flags |= PORT_LOOPBACK; bitmap_set(udp_act[V4][UDP_ACT_TAP], src_port); - } else if (c->ip4.dns_fwd && - src == htonl(c->ip4.dns[0]) && src_port == 53) { - b->iph.saddr = c->ip4.dns_fwd; + } else if (!IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_fwd) && + IN4_ARE_ADDR_EQUAL(&b->s_in.sin_addr, &c->ip4.dns[0]) && + src_port == 53) { + b->iph.saddr = c->ip4.dns_fwd.s_addr; } else { b->iph.saddr = b->s_in.sin_addr.s_addr; } @@ -1016,15 +1016,15 @@ int udp_tap_handler(struct ctx *c, int af, const void *addr, udp_tap_map[V4][src].ts = now->tv_sec; - if (s_in.sin_addr.s_addr == c->ip4.gw && !c->no_map_gw) { + if (IN4_ARE_ADDR_EQUAL(&s_in.sin_addr, &c->ip4.gw) && !c->no_map_gw) { if (!(udp_tap_map[V4][dst].flags & PORT_LOCAL) || (udp_tap_map[V4][dst].flags & PORT_LOOPBACK)) s_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); else - s_in.sin_addr.s_addr = c->ip4.addr_seen; - } else if (s_in.sin_addr.s_addr == c->ip4.dns_fwd && + s_in.sin_addr = c->ip4.addr_seen; + } else if (IN4_ARE_ADDR_EQUAL(&s_in.sin_addr, &c->ip4.dns_fwd) && ntohs(s_in.sin_port) == 53) { - s_in.sin_addr.s_addr = c->ip4.dns[0]; + s_in.sin_addr = c->ip4.dns[0]; } } else { s_in6 = (struct sockaddr_in6) { @@ -17,7 +17,7 @@ void udp_sock_init(const struct ctx *c, int ns, sa_family_t af, int udp_init(struct ctx *c); void udp_timer(struct ctx *c, const struct timespec *ts); void udp_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s, - const uint32_t *ip_da); + const struct in_addr *ip_da); /** * union udp_epoll_ref - epoll reference portion for TCP connections @@ -69,8 +69,16 @@ #define MAC_ZERO ((uint8_t [ETH_ALEN]){ 0 }) #define MAC_IS_ZERO(addr) (!memcmp((addr), MAC_ZERO, ETH_ALEN)) -#define IPV4_IS_LOOPBACK(addr) \ - ((addr) >> IN_CLASSA_NSHIFT == IN_LOOPBACKNET) +#define IN4_IS_ADDR_UNSPECIFIED(a) \ + ((a)->s_addr == htonl(INADDR_ANY)) +#define IN4_IS_ADDR_BROADCAST(a) \ + ((a)->s_addr == htonl(INADDR_BROADCAST)) +#define IN4_IS_ADDR_LOOPBACK(a) \ + (ntohl((a)->s_addr) >> IN_CLASSA_NSHIFT == IN_LOOPBACKNET) +#define IN4_IS_ADDR_MULTICAST(a) \ + (IN_MULTICAST(ntohl((a)->s_addr))) +#define IN4_ARE_ADDR_EQUAL(a, b) \ + (((struct in_addr *)(a))->s_addr == ((struct in_addr *)b)->s_addr) #define NS_FN_STACK_SIZE (RLIMIT_STACK_VAL * 1024 / 8) #define NS_CALL(fn, arg) \ |