mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-04 09:59:32 +00:00
ipvs: Make ip_vs_schedule aware of inverse iph'es
This is necessary to schedule icmp later. Signed-off-by: Alex Gartrell <agartrell@fb.com> Acked-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: Simon Horman <horms@verge.net.au>
This commit is contained in:
parent
802c41adcf
commit
ee78378f97
1 changed files with 36 additions and 14 deletions
|
@ -245,20 +245,30 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
|
|||
const union nf_inet_addr fwmark = { .ip = htonl(svc->fwmark) };
|
||||
union nf_inet_addr snet; /* source network of the client,
|
||||
after masking */
|
||||
const union nf_inet_addr *src_addr, *dst_addr;
|
||||
|
||||
if (likely(!ip_vs_iph_inverse(iph))) {
|
||||
src_addr = &iph->saddr;
|
||||
dst_addr = &iph->daddr;
|
||||
} else {
|
||||
src_addr = &iph->daddr;
|
||||
dst_addr = &iph->saddr;
|
||||
}
|
||||
|
||||
|
||||
/* Mask saddr with the netmask to adjust template granularity */
|
||||
#ifdef CONFIG_IP_VS_IPV6
|
||||
if (svc->af == AF_INET6)
|
||||
ipv6_addr_prefix(&snet.in6, &iph->saddr.in6,
|
||||
ipv6_addr_prefix(&snet.in6, &src_addr->in6,
|
||||
(__force __u32) svc->netmask);
|
||||
else
|
||||
#endif
|
||||
snet.ip = iph->saddr.ip & svc->netmask;
|
||||
snet.ip = src_addr->ip & svc->netmask;
|
||||
|
||||
IP_VS_DBG_BUF(6, "p-schedule: src %s:%u dest %s:%u "
|
||||
"mnet %s\n",
|
||||
IP_VS_DBG_ADDR(svc->af, &iph->saddr), ntohs(src_port),
|
||||
IP_VS_DBG_ADDR(svc->af, &iph->daddr), ntohs(dst_port),
|
||||
IP_VS_DBG_ADDR(svc->af, src_addr), ntohs(src_port),
|
||||
IP_VS_DBG_ADDR(svc->af, dst_addr), ntohs(dst_port),
|
||||
IP_VS_DBG_ADDR(svc->af, &snet));
|
||||
|
||||
/*
|
||||
|
@ -276,7 +286,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
|
|||
*/
|
||||
{
|
||||
int protocol = iph->protocol;
|
||||
const union nf_inet_addr *vaddr = &iph->daddr;
|
||||
const union nf_inet_addr *vaddr = dst_addr;
|
||||
__be16 vport = 0;
|
||||
|
||||
if (dst_port == svc->port) {
|
||||
|
@ -366,8 +376,8 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
|
|||
/*
|
||||
* Create a new connection according to the template
|
||||
*/
|
||||
ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol, &iph->saddr,
|
||||
src_port, &iph->daddr, dst_port, ¶m);
|
||||
ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol, src_addr,
|
||||
src_port, dst_addr, dst_port, ¶m);
|
||||
|
||||
cp = ip_vs_conn_new(¶m, dest->af, &dest->addr, dport, flags, dest,
|
||||
skb->mark);
|
||||
|
@ -418,7 +428,8 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
|
|||
struct ip_vs_conn *cp = NULL;
|
||||
struct ip_vs_scheduler *sched;
|
||||
struct ip_vs_dest *dest;
|
||||
__be16 _ports[2], *pptr;
|
||||
__be16 _ports[2], *pptr, cport, vport;
|
||||
const void *caddr, *vaddr;
|
||||
unsigned int flags;
|
||||
|
||||
*ignored = 1;
|
||||
|
@ -429,13 +440,25 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
|
|||
if (pptr == NULL)
|
||||
return NULL;
|
||||
|
||||
if (likely(!ip_vs_iph_inverse(iph))) {
|
||||
cport = pptr[0];
|
||||
caddr = &iph->saddr;
|
||||
vport = pptr[1];
|
||||
vaddr = &iph->daddr;
|
||||
} else {
|
||||
cport = pptr[1];
|
||||
caddr = &iph->daddr;
|
||||
vport = pptr[0];
|
||||
vaddr = &iph->saddr;
|
||||
}
|
||||
|
||||
/*
|
||||
* FTPDATA needs this check when using local real server.
|
||||
* Never schedule Active FTPDATA connections from real server.
|
||||
* For LVS-NAT they must be already created. For other methods
|
||||
* with persistence the connection is created on SYN+ACK.
|
||||
*/
|
||||
if (pptr[0] == FTPDATA) {
|
||||
if (cport == FTPDATA) {
|
||||
IP_VS_DBG_PKT(12, svc->af, pp, skb, iph->off,
|
||||
"Not scheduling FTPDATA");
|
||||
return NULL;
|
||||
|
@ -462,7 +485,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
|
|||
* Persistent service
|
||||
*/
|
||||
if (svc->flags & IP_VS_SVC_F_PERSISTENT)
|
||||
return ip_vs_sched_persist(svc, skb, pptr[0], pptr[1], ignored,
|
||||
return ip_vs_sched_persist(svc, skb, cport, vport, ignored,
|
||||
iph);
|
||||
|
||||
*ignored = 0;
|
||||
|
@ -470,7 +493,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
|
|||
/*
|
||||
* Non-persistent service
|
||||
*/
|
||||
if (!svc->fwmark && pptr[1] != svc->port) {
|
||||
if (!svc->fwmark && vport != svc->port) {
|
||||
if (!svc->port)
|
||||
pr_err("Schedule: port zero only supported "
|
||||
"in persistent services, "
|
||||
|
@ -502,10 +525,9 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
|
|||
struct ip_vs_conn_param p;
|
||||
|
||||
ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol,
|
||||
&iph->saddr, pptr[0], &iph->daddr,
|
||||
pptr[1], &p);
|
||||
caddr, cport, vaddr, vport, &p);
|
||||
cp = ip_vs_conn_new(&p, dest->af, &dest->addr,
|
||||
dest->port ? dest->port : pptr[1],
|
||||
dest->port ? dest->port : vport,
|
||||
flags, dest, skb->mark);
|
||||
if (!cp) {
|
||||
*ignored = -1;
|
||||
|
|
Loading…
Reference in a new issue