mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 14:42:24 +00:00
Merge tag 'ipvs-fixes-for-v4.5' of https://git.kernel.org/pub/scm/linux/kernel/git/horms/ipvs
Simon Horman says: ==================== please consider these IPVS fixes for v4.5 or if it is too late please consider them for v4.6. * Arnd Bergman has corrected an error whereby the SIP persistence engine may incorrectly access protocol fields * Julian Anastasov has corrected a problem reported by Jiri Bohac with the connection rescheduling mechanism added in 3.10 when new SYNs in connection to dead real server can be redirected to another real server. * Marco Angaroni resolved a problem in the SIP persistence engine whereby the Call-ID could not be found if it was at the beginning of a SIP message. ==================== Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
commit
d387eaf51f
@ -1588,6 +1588,23 @@ static inline void ip_vs_conn_drop_conntrack(struct ip_vs_conn *cp)
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_IP_VS_NFCT */
|
#endif /* CONFIG_IP_VS_NFCT */
|
||||||
|
|
||||||
|
/* Really using conntrack? */
|
||||||
|
static inline bool ip_vs_conn_uses_conntrack(struct ip_vs_conn *cp,
|
||||||
|
struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_IP_VS_NFCT
|
||||||
|
enum ip_conntrack_info ctinfo;
|
||||||
|
struct nf_conn *ct;
|
||||||
|
|
||||||
|
if (!(cp->flags & IP_VS_CONN_F_NFCT))
|
||||||
|
return false;
|
||||||
|
ct = nf_ct_get(skb, &ctinfo);
|
||||||
|
if (ct && !nf_ct_is_untracked(ct))
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
ip_vs_dest_conn_overhead(struct ip_vs_dest *dest)
|
ip_vs_dest_conn_overhead(struct ip_vs_dest *dest)
|
||||||
{
|
{
|
||||||
|
@ -1089,6 +1089,7 @@ static inline bool is_new_conn_expected(const struct ip_vs_conn *cp,
|
|||||||
switch (cp->protocol) {
|
switch (cp->protocol) {
|
||||||
case IPPROTO_TCP:
|
case IPPROTO_TCP:
|
||||||
return (cp->state == IP_VS_TCP_S_TIME_WAIT) ||
|
return (cp->state == IP_VS_TCP_S_TIME_WAIT) ||
|
||||||
|
(cp->state == IP_VS_TCP_S_CLOSE) ||
|
||||||
((conn_reuse_mode & 2) &&
|
((conn_reuse_mode & 2) &&
|
||||||
(cp->state == IP_VS_TCP_S_FIN_WAIT) &&
|
(cp->state == IP_VS_TCP_S_FIN_WAIT) &&
|
||||||
(cp->flags & IP_VS_CONN_F_NOOUTPUT));
|
(cp->flags & IP_VS_CONN_F_NOOUTPUT));
|
||||||
@ -1757,15 +1758,34 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int
|
|||||||
cp = pp->conn_in_get(ipvs, af, skb, &iph);
|
cp = pp->conn_in_get(ipvs, af, skb, &iph);
|
||||||
|
|
||||||
conn_reuse_mode = sysctl_conn_reuse_mode(ipvs);
|
conn_reuse_mode = sysctl_conn_reuse_mode(ipvs);
|
||||||
if (conn_reuse_mode && !iph.fragoffs &&
|
if (conn_reuse_mode && !iph.fragoffs && is_new_conn(skb, &iph) && cp) {
|
||||||
is_new_conn(skb, &iph) && cp &&
|
bool uses_ct = false, resched = false;
|
||||||
((unlikely(sysctl_expire_nodest_conn(ipvs)) && cp->dest &&
|
|
||||||
unlikely(!atomic_read(&cp->dest->weight))) ||
|
if (unlikely(sysctl_expire_nodest_conn(ipvs)) && cp->dest &&
|
||||||
unlikely(is_new_conn_expected(cp, conn_reuse_mode)))) {
|
unlikely(!atomic_read(&cp->dest->weight))) {
|
||||||
if (!atomic_read(&cp->n_control))
|
resched = true;
|
||||||
ip_vs_conn_expire_now(cp);
|
uses_ct = ip_vs_conn_uses_conntrack(cp, skb);
|
||||||
__ip_vs_conn_put(cp);
|
} else if (is_new_conn_expected(cp, conn_reuse_mode)) {
|
||||||
cp = NULL;
|
uses_ct = ip_vs_conn_uses_conntrack(cp, skb);
|
||||||
|
if (!atomic_read(&cp->n_control)) {
|
||||||
|
resched = true;
|
||||||
|
} else {
|
||||||
|
/* Do not reschedule controlling connection
|
||||||
|
* that uses conntrack while it is still
|
||||||
|
* referenced by controlled connection(s).
|
||||||
|
*/
|
||||||
|
resched = !uses_ct;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resched) {
|
||||||
|
if (!atomic_read(&cp->n_control))
|
||||||
|
ip_vs_conn_expire_now(cp);
|
||||||
|
__ip_vs_conn_put(cp);
|
||||||
|
if (uses_ct)
|
||||||
|
return NF_DROP;
|
||||||
|
cp = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(!cp)) {
|
if (unlikely(!cp)) {
|
||||||
|
@ -70,10 +70,10 @@ ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb)
|
|||||||
const char *dptr;
|
const char *dptr;
|
||||||
int retc;
|
int retc;
|
||||||
|
|
||||||
ip_vs_fill_iph_skb(p->af, skb, false, &iph);
|
retc = ip_vs_fill_iph_skb(p->af, skb, false, &iph);
|
||||||
|
|
||||||
/* Only useful with UDP */
|
/* Only useful with UDP */
|
||||||
if (iph.protocol != IPPROTO_UDP)
|
if (!retc || iph.protocol != IPPROTO_UDP)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
/* todo: IPv6 fragments:
|
/* todo: IPv6 fragments:
|
||||||
* I think this only should be done for the first fragment. /HS
|
* I think this only should be done for the first fragment. /HS
|
||||||
@ -88,7 +88,7 @@ ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb)
|
|||||||
dptr = skb->data + dataoff;
|
dptr = skb->data + dataoff;
|
||||||
datalen = skb->len - dataoff;
|
datalen = skb->len - dataoff;
|
||||||
|
|
||||||
if (get_callid(dptr, dataoff, datalen, &matchoff, &matchlen))
|
if (get_callid(dptr, 0, datalen, &matchoff, &matchlen))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* N.B: pe_data is only set on success,
|
/* N.B: pe_data is only set on success,
|
||||||
|
@ -242,6 +242,9 @@ nfacct_filter_alloc(const struct nlattr * const attr)
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
|
|
||||||
|
if (!tb[NFACCT_FILTER_MASK] || !tb[NFACCT_FILTER_VALUE])
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
filter = kzalloc(sizeof(struct nfacct_filter), GFP_KERNEL);
|
filter = kzalloc(sizeof(struct nfacct_filter), GFP_KERNEL);
|
||||||
if (!filter)
|
if (!filter)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
Loading…
Reference in New Issue
Block a user