/*
* IP Virtual Server
* data structure and functionality definitions
*/
#ifndef _NET_IP_VS_H
#define _NET_IP_VS_H
#include <linux/ip_vs.h> /* definitions shared with userland */
/* old ipvsadm versions still include this file directly */
#ifdef __KERNEL__
#include <asm/types.h> /* for __uXX types */
#include <linux/sysctl.h> /* for ctl_path */
#include <linux/list.h> /* for struct list_head */
#include <linux/spinlock.h> /* for struct rwlock_t */
#include <asm/atomic.h> /* for struct atomic_t */
#include <linux/compiler.h>
#include <linux/timer.h>
#include <net/checksum.h>
#include <linux/netfilter.h> /* for union nf_inet_addr */
#include <linux/ip.h>
#include <linux/ipv6.h> /* for struct ipv6hdr */
#include <net/ipv6.h> /* for ipv6_addr_copy */
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
#include <net/netfilter/nf_conntrack.h>
#endif
/* Connections' size value needed by ip_vs_ctl.c */
extern int ip_vs_conn_tab_size;
struct ip_vs_iphdr {
int len;
__u8 protocol;
union nf_inet_addr saddr;
union nf_inet_addr daddr;
};
static inline void
ip_vs_fill_iphdr(int af, const void *nh, struct ip_vs_iphdr *iphdr)
{
#ifdef CONFIG_IP_VS_IPV6
if (af == AF_INET6) {
const struct ipv6hdr *iph = nh;
iphdr->len = sizeof(struct ipv6hdr);
iphdr->protocol = iph->nexthdr;
ipv6_addr_copy(&iphdr->saddr.in6, &iph->saddr);
ipv6_addr_copy(&iphdr->daddr.in6, &iph->daddr);
} else
#endif
{
const struct iphdr *iph = nh;
iphdr->len = iph->ihl * 4;
iphdr->protocol = iph->protocol;
iphdr->saddr.ip = iph->saddr;
iphdr->daddr.ip = iph->daddr;
}
}
static inline void ip_vs_addr_copy(int af, union nf_inet_addr *dst,
const union nf_inet_addr *src)
{
#ifdef CONFIG_IP_VS_IPV6
if (af == AF_INET6)
ipv6_addr_copy(&dst->in6, &src->in6);
else
#endif
dst->ip = src->ip;
}
static inline int ip_vs_addr_equal(int af, const union nf_inet_addr *a,
const union nf_inet_addr *b)
{
#ifdef CONFIG_IP_VS_IPV6
if (af == AF_INET6)
return ipv6_addr_equal(&a->in6, &b->in6);
#endif
return a->ip == b->ip;
}
#ifdef CONFIG_IP_VS_DEBUG
#include <linux/net.h>
extern int ip_vs_get_debug_level(void);
static inline const char *ip_vs_dbg_addr(int af, char *buf, size_t buf_len,
const union nf_inet_addr *addr,
int *idx)
{
int len;
#ifdef CONFIG_IP_VS_IPV6
if (af == AF_INET6)
len = snprintf(&buf[*idx], buf_len - *idx, "[%pI6]",
&addr->in6) + 1;
else
#endif
len = snprintf(&buf[*idx], buf_len - *idx, "%pI4",
&addr->ip) + 1;
*idx += len;
BUG_ON(*idx > buf_len + 1);
return &buf[*idx - len];
}
#define IP_VS_DBG_BUF(level, msg, ...) \
do { \
char ip_vs_dbg_buf[160]; \
int ip_vs_dbg_idx = 0; \
if (level <= ip_vs_get_debug_level()) \
printk(KERN_DEBUG pr_fmt(msg), ##__VA_ARGS__); \
} while (0)
#define IP_VS_ERR_BUF(msg...) \
do { \
char ip_vs_dbg_buf[160]; \
int ip_vs_dbg_idx = 0; \
pr_err(msg); \
} while (0)
/* Only use from within IP_VS_DBG_BUF() or IP_VS_ERR_BUF macros */
#define IP_VS_DBG_ADDR(af, addr) \
ip_vs_dbg_addr(af, ip_vs_dbg_buf, \
sizeof(ip_vs_dbg_buf), addr, \
&ip_vs_dbg_idx)
#define IP_VS_DBG(level, msg, ...) \
do { \
if (level <= ip_vs_get_debug_level()) \
printk(KERN_DEBUG pr_fmt(msg), ##__VA_ARGS__); \
} while (0)
#define IP_VS_DBG_RL(msg, ...) \
do { \
if (net_ratelimit()) \
printk(KERN_DEBUG pr_fmt(msg), ##__VA_ARGS__); \
} while (0)
#define IP_VS_DBG_PKT(level, af, pp, skb, ofs, msg) \
do { \
if (level <= ip_vs_get_debug_level()) \
pp->debug_packet(af, pp, skb, ofs, msg); \
} while (0)
#define IP_VS_DBG_RL_PKT(level, af, pp, skb, ofs, msg) \
do { \
if (level <= ip_vs_get_debug_level() && \
net_ratelimit()) \
pp->debug_packet(af, pp, skb, ofs, msg); \
} while (0)
#else /* NO DEBUGGING at ALL */
#define IP_VS_DBG_BUF(level, msg...) do {} while (0)
#define IP_VS_ERR_BUF(msg...) do {} while (0)
#define IP_VS_DBG(level, msg...) do {} while (0)
#define IP_VS_DBG_RL(msg...) do {} while (0)
#define IP_VS_DBG_PKT(level, af, pp, skb, ofs, msg) do {} while (0)
#define IP_VS_DBG_RL_PKT(level, af, pp, skb, ofs, msg) do {} while (0)
#endif
#define IP_VS_BUG() BUG()
#define