slirp: Adding ICMPv6 error sending

Adding icmp6_send_error to send ICMPv6 Error messages. This function is
simpler than the v4 version.
Adding some calls in various functions to send ICMP errors, when a
received packet is too big, or when its hop limit is 0.

Signed-off-by: Yann Bordenave <meow@meowstars.org>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
This commit is contained in:
Yann Bordenave 2016-03-15 10:31:19 +01:00 committed by Samuel Thibault
parent de40abfecf
commit fc6c9257c6
3 changed files with 84 additions and 3 deletions

View file

@ -60,6 +60,72 @@ static void icmp6_send_echoreply(struct mbuf *m, Slirp *slirp, struct ip6 *ip,
ip6_output(NULL, t, 0);
}
void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code)
{
Slirp *slirp = m->slirp;
struct mbuf *t;
struct ip6 *ip = mtod(m, struct ip6 *);
DEBUG_CALL("icmp6_send_error");
DEBUG_ARGS((dfd, " type = %d, code = %d\n", type, code));
if (IN6_IS_ADDR_MULTICAST(&ip->ip_src) ||
IN6_IS_ADDR_UNSPECIFIED(&ip->ip_src)) {
/* TODO icmp error? */
return;
}
t = m_get(slirp);
/* IPv6 packet */
struct ip6 *rip = mtod(t, struct ip6 *);
rip->ip_src = (struct in6_addr)LINKLOCAL_ADDR;
rip->ip_dst = ip->ip_src;
#if !defined(_WIN32) || (_WIN32_WINNT >= 0x0600)
char addrstr[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &rip->ip_dst, addrstr, INET6_ADDRSTRLEN);
DEBUG_ARG("target = %s", addrstr);
#endif
rip->ip_nh = IPPROTO_ICMPV6;
const int error_data_len = min(m->m_len,
IF_MTU - (sizeof(struct ip6) + ICMP6_ERROR_MINLEN));
rip->ip_pl = htons(ICMP6_ERROR_MINLEN + error_data_len);
t->m_len = sizeof(struct ip6) + ntohs(rip->ip_pl);
/* ICMPv6 packet */
t->m_data += sizeof(struct ip6);
struct icmp6 *ricmp = mtod(t, struct icmp6 *);
ricmp->icmp6_type = type;
ricmp->icmp6_code = code;
ricmp->icmp6_cksum = 0;
switch (type) {
case ICMP6_UNREACH:
case ICMP6_TIMXCEED:
ricmp->icmp6_err.unused = 0;
break;
case ICMP6_TOOBIG:
ricmp->icmp6_err.mtu = htonl(IF_MTU);
break;
case ICMP6_PARAMPROB:
/* TODO: Handle this case */
break;
default:
g_assert_not_reached();
break;
}
t->m_data += ICMP6_ERROR_MINLEN;
memcpy(t->m_data, m->m_data, error_data_len);
/* Checksum */
t->m_data -= ICMP6_ERROR_MINLEN;
t->m_data -= sizeof(struct ip6);
ricmp->icmp6_cksum = ip6_cksum(t);
ip6_output(NULL, t, 0);
}
/*
* Send NDP Router Advertisement
*/