aboutsummaryrefslogtreecommitdiff
path: root/slirp/src/ip6_icmp.h
blob: e8ed753db55a4508dd0cf86b68593d808d0b900f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
/*
 * 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
    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
    uint32_t
        R:1,                /* Router Flag */
        S:1,                /* Solicited Flag */
        O:1,                /* Override Flag */
        reserved_hi:5,
        reserved_lo:24;
#else
    uint32_t
        reserved_hi:5,
        O:1,
        S:1,
        R:1,
        reserved_lo:24;
#endif
    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_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
 */
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
        struct prefixinfo {                     /* Prefix Information */
            uint8_t     prefix_length;
#if G_BYTE_ORDER == G_BIG_ENDIAN
            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 prefixinfo;
#define ndpopt_prefixinfo ndpopt_body.prefixinfo
        struct rdnss {
            uint16_t reserved;
            uint32_t lifetime;
            struct in6_addr addr;
        } SLIRP_PACKED rdnss;
#define ndpopt_rdnss ndpopt_body.rdnss
    } ndpopt_body;
} SLIRP_PACKED;

/* 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

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);

#endif