^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * INET An implementation of the TCP/IP protocol suite for the LINUX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * operating system. INET is implemented using the BSD Socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * interface as the means of communication with the user level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * "Ping" sockets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Based on ipv4/ping.c code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Authors: Lorenzo Colitti (IPv6 support)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Vasiliy Kulikov / Openwall (IPv4 implementation, for Linux 2.6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Pavel Kankovsky (IPv4 implementation, for Linux 2.4.32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <net/addrconf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <net/ipv6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <net/ip6_route.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <net/protocol.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <net/udp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <net/transp_v6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <net/ping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /* Compatibility glue so we can support IPv6 when it's compiled as a module */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) int *addr_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return -EAFNOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static void dummy_ip6_datagram_recv_ctl(struct sock *sk, struct msghdr *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static int dummy_icmpv6_err_convert(u8 type, u8 code, int *err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return -EAFNOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static void dummy_ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) __be16 port, u32 info, u8 *payload) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static int dummy_ipv6_chk_addr(struct net *net, const struct in6_addr *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) const struct net_device *dev, int strict)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct inet_sock *inet = inet_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct ipv6_pinfo *np = inet6_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct icmp6hdr user_icmph;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) int addr_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct in6_addr *daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) int oif = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct flowi6 fl6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct dst_entry *dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct rt6_info *rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct pingfakehdr pfh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct ipcm6_cookie ipc6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) pr_debug("ping_v6_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) err = ping_common_sendmsg(AF_INET6, msg, len, &user_icmph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) sizeof(user_icmph));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (msg->msg_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) DECLARE_SOCKADDR(struct sockaddr_in6 *, u, msg->msg_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (msg->msg_namelen < sizeof(*u))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (u->sin6_family != AF_INET6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return -EAFNOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) daddr = &(u->sin6_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (__ipv6_addr_needs_scope_id(ipv6_addr_type(daddr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) oif = u->sin6_scope_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (sk->sk_state != TCP_ESTABLISHED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return -EDESTADDRREQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) daddr = &sk->sk_v6_daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (!oif)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) oif = sk->sk_bound_dev_if;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (!oif)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) oif = np->sticky_pktinfo.ipi6_ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (!oif && ipv6_addr_is_multicast(daddr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) oif = np->mcast_oif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) else if (!oif)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) oif = np->ucast_oif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) addr_type = ipv6_addr_type(daddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if ((__ipv6_addr_needs_scope_id(addr_type) && !oif) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) (addr_type & IPV6_ADDR_MAPPED) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) (oif && sk->sk_bound_dev_if && oif != sk->sk_bound_dev_if))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* TODO: use ip6_datagram_send_ctl to get options from cmsg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) memset(&fl6, 0, sizeof(fl6));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) fl6.flowi6_proto = IPPROTO_ICMPV6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) fl6.saddr = np->saddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) fl6.daddr = *daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) fl6.flowi6_oif = oif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) fl6.flowi6_mark = sk->sk_mark;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) fl6.flowi6_uid = sk->sk_uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) fl6.fl6_icmp_type = user_icmph.icmp6_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) fl6.fl6_icmp_code = user_icmph.icmp6_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) ipcm6_init_sk(&ipc6, np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ipc6.sockc.mark = sk->sk_mark;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) fl6.flowlabel = ip6_make_flowinfo(ipc6.tclass, fl6.flowlabel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) dst = ip6_sk_dst_lookup_flow(sk, &fl6, daddr, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (IS_ERR(dst))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return PTR_ERR(dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) rt = (struct rt6_info *) dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) fl6.flowi6_oif = np->mcast_oif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) else if (!fl6.flowi6_oif)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) fl6.flowi6_oif = np->ucast_oif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) pfh.icmph.type = user_icmph.icmp6_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) pfh.icmph.code = user_icmph.icmp6_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) pfh.icmph.checksum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) pfh.icmph.un.echo.id = inet->inet_sport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) pfh.icmph.un.echo.sequence = user_icmph.icmp6_sequence;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) pfh.msg = msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) pfh.wcheck = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) pfh.family = AF_INET6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) err = ip6_append_data(sk, ping_getfrag, &pfh, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 0, &ipc6, &fl6, rt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) MSG_DONTWAIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) ICMP6_INC_STATS(sock_net(sk), rt->rt6i_idev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) ICMP6_MIB_OUTERRORS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) ip6_flush_pending_frames(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) icmpv6_push_pending_frames(sk, &fl6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) (struct icmp6hdr *)&pfh.icmph, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) dst_release(dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct proto pingv6_prot = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) .name = "PINGv6",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) .init = ping_init_sock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) .close = ping_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) .connect = ip6_datagram_connect_v6_only,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) .disconnect = __udp_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) .setsockopt = ipv6_setsockopt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .getsockopt = ipv6_getsockopt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) .sendmsg = ping_v6_sendmsg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) .recvmsg = ping_recvmsg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) .bind = ping_bind,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) .backlog_rcv = ping_queue_rcv_skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .hash = ping_hash,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .unhash = ping_unhash,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) .get_port = ping_get_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .obj_size = sizeof(struct raw6_sock),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) EXPORT_SYMBOL_GPL(pingv6_prot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static struct inet_protosw pingv6_protosw = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .type = SOCK_DGRAM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) .protocol = IPPROTO_ICMPV6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) .prot = &pingv6_prot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) .ops = &inet6_sockraw_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .flags = INET_PROTOSW_REUSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) #ifdef CONFIG_PROC_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) static void *ping_v6_seq_start(struct seq_file *seq, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return ping_seq_start(seq, pos, AF_INET6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static int ping_v6_seq_show(struct seq_file *seq, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (v == SEQ_START_TOKEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) seq_puts(seq, IPV6_SEQ_DGRAM_HEADER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) int bucket = ((struct ping_iter_state *) seq->private)->bucket;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) struct inet_sock *inet = inet_sk(v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) __u16 srcp = ntohs(inet->inet_sport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) __u16 destp = ntohs(inet->inet_dport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) ip6_dgram_sock_seq_show(seq, v, srcp, destp, bucket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static const struct seq_operations ping_v6_seq_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .start = ping_v6_seq_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) .show = ping_v6_seq_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) .next = ping_seq_next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) .stop = ping_seq_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static int __net_init ping_v6_proc_init_net(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (!proc_create_net("icmp6", 0444, net->proc_net, &ping_v6_seq_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) sizeof(struct ping_iter_state)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static void __net_exit ping_v6_proc_exit_net(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) remove_proc_entry("icmp6", net->proc_net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static struct pernet_operations ping_v6_net_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) .init = ping_v6_proc_init_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) .exit = ping_v6_proc_exit_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) int __init pingv6_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) #ifdef CONFIG_PROC_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int ret = register_pernet_subsys(&ping_v6_net_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) pingv6_ops.ipv6_recv_error = ipv6_recv_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) pingv6_ops.ip6_datagram_recv_common_ctl = ip6_datagram_recv_common_ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) pingv6_ops.ip6_datagram_recv_specific_ctl =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) ip6_datagram_recv_specific_ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) pingv6_ops.icmpv6_err_convert = icmpv6_err_convert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) pingv6_ops.ipv6_icmp_error = ipv6_icmp_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) pingv6_ops.ipv6_chk_addr = ipv6_chk_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return inet6_register_protosw(&pingv6_protosw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /* This never gets called because it's not possible to unload the ipv6 module,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * but just in case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) void pingv6_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) pingv6_ops.ipv6_recv_error = dummy_ipv6_recv_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) pingv6_ops.ip6_datagram_recv_common_ctl = dummy_ip6_datagram_recv_ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) pingv6_ops.ip6_datagram_recv_specific_ctl = dummy_ip6_datagram_recv_ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) pingv6_ops.icmpv6_err_convert = dummy_icmpv6_err_convert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) pingv6_ops.ipv6_icmp_error = dummy_ipv6_icmp_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) pingv6_ops.ipv6_chk_addr = dummy_ipv6_chk_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) #ifdef CONFIG_PROC_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) unregister_pernet_subsys(&ping_v6_net_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) inet6_unregister_protosw(&pingv6_protosw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }