Commit 61c6c681 authored by Daniele Lacamera's avatar Daniele Lacamera

IPv6: frame push now accept an optional source address

Ping replies can be now correctly rebounced to the sender using the
destination in the request as source.

Fixes Tahi 2.14 and 2.15
parent 76ff09cb
......@@ -49,6 +49,7 @@ static int pico_icmp6_send_echoreply(struct pico_frame *echo)
struct pico_frame *reply = NULL;
struct pico_icmp6_hdr *ehdr = NULL, *rhdr = NULL;
struct pico_ip6 src;
struct pico_ip6 dst;
reply = pico_proto_ipv6.alloc(&pico_proto_ipv6, (uint16_t)(echo->transport_len));
if (!reply) {
......@@ -69,8 +70,10 @@ static int pico_icmp6_send_echoreply(struct pico_frame *echo)
memcpy(reply->payload, echo->payload, (uint32_t)(echo->transport_len - PICO_ICMP6HDR_ECHO_REQUEST_SIZE));
rhdr->crc = 0;
rhdr->crc = short_be(pico_icmp6_checksum(reply));
memcpy(src.addr, ((struct pico_ipv6_hdr *)echo->net_hdr)->src.addr, PICO_SIZE_IP6);
pico_ipv6_frame_push(reply, &src, PICO_PROTO_ICMP6, 0);
/* Get destination and source swapped */
memcpy(dst.addr, ((struct pico_ipv6_hdr *)echo->net_hdr)->src.addr, PICO_SIZE_IP6);
memcpy(src.addr, ((struct pico_ipv6_hdr *)echo->net_hdr)->dst.addr, PICO_SIZE_IP6);
pico_ipv6_frame_push(reply, &src, &dst, PICO_PROTO_ICMP6, 0);
return 0;
}
......@@ -199,7 +202,7 @@ static int pico_icmp6_notify(struct pico_frame *f, uint8_t type, uint8_t code, u
memcpy(notice->payload, f->net_hdr, notice->payload_len);
notice->dev = f->dev;
/* f->src is set in frame_push, checksum calculated there */
pico_ipv6_frame_push(notice, &ipv6_hdr->src, PICO_PROTO_ICMP6, 0);
pico_ipv6_frame_push(notice, NULL, &ipv6_hdr->src, PICO_PROTO_ICMP6, 0);
return 0;
}
......@@ -312,7 +315,7 @@ int pico_icmp6_neighbor_solicitation(struct pico_device *dev, struct pico_ip6 *d
sol->dev = dev;
/* f->src is set in frame_push, checksum calculated there */
pico_ipv6_frame_push(sol, &daddr, PICO_PROTO_ICMP6, (type == PICO_ICMP6_ND_DAD));
pico_ipv6_frame_push(sol, NULL, &daddr, PICO_PROTO_ICMP6, (type == PICO_ICMP6_ND_DAD));
return 0;
}
......@@ -365,7 +368,7 @@ int pico_icmp6_neighbor_advertisement(struct pico_frame *f, struct pico_ip6 *tar
adv->dev = f->dev;
/* f->src is set in frame_push, checksum calculated there */
pico_ipv6_frame_push(adv, &dst, PICO_PROTO_ICMP6, 0);
pico_ipv6_frame_push(adv, NULL, &dst, PICO_PROTO_ICMP6, 0);
return 0;
}
......@@ -404,7 +407,7 @@ int pico_icmp6_router_solicitation(struct pico_device *dev, struct pico_ip6 *src
sol->dev = dev;
/* f->src is set in frame_push, checksum calculated there */
pico_ipv6_frame_push(sol, &daddr, PICO_PROTO_ICMP6, 0);
pico_ipv6_frame_push(sol, NULL, &daddr, PICO_PROTO_ICMP6, 0);
return 0;
}
......@@ -459,7 +462,7 @@ int pico_icmp6_router_advertisement(struct pico_device *dev, struct pico_ip6 *ds
icmp6_hdr->crc = 0;
icmp6_hdr->crc = short_be(pico_icmp6_checksum(adv));
/* f->src is set in frame_push, checksum calculated there */
pico_ipv6_frame_push(adv, &dst_mcast, PICO_PROTO_ICMP6, 0);
pico_ipv6_frame_push(adv, NULL, &dst_mcast, PICO_PROTO_ICMP6, 0);
return 0;
}
......@@ -519,7 +522,7 @@ static int pico_icmp6_send_echo(struct pico_icmp6_ping_cookie *cookie)
hdr->crc = 0;
hdr->crc = short_be(pico_icmp6_checksum(echo));
echo->dev = cookie->dev;
pico_ipv6_frame_push(echo, &cookie->dst, PICO_PROTO_ICMP6, 0);
pico_ipv6_frame_push(echo, NULL, &cookie->dst, PICO_PROTO_ICMP6, 0);
return 0;
}
......
......@@ -980,7 +980,7 @@ static inline struct pico_ipv6_route *ipv6_pushed_frame_checks(struct pico_frame
return route;
}
static inline void ipv6_push_hdr_adjust(struct pico_frame *f, struct pico_ipv6_link *link, struct pico_ip6 *dst, uint8_t proto, int is_dad)
static inline void ipv6_push_hdr_adjust(struct pico_frame *f, struct pico_ipv6_link *link, struct pico_ip6 *src, struct pico_ip6 *dst, uint8_t proto, int is_dad)
{
struct pico_icmp6_hdr *icmp6_hdr = NULL;
struct pico_ipv6_hdr *hdr = NULL;
......@@ -992,7 +992,14 @@ static inline void ipv6_push_hdr_adjust(struct pico_frame *f, struct pico_ipv6_l
hdr->nxthdr = proto;
hdr->hop = f->dev->hostvars.hoplimit;
hdr->dst = *dst;
hdr->src = link->address;
if (!src)
/* Address defaults to the link information: src address selection is done via link */
hdr->src = link->address;
else {
/* Sender protocol is forcing an IPv6 address */
memcpy(hdr->src.addr, src->addr, PICO_SIZE_IP6);
}
if (f->send_ttl) {
hdr->hop = f->send_ttl;
......@@ -1047,7 +1054,7 @@ static int ipv6_frame_push_final(struct pico_frame *f)
struct pico_ipv6_link *pico_ipv6_linklocal_get(struct pico_device *dev);
int pico_ipv6_frame_push(struct pico_frame *f, struct pico_ip6 *dst, uint8_t proto, int is_dad)
int pico_ipv6_frame_push(struct pico_frame *f, struct pico_ip6 *src, struct pico_ip6 *dst, uint8_t proto, int is_dad)
{
struct pico_ipv6_route *route = NULL;
struct pico_ipv6_link *link = NULL;
......@@ -1095,7 +1102,7 @@ int pico_ipv6_frame_push(struct pico_frame *f, struct pico_ip6 *dst, uint8_t pro
#endif
push_final:
ipv6_push_hdr_adjust(f, link, dst, proto, is_dad);
ipv6_push_hdr_adjust(f, link, src, dst, proto, is_dad);
return ipv6_frame_push_final(f);
}
......@@ -1118,7 +1125,7 @@ static int pico_ipv6_frame_sock_push(struct pico_protocol *self, struct pico_fra
dst = &f->sock->remote_addr.ip6;
}
return pico_ipv6_frame_push(f, dst, (uint8_t)f->sock->proto->proto_number, 0);
return pico_ipv6_frame_push(f, NULL, dst, (uint8_t)f->sock->proto->proto_number, 0);
}
/* interface: protocol definition */
......
......@@ -110,7 +110,7 @@ int pico_ipv6_is_linklocal(const uint8_t addr[PICO_SIZE_IP6]);
int pico_ipv6_is_solicited(const uint8_t addr[PICO_SIZE_IP6]);
int pico_ipv6_is_unspecified(const uint8_t addr[PICO_SIZE_IP6]);
int pico_ipv6_frame_push(struct pico_frame *f, struct pico_ip6 *dst, uint8_t proto, int is_dad);
int pico_ipv6_frame_push(struct pico_frame *f, struct pico_ip6 *src, struct pico_ip6 *dst, uint8_t proto, int is_dad);
int pico_ipv6_route_add(struct pico_ip6 address, struct pico_ip6 netmask, struct pico_ip6 gateway, int metric, struct pico_ipv6_link *link);
void pico_ipv6_unreachable(struct pico_frame *f, uint8_t code);
......
......@@ -763,7 +763,7 @@ static void pico_ipv6_nd_timer_elapsed(pico_time now, struct pico_ipv6_neighbor
case PICO_ND_STATE_REACHABLE:
n->state = PICO_ND_STATE_STALE;
dbg("IPv6_ND: neighbor expired!\n");
//dbg("IPv6_ND: neighbor expired!\n");
return;
case PICO_ND_STATE_STALE:
......
......@@ -1369,7 +1369,7 @@ int pico_tcp_reply_rst(struct pico_frame *fr)
#endif
#ifdef PICO_SUPPORT_IPV6
} else {
pico_ipv6_frame_push(f, &(((struct pico_ipv6_hdr *)(f->net_hdr))->dst), PICO_PROTO_TCP, 0);
pico_ipv6_frame_push(f, NULL, &(((struct pico_ipv6_hdr *)(f->net_hdr))->dst), PICO_PROTO_TCP, 0);
#endif
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment