aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Horman <horms@verge.net.au>2010-08-22 08:37:52 -0400
committerSimon Horman <horms@verge.net.au>2010-10-04 09:45:24 -0400
commitf11017ec2d1859c661f4e2b12c4a8d250e1f47cf (patch)
tree07278dbced3c8c61b9e6bbe9c3d502c65b127f24
parent5b57a98c1f0d78a4c238d83c4ac70de3bd237b2f (diff)
IPVS: Add struct ip_vs_conn_param
Signed-off-by: Simon Horman <horms@verge.net.au> Acked-by: Julian Anastasov <ja@ssi.bg>
-rw-r--r--include/net/ip_vs.h44
-rw-r--r--net/netfilter/ipvs/ip_vs_conn.c171
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c64
-rw-r--r--net/netfilter/ipvs/ip_vs_ftp.c43
-rw-r--r--net/netfilter/ipvs/ip_vs_nfct.c12
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_ah_esp.c47
-rw-r--r--net/netfilter/ipvs/ip_vs_sync.c33
7 files changed, 211 insertions, 203 deletions
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 3915a4f4cd30..d4da774eca75 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -357,6 +357,15 @@ struct ip_vs_protocol {
357 357
358extern struct ip_vs_protocol * ip_vs_proto_get(unsigned short proto); 358extern struct ip_vs_protocol * ip_vs_proto_get(unsigned short proto);
359 359
360struct ip_vs_conn_param {
361 const union nf_inet_addr *caddr;
362 const union nf_inet_addr *vaddr;
363 __be16 cport;
364 __be16 vport;
365 __u16 protocol;
366 u16 af;
367};
368
360/* 369/*
361 * IP_VS structure allocated for each dynamically scheduled connection 370 * IP_VS structure allocated for each dynamically scheduled connection
362 */ 371 */
@@ -626,13 +635,23 @@ enum {
626 IP_VS_DIR_LAST, 635 IP_VS_DIR_LAST,
627}; 636};
628 637
629extern struct ip_vs_conn *ip_vs_conn_in_get 638static inline void ip_vs_conn_fill_param(int af, int protocol,
630(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port, 639 const union nf_inet_addr *caddr,
631 const union nf_inet_addr *d_addr, __be16 d_port); 640 __be16 cport,
641 const union nf_inet_addr *vaddr,
642 __be16 vport,
643 struct ip_vs_conn_param *p)
644{
645 p->af = af;
646 p->protocol = protocol;
647 p->caddr = caddr;
648 p->cport = cport;
649 p->vaddr = vaddr;
650 p->vport = vport;
651}
632 652
633extern struct ip_vs_conn *ip_vs_ct_in_get 653struct ip_vs_conn *ip_vs_conn_in_get(const struct ip_vs_conn_param *p);
634(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port, 654struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p);
635 const union nf_inet_addr *d_addr, __be16 d_port);
636 655
637struct ip_vs_conn * ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb, 656struct ip_vs_conn * ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,
638 struct ip_vs_protocol *pp, 657 struct ip_vs_protocol *pp,
@@ -640,9 +659,7 @@ struct ip_vs_conn * ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,
640 unsigned int proto_off, 659 unsigned int proto_off,
641 int inverse); 660 int inverse);
642 661
643extern struct ip_vs_conn *ip_vs_conn_out_get 662struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p);
644(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
645 const union nf_inet_addr *d_addr, __be16 d_port);
646 663
647struct ip_vs_conn * ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb, 664struct ip_vs_conn * ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb,
648 struct ip_vs_protocol *pp, 665 struct ip_vs_protocol *pp,
@@ -658,11 +675,10 @@ static inline void __ip_vs_conn_put(struct ip_vs_conn *cp)
658extern void ip_vs_conn_put(struct ip_vs_conn *cp); 675extern void ip_vs_conn_put(struct ip_vs_conn *cp);
659extern void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport); 676extern void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport);
660 677
661extern struct ip_vs_conn * 678struct ip_vs_conn *ip_vs_conn_new(const struct ip_vs_conn_param *p,
662ip_vs_conn_new(int af, int proto, const union nf_inet_addr *caddr, __be16 cport, 679 const union nf_inet_addr *daddr,
663 const union nf_inet_addr *vaddr, __be16 vport, 680 __be16 dport, unsigned flags,
664 const union nf_inet_addr *daddr, __be16 dport, unsigned flags, 681 struct ip_vs_dest *dest);
665 struct ip_vs_dest *dest);
666extern void ip_vs_conn_expire_now(struct ip_vs_conn *cp); 682extern void ip_vs_conn_expire_now(struct ip_vs_conn *cp);
667 683
668extern const char * ip_vs_state_name(__u16 proto, int state); 684extern const char * ip_vs_state_name(__u16 proto, int state);
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index a970d9691496..deeb906a797b 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -218,27 +218,26 @@ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp)
218/* 218/*
219 * Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab. 219 * Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab.
220 * Called for pkts coming from OUTside-to-INside. 220 * Called for pkts coming from OUTside-to-INside.
221 * s_addr, s_port: pkt source address (foreign host) 221 * p->caddr, p->cport: pkt source address (foreign host)
222 * d_addr, d_port: pkt dest address (load balancer) 222 * p->vaddr, p->vport: pkt dest address (load balancer)
223 */ 223 */
224static inline struct ip_vs_conn *__ip_vs_conn_in_get 224static inline struct ip_vs_conn *
225(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port, 225__ip_vs_conn_in_get(const struct ip_vs_conn_param *p)
226 const union nf_inet_addr *d_addr, __be16 d_port)
227{ 226{
228 unsigned hash; 227 unsigned hash;
229 struct ip_vs_conn *cp; 228 struct ip_vs_conn *cp;
230 229
231 hash = ip_vs_conn_hashkey(af, protocol, s_addr, s_port); 230 hash = ip_vs_conn_hashkey(p->af, p->protocol, p->caddr, p->cport);
232 231
233 ct_read_lock(hash); 232 ct_read_lock(hash);
234 233
235 list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) { 234 list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
236 if (cp->af == af && 235 if (cp->af == p->af &&
237 ip_vs_addr_equal(af, s_addr, &cp->caddr) && 236 ip_vs_addr_equal(p->af, p->caddr, &cp->caddr) &&
238 ip_vs_addr_equal(af, d_addr, &cp->vaddr) && 237 ip_vs_addr_equal(p->af, p->vaddr, &cp->vaddr) &&
239 s_port == cp->cport && d_port == cp->vport && 238 p->cport == cp->cport && p->vport == cp->vport &&
240 ((!s_port) ^ (!(cp->flags & IP_VS_CONN_F_NO_CPORT))) && 239 ((!p->cport) ^ (!(cp->flags & IP_VS_CONN_F_NO_CPORT))) &&
241 protocol == cp->protocol) { 240 p->protocol == cp->protocol) {
242 /* HIT */ 241 /* HIT */
243 atomic_inc(&cp->refcnt); 242 atomic_inc(&cp->refcnt);
244 ct_read_unlock(hash); 243 ct_read_unlock(hash);
@@ -251,71 +250,82 @@ static inline struct ip_vs_conn *__ip_vs_conn_in_get
251 return NULL; 250 return NULL;
252} 251}
253 252
254struct ip_vs_conn *ip_vs_conn_in_get 253struct ip_vs_conn *ip_vs_conn_in_get(const struct ip_vs_conn_param *p)
255(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
256 const union nf_inet_addr *d_addr, __be16 d_port)
257{ 254{
258 struct ip_vs_conn *cp; 255 struct ip_vs_conn *cp;
259 256
260 cp = __ip_vs_conn_in_get(af, protocol, s_addr, s_port, d_addr, d_port); 257 cp = __ip_vs_conn_in_get(p);
261 if (!cp && atomic_read(&ip_vs_conn_no_cport_cnt)) 258 if (!cp && atomic_read(&ip_vs_conn_no_cport_cnt)) {
262 cp = __ip_vs_conn_in_get(af, protocol, s_addr, 0, d_addr, 259 struct ip_vs_conn_param cport_zero_p = *p;
263 d_port); 260 cport_zero_p.cport = 0;
261 cp = __ip_vs_conn_in_get(&cport_zero_p);
262 }
264 263
265 IP_VS_DBG_BUF(9, "lookup/in %s %s:%d->%s:%d %s\n", 264 IP_VS_DBG_BUF(9, "lookup/in %s %s:%d->%s:%d %s\n",
266 ip_vs_proto_name(protocol), 265 ip_vs_proto_name(p->protocol),
267 IP_VS_DBG_ADDR(af, s_addr), ntohs(s_port), 266 IP_VS_DBG_ADDR(p->af, p->caddr), ntohs(p->cport),
268 IP_VS_DBG_ADDR(af, d_addr), ntohs(d_port), 267 IP_VS_DBG_ADDR(p->af, p->vaddr), ntohs(p->vport),
269 cp ? "hit" : "not hit"); 268 cp ? "hit" : "not hit");
270 269
271 return cp; 270 return cp;
272} 271}
273 272
273static int
274ip_vs_conn_fill_param_proto(int af, const struct sk_buff *skb,
275 const struct ip_vs_iphdr *iph,
276 unsigned int proto_off, int inverse,
277 struct ip_vs_conn_param *p)
278{
279 __be16 _ports[2], *pptr;
280
281 pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
282 if (pptr == NULL)
283 return 1;
284
285 if (likely(!inverse))
286 ip_vs_conn_fill_param(af, iph->protocol, &iph->saddr, pptr[0],
287 &iph->daddr, pptr[1], p);
288 else
289 ip_vs_conn_fill_param(af, iph->protocol, &iph->daddr, pptr[1],
290 &iph->saddr, pptr[0], p);
291 return 0;
292}
293
274struct ip_vs_conn * 294struct ip_vs_conn *
275ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb, 295ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,
276 struct ip_vs_protocol *pp, 296 struct ip_vs_protocol *pp,
277 const struct ip_vs_iphdr *iph, 297 const struct ip_vs_iphdr *iph,
278 unsigned int proto_off, int inverse) 298 unsigned int proto_off, int inverse)
279{ 299{
280 __be16 _ports[2], *pptr; 300 struct ip_vs_conn_param p;
281 301
282 pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports); 302 if (ip_vs_conn_fill_param_proto(af, skb, iph, proto_off, inverse, &p))
283 if (pptr == NULL)
284 return NULL; 303 return NULL;
285 304
286 if (likely(!inverse)) 305 return ip_vs_conn_in_get(&p);
287 return ip_vs_conn_in_get(af, iph->protocol,
288 &iph->saddr, pptr[0],
289 &iph->daddr, pptr[1]);
290 else
291 return ip_vs_conn_in_get(af, iph->protocol,
292 &iph->daddr, pptr[1],
293 &iph->saddr, pptr[0]);
294} 306}
295EXPORT_SYMBOL_GPL(ip_vs_conn_in_get_proto); 307EXPORT_SYMBOL_GPL(ip_vs_conn_in_get_proto);
296 308
297/* Get reference to connection template */ 309/* Get reference to connection template */
298struct ip_vs_conn *ip_vs_ct_in_get 310struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p)
299(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
300 const union nf_inet_addr *d_addr, __be16 d_port)
301{ 311{
302 unsigned hash; 312 unsigned hash;
303 struct ip_vs_conn *cp; 313 struct ip_vs_conn *cp;
304 314
305 hash = ip_vs_conn_hashkey(af, protocol, s_addr, s_port); 315 hash = ip_vs_conn_hashkey(p->af, p->protocol, p->caddr, p->cport);
306 316
307 ct_read_lock(hash); 317 ct_read_lock(hash);
308 318
309 list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) { 319 list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
310 if (cp->af == af && 320 if (cp->af == p->af &&
311 ip_vs_addr_equal(af, s_addr, &cp->caddr) && 321 ip_vs_addr_equal(p->af, p->caddr, &cp->caddr) &&
312 /* protocol should only be IPPROTO_IP if 322 /* protocol should only be IPPROTO_IP if
313 * d_addr is a fwmark */ 323 * p->vaddr is a fwmark */
314 ip_vs_addr_equal(protocol == IPPROTO_IP ? AF_UNSPEC : af, 324 ip_vs_addr_equal(p->protocol == IPPROTO_IP ? AF_UNSPEC :
315 d_addr, &cp->vaddr) && 325 p->af, p->vaddr, &cp->vaddr) &&
316 s_port == cp->cport && d_port == cp->vport && 326 p->cport == cp->cport && p->vport == cp->vport &&
317 cp->flags & IP_VS_CONN_F_TEMPLATE && 327 cp->flags & IP_VS_CONN_F_TEMPLATE &&
318 protocol == cp->protocol) { 328 p->protocol == cp->protocol) {
319 /* HIT */ 329 /* HIT */
320 atomic_inc(&cp->refcnt); 330 atomic_inc(&cp->refcnt);
321 goto out; 331 goto out;
@@ -327,23 +337,19 @@ struct ip_vs_conn *ip_vs_ct_in_get
327 ct_read_unlock(hash); 337 ct_read_unlock(hash);
328 338
329 IP_VS_DBG_BUF(9, "template lookup/in %s %s:%d->%s:%d %s\n", 339 IP_VS_DBG_BUF(9, "template lookup/in %s %s:%d->%s:%d %s\n",
330 ip_vs_proto_name(protocol), 340 ip_vs_proto_name(p->protocol),
331 IP_VS_DBG_ADDR(af, s_addr), ntohs(s_port), 341 IP_VS_DBG_ADDR(p->af, p->caddr), ntohs(p->cport),
332 IP_VS_DBG_ADDR(af, d_addr), ntohs(d_port), 342 IP_VS_DBG_ADDR(p->af, p->vaddr), ntohs(p->vport),
333 cp ? "hit" : "not hit"); 343 cp ? "hit" : "not hit");
334 344
335 return cp; 345 return cp;
336} 346}
337 347
338/* 348/* Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab.
339 * Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab. 349 * Called for pkts coming from inside-to-OUTside.
340 * Called for pkts coming from inside-to-OUTside. 350 * p->caddr, p->cport: pkt source address (inside host)
341 * s_addr, s_port: pkt source address (inside host) 351 * p->vaddr, p->vport: pkt dest address (foreign host) */
342 * d_addr, d_port: pkt dest address (foreign host) 352struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p)
343 */
344struct ip_vs_conn *ip_vs_conn_out_get
345(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
346 const union nf_inet_addr *d_addr, __be16 d_port)
347{ 353{
348 unsigned hash; 354 unsigned hash;
349 struct ip_vs_conn *cp, *ret=NULL; 355 struct ip_vs_conn *cp, *ret=NULL;
@@ -351,16 +357,16 @@ struct ip_vs_conn *ip_vs_conn_out_get
351 /* 357 /*
352 * Check for "full" addressed entries 358 * Check for "full" addressed entries
353 */ 359 */
354 hash = ip_vs_conn_hashkey(af, protocol, d_addr, d_port); 360 hash = ip_vs_conn_hashkey(p->af, p->protocol, p->vaddr, p->vport);
355 361
356 ct_read_lock(hash); 362 ct_read_lock(hash);
357 363
358 list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) { 364 list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
359 if (cp->af == af && 365 if (cp->af == p->af &&
360 ip_vs_addr_equal(af, d_addr, &cp->caddr) && 366 ip_vs_addr_equal(p->af, p->vaddr, &cp->caddr) &&
361 ip_vs_addr_equal(af, s_addr, &cp->daddr) && 367 ip_vs_addr_equal(p->af, p->caddr, &cp->daddr) &&
362 d_port == cp->cport && s_port == cp->dport && 368 p->vport == cp->cport && p->cport == cp->dport &&
363 protocol == cp->protocol) { 369 p->protocol == cp->protocol) {
364 /* HIT */ 370 /* HIT */
365 atomic_inc(&cp->refcnt); 371 atomic_inc(&cp->refcnt);
366 ret = cp; 372 ret = cp;
@@ -371,9 +377,9 @@ struct ip_vs_conn *ip_vs_conn_out_get
371 ct_read_unlock(hash); 377 ct_read_unlock(hash);
372 378
373 IP_VS_DBG_BUF(9, "lookup/out %s %s:%d->%s:%d %s\n", 379 IP_VS_DBG_BUF(9, "lookup/out %s %s:%d->%s:%d %s\n",
374 ip_vs_proto_name(protocol), 380 ip_vs_proto_name(p->protocol),
375 IP_VS_DBG_ADDR(af, s_addr), ntohs(s_port), 381 IP_VS_DBG_ADDR(p->af, p->caddr), ntohs(p->cport),
376 IP_VS_DBG_ADDR(af, d_addr), ntohs(d_port), 382 IP_VS_DBG_ADDR(p->af, p->vaddr), ntohs(p->vport),
377 ret ? "hit" : "not hit"); 383 ret ? "hit" : "not hit");
378 384
379 return ret; 385 return ret;
@@ -385,20 +391,12 @@ ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb,
385 const struct ip_vs_iphdr *iph, 391 const struct ip_vs_iphdr *iph,
386 unsigned int proto_off, int inverse) 392 unsigned int proto_off, int inverse)
387{ 393{
388 __be16 _ports[2], *pptr; 394 struct ip_vs_conn_param p;
389 395
390 pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports); 396 if (ip_vs_conn_fill_param_proto(af, skb, iph, proto_off, inverse, &p))
391 if (pptr == NULL)
392 return NULL; 397 return NULL;
393 398
394 if (likely(!inverse)) 399 return ip_vs_conn_out_get(&p);
395 return ip_vs_conn_out_get(af, iph->protocol,
396 &iph->saddr, pptr[0],
397 &iph->daddr, pptr[1]);
398 else
399 return ip_vs_conn_out_get(af, iph->protocol,
400 &iph->daddr, pptr[1],
401 &iph->saddr, pptr[0]);
402} 400}
403EXPORT_SYMBOL_GPL(ip_vs_conn_out_get_proto); 401EXPORT_SYMBOL_GPL(ip_vs_conn_out_get_proto);
404 402
@@ -758,13 +756,12 @@ void ip_vs_conn_expire_now(struct ip_vs_conn *cp)
758 * Create a new connection entry and hash it into the ip_vs_conn_tab 756 * Create a new connection entry and hash it into the ip_vs_conn_tab
759 */ 757 */
760struct ip_vs_conn * 758struct ip_vs_conn *
761ip_vs_conn_new(int af, int proto, const union nf_inet_addr *caddr, __be16 cport, 759ip_vs_conn_new(const struct ip_vs_conn_param *p,
762 const union nf_inet_addr *vaddr, __be16 vport,
763 const union nf_inet_addr *daddr, __be16 dport, unsigned flags, 760 const union nf_inet_addr *daddr, __be16 dport, unsigned flags,
764 struct ip_vs_dest *dest) 761 struct ip_vs_dest *dest)
765{ 762{
766 struct ip_vs_conn *cp; 763 struct ip_vs_conn *cp;
767 struct ip_vs_protocol *pp = ip_vs_proto_get(proto); 764 struct ip_vs_protocol *pp = ip_vs_proto_get(p->protocol);
768 765
769 cp = kmem_cache_zalloc(ip_vs_conn_cachep, GFP_ATOMIC); 766 cp = kmem_cache_zalloc(ip_vs_conn_cachep, GFP_ATOMIC);
770 if (cp == NULL) { 767 if (cp == NULL) {
@@ -774,14 +771,14 @@ ip_vs_conn_new(int af, int proto, const union nf_inet_addr *caddr, __be16 cport,
774 771
775 INIT_LIST_HEAD(&cp->c_list); 772 INIT_LIST_HEAD(&cp->c_list);
776 setup_timer(&cp->timer, ip_vs_conn_expire, (unsigned long)cp); 773 setup_timer(&cp->timer, ip_vs_conn_expire, (unsigned long)cp);
777 cp->af = af; 774 cp->af = p->af;
778 cp->protocol = proto; 775 cp->protocol = p->protocol;
779 ip_vs_addr_copy(af, &cp->caddr, caddr); 776 ip_vs_addr_copy(p->af, &cp->caddr, p->caddr);
780 cp->cport = cport; 777 cp->cport = p->cport;
781 ip_vs_addr_copy(af, &cp->vaddr, vaddr); 778 ip_vs_addr_copy(p->af, &cp->vaddr, p->vaddr);
782 cp->vport = vport; 779 cp->vport = p->vport;
783 /* proto should only be IPPROTO_IP if d_addr is a fwmark */ 780 /* proto should only be IPPROTO_IP if d_addr is a fwmark */
784 ip_vs_addr_copy(proto == IPPROTO_IP ? AF_UNSPEC : af, 781 ip_vs_addr_copy(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af,
785 &cp->daddr, daddr); 782 &cp->daddr, daddr);
786 cp->dport = dport; 783 cp->dport = dport;
787 cp->flags = flags; 784 cp->flags = flags;
@@ -810,7 +807,7 @@ ip_vs_conn_new(int af, int proto, const union nf_inet_addr *caddr, __be16 cport,
810 807
811 /* Bind its packet transmitter */ 808 /* Bind its packet transmitter */
812#ifdef CONFIG_IP_VS_IPV6 809#ifdef CONFIG_IP_VS_IPV6
813 if (af == AF_INET6) 810 if (p->af == AF_INET6)
814 ip_vs_bind_xmit_v6(cp); 811 ip_vs_bind_xmit_v6(cp);
815 else 812 else
816#endif 813#endif
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 70a5cacf86d5..87602a62458e 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -193,14 +193,11 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
193 struct ip_vs_iphdr iph; 193 struct ip_vs_iphdr iph;
194 struct ip_vs_dest *dest; 194 struct ip_vs_dest *dest;
195 struct ip_vs_conn *ct; 195 struct ip_vs_conn *ct;
196 int protocol = iph.protocol;
197 __be16 dport = 0; /* destination port to forward */ 196 __be16 dport = 0; /* destination port to forward */
198 __be16 vport = 0; /* virtual service port */
199 unsigned int flags; 197 unsigned int flags;
198 struct ip_vs_conn_param param;
200 union nf_inet_addr snet; /* source network of the client, 199 union nf_inet_addr snet; /* source network of the client,
201 after masking */ 200 after masking */
202 const union nf_inet_addr fwmark = { .ip = htonl(svc->fwmark) };
203 const union nf_inet_addr *vaddr = &iph.daddr;
204 201
205 ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph); 202 ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
206 203
@@ -232,6 +229,11 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
232 * is created for other persistent services. 229 * is created for other persistent services.
233 */ 230 */
234 { 231 {
232 int protocol = iph.protocol;
233 const union nf_inet_addr *vaddr = &iph.daddr;
234 const union nf_inet_addr fwmark = { .ip = htonl(svc->fwmark) };
235 __be16 vport = 0;
236
235 if (ports[1] == svc->port) { 237 if (ports[1] == svc->port) {
236 /* non-FTP template: 238 /* non-FTP template:
237 * <protocol, caddr, 0, vaddr, vport, daddr, dport> 239 * <protocol, caddr, 0, vaddr, vport, daddr, dport>
@@ -253,11 +255,12 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
253 vaddr = &fwmark; 255 vaddr = &fwmark;
254 } 256 }
255 } 257 }
258 ip_vs_conn_fill_param(svc->af, protocol, &snet, 0,
259 vaddr, vport, &param);
256 } 260 }
257 261
258 /* Check if a template already exists */ 262 /* Check if a template already exists */
259 ct = ip_vs_ct_in_get(svc->af, protocol, &snet, 0, vaddr, vport); 263 ct = ip_vs_ct_in_get(&param);
260
261 if (!ct || !ip_vs_check_template(ct)) { 264 if (!ct || !ip_vs_check_template(ct)) {
262 /* No template found or the dest of the connection 265 /* No template found or the dest of the connection
263 * template is not available. 266 * template is not available.
@@ -272,8 +275,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
272 dport = dest->port; 275 dport = dest->port;
273 276
274 /* Create a template */ 277 /* Create a template */
275 ct = ip_vs_conn_new(svc->af, protocol, &snet, 0,vaddr, vport, 278 ct = ip_vs_conn_new(&param, &dest->addr, dport,
276 &dest->addr, dport,
277 IP_VS_CONN_F_TEMPLATE, dest); 279 IP_VS_CONN_F_TEMPLATE, dest);
278 if (ct == NULL) 280 if (ct == NULL)
279 return NULL; 281 return NULL;
@@ -294,12 +296,9 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
294 /* 296 /*
295 * Create a new connection according to the template 297 * Create a new connection according to the template
296 */ 298 */
297 cp = ip_vs_conn_new(svc->af, iph.protocol, 299 ip_vs_conn_fill_param(svc->af, iph.protocol, &iph.saddr, ports[0],
298 &iph.saddr, ports[0], 300 &iph.daddr, ports[1], &param);
299 &iph.daddr, ports[1], 301 cp = ip_vs_conn_new(&param, &dest->addr, dport, flags, dest);
300 &dest->addr, dport,
301 flags,
302 dest);
303 if (cp == NULL) { 302 if (cp == NULL) {
304 ip_vs_conn_put(ct); 303 ip_vs_conn_put(ct);
305 return NULL; 304 return NULL;
@@ -366,14 +365,16 @@ ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
366 /* 365 /*
367 * Create a connection entry. 366 * Create a connection entry.
368 */ 367 */
369 cp = ip_vs_conn_new(svc->af, iph.protocol, 368 {
370 &iph.saddr, pptr[0], 369 struct ip_vs_conn_param p;
371 &iph.daddr, pptr[1], 370 ip_vs_conn_fill_param(svc->af, iph.protocol, &iph.saddr,
372 &dest->addr, dest->port ? dest->port : pptr[1], 371 pptr[0], &iph.daddr, pptr[1], &p);
373 flags, 372 cp = ip_vs_conn_new(&p, &dest->addr,
374 dest); 373 dest->port ? dest->port : pptr[1],
375 if (cp == NULL) 374 flags, dest);
376 return NULL; 375 if (!cp)
376 return NULL;
377 }
377 378
378 IP_VS_DBG_BUF(6, "Schedule fwd:%c c:%s:%u v:%s:%u " 379 IP_VS_DBG_BUF(6, "Schedule fwd:%c c:%s:%u v:%s:%u "
379 "d:%s:%u conn->flags:%X conn->refcnt:%d\n", 380 "d:%s:%u conn->flags:%X conn->refcnt:%d\n",
@@ -429,14 +430,17 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
429 430
430 /* create a new connection entry */ 431 /* create a new connection entry */
431 IP_VS_DBG(6, "%s(): create a cache_bypass entry\n", __func__); 432 IP_VS_DBG(6, "%s(): create a cache_bypass entry\n", __func__);
432 cp = ip_vs_conn_new(svc->af, iph.protocol, 433 {
433 &iph.saddr, pptr[0], 434 struct ip_vs_conn_param p;
434 &iph.daddr, pptr[1], 435 ip_vs_conn_fill_param(svc->af, iph.protocol,
435 &daddr, 0, 436 &iph.saddr, pptr[0],
436 IP_VS_CONN_F_BYPASS | flags, 437 &iph.daddr, pptr[1], &p);
437 NULL); 438 cp = ip_vs_conn_new(&p, &daddr, 0,
438 if (cp == NULL) 439 IP_VS_CONN_F_BYPASS | flags,
439 return NF_DROP; 440 NULL);
441 if (!cp)
442 return NF_DROP;
443 }
440 444
441 /* statistics */ 445 /* statistics */
442 ip_vs_in_stats(cp, skb); 446 ip_vs_in_stats(cp, skb);
diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c
index 9cd375f94d61..090889a3b3af 100644
--- a/net/netfilter/ipvs/ip_vs_ftp.c
+++ b/net/netfilter/ipvs/ip_vs_ftp.c
@@ -195,13 +195,17 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
195 /* 195 /*
196 * Now update or create an connection entry for it 196 * Now update or create an connection entry for it
197 */ 197 */
198 n_cp = ip_vs_conn_out_get(AF_INET, iph->protocol, &from, port, 198 {
199 &cp->caddr, 0); 199 struct ip_vs_conn_param p;
200 ip_vs_conn_fill_param(AF_INET, iph->protocol,
201 &from, port, &cp->caddr, 0, &p);
202 n_cp = ip_vs_conn_out_get(&p);
203 }
200 if (!n_cp) { 204 if (!n_cp) {
201 n_cp = ip_vs_conn_new(AF_INET, IPPROTO_TCP, 205 struct ip_vs_conn_param p;
202 &cp->caddr, 0, 206 ip_vs_conn_fill_param(AF_INET, IPPROTO_TCP, &cp->caddr,
203 &cp->vaddr, port, 207 0, &cp->vaddr, port, &p);
204 &from, port, 208 n_cp = ip_vs_conn_new(&p, &from, port,
205 IP_VS_CONN_F_NO_CPORT | 209 IP_VS_CONN_F_NO_CPORT |
206 IP_VS_CONN_F_NFCT, 210 IP_VS_CONN_F_NFCT,
207 cp->dest); 211 cp->dest);
@@ -347,21 +351,22 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
347 ip_vs_proto_name(iph->protocol), 351 ip_vs_proto_name(iph->protocol),
348 &to.ip, ntohs(port), &cp->vaddr.ip, 0); 352 &to.ip, ntohs(port), &cp->vaddr.ip, 0);
349 353
350 n_cp = ip_vs_conn_in_get(AF_INET, iph->protocol, 354 {
351 &to, port, 355 struct ip_vs_conn_param p;
352 &cp->vaddr, htons(ntohs(cp->vport)-1)); 356 ip_vs_conn_fill_param(AF_INET, iph->protocol, &to, port,
353 if (!n_cp) {
354 n_cp = ip_vs_conn_new(AF_INET, IPPROTO_TCP,
355 &to, port,
356 &cp->vaddr, htons(ntohs(cp->vport)-1), 357 &cp->vaddr, htons(ntohs(cp->vport)-1),
357 &cp->daddr, htons(ntohs(cp->dport)-1), 358 &p);
358 IP_VS_CONN_F_NFCT, 359 n_cp = ip_vs_conn_in_get(&p);
359 cp->dest); 360 if (!n_cp) {
360 if (!n_cp) 361 n_cp = ip_vs_conn_new(&p, &cp->daddr,
361 return 0; 362 htons(ntohs(cp->dport)-1),
363 IP_VS_CONN_F_NFCT, cp->dest);
364 if (!n_cp)
365 return 0;
362 366
363 /* add its controller */ 367 /* add its controller */
364 ip_vs_control_add(n_cp, cp); 368 ip_vs_control_add(n_cp, cp);
369 }
365 } 370 }
366 371
367 /* 372 /*
diff --git a/net/netfilter/ipvs/ip_vs_nfct.c b/net/netfilter/ipvs/ip_vs_nfct.c
index c038458d0290..4680647cd450 100644
--- a/net/netfilter/ipvs/ip_vs_nfct.c
+++ b/net/netfilter/ipvs/ip_vs_nfct.c
@@ -140,6 +140,7 @@ static void ip_vs_nfct_expect_callback(struct nf_conn *ct,
140{ 140{
141 struct nf_conntrack_tuple *orig, new_reply; 141 struct nf_conntrack_tuple *orig, new_reply;
142 struct ip_vs_conn *cp; 142 struct ip_vs_conn *cp;
143 struct ip_vs_conn_param p;
143 144
144 if (exp->tuple.src.l3num != PF_INET) 145 if (exp->tuple.src.l3num != PF_INET)
145 return; 146 return;
@@ -154,9 +155,10 @@ static void ip_vs_nfct_expect_callback(struct nf_conn *ct,
154 155
155 /* RS->CLIENT */ 156 /* RS->CLIENT */
156 orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; 157 orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
157 cp = ip_vs_conn_out_get(exp->tuple.src.l3num, orig->dst.protonum, 158 ip_vs_conn_fill_param(exp->tuple.src.l3num, orig->dst.protonum,
158 &orig->src.u3, orig->src.u.tcp.port, 159 &orig->src.u3, orig->src.u.tcp.port,
159 &orig->dst.u3, orig->dst.u.tcp.port); 160 &orig->dst.u3, orig->dst.u.tcp.port, &p);
161 cp = ip_vs_conn_out_get(&p);
160 if (cp) { 162 if (cp) {
161 /* Change reply CLIENT->RS to CLIENT->VS */ 163 /* Change reply CLIENT->RS to CLIENT->VS */
162 new_reply = ct->tuplehash[IP_CT_DIR_REPLY].tuple; 164 new_reply = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
@@ -176,9 +178,7 @@ static void ip_vs_nfct_expect_callback(struct nf_conn *ct,
176 } 178 }
177 179
178 /* CLIENT->VS */ 180 /* CLIENT->VS */
179 cp = ip_vs_conn_in_get(exp->tuple.src.l3num, orig->dst.protonum, 181 cp = ip_vs_conn_in_get(&p);
180 &orig->src.u3, orig->src.u.tcp.port,
181 &orig->dst.u3, orig->dst.u.tcp.port);
182 if (cp) { 182 if (cp) {
183 /* Change reply VS->CLIENT to RS->CLIENT */ 183 /* Change reply VS->CLIENT to RS->CLIENT */
184 new_reply = ct->tuplehash[IP_CT_DIR_REPLY].tuple; 184 new_reply = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
diff --git a/net/netfilter/ipvs/ip_vs_proto_ah_esp.c b/net/netfilter/ipvs/ip_vs_proto_ah_esp.c
index 1892dfc12fdd..8956ef33ea6c 100644
--- a/net/netfilter/ipvs/ip_vs_proto_ah_esp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_ah_esp.c
@@ -40,6 +40,19 @@ struct isakmp_hdr {
40 40
41#define PORT_ISAKMP 500 41#define PORT_ISAKMP 500
42 42
43static void
44ah_esp_conn_fill_param_proto(int af, const struct ip_vs_iphdr *iph,
45 int inverse, struct ip_vs_conn_param *p)
46{
47 if (likely(!inverse))
48 ip_vs_conn_fill_param(af, IPPROTO_UDP,
49 &iph->saddr, htons(PORT_ISAKMP),
50 &iph->daddr, htons(PORT_ISAKMP), p);
51 else
52 ip_vs_conn_fill_param(af, IPPROTO_UDP,
53 &iph->daddr, htons(PORT_ISAKMP),
54 &iph->saddr, htons(PORT_ISAKMP), p);
55}
43 56
44static struct ip_vs_conn * 57static struct ip_vs_conn *
45ah_esp_conn_in_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp, 58ah_esp_conn_in_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp,
@@ -47,21 +60,10 @@ ah_esp_conn_in_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp,
47 int inverse) 60 int inverse)
48{ 61{
49 struct ip_vs_conn *cp; 62 struct ip_vs_conn *cp;
63 struct ip_vs_conn_param p;
50 64
51 if (likely(!inverse)) { 65 ah_esp_conn_fill_param_proto(af, iph, inverse, &p);
52 cp = ip_vs_conn_in_get(af, IPPROTO_UDP, 66 cp = ip_vs_conn_in_get(&p);
53 &iph->saddr,
54 htons(PORT_ISAKMP),
55 &iph->daddr,
56 htons(PORT_ISAKMP));
57 } else {
58 cp = ip_vs_conn_in_get(af, IPPROTO_UDP,
59 &iph->daddr,
60 htons(PORT_ISAKMP),
61 &iph->saddr,
62 htons(PORT_ISAKMP));
63 }
64
65 if (!cp) { 67 if (!cp) {
66 /* 68 /*
67 * We are not sure if the packet is from our 69 * We are not sure if the packet is from our
@@ -87,21 +89,10 @@ ah_esp_conn_out_get(int af, const struct sk_buff *skb,
87 int inverse) 89 int inverse)
88{ 90{
89 struct ip_vs_conn *cp; 91 struct ip_vs_conn *cp;
92 struct ip_vs_conn_param p;
90 93
91 if (likely(!inverse)) { 94 ah_esp_conn_fill_param_proto(af, iph, inverse, &p);
92 cp = ip_vs_conn_out_get(af, IPPROTO_UDP, 95 cp = ip_vs_conn_out_get(&p);
93 &iph->saddr,
94 htons(PORT_ISAKMP),
95 &iph->daddr,
96 htons(PORT_ISAKMP));
97 } else {
98 cp = ip_vs_conn_out_get(af, IPPROTO_UDP,
99 &iph->daddr,
100 htons(PORT_ISAKMP),
101 &iph->saddr,
102 htons(PORT_ISAKMP));
103 }
104
105 if (!cp) { 96 if (!cp) {
106 IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for inout packet " 97 IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for inout packet "
107 "%s%s %s->%s\n", 98 "%s%s %s->%s\n",
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 7ba06939829f..f68631f75f09 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -301,6 +301,7 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
301 struct ip_vs_conn *cp; 301 struct ip_vs_conn *cp;
302 struct ip_vs_protocol *pp; 302 struct ip_vs_protocol *pp;
303 struct ip_vs_dest *dest; 303 struct ip_vs_dest *dest;
304 struct ip_vs_conn_param param;
304 char *p; 305 char *p;
305 int i; 306 int i;
306 307
@@ -370,18 +371,17 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
370 } 371 }
371 } 372 }
372 373
373 if (!(flags & IP_VS_CONN_F_TEMPLATE)) 374 {
374 cp = ip_vs_conn_in_get(AF_INET, s->protocol, 375 ip_vs_conn_fill_param(AF_INET, s->protocol,
375 (union nf_inet_addr *)&s->caddr, 376 (union nf_inet_addr *)&s->caddr,
376 s->cport, 377 s->cport,
377 (union nf_inet_addr *)&s->vaddr, 378 (union nf_inet_addr *)&s->vaddr,
378 s->vport); 379 s->vport, &param);
379 else 380 if (!(flags & IP_VS_CONN_F_TEMPLATE))
380 cp = ip_vs_ct_in_get(AF_INET, s->protocol, 381 cp = ip_vs_conn_in_get(&param);
381 (union nf_inet_addr *)&s->caddr, 382 else
382 s->cport, 383 cp = ip_vs_ct_in_get(&param);
383 (union nf_inet_addr *)&s->vaddr, 384 }
384 s->vport);
385 if (!cp) { 385 if (!cp) {
386 /* 386 /*
387 * Find the appropriate destination for the connection. 387 * Find the appropriate destination for the connection.
@@ -406,14 +406,9 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
406 else 406 else
407 flags &= ~IP_VS_CONN_F_INACTIVE; 407 flags &= ~IP_VS_CONN_F_INACTIVE;
408 } 408 }
409 cp = ip_vs_conn_new(AF_INET, s->protocol, 409 cp = ip_vs_conn_new(&param,
410 (union nf_inet_addr *)&s->caddr,
411 s->cport,
412 (union nf_inet_addr *)&s->vaddr,
413 s->vport,
414 (union nf_inet_addr *)&s->daddr, 410 (union nf_inet_addr *)&s->daddr,
415 s->dport, 411 s->dport, flags, dest);
416 flags, dest);
417 if (dest) 412 if (dest)
418 atomic_dec(&dest->refcnt); 413 atomic_dec(&dest->refcnt);
419 if (!cp) { 414 if (!cp) {