linux/net/netfilter/ipvs/ip_vs_core.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * IPVS         An implementation of the IP virtual server support for the
 *              LINUX operating system.  IPVS is now implemented as a module
 *              over the Netfilter framework. IPVS can be used to build a
 *              high-performance and highly available server based on a
 *              cluster of servers.
 *
 * Authors:     Wensong Zhang <[email protected]>
 *              Peter Kese <[email protected]>
 *              Julian Anastasov <[email protected]>
 *
 * The IPVS code for kernel 2.2 was done by Wensong Zhang and Peter Kese,
 * with changes/fixes from Julian Anastasov, Lars Marowsky-Bree, Horms
 * and others.
 *
 * Changes:
 *	Paul `Rusty' Russell		properly handle non-linear skbs
 *	Harald Welte			don't use nfcache
 */

#define KMSG_COMPONENT
#define pr_fmt(fmt)

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/sctp.h>
#include <linux/icmp.h>
#include <linux/slab.h>

#include <net/ip.h>
#include <net/tcp.h>
#include <net/udp.h>
#include <net/icmp.h>                   /* for icmp_send */
#include <net/gue.h>
#include <net/gre.h>
#include <net/route.h>
#include <net/ip6_checksum.h>
#include <net/netns/generic.h>		/* net_generic() */

#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>

#ifdef CONFIG_IP_VS_IPV6
#include <net/ipv6.h>
#include <linux/netfilter_ipv6.h>
#include <net/ip6_route.h>
#endif

#include <net/ip_vs.h>
#include <linux/indirect_call_wrapper.h>


EXPORT_SYMBOL();
EXPORT_SYMBOL();
EXPORT_SYMBOL();
EXPORT_SYMBOL();
EXPORT_SYMBOL();
EXPORT_SYMBOL();
#ifdef CONFIG_IP_VS_PROTO_TCP
EXPORT_SYMBOL();
#endif
EXPORT_SYMBOL();
#ifdef CONFIG_IP_VS_DEBUG
EXPORT_SYMBOL();
#endif
EXPORT_SYMBOL();

#if defined(CONFIG_IP_VS_PROTO_TCP) && defined(CONFIG_IP_VS_PROTO_UDP)
#define SNAT_CALL(f, ...)
#elif defined(CONFIG_IP_VS_PROTO_TCP)
#define SNAT_CALL
#elif defined(CONFIG_IP_VS_PROTO_UDP)
#define SNAT_CALL
#else
#define SNAT_CALL
#endif

static unsigned int ip_vs_net_id __read_mostly;
/* netns cnt used for uniqueness */
static atomic_t ipvs_netns_cnt =;

/* ID used in ICMP lookups */
#define icmp_id(icmph)
#define icmpv6_id(icmph)

const char *ip_vs_proto_name(unsigned int proto)
{}

void ip_vs_init_hash_table(struct list_head *table, int rows)
{}

static inline void
ip_vs_in_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
{}


static inline void
ip_vs_out_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
{}


static inline void
ip_vs_conn_stats(struct ip_vs_conn *cp, struct ip_vs_service *svc)
{}


static inline void
ip_vs_set_state(struct ip_vs_conn *cp, int direction,
		const struct sk_buff *skb,
		struct ip_vs_proto_data *pd)
{}

static inline int
ip_vs_conn_fill_param_persist(const struct ip_vs_service *svc,
			      struct sk_buff *skb, int protocol,
			      const union nf_inet_addr *caddr, __be16 cport,
			      const union nf_inet_addr *vaddr, __be16 vport,
			      struct ip_vs_conn_param *p)
{}

/*
 *  IPVS persistent scheduling function
 *  It creates a connection entry according to its template if exists,
 *  or selects a server and creates a connection entry plus a template.
 *  Locking: we are svc user (svc->refcnt), so we hold all dests too
 *  Protocols supported: TCP, UDP
 */
static struct ip_vs_conn *
ip_vs_sched_persist(struct ip_vs_service *svc,
		    struct sk_buff *skb, __be16 src_port, __be16 dst_port,
		    int *ignored, struct ip_vs_iphdr *iph)
{}


/*
 *  IPVS main scheduling function
 *  It selects a server according to the virtual service, and
 *  creates a connection entry.
 *  Protocols supported: TCP, UDP
 *
 *  Usage of *ignored
 *
 * 1 :   protocol tried to schedule (eg. on SYN), found svc but the
 *       svc/scheduler decides that this packet should be accepted with
 *       NF_ACCEPT because it must not be scheduled.
 *
 * 0 :   scheduler can not find destination, so try bypass or
 *       return ICMP and then NF_DROP (ip_vs_leave).
 *
 * -1 :  scheduler tried to schedule but fatal error occurred, eg.
 *       ip_vs_conn_new failure (ENOMEM) or ip_vs_sip_fill_param
 *       failure such as missing Call-ID, ENOMEM on skb_linearize
 *       or pe_data. In this case we should return NF_DROP without
 *       any attempts to send ICMP with ip_vs_leave.
 */
struct ip_vs_conn *
ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
	       struct ip_vs_proto_data *pd, int *ignored,
	       struct ip_vs_iphdr *iph)
{}

static inline int ip_vs_addr_is_unicast(struct net *net, int af,
					union nf_inet_addr *addr)
{}

/*
 *  Pass or drop the packet.
 *  Called by ip_vs_in, when the virtual service is available but
 *  no destination is available for a new connection.
 */
int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
		struct ip_vs_proto_data *pd, struct ip_vs_iphdr *iph)
{}

#ifdef CONFIG_SYSCTL

static int sysctl_snat_reroute(struct netns_ipvs *ipvs)
{}

static int sysctl_nat_icmp_send(struct netns_ipvs *ipvs)
{}

#else

static int sysctl_snat_reroute(struct netns_ipvs *ipvs) { return 0; }
static int sysctl_nat_icmp_send(struct netns_ipvs *ipvs) { return 0; }

#endif

__sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset)
{}

static inline enum ip_defrag_users ip_vs_defrag_user(unsigned int hooknum)
{}

static inline int ip_vs_gather_frags(struct netns_ipvs *ipvs,
				     struct sk_buff *skb, u_int32_t user)
{}

static int ip_vs_route_me_harder(struct netns_ipvs *ipvs, int af,
				 struct sk_buff *skb, unsigned int hooknum)
{}

/*
 * Packet has been made sufficiently writable in caller
 * - inout: 1=in->out, 0=out->in
 */
void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
		    struct ip_vs_conn *cp, int inout)
{}

#ifdef CONFIG_IP_VS_IPV6
void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp,
		    struct ip_vs_conn *cp, int inout)
{}
#endif

/* Handle relevant response ICMP messages - forward to the right
 * destination host.
 */
static int handle_response_icmp(int af, struct sk_buff *skb,
				union nf_inet_addr *snet,
				__u8 protocol, struct ip_vs_conn *cp,
				struct ip_vs_protocol *pp,
				unsigned int offset, unsigned int ihl,
				unsigned int hooknum)
{}

/*
 *	Handle ICMP messages in the inside-to-outside direction (outgoing).
 *	Find any that might be relevant, check against existing connections.
 *	Currently handles error types - unreachable, quench, ttl exceeded.
 */
static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
			  int *related, unsigned int hooknum)
{}

#ifdef CONFIG_IP_VS_IPV6
static int ip_vs_out_icmp_v6(struct netns_ipvs *ipvs, struct sk_buff *skb,
			     int *related,  unsigned int hooknum,
			     struct ip_vs_iphdr *ipvsh)
{}
#endif

/*
 * Check if sctp chunc is ABORT chunk
 */
static inline int is_sctp_abort(const struct sk_buff *skb, int nh_len)
{}

static inline int is_tcp_reset(const struct sk_buff *skb, int nh_len)
{}

static inline bool is_new_conn(const struct sk_buff *skb,
			       struct ip_vs_iphdr *iph)
{}

static inline bool is_new_conn_expected(const struct ip_vs_conn *cp,
					int conn_reuse_mode)
{}

/* Generic function to create new connections for outgoing RS packets
 *
 * Pre-requisites for successful connection creation:
 * 1) Virtual Service is NOT fwmark based:
 *    In fwmark-VS actual vaddr and vport are unknown to IPVS
 * 2) Real Server and Virtual Service were NOT configured without port:
 *    This is to allow match of different VS to the same RS ip-addr
 */
struct ip_vs_conn *ip_vs_new_conn_out(struct ip_vs_service *svc,
				      struct ip_vs_dest *dest,
				      struct sk_buff *skb,
				      const struct ip_vs_iphdr *iph,
				      __be16 dport,
				      __be16 cport)
{}

/* Handle outgoing packets which are considered requests initiated by
 * real servers, so that subsequent responses from external client can be
 * routed to the right real server.
 * Used also for outgoing responses in OPS mode.
 *
 * Connection management is handled by persistent-engine specific callback.
 */
static struct ip_vs_conn *__ip_vs_rs_conn_out(unsigned int hooknum,
					      struct netns_ipvs *ipvs,
					      int af, struct sk_buff *skb,
					      const struct ip_vs_iphdr *iph)
{}

/* Handle response packets: rewrite addresses and send away...
 */
static unsigned int
handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
		struct ip_vs_conn *cp, struct ip_vs_iphdr *iph,
		unsigned int hooknum)
{}

/*
 *	Check if outgoing packet belongs to the established ip_vs_conn.
 */
static unsigned int
ip_vs_out_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
{}

static unsigned int
ip_vs_try_to_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
		      struct ip_vs_proto_data *pd,
		      int *verdict, struct ip_vs_conn **cpp,
		      struct ip_vs_iphdr *iph)
{}

/* Check the UDP tunnel and return its header length */
static int ipvs_udp_decap(struct netns_ipvs *ipvs, struct sk_buff *skb,
			  unsigned int offset, __u16 af,
			  const union nf_inet_addr *daddr, __u8 *proto)
{}

/* Check the GRE tunnel and return its header length */
static int ipvs_gre_decap(struct netns_ipvs *ipvs, struct sk_buff *skb,
			  unsigned int offset, __u16 af,
			  const union nf_inet_addr *daddr, __u8 *proto)
{}

/*
 *	Handle ICMP messages in the outside-to-inside direction (incoming).
 *	Find any that might be relevant, check against existing connections,
 *	forward to the right destination host if relevant.
 *	Currently handles error types - unreachable, quench, ttl exceeded.
 */
static int
ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
	      unsigned int hooknum)
{}

#ifdef CONFIG_IP_VS_IPV6
static int ip_vs_in_icmp_v6(struct netns_ipvs *ipvs, struct sk_buff *skb,
			    int *related, unsigned int hooknum,
			    struct ip_vs_iphdr *iph)
{}
#endif


/*
 *	Check if it's for virtual services, look it up,
 *	and send it on its way...
 */
static unsigned int
ip_vs_in_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
{}

/*
 *	It is hooked at the NF_INET_FORWARD chain, in order to catch ICMP
 *      related packets destined for 0.0.0.0/0.
 *      When fwmark-based virtual service is used, such as transparent
 *      cache cluster, TCP packets can be marked and routed to ip_vs_in,
 *      but ICMP destined for 0.0.0.0/0 cannot not be easily marked and
 *      sent to ip_vs_in_icmp. So, catch them at the NF_INET_FORWARD chain
 *      and send them to ip_vs_in_icmp.
 */
static unsigned int
ip_vs_forward_icmp(void *priv, struct sk_buff *skb,
		   const struct nf_hook_state *state)
{}

static const struct nf_hook_ops ip_vs_ops4[] =;

#ifdef CONFIG_IP_VS_IPV6
static const struct nf_hook_ops ip_vs_ops6[] =;
#endif

int ip_vs_register_hooks(struct netns_ipvs *ipvs, unsigned int af)
{}

void ip_vs_unregister_hooks(struct netns_ipvs *ipvs, unsigned int af)
{}

/*
 *	Initialize IP Virtual Server netns mem.
 */
static int __net_init __ip_vs_init(struct net *net)
{}

static void __net_exit __ip_vs_cleanup_batch(struct list_head *net_list)
{}

static void __net_exit __ip_vs_dev_cleanup_batch(struct list_head *net_list)
{}

static struct pernet_operations ipvs_core_ops =;

static struct pernet_operations ipvs_core_dev_ops =;

/*
 *	Initialize IP Virtual Server
 */
static int __init ip_vs_init(void)
{}

static void __exit ip_vs_cleanup(void)
{}

module_init();
module_exit(ip_vs_cleanup);
MODULE_LICENSE();
MODULE_DESCRIPTION();