Skip to content

Commit 6d0bfe2

Browse files
lcolittidavem330
authored andcommitted
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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 6e2842f commit 6d0bfe2

File tree

9 files changed

+698
-171
lines changed

9 files changed

+698
-171
lines changed

include/net/ipv6.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,12 @@ static inline void fl6_sock_release(struct ip6_flowlabel *fl)
260260

261261
extern void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info);
262262

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+
263269
extern int ip6_ra_control(struct sock *sk, int sel);
264270

265271
extern int ipv6_parse_hopopts(struct sk_buff *skb);

include/net/ping.h

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef _PING_H
1414
#define _PING_H
1515

16+
#include <net/icmp.h>
1617
#include <net/netns/hash.h>
1718

1819
/* PING_HTABLE_SIZE must be power of 2 */
@@ -28,6 +29,18 @@
2829
*/
2930
#define GID_T_MAX (((gid_t)~0U) >> 1)
3031

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+
3144
struct ping_table {
3245
struct hlist_nulls_head hash[PING_HTABLE_SIZE];
3346
rwlock_t lock;
@@ -39,17 +52,47 @@ struct ping_iter_state {
3952
};
4053

4154
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
4259

60+
struct pingfakehdr {
61+
struct icmphdr icmph;
62+
struct iovec *iov;
63+
sa_family_t family;
64+
__wsum wcheck;
65+
};
4366

44-
extern void ping_rcv(struct sk_buff *);
45-
extern void ping_err(struct sk_buff *, u32 info);
67+
int ping_get_port(struct sock *sk, unsigned short ident);
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);
4688

4789
#ifdef CONFIG_PROC_FS
4890
extern int __init ping_proc_init(void);
4991
extern void ping_proc_exit(void);
5092
#endif
5193

5294
void __init ping_init(void);
53-
95+
int __init pingv6_init(void);
96+
void pingv6_exit(void);
5497

5598
#endif /* _PING_H */

include/net/transp_v6.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ extern struct proto rawv6_prot;
1111
extern struct proto udpv6_prot;
1212
extern struct proto udplitev6_prot;
1313
extern struct proto tcpv6_prot;
14+
extern struct proto pingv6_prot;
1415

1516
struct flowi6;
1617

@@ -21,6 +22,8 @@ extern int ipv6_frag_init(void);
2122
extern void ipv6_frag_exit(void);
2223

2324
/* transport protocols */
25+
extern int pingv6_init(void);
26+
extern void pingv6_exit(void);
2427
extern int rawv6_init(void);
2528
extern void rawv6_exit(void);
2629
extern int udpv6_init(void);

net/ipv4/icmp.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -939,7 +939,8 @@ int icmp_rcv(struct sk_buff *skb)
939939
void icmp_err(struct sk_buff *skb, u32 info)
940940
{
941941
struct iphdr *iph = (struct iphdr *)skb->data;
942-
struct icmphdr *icmph = (struct icmphdr *)(skb->data+(iph->ihl<<2));
942+
int offset = iph->ihl<<2;
943+
struct icmphdr *icmph = (struct icmphdr *)(skb->data + offset);
943944
int type = icmp_hdr(skb)->type;
944945
int code = icmp_hdr(skb)->code;
945946
struct net *net = dev_net(skb->dev);
@@ -949,7 +950,7 @@ void icmp_err(struct sk_buff *skb, u32 info)
949950
* triggered by ICMP_ECHOREPLY which sent from kernel.
950951
*/
951952
if (icmph->type != ICMP_ECHOREPLY) {
952-
ping_err(skb, info);
953+
ping_err(skb, offset, info);
953954
return;
954955
}
955956

0 commit comments

Comments
 (0)