]>
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 } } } | |
84 | ||
85 | #define IPV6_LINK_LOCAL_PREFIX 0xfe80 | |
86 | ||
87 | /* hop limit for neighbour discovery packets */ | |
88 | #define IPV6_NDISC_HOPLIMIT 255 | |
89 | #define NDISC_TIMEOUT 5000UL | |
90 | #define NDISC_TIMEOUT_COUNT 3 | |
91 | ||
92 | /* struct icmp6hdr - Internet Control Message Protocol header for IPV6 */ | |
93 | struct icmp6hdr { | |
94 | u8 icmp6_type; | |
95 | #define IPV6_ICMP_ECHO_REQUEST 128 | |
96 | #define IPV6_ICMP_ECHO_REPLY 129 | |
97 | #define IPV6_NDISC_ROUTER_SOLICITATION 133 | |
98 | #define IPV6_NDISC_ROUTER_ADVERTISEMENT 134 | |
99 | #define IPV6_NDISC_NEIGHBOUR_SOLICITATION 135 | |
100 | #define IPV6_NDISC_NEIGHBOUR_ADVERTISEMENT 136 | |
101 | #define IPV6_NDISC_REDIRECT 137 | |
102 | u8 icmp6_code; | |
103 | __be16 icmp6_cksum; | |
104 | ||
105 | /* ICMPv6 data */ | |
106 | union { | |
107 | __be32 un_data32[1]; | |
108 | __be16 un_data16[2]; | |
109 | u8 un_data8[4]; | |
110 | ||
111 | /* struct icmpv6_echo - echo request/reply message format */ | |
112 | struct icmpv6_echo { | |
113 | __be16 identifier; | |
114 | __be16 sequence; | |
115 | } u_echo; | |
116 | ||
117 | /* struct icmpv6_nd_advt - Neighbor Advertisement format */ | |
118 | struct icmpv6_nd_advt { | |
119 | #if defined(__LITTLE_ENDIAN_BITFIELD) | |
120 | __be32 reserved:5, | |
121 | override:1, | |
122 | solicited:1, | |
123 | router:1, | |
124 | reserved2:24; | |
125 | #elif defined(__BIG_ENDIAN_BITFIELD) | |
126 | __be32 router:1, | |
127 | solicited:1, | |
128 | override:1, | |
129 | reserved:29; | |
130 | #else | |
131 | #error "Please fix <asm/byteorder.h>" | |
132 | #endif | |
133 | } u_nd_advt; | |
134 | ||
135 | /* struct icmpv6_nd_ra - Router Advertisement format */ | |
136 | struct icmpv6_nd_ra { | |
137 | u8 hop_limit; | |
138 | #if defined(__LITTLE_ENDIAN_BITFIELD) | |
139 | u8 reserved:6, | |
140 | other:1, | |
141 | managed:1; | |
142 | ||
143 | #elif defined(__BIG_ENDIAN_BITFIELD) | |
144 | u8 managed:1, | |
145 | other:1, | |
146 | reserved:6; | |
147 | #else | |
148 | #error "Please fix <asm/byteorder.h>" | |
149 | #endif | |
150 | __be16 rt_lifetime; | |
151 | } u_nd_ra; | |
152 | } icmp6_dataun; | |
153 | #define icmp6_identifier icmp6_dataun.u_echo.identifier | |
154 | #define icmp6_sequence icmp6_dataun.u_echo.sequence | |
155 | #define icmp6_pointer icmp6_dataun.un_data32[0] | |
156 | #define icmp6_mtu icmp6_dataun.un_data32[0] | |
157 | #define icmp6_unused icmp6_dataun.un_data32[0] | |
158 | #define icmp6_maxdelay icmp6_dataun.un_data16[0] | |
159 | #define icmp6_router icmp6_dataun.u_nd_advt.router | |
160 | #define icmp6_solicited icmp6_dataun.u_nd_advt.solicited | |
161 | #define icmp6_override icmp6_dataun.u_nd_advt.override | |
162 | #define icmp6_ndiscreserved icmp6_dataun.u_nd_advt.reserved | |
163 | #define icmp6_hop_limit icmp6_dataun.u_nd_ra.hop_limit | |
164 | #define icmp6_addrconf_managed icmp6_dataun.u_nd_ra.managed | |
165 | #define icmp6_addrconf_other icmp6_dataun.u_nd_ra.other | |
166 | #define icmp6_rt_lifetime icmp6_dataun.u_nd_ra.rt_lifetime | |
9bc80c0b | 167 | } __packed; |
33b5066a VM |
168 | |
169 | extern struct in6_addr const net_null_addr_ip6; /* NULL IPv6 address */ | |
170 | extern struct in6_addr net_gateway6; /* Our gateways IPv6 address */ | |
171 | extern struct in6_addr net_ip6; /* Our IPv6 addr (0 = unknown) */ | |
172 | extern struct in6_addr net_link_local_ip6; /* Our link local IPv6 addr */ | |
173 | extern u32 net_prefix_length; /* Our prefixlength (0 = unknown) */ | |
174 | extern struct in6_addr net_server_ip6; /* Server IPv6 addr (0 = unknown) */ | |
eeb0a2c6 | 175 | extern struct in6_addr net_ping_ip6; /* the ipv6 address to ping */ |
33b5066a VM |
176 | extern bool use_ip6; |
177 | ||
2f7f2f2a | 178 | #if IS_ENABLED(CONFIG_IPV6) |
33b5066a VM |
179 | /** |
180 | * string_to_ip6() - Convert IPv6 string addr to inner IPV6 addr format | |
181 | * | |
182 | * Examples of valid strings: | |
183 | * 2001:db8::0:1234:1 | |
184 | * 2001:0db8:0000:0000:0000:0000:1234:0001 | |
185 | * ::1 | |
186 | * ::ffff:192.168.1.1 | |
187 | * | |
188 | * Examples of invalid strings | |
189 | * 2001:db8::0::0 (:: can only appear once) | |
190 | * 2001:db8:192.168.1.1::1 (v4 part can only appear at the end) | |
191 | * 192.168.1.1 (we don't implicity map v4) | |
192 | * | |
193 | * @s: IPv6 string addr format | |
194 | * @len: IPv6 string addr length | |
195 | * @addr: converted IPv6 addr | |
196 | * Return: 0 if conversion successful, -EINVAL if fail | |
197 | */ | |
2f7f2f2a | 198 | int string_to_ip6(const char *s, size_t len, struct in6_addr *addr); |
33b5066a VM |
199 | |
200 | /** | |
201 | * ip6_is_unspecified_addr() - Check if IPv6 addr is not set i.e. is zero | |
202 | * | |
203 | * @addr: IPv6 addr | |
204 | * Return: 0 if addr is not set, -1 if is set | |
205 | */ | |
1feb6978 | 206 | int ip6_is_unspecified_addr(struct in6_addr *addr); |
33b5066a VM |
207 | |
208 | /** | |
209 | * ip6_is_our_addr() - Check if IPv6 addr belongs to our host addr | |
210 | * | |
211 | * We have 2 addresses that we should respond to. A link local address and a | |
212 | * global address. This returns true if the specified address matches either | |
213 | * of these. | |
214 | * | |
215 | * @addr: addr to check | |
216 | * Return: 0 if addr is our, -1 otherwise | |
217 | */ | |
1feb6978 | 218 | int ip6_is_our_addr(struct in6_addr *addr); |
33b5066a VM |
219 | |
220 | /** | |
221 | * ip6_addr_in_subnet() - Check if two IPv6 addresses are in the same subnet | |
222 | * | |
223 | * @our_addr: first IPv6 addr | |
224 | * @neigh_addr: second IPv6 addr | |
225 | * @prefix_length: network mask length | |
226 | * Return: 0 if two addresses in the same subnet, -1 otherwise | |
227 | */ | |
1feb6978 VM |
228 | int ip6_addr_in_subnet(struct in6_addr *our_addr, struct in6_addr *neigh_addr, |
229 | u32 prefix_length); | |
33b5066a VM |
230 | |
231 | /** | |
232 | * ip6_make_lladd() - rMake up IPv6 Link Local address | |
233 | * | |
234 | * @lladdr: formed IPv6 Link Local address | |
235 | * @enetaddr: MAC addr of a device | |
236 | */ | |
1feb6978 | 237 | void ip6_make_lladdr(struct in6_addr *lladr, unsigned char const enetaddr[6]); |
33b5066a VM |
238 | |
239 | /** | |
240 | * ip6_make_snma() - aMake up Solicited Node Multicast Address from IPv6 addr | |
241 | * | |
242 | * @mcast_addr: formed SNMA addr | |
243 | * @ip6_addr: base IPv6 addr | |
244 | */ | |
1feb6978 | 245 | void ip6_make_snma(struct in6_addr *mcast_addr, struct in6_addr *ip6_addr); |
33b5066a VM |
246 | |
247 | /** | |
248 | * ip6_make_mult_ethdstaddr() - Make up IPv6 multicast addr | |
249 | * | |
250 | * @enetaddr: MAC addr of a device | |
251 | * @mcast_addr: formed IPv6 multicast addr | |
252 | */ | |
1feb6978 VM |
253 | void ip6_make_mult_ethdstaddr(unsigned char enetaddr[6], |
254 | struct in6_addr *mcast_addr); | |
33b5066a VM |
255 | |
256 | /** | |
257 | * csum_partial() - Compute an internet checksum | |
258 | * | |
259 | * @buff: buffer to be checksummed | |
260 | * @len: length of buffer | |
261 | * @sum: initial sum to be added in | |
262 | * Return: internet checksum of the buffer | |
263 | */ | |
1feb6978 | 264 | unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum); |
33b5066a VM |
265 | |
266 | /** | |
267 | * csum_ipv6_magic() - Compute checksum of IPv6 "psuedo-header" per RFC2460 section 8.1 | |
268 | * | |
269 | * @saddr: source IPv6 addr | |
270 | * @daddr: destination IPv6 add | |
271 | * @len: data length to be checksummed | |
272 | * @proto: IPv6 above protocol code | |
273 | * @csum: upper layer checksum | |
274 | * Return: computed checksum | |
275 | */ | |
1feb6978 VM |
276 | unsigned short int csum_ipv6_magic(struct in6_addr *saddr, |
277 | struct in6_addr *daddr, u16 len, | |
278 | unsigned short proto, unsigned int csum); | |
33b5066a VM |
279 | |
280 | /** | |
281 | * ip6_add_hdr() - Make up IPv6 header | |
282 | * | |
283 | * @xip: pointer to IPv6 header to be formed | |
284 | * @src: source IPv6 addr | |
285 | * @dest: destination IPv6 addr | |
286 | * @nextheader: next header type | |
287 | * @hoplimit: hop limit | |
288 | * @payload_len: payload length | |
289 | * Return: IPv6 header length | |
290 | */ | |
1feb6978 VM |
291 | int ip6_add_hdr(uchar *xip, struct in6_addr *src, struct in6_addr *dest, |
292 | int nextheader, int hoplimit, int payload_len); | |
33b5066a VM |
293 | |
294 | /** | |
295 | * net_send_udp_packet6() - Make up UDP packet and send it | |
296 | * | |
297 | * @ether: destination MAC addr | |
298 | * @dest: destination IPv6 addr | |
299 | * @dport: destination port | |
300 | * @sport: source port | |
301 | * @len: UDP packet length | |
302 | * Return: 0 if send successfully, -1 otherwise | |
303 | */ | |
1feb6978 VM |
304 | int net_send_udp_packet6(uchar *ether, struct in6_addr *dest, int dport, |
305 | int sport, int len); | |
33b5066a VM |
306 | |
307 | /** | |
308 | * net_ip6_handler() - Handle IPv6 packet | |
309 | * | |
310 | * @et: pointer to the beginning of the packet | |
311 | * @ip6: pointer to the beginning of IPv6 protocol | |
312 | * @len: incoming packet len | |
313 | * Return: 0 if handle packet successfully, -EINVAL in case of invalid protocol | |
314 | */ | |
1feb6978 | 315 | int net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len); |
33b5066a VM |
316 | |
317 | /** | |
318 | * net_copy_ip6() - Copy IPv6 addr | |
319 | * | |
320 | * @to: destination IPv6 addr | |
321 | * @from: source IPv6 addr | |
322 | */ | |
323 | static inline void net_copy_ip6(void *to, const void *from) | |
324 | { | |
1feb6978 | 325 | memcpy((void *)to, from, sizeof(struct in6_addr)); |
33b5066a | 326 | } |
1feb6978 VM |
327 | #else |
328 | static inline int | |
329 | string_to_ip6(const char *s, size_t len, struct in6_addr *addr) | |
330 | { | |
331 | return -EINVAL; | |
332 | } | |
333 | ||
334 | static inline int ip6_is_unspecified_addr(struct in6_addr *addr) | |
335 | { | |
336 | return -1; | |
337 | } | |
338 | ||
339 | static inline int ip6_is_our_addr(struct in6_addr *addr) | |
340 | { | |
341 | return -1; | |
342 | } | |
343 | ||
344 | static inline int | |
345 | ip6_addr_in_subnet(struct in6_addr *our_addr, struct in6_addr *neigh_addr, | |
346 | u32 prefix_length) | |
347 | { | |
348 | return -1; | |
349 | } | |
350 | ||
351 | static inline void | |
352 | ip6_make_lladdr(struct in6_addr *lladdr, unsigned char const enetaddr[6]) | |
353 | { | |
354 | } | |
355 | ||
356 | static inline void | |
357 | ip6_make_snma(struct in6_addr *mcast_addr, struct in6_addr *ip6_addr) | |
358 | { | |
359 | } | |
360 | ||
361 | static inline void | |
362 | ip6_make_mult_ethdstaddr(unsigned char enetaddr[6], | |
363 | struct in6_addr *mcast_addr) | |
364 | { | |
365 | } | |
366 | ||
367 | static inline unsigned int | |
368 | csum_partial(const unsigned char *buff, int len, unsigned int sum) | |
369 | { | |
370 | return 0; | |
371 | } | |
372 | ||
373 | static inline unsigned short | |
374 | csum_ipv6_magic(struct in6_addr *saddr, | |
375 | struct in6_addr *daddr, u16 len, | |
376 | unsigned short proto, unsigned int csum) | |
377 | { | |
378 | return 0; | |
379 | } | |
380 | ||
381 | static inline unsigned int | |
382 | ip6_add_hdr(uchar *xip, struct in6_addr *src, struct in6_addr *dest, | |
383 | int nextheader, int hoplimit, int payload_len) | |
384 | { | |
385 | return 0; | |
386 | } | |
387 | ||
388 | static inline int | |
389 | net_send_udp_packet6(uchar *ether, struct in6_addr *dest, | |
390 | int dport, int sport, int len) | |
391 | { | |
392 | return -1; | |
393 | } | |
394 | ||
395 | static inline int | |
396 | net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6, | |
397 | int len) | |
398 | { | |
399 | return -EINVAL; | |
400 | } | |
401 | ||
402 | static inline void net_copy_ip6(void *to, const void *from) | |
403 | { | |
404 | } | |
405 | #endif | |
33b5066a | 406 | |
eeb0a2c6 VM |
407 | #if IS_ENABLED(CONFIG_CMD_PING6) |
408 | /* Send ping requset */ | |
409 | void ping6_start(void); | |
410 | ||
411 | /** | |
412 | * ping6_receive() - Handle reception of ICMPv6 echo request/reply | |
413 | * | |
414 | * @et: pointer to incoming patcket | |
415 | * @ip6: pointer to IPv6 protocol | |
416 | * @len: packet length | |
417 | * Return: 0 if success, -EINVAL in case of failure during reception | |
418 | */ | |
419 | int ping6_receive(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len); | |
420 | #else | |
421 | static inline void ping6_start(void) | |
422 | { | |
423 | } | |
424 | ||
425 | static inline | |
426 | int ping6_receive(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len) | |
427 | { | |
428 | return -EINVAL; | |
429 | } | |
430 | #endif /* CONFIG_CMD_PING6 */ | |
431 | ||
33b5066a | 432 | #endif /* __NET6_H__ */ |