diff options
| author | Lorenzo Colitti <lorenzo@google.com> | 2013-05-22 16:17:31 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2013-05-26 00:07:49 -0400 |
| commit | 6d0bfe22611602f36617bc7aa2ffa1bbb2f54c67 (patch) | |
| tree | 140f06221a5da5c44526cb61f921d80fec2132c2 /include | |
| parent | 6e2842f4bbb5abcf57d3cb0f10870e0ce20c0ba2 (diff) | |
net: ipv6: Add IPv6 support to the ping socket.
This adds the ability to send ICMPv6 echo requests without a
raw socket. The equivalent ability for ICMPv4 was added in
2011.
Instead of having separate code paths for IPv4 and IPv6, make
most of the code in net/ipv4/ping.c dual-stack and only add a
few IPv6-specific bits (like the protocol definition) to a new
net/ipv6/ping.c. Hopefully this will reduce divergence and/or
duplication of bugs in the future.
Caveats:
- Setting options via ancillary data (e.g., using IPV6_PKTINFO
to specify the outgoing interface) is not yet supported.
- There are no separate security settings for IPv4 and IPv6;
everything is controlled by /proc/net/ipv4/ping_group_range.
- The proc interface does not yet display IPv6 ping sockets
properly.
Tested with a patched copy of ping6 and using raw socket calls.
Compiles and works with all of CONFIG_IPV6={n,m,y}.
Signed-off-by: Lorenzo Colitti <lorenzo@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
| -rw-r--r-- | include/net/ipv6.h | 6 | ||||
| -rw-r--r-- | include/net/ping.h | 49 | ||||
| -rw-r--r-- | include/net/transp_v6.h | 3 |
3 files changed, 55 insertions, 3 deletions
diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 0810aa57c780..ab47582f6c0b 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h | |||
| @@ -260,6 +260,12 @@ static inline void fl6_sock_release(struct ip6_flowlabel *fl) | |||
| 260 | 260 | ||
| 261 | extern void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info); | 261 | extern void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info); |
| 262 | 262 | ||
| 263 | int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, | ||
| 264 | struct icmp6hdr *thdr, int len); | ||
| 265 | |||
| 266 | struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb, | ||
| 267 | struct sock *sk, struct flowi6 *fl6); | ||
| 268 | |||
| 263 | extern int ip6_ra_control(struct sock *sk, int sel); | 269 | extern int ip6_ra_control(struct sock *sk, int sel); |
| 264 | 270 | ||
| 265 | extern int ipv6_parse_hopopts(struct sk_buff *skb); | 271 | extern int ipv6_parse_hopopts(struct sk_buff *skb); |
diff --git a/include/net/ping.h b/include/net/ping.h index 682b5ae9af51..9242fa090d3d 100644 --- a/include/net/ping.h +++ b/include/net/ping.h | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #ifndef _PING_H | 13 | #ifndef _PING_H |
| 14 | #define _PING_H | 14 | #define _PING_H |
| 15 | 15 | ||
| 16 | #include <net/icmp.h> | ||
| 16 | #include <net/netns/hash.h> | 17 | #include <net/netns/hash.h> |
| 17 | 18 | ||
| 18 | /* PING_HTABLE_SIZE must be power of 2 */ | 19 | /* PING_HTABLE_SIZE must be power of 2 */ |
| @@ -28,6 +29,18 @@ | |||
| 28 | */ | 29 | */ |
| 29 | #define GID_T_MAX (((gid_t)~0U) >> 1) | 30 | #define GID_T_MAX (((gid_t)~0U) >> 1) |
| 30 | 31 | ||
| 32 | /* Compatibility glue so we can support IPv6 when it's compiled as a module */ | ||
| 33 | struct pingv6_ops { | ||
| 34 | int (*ipv6_recv_error)(struct sock *sk, struct msghdr *msg, int len); | ||
| 35 | int (*ip6_datagram_recv_ctl)(struct sock *sk, struct msghdr *msg, | ||
| 36 | struct sk_buff *skb); | ||
| 37 | int (*icmpv6_err_convert)(u8 type, u8 code, int *err); | ||
| 38 | void (*ipv6_icmp_error)(struct sock *sk, struct sk_buff *skb, int err, | ||
| 39 | __be16 port, u32 info, u8 *payload); | ||
| 40 | int (*ipv6_chk_addr)(struct net *net, const struct in6_addr *addr, | ||
| 41 | struct net_device *dev, int strict); | ||
| 42 | }; | ||
| 43 | |||
| 31 | struct ping_table { | 44 | struct ping_table { |
| 32 | struct hlist_nulls_head hash[PING_HTABLE_SIZE]; | 45 | struct hlist_nulls_head hash[PING_HTABLE_SIZE]; |
| 33 | rwlock_t lock; | 46 | rwlock_t lock; |
| @@ -39,10 +52,39 @@ struct ping_iter_state { | |||
| 39 | }; | 52 | }; |
| 40 | 53 | ||
| 41 | extern struct proto ping_prot; | 54 | extern struct proto ping_prot; |
| 55 | extern struct ping_table ping_table; | ||
| 56 | #if IS_ENABLED(CONFIG_IPV6) | ||
| 57 | extern struct pingv6_ops pingv6_ops; | ||
| 58 | #endif | ||
| 42 | 59 | ||
| 60 | struct pingfakehdr { | ||
| 61 | struct icmphdr icmph; | ||
| 62 | struct iovec *iov; | ||
| 63 | sa_family_t family; | ||
| 64 | __wsum wcheck; | ||
| 65 | }; | ||
| 43 | 66 | ||
| 44 | extern void ping_rcv(struct sk_buff *); | 67 | int ping_get_port(struct sock *sk, unsigned short ident); |
| 45 | extern void ping_err(struct sk_buff *, u32 info); | 68 | void ping_hash(struct sock *sk); |
| 69 | void ping_unhash(struct sock *sk); | ||
| 70 | |||
| 71 | int ping_init_sock(struct sock *sk); | ||
| 72 | void ping_close(struct sock *sk, long timeout); | ||
| 73 | int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len); | ||
| 74 | void ping_err(struct sk_buff *skb, int offset, u32 info); | ||
| 75 | int ping_getfrag(void *from, char *to, int offset, int fraglen, int odd, | ||
| 76 | struct sk_buff *); | ||
| 77 | |||
| 78 | int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | ||
| 79 | size_t len, int noblock, int flags, int *addr_len); | ||
| 80 | int ping_common_sendmsg(int family, struct msghdr *msg, size_t len, | ||
| 81 | void *user_icmph, size_t icmph_len); | ||
| 82 | int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | ||
| 83 | size_t len); | ||
| 84 | int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | ||
| 85 | size_t len); | ||
| 86 | int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); | ||
| 87 | void ping_rcv(struct sk_buff *skb); | ||
| 46 | 88 | ||
| 47 | #ifdef CONFIG_PROC_FS | 89 | #ifdef CONFIG_PROC_FS |
| 48 | extern int __init ping_proc_init(void); | 90 | extern int __init ping_proc_init(void); |
| @@ -50,6 +92,7 @@ extern void ping_proc_exit(void); | |||
| 50 | #endif | 92 | #endif |
| 51 | 93 | ||
| 52 | void __init ping_init(void); | 94 | void __init ping_init(void); |
| 53 | 95 | int __init pingv6_init(void); | |
| 96 | void pingv6_exit(void); | ||
| 54 | 97 | ||
| 55 | #endif /* _PING_H */ | 98 | #endif /* _PING_H */ |
diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h index 938b7fd11204..eb40e71ff2ee 100644 --- a/include/net/transp_v6.h +++ b/include/net/transp_v6.h | |||
| @@ -11,6 +11,7 @@ extern struct proto rawv6_prot; | |||
| 11 | extern struct proto udpv6_prot; | 11 | extern struct proto udpv6_prot; |
| 12 | extern struct proto udplitev6_prot; | 12 | extern struct proto udplitev6_prot; |
| 13 | extern struct proto tcpv6_prot; | 13 | extern struct proto tcpv6_prot; |
| 14 | extern struct proto pingv6_prot; | ||
| 14 | 15 | ||
| 15 | struct flowi6; | 16 | struct flowi6; |
| 16 | 17 | ||
| @@ -21,6 +22,8 @@ extern int ipv6_frag_init(void); | |||
| 21 | extern void ipv6_frag_exit(void); | 22 | extern void ipv6_frag_exit(void); |
| 22 | 23 | ||
| 23 | /* transport protocols */ | 24 | /* transport protocols */ |
| 25 | extern int pingv6_init(void); | ||
| 26 | extern void pingv6_exit(void); | ||
| 24 | extern int rawv6_init(void); | 27 | extern int rawv6_init(void); |
| 25 | extern void rawv6_exit(void); | 28 | extern void rawv6_exit(void); |
| 26 | extern int udpv6_init(void); | 29 | extern int udpv6_init(void); |
