Commit 9330419d authored by Hans Schillstrom's avatar Hans Schillstrom Committed by Simon Horman

IPVS: netns, use ip_vs_proto_data as param.

ip_vs_protocol *pp is replaced by ip_vs_proto_data *pd in
function call in ip_vs_protocol struct i.e. :,
 - timeout_change()
 - state_transition()

ip_vs_protocol_timeout_change() got ipvs as param, due to above
and a upcoming patch - defence work

Most of this changes are triggered by Julians comment:
"tcp_timeout_change should work with the new struct ip_vs_proto_data
        so that tcp_state_table will go to pd->state_table
        and set_tcp_state will get pd instead of pp"

*v3
Mostly comments from Julian
The pp -> pd conversion should start from functions like
ip_vs_out() that use pp = ip_vs_proto_get(iph.protocol),
now they should use ip_vs_proto_data_get(net, iph.protocol).
conn_in_get() and conn_out_get() unused param *pp, removed.

*v4
ip_vs_protocol_timeout_change() walk the proto_data path.
Signed-off-by: default avatarHans Schillstrom <hans.schillstrom@ericsson.com>
Acked-by: default avatarJulian Anastasov <ja@ssi.bg>
Signed-off-by: default avatarSimon Horman <horms@verge.net.au>
parent 88fe2d37
...@@ -372,13 +372,12 @@ struct ip_vs_protocol { ...@@ -372,13 +372,12 @@ struct ip_vs_protocol {
void (*exit_netns)(struct net *net, struct ip_vs_proto_data *pd); void (*exit_netns)(struct net *net, struct ip_vs_proto_data *pd);
int (*conn_schedule)(int af, struct sk_buff *skb, int (*conn_schedule)(int af, struct sk_buff *skb,
struct ip_vs_protocol *pp, struct ip_vs_proto_data *pd,
int *verdict, struct ip_vs_conn **cpp); int *verdict, struct ip_vs_conn **cpp);
struct ip_vs_conn * struct ip_vs_conn *
(*conn_in_get)(int af, (*conn_in_get)(int af,
const struct sk_buff *skb, const struct sk_buff *skb,
struct ip_vs_protocol *pp,
const struct ip_vs_iphdr *iph, const struct ip_vs_iphdr *iph,
unsigned int proto_off, unsigned int proto_off,
int inverse); int inverse);
...@@ -386,7 +385,6 @@ struct ip_vs_protocol { ...@@ -386,7 +385,6 @@ struct ip_vs_protocol {
struct ip_vs_conn * struct ip_vs_conn *
(*conn_out_get)(int af, (*conn_out_get)(int af,
const struct sk_buff *skb, const struct sk_buff *skb,
struct ip_vs_protocol *pp,
const struct ip_vs_iphdr *iph, const struct ip_vs_iphdr *iph,
unsigned int proto_off, unsigned int proto_off,
int inverse); int inverse);
...@@ -404,7 +402,7 @@ struct ip_vs_protocol { ...@@ -404,7 +402,7 @@ struct ip_vs_protocol {
int (*state_transition)(struct ip_vs_conn *cp, int direction, int (*state_transition)(struct ip_vs_conn *cp, int direction,
const struct sk_buff *skb, const struct sk_buff *skb,
struct ip_vs_protocol *pp); struct ip_vs_proto_data *pd);
int (*register_app)(struct ip_vs_app *inc); int (*register_app)(struct ip_vs_app *inc);
...@@ -417,9 +415,7 @@ struct ip_vs_protocol { ...@@ -417,9 +415,7 @@ struct ip_vs_protocol {
int offset, int offset,
const char *msg); const char *msg);
void (*timeout_change)(struct ip_vs_protocol *pp, int flags); void (*timeout_change)(struct ip_vs_proto_data *pd, int flags);
int (*set_state_timeout)(struct ip_vs_protocol *pp, char *sname, int to);
}; };
/* /*
...@@ -778,7 +774,6 @@ struct ip_vs_conn *ip_vs_conn_in_get(const struct ip_vs_conn_param *p); ...@@ -778,7 +774,6 @@ struct ip_vs_conn *ip_vs_conn_in_get(const struct ip_vs_conn_param *p);
struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p); struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p);
struct ip_vs_conn * ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb, struct ip_vs_conn * ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,
struct ip_vs_protocol *pp,
const struct ip_vs_iphdr *iph, const struct ip_vs_iphdr *iph,
unsigned int proto_off, unsigned int proto_off,
int inverse); int inverse);
...@@ -786,7 +781,6 @@ struct ip_vs_conn * ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb, ...@@ -786,7 +781,6 @@ struct ip_vs_conn * ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,
struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p); struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p);
struct ip_vs_conn * ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb, struct ip_vs_conn * ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb,
struct ip_vs_protocol *pp,
const struct ip_vs_iphdr *iph, const struct ip_vs_iphdr *iph,
unsigned int proto_off, unsigned int proto_off,
int inverse); int inverse);
...@@ -917,7 +911,7 @@ static inline void ip_vs_pe_put(const struct ip_vs_pe *pe) ...@@ -917,7 +911,7 @@ static inline void ip_vs_pe_put(const struct ip_vs_pe *pe)
*/ */
extern int ip_vs_protocol_init(void); extern int ip_vs_protocol_init(void);
extern void ip_vs_protocol_cleanup(void); extern void ip_vs_protocol_cleanup(void);
extern void ip_vs_protocol_timeout_change(int flags); extern void ip_vs_protocol_timeout_change(struct netns_ipvs *ipvs, int flags);
extern int *ip_vs_create_timeout_table(int *table, int size); extern int *ip_vs_create_timeout_table(int *table, int size);
extern int extern int
ip_vs_set_state_timeout(int *table, int num, const char *const *names, ip_vs_set_state_timeout(int *table, int num, const char *const *names,
...@@ -947,9 +941,9 @@ extern struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name); ...@@ -947,9 +941,9 @@ extern struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name);
extern void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler); extern void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler);
extern struct ip_vs_conn * extern struct ip_vs_conn *
ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb, ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
struct ip_vs_protocol *pp, int *ignored); struct ip_vs_proto_data *pd, int *ignored);
extern int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, extern int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
struct ip_vs_protocol *pp); struct ip_vs_proto_data *pd);
/* /*
......
...@@ -329,7 +329,6 @@ ip_vs_conn_fill_param_proto(int af, const struct sk_buff *skb, ...@@ -329,7 +329,6 @@ ip_vs_conn_fill_param_proto(int af, const struct sk_buff *skb,
struct ip_vs_conn * struct ip_vs_conn *
ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb, ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,
struct ip_vs_protocol *pp,
const struct ip_vs_iphdr *iph, const struct ip_vs_iphdr *iph,
unsigned int proto_off, int inverse) unsigned int proto_off, int inverse)
{ {
...@@ -428,7 +427,6 @@ struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p) ...@@ -428,7 +427,6 @@ struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p)
struct ip_vs_conn * struct ip_vs_conn *
ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb, ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb,
struct ip_vs_protocol *pp,
const struct ip_vs_iphdr *iph, const struct ip_vs_iphdr *iph,
unsigned int proto_off, int inverse) unsigned int proto_off, int inverse)
{ {
......
...@@ -177,11 +177,11 @@ ip_vs_conn_stats(struct ip_vs_conn *cp, struct ip_vs_service *svc) ...@@ -177,11 +177,11 @@ ip_vs_conn_stats(struct ip_vs_conn *cp, struct ip_vs_service *svc)
static inline int static inline int
ip_vs_set_state(struct ip_vs_conn *cp, int direction, ip_vs_set_state(struct ip_vs_conn *cp, int direction,
const struct sk_buff *skb, const struct sk_buff *skb,
struct ip_vs_protocol *pp) struct ip_vs_proto_data *pd)
{ {
if (unlikely(!pp->state_transition)) if (unlikely(!pd->pp->state_transition))
return 0; return 0;
return pp->state_transition(cp, direction, skb, pp); return pd->pp->state_transition(cp, direction, skb, pd);
} }
static inline int static inline int
...@@ -378,8 +378,9 @@ ip_vs_sched_persist(struct ip_vs_service *svc, ...@@ -378,8 +378,9 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
*/ */
struct ip_vs_conn * struct ip_vs_conn *
ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb, ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
struct ip_vs_protocol *pp, int *ignored) struct ip_vs_proto_data *pd, int *ignored)
{ {
struct ip_vs_protocol *pp = pd->pp;
struct ip_vs_conn *cp = NULL; struct ip_vs_conn *cp = NULL;
struct ip_vs_iphdr iph; struct ip_vs_iphdr iph;
struct ip_vs_dest *dest; struct ip_vs_dest *dest;
...@@ -408,7 +409,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb, ...@@ -408,7 +409,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
* Do not schedule replies from local real server. * Do not schedule replies from local real server.
*/ */
if ((!skb->dev || skb->dev->flags & IFF_LOOPBACK) && if ((!skb->dev || skb->dev->flags & IFF_LOOPBACK) &&
(cp = pp->conn_in_get(svc->af, skb, pp, &iph, iph.len, 1))) { (cp = pp->conn_in_get(svc->af, skb, &iph, iph.len, 1))) {
IP_VS_DBG_PKT(12, svc->af, pp, skb, 0, IP_VS_DBG_PKT(12, svc->af, pp, skb, 0,
"Not scheduling reply for existing connection"); "Not scheduling reply for existing connection");
__ip_vs_conn_put(cp); __ip_vs_conn_put(cp);
...@@ -479,11 +480,12 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb, ...@@ -479,11 +480,12 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
* no destination is available for a new connection. * no destination is available for a new connection.
*/ */
int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
struct ip_vs_protocol *pp) struct ip_vs_proto_data *pd)
{ {
__be16 _ports[2], *pptr; __be16 _ports[2], *pptr;
struct ip_vs_iphdr iph; struct ip_vs_iphdr iph;
int unicast; int unicast;
ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph); ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
pptr = skb_header_pointer(skb, iph.len, sizeof(_ports), _ports); pptr = skb_header_pointer(skb, iph.len, sizeof(_ports), _ports);
...@@ -530,10 +532,10 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, ...@@ -530,10 +532,10 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
ip_vs_in_stats(cp, skb); ip_vs_in_stats(cp, skb);
/* set state */ /* set state */
cs = ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pp); cs = ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pd);
/* transmit the first SYN packet */ /* transmit the first SYN packet */
ret = cp->packet_xmit(skb, cp, pp); ret = cp->packet_xmit(skb, cp, pd->pp);
/* do not touch skb anymore */ /* do not touch skb anymore */
atomic_inc(&cp->in_pkts); atomic_inc(&cp->in_pkts);
...@@ -840,7 +842,7 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related, ...@@ -840,7 +842,7 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related,
ip_vs_fill_iphdr(AF_INET, cih, &ciph); ip_vs_fill_iphdr(AF_INET, cih, &ciph);
/* The embedded headers contain source and dest in reverse order */ /* The embedded headers contain source and dest in reverse order */
cp = pp->conn_out_get(AF_INET, skb, pp, &ciph, offset, 1); cp = pp->conn_out_get(AF_INET, skb, &ciph, offset, 1);
if (!cp) if (!cp)
return NF_ACCEPT; return NF_ACCEPT;
...@@ -917,7 +919,7 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related, ...@@ -917,7 +919,7 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related,
ip_vs_fill_iphdr(AF_INET6, cih, &ciph); ip_vs_fill_iphdr(AF_INET6, cih, &ciph);
/* The embedded headers contain source and dest in reverse order */ /* The embedded headers contain source and dest in reverse order */
cp = pp->conn_out_get(AF_INET6, skb, pp, &ciph, offset, 1); cp = pp->conn_out_get(AF_INET6, skb, &ciph, offset, 1);
if (!cp) if (!cp)
return NF_ACCEPT; return NF_ACCEPT;
...@@ -956,9 +958,11 @@ static inline int is_tcp_reset(const struct sk_buff *skb, int nh_len) ...@@ -956,9 +958,11 @@ static inline int is_tcp_reset(const struct sk_buff *skb, int nh_len)
* Used for NAT and local client. * Used for NAT and local client.
*/ */
static unsigned int static unsigned int
handle_response(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
struct ip_vs_conn *cp, int ihl) struct ip_vs_conn *cp, int ihl)
{ {
struct ip_vs_protocol *pp = pd->pp;
IP_VS_DBG_PKT(11, af, pp, skb, 0, "Outgoing packet"); IP_VS_DBG_PKT(11, af, pp, skb, 0, "Outgoing packet");
if (!skb_make_writable(skb, ihl)) if (!skb_make_writable(skb, ihl))
...@@ -1007,7 +1011,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -1007,7 +1011,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
IP_VS_DBG_PKT(10, af, pp, skb, 0, "After SNAT"); IP_VS_DBG_PKT(10, af, pp, skb, 0, "After SNAT");
ip_vs_out_stats(cp, skb); ip_vs_out_stats(cp, skb);
ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pp); ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pd);
skb->ipvs_property = 1; skb->ipvs_property = 1;
if (!(cp->flags & IP_VS_CONN_F_NFCT)) if (!(cp->flags & IP_VS_CONN_F_NFCT))
ip_vs_notrack(skb); ip_vs_notrack(skb);
...@@ -1034,6 +1038,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) ...@@ -1034,6 +1038,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
struct net *net = NULL; struct net *net = NULL;
struct ip_vs_iphdr iph; struct ip_vs_iphdr iph;
struct ip_vs_protocol *pp; struct ip_vs_protocol *pp;
struct ip_vs_proto_data *pd;
struct ip_vs_conn *cp; struct ip_vs_conn *cp;
EnterFunction(11); EnterFunction(11);
...@@ -1079,9 +1084,10 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) ...@@ -1079,9 +1084,10 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
} }
pp = ip_vs_proto_get(iph.protocol); pd = ip_vs_proto_data_get(net, iph.protocol);
if (unlikely(!pp)) if (unlikely(!pd))
return NF_ACCEPT; return NF_ACCEPT;
pp = pd->pp;
/* reassemble IP fragments */ /* reassemble IP fragments */
#ifdef CONFIG_IP_VS_IPV6 #ifdef CONFIG_IP_VS_IPV6
...@@ -1107,10 +1113,10 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) ...@@ -1107,10 +1113,10 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
/* /*
* Check if the packet belongs to an existing entry * Check if the packet belongs to an existing entry
*/ */
cp = pp->conn_out_get(af, skb, pp, &iph, iph.len, 0); cp = pp->conn_out_get(af, skb, &iph, iph.len, 0);
if (likely(cp)) if (likely(cp))
return handle_response(af, skb, pp, cp, iph.len); return handle_response(af, skb, pd, cp, iph.len);
if (sysctl_ip_vs_nat_icmp_send && if (sysctl_ip_vs_nat_icmp_send &&
(pp->protocol == IPPROTO_TCP || (pp->protocol == IPPROTO_TCP ||
pp->protocol == IPPROTO_UDP || pp->protocol == IPPROTO_UDP ||
...@@ -1236,12 +1242,14 @@ ip_vs_local_reply6(unsigned int hooknum, struct sk_buff *skb, ...@@ -1236,12 +1242,14 @@ ip_vs_local_reply6(unsigned int hooknum, struct sk_buff *skb,
static int static int
ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
{ {
struct net *net = NULL;
struct iphdr *iph; struct iphdr *iph;
struct icmphdr _icmph, *ic; struct icmphdr _icmph, *ic;
struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */ struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */
struct ip_vs_iphdr ciph; struct ip_vs_iphdr ciph;
struct ip_vs_conn *cp; struct ip_vs_conn *cp;
struct ip_vs_protocol *pp; struct ip_vs_protocol *pp;
struct ip_vs_proto_data *pd;
unsigned int offset, ihl, verdict; unsigned int offset, ihl, verdict;
union nf_inet_addr snet; union nf_inet_addr snet;
...@@ -1283,9 +1291,11 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) ...@@ -1283,9 +1291,11 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
if (cih == NULL) if (cih == NULL)
return NF_ACCEPT; /* The packet looks wrong, ignore */ return NF_ACCEPT; /* The packet looks wrong, ignore */
pp = ip_vs_proto_get(cih->protocol); net = skb_net(skb);
if (!pp) pd = ip_vs_proto_data_get(net, cih->protocol);
if (!pd)
return NF_ACCEPT; return NF_ACCEPT;
pp = pd->pp;
/* Is the embedded protocol header present? */ /* Is the embedded protocol header present? */
if (unlikely(cih->frag_off & htons(IP_OFFSET) && if (unlikely(cih->frag_off & htons(IP_OFFSET) &&
...@@ -1299,10 +1309,10 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) ...@@ -1299,10 +1309,10 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
ip_vs_fill_iphdr(AF_INET, cih, &ciph); ip_vs_fill_iphdr(AF_INET, cih, &ciph);
/* The embedded headers contain source and dest in reverse order */ /* The embedded headers contain source and dest in reverse order */
cp = pp->conn_in_get(AF_INET, skb, pp, &ciph, offset, 1); cp = pp->conn_in_get(AF_INET, skb, &ciph, offset, 1);
if (!cp) { if (!cp) {
/* The packet could also belong to a local client */ /* The packet could also belong to a local client */
cp = pp->conn_out_get(AF_INET, skb, pp, &ciph, offset, 1); cp = pp->conn_out_get(AF_INET, skb, &ciph, offset, 1);
if (cp) { if (cp) {
snet.ip = iph->saddr; snet.ip = iph->saddr;
return handle_response_icmp(AF_INET, skb, &snet, return handle_response_icmp(AF_INET, skb, &snet,
...@@ -1346,6 +1356,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) ...@@ -1346,6 +1356,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
static int static int
ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum) ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum)
{ {
struct net *net = NULL;
struct ipv6hdr *iph; struct ipv6hdr *iph;
struct icmp6hdr _icmph, *ic; struct icmp6hdr _icmph, *ic;
struct ipv6hdr _ciph, *cih; /* The ip header contained struct ipv6hdr _ciph, *cih; /* The ip header contained
...@@ -1353,6 +1364,7 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum) ...@@ -1353,6 +1364,7 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum)
struct ip_vs_iphdr ciph; struct ip_vs_iphdr ciph;
struct ip_vs_conn *cp; struct ip_vs_conn *cp;
struct ip_vs_protocol *pp; struct ip_vs_protocol *pp;
struct ip_vs_proto_data *pd;
unsigned int offset, verdict; unsigned int offset, verdict;
union nf_inet_addr snet; union nf_inet_addr snet;
struct rt6_info *rt; struct rt6_info *rt;
...@@ -1395,9 +1407,11 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum) ...@@ -1395,9 +1407,11 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum)
if (cih == NULL) if (cih == NULL)
return NF_ACCEPT; /* The packet looks wrong, ignore */ return NF_ACCEPT; /* The packet looks wrong, ignore */
pp = ip_vs_proto_get(cih->nexthdr); net = skb_net(skb);
if (!pp) pd = ip_vs_proto_data_get(net, cih->nexthdr);
if (!pd)
return NF_ACCEPT; return NF_ACCEPT;
pp = pd->pp;
/* Is the embedded protocol header present? */ /* Is the embedded protocol header present? */
/* TODO: we don't support fragmentation at the moment anyways */ /* TODO: we don't support fragmentation at the moment anyways */
...@@ -1411,10 +1425,10 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum) ...@@ -1411,10 +1425,10 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum)
ip_vs_fill_iphdr(AF_INET6, cih, &ciph); ip_vs_fill_iphdr(AF_INET6, cih, &ciph);
/* The embedded headers contain source and dest in reverse order */ /* The embedded headers contain source and dest in reverse order */
cp = pp->conn_in_get(AF_INET6, skb, pp, &ciph, offset, 1); cp = pp->conn_in_get(AF_INET6, skb, &ciph, offset, 1);
if (!cp) { if (!cp) {
/* The packet could also belong to a local client */ /* The packet could also belong to a local client */
cp = pp->conn_out_get(AF_INET6, skb, pp, &ciph, offset, 1); cp = pp->conn_out_get(AF_INET6, skb, &ciph, offset, 1);
if (cp) { if (cp) {
ipv6_addr_copy(&snet.in6, &iph->saddr); ipv6_addr_copy(&snet.in6, &iph->saddr);
return handle_response_icmp(AF_INET6, skb, &snet, return handle_response_icmp(AF_INET6, skb, &snet,
...@@ -1457,8 +1471,10 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum) ...@@ -1457,8 +1471,10 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum)
static unsigned int static unsigned int
ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
{ {
struct net *net = NULL;
struct ip_vs_iphdr iph; struct ip_vs_iphdr iph;
struct ip_vs_protocol *pp; struct ip_vs_protocol *pp;
struct ip_vs_proto_data *pd;
struct ip_vs_conn *cp; struct ip_vs_conn *cp;
int ret, restart, pkts; int ret, restart, pkts;
...@@ -1514,20 +1530,21 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) ...@@ -1514,20 +1530,21 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
} }
net = skb_net(skb);
/* Protocol supported? */ /* Protocol supported? */
pp = ip_vs_proto_get(iph.protocol); pd = ip_vs_proto_data_get(net, iph.protocol);
if (unlikely(!pp)) if (unlikely(!pd))
return NF_ACCEPT; return NF_ACCEPT;
pp = pd->pp;
/* /*
* Check if the packet belongs to an existing connection entry * Check if the packet belongs to an existing connection entry
*/ */
cp = pp->conn_in_get(af, skb, pp, &iph, iph.len, 0); cp = pp->conn_in_get(af, skb, &iph, iph.len, 0);
if (unlikely(!cp)) { if (unlikely(!cp)) {
int v; int v;
if (!pp->conn_schedule(af, skb, pp, &v, &cp)) if (!pp->conn_schedule(af, skb, pd, &v, &cp))
return v; return v;
} }
...@@ -1555,7 +1572,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) ...@@ -1555,7 +1572,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
} }
ip_vs_in_stats(cp, skb); ip_vs_in_stats(cp, skb);
restart = ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pp); restart = ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pd);
if (cp->packet_xmit) if (cp->packet_xmit)
ret = cp->packet_xmit(skb, cp, pp); ret = cp->packet_xmit(skb, cp, pp);
/* do not touch skb anymore */ /* do not touch skb anymore */
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <net/net_namespace.h> #include <net/net_namespace.h>
#include <linux/nsproxy.h>
#include <net/ip.h> #include <net/ip.h>
#ifdef CONFIG_IP_VS_IPV6 #ifdef CONFIG_IP_VS_IPV6
#include <net/ipv6.h> #include <net/ipv6.h>
...@@ -125,7 +126,7 @@ static int __ip_vs_addr_is_local_v6(const struct in6_addr *addr) ...@@ -125,7 +126,7 @@ static int __ip_vs_addr_is_local_v6(const struct in6_addr *addr)
* update_defense_level is called from keventd and from sysctl, * update_defense_level is called from keventd and from sysctl,
* so it needs to protect itself from softirqs * so it needs to protect itself from softirqs
*/ */
static void update_defense_level(void) static void update_defense_level(struct netns_ipvs *ipvs)
{ {
struct sysinfo i; struct sysinfo i;
static int old_secure_tcp = 0; static int old_secure_tcp = 0;
...@@ -239,7 +240,8 @@ static void update_defense_level(void) ...@@ -239,7 +240,8 @@ static void update_defense_level(void)
} }
old_secure_tcp = sysctl_ip_vs_secure_tcp; old_secure_tcp = sysctl_ip_vs_secure_tcp;
if (to_change >= 0) if (to_change >= 0)
ip_vs_protocol_timeout_change(sysctl_ip_vs_secure_tcp>1); ip_vs_protocol_timeout_change(ipvs,
sysctl_ip_vs_secure_tcp > 1);
spin_unlock(&ip_vs_securetcp_lock); spin_unlock(&ip_vs_securetcp_lock);
local_bh_enable(); local_bh_enable();
...@@ -255,7 +257,10 @@ static DECLARE_DELAYED_WORK(defense_work, defense_work_handler); ...@@ -255,7 +257,10 @@ static DECLARE_DELAYED_WORK(defense_work, defense_work_handler);
static void defense_work_handler(struct work_struct *work) static void defense_work_handler(struct work_struct *work)
{ {
update_defense_level(); struct net *net = &init_net;
struct netns_ipvs *ipvs = net_ipvs(net);
update_defense_level(ipvs);
if (atomic_read(&ip_vs_dropentry)) if (atomic_read(&ip_vs_dropentry))
ip_vs_random_dropentry(); ip_vs_random_dropentry();
...@@ -1502,6 +1507,7 @@ static int ...@@ -1502,6 +1507,7 @@ static int
proc_do_defense_mode(ctl_table *table, int write, proc_do_defense_mode(ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos) void __user *buffer, size_t *lenp, loff_t *ppos)
{ {
struct net *net = current->nsproxy->net_ns;
int *valp = table->data; int *valp = table->data;
int val = *valp; int val = *valp;
int rc; int rc;
...@@ -1512,7 +1518,7 @@ proc_do_defense_mode(ctl_table *table, int write, ...@@ -1512,7 +1518,7 @@ proc_do_defense_mode(ctl_table *table, int write,
/* Restore the correct value */ /* Restore the correct value */
*valp = val; *valp = val;
} else { } else {
update_defense_level(); update_defense_level(net_ipvs(net));
} }
} }
return rc; return rc;
...@@ -2033,8 +2039,10 @@ static const struct file_operations ip_vs_stats_fops = { ...@@ -2033,8 +2039,10 @@ static const struct file_operations ip_vs_stats_fops = {
/* /*
* Set timeout values for tcp tcpfin udp in the timeout_table. * Set timeout values for tcp tcpfin udp in the timeout_table.
*/ */
static int ip_vs_set_timeout(struct ip_vs_timeout_user *u) static int ip_vs_set_timeout(struct net *net, struct ip_vs_timeout_user *u)
{ {
struct ip_vs_proto_data *pd;
IP_VS_DBG(2, "Setting timeout tcp:%d tcpfin:%d udp:%d\n", IP_VS_DBG(2, "Setting timeout tcp:%d tcpfin:%d udp:%d\n",
u->tcp_timeout, u->tcp_timeout,
u->tcp_fin_timeout, u->tcp_fin_timeout,
...@@ -2042,19 +2050,22 @@ static int ip_vs_set_timeout(struct ip_vs_timeout_user *u) ...@@ -2042,19 +2050,22 @@ static int ip_vs_set_timeout(struct ip_vs_timeout_user *u)
#ifdef CONFIG_IP_VS_PROTO_TCP #ifdef CONFIG_IP_VS_PROTO_TCP
if (u->tcp_timeout) { if (u->tcp_timeout) {
ip_vs_protocol_tcp.timeout_table[IP_VS_TCP_S_ESTABLISHED] pd = ip_vs_proto_data_get(net, IPPROTO_TCP);
pd->timeout_table[IP_VS_TCP_S_ESTABLISHED]
= u->tcp_timeout * HZ; = u->tcp_timeout * HZ;
} }
if (u->tcp_fin_timeout) { if (u->tcp_fin_timeout) {
ip_vs_protocol_tcp.timeout_table[IP_VS_TCP_S_FIN_WAIT] pd = ip_vs_proto_data_get(net, IPPROTO_TCP);
pd->timeout_table[IP_VS_TCP_S_FIN_WAIT]
= u->tcp_fin_timeout * HZ; = u->tcp_fin_timeout * HZ;
} }
#endif #endif
#ifdef CONFIG_IP_VS_PROTO_UDP #ifdef CONFIG_IP_VS_PROTO_UDP
if (u->udp_timeout) { if (u->udp_timeout) {
ip_vs_protocol_udp.timeout_table[IP_VS_UDP_S_NORMAL] pd = ip_vs_proto_data_get(net, IPPROTO_UDP);
pd->timeout_table[IP_VS_UDP_S_NORMAL]
= u->udp_timeout * HZ; = u->udp_timeout * HZ;
} }
#endif #endif
...@@ -2158,7 +2169,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) ...@@ -2158,7 +2169,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
goto out_unlock; goto out_unlock;
} else if (cmd == IP_VS_SO_SET_TIMEOUT) { } else if (cmd == IP_VS_SO_SET_TIMEOUT) {
/* Set timeout values for (tcp tcpfin udp) */ /* Set timeout values for (tcp tcpfin udp) */
ret = ip_vs_set_timeout((struct ip_vs_timeout_user *)arg); ret = ip_vs_set_timeout(net, (struct ip_vs_timeout_user *)arg);
goto out_unlock; goto out_unlock;
} else if (cmd == IP_VS_SO_SET_STARTDAEMON) { } else if (cmd == IP_VS_SO_SET_STARTDAEMON) {
struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg; struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg;
...@@ -2370,17 +2381,19 @@ __ip_vs_get_dest_entries(struct net *net, const struct ip_vs_get_dests *get, ...@@ -2370,17 +2381,19 @@ __ip_vs_get_dest_entries(struct net *net, const struct ip_vs_get_dests *get,
} }
static inline void static inline void
__ip_vs_get_timeouts(struct ip_vs_timeout_user *u) __ip_vs_get_timeouts(struct net *net, struct ip_vs_timeout_user *u)
{ {
struct ip_vs_proto_data *pd;
#ifdef CONFIG_IP_VS_PROTO_TCP #ifdef CONFIG_IP_VS_PROTO_TCP
u->tcp_timeout = pd = ip_vs_proto_data_get(net, IPPROTO_TCP);
ip_vs_protocol_tcp.timeout_table[IP_VS_TCP_S_ESTABLISHED] / HZ; u->tcp_timeout = pd->timeout_table[IP_VS_TCP_S_ESTABLISHED] / HZ;
u->tcp_fin_timeout = u->tcp_fin_timeout = pd->timeout_table[IP_VS_TCP_S_FIN_WAIT] / HZ;
ip_vs_protocol_tcp.timeout_table[IP_VS_TCP_S_FIN_WAIT] / HZ;
#endif #endif
#ifdef CONFIG_IP_VS_PROTO_UDP #ifdef CONFIG_IP_VS_PROTO_UDP
pd = ip_vs_proto_data_get(net, IPPROTO_UDP);
u->udp_timeout = u->udp_timeout =
ip_vs_protocol_udp.timeout_table[IP_VS_UDP_S_NORMAL] / HZ; pd->timeout_table[IP_VS_UDP_S_NORMAL] / HZ;
#endif #endif
} }
...@@ -2521,7 +2534,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) ...@@ -2521,7 +2534,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
{ {
struct ip_vs_timeout_user t; struct ip_vs_timeout_user t;
__ip_vs_get_timeouts(&t); __ip_vs_get_timeouts(net, &t);
if (copy_to_user(user, &t, sizeof(t)) != 0) if (copy_to_user(user, &t, sizeof(t)) != 0)
ret = -EFAULT; ret = -EFAULT;
} }
...@@ -3092,11 +3105,11 @@ static int ip_vs_genl_del_daemon(struct nlattr **attrs) ...@@ -3092,11 +3105,11 @@ static int ip_vs_genl_del_daemon(struct nlattr **attrs)
return stop_sync_thread(nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE])); return stop_sync_thread(nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE]));
} }
static int ip_vs_genl_set_config(struct nlattr **attrs) static int ip_vs_genl_set_config(struct net *net, struct nlattr **attrs)
{ {
struct ip_vs_timeout_user t; struct ip_vs_timeout_user t;
__ip_vs_get_timeouts(&t); __ip_vs_get_timeouts(net, &t);
if (attrs[IPVS_CMD_ATTR_TIMEOUT_TCP]) if (attrs[IPVS_CMD_ATTR_TIMEOUT_TCP])
t.tcp_timeout = nla_get_u32(attrs[IPVS_CMD_ATTR_TIMEOUT_TCP]); t.tcp_timeout = nla_get_u32(attrs[IPVS_CMD_ATTR_TIMEOUT_TCP]);
...@@ -3108,7 +3121,7 @@ static int ip_vs_genl_set_config(struct nlattr **attrs) ...@@ -3108,7 +3121,7 @@ static int ip_vs_genl_set_config(struct nlattr **attrs)
if (attrs[IPVS_CMD_ATTR_TIMEOUT_UDP]) if (attrs[IPVS_CMD_ATTR_TIMEOUT_UDP])
t.udp_timeout = nla_get_u32(attrs[IPVS_CMD_ATTR_TIMEOUT_UDP]); t.udp_timeout = nla_get_u32(attrs[IPVS_CMD_ATTR_TIMEOUT_UDP]);
return ip_vs_set_timeout(&t); return ip_vs_set_timeout(net, &t);
} }
static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
...@@ -3129,7 +3142,7 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) ...@@ -3129,7 +3142,7 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
ret = ip_vs_flush(net); ret = ip_vs_flush(net);
goto out; goto out;
} else if (cmd == IPVS_CMD_SET_CONFIG) { } else if (cmd == IPVS_CMD_SET_CONFIG) {
ret = ip_vs_genl_set_config(info->attrs); ret = ip_vs_genl_set_config(net, info->attrs);
goto out; goto out;
} else if (cmd == IPVS_CMD_NEW_DAEMON || } else if (cmd == IPVS_CMD_NEW_DAEMON ||
cmd == IPVS_CMD_DEL_DAEMON) { cmd == IPVS_CMD_DEL_DAEMON) {
...@@ -3281,7 +3294,7 @@ static int ip_vs_genl_get_cmd(struct sk_buff *skb, struct genl_info *info) ...@@ -3281,7 +3294,7 @@ static int ip_vs_genl_get_cmd(struct sk_buff *skb, struct genl_info *info)
{ {
struct ip_vs_timeout_user t; struct ip_vs_timeout_user t;
__ip_vs_get_timeouts(&t); __ip_vs_get_timeouts(net, &t);
#ifdef CONFIG_IP_VS_PROTO_TCP #ifdef CONFIG_IP_VS_PROTO_TCP
NLA_PUT_U32(msg, IPVS_CMD_ATTR_TIMEOUT_TCP, t.tcp_timeout); NLA_PUT_U32(msg, IPVS_CMD_ATTR_TIMEOUT_TCP, t.tcp_timeout);
NLA_PUT_U32(msg, IPVS_CMD_ATTR_TIMEOUT_TCP_FIN, NLA_PUT_U32(msg, IPVS_CMD_ATTR_TIMEOUT_TCP_FIN,
......
...@@ -152,9 +152,8 @@ EXPORT_SYMBOL(ip_vs_proto_get); ...@@ -152,9 +152,8 @@ EXPORT_SYMBOL(ip_vs_proto_get);
* get ip_vs_protocol object data by netns and proto * get ip_vs_protocol object data by netns and proto
*/ */
struct ip_vs_proto_data * struct ip_vs_proto_data *
ip_vs_proto_data_get(struct net *net, unsigned short proto) __ipvs_proto_data_get(struct netns_ipvs *ipvs, unsigned short proto)
{ {
struct netns_ipvs *ipvs = net_ipvs(net);
struct ip_vs_proto_data *pd; struct ip_vs_proto_data *pd;
unsigned hash = IP_VS_PROTO_HASH(proto); unsigned hash = IP_VS_PROTO_HASH(proto);
...@@ -165,20 +164,28 @@ ip_vs_proto_data_get(struct net *net, unsigned short proto) ...@@ -165,20 +164,28 @@ ip_vs_proto_data_get(struct net *net, unsigned short proto)
return NULL; return NULL;
} }
struct ip_vs_proto_data *
ip_vs_proto_data_get(struct net *net, unsigned short proto)
{
struct netns_ipvs *ipvs = net_ipvs(net);
return __ipvs_proto_data_get(ipvs, proto);
}
EXPORT_SYMBOL(ip_vs_proto_data_get); EXPORT_SYMBOL(ip_vs_proto_data_get);
/* /*
* Propagate event for state change to all protocols * Propagate event for state change to all protocols
*/ */
void ip_vs_protocol_timeout_change(int flags) void ip_vs_protocol_timeout_change(struct netns_ipvs *ipvs, int flags)
{ {
struct ip_vs_protocol *pp; struct ip_vs_proto_data *pd;
int i; int i;
for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) { for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) {
for (pp = ip_vs_proto_table[i]; pp; pp = pp->next) { for (pd = ipvs->proto_data_table[i]; pd; pd = pd->next) {
if (pp->timeout_change) if (pd->pp->timeout_change)
pp->timeout_change(pp, flags); pd->pp->timeout_change(pd, flags);
} }
} }
} }
......
...@@ -55,7 +55,7 @@ ah_esp_conn_fill_param_proto(int af, const struct ip_vs_iphdr *iph, ...@@ -55,7 +55,7 @@ ah_esp_conn_fill_param_proto(int af, const struct ip_vs_iphdr *iph,
} }
static struct ip_vs_conn * static struct ip_vs_conn *
ah_esp_conn_in_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp, ah_esp_conn_in_get(int af, const struct sk_buff *skb,
const struct ip_vs_iphdr *iph, unsigned int proto_off, const struct ip_vs_iphdr *iph, unsigned int proto_off,
int inverse) int inverse)
{ {
...@@ -72,7 +72,7 @@ ah_esp_conn_in_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -72,7 +72,7 @@ ah_esp_conn_in_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp,
IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for outin packet " IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for outin packet "
"%s%s %s->%s\n", "%s%s %s->%s\n",
inverse ? "ICMP+" : "", inverse ? "ICMP+" : "",
pp->name, ip_vs_proto_get(iph->protocol)->name,
IP_VS_DBG_ADDR(af, &iph->saddr), IP_VS_DBG_ADDR(af, &iph->saddr),
IP_VS_DBG_ADDR(af, &iph->daddr)); IP_VS_DBG_ADDR(af, &iph->daddr));
} }
...@@ -83,7 +83,6 @@ ah_esp_conn_in_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -83,7 +83,6 @@ ah_esp_conn_in_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp,
static struct ip_vs_conn * static struct ip_vs_conn *
ah_esp_conn_out_get(int af, const struct sk_buff *skb, ah_esp_conn_out_get(int af, const struct sk_buff *skb,
struct ip_vs_protocol *pp,
const struct ip_vs_iphdr *iph, const struct ip_vs_iphdr *iph,
unsigned int proto_off, unsigned int proto_off,
int inverse) int inverse)
...@@ -97,7 +96,7 @@ ah_esp_conn_out_get(int af, const struct sk_buff *skb, ...@@ -97,7 +96,7 @@ ah_esp_conn_out_get(int af, const struct sk_buff *skb,
IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for inout packet " IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for inout packet "
"%s%s %s->%s\n", "%s%s %s->%s\n",
inverse ? "ICMP+" : "", inverse ? "ICMP+" : "",
pp->name, ip_vs_proto_get(iph->protocol)->name,
IP_VS_DBG_ADDR(af, &iph->saddr), IP_VS_DBG_ADDR(af, &iph->saddr),
IP_VS_DBG_ADDR(af, &iph->daddr)); IP_VS_DBG_ADDR(af, &iph->daddr));
} }
...@@ -107,7 +106,7 @@ ah_esp_conn_out_get(int af, const struct sk_buff *skb, ...@@ -107,7 +106,7 @@ ah_esp_conn_out_get(int af, const struct sk_buff *skb,
static int static int
ah_esp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, ah_esp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
int *verdict, struct ip_vs_conn **cpp) int *verdict, struct ip_vs_conn **cpp)
{ {
/* /*
...@@ -137,7 +136,6 @@ struct ip_vs_protocol ip_vs_protocol_ah = { ...@@ -137,7 +136,6 @@ struct ip_vs_protocol ip_vs_protocol_ah = {
.app_conn_bind = NULL, .app_conn_bind = NULL,
.debug_packet = ip_vs_tcpudp_debug_packet, .debug_packet = ip_vs_tcpudp_debug_packet,
.timeout_change = NULL, /* ISAKMP */ .timeout_change = NULL, /* ISAKMP */
.set_state_timeout = NULL,
}; };
#endif #endif
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include <net/ip_vs.h> #include <net/ip_vs.h>
static int static int
sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
int *verdict, struct ip_vs_conn **cpp) int *verdict, struct ip_vs_conn **cpp)
{ {
struct net *net; struct net *net;
...@@ -47,10 +47,10 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -47,10 +47,10 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
* Let the virtual server select a real server for the * Let the virtual server select a real server for the
* incoming connection, and create a connection entry. * incoming connection, and create a connection entry.
*/ */
*cpp = ip_vs_schedule(svc, skb, pp, &ignored); *cpp = ip_vs_schedule(svc, skb, pd, &ignored);
if (!*cpp && ignored <= 0) { if (!*cpp && ignored <= 0) {
if (!ignored) if (!ignored)
*verdict = ip_vs_leave(svc, skb, pp); *verdict = ip_vs_leave(svc, skb, pd);
else { else {
ip_vs_service_put(svc); ip_vs_service_put(svc);
*verdict = NF_DROP; *verdict = NF_DROP;
...@@ -907,14 +907,13 @@ static const char *sctp_state_name(int state) ...@@ -907,14 +907,13 @@ static const char *sctp_state_name(int state)
} }
static inline int static inline int
set_sctp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp, set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
int direction, const struct sk_buff *skb) int direction, const struct sk_buff *skb)
{ {
sctp_chunkhdr_t _sctpch, *sch; sctp_chunkhdr_t _sctpch, *sch;
unsigned char chunk_type; unsigned char chunk_type;
int event, next_state; int event, next_state;
int ihl; int ihl;
struct ip_vs_proto_data *pd;
#ifdef CONFIG_IP_VS_IPV6 #ifdef CONFIG_IP_VS_IPV6
ihl = cp->af == AF_INET ? ip_hdrlen(skb) : sizeof(struct ipv6hdr); ihl = cp->af == AF_INET ? ip_hdrlen(skb) : sizeof(struct ipv6hdr);
...@@ -966,7 +965,7 @@ set_sctp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp, ...@@ -966,7 +965,7 @@ set_sctp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp,
IP_VS_DBG_BUF(8, "%s %s %s:%d->" IP_VS_DBG_BUF(8, "%s %s %s:%d->"
"%s:%d state: %s->%s conn->refcnt:%d\n", "%s:%d state: %s->%s conn->refcnt:%d\n",
pp->name, pd->pp->name,
((direction == IP_VS_DIR_OUTPUT) ? ((direction == IP_VS_DIR_OUTPUT) ?
"output " : "input "), "output " : "input "),
IP_VS_DBG_ADDR(cp->af, &cp->daddr), IP_VS_DBG_ADDR(cp->af, &cp->daddr),
...@@ -990,7 +989,6 @@ set_sctp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp, ...@@ -990,7 +989,6 @@ set_sctp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp,
} }
} }
} }
pd = ip_vs_proto_data_get(&init_net, pp->protocol); /* tmp fix */
if (likely(pd)) if (likely(pd))
cp->timeout = pd->timeout_table[cp->state = next_state]; cp->timeout = pd->timeout_table[cp->state = next_state];
else /* What to do ? */ else /* What to do ? */
...@@ -1001,12 +999,12 @@ set_sctp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp, ...@@ -1001,12 +999,12 @@ set_sctp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp,
static int static int
sctp_state_transition(struct ip_vs_conn *cp, int direction, sctp_state_transition(struct ip_vs_conn *cp, int direction,
const struct sk_buff *skb, struct ip_vs_protocol *pp) const struct sk_buff *skb, struct ip_vs_proto_data *pd)
{ {
int ret = 0; int ret = 0;
spin_lock(&cp->lock); spin_lock(&cp->lock);
ret = set_sctp_state(pp, cp, direction, skb); ret = set_sctp_state(pd, cp, direction, skb);
spin_unlock(&cp->lock); spin_unlock(&cp->lock);
return ret; return ret;
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
#include <net/ip_vs.h> #include <net/ip_vs.h>
static int static int
tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
int *verdict, struct ip_vs_conn **cpp) int *verdict, struct ip_vs_conn **cpp)
{ {
struct net *net; struct net *net;
...@@ -68,10 +68,10 @@ tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -68,10 +68,10 @@ tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
* Let the virtual server select a real server for the * Let the virtual server select a real server for the
* incoming connection, and create a connection entry. * incoming connection, and create a connection entry.
*/ */
*cpp = ip_vs_schedule(svc, skb, pp, &ignored); *cpp = ip_vs_schedule(svc, skb, pd, &ignored);
if (!*cpp && ignored <= 0) { if (!*cpp && ignored <= 0) {
if (!ignored) if (!ignored)
*verdict = ip_vs_leave(svc, skb, pp); *verdict = ip_vs_leave(svc, skb, pd);
else { else {
ip_vs_service_put(svc); ip_vs_service_put(svc);
*verdict = NF_DROP; *verdict = NF_DROP;
...@@ -448,10 +448,7 @@ static struct tcp_states_t tcp_states_dos [] = { ...@@ -448,10 +448,7 @@ static struct tcp_states_t tcp_states_dos [] = {
/*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sCL }}, /*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sCL }},
}; };
static struct tcp_states_t *tcp_state_table = tcp_states; static void tcp_timeout_change(struct ip_vs_proto_data *pd, int flags)
static void tcp_timeout_change(struct ip_vs_protocol *pp, int flags)
{ {
int on = (flags & 1); /* secure_tcp */ int on = (flags & 1); /* secure_tcp */
...@@ -461,7 +458,7 @@ static void tcp_timeout_change(struct ip_vs_protocol *pp, int flags) ...@@ -461,7 +458,7 @@ static void tcp_timeout_change(struct ip_vs_protocol *pp, int flags)
** for most if not for all of the applications. Something ** for most if not for all of the applications. Something
** like "capabilities" (flags) for each object. ** like "capabilities" (flags) for each object.
*/ */
tcp_state_table = (on? tcp_states_dos : tcp_states); pd->tcp_state_table = (on ? tcp_states_dos : tcp_states);
} }
static inline int tcp_state_idx(struct tcphdr *th) static inline int tcp_state_idx(struct tcphdr *th)
...@@ -478,13 +475,12 @@ static inline int tcp_state_idx(struct tcphdr *th) ...@@ -478,13 +475,12 @@ static inline int tcp_state_idx(struct tcphdr *th)
} }
static inline void static inline void
set_tcp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp, set_tcp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
int direction, struct tcphdr *th) int direction, struct tcphdr *th)
{ {
int state_idx; int state_idx;
int new_state = IP_VS_TCP_S_CLOSE; int new_state = IP_VS_TCP_S_CLOSE;
int state_off = tcp_state_off[direction]; int state_off = tcp_state_off[direction];
struct ip_vs_proto_data *pd; /* Temp fix */
/* /*
* Update state offset to INPUT_ONLY if necessary * Update state offset to INPUT_ONLY if necessary
...@@ -502,7 +498,8 @@ set_tcp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp, ...@@ -502,7 +498,8 @@ set_tcp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp,
goto tcp_state_out; goto tcp_state_out;
} }
new_state = tcp_state_table[state_off+state_idx].next_state[cp->state]; new_state =
pd->tcp_state_table[state_off+state_idx].next_state[cp->state];
tcp_state_out: tcp_state_out:
if (new_state != cp->state) { if (new_state != cp->state) {
...@@ -510,7 +507,7 @@ set_tcp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp, ...@@ -510,7 +507,7 @@ set_tcp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp,
IP_VS_DBG_BUF(8, "%s %s [%c%c%c%c] %s:%d->" IP_VS_DBG_BUF(8, "%s %s [%c%c%c%c] %s:%d->"
"%s:%d state: %s->%s conn->refcnt:%d\n", "%s:%d state: %s->%s conn->refcnt:%d\n",
pp->name, pd->pp->name,
((state_off == TCP_DIR_OUTPUT) ? ((state_off == TCP_DIR_OUTPUT) ?
"output " : "input "), "output " : "input "),
th->syn ? 'S' : '.', th->syn ? 'S' : '.',
...@@ -540,7 +537,6 @@ set_tcp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp, ...@@ -540,7 +537,6 @@ set_tcp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp,
} }
} }
pd = ip_vs_proto_data_get(&init_net, pp->protocol);
if (likely(pd)) if (likely(pd))
cp->timeout = pd->timeout_table[cp->state = new_state]; cp->timeout = pd->timeout_table[cp->state = new_state];
else /* What to do ? */ else /* What to do ? */
...@@ -553,7 +549,7 @@ set_tcp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp, ...@@ -553,7 +549,7 @@ set_tcp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp,
static int static int
tcp_state_transition(struct ip_vs_conn *cp, int direction, tcp_state_transition(struct ip_vs_conn *cp, int direction,
const struct sk_buff *skb, const struct sk_buff *skb,
struct ip_vs_protocol *pp) struct ip_vs_proto_data *pd)
{ {
struct tcphdr _tcph, *th; struct tcphdr _tcph, *th;
...@@ -568,7 +564,7 @@ tcp_state_transition(struct ip_vs_conn *cp, int direction, ...@@ -568,7 +564,7 @@ tcp_state_transition(struct ip_vs_conn *cp, int direction,
return 0; return 0;
spin_lock(&cp->lock); spin_lock(&cp->lock);
set_tcp_state(pp, cp, direction, th); set_tcp_state(pd, cp, direction, th);
spin_unlock(&cp->lock); spin_unlock(&cp->lock);
return 1; return 1;
...@@ -691,6 +687,7 @@ static void __ip_vs_tcp_init(struct net *net, struct ip_vs_proto_data *pd) ...@@ -691,6 +687,7 @@ static void __ip_vs_tcp_init(struct net *net, struct ip_vs_proto_data *pd)
spin_lock_init(&ipvs->tcp_app_lock); spin_lock_init(&ipvs->tcp_app_lock);
pd->timeout_table = ip_vs_create_timeout_table((int *)tcp_timeouts, pd->timeout_table = ip_vs_create_timeout_table((int *)tcp_timeouts,
sizeof(tcp_timeouts)); sizeof(tcp_timeouts));
pd->tcp_state_table = tcp_states;
} }
static void __ip_vs_tcp_exit(struct net *net, struct ip_vs_proto_data *pd) static void __ip_vs_tcp_exit(struct net *net, struct ip_vs_proto_data *pd)
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
#include <net/ip6_checksum.h> #include <net/ip6_checksum.h>
static int static int
udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
int *verdict, struct ip_vs_conn **cpp) int *verdict, struct ip_vs_conn **cpp)
{ {
struct net *net; struct net *net;
...@@ -64,10 +64,10 @@ udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -64,10 +64,10 @@ udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
* Let the virtual server select a real server for the * Let the virtual server select a real server for the
* incoming connection, and create a connection entry. * incoming connection, and create a connection entry.
*/ */
*cpp = ip_vs_schedule(svc, skb, pp, &ignored); *cpp = ip_vs_schedule(svc, skb, pd, &ignored);
if (!*cpp && ignored <= 0) { if (!*cpp && ignored <= 0) {
if (!ignored) if (!ignored)
*verdict = ip_vs_leave(svc, skb, pp); *verdict = ip_vs_leave(svc, skb, pd);
else { else {
ip_vs_service_put(svc); ip_vs_service_put(svc);
*verdict = NF_DROP; *verdict = NF_DROP;
...@@ -457,11 +457,8 @@ static const char * udp_state_name(int state) ...@@ -457,11 +457,8 @@ static const char * udp_state_name(int state)
static int static int
udp_state_transition(struct ip_vs_conn *cp, int direction, udp_state_transition(struct ip_vs_conn *cp, int direction,
const struct sk_buff *skb, const struct sk_buff *skb,
struct ip_vs_protocol *pp) struct ip_vs_proto_data *pd)
{ {
struct ip_vs_proto_data *pd; /* Temp fix, pp will be replaced by pd */
pd = ip_vs_proto_data_get(&init_net, IPPROTO_UDP);
if (unlikely(!pd)) { if (unlikely(!pd)) {
pr_err("UDP no ns data\n"); pr_err("UDP no ns data\n");
return 0; return 0;
......
...@@ -85,7 +85,7 @@ ipvs_mt(const struct sk_buff *skb, struct xt_action_param *par) ...@@ -85,7 +85,7 @@ ipvs_mt(const struct sk_buff *skb, struct xt_action_param *par)
/* /*
* Check if the packet belongs to an existing entry * Check if the packet belongs to an existing entry
*/ */
cp = pp->conn_out_get(family, skb, pp, &iph, iph.len, 1 /* inverse */); cp = pp->conn_out_get(family, skb, &iph, iph.len, 1 /* inverse */);
if (unlikely(cp == NULL)) { if (unlikely(cp == NULL)) {
match = false; match = false;
goto out; goto out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment