aboutgitcodebugslistschat
diff options
context:
space:
mode:
-rw-r--r--dhcpv6.c10
-rw-r--r--ndp.c6
-rw-r--r--tcp.c12
-rw-r--r--udp.c5
4 files changed, 28 insertions, 5 deletions
diff --git a/dhcpv6.c b/dhcpv6.c
index cac220e..27d3a9c 100644
--- a/dhcpv6.c
+++ b/dhcpv6.c
@@ -452,6 +452,7 @@ int dhcpv6(struct ctx *c, struct ethhdr *eh, size_t len)
{
struct ipv6hdr *ip6h = (struct ipv6hdr *)(eh + 1);
struct opt_hdr *ia, *bad_ia, *client_id, *server_id;
+ struct in6_addr *src;
struct msg_hdr *mh;
struct udphdr *uh;
uint8_t proto;
@@ -476,6 +477,11 @@ int dhcpv6(struct ctx *c, struct ethhdr *eh, size_t len)
c->addr6_ll_seen = ip6h->saddr;
+ if (IN6_IS_ADDR_LINKLOCAL(&c->gw6))
+ src = &c->gw6;
+ else
+ src = &c->addr6_ll;
+
mh = (struct msg_hdr *)(uh + 1);
mlen -= sizeof(struct msg_hdr);
@@ -527,7 +533,7 @@ int dhcpv6(struct ctx *c, struct ethhdr *eh, size_t len)
resp_not_on_link.hdr.xid = mh->xid;
- tap_ip_send(c, &c->gw6, IPPROTO_UDP,
+ tap_ip_send(c, src, IPPROTO_UDP,
(char *)&resp_not_on_link, n, mh->xid);
return 1;
@@ -577,7 +583,7 @@ int dhcpv6(struct ctx *c, struct ethhdr *eh, size_t len)
resp.hdr.xid = mh->xid;
- tap_ip_send(c, &c->gw6, IPPROTO_UDP, (char *)&resp, n, mh->xid);
+ tap_ip_send(c, src, IPPROTO_UDP, (char *)&resp, n, mh->xid);
c->addr6_seen = c->addr6;
return 1;
diff --git a/ndp.c b/ndp.c
index 10c091c..e779ae0 100644
--- a/ndp.c
+++ b/ndp.c
@@ -183,7 +183,11 @@ int ndp(struct ctx *c, struct ethhdr *eh, size_t len)
c->addr6_seen = ip6h->saddr;
ip6hr->daddr = ip6h->saddr;
- ip6hr->saddr = c->gw6;
+ if (IN6_IS_ADDR_LINKLOCAL(&c->gw6))
+ ip6hr->saddr = c->gw6;
+ else
+ ip6hr->saddr = c->addr6_ll;
+
ip6hr->payload_len = htons(sizeof(*ihr) + len);
ip6hr->hop_limit = IPPROTO_ICMPV6;
ihr->icmp6_cksum = 0;
diff --git a/tcp.c b/tcp.c
index c8815c5..6b5d29b 100644
--- a/tcp.c
+++ b/tcp.c
@@ -2921,8 +2921,16 @@ static void tcp_conn_from_sock(struct ctx *c, union epoll_ref ref,
if (IN6_IS_ADDR_LOOPBACK(&sa6.sin6_addr) ||
!memcmp(&sa6.sin6_addr, &c->addr6_seen, sizeof(c->gw6)) ||
- !memcmp(&sa6.sin6_addr, &c->addr6, sizeof(c->gw6)))
- memcpy(&sa6.sin6_addr, &c->gw6, sizeof(c->gw6));
+ !memcmp(&sa6.sin6_addr, &c->addr6, sizeof(c->gw6))) {
+ struct in6_addr *src;
+
+ if (IN6_IS_ADDR_LINKLOCAL(&c->gw6))
+ src = &c->gw6;
+ else
+ src = &c->addr6_ll;
+
+ memcpy(&sa6.sin6_addr, src, sizeof(*src));
+ }
memcpy(&conn->a.a6, &sa6.sin6_addr, sizeof(conn->a.a6));
diff --git a/udp.c b/udp.c
index bd03036..229c038 100644
--- a/udp.c
+++ b/udp.c
@@ -698,6 +698,11 @@ void udp_sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events,
in_port_t src = htons(b->s_in6.sin6_port);
b->ip6h.daddr = c->addr6_ll_seen;
+ if (IN6_IS_ADDR_LINKLOCAL(&c->gw6))
+ b->ip6h.saddr = c->gw6;
+ else
+ b->ip6h.saddr = c->addr6_ll;
+
b->ip6h.saddr = c->gw6;
udp_tap_map[V6][src].ts_local = now->tv_sec;