On Sat, Jun 02, 2018 at 09:50:01PM +0300, Julian Anastasov wrote: > cp->state was not used for templates. Add support for state bits > and for the first "assured" bit which indicates that some > connection controlled by this template was established or assured > by the real server. In a followup patch we will use it to drop > templates under SYN attack. > > Signed-off-by: Julian Anastasov <ja@xxxxxx> > --- > include/net/ip_vs.h | 7 ++++++- > net/netfilter/ipvs/ip_vs_conn.c | 8 ++++---- > net/netfilter/ipvs/ip_vs_proto.c | 19 ++++++++++++++++--- > net/netfilter/ipvs/ip_vs_proto_sctp.c | 7 +++++++ > net/netfilter/ipvs/ip_vs_proto_tcp.c | 7 +++++++ > net/netfilter/ipvs/ip_vs_proto_udp.c | 7 +++++++ > net/netfilter/ipvs/ip_vs_sync.c | 18 ++++++++---------- > 7 files changed, 55 insertions(+), 18 deletions(-) > > diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h > index 824d7ef..d786649 100644 > --- a/include/net/ip_vs.h > +++ b/include/net/ip_vs.h > @@ -347,6 +347,11 @@ enum ip_vs_sctp_states { > IP_VS_SCTP_S_LAST > }; > > +/* Connection templates use bits from state */ > +#define IP_VS_CTPL_S_NONE 0x0000 > +#define IP_VS_CTPL_S_ASSURED 0x0001 > +#define IP_VS_CTPL_S_LAST 0x0002 > + > /* Delta sequence info structure > * Each ip_vs_conn has 2 (output AND input seq. changes). > * Only used in the VS/NAT. > @@ -1232,7 +1237,7 @@ struct ip_vs_conn *ip_vs_conn_new(const struct ip_vs_conn_param *p, int dest_af, > struct ip_vs_dest *dest, __u32 fwmark); > void ip_vs_conn_expire_now(struct ip_vs_conn *cp); > > -const char *ip_vs_state_name(__u16 proto, int state); > +const char *ip_vs_state_name(const struct ip_vs_conn *cp); > > void ip_vs_tcp_conn_listen(struct ip_vs_conn *cp); > int ip_vs_check_template(struct ip_vs_conn *ct, struct ip_vs_dest *cdest); > diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c > index 75de465..8f76644 100644 > --- a/net/netfilter/ipvs/ip_vs_conn.c > +++ b/net/netfilter/ipvs/ip_vs_conn.c > @@ -1107,7 +1107,7 @@ static int ip_vs_conn_seq_show(struct seq_file *seq, void *v) > &cp->caddr.in6, ntohs(cp->cport), > &cp->vaddr.in6, ntohs(cp->vport), > dbuf, ntohs(cp->dport), > - ip_vs_state_name(cp->protocol, cp->state), > + ip_vs_state_name(cp), > (cp->timer.expires-jiffies)/HZ, pe_data); > else > #endif > @@ -1118,7 +1118,7 @@ static int ip_vs_conn_seq_show(struct seq_file *seq, void *v) > ntohl(cp->caddr.ip), ntohs(cp->cport), > ntohl(cp->vaddr.ip), ntohs(cp->vport), > dbuf, ntohs(cp->dport), > - ip_vs_state_name(cp->protocol, cp->state), > + ip_vs_state_name(cp), > (cp->timer.expires-jiffies)/HZ, pe_data); > } > return 0; > @@ -1182,7 +1182,7 @@ static int ip_vs_conn_sync_seq_show(struct seq_file *seq, void *v) > &cp->caddr.in6, ntohs(cp->cport), > &cp->vaddr.in6, ntohs(cp->vport), > dbuf, ntohs(cp->dport), > - ip_vs_state_name(cp->protocol, cp->state), > + ip_vs_state_name(cp), > ip_vs_origin_name(cp->flags), > (cp->timer.expires-jiffies)/HZ); > else > @@ -1194,7 +1194,7 @@ static int ip_vs_conn_sync_seq_show(struct seq_file *seq, void *v) > ntohl(cp->caddr.ip), ntohs(cp->cport), > ntohl(cp->vaddr.ip), ntohs(cp->vport), > dbuf, ntohs(cp->dport), > - ip_vs_state_name(cp->protocol, cp->state), > + ip_vs_state_name(cp), > ip_vs_origin_name(cp->flags), > (cp->timer.expires-jiffies)/HZ); > } > diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c > index ca880a3..ae7d786 100644 > --- a/net/netfilter/ipvs/ip_vs_proto.c > +++ b/net/netfilter/ipvs/ip_vs_proto.c > @@ -42,6 +42,11 @@ > > static struct ip_vs_protocol *ip_vs_proto_table[IP_VS_PROTO_TAB_SIZE]; > > +/* States for conn templates: NONE or letters separated with "," */ > +static const char *ip_vs_ctpl_state_name_table[IP_VS_CTPL_S_LAST] = { > + [IP_VS_CTPL_S_NONE] = "NONE", > + [IP_VS_CTPL_S_ASSURED] = "A", "A" seems a bit cryptic, why not "ASSURED" ? > +}; > > /* > * register an ipvs protocol > @@ -193,12 +198,20 @@ ip_vs_create_timeout_table(int *table, int size) > } > > > -const char * ip_vs_state_name(__u16 proto, int state) > +const char *ip_vs_state_name(const struct ip_vs_conn *cp) > { > - struct ip_vs_protocol *pp = ip_vs_proto_get(proto); > + unsigned int state = cp->state; > + struct ip_vs_protocol *pp; > + > + if (cp->flags & IP_VS_CONN_F_TEMPLATE) { > > + if (state >= IP_VS_CTPL_S_LAST) > + return "ERR!"; > + return ip_vs_ctpl_state_name_table[state] ? : "?"; > + } > + pp = ip_vs_proto_get(cp->protocol); > if (pp == NULL || pp->state_name == NULL) > - return (IPPROTO_IP == proto) ? "NONE" : "ERR!"; > + return (cp->protocol == IPPROTO_IP) ? "NONE" : "ERR!"; > return pp->state_name(state); > } I'd slightly prefer if refactoring ip_vs_state_name to not take a state parameter was a separate patch. Its a nice cleanup. But it doesn't seem related to the rest of what is going on here. > > diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c > index 3250c4a1..13826ee 100644 > --- a/net/netfilter/ipvs/ip_vs_proto_sctp.c > +++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c > @@ -461,6 +461,13 @@ set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp, > cp->flags &= ~IP_VS_CONN_F_INACTIVE; > } > } > + if (next_state == IP_VS_SCTP_S_ESTABLISHED) { > + struct ip_vs_conn *ct = cp->control; > + > + if (ct && (ct->flags & IP_VS_CONN_F_TEMPLATE) && > + !(ct->state & IP_VS_CTPL_S_ASSURED)) > + ct->state |= IP_VS_CTPL_S_ASSURED; > + } The logic above seems to be replicated several times below. Could we have a helper function? > } > if (likely(pd)) > cp->timeout = pd->timeout_table[cp->state = next_state]; > diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c b/net/netfilter/ipvs/ip_vs_proto_tcp.c > index b73fe6e..467a69e 100644 > --- a/net/netfilter/ipvs/ip_vs_proto_tcp.c > +++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c > @@ -569,6 +569,13 @@ set_tcp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp, > cp->flags &= ~IP_VS_CONN_F_INACTIVE; > } > } > + if (new_state == IP_VS_TCP_S_ESTABLISHED) { > + struct ip_vs_conn *ct = cp->control; > + > + if (ct && (ct->flags & IP_VS_CONN_F_TEMPLATE) && > + !(ct->state & IP_VS_CTPL_S_ASSURED)) > + ct->state |= IP_VS_CTPL_S_ASSURED; > + } > } > > if (likely(pd)) > diff --git a/net/netfilter/ipvs/ip_vs_proto_udp.c b/net/netfilter/ipvs/ip_vs_proto_udp.c > index e0ef11c..c733ed6 100644 > --- a/net/netfilter/ipvs/ip_vs_proto_udp.c > +++ b/net/netfilter/ipvs/ip_vs_proto_udp.c > @@ -460,6 +460,13 @@ udp_state_transition(struct ip_vs_conn *cp, int direction, > } > > cp->timeout = pd->timeout_table[IP_VS_UDP_S_NORMAL]; > + if (direction == IP_VS_DIR_OUTPUT) { > + struct ip_vs_conn *ct = cp->control; > + > + if (ct && (ct->flags & IP_VS_CONN_F_TEMPLATE) && > + !(ct->state & IP_VS_CTPL_S_ASSURED)) > + ct->state |= IP_VS_CTPL_S_ASSURED; > + } > } > > static int __udp_init(struct netns_ipvs *ipvs, struct ip_vs_proto_data *pd) > diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c > index 001501e..24891bd 100644 > --- a/net/netfilter/ipvs/ip_vs_sync.c > +++ b/net/netfilter/ipvs/ip_vs_sync.c > @@ -1003,11 +1003,10 @@ static void ip_vs_process_message_v0(struct netns_ipvs *ipvs, const char *buffer > continue; > } > } else { > - /* protocol in templates is not used for state/timeout */ > - if (state > 0) { > - IP_VS_DBG(2, "BACKUP v0, Invalid template state %u\n", > - state); > - state = 0; > + if (state >= IP_VS_CTPL_S_LAST) { > + IP_VS_DBG(7, "BACKUP v0, Invalid tpl state %u\n", > + state); Not strictly related to this patch, but should these debug messages be rate limited in some way? > + state &= IP_VS_CTPL_S_LAST - 1; > } > } > > @@ -1166,11 +1165,10 @@ static inline int ip_vs_proc_sync_conn(struct netns_ipvs *ipvs, __u8 *p, __u8 *m > goto out; > } > } else { > - /* protocol in templates is not used for state/timeout */ > - if (state > 0) { > - IP_VS_DBG(3, "BACKUP, Invalid template state %u\n", > - state); > - state = 0; > + if (state >= IP_VS_CTPL_S_LAST) { > + IP_VS_DBG(7, "BACKUP, Invalid tpl state %u\n", > + state); > + state &= IP_VS_CTPL_S_LAST - 1; > } > } > if (ip_vs_conn_fill_param_sync(ipvs, af, s, ¶m, pe_data, > -- > 2.9.5 > -- To unsubscribe from this list: send the line "unsubscribe lvs-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html