IPVS: Add struct ip_vs_conn_param
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / netfilter / ipvs / ip_vs_conn.c
index a970d9691496dfb488ce93887e0591e0b6effa60..deeb906a797b22ab8ea4b83209a6fa638637b846 100644 (file)
@@ -218,27 +218,26 @@ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp)
 /*
  *  Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab.
  *  Called for pkts coming from OUTside-to-INside.
- *     s_addr, s_port: pkt source address (foreign host)
- *     d_addr, d_port: pkt dest address (load balancer)
+ *     p->caddr, p->cport: pkt source address (foreign host)
+ *     p->vaddr, p->vport: pkt dest address (load balancer)
  */
-static inline struct ip_vs_conn *__ip_vs_conn_in_get
-(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
- const union nf_inet_addr *d_addr, __be16 d_port)
+static inline struct ip_vs_conn *
+__ip_vs_conn_in_get(const struct ip_vs_conn_param *p)
 {
        unsigned hash;
        struct ip_vs_conn *cp;
 
-       hash = ip_vs_conn_hashkey(af, protocol, s_addr, s_port);
+       hash = ip_vs_conn_hashkey(p->af, p->protocol, p->caddr, p->cport);
 
        ct_read_lock(hash);
 
        list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
-               if (cp->af == af &&
-                   ip_vs_addr_equal(af, s_addr, &cp->caddr) &&
-                   ip_vs_addr_equal(af, d_addr, &cp->vaddr) &&
-                   s_port == cp->cport && d_port == cp->vport &&
-                   ((!s_port) ^ (!(cp->flags & IP_VS_CONN_F_NO_CPORT))) &&
-                   protocol == cp->protocol) {
+               if (cp->af == p->af &&
+                   ip_vs_addr_equal(p->af, p->caddr, &cp->caddr) &&
+                   ip_vs_addr_equal(p->af, p->vaddr, &cp->vaddr) &&
+                   p->cport == cp->cport && p->vport == cp->vport &&
+                   ((!p->cport) ^ (!(cp->flags & IP_VS_CONN_F_NO_CPORT))) &&
+                   p->protocol == cp->protocol) {
                        /* HIT */
                        atomic_inc(&cp->refcnt);
                        ct_read_unlock(hash);
@@ -251,71 +250,82 @@ static inline struct ip_vs_conn *__ip_vs_conn_in_get
        return NULL;
 }
 
-struct ip_vs_conn *ip_vs_conn_in_get
-(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
- const union nf_inet_addr *d_addr, __be16 d_port)
+struct ip_vs_conn *ip_vs_conn_in_get(const struct ip_vs_conn_param *p)
 {
        struct ip_vs_conn *cp;
 
-       cp = __ip_vs_conn_in_get(af, protocol, s_addr, s_port, d_addr, d_port);
-       if (!cp && atomic_read(&ip_vs_conn_no_cport_cnt))
-               cp = __ip_vs_conn_in_get(af, protocol, s_addr, 0, d_addr,
-                                        d_port);
+       cp = __ip_vs_conn_in_get(p);
+       if (!cp && atomic_read(&ip_vs_conn_no_cport_cnt)) {
+               struct ip_vs_conn_param cport_zero_p = *p;
+               cport_zero_p.cport = 0;
+               cp = __ip_vs_conn_in_get(&cport_zero_p);
+       }
 
        IP_VS_DBG_BUF(9, "lookup/in %s %s:%d->%s:%d %s\n",
-                     ip_vs_proto_name(protocol),
-                     IP_VS_DBG_ADDR(af, s_addr), ntohs(s_port),
-                     IP_VS_DBG_ADDR(af, d_addr), ntohs(d_port),
+                     ip_vs_proto_name(p->protocol),
+                     IP_VS_DBG_ADDR(p->af, p->caddr), ntohs(p->cport),
+                     IP_VS_DBG_ADDR(p->af, p->vaddr), ntohs(p->vport),
                      cp ? "hit" : "not hit");
 
        return cp;
 }
 
+static int
+ip_vs_conn_fill_param_proto(int af, const struct sk_buff *skb,
+                           const struct ip_vs_iphdr *iph,
+                           unsigned int proto_off, int inverse,
+                           struct ip_vs_conn_param *p)
+{
+       __be16 _ports[2], *pptr;
+
+       pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
+       if (pptr == NULL)
+               return 1;
+
+       if (likely(!inverse))
+               ip_vs_conn_fill_param(af, iph->protocol, &iph->saddr, pptr[0],
+                                     &iph->daddr, pptr[1], p);
+       else
+               ip_vs_conn_fill_param(af, iph->protocol, &iph->daddr, pptr[1],
+                                     &iph->saddr, pptr[0], p);
+       return 0;
+}
+
 struct ip_vs_conn *
 ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,
                        struct ip_vs_protocol *pp,
                        const struct ip_vs_iphdr *iph,
                        unsigned int proto_off, int inverse)
 {
-       __be16 _ports[2], *pptr;
+       struct ip_vs_conn_param p;
 
-       pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
-       if (pptr == NULL)
+       if (ip_vs_conn_fill_param_proto(af, skb, iph, proto_off, inverse, &p))
                return NULL;
 
-       if (likely(!inverse))
-               return ip_vs_conn_in_get(af, iph->protocol,
-                                        &iph->saddr, pptr[0],
-                                        &iph->daddr, pptr[1]);
-       else
-               return ip_vs_conn_in_get(af, iph->protocol,
-                                        &iph->daddr, pptr[1],
-                                        &iph->saddr, pptr[0]);
+       return ip_vs_conn_in_get(&p);
 }
 EXPORT_SYMBOL_GPL(ip_vs_conn_in_get_proto);
 
 /* Get reference to connection template */
-struct ip_vs_conn *ip_vs_ct_in_get
-(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
- const union nf_inet_addr *d_addr, __be16 d_port)
+struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p)
 {
        unsigned hash;
        struct ip_vs_conn *cp;
 
-       hash = ip_vs_conn_hashkey(af, protocol, s_addr, s_port);
+       hash = ip_vs_conn_hashkey(p->af, p->protocol, p->caddr, p->cport);
 
        ct_read_lock(hash);
 
        list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
-               if (cp->af == af &&
-                   ip_vs_addr_equal(af, s_addr, &cp->caddr) &&
+               if (cp->af == p->af &&
+                   ip_vs_addr_equal(p->af, p->caddr, &cp->caddr) &&
                    /* protocol should only be IPPROTO_IP if
-                    * d_addr is a fwmark */
-                   ip_vs_addr_equal(protocol == IPPROTO_IP ? AF_UNSPEC : af,
-                                    d_addr, &cp->vaddr) &&
-                   s_port == cp->cport && d_port == cp->vport &&
+                    * p->vaddr is a fwmark */
+                   ip_vs_addr_equal(p->protocol == IPPROTO_IP ? AF_UNSPEC :
+                                    p->af, p->vaddr, &cp->vaddr) &&
+                   p->cport == cp->cport && p->vport == cp->vport &&
                    cp->flags & IP_VS_CONN_F_TEMPLATE &&
-                   protocol == cp->protocol) {
+                   p->protocol == cp->protocol) {
                        /* HIT */
                        atomic_inc(&cp->refcnt);
                        goto out;
@@ -327,23 +337,19 @@ struct ip_vs_conn *ip_vs_ct_in_get
        ct_read_unlock(hash);
 
        IP_VS_DBG_BUF(9, "template lookup/in %s %s:%d->%s:%d %s\n",
-                     ip_vs_proto_name(protocol),
-                     IP_VS_DBG_ADDR(af, s_addr), ntohs(s_port),
-                     IP_VS_DBG_ADDR(af, d_addr), ntohs(d_port),
+                     ip_vs_proto_name(p->protocol),
+                     IP_VS_DBG_ADDR(p->af, p->caddr), ntohs(p->cport),
+                     IP_VS_DBG_ADDR(p->af, p->vaddr), ntohs(p->vport),
                      cp ? "hit" : "not hit");
 
        return cp;
 }
 
-/*
- *  Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab.
- *  Called for pkts coming from inside-to-OUTside.
- *     s_addr, s_port: pkt source address (inside host)
- *     d_addr, d_port: pkt dest address (foreign host)
- */
-struct ip_vs_conn *ip_vs_conn_out_get
-(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
- const union nf_inet_addr *d_addr, __be16 d_port)
+/* Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab.
+ * Called for pkts coming from inside-to-OUTside.
+ *     p->caddr, p->cport: pkt source address (inside host)
+ *     p->vaddr, p->vport: pkt dest address (foreign host) */
+struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p)
 {
        unsigned hash;
        struct ip_vs_conn *cp, *ret=NULL;
@@ -351,16 +357,16 @@ struct ip_vs_conn *ip_vs_conn_out_get
        /*
         *      Check for "full" addressed entries
         */
-       hash = ip_vs_conn_hashkey(af, protocol, d_addr, d_port);
+       hash = ip_vs_conn_hashkey(p->af, p->protocol, p->vaddr, p->vport);
 
        ct_read_lock(hash);
 
        list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
-               if (cp->af == af &&
-                   ip_vs_addr_equal(af, d_addr, &cp->caddr) &&
-                   ip_vs_addr_equal(af, s_addr, &cp->daddr) &&
-                   d_port == cp->cport && s_port == cp->dport &&
-                   protocol == cp->protocol) {
+               if (cp->af == p->af &&
+                   ip_vs_addr_equal(p->af, p->vaddr, &cp->caddr) &&
+                   ip_vs_addr_equal(p->af, p->caddr, &cp->daddr) &&
+                   p->vport == cp->cport && p->cport == cp->dport &&
+                   p->protocol == cp->protocol) {
                        /* HIT */
                        atomic_inc(&cp->refcnt);
                        ret = cp;
@@ -371,9 +377,9 @@ struct ip_vs_conn *ip_vs_conn_out_get
        ct_read_unlock(hash);
 
        IP_VS_DBG_BUF(9, "lookup/out %s %s:%d->%s:%d %s\n",
-                     ip_vs_proto_name(protocol),
-                     IP_VS_DBG_ADDR(af, s_addr), ntohs(s_port),
-                     IP_VS_DBG_ADDR(af, d_addr), ntohs(d_port),
+                     ip_vs_proto_name(p->protocol),
+                     IP_VS_DBG_ADDR(p->af, p->caddr), ntohs(p->cport),
+                     IP_VS_DBG_ADDR(p->af, p->vaddr), ntohs(p->vport),
                      ret ? "hit" : "not hit");
 
        return ret;
@@ -385,20 +391,12 @@ ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb,
                         const struct ip_vs_iphdr *iph,
                         unsigned int proto_off, int inverse)
 {
-       __be16 _ports[2], *pptr;
+       struct ip_vs_conn_param p;
 
-       pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
-       if (pptr == NULL)
+       if (ip_vs_conn_fill_param_proto(af, skb, iph, proto_off, inverse, &p))
                return NULL;
 
-       if (likely(!inverse))
-               return ip_vs_conn_out_get(af, iph->protocol,
-                                         &iph->saddr, pptr[0],
-                                         &iph->daddr, pptr[1]);
-       else
-               return ip_vs_conn_out_get(af, iph->protocol,
-                                         &iph->daddr, pptr[1],
-                                         &iph->saddr, pptr[0]);
+       return ip_vs_conn_out_get(&p);
 }
 EXPORT_SYMBOL_GPL(ip_vs_conn_out_get_proto);
 
@@ -758,13 +756,12 @@ void ip_vs_conn_expire_now(struct ip_vs_conn *cp)
  *     Create a new connection entry and hash it into the ip_vs_conn_tab
  */
 struct ip_vs_conn *
-ip_vs_conn_new(int af, int proto, const union nf_inet_addr *caddr, __be16 cport,
-              const union nf_inet_addr *vaddr, __be16 vport,
+ip_vs_conn_new(const struct ip_vs_conn_param *p,
               const union nf_inet_addr *daddr, __be16 dport, unsigned flags,
               struct ip_vs_dest *dest)
 {
        struct ip_vs_conn *cp;
-       struct ip_vs_protocol *pp = ip_vs_proto_get(proto);
+       struct ip_vs_protocol *pp = ip_vs_proto_get(p->protocol);
 
        cp = kmem_cache_zalloc(ip_vs_conn_cachep, GFP_ATOMIC);
        if (cp == NULL) {
@@ -774,14 +771,14 @@ ip_vs_conn_new(int af, int proto, const union nf_inet_addr *caddr, __be16 cport,
 
        INIT_LIST_HEAD(&cp->c_list);
        setup_timer(&cp->timer, ip_vs_conn_expire, (unsigned long)cp);
-       cp->af             = af;
-       cp->protocol       = proto;
-       ip_vs_addr_copy(af, &cp->caddr, caddr);
-       cp->cport          = cport;
-       ip_vs_addr_copy(af, &cp->vaddr, vaddr);
-       cp->vport          = vport;
+       cp->af             = p->af;
+       cp->protocol       = p->protocol;
+       ip_vs_addr_copy(p->af, &cp->caddr, p->caddr);
+       cp->cport          = p->cport;
+       ip_vs_addr_copy(p->af, &cp->vaddr, p->vaddr);
+       cp->vport          = p->vport;
        /* proto should only be IPPROTO_IP if d_addr is a fwmark */
-       ip_vs_addr_copy(proto == IPPROTO_IP ? AF_UNSPEC : af,
+       ip_vs_addr_copy(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af,
                        &cp->daddr, daddr);
        cp->dport          = dport;
        cp->flags          = flags;
@@ -810,7 +807,7 @@ ip_vs_conn_new(int af, int proto, const union nf_inet_addr *caddr, __be16 cport,
 
        /* Bind its packet transmitter */
 #ifdef CONFIG_IP_VS_IPV6
-       if (af == AF_INET6)
+       if (p->af == AF_INET6)
                ip_vs_bind_xmit_v6(cp);
        else
 #endif