1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 21da177e4SLinus Torvalds #ifndef _LINUX_ICMPV6_H 31da177e4SLinus Torvalds #define _LINUX_ICMPV6_H 41da177e4SLinus Torvalds 5cc70ab26SArnaldo Carvalho de Melo #include <linux/skbuff.h> 6*ee576c47SJason A. Donenfeld #include <linux/ipv6.h> 7607ca46eSDavid Howells #include <uapi/linux/icmpv6.h> 8cc70ab26SArnaldo Carvalho de Melo 9cc70ab26SArnaldo Carvalho de Melo static inline struct icmp6hdr *icmp6_hdr(const struct sk_buff *skb) 10cc70ab26SArnaldo Carvalho de Melo { 119c70220bSArnaldo Carvalho de Melo return (struct icmp6hdr *)skb_transport_header(skb); 12cc70ab26SArnaldo Carvalho de Melo } 131da177e4SLinus Torvalds 141da177e4SLinus Torvalds #include <linux/netdevice.h> 151da177e4SLinus Torvalds 165f5624cfSPravin B Shelar #if IS_ENABLED(CONFIG_IPV6) 175f5624cfSPravin B Shelar 18b1cadc1aSEric Dumazet typedef void ip6_icmp_send_t(struct sk_buff *skb, u8 type, u8 code, __u32 info, 19*ee576c47SJason A. Donenfeld const struct in6_addr *force_saddr, 20*ee576c47SJason A. Donenfeld const struct inet6_skb_parm *parm); 21cc7a21b6SEric Dumazet void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, 22*ee576c47SJason A. Donenfeld const struct in6_addr *force_saddr, 23*ee576c47SJason A. Donenfeld const struct inet6_skb_parm *parm); 241faba27fSLeon Romanovsky #if IS_BUILTIN(CONFIG_IPV6) 25*ee576c47SJason A. Donenfeld static inline void __icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, 26*ee576c47SJason A. Donenfeld const struct inet6_skb_parm *parm) 27cc7a21b6SEric Dumazet { 28*ee576c47SJason A. Donenfeld icmp6_send(skb, type, code, info, NULL, parm); 29cc7a21b6SEric Dumazet } 30cc7a21b6SEric Dumazet static inline int inet6_register_icmp_sender(ip6_icmp_send_t *fn) 31cc7a21b6SEric Dumazet { 32cc7a21b6SEric Dumazet BUILD_BUG_ON(fn != icmp6_send); 33cc7a21b6SEric Dumazet return 0; 34cc7a21b6SEric Dumazet } 35cc7a21b6SEric Dumazet static inline int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn) 36cc7a21b6SEric Dumazet { 37cc7a21b6SEric Dumazet BUILD_BUG_ON(fn != icmp6_send); 38cc7a21b6SEric Dumazet return 0; 39cc7a21b6SEric Dumazet } 40cc7a21b6SEric Dumazet #else 41*ee576c47SJason A. Donenfeld extern void __icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, 42*ee576c47SJason A. Donenfeld const struct inet6_skb_parm *parm); 435f5624cfSPravin B Shelar extern int inet6_register_icmp_sender(ip6_icmp_send_t *fn); 445f5624cfSPravin B Shelar extern int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn); 45cc7a21b6SEric Dumazet #endif 46cc7a21b6SEric Dumazet 47*ee576c47SJason A. Donenfeld static inline void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) 48*ee576c47SJason A. Donenfeld { 49*ee576c47SJason A. Donenfeld __icmpv6_send(skb, type, code, info, IP6CB(skb)); 50*ee576c47SJason A. Donenfeld } 51*ee576c47SJason A. Donenfeld 5220e1954fSEric Dumazet int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs, int type, 5320e1954fSEric Dumazet unsigned int data_len); 545f5624cfSPravin B Shelar 55a8e41f60SJason A. Donenfeld #if IS_ENABLED(CONFIG_NF_NAT) 56a8e41f60SJason A. Donenfeld void icmpv6_ndo_send(struct sk_buff *skb_in, u8 type, u8 code, __u32 info); 57a8e41f60SJason A. Donenfeld #else 58*ee576c47SJason A. Donenfeld static inline void icmpv6_ndo_send(struct sk_buff *skb_in, u8 type, u8 code, __u32 info) 59*ee576c47SJason A. Donenfeld { 60*ee576c47SJason A. Donenfeld struct inet6_skb_parm parm = { 0 }; 61*ee576c47SJason A. Donenfeld __icmpv6_send(skb_in, type, code, info, &parm); 62*ee576c47SJason A. Donenfeld } 63a8e41f60SJason A. Donenfeld #endif 64a8e41f60SJason A. Donenfeld 655f5624cfSPravin B Shelar #else 665f5624cfSPravin B Shelar 675f5624cfSPravin B Shelar static inline void icmpv6_send(struct sk_buff *skb, 685f5624cfSPravin B Shelar u8 type, u8 code, __u32 info) 695f5624cfSPravin B Shelar { 705f5624cfSPravin B Shelar } 711da177e4SLinus Torvalds 72a8e41f60SJason A. Donenfeld static inline void icmpv6_ndo_send(struct sk_buff *skb, 73a8e41f60SJason A. Donenfeld u8 type, u8 code, __u32 info) 74a8e41f60SJason A. Donenfeld { 75a8e41f60SJason A. Donenfeld } 760b41713bSJason A. Donenfeld #endif 770b41713bSJason A. Donenfeld 789b0f976fSDenis V. Lunev extern int icmpv6_init(void); 79d5fdd6baSBrian Haley extern int icmpv6_err_convert(u8 type, u8 code, 801da177e4SLinus Torvalds int *err); 811da177e4SLinus Torvalds extern void icmpv6_cleanup(void); 821da177e4SLinus Torvalds extern void icmpv6_param_prob(struct sk_buff *skb, 83d5fdd6baSBrian Haley u8 code, int pos); 8495e41e93SYOSHIFUJI Hideaki 854c9483b2SDavid S. Miller struct flowi6; 86f59d4389SDavid S. Miller struct in6_addr; 8795e41e93SYOSHIFUJI Hideaki extern void icmpv6_flow_init(struct sock *sk, 884c9483b2SDavid S. Miller struct flowi6 *fl6, 8995e41e93SYOSHIFUJI Hideaki u8 type, 9095e41e93SYOSHIFUJI Hideaki const struct in6_addr *saddr, 9195e41e93SYOSHIFUJI Hideaki const struct in6_addr *daddr, 9295e41e93SYOSHIFUJI Hideaki int oif); 9315122464SMatteo Croce 9415122464SMatteo Croce static inline bool icmpv6_is_err(int type) 9515122464SMatteo Croce { 9615122464SMatteo Croce switch (type) { 9715122464SMatteo Croce case ICMPV6_DEST_UNREACH: 9815122464SMatteo Croce case ICMPV6_PKT_TOOBIG: 9915122464SMatteo Croce case ICMPV6_TIME_EXCEED: 10015122464SMatteo Croce case ICMPV6_PARAMPROB: 10115122464SMatteo Croce return true; 10215122464SMatteo Croce } 10315122464SMatteo Croce 10415122464SMatteo Croce return false; 10515122464SMatteo Croce } 10615122464SMatteo Croce 1071da177e4SLinus Torvalds #endif 108