Skip to content

Commit

Permalink
IPv6: frame push now accept an optional source address
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Daniele Lacamera committed Apr 3, 2015
1 parent 76ff09c commit 61c6c68
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 16 deletions.
19 changes: 11 additions & 8 deletions modules/pico_icmp6.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down
17 changes: 12 additions & 5 deletions modules/pico_ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

Expand All @@ -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 */
Expand Down
2 changes: 1 addition & 1 deletion modules/pico_ipv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion modules/pico_ipv6_nd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion modules/pico_tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down

0 comments on commit 61c6c68

Please sign in to comment.