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 <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
27 } __packed;
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;
65 } __packed;
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  * 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 } } }
92 
93 #define IPV6_LINK_LOCAL_PREFIX	0xfe80
94 #define IPV6_LINK_LOCAL_MASK	0xffb0 /* The first 10-bit of address mask. */
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
176 } __packed;
177 
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;
207 };
208 
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) */
215 extern struct in6_addr net_ping_ip6; /* the ipv6 address to ping */
216 extern bool use_ip6;
217 
218 #if IS_ENABLED(CONFIG_IPV6)
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  */
238 int string_to_ip6(const char *s, size_t len, struct in6_addr *addr);
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  */
246 int ip6_is_unspecified_addr(struct in6_addr *addr);
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  */
258 int ip6_is_our_addr(struct in6_addr *addr);
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  */
268 int ip6_addr_in_subnet(struct in6_addr *our_addr, struct in6_addr *neigh_addr,
269 		       u32 prefix_length);
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  */
277 void ip6_make_lladdr(struct in6_addr *lladr, unsigned char const enetaddr[6]);
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  */
285 void ip6_make_snma(struct in6_addr *mcast_addr, struct in6_addr *ip6_addr);
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  */
293 void ip6_make_mult_ethdstaddr(unsigned char enetaddr[6],
294 			      struct in6_addr *mcast_addr);
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  */
304 unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum);
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  */
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);
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  */
331 int ip6_add_hdr(uchar *xip, struct in6_addr *src, struct in6_addr *dest,
332 		int nextheader, int hoplimit, int payload_len);
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  */
344 int net_send_udp_packet6(uchar *ether, struct in6_addr *dest, int dport,
345 			 int sport, int len);
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  */
355 int net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len);
356 
357 /**
358  * net_copy_ip6() - Copy IPv6 addr
359  *
360  * @to:		destination IPv6 addr
361  * @from:	source IPv6 addr
362  */
net_copy_ip6(void * to,const void * from)363 static inline void net_copy_ip6(void *to, const void *from)
364 {
365 	memcpy((void *)to, from, sizeof(struct in6_addr));
366 }
367 #else
368 static inline int
string_to_ip6(const char * s,size_t len,struct in6_addr * addr)369 string_to_ip6(const char *s, size_t len, struct in6_addr *addr)
370 {
371 	return -EINVAL;
372 }
373 
ip6_is_unspecified_addr(struct in6_addr * addr)374 static inline int ip6_is_unspecified_addr(struct in6_addr *addr)
375 {
376 	return -1;
377 }
378 
ip6_is_our_addr(struct in6_addr * addr)379 static inline int ip6_is_our_addr(struct in6_addr *addr)
380 {
381 	return -1;
382 }
383 
384 static inline int
ip6_addr_in_subnet(struct in6_addr * our_addr,struct in6_addr * neigh_addr,u32 prefix_length)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
ip6_make_lladdr(struct in6_addr * lladdr,unsigned char const enetaddr[6])392 ip6_make_lladdr(struct in6_addr *lladdr, unsigned char const enetaddr[6])
393 {
394 }
395 
396 static inline void
ip6_make_snma(struct in6_addr * mcast_addr,struct in6_addr * ip6_addr)397 ip6_make_snma(struct in6_addr *mcast_addr, struct in6_addr *ip6_addr)
398 {
399 }
400 
401 static inline void
ip6_make_mult_ethdstaddr(unsigned char enetaddr[6],struct in6_addr * mcast_addr)402 ip6_make_mult_ethdstaddr(unsigned char enetaddr[6],
403 			 struct in6_addr *mcast_addr)
404 {
405 }
406 
407 static inline unsigned int
csum_partial(const unsigned char * buff,int len,unsigned int sum)408 csum_partial(const unsigned char *buff, int len, unsigned int sum)
409 {
410 	return 0;
411 }
412 
413 static inline unsigned short
csum_ipv6_magic(struct in6_addr * saddr,struct in6_addr * daddr,u16 len,unsigned short proto,unsigned int csum)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
ip6_add_hdr(uchar * xip,struct in6_addr * src,struct in6_addr * dest,int nextheader,int hoplimit,int payload_len)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
net_send_udp_packet6(uchar * ether,struct in6_addr * dest,int dport,int sport,int len)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
net_ip6_handler(struct ethernet_hdr * et,struct ip6_hdr * ip6,int len)436 net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6,
437 		int len)
438 {
439 	return -EINVAL;
440 }
441 
net_copy_ip6(void * to,const void * from)442 static inline void net_copy_ip6(void *to, const void *from)
443 {
444 }
445 #endif
446 
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
ping6_start(void)461 static inline void ping6_start(void)
462 {
463 }
464 
465 static inline
ping6_receive(struct ethernet_hdr * et,struct ip6_hdr * ip6,int len)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 
472 #endif /* __NET6_H__ */
473