18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef LINUX_MLD_H 38c2ecf20Sopenharmony_ci#define LINUX_MLD_H 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#include <linux/in6.h> 68c2ecf20Sopenharmony_ci#include <linux/icmpv6.h> 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci/* MLDv1 Query/Report/Done */ 98c2ecf20Sopenharmony_cistruct mld_msg { 108c2ecf20Sopenharmony_ci struct icmp6hdr mld_hdr; 118c2ecf20Sopenharmony_ci struct in6_addr mld_mca; 128c2ecf20Sopenharmony_ci}; 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#define mld_type mld_hdr.icmp6_type 158c2ecf20Sopenharmony_ci#define mld_code mld_hdr.icmp6_code 168c2ecf20Sopenharmony_ci#define mld_cksum mld_hdr.icmp6_cksum 178c2ecf20Sopenharmony_ci#define mld_maxdelay mld_hdr.icmp6_maxdelay 188c2ecf20Sopenharmony_ci#define mld_reserved mld_hdr.icmp6_dataun.un_data16[1] 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci/* Multicast Listener Discovery version 2 headers */ 218c2ecf20Sopenharmony_ci/* MLDv2 Report */ 228c2ecf20Sopenharmony_cistruct mld2_grec { 238c2ecf20Sopenharmony_ci __u8 grec_type; 248c2ecf20Sopenharmony_ci __u8 grec_auxwords; 258c2ecf20Sopenharmony_ci __be16 grec_nsrcs; 268c2ecf20Sopenharmony_ci struct in6_addr grec_mca; 278c2ecf20Sopenharmony_ci struct in6_addr grec_src[]; 288c2ecf20Sopenharmony_ci}; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistruct mld2_report { 318c2ecf20Sopenharmony_ci struct icmp6hdr mld2r_hdr; 328c2ecf20Sopenharmony_ci struct mld2_grec mld2r_grec[]; 338c2ecf20Sopenharmony_ci}; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#define mld2r_type mld2r_hdr.icmp6_type 368c2ecf20Sopenharmony_ci#define mld2r_resv1 mld2r_hdr.icmp6_code 378c2ecf20Sopenharmony_ci#define mld2r_cksum mld2r_hdr.icmp6_cksum 388c2ecf20Sopenharmony_ci#define mld2r_resv2 mld2r_hdr.icmp6_dataun.un_data16[0] 398c2ecf20Sopenharmony_ci#define mld2r_ngrec mld2r_hdr.icmp6_dataun.un_data16[1] 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci/* MLDv2 Query */ 428c2ecf20Sopenharmony_cistruct mld2_query { 438c2ecf20Sopenharmony_ci struct icmp6hdr mld2q_hdr; 448c2ecf20Sopenharmony_ci struct in6_addr mld2q_mca; 458c2ecf20Sopenharmony_ci#if defined(__LITTLE_ENDIAN_BITFIELD) 468c2ecf20Sopenharmony_ci __u8 mld2q_qrv:3, 478c2ecf20Sopenharmony_ci mld2q_suppress:1, 488c2ecf20Sopenharmony_ci mld2q_resv2:4; 498c2ecf20Sopenharmony_ci#elif defined(__BIG_ENDIAN_BITFIELD) 508c2ecf20Sopenharmony_ci __u8 mld2q_resv2:4, 518c2ecf20Sopenharmony_ci mld2q_suppress:1, 528c2ecf20Sopenharmony_ci mld2q_qrv:3; 538c2ecf20Sopenharmony_ci#else 548c2ecf20Sopenharmony_ci#error "Please fix <asm/byteorder.h>" 558c2ecf20Sopenharmony_ci#endif 568c2ecf20Sopenharmony_ci __u8 mld2q_qqic; 578c2ecf20Sopenharmony_ci __be16 mld2q_nsrcs; 588c2ecf20Sopenharmony_ci struct in6_addr mld2q_srcs[]; 598c2ecf20Sopenharmony_ci}; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci#define mld2q_type mld2q_hdr.icmp6_type 628c2ecf20Sopenharmony_ci#define mld2q_code mld2q_hdr.icmp6_code 638c2ecf20Sopenharmony_ci#define mld2q_cksum mld2q_hdr.icmp6_cksum 648c2ecf20Sopenharmony_ci#define mld2q_mrc mld2q_hdr.icmp6_maxdelay 658c2ecf20Sopenharmony_ci#define mld2q_resv1 mld2q_hdr.icmp6_dataun.un_data16[1] 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci/* RFC3810, 5.1.3. Maximum Response Code: 688c2ecf20Sopenharmony_ci * 698c2ecf20Sopenharmony_ci * If Maximum Response Code >= 32768, Maximum Response Code represents a 708c2ecf20Sopenharmony_ci * floating-point value as follows: 718c2ecf20Sopenharmony_ci * 728c2ecf20Sopenharmony_ci * 0 1 2 3 4 5 6 7 8 9 A B C D E F 738c2ecf20Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 748c2ecf20Sopenharmony_ci * |1| exp | mant | 758c2ecf20Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 768c2ecf20Sopenharmony_ci */ 778c2ecf20Sopenharmony_ci#define MLDV2_MRC_EXP(value) (((value) >> 12) & 0x0007) 788c2ecf20Sopenharmony_ci#define MLDV2_MRC_MAN(value) ((value) & 0x0fff) 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci/* RFC3810, 5.1.9. QQIC (Querier's Query Interval Code): 818c2ecf20Sopenharmony_ci * 828c2ecf20Sopenharmony_ci * If QQIC >= 128, QQIC represents a floating-point value as follows: 838c2ecf20Sopenharmony_ci * 848c2ecf20Sopenharmony_ci * 0 1 2 3 4 5 6 7 858c2ecf20Sopenharmony_ci * +-+-+-+-+-+-+-+-+ 868c2ecf20Sopenharmony_ci * |1| exp | mant | 878c2ecf20Sopenharmony_ci * +-+-+-+-+-+-+-+-+ 888c2ecf20Sopenharmony_ci */ 898c2ecf20Sopenharmony_ci#define MLDV2_QQIC_EXP(value) (((value) >> 4) & 0x07) 908c2ecf20Sopenharmony_ci#define MLDV2_QQIC_MAN(value) ((value) & 0x0f) 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci#define MLD_EXP_MIN_LIMIT 32768UL 938c2ecf20Sopenharmony_ci#define MLDV1_MRD_MAX_COMPAT (MLD_EXP_MIN_LIMIT - 1) 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic inline unsigned long mldv2_mrc(const struct mld2_query *mlh2) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci /* RFC3810, 5.1.3. Maximum Response Code */ 988c2ecf20Sopenharmony_ci unsigned long ret, mc_mrc = ntohs(mlh2->mld2q_mrc); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci if (mc_mrc < MLD_EXP_MIN_LIMIT) { 1018c2ecf20Sopenharmony_ci ret = mc_mrc; 1028c2ecf20Sopenharmony_ci } else { 1038c2ecf20Sopenharmony_ci unsigned long mc_man, mc_exp; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci mc_exp = MLDV2_MRC_EXP(mc_mrc); 1068c2ecf20Sopenharmony_ci mc_man = MLDV2_MRC_MAN(mc_mrc); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci ret = (mc_man | 0x1000) << (mc_exp + 3); 1098c2ecf20Sopenharmony_ci } 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci return ret; 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci#endif 115