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#include <linux/errno.h> 16 17/* struct in6_addr - 128 bits long IPv6 address */ 18struct 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 28} __packed; 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 */ 50struct 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; 66} __packed; 67#define IP6_HDR_SIZE (sizeof(struct ip6_hdr)) 68 69/* struct udp_hdr - User Datagram Protocol header */ 70struct 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 } } } 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 } } } 93 94#define IPV6_LINK_LOCAL_PREFIX 0xfe80 95#define IPV6_LINK_LOCAL_MASK 0xffb0 /* The first 10-bit of address mask. */ 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 */ 103struct 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 177} __packed; 178 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 */ 184struct 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; 208} __packed; 209 210extern struct in6_addr const net_null_addr_ip6; /* NULL IPv6 address */ 211extern struct in6_addr net_gateway6; /* Our gateways IPv6 address */ 212extern struct in6_addr net_ip6; /* Our IPv6 addr (0 = unknown) */ 213extern struct in6_addr net_link_local_ip6; /* Our link local IPv6 addr */ 214extern u32 net_prefix_length; /* Our prefixlength (0 = unknown) */ 215extern struct in6_addr net_server_ip6; /* Server IPv6 addr (0 = unknown) */ 216extern struct in6_addr net_ping_ip6; /* the ipv6 address to ping */ 217extern bool use_ip6; 218 219#if IS_ENABLED(CONFIG_IPV6) 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 */ 239int string_to_ip6(const char *s, size_t len, struct in6_addr *addr); 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 */ 247int ip6_is_unspecified_addr(struct in6_addr *addr); 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 */ 259int ip6_is_our_addr(struct in6_addr *addr); 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 */ 269int ip6_addr_in_subnet(struct in6_addr *our_addr, struct in6_addr *neigh_addr, 270 u32 prefix_length); 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 */ 278void ip6_make_lladdr(struct in6_addr *lladr, unsigned char const enetaddr[6]); 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 */ 286void ip6_make_snma(struct in6_addr *mcast_addr, struct in6_addr *ip6_addr); 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 */ 294void ip6_make_mult_ethdstaddr(unsigned char enetaddr[6], 295 struct in6_addr *mcast_addr); 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 */ 305unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum); 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 */ 317unsigned short int csum_ipv6_magic(struct in6_addr *saddr, 318 struct in6_addr *daddr, u16 len, 319 unsigned short proto, unsigned int csum); 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 */ 332int ip6_add_hdr(uchar *xip, struct in6_addr *src, struct in6_addr *dest, 333 int nextheader, int hoplimit, int payload_len); 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 */ 345int net_send_udp_packet6(uchar *ether, struct in6_addr *dest, int dport, 346 int sport, int len); 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 */ 356int net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len); 357 358/** 359 * net_copy_ip6() - Copy IPv6 addr 360 * 361 * @to: destination IPv6 addr 362 * @from: source IPv6 addr 363 */ 364static inline void net_copy_ip6(void *to, const void *from) 365{ 366 memcpy((void *)to, from, sizeof(struct in6_addr)); 367} 368#else 369static inline int 370string_to_ip6(const char *s, size_t len, struct in6_addr *addr) 371{ 372 return -EINVAL; 373} 374 375static inline int ip6_is_unspecified_addr(struct in6_addr *addr) 376{ 377 return -1; 378} 379 380static inline int ip6_is_our_addr(struct in6_addr *addr) 381{ 382 return -1; 383} 384 385static inline int 386ip6_addr_in_subnet(struct in6_addr *our_addr, struct in6_addr *neigh_addr, 387 u32 prefix_length) 388{ 389 return -1; 390} 391 392static inline void 393ip6_make_lladdr(struct in6_addr *lladdr, unsigned char const enetaddr[6]) 394{ 395} 396 397static inline void 398ip6_make_snma(struct in6_addr *mcast_addr, struct in6_addr *ip6_addr) 399{ 400} 401 402static inline void 403ip6_make_mult_ethdstaddr(unsigned char enetaddr[6], 404 struct in6_addr *mcast_addr) 405{ 406} 407 408static inline unsigned int 409csum_partial(const unsigned char *buff, int len, unsigned int sum) 410{ 411 return 0; 412} 413 414static inline unsigned short 415csum_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 422static inline unsigned int 423ip6_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 429static inline int 430net_send_udp_packet6(uchar *ether, struct in6_addr *dest, 431 int dport, int sport, int len) 432{ 433 return -1; 434} 435 436static inline int 437net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6, 438 int len) 439{ 440 return -EINVAL; 441} 442 443static inline void net_copy_ip6(void *to, const void *from) 444{ 445} 446#endif 447 448#if IS_ENABLED(CONFIG_CMD_PING6) 449/* Send ping requset */ 450void 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 */ 460int ping6_receive(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len); 461#else 462static inline void ping6_start(void) 463{ 464} 465 466static inline 467int ping6_receive(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len) 468{ 469 return -EINVAL; 470} 471#endif /* CONFIG_CMD_PING6 */ 472 473#endif /* __NET6_H__ */ 474