]>
Commit | Line | Data |
---|---|---|
33b5066a VM |
1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
2 | /* | |
3 | * Copyright (C) 2013 Allied Telesis Labs NZ | |
4 | * Chris Packham, <[email protected]> | |
5 | * | |
6 | * Copyright (C) 2022 YADRO | |
7 | * Viacheslav Mitrofanov <[email protected]> | |
8 | */ | |
9 | ||
10 | #ifndef __NET6_H__ | |
11 | #define __NET6_H__ | |
12 | ||
13 | #include <net.h> | |
14 | #include <linux/ctype.h> | |
15 | ||
16 | /* struct in6_addr - 128 bits long IPv6 address */ | |
17 | struct in6_addr { | |
18 | union { | |
19 | u8 u6_addr8[16]; | |
20 | __be16 u6_addr16[8]; | |
21 | __be32 u6_addr32[4]; | |
22 | } in6_u; | |
23 | ||
24 | #define s6_addr in6_u.u6_addr8 | |
25 | #define s6_addr16 in6_u.u6_addr16 | |
26 | #define s6_addr32 in6_u.u6_addr32 | |
9bc80c0b | 27 | } __packed; |
33b5066a VM |
28 | |
29 | #define IN6ADDRSZ sizeof(struct in6_addr) | |
30 | #define INETHADDRSZ sizeof(net_ethaddr) | |
31 | ||
32 | #define PROT_IP6 0x86DD /* IPv6 protocol */ | |
33 | #define PROT_ICMPV6 58 /* ICMPv6 protocol*/ | |
34 | ||
35 | #define IPV6_ADDRSCOPE_INTF 0x01 | |
36 | #define IPV6_ADDRSCOPE_LINK 0x02 | |
37 | #define IPV6_ADDRSCOPE_AMDIN 0x04 | |
38 | #define IPV6_ADDRSCOPE_SITE 0x05 | |
39 | #define IPV6_ADDRSCOPE_ORG 0x08 | |
40 | #define IPV6_ADDRSCOPE_GLOBAL 0x0E | |
41 | ||
42 | #define USE_IP6_CMD_PARAM "-ipv6" | |
43 | ||
44 | /** | |
45 | * struct ipv6hdr - Internet Protocol V6 (IPv6) header. | |
46 | * | |
47 | * IPv6 packet header as defined in RFC 2460. | |
48 | */ | |
49 | struct ip6_hdr { | |
50 | #if defined(__LITTLE_ENDIAN_BITFIELD) | |
51 | u8 priority:4, | |
52 | version:4; | |
53 | #elif defined(__BIG_ENDIAN_BITFIELD) | |
54 | u8 version:4, | |
55 | priority:4; | |
56 | #else | |
57 | #error "Please fix <asm/byteorder.h>" | |
58 | #endif | |
59 | u8 flow_lbl[3]; | |
60 | __be16 payload_len; | |
61 | u8 nexthdr; | |
62 | u8 hop_limit; | |
63 | struct in6_addr saddr; | |
64 | struct in6_addr daddr; | |
9bc80c0b | 65 | } __packed; |
33b5066a VM |
66 | #define IP6_HDR_SIZE (sizeof(struct ip6_hdr)) |
67 | ||
68 | /* struct udp_hdr - User Datagram Protocol header */ | |
69 | struct udp_hdr { | |
70 | u16 udp_src; /* UDP source port */ | |
71 | u16 udp_dst; /* UDP destination port */ | |
72 | u16 udp_len; /* Length of UDP packet */ | |
73 | u16 udp_xsum; /* Checksum */ | |
74 | } __packed; | |
75 | ||
76 | /* | |
77 | * Handy for static initialisations of struct in6_addr, atlhough the | |
78 | * c99 '= { 0 }' idiom might work depending on you compiler. | |
79 | */ | |
80 | #define ZERO_IPV6_ADDR { { { 0x00, 0x00, 0x00, 0x00, \ | |
81 | 0x00, 0x00, 0x00, 0x00, \ | |
82 | 0x00, 0x00, 0x00, 0x00, \ | |
83 | 0x00, 0x00, 0x00, 0x00 } } } | |
6de98b60 EM |
84 | /* |
85 | * All-routers multicast address is the link-local scope address to reach all | |
86 | * routers. | |
87 | */ | |
88 | #define ALL_ROUTERS_MULT_ADDR { { { 0xFF, 0x02, 0x00, 0x00, \ | |
89 | 0x00, 0x00, 0x00, 0x00, \ | |
90 | 0x00, 0x00, 0x00, 0x00, \ | |
91 | 0x00, 0x00, 0x00, 0x02 } } } | |
33b5066a VM |
92 | |
93 | #define IPV6_LINK_LOCAL_PREFIX 0xfe80 | |
6de98b60 | 94 | #define IPV6_LINK_LOCAL_MASK 0xffb0 /* The first 10-bit of address mask. */ |
33b5066a VM |
95 | |
96 | /* hop limit for neighbour discovery packets */ | |
97 | #define IPV6_NDISC_HOPLIMIT 255 | |
98 | #define NDISC_TIMEOUT 5000UL | |
99 | #define NDISC_TIMEOUT_COUNT 3 | |
100 | ||
101 | /* struct icmp6hdr - Internet Control Message Protocol header for IPV6 */ | |
102 | struct icmp6hdr { | |
103 | u8 icmp6_type; | |
104 | #define IPV6_ICMP_ECHO_REQUEST 128 | |
105 | #define IPV6_ICMP_ECHO_REPLY 129 | |
106 | #define IPV6_NDISC_ROUTER_SOLICITATION 133 | |
107 | #define IPV6_NDISC_ROUTER_ADVERTISEMENT 134 | |
108 | #define IPV6_NDISC_NEIGHBOUR_SOLICITATION 135 | |
109 | #define IPV6_NDISC_NEIGHBOUR_ADVERTISEMENT 136 | |
110 | #define IPV6_NDISC_REDIRECT 137 | |
111 | u8 icmp6_code; | |
112 | __be16 icmp6_cksum; | |
113 | ||
114 | /* ICMPv6 data */ | |
115 | union { | |
116 | __be32 un_data32[1]; | |
117 | __be16 un_data16[2]; | |
118 | u8 un_data8[4]; | |
119 | ||
120 | /* struct icmpv6_echo - echo request/reply message format */ | |
121 | struct icmpv6_echo { | |
122 | __be16 identifier; | |
123 | __be16 sequence; | |
124 | } u_echo; | |
125 | ||
126 | /* struct icmpv6_nd_advt - Neighbor Advertisement format */ | |
127 | struct icmpv6_nd_advt { | |
128 | #if defined(__LITTLE_ENDIAN_BITFIELD) | |
129 | __be32 reserved:5, | |
130 | override:1, | |
131 | solicited:1, | |
132 | router:1, | |
133 | reserved2:24; | |
134 | #elif defined(__BIG_ENDIAN_BITFIELD) | |
135 | __be32 router:1, | |
136 | solicited:1, | |
137 | override:1, | |
138 | reserved:29; | |
139 | #else | |
140 | #error "Please fix <asm/byteorder.h>" | |
141 | #endif | |
142 | } u_nd_advt; | |
143 | ||
144 | /* struct icmpv6_nd_ra - Router Advertisement format */ | |
145 | struct icmpv6_nd_ra { | |
146 | u8 hop_limit; | |
147 | #if defined(__LITTLE_ENDIAN_BITFIELD) | |
148 | u8 reserved:6, | |
149 | other:1, | |
150 | managed:1; | |
151 | ||
152 | #elif defined(__BIG_ENDIAN_BITFIELD) | |
153 | u8 managed:1, | |
154 | other:1, | |
155 | reserved:6; | |
156 | #else | |
157 | #error "Please fix <asm/byteorder.h>" | |
158 | #endif | |
159 | __be16 rt_lifetime; | |
160 | } u_nd_ra; | |
161 | } icmp6_dataun; | |
162 | #define icmp6_identifier icmp6_dataun.u_echo.identifier | |
163 | #define icmp6_sequence icmp6_dataun.u_echo.sequence | |
164 | #define icmp6_pointer icmp6_dataun.un_data32[0] | |
165 | #define icmp6_mtu icmp6_dataun.un_data32[0] | |
166 | #define icmp6_unused icmp6_dataun.un_data32[0] | |
167 | #define icmp6_maxdelay icmp6_dataun.un_data16[0] | |
168 | #define icmp6_router icmp6_dataun.u_nd_advt.router | |
169 | #define icmp6_solicited icmp6_dataun.u_nd_advt.solicited | |
170 | #define icmp6_override icmp6_dataun.u_nd_advt.override | |
171 | #define icmp6_ndiscreserved icmp6_dataun.u_nd_advt.reserved | |
172 | #define icmp6_hop_limit icmp6_dataun.u_nd_ra.hop_limit | |
173 | #define icmp6_addrconf_managed icmp6_dataun.u_nd_ra.managed | |
174 | #define icmp6_addrconf_other icmp6_dataun.u_nd_ra.other | |
175 | #define icmp6_rt_lifetime icmp6_dataun.u_nd_ra.rt_lifetime | |
9bc80c0b | 176 | } __packed; |
33b5066a | 177 | |
6de98b60 EM |
178 | /* |
179 | * struct icmp6_ra_prefix_info - Prefix Information option of the ICMPv6 message | |
180 | * The Prefix Information option provides hosts with on-link prefixes and | |
181 | * prefixes for Address Autoconfiguration. Refer to RFC 4861 for more info. | |
182 | */ | |
183 | struct icmp6_ra_prefix_info { | |
184 | u8 type; /* Type is 3 for Prefix Information. */ | |
185 | u8 len; /* Len is 4 for Prefix Information. */ | |
186 | /* The number of leading bits in the Prefix that are valid. */ | |
187 | u8 prefix_len; | |
188 | u8 reserved1:6, /* MUST be ignored by the receiver. */ | |
189 | aac:1, /* autonomous address-configuration flag */ | |
190 | /* Indicates that this prefix can be used for on-link determination. */ | |
191 | on_link:1; | |
192 | /* | |
193 | * The length of time in seconds that the prefix is valid for the | |
194 | * purpose of on-link determination. | |
195 | */ | |
196 | __be32 valid_lifetime; | |
197 | /* The length of time addresses remain preferred. */ | |
198 | __be32 preferred_lifetime; | |
199 | __be32 reserved2; /* MUST be ignored by the receiver. */ | |
200 | /* | |
201 | * Prefix is an IP address or a prefix of an IP address. The Prefix | |
202 | * Length field contains the number of valid leading bits in the prefix. | |
203 | * The bits in the prefix after the prefix length are reserved and MUST | |
204 | * be initialized to zero by the sender and ignored by the receiver. | |
205 | */ | |
206 | struct in6_addr prefix; | |
1196e524 | 207 | } __packed; |
6de98b60 | 208 | |
33b5066a VM |
209 | extern struct in6_addr const net_null_addr_ip6; /* NULL IPv6 address */ |
210 | extern struct in6_addr net_gateway6; /* Our gateways IPv6 address */ | |
211 | extern struct in6_addr net_ip6; /* Our IPv6 addr (0 = unknown) */ | |
212 | extern struct in6_addr net_link_local_ip6; /* Our link local IPv6 addr */ | |
213 | extern u32 net_prefix_length; /* Our prefixlength (0 = unknown) */ | |
214 | extern struct in6_addr net_server_ip6; /* Server IPv6 addr (0 = unknown) */ | |
eeb0a2c6 | 215 | extern struct in6_addr net_ping_ip6; /* the ipv6 address to ping */ |
33b5066a VM |
216 | extern bool use_ip6; |
217 | ||
2f7f2f2a | 218 | #if IS_ENABLED(CONFIG_IPV6) |
33b5066a VM |
219 | /** |
220 | * string_to_ip6() - Convert IPv6 string addr to inner IPV6 addr format | |
221 | * | |
222 | * Examples of valid strings: | |
223 | * 2001:db8::0:1234:1 | |
224 | * 2001:0db8:0000:0000:0000:0000:1234:0001 | |
225 | * ::1 | |
226 | * ::ffff:192.168.1.1 | |
227 | * | |
228 | * Examples of invalid strings | |
229 | * 2001:db8::0::0 (:: can only appear once) | |
230 | * 2001:db8:192.168.1.1::1 (v4 part can only appear at the end) | |
231 | * 192.168.1.1 (we don't implicity map v4) | |
232 | * | |
233 | * @s: IPv6 string addr format | |
234 | * @len: IPv6 string addr length | |
235 | * @addr: converted IPv6 addr | |
236 | * Return: 0 if conversion successful, -EINVAL if fail | |
237 | */ | |
2f7f2f2a | 238 | int string_to_ip6(const char *s, size_t len, struct in6_addr *addr); |
33b5066a VM |
239 | |
240 | /** | |
241 | * ip6_is_unspecified_addr() - Check if IPv6 addr is not set i.e. is zero | |
242 | * | |
243 | * @addr: IPv6 addr | |
244 | * Return: 0 if addr is not set, -1 if is set | |
245 | */ | |
1feb6978 | 246 | int ip6_is_unspecified_addr(struct in6_addr *addr); |
33b5066a VM |
247 | |
248 | /** | |
249 | * ip6_is_our_addr() - Check if IPv6 addr belongs to our host addr | |
250 | * | |
251 | * We have 2 addresses that we should respond to. A link local address and a | |
252 | * global address. This returns true if the specified address matches either | |
253 | * of these. | |
254 | * | |
255 | * @addr: addr to check | |
256 | * Return: 0 if addr is our, -1 otherwise | |
257 | */ | |
1feb6978 | 258 | int ip6_is_our_addr(struct in6_addr *addr); |
33b5066a VM |
259 | |
260 | /** | |
261 | * ip6_addr_in_subnet() - Check if two IPv6 addresses are in the same subnet | |
262 | * | |
263 | * @our_addr: first IPv6 addr | |
264 | * @neigh_addr: second IPv6 addr | |
265 | * @prefix_length: network mask length | |
266 | * Return: 0 if two addresses in the same subnet, -1 otherwise | |
267 | */ | |
1feb6978 VM |
268 | int ip6_addr_in_subnet(struct in6_addr *our_addr, struct in6_addr *neigh_addr, |
269 | u32 prefix_length); | |
33b5066a VM |
270 | |
271 | /** | |
272 | * ip6_make_lladd() - rMake up IPv6 Link Local address | |
273 | * | |
274 | * @lladdr: formed IPv6 Link Local address | |
275 | * @enetaddr: MAC addr of a device | |
276 | */ | |
1feb6978 | 277 | void ip6_make_lladdr(struct in6_addr *lladr, unsigned char const enetaddr[6]); |
33b5066a VM |
278 | |
279 | /** | |
280 | * ip6_make_snma() - aMake up Solicited Node Multicast Address from IPv6 addr | |
281 | * | |
282 | * @mcast_addr: formed SNMA addr | |
283 | * @ip6_addr: base IPv6 addr | |
284 | */ | |
1feb6978 | 285 | void ip6_make_snma(struct in6_addr *mcast_addr, struct in6_addr *ip6_addr); |
33b5066a VM |
286 | |
287 | /** | |
288 | * ip6_make_mult_ethdstaddr() - Make up IPv6 multicast addr | |
289 | * | |
290 | * @enetaddr: MAC addr of a device | |
291 | * @mcast_addr: formed IPv6 multicast addr | |
292 | */ | |
1feb6978 VM |
293 | void ip6_make_mult_ethdstaddr(unsigned char enetaddr[6], |
294 | struct in6_addr *mcast_addr); | |
33b5066a VM |
295 | |
296 | /** | |
297 | * csum_partial() - Compute an internet checksum | |
298 | * | |
299 | * @buff: buffer to be checksummed | |
300 | * @len: length of buffer | |
301 | * @sum: initial sum to be added in | |
302 | * Return: internet checksum of the buffer | |
303 | */ | |
1feb6978 | 304 | unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum); |
33b5066a VM |
305 | |
306 | /** | |
307 | * csum_ipv6_magic() - Compute checksum of IPv6 "psuedo-header" per RFC2460 section 8.1 | |
308 | * | |
309 | * @saddr: source IPv6 addr | |
310 | * @daddr: destination IPv6 add | |
311 | * @len: data length to be checksummed | |
312 | * @proto: IPv6 above protocol code | |
313 | * @csum: upper layer checksum | |
314 | * Return: computed checksum | |
315 | */ | |
1feb6978 VM |
316 | unsigned short int csum_ipv6_magic(struct in6_addr *saddr, |
317 | struct in6_addr *daddr, u16 len, | |
318 | unsigned short proto, unsigned int csum); | |
33b5066a VM |
319 | |
320 | /** | |
321 | * ip6_add_hdr() - Make up IPv6 header | |
322 | * | |
323 | * @xip: pointer to IPv6 header to be formed | |
324 | * @src: source IPv6 addr | |
325 | * @dest: destination IPv6 addr | |
326 | * @nextheader: next header type | |
327 | * @hoplimit: hop limit | |
328 | * @payload_len: payload length | |
329 | * Return: IPv6 header length | |
330 | */ | |
1feb6978 VM |
331 | int ip6_add_hdr(uchar *xip, struct in6_addr *src, struct in6_addr *dest, |
332 | int nextheader, int hoplimit, int payload_len); | |
33b5066a VM |
333 | |
334 | /** | |
335 | * net_send_udp_packet6() - Make up UDP packet and send it | |
336 | * | |
337 | * @ether: destination MAC addr | |
338 | * @dest: destination IPv6 addr | |
339 | * @dport: destination port | |
340 | * @sport: source port | |
341 | * @len: UDP packet length | |
342 | * Return: 0 if send successfully, -1 otherwise | |
343 | */ | |
1feb6978 VM |
344 | int net_send_udp_packet6(uchar *ether, struct in6_addr *dest, int dport, |
345 | int sport, int len); | |
33b5066a VM |
346 | |
347 | /** | |
348 | * net_ip6_handler() - Handle IPv6 packet | |
349 | * | |
350 | * @et: pointer to the beginning of the packet | |
351 | * @ip6: pointer to the beginning of IPv6 protocol | |
352 | * @len: incoming packet len | |
353 | * Return: 0 if handle packet successfully, -EINVAL in case of invalid protocol | |
354 | */ | |
1feb6978 | 355 | int net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len); |
33b5066a VM |
356 | |
357 | /** | |
358 | * net_copy_ip6() - Copy IPv6 addr | |
359 | * | |
360 | * @to: destination IPv6 addr | |
361 | * @from: source IPv6 addr | |
362 | */ | |
363 | static inline void net_copy_ip6(void *to, const void *from) | |
364 | { | |
1feb6978 | 365 | memcpy((void *)to, from, sizeof(struct in6_addr)); |
33b5066a | 366 | } |
1feb6978 VM |
367 | #else |
368 | static inline int | |
369 | string_to_ip6(const char *s, size_t len, struct in6_addr *addr) | |
370 | { | |
371 | return -EINVAL; | |
372 | } | |
373 | ||
374 | static inline int ip6_is_unspecified_addr(struct in6_addr *addr) | |
375 | { | |
376 | return -1; | |
377 | } | |
378 | ||
379 | static inline int ip6_is_our_addr(struct in6_addr *addr) | |
380 | { | |
381 | return -1; | |
382 | } | |
383 | ||
384 | static inline int | |
385 | ip6_addr_in_subnet(struct in6_addr *our_addr, struct in6_addr *neigh_addr, | |
386 | u32 prefix_length) | |
387 | { | |
388 | return -1; | |
389 | } | |
390 | ||
391 | static inline void | |
392 | ip6_make_lladdr(struct in6_addr *lladdr, unsigned char const enetaddr[6]) | |
393 | { | |
394 | } | |
395 | ||
396 | static inline void | |
397 | ip6_make_snma(struct in6_addr *mcast_addr, struct in6_addr *ip6_addr) | |
398 | { | |
399 | } | |
400 | ||
401 | static inline void | |
402 | ip6_make_mult_ethdstaddr(unsigned char enetaddr[6], | |
403 | struct in6_addr *mcast_addr) | |
404 | { | |
405 | } | |
406 | ||
407 | static inline unsigned int | |
408 | csum_partial(const unsigned char *buff, int len, unsigned int sum) | |
409 | { | |
410 | return 0; | |
411 | } | |
412 | ||
413 | static inline unsigned short | |
414 | csum_ipv6_magic(struct in6_addr *saddr, | |
415 | struct in6_addr *daddr, u16 len, | |
416 | unsigned short proto, unsigned int csum) | |
417 | { | |
418 | return 0; | |
419 | } | |
420 | ||
421 | static inline unsigned int | |
422 | ip6_add_hdr(uchar *xip, struct in6_addr *src, struct in6_addr *dest, | |
423 | int nextheader, int hoplimit, int payload_len) | |
424 | { | |
425 | return 0; | |
426 | } | |
427 | ||
428 | static inline int | |
429 | net_send_udp_packet6(uchar *ether, struct in6_addr *dest, | |
430 | int dport, int sport, int len) | |
431 | { | |
432 | return -1; | |
433 | } | |
434 | ||
435 | static inline int | |
436 | net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6, | |
437 | int len) | |
438 | { | |
439 | return -EINVAL; | |
440 | } | |
441 | ||
442 | static inline void net_copy_ip6(void *to, const void *from) | |
443 | { | |
444 | } | |
445 | #endif | |
33b5066a | 446 | |
eeb0a2c6 VM |
447 | #if IS_ENABLED(CONFIG_CMD_PING6) |
448 | /* Send ping requset */ | |
449 | void ping6_start(void); | |
450 | ||
451 | /** | |
452 | * ping6_receive() - Handle reception of ICMPv6 echo request/reply | |
453 | * | |
454 | * @et: pointer to incoming patcket | |
455 | * @ip6: pointer to IPv6 protocol | |
456 | * @len: packet length | |
457 | * Return: 0 if success, -EINVAL in case of failure during reception | |
458 | */ | |
459 | int ping6_receive(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len); | |
460 | #else | |
461 | static inline void ping6_start(void) | |
462 | { | |
463 | } | |
464 | ||
465 | static inline | |
466 | int ping6_receive(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len) | |
467 | { | |
468 | return -EINVAL; | |
469 | } | |
470 | #endif /* CONFIG_CMD_PING6 */ | |
471 | ||
33b5066a | 472 | #endif /* __NET6_H__ */ |