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