aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulius Volz <juliusv@google.com>2008-09-02 09:55:43 -0400
committerSimon Horman <horms@verge.net.au>2008-09-04 21:17:08 -0400
commit28364a59f3dfe7fed3560ec7aff9b7aeb02824fb (patch)
tree88b14c8c4d48c5ae538d7d7defe33272498aaebd
parent0bbdd42b7efa66685b6d74701bcde3a596a3a59d (diff)
IPVS: Extend functions for getting/creating connections
Extend functions for getting/creating connections and connection templates for IPv6 support and fix the callers. Signed-off-by: Julius Volz <juliusv@google.com> Signed-off-by: Simon Horman <horms@verge.net.au>
-rw-r--r--include/net/ip_vs.h16
-rw-r--r--net/ipv4/ipvs/ip_vs_conn.c100
-rw-r--r--net/ipv4/ipvs/ip_vs_core.c112
-rw-r--r--net/ipv4/ipvs/ip_vs_ftp.c45
-rw-r--r--net/ipv4/ipvs/ip_vs_proto_ah_esp.c24
-rw-r--r--net/ipv4/ipvs/ip_vs_proto_tcp.c24
-rw-r--r--net/ipv4/ipvs/ip_vs_proto_udp.c24
-rw-r--r--net/ipv4/ipvs/ip_vs_sync.c27
8 files changed, 209 insertions, 163 deletions
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index c173f1a7de2c..26893499eb6f 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -642,11 +642,16 @@ enum {
642}; 642};
643 643
644extern struct ip_vs_conn *ip_vs_conn_in_get 644extern struct ip_vs_conn *ip_vs_conn_in_get
645(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port); 645(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
646 const union nf_inet_addr *d_addr, __be16 d_port);
647
646extern struct ip_vs_conn *ip_vs_ct_in_get 648extern struct ip_vs_conn *ip_vs_ct_in_get
647(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port); 649(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
650 const union nf_inet_addr *d_addr, __be16 d_port);
651
648extern struct ip_vs_conn *ip_vs_conn_out_get 652extern struct ip_vs_conn *ip_vs_conn_out_get
649(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port); 653(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
654 const union nf_inet_addr *d_addr, __be16 d_port);
650 655
651/* put back the conn without restarting its timer */ 656/* put back the conn without restarting its timer */
652static inline void __ip_vs_conn_put(struct ip_vs_conn *cp) 657static inline void __ip_vs_conn_put(struct ip_vs_conn *cp)
@@ -657,8 +662,9 @@ extern void ip_vs_conn_put(struct ip_vs_conn *cp);
657extern void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport); 662extern void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport);
658 663
659extern struct ip_vs_conn * 664extern struct ip_vs_conn *
660ip_vs_conn_new(int proto, __be32 caddr, __be16 cport, __be32 vaddr, __be16 vport, 665ip_vs_conn_new(int af, int proto, const union nf_inet_addr *caddr, __be16 cport,
661 __be32 daddr, __be16 dport, unsigned flags, 666 const union nf_inet_addr *vaddr, __be16 vport,
667 const union nf_inet_addr *daddr, __be16 dport, unsigned flags,
662 struct ip_vs_dest *dest); 668 struct ip_vs_dest *dest);
663extern void ip_vs_conn_expire_now(struct ip_vs_conn *cp); 669extern void ip_vs_conn_expire_now(struct ip_vs_conn *cp);
664 670
diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c
index 639d4bc7fc1d..15eec282b17c 100644
--- a/net/ipv4/ipvs/ip_vs_conn.c
+++ b/net/ipv4/ipvs/ip_vs_conn.c
@@ -114,9 +114,18 @@ static inline void ct_write_unlock_bh(unsigned key)
114/* 114/*
115 * Returns hash value for IPVS connection entry 115 * Returns hash value for IPVS connection entry
116 */ 116 */
117static unsigned int ip_vs_conn_hashkey(unsigned proto, __be32 addr, __be16 port) 117static unsigned int ip_vs_conn_hashkey(int af, unsigned proto,
118 const union nf_inet_addr *addr,
119 __be16 port)
118{ 120{
119 return jhash_3words((__force u32)addr, (__force u32)port, proto, ip_vs_conn_rnd) 121#ifdef CONFIG_IP_VS_IPV6
122 if (af == AF_INET6)
123 return jhash_3words(jhash(addr, 16, ip_vs_conn_rnd),
124 (__force u32)port, proto, ip_vs_conn_rnd)
125 & IP_VS_CONN_TAB_MASK;
126#endif
127 return jhash_3words((__force u32)addr->ip, (__force u32)port, proto,
128 ip_vs_conn_rnd)
120 & IP_VS_CONN_TAB_MASK; 129 & IP_VS_CONN_TAB_MASK;
121} 130}
122 131
@@ -131,7 +140,7 @@ static inline int ip_vs_conn_hash(struct ip_vs_conn *cp)
131 int ret; 140 int ret;
132 141
133 /* Hash by protocol, client address and port */ 142 /* Hash by protocol, client address and port */
134 hash = ip_vs_conn_hashkey(cp->protocol, cp->caddr.ip, cp->cport); 143 hash = ip_vs_conn_hashkey(cp->af, cp->protocol, &cp->caddr, cp->cport);
135 144
136 ct_write_lock(hash); 145 ct_write_lock(hash);
137 146
@@ -162,7 +171,7 @@ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp)
162 int ret; 171 int ret;
163 172
164 /* unhash it and decrease its reference counter */ 173 /* unhash it and decrease its reference counter */
165 hash = ip_vs_conn_hashkey(cp->protocol, cp->caddr.ip, cp->cport); 174 hash = ip_vs_conn_hashkey(cp->af, cp->protocol, &cp->caddr, cp->cport);
166 175
167 ct_write_lock(hash); 176 ct_write_lock(hash);
168 177
@@ -187,18 +196,21 @@ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp)
187 * d_addr, d_port: pkt dest address (load balancer) 196 * d_addr, d_port: pkt dest address (load balancer)
188 */ 197 */
189static inline struct ip_vs_conn *__ip_vs_conn_in_get 198static inline struct ip_vs_conn *__ip_vs_conn_in_get
190(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port) 199(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
200 const union nf_inet_addr *d_addr, __be16 d_port)
191{ 201{
192 unsigned hash; 202 unsigned hash;
193 struct ip_vs_conn *cp; 203 struct ip_vs_conn *cp;
194 204
195 hash = ip_vs_conn_hashkey(protocol, s_addr, s_port); 205 hash = ip_vs_conn_hashkey(af, protocol, s_addr, s_port);
196 206
197 ct_read_lock(hash); 207 ct_read_lock(hash);
198 208
199 list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) { 209 list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
200 if (s_addr == cp->caddr.ip && s_port == cp->cport && 210 if (cp->af == af &&
201 d_port == cp->vport && d_addr == cp->vaddr.ip && 211 ip_vs_addr_equal(af, s_addr, &cp->caddr) &&
212 ip_vs_addr_equal(af, d_addr, &cp->vaddr) &&
213 s_port == cp->cport && d_port == cp->vport &&
202 ((!s_port) ^ (!(cp->flags & IP_VS_CONN_F_NO_CPORT))) && 214 ((!s_port) ^ (!(cp->flags & IP_VS_CONN_F_NO_CPORT))) &&
203 protocol == cp->protocol) { 215 protocol == cp->protocol) {
204 /* HIT */ 216 /* HIT */
@@ -214,37 +226,42 @@ static inline struct ip_vs_conn *__ip_vs_conn_in_get
214} 226}
215 227
216struct ip_vs_conn *ip_vs_conn_in_get 228struct ip_vs_conn *ip_vs_conn_in_get
217(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port) 229(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
230 const union nf_inet_addr *d_addr, __be16 d_port)
218{ 231{
219 struct ip_vs_conn *cp; 232 struct ip_vs_conn *cp;
220 233
221 cp = __ip_vs_conn_in_get(protocol, s_addr, s_port, d_addr, d_port); 234 cp = __ip_vs_conn_in_get(af, protocol, s_addr, s_port, d_addr, d_port);
222 if (!cp && atomic_read(&ip_vs_conn_no_cport_cnt)) 235 if (!cp && atomic_read(&ip_vs_conn_no_cport_cnt))
223 cp = __ip_vs_conn_in_get(protocol, s_addr, 0, d_addr, d_port); 236 cp = __ip_vs_conn_in_get(af, protocol, s_addr, 0, d_addr,
237 d_port);
224 238
225 IP_VS_DBG(9, "lookup/in %s %u.%u.%u.%u:%d->%u.%u.%u.%u:%d %s\n", 239 IP_VS_DBG_BUF(9, "lookup/in %s %s:%d->%s:%d %s\n",
226 ip_vs_proto_name(protocol), 240 ip_vs_proto_name(protocol),
227 NIPQUAD(s_addr), ntohs(s_port), 241 IP_VS_DBG_ADDR(af, s_addr), ntohs(s_port),
228 NIPQUAD(d_addr), ntohs(d_port), 242 IP_VS_DBG_ADDR(af, d_addr), ntohs(d_port),
229 cp?"hit":"not hit"); 243 cp ? "hit" : "not hit");
230 244
231 return cp; 245 return cp;
232} 246}
233 247
234/* Get reference to connection template */ 248/* Get reference to connection template */
235struct ip_vs_conn *ip_vs_ct_in_get 249struct ip_vs_conn *ip_vs_ct_in_get
236(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port) 250(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
251 const union nf_inet_addr *d_addr, __be16 d_port)
237{ 252{
238 unsigned hash; 253 unsigned hash;
239 struct ip_vs_conn *cp; 254 struct ip_vs_conn *cp;
240 255
241 hash = ip_vs_conn_hashkey(protocol, s_addr, s_port); 256 hash = ip_vs_conn_hashkey(af, protocol, s_addr, s_port);
242 257
243 ct_read_lock(hash); 258 ct_read_lock(hash);
244 259
245 list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) { 260 list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
246 if (s_addr == cp->caddr.ip && s_port == cp->cport && 261 if (cp->af == af &&
247 d_port == cp->vport && d_addr == cp->vaddr.ip && 262 ip_vs_addr_equal(af, s_addr, &cp->caddr) &&
263 ip_vs_addr_equal(af, d_addr, &cp->vaddr) &&
264 s_port == cp->cport && d_port == cp->vport &&
248 cp->flags & IP_VS_CONN_F_TEMPLATE && 265 cp->flags & IP_VS_CONN_F_TEMPLATE &&
249 protocol == cp->protocol) { 266 protocol == cp->protocol) {
250 /* HIT */ 267 /* HIT */
@@ -257,11 +274,11 @@ struct ip_vs_conn *ip_vs_ct_in_get
257 out: 274 out:
258 ct_read_unlock(hash); 275 ct_read_unlock(hash);
259 276
260 IP_VS_DBG(9, "template lookup/in %s %u.%u.%u.%u:%d->%u.%u.%u.%u:%d %s\n", 277 IP_VS_DBG_BUF(9, "template lookup/in %s %s:%d->%s:%d %s\n",
261 ip_vs_proto_name(protocol), 278 ip_vs_proto_name(protocol),
262 NIPQUAD(s_addr), ntohs(s_port), 279 IP_VS_DBG_ADDR(af, s_addr), ntohs(s_port),
263 NIPQUAD(d_addr), ntohs(d_port), 280 IP_VS_DBG_ADDR(af, d_addr), ntohs(d_port),
264 cp?"hit":"not hit"); 281 cp ? "hit" : "not hit");
265 282
266 return cp; 283 return cp;
267} 284}
@@ -273,7 +290,8 @@ struct ip_vs_conn *ip_vs_ct_in_get
273 * d_addr, d_port: pkt dest address (foreign host) 290 * d_addr, d_port: pkt dest address (foreign host)
274 */ 291 */
275struct ip_vs_conn *ip_vs_conn_out_get 292struct ip_vs_conn *ip_vs_conn_out_get
276(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port) 293(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
294 const union nf_inet_addr *d_addr, __be16 d_port)
277{ 295{
278 unsigned hash; 296 unsigned hash;
279 struct ip_vs_conn *cp, *ret=NULL; 297 struct ip_vs_conn *cp, *ret=NULL;
@@ -281,13 +299,15 @@ struct ip_vs_conn *ip_vs_conn_out_get
281 /* 299 /*
282 * Check for "full" addressed entries 300 * Check for "full" addressed entries
283 */ 301 */
284 hash = ip_vs_conn_hashkey(protocol, d_addr, d_port); 302 hash = ip_vs_conn_hashkey(af, protocol, d_addr, d_port);
285 303
286 ct_read_lock(hash); 304 ct_read_lock(hash);
287 305
288 list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) { 306 list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
289 if (d_addr == cp->caddr.ip && d_port == cp->cport && 307 if (cp->af == af &&
290 s_port == cp->dport && s_addr == cp->daddr.ip && 308 ip_vs_addr_equal(af, d_addr, &cp->caddr) &&
309 ip_vs_addr_equal(af, s_addr, &cp->daddr) &&
310 d_port == cp->cport && s_port == cp->dport &&
291 protocol == cp->protocol) { 311 protocol == cp->protocol) {
292 /* HIT */ 312 /* HIT */
293 atomic_inc(&cp->refcnt); 313 atomic_inc(&cp->refcnt);
@@ -298,11 +318,11 @@ struct ip_vs_conn *ip_vs_conn_out_get
298 318
299 ct_read_unlock(hash); 319 ct_read_unlock(hash);
300 320
301 IP_VS_DBG(9, "lookup/out %s %u.%u.%u.%u:%d->%u.%u.%u.%u:%d %s\n", 321 IP_VS_DBG_BUF(9, "lookup/out %s %s:%d->%s:%d %s\n",
302 ip_vs_proto_name(protocol), 322 ip_vs_proto_name(protocol),
303 NIPQUAD(s_addr), ntohs(s_port), 323 IP_VS_DBG_ADDR(af, s_addr), ntohs(s_port),
304 NIPQUAD(d_addr), ntohs(d_port), 324 IP_VS_DBG_ADDR(af, d_addr), ntohs(d_port),
305 ret?"hit":"not hit"); 325 ret ? "hit" : "not hit");
306 326
307 return ret; 327 return ret;
308} 328}
@@ -625,8 +645,9 @@ void ip_vs_conn_expire_now(struct ip_vs_conn *cp)
625 * Create a new connection entry and hash it into the ip_vs_conn_tab 645 * Create a new connection entry and hash it into the ip_vs_conn_tab
626 */ 646 */
627struct ip_vs_conn * 647struct ip_vs_conn *
628ip_vs_conn_new(int proto, __be32 caddr, __be16 cport, __be32 vaddr, __be16 vport, 648ip_vs_conn_new(int af, int proto, const union nf_inet_addr *caddr, __be16 cport,
629 __be32 daddr, __be16 dport, unsigned flags, 649 const union nf_inet_addr *vaddr, __be16 vport,
650 const union nf_inet_addr *daddr, __be16 dport, unsigned flags,
630 struct ip_vs_dest *dest) 651 struct ip_vs_dest *dest)
631{ 652{
632 struct ip_vs_conn *cp; 653 struct ip_vs_conn *cp;
@@ -640,12 +661,13 @@ ip_vs_conn_new(int proto, __be32 caddr, __be16 cport, __be32 vaddr, __be16 vport
640 661
641 INIT_LIST_HEAD(&cp->c_list); 662 INIT_LIST_HEAD(&cp->c_list);
642 setup_timer(&cp->timer, ip_vs_conn_expire, (unsigned long)cp); 663 setup_timer(&cp->timer, ip_vs_conn_expire, (unsigned long)cp);
664 cp->af = af;
643 cp->protocol = proto; 665 cp->protocol = proto;
644 cp->caddr.ip = caddr; 666 ip_vs_addr_copy(af, &cp->caddr, caddr);
645 cp->cport = cport; 667 cp->cport = cport;
646 cp->vaddr.ip = vaddr; 668 ip_vs_addr_copy(af, &cp->vaddr, vaddr);
647 cp->vport = vport; 669 cp->vport = vport;
648 cp->daddr.ip = daddr; 670 ip_vs_addr_copy(af, &cp->daddr, daddr);
649 cp->dport = dport; 671 cp->dport = dport;
650 cp->flags = flags; 672 cp->flags = flags;
651 spin_lock_init(&cp->lock); 673 spin_lock_init(&cp->lock);
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index 34aaa1480d90..2d5a4331709b 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -173,19 +173,21 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
173 __be16 ports[2]) 173 __be16 ports[2])
174{ 174{
175 struct ip_vs_conn *cp = NULL; 175 struct ip_vs_conn *cp = NULL;
176 struct iphdr *iph = ip_hdr(skb); 176 struct ip_vs_iphdr iph;
177 struct ip_vs_dest *dest; 177 struct ip_vs_dest *dest;
178 struct ip_vs_conn *ct; 178 struct ip_vs_conn *ct;
179 __be16 dport; /* destination port to forward */ 179 __be16 dport; /* destination port to forward */
180 __be32 snet; /* source network of the client, after masking */ 180 union nf_inet_addr snet; /* source network of the client,
181 after masking */
182 ip_vs_fill_iphdr(AF_INET, skb_network_header(skb), &iph);
181 183
182 /* Mask saddr with the netmask to adjust template granularity */ 184 /* Mask saddr with the netmask to adjust template granularity */
183 snet = iph->saddr & svc->netmask; 185 snet.ip = iph.saddr.ip & svc->netmask;
184 186
185 IP_VS_DBG(6, "p-schedule: src %u.%u.%u.%u:%u dest %u.%u.%u.%u:%u " 187 IP_VS_DBG(6, "p-schedule: src %u.%u.%u.%u:%u dest %u.%u.%u.%u:%u "
186 "mnet %u.%u.%u.%u\n", 188 "mnet %u.%u.%u.%u\n",
187 NIPQUAD(iph->saddr), ntohs(ports[0]), 189 NIPQUAD(iph.saddr.ip), ntohs(ports[0]),
188 NIPQUAD(iph->daddr), ntohs(ports[1]), 190 NIPQUAD(iph.daddr.ip), ntohs(ports[1]),
189 NIPQUAD(snet)); 191 NIPQUAD(snet));
190 192
191 /* 193 /*
@@ -204,11 +206,11 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
204 if (ports[1] == svc->port) { 206 if (ports[1] == svc->port) {
205 /* Check if a template already exists */ 207 /* Check if a template already exists */
206 if (svc->port != FTPPORT) 208 if (svc->port != FTPPORT)
207 ct = ip_vs_ct_in_get(iph->protocol, snet, 0, 209 ct = ip_vs_ct_in_get(AF_INET, iph.protocol, &snet, 0,
208 iph->daddr, ports[1]); 210 &iph.daddr, ports[1]);
209 else 211 else
210 ct = ip_vs_ct_in_get(iph->protocol, snet, 0, 212 ct = ip_vs_ct_in_get(AF_INET, iph.protocol, &snet, 0,
211 iph->daddr, 0); 213 &iph.daddr, 0);
212 214
213 if (!ct || !ip_vs_check_template(ct)) { 215 if (!ct || !ip_vs_check_template(ct)) {
214 /* 216 /*
@@ -228,18 +230,18 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
228 * for ftp service. 230 * for ftp service.
229 */ 231 */
230 if (svc->port != FTPPORT) 232 if (svc->port != FTPPORT)
231 ct = ip_vs_conn_new(iph->protocol, 233 ct = ip_vs_conn_new(AF_INET, iph.protocol,
232 snet, 0, 234 &snet, 0,
233 iph->daddr, 235 &iph.daddr,
234 ports[1], 236 ports[1],
235 dest->addr.ip, dest->port, 237 &dest->addr, dest->port,
236 IP_VS_CONN_F_TEMPLATE, 238 IP_VS_CONN_F_TEMPLATE,
237 dest); 239 dest);
238 else 240 else
239 ct = ip_vs_conn_new(iph->protocol, 241 ct = ip_vs_conn_new(AF_INET, iph.protocol,
240 snet, 0, 242 &snet, 0,
241 iph->daddr, 0, 243 &iph.daddr, 0,
242 dest->addr.ip, 0, 244 &dest->addr, 0,
243 IP_VS_CONN_F_TEMPLATE, 245 IP_VS_CONN_F_TEMPLATE,
244 dest); 246 dest);
245 if (ct == NULL) 247 if (ct == NULL)
@@ -258,12 +260,16 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
258 * fwmark template: <IPPROTO_IP,caddr,0,fwmark,0,daddr,0> 260 * fwmark template: <IPPROTO_IP,caddr,0,fwmark,0,daddr,0>
259 * port zero template: <protocol,caddr,0,vaddr,0,daddr,0> 261 * port zero template: <protocol,caddr,0,vaddr,0,daddr,0>
260 */ 262 */
261 if (svc->fwmark) 263 if (svc->fwmark) {
262 ct = ip_vs_ct_in_get(IPPROTO_IP, snet, 0, 264 union nf_inet_addr fwmark = {
263 htonl(svc->fwmark), 0); 265 .all = { 0, 0, 0, htonl(svc->fwmark) }
264 else 266 };
265 ct = ip_vs_ct_in_get(iph->protocol, snet, 0, 267
266 iph->daddr, 0); 268 ct = ip_vs_ct_in_get(AF_INET, IPPROTO_IP, &snet, 0,
269 &fwmark, 0);
270 } else
271 ct = ip_vs_ct_in_get(AF_INET, iph.protocol, &snet, 0,
272 &iph.daddr, 0);
267 273
268 if (!ct || !ip_vs_check_template(ct)) { 274 if (!ct || !ip_vs_check_template(ct)) {
269 /* 275 /*
@@ -282,18 +288,22 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
282 /* 288 /*
283 * Create a template according to the service 289 * Create a template according to the service
284 */ 290 */
285 if (svc->fwmark) 291 if (svc->fwmark) {
286 ct = ip_vs_conn_new(IPPROTO_IP, 292 union nf_inet_addr fwmark = {
287 snet, 0, 293 .all = { 0, 0, 0, htonl(svc->fwmark) }
288 htonl(svc->fwmark), 0, 294 };
289 dest->addr.ip, 0, 295
296 ct = ip_vs_conn_new(AF_INET, IPPROTO_IP,
297 &snet, 0,
298 &fwmark, 0,
299 &dest->addr, 0,
290 IP_VS_CONN_F_TEMPLATE, 300 IP_VS_CONN_F_TEMPLATE,
291 dest); 301 dest);
292 else 302 } else
293 ct = ip_vs_conn_new(iph->protocol, 303 ct = ip_vs_conn_new(AF_INET, iph.protocol,
294 snet, 0, 304 &snet, 0,
295 iph->daddr, 0, 305 &iph.daddr, 0,
296 dest->addr.ip, 0, 306 &dest->addr, 0,
297 IP_VS_CONN_F_TEMPLATE, 307 IP_VS_CONN_F_TEMPLATE,
298 dest); 308 dest);
299 if (ct == NULL) 309 if (ct == NULL)
@@ -310,10 +320,10 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
310 /* 320 /*
311 * Create a new connection according to the template 321 * Create a new connection according to the template
312 */ 322 */
313 cp = ip_vs_conn_new(iph->protocol, 323 cp = ip_vs_conn_new(AF_INET, iph.protocol,
314 iph->saddr, ports[0], 324 &iph.saddr, ports[0],
315 iph->daddr, ports[1], 325 &iph.daddr, ports[1],
316 dest->addr.ip, dport, 326 &dest->addr, dport,
317 0, 327 0,
318 dest); 328 dest);
319 if (cp == NULL) { 329 if (cp == NULL) {
@@ -342,12 +352,12 @@ struct ip_vs_conn *
342ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) 352ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
343{ 353{
344 struct ip_vs_conn *cp = NULL; 354 struct ip_vs_conn *cp = NULL;
345 struct iphdr *iph = ip_hdr(skb); 355 struct ip_vs_iphdr iph;
346 struct ip_vs_dest *dest; 356 struct ip_vs_dest *dest;
347 __be16 _ports[2], *pptr; 357 __be16 _ports[2], *pptr;
348 358
349 pptr = skb_header_pointer(skb, iph->ihl*4, 359 ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
350 sizeof(_ports), _ports); 360 pptr = skb_header_pointer(skb, iph.len, sizeof(_ports), _ports);
351 if (pptr == NULL) 361 if (pptr == NULL)
352 return NULL; 362 return NULL;
353 363
@@ -377,10 +387,10 @@ ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
377 /* 387 /*
378 * Create a connection entry. 388 * Create a connection entry.
379 */ 389 */
380 cp = ip_vs_conn_new(iph->protocol, 390 cp = ip_vs_conn_new(AF_INET, iph.protocol,
381 iph->saddr, pptr[0], 391 &iph.saddr, pptr[0],
382 iph->daddr, pptr[1], 392 &iph.daddr, pptr[1],
383 dest->addr.ip, dest->port ? dest->port : pptr[1], 393 &dest->addr, dest->port ? dest->port : pptr[1],
384 0, 394 0,
385 dest); 395 dest);
386 if (cp == NULL) 396 if (cp == NULL)
@@ -408,10 +418,10 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
408 struct ip_vs_protocol *pp) 418 struct ip_vs_protocol *pp)
409{ 419{
410 __be16 _ports[2], *pptr; 420 __be16 _ports[2], *pptr;
411 struct iphdr *iph = ip_hdr(skb); 421 struct ip_vs_iphdr iph;
422 ip_vs_fill_iphdr(AF_INET, skb_network_header(skb), &iph);
412 423
413 pptr = skb_header_pointer(skb, iph->ihl*4, 424 pptr = skb_header_pointer(skb, iph.len, sizeof(_ports), _ports);
414 sizeof(_ports), _ports);
415 if (pptr == NULL) { 425 if (pptr == NULL) {
416 ip_vs_service_put(svc); 426 ip_vs_service_put(svc);
417 return NF_DROP; 427 return NF_DROP;
@@ -421,7 +431,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
421 and the destination is RTN_UNICAST (and not local), then create 431 and the destination is RTN_UNICAST (and not local), then create
422 a cache_bypass connection entry */ 432 a cache_bypass connection entry */
423 if (sysctl_ip_vs_cache_bypass && svc->fwmark 433 if (sysctl_ip_vs_cache_bypass && svc->fwmark
424 && (inet_addr_type(&init_net, iph->daddr) == RTN_UNICAST)) { 434 && (inet_addr_type(&init_net, iph.daddr.ip) == RTN_UNICAST)) {
425 int ret, cs; 435 int ret, cs;
426 struct ip_vs_conn *cp; 436 struct ip_vs_conn *cp;
427 437
@@ -429,9 +439,9 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
429 439
430 /* create a new connection entry */ 440 /* create a new connection entry */
431 IP_VS_DBG(6, "ip_vs_leave: create a cache_bypass entry\n"); 441 IP_VS_DBG(6, "ip_vs_leave: create a cache_bypass entry\n");
432 cp = ip_vs_conn_new(iph->protocol, 442 cp = ip_vs_conn_new(AF_INET, iph.protocol,
433 iph->saddr, pptr[0], 443 &iph.saddr, pptr[0],
434 iph->daddr, pptr[1], 444 &iph.daddr, pptr[1],
435 0, 0, 445 0, 0,
436 IP_VS_CONN_F_BYPASS, 446 IP_VS_CONN_F_BYPASS,
437 NULL); 447 NULL);
diff --git a/net/ipv4/ipvs/ip_vs_ftp.c b/net/ipv4/ipvs/ip_vs_ftp.c
index bfe5d7050a58..0c3fbe0de5f1 100644
--- a/net/ipv4/ipvs/ip_vs_ftp.c
+++ b/net/ipv4/ipvs/ip_vs_ftp.c
@@ -140,7 +140,7 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
140 struct tcphdr *th; 140 struct tcphdr *th;
141 char *data, *data_limit; 141 char *data, *data_limit;
142 char *start, *end; 142 char *start, *end;
143 __be32 from; 143 union nf_inet_addr from;
144 __be16 port; 144 __be16 port;
145 struct ip_vs_conn *n_cp; 145 struct ip_vs_conn *n_cp;
146 char buf[24]; /* xxx.xxx.xxx.xxx,ppp,ppp\000 */ 146 char buf[24]; /* xxx.xxx.xxx.xxx,ppp,ppp\000 */
@@ -166,24 +166,25 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
166 if (ip_vs_ftp_get_addrport(data, data_limit, 166 if (ip_vs_ftp_get_addrport(data, data_limit,
167 SERVER_STRING, 167 SERVER_STRING,
168 sizeof(SERVER_STRING)-1, ')', 168 sizeof(SERVER_STRING)-1, ')',
169 &from, &port, 169 &from.ip, &port,
170 &start, &end) != 1) 170 &start, &end) != 1)
171 return 1; 171 return 1;
172 172
173 IP_VS_DBG(7, "PASV response (%u.%u.%u.%u:%d) -> " 173 IP_VS_DBG(7, "PASV response (%u.%u.%u.%u:%d) -> "
174 "%u.%u.%u.%u:%d detected\n", 174 "%u.%u.%u.%u:%d detected\n",
175 NIPQUAD(from), ntohs(port), NIPQUAD(cp->caddr.ip), 0); 175 NIPQUAD(from.ip), ntohs(port),
176 NIPQUAD(cp->caddr.ip), 0);
176 177
177 /* 178 /*
178 * Now update or create an connection entry for it 179 * Now update or create an connection entry for it
179 */ 180 */
180 n_cp = ip_vs_conn_out_get(iph->protocol, from, port, 181 n_cp = ip_vs_conn_out_get(AF_INET, iph->protocol, &from, port,
181 cp->caddr.ip, 0); 182 &cp->caddr, 0);
182 if (!n_cp) { 183 if (!n_cp) {
183 n_cp = ip_vs_conn_new(IPPROTO_TCP, 184 n_cp = ip_vs_conn_new(AF_INET, IPPROTO_TCP,
184 cp->caddr.ip, 0, 185 &cp->caddr, 0,
185 cp->vaddr.ip, port, 186 &cp->vaddr, port,
186 from, port, 187 &from, port,
187 IP_VS_CONN_F_NO_CPORT, 188 IP_VS_CONN_F_NO_CPORT,
188 cp->dest); 189 cp->dest);
189 if (!n_cp) 190 if (!n_cp)
@@ -196,9 +197,9 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
196 /* 197 /*
197 * Replace the old passive address with the new one 198 * Replace the old passive address with the new one
198 */ 199 */
199 from = n_cp->vaddr.ip; 200 from.ip = n_cp->vaddr.ip;
200 port = n_cp->vport; 201 port = n_cp->vport;
201 sprintf(buf,"%d,%d,%d,%d,%d,%d", NIPQUAD(from), 202 sprintf(buf, "%d,%d,%d,%d,%d,%d", NIPQUAD(from.ip),
202 (ntohs(port)>>8)&255, ntohs(port)&255); 203 (ntohs(port)>>8)&255, ntohs(port)&255);
203 buf_len = strlen(buf); 204 buf_len = strlen(buf);
204 205
@@ -243,7 +244,7 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
243 struct tcphdr *th; 244 struct tcphdr *th;
244 char *data, *data_start, *data_limit; 245 char *data, *data_start, *data_limit;
245 char *start, *end; 246 char *start, *end;
246 __be32 to; 247 union nf_inet_addr to;
247 __be16 port; 248 __be16 port;
248 struct ip_vs_conn *n_cp; 249 struct ip_vs_conn *n_cp;
249 250
@@ -291,12 +292,12 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
291 */ 292 */
292 if (ip_vs_ftp_get_addrport(data_start, data_limit, 293 if (ip_vs_ftp_get_addrport(data_start, data_limit,
293 CLIENT_STRING, sizeof(CLIENT_STRING)-1, 294 CLIENT_STRING, sizeof(CLIENT_STRING)-1,
294 '\r', &to, &port, 295 '\r', &to.ip, &port,
295 &start, &end) != 1) 296 &start, &end) != 1)
296 return 1; 297 return 1;
297 298
298 IP_VS_DBG(7, "PORT %u.%u.%u.%u:%d detected\n", 299 IP_VS_DBG(7, "PORT %u.%u.%u.%u:%d detected\n",
299 NIPQUAD(to), ntohs(port)); 300 NIPQUAD(to.ip), ntohs(port));
300 301
301 /* Passive mode off */ 302 /* Passive mode off */
302 cp->app_data = NULL; 303 cp->app_data = NULL;
@@ -306,16 +307,16 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
306 */ 307 */
307 IP_VS_DBG(7, "protocol %s %u.%u.%u.%u:%d %u.%u.%u.%u:%d\n", 308 IP_VS_DBG(7, "protocol %s %u.%u.%u.%u:%d %u.%u.%u.%u:%d\n",
308 ip_vs_proto_name(iph->protocol), 309 ip_vs_proto_name(iph->protocol),
309 NIPQUAD(to), ntohs(port), NIPQUAD(cp->vaddr.ip), 0); 310 NIPQUAD(to.ip), ntohs(port), NIPQUAD(cp->vaddr.ip), 0);
310 311
311 n_cp = ip_vs_conn_in_get(iph->protocol, 312 n_cp = ip_vs_conn_in_get(AF_INET, iph->protocol,
312 to, port, 313 &to, port,
313 cp->vaddr.ip, htons(ntohs(cp->vport)-1)); 314 &cp->vaddr, htons(ntohs(cp->vport)-1));
314 if (!n_cp) { 315 if (!n_cp) {
315 n_cp = ip_vs_conn_new(IPPROTO_TCP, 316 n_cp = ip_vs_conn_new(AF_INET, IPPROTO_TCP,
316 to, port, 317 &to, port,
317 cp->vaddr.ip, htons(ntohs(cp->vport)-1), 318 &cp->vaddr, htons(ntohs(cp->vport)-1),
318 cp->daddr.ip, htons(ntohs(cp->dport)-1), 319 &cp->daddr, htons(ntohs(cp->dport)-1),
319 0, 320 0,
320 cp->dest); 321 cp->dest);
321 if (!n_cp) 322 if (!n_cp)
diff --git a/net/ipv4/ipvs/ip_vs_proto_ah_esp.c b/net/ipv4/ipvs/ip_vs_proto_ah_esp.c
index 4b0b8f268d10..2b18a78d0399 100644
--- a/net/ipv4/ipvs/ip_vs_proto_ah_esp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_ah_esp.c
@@ -46,16 +46,16 @@ ah_esp_conn_in_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp,
46 struct ip_vs_conn *cp; 46 struct ip_vs_conn *cp;
47 47
48 if (likely(!inverse)) { 48 if (likely(!inverse)) {
49 cp = ip_vs_conn_in_get(IPPROTO_UDP, 49 cp = ip_vs_conn_in_get(af, IPPROTO_UDP,
50 iph->saddr.ip, 50 &iph->saddr,
51 htons(PORT_ISAKMP), 51 htons(PORT_ISAKMP),
52 iph->daddr.ip, 52 &iph->daddr,
53 htons(PORT_ISAKMP)); 53 htons(PORT_ISAKMP));
54 } else { 54 } else {
55 cp = ip_vs_conn_in_get(IPPROTO_UDP, 55 cp = ip_vs_conn_in_get(af, IPPROTO_UDP,
56 iph->daddr.ip, 56 &iph->daddr,
57 htons(PORT_ISAKMP), 57 htons(PORT_ISAKMP),
58 iph->saddr.ip, 58 &iph->saddr,
59 htons(PORT_ISAKMP)); 59 htons(PORT_ISAKMP));
60 } 60 }
61 61
@@ -86,16 +86,16 @@ ah_esp_conn_out_get(int af, const struct sk_buff *skb,
86 struct ip_vs_conn *cp; 86 struct ip_vs_conn *cp;
87 87
88 if (likely(!inverse)) { 88 if (likely(!inverse)) {
89 cp = ip_vs_conn_out_get(IPPROTO_UDP, 89 cp = ip_vs_conn_out_get(af, IPPROTO_UDP,
90 iph->saddr.ip, 90 &iph->saddr,
91 htons(PORT_ISAKMP), 91 htons(PORT_ISAKMP),
92 iph->daddr.ip, 92 &iph->daddr,
93 htons(PORT_ISAKMP)); 93 htons(PORT_ISAKMP));
94 } else { 94 } else {
95 cp = ip_vs_conn_out_get(IPPROTO_UDP, 95 cp = ip_vs_conn_out_get(af, IPPROTO_UDP,
96 iph->daddr.ip, 96 &iph->daddr,
97 htons(PORT_ISAKMP), 97 htons(PORT_ISAKMP),
98 iph->saddr.ip, 98 &iph->saddr,
99 htons(PORT_ISAKMP)); 99 htons(PORT_ISAKMP));
100 } 100 }
101 101
diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c
index 3daae43ae44b..3da2bb05ee74 100644
--- a/net/ipv4/ipvs/ip_vs_proto_tcp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c
@@ -36,13 +36,13 @@ tcp_conn_in_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp,
36 return NULL; 36 return NULL;
37 37
38 if (likely(!inverse)) { 38 if (likely(!inverse)) {
39 return ip_vs_conn_in_get(iph->protocol, 39 return ip_vs_conn_in_get(af, iph->protocol,
40 iph->saddr.ip, pptr[0], 40 &iph->saddr, pptr[0],
41 iph->daddr.ip, pptr[1]); 41 &iph->daddr, pptr[1]);
42 } else { 42 } else {
43 return ip_vs_conn_in_get(iph->protocol, 43 return ip_vs_conn_in_get(af, iph->protocol,
44 iph->daddr.ip, pptr[1], 44 &iph->daddr, pptr[1],
45 iph->saddr.ip, pptr[0]); 45 &iph->saddr, pptr[0]);
46 } 46 }
47} 47}
48 48
@@ -58,13 +58,13 @@ tcp_conn_out_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp,
58 return NULL; 58 return NULL;
59 59
60 if (likely(!inverse)) { 60 if (likely(!inverse)) {
61 return ip_vs_conn_out_get(iph->protocol, 61 return ip_vs_conn_out_get(af, iph->protocol,
62 iph->saddr.ip, pptr[0], 62 &iph->saddr, pptr[0],
63 iph->daddr.ip, pptr[1]); 63 &iph->daddr, pptr[1]);
64 } else { 64 } else {
65 return ip_vs_conn_out_get(iph->protocol, 65 return ip_vs_conn_out_get(af, iph->protocol,
66 iph->daddr.ip, pptr[1], 66 &iph->daddr, pptr[1],
67 iph->saddr.ip, pptr[0]); 67 &iph->saddr, pptr[0]);
68 } 68 }
69} 69}
70 70
diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c
index 6cca0ad8e325..fd8bd934cc02 100644
--- a/net/ipv4/ipvs/ip_vs_proto_udp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_udp.c
@@ -36,13 +36,13 @@ udp_conn_in_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp,
36 return NULL; 36 return NULL;
37 37
38 if (likely(!inverse)) { 38 if (likely(!inverse)) {
39 cp = ip_vs_conn_in_get(iph->protocol, 39 cp = ip_vs_conn_in_get(af, iph->protocol,
40 iph->saddr.ip, pptr[0], 40 &iph->saddr, pptr[0],
41 iph->daddr.ip, pptr[1]); 41 &iph->daddr, pptr[1]);
42 } else { 42 } else {
43 cp = ip_vs_conn_in_get(iph->protocol, 43 cp = ip_vs_conn_in_get(af, iph->protocol,
44 iph->daddr.ip, pptr[1], 44 &iph->daddr, pptr[1],
45 iph->saddr.ip, pptr[0]); 45 &iph->saddr, pptr[0]);
46 } 46 }
47 47
48 return cp; 48 return cp;
@@ -62,13 +62,13 @@ udp_conn_out_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp,
62 return NULL; 62 return NULL;
63 63
64 if (likely(!inverse)) { 64 if (likely(!inverse)) {
65 cp = ip_vs_conn_out_get(iph->protocol, 65 cp = ip_vs_conn_out_get(af, iph->protocol,
66 iph->saddr.ip, pptr[0], 66 &iph->saddr, pptr[0],
67 iph->daddr.ip, pptr[1]); 67 &iph->daddr, pptr[1]);
68 } else { 68 } else {
69 cp = ip_vs_conn_out_get(iph->protocol, 69 cp = ip_vs_conn_out_get(af, iph->protocol,
70 iph->daddr.ip, pptr[1], 70 &iph->daddr, pptr[1],
71 iph->saddr.ip, pptr[0]); 71 &iph->saddr, pptr[0]);
72 } 72 }
73 73
74 return cp; 74 return cp;
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c
index 2cf47b2e1669..3ce1093e0670 100644
--- a/net/ipv4/ipvs/ip_vs_sync.c
+++ b/net/ipv4/ipvs/ip_vs_sync.c
@@ -366,13 +366,17 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
366 } 366 }
367 367
368 if (!(flags & IP_VS_CONN_F_TEMPLATE)) 368 if (!(flags & IP_VS_CONN_F_TEMPLATE))
369 cp = ip_vs_conn_in_get(s->protocol, 369 cp = ip_vs_conn_in_get(AF_INET, s->protocol,
370 s->caddr, s->cport, 370 (union nf_inet_addr *)&s->caddr,
371 s->vaddr, s->vport); 371 s->cport,
372 (union nf_inet_addr *)&s->vaddr,
373 s->vport);
372 else 374 else
373 cp = ip_vs_ct_in_get(s->protocol, 375 cp = ip_vs_ct_in_get(AF_INET, s->protocol,
374 s->caddr, s->cport, 376 (union nf_inet_addr *)&s->caddr,
375 s->vaddr, s->vport); 377 s->cport,
378 (union nf_inet_addr *)&s->vaddr,
379 s->vport);
376 if (!cp) { 380 if (!cp) {
377 /* 381 /*
378 * Find the appropriate destination for the connection. 382 * Find the appropriate destination for the connection.
@@ -389,10 +393,13 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
389 else 393 else
390 flags &= ~IP_VS_CONN_F_INACTIVE; 394 flags &= ~IP_VS_CONN_F_INACTIVE;
391 } 395 }
392 cp = ip_vs_conn_new(s->protocol, 396 cp = ip_vs_conn_new(AF_INET, s->protocol,
393 s->caddr, s->cport, 397 (union nf_inet_addr *)s->caddr,
394 s->vaddr, s->vport, 398 s->cport,
395 s->daddr, s->dport, 399 (union nf_inet_addr *)s->vaddr,
400 s->vport,
401 (union nf_inet_addr *)s->daddr,
402 s->dport,
396 flags, dest); 403 flags, dest);
397 if (dest) 404 if (dest)
398 atomic_dec(&dest->refcnt); 405 atomic_dec(&dest->refcnt);