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:
parent
de40abfecf
commit
fc6c9257c6
@ -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
|
||||
*/
|
||||
|
@ -19,6 +19,12 @@ struct icmp6_echo { /* Echo Messages */
|
||||
uint16_t seq_num;
|
||||
};
|
||||
|
||||
union icmp6_error_body {
|
||||
uint32_t unused;
|
||||
uint32_t pointer;
|
||||
uint32_t mtu;
|
||||
};
|
||||
|
||||
/*
|
||||
* NDP Messages
|
||||
*/
|
||||
@ -82,6 +88,7 @@ struct icmp6 {
|
||||
uint8_t icmp6_code; /* type sub code */
|
||||
uint16_t icmp6_cksum; /* ones complement cksum of struct */
|
||||
union {
|
||||
union icmp6_error_body error_body;
|
||||
struct icmp6_echo echo;
|
||||
struct ndp_rs ndp_rs;
|
||||
struct ndp_ra ndp_ra;
|
||||
@ -89,6 +96,7 @@ struct icmp6 {
|
||||
struct ndp_na ndp_na;
|
||||
struct ndp_redirect ndp_redirect;
|
||||
} icmp6_body;
|
||||
#define icmp6_err icmp6_body.error_body
|
||||
#define icmp6_echo icmp6_body.echo
|
||||
#define icmp6_nrs icmp6_body.ndp_rs
|
||||
#define icmp6_nra icmp6_body.ndp_ra
|
||||
@ -98,6 +106,7 @@ struct icmp6 {
|
||||
} QEMU_PACKED;
|
||||
|
||||
#define ICMP6_MINLEN 4
|
||||
#define ICMP6_ERROR_MINLEN 8
|
||||
#define ICMP6_ECHO_MINLEN 8
|
||||
#define ICMP6_NDP_RS_MINLEN 8
|
||||
#define ICMP6_NDP_RA_MINLEN 16
|
||||
@ -197,6 +206,7 @@ struct ndpopt {
|
||||
void icmp6_init(Slirp *slirp);
|
||||
void icmp6_cleanup(Slirp *slirp);
|
||||
void icmp6_input(struct mbuf *);
|
||||
void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code);
|
||||
void ndp_send_ra(Slirp *slirp);
|
||||
void ndp_send_ns(Slirp *slirp, struct in6_addr addr);
|
||||
|
||||
|
@ -39,9 +39,14 @@ void ip6_input(struct mbuf *m)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (ntohs(ip6->ip_pl) > IF_MTU) {
|
||||
icmp6_send_error(m, ICMP6_TOOBIG, 0);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* check ip_ttl for a correct ICMP reply */
|
||||
if (ip6->ip_hl == 0) {
|
||||
/*icmp_send_error(m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl");*/
|
||||
icmp6_send_error(m, ICMP6_TIMXCEED, ICMP6_TIMXCEED_INTRANS);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
@ -50,10 +55,10 @@ void ip6_input(struct mbuf *m)
|
||||
*/
|
||||
switch (ip6->ip_nh) {
|
||||
case IPPROTO_TCP:
|
||||
/*tcp_input(m, hlen, (struct socket *)NULL);*/
|
||||
icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE);
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
/*udp_input(m, hlen);*/
|
||||
icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE);
|
||||
break;
|
||||
case IPPROTO_ICMPV6:
|
||||
icmp6_input(m);
|
||||
|
Loading…
Reference in New Issue
Block a user