| /* SPDX-License-Identifier: BSD-3-Clause */ | |
| /* | |
| * Copyright (c) 2013 | |
| * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. | |
| */ | |
| #ifndef SLIRP_IP6_ICMP_H | |
| #define SLIRP_IP6_ICMP_H | |
| /* | |
| * Interface Control Message Protocol version 6 Definitions. | |
| * Per RFC 4443, March 2006. | |
| * | |
| * Network Discover Protocol Definitions. | |
| * Per RFC 4861, September 2007. | |
| */ | |
| struct icmp6_echo { /* Echo Messages */ | |
| uint16_t id; | |
| uint16_t seq_num; | |
| }; | |
| union icmp6_error_body { | |
| uint32_t unused; | |
| uint32_t pointer; | |
| uint32_t mtu; | |
| }; | |
| /* | |
| * NDP Messages | |
| */ | |
| struct ndp_rs { /* Router Solicitation Message */ | |
| uint32_t reserved; | |
| }; | |
| struct ndp_ra { /* Router Advertisement Message */ | |
| uint8_t chl; /* Cur Hop Limit */ | |
| #if (G_BYTE_ORDER == G_BIG_ENDIAN) && !defined(_MSC_VER) | |
| uint8_t M : 1, O : 1, reserved : 6; | |
| #else | |
| uint8_t reserved : 6, O : 1, M : 1; | |
| #endif | |
| uint16_t lifetime; /* Router Lifetime */ | |
| uint32_t reach_time; /* Reachable Time */ | |
| uint32_t retrans_time; /* Retrans Timer */ | |
| }; | |
| G_STATIC_ASSERT(sizeof(struct ndp_ra) == 12); | |
| struct ndp_ns { /* Neighbor Solicitation Message */ | |
| uint32_t reserved; | |
| struct in6_addr target; /* Target Address */ | |
| }; | |
| G_STATIC_ASSERT(sizeof(struct ndp_ns) == 20); | |
| struct ndp_na { /* Neighbor Advertisement Message */ | |
| #if (G_BYTE_ORDER == G_BIG_ENDIAN) && !defined(_MSC_VER) | |
| uint8_t R : 1, /* Router Flag */ | |
| S : 1, /* Solicited Flag */ | |
| O : 1, /* Override Flag */ | |
| reserved_1 : 5; | |
| #else | |
| uint8_t reserved_1 : 5, O : 1, S : 1, R : 1; | |
| #endif | |
| uint8_t reserved_2; | |
| uint16_t reserved_3; | |
| struct in6_addr target; /* Target Address */ | |
| }; | |
| G_STATIC_ASSERT(sizeof(struct ndp_na) == 20); | |
| struct ndp_redirect { | |
| uint32_t reserved; | |
| struct in6_addr target; /* Target Address */ | |
| struct in6_addr dest; /* Destination Address */ | |
| }; | |
| G_STATIC_ASSERT(sizeof(struct ndp_redirect) == 36); | |
| /* | |
| * Structure of an icmpv6 header. | |
| */ | |
| struct icmp6 { | |
| uint8_t icmp6_type; /* type of message, see below */ | |
| 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; | |
| struct ndp_ns ndp_ns; | |
| 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_id icmp6_body.echo.id | |
| #define icmp6_seq icmp6_body.echo.seq_num | |
| #define icmp6_nrs icmp6_body.ndp_rs | |
| #define icmp6_nra icmp6_body.ndp_ra | |
| #define icmp6_nns icmp6_body.ndp_ns | |
| #define icmp6_nna icmp6_body.ndp_na | |
| #define icmp6_redirect icmp6_body.ndp_redirect | |
| }; | |
| G_STATIC_ASSERT(sizeof(struct icmp6) == 40); | |
| #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 | |
| #define ICMP6_NDP_NS_MINLEN 24 | |
| #define ICMP6_NDP_NA_MINLEN 24 | |
| #define ICMP6_NDP_REDIRECT_MINLEN 40 | |
| /* | |
| * NDP Options | |
| */ | |
| SLIRP_PACKED_BEGIN | |
| struct ndpopt { | |
| uint8_t ndpopt_type; /* Option type */ | |
| uint8_t ndpopt_len; /* /!\ In units of 8 octets */ | |
| union { | |
| unsigned char linklayer_addr[6]; /* Source/Target Link-layer */ | |
| #define ndpopt_linklayer ndpopt_body.linklayer_addr | |
| SLIRP_PACKED_BEGIN | |
| struct prefixinfo { /* Prefix Information */ | |
| uint8_t prefix_length; | |
| #if (G_BYTE_ORDER == G_BIG_ENDIAN) && !defined(_MSC_VER) | |
| uint8_t L : 1, A : 1, reserved1 : 6; | |
| #else | |
| uint8_t reserved1 : 6, A : 1, L : 1; | |
| #endif | |
| uint32_t valid_lt; /* Valid Lifetime */ | |
| uint32_t pref_lt; /* Preferred Lifetime */ | |
| uint32_t reserved2; | |
| struct in6_addr prefix; | |
| } SLIRP_PACKED_END prefixinfo; | |
| #define ndpopt_prefixinfo ndpopt_body.prefixinfo | |
| SLIRP_PACKED_BEGIN | |
| struct rdnss { | |
| uint16_t reserved; | |
| uint32_t lifetime; | |
| struct in6_addr addr; | |
| } SLIRP_PACKED_END rdnss; | |
| #define ndpopt_rdnss ndpopt_body.rdnss | |
| } ndpopt_body; | |
| } SLIRP_PACKED_END; | |
| /* NDP options type */ | |
| #define NDPOPT_LINKLAYER_SOURCE 1 /* Source Link-Layer Address */ | |
| #define NDPOPT_LINKLAYER_TARGET 2 /* Target Link-Layer Address */ | |
| #define NDPOPT_PREFIX_INFO 3 /* Prefix Information */ | |
| #define NDPOPT_RDNSS 25 /* Recursive DNS Server Address */ | |
| /* NDP options size, in octets. */ | |
| #define NDPOPT_LINKLAYER_LEN 8 | |
| #define NDPOPT_PREFIXINFO_LEN 32 | |
| #define NDPOPT_RDNSS_LEN 24 | |
| /* | |
| * Definition of type and code field values. | |
| * Per https://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xml | |
| * Last Updated 2012-11-12 | |
| */ | |
| /* Errors */ | |
| #define ICMP6_UNREACH 1 /* Destination Unreachable */ | |
| #define ICMP6_UNREACH_NO_ROUTE 0 /* no route to dest */ | |
| #define ICMP6_UNREACH_DEST_PROHIB 1 /* com with dest prohibited */ | |
| #define ICMP6_UNREACH_SCOPE 2 /* beyond scope of src addr */ | |
| #define ICMP6_UNREACH_ADDRESS 3 /* address unreachable */ | |
| #define ICMP6_UNREACH_PORT 4 /* port unreachable */ | |
| #define ICMP6_UNREACH_SRC_FAIL 5 /* src addr failed */ | |
| #define ICMP6_UNREACH_REJECT_ROUTE 6 /* reject route to dest */ | |
| #define ICMP6_UNREACH_SRC_HDR_ERROR 7 /* error in src routing header */ | |
| #define ICMP6_TOOBIG 2 /* Packet Too Big */ | |
| #define ICMP6_TIMXCEED 3 /* Time Exceeded */ | |
| #define ICMP6_TIMXCEED_INTRANS 0 /* hop limit exceeded in transit */ | |
| #define ICMP6_TIMXCEED_REASS 1 /* ttl=0 in reass */ | |
| #define ICMP6_PARAMPROB 4 /* Parameter Problem */ | |
| #define ICMP6_PARAMPROB_HDR_FIELD 0 /* err header field */ | |
| #define ICMP6_PARAMPROB_NXTHDR_TYPE 1 /* unrecognized Next Header type */ | |
| #define ICMP6_PARAMPROB_IPV6_OPT 2 /* unrecognized IPv6 option */ | |
| /* Informational Messages */ | |
| #define ICMP6_ECHO_REQUEST 128 /* Echo Request */ | |
| #define ICMP6_ECHO_REPLY 129 /* Echo Reply */ | |
| #define ICMP6_NDP_RS 133 /* Router Solicitation (NDP) */ | |
| #define ICMP6_NDP_RA 134 /* Router Advertisement (NDP) */ | |
| #define ICMP6_NDP_NS 135 /* Neighbor Solicitation (NDP) */ | |
| #define ICMP6_NDP_NA 136 /* Neighbor Advertisement (NDP) */ | |
| #define ICMP6_NDP_REDIRECT 137 /* Redirect Message (NDP) */ | |
| /* | |
| * Router Configuration Variables (rfc4861#section-6) | |
| */ | |
| #define NDP_IsRouter 1 | |
| #define NDP_AdvSendAdvertisements 1 | |
| #define NDP_MaxRtrAdvInterval 600000 | |
| #define NDP_MinRtrAdvInterval \ | |
| ((NDP_MaxRtrAdvInterval >= 9) ? NDP_MaxRtrAdvInterval / 3 : \ | |
| NDP_MaxRtrAdvInterval) | |
| #define NDP_AdvManagedFlag 0 | |
| #define NDP_AdvOtherConfigFlag 0 | |
| #define NDP_AdvLinkMTU 0 | |
| #define NDP_AdvReachableTime 0 | |
| #define NDP_AdvRetransTime 0 | |
| #define NDP_AdvCurHopLimit 64 | |
| #define NDP_AdvDefaultLifetime ((3 * NDP_MaxRtrAdvInterval) / 1000) | |
| #define NDP_AdvValidLifetime 86400 | |
| #define NDP_AdvOnLinkFlag 1 | |
| #define NDP_AdvPrefLifetime 14400 | |
| #define NDP_AdvAutonomousFlag 1 | |
| /* Called from slirp_new, but after other initialization */ | |
| void icmp6_post_init(Slirp *slirp); | |
| /* Called from slirp_cleanup */ | |
| void icmp6_cleanup(Slirp *slirp); | |
| /* Process an ICMPv6 packet from the guest */ | |
| void icmp6_input(struct mbuf *); | |
| /* Send an ICMPv6 error related to the given packet, using the given ICMPv6 type and code, using the given source */ | |
| void icmp6_forward_error(struct mbuf *m, uint8_t type, uint8_t code, struct in6_addr *src); | |
| /* Similar to icmp6_forward_error, but use the link-local address as source */ | |
| void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code); | |
| /* Forward the ICMP packet to the guest (probably a ping reply) */ | |
| void icmp6_reflect(struct mbuf *); | |
| /* Handle ICMP data from the ICMP socket, and forward it to the guest (using so_m as reference) */ | |
| void icmp6_receive(struct socket *so); | |
| /* Send a neighbour sollicitation, to resolve the given IPV6 address */ | |
| void ndp_send_ns(Slirp *slirp, struct in6_addr addr); | |
| /* Timer handler for router advertisement, to send it and reschedule the timer */ | |
| void ra_timer_handler(Slirp *slirp, void *unused); | |
| #endif |