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