integrated
[ipfw.git] / dummynet2 / ip_fw_nat.c
index ead46a7..41fe919 100644 (file)
@@ -55,7 +55,7 @@ __FBSDID("$FreeBSD: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_nat.c 200975 20
 static VNET_DEFINE(eventhandler_tag, ifaddr_event_tag);
 #define        V_ifaddr_event_tag      VNET(ifaddr_event_tag)
 
-static void 
+static void
 ifaddr_change(void *arg __unused, struct ifnet *ifp)
 {
        struct cfg_nat *ptr;
@@ -69,18 +69,18 @@ ifaddr_change(void *arg __unused, struct ifnet *ifp)
                /* ...using nic 'ifp->if_xname' as dynamic alias address. */
                if (strncmp(ptr->if_name, ifp->if_xname, IF_NAMESIZE) != 0)
                        continue;
-                       if_addr_rlock(ifp);
-                       TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
-                               if (ifa->ifa_addr == NULL)
-                                       continue;
-                               if (ifa->ifa_addr->sa_family != AF_INET)
-                                       continue;
-                               ptr->ip = ((struct sockaddr_in *) 
-                                   (ifa->ifa_addr))->sin_addr;
-                               LibAliasSetAddress(ptr->lib, ptr->ip);
-                       }
-                       if_addr_runlock(ifp);
+               if_addr_rlock(ifp);
+               TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+                       if (ifa->ifa_addr == NULL)
+                               continue;
+                       if (ifa->ifa_addr->sa_family != AF_INET)
+                               continue;
+                       ptr->ip = ((struct sockaddr_in *)
+                           (ifa->ifa_addr))->sin_addr;
+                       LibAliasSetAddress(ptr->lib, ptr->ip);
                }
+               if_addr_runlock(ifp);
+       }
        IPFW_WUNLOCK(chain);
 }
 
@@ -131,9 +131,9 @@ del_redir_spool_cfg(struct cfg_nat *n, struct redir_chain *head)
                        free(r, M_IPFW);
                        break;
                default:
-                       printf("unknown redirect mode: %u\n", r->mode);                         
+                       printf("unknown redirect mode: %u\n", r->mode);
                        /* XXX - panic?!?!? */
-                       break; 
+                       break;
                }
        }
 }
@@ -166,7 +166,7 @@ add_redir_spool_cfg(char *buf, struct cfg_nat *ptr)
                                        remotePortCopy = 0;
                                r->alink[i] = LibAliasRedirectPort(ptr->lib,
                                    r->laddr, htons(r->lport + i), r->raddr,
-                                   htons(remotePortCopy), r->paddr, 
+                                   htons(remotePortCopy), r->paddr,
                                    htons(r->pport + i), r->proto);
                                if (r->alink[i] == NULL) {
                                        r->alink[0] = NULL;
@@ -180,22 +180,22 @@ add_redir_spool_cfg(char *buf, struct cfg_nat *ptr)
                        break;
                default:
                        printf("unknown redirect mode: %u\n", r->mode);
-                       break; 
+                       break;
                }
                /* XXX perhaps return an error instead of panic ? */
                if (r->alink[0] == NULL)
                        panic("LibAliasRedirect* returned NULL");
                /* LSNAT handling. */
-                       for (i = 0; i < r->spool_cnt; i++) {
-                               ser_s = (struct cfg_spool *)&buf[off];
+               for (i = 0; i < r->spool_cnt; i++) {
+                       ser_s = (struct cfg_spool *)&buf[off];
                        s = malloc(SOF_REDIR, M_IPFW, M_WAITOK | M_ZERO);
-                               memcpy(s, ser_s, SOF_SPOOL);
-                               LibAliasAddServer(ptr->lib, r->alink[0], 
-                                   s->addr, htons(s->port));
-                               off += SOF_SPOOL;
-                               /* Hook spool entry. */
+                       memcpy(s, ser_s, SOF_SPOOL);
+                       LibAliasAddServer(ptr->lib, r->alink[0],
+                           s->addr, htons(s->port));
+                       off += SOF_SPOOL;
+                       /* Hook spool entry. */
                        LIST_INSERT_HEAD(&r->spool_chain, s, _next);
-                       }
+               }
                /* And finally hook this redir entry. */
                LIST_INSERT_HEAD(&ptr->redir_chain, r, _next);
        }
@@ -220,9 +220,9 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m)
        }
        ip = mtod(mcl, struct ip *);
 
-       /* 
+       /*
         * XXX - Libalias checksum offload 'duct tape':
-        * 
+        *
         * locally generated packets have only pseudo-header checksum
         * calculated and libalias will break it[1], so mark them for
         * later fix.  Moreover there are cases when libalias modifies
@@ -252,20 +252,20 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m)
         * it can handle delayed checksum and tso)
         */
 
-       if (mcl->m_pkthdr.rcvif == NULL && 
+       if (mcl->m_pkthdr.rcvif == NULL &&
            mcl->m_pkthdr.csum_flags & CSUM_DELAY_DATA)
                ldt = 1;
 
        c = mtod(mcl, char *);
        if (args->oif == NULL)
-               retval = LibAliasIn(t->lib, c, 
+               retval = LibAliasIn(t->lib, c,
                        mcl->m_len + M_TRAILINGSPACE(mcl));
        else
-               retval = LibAliasOut(t->lib, c, 
+               retval = LibAliasOut(t->lib, c,
                        mcl->m_len + M_TRAILINGSPACE(mcl));
        if (retval == PKT_ALIAS_RESPOND) {
-         m->m_flags |= M_SKIP_FIREWALL;
-         retval = PKT_ALIAS_OK;
+               m->m_flags |= M_SKIP_FIREWALL;
+               retval = PKT_ALIAS_OK;
        }
        if (retval != PKT_ALIAS_OK &&
            retval != PKT_ALIAS_FOUND_HEADER_FRAGMENT) {
@@ -276,17 +276,17 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m)
        }
        mcl->m_pkthdr.len = mcl->m_len = ntohs(ip->ip_len);
 
-       /* 
-        * XXX - libalias checksum offload 
-        * 'duct tape' (see above) 
+       /*
+        * XXX - libalias checksum offload
+        * 'duct tape' (see above)
         */
 
-       if ((ip->ip_off & htons(IP_OFFMASK)) == 0 && 
+       if ((ip->ip_off & htons(IP_OFFMASK)) == 0 &&
            ip->ip_p == IPPROTO_TCP) {
-               struct tcphdr   *th; 
+               struct tcphdr   *th;
 
                th = (struct tcphdr *)(ip + 1);
-               if (th->th_x2) 
+               if (th->th_x2)
                        ldt = 1;
        }
 
@@ -295,37 +295,35 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m)
                struct udphdr   *uh;
                u_short cksum;
 
-               /* XXX check if ip_len can stay in net format */
-               cksum = in_pseudo(
-                   ip->ip_src.s_addr,
-                   ip->ip_dst.s_addr, 
-                   htons(ip->ip_p + ntohs(ip->ip_len) - (ip->ip_hl << 2))
-               );
-                                       
+               ip->ip_len = ntohs(ip->ip_len);
+               cksum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
+                   htons(ip->ip_p + ip->ip_len - (ip->ip_hl << 2)));
+
                switch (ip->ip_p) {
                case IPPROTO_TCP:
                        th = (struct tcphdr *)(ip + 1);
-                       /* 
-                        * Maybe it was set in 
-                        * libalias... 
+                       /*
+                        * Maybe it was set in
+                        * libalias...
                         */
                        th->th_x2 = 0;
                        th->th_sum = cksum;
-                       mcl->m_pkthdr.csum_data = 
+                       mcl->m_pkthdr.csum_data =
                            offsetof(struct tcphdr, th_sum);
                        break;
                case IPPROTO_UDP:
                        uh = (struct udphdr *)(ip + 1);
                        uh->uh_sum = cksum;
-                       mcl->m_pkthdr.csum_data = 
+                       mcl->m_pkthdr.csum_data =
                            offsetof(struct udphdr, uh_sum);
-                       break;                                          
+                       break;
                }
                /* No hw checksum offloading: do it ourselves */
                if ((mcl->m_pkthdr.csum_flags & CSUM_DELAY_DATA) == 0) {
                        in_delayed_cksum(mcl);
                        mcl->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
                }
+               ip->ip_len = htons(ip->ip_len);
        }
        args->m = mcl;
        return (IP_FW_NAT);
@@ -343,7 +341,7 @@ lookup_nat(struct nat_list *l, int nat_id)
        return res;
 }
 
-static int 
+static int
 ipfw_nat_cfg(struct sockopt *sopt)
 {
        struct cfg_nat *ptr, *ser_n;
@@ -355,14 +353,14 @@ ipfw_nat_cfg(struct sockopt *sopt)
        ser_n = (struct cfg_nat *)buf;
 
        /* check valid parameter ser_n->id > 0 ? */
-       /* 
+       /*
         * Find/create nat rule.
         */
        IPFW_WLOCK(chain);
        ptr = lookup_nat(&chain->nat, ser_n->id);
        if (ptr == NULL) {
                /* New rule: allocate and init new instance. */
-               ptr = malloc(sizeof(struct cfg_nat), 
+               ptr = malloc(sizeof(struct cfg_nat),
                    M_IPFW, M_NOWAIT | M_ZERO);
                if (ptr == NULL) {
                        IPFW_WUNLOCK(chain);
@@ -384,13 +382,13 @@ ipfw_nat_cfg(struct sockopt *sopt)
        }
        IPFW_WUNLOCK(chain);
 
-       /* 
+       /*
         * Basic nat configuration.
         */
        ptr->id = ser_n->id;
-       /* 
-        * XXX - what if this rule doesn't nat any ip and just 
-        * redirect? 
+       /*
+        * XXX - what if this rule doesn't nat any ip and just
+        * redirect?
         * do we set aliasaddress to 0.0.0.0?
         */
        ptr->ip = ser_n->ip;
@@ -400,7 +398,7 @@ ipfw_nat_cfg(struct sockopt *sopt)
        LibAliasSetAddress(ptr->lib, ptr->ip);
        memcpy(ptr->if_name, ser_n->if_name, IF_NAMESIZE);
 
-       /* 
+       /*
         * Redir and LSNAT configuration.
         */
        /* Delete old cfgs. */
@@ -420,7 +418,7 @@ ipfw_nat_del(struct sockopt *sopt)
        struct cfg_nat *ptr;
        struct ip_fw_chain *chain = &V_layer3_chain;
        int i;
-               
+
        sooptcopyin(sopt, &i, sizeof i, sizeof i);
        /* XXX validate i */
        IPFW_WLOCK(chain);
@@ -440,7 +438,7 @@ ipfw_nat_del(struct sockopt *sopt)
 
 static int
 ipfw_nat_get_cfg(struct sockopt *sopt)
-{      
+{
        uint8_t *data;
        struct cfg_nat *n;
        struct cfg_redir *r;
@@ -448,7 +446,7 @@ ipfw_nat_get_cfg(struct sockopt *sopt)
        int nat_cnt, off;
        struct ip_fw_chain *chain;
        int err = ENOSPC;
-               
+
        chain = &V_layer3_chain;
        nat_cnt = 0;
        off = sizeof(nat_cnt);
@@ -460,30 +458,30 @@ ipfw_nat_get_cfg(struct sockopt *sopt)
                nat_cnt++;
                if (off + SOF_NAT >= NAT_BUF_LEN)
                        goto nospace;
-                       bcopy(n, &data[off], SOF_NAT);
-                       off += SOF_NAT;
-                       LIST_FOREACH(r, &n->redir_chain, _next) {
+               bcopy(n, &data[off], SOF_NAT);
+               off += SOF_NAT;
+               LIST_FOREACH(r, &n->redir_chain, _next) {
                        if (off + SOF_REDIR >= NAT_BUF_LEN)
                                goto nospace;
                        bcopy(r, &data[off], SOF_REDIR);
-                                       off += SOF_REDIR;
+                       off += SOF_REDIR;
                        LIST_FOREACH(s, &r->spool_chain, _next) {
                                if (off + SOF_SPOOL >= NAT_BUF_LEN)
-                                                       goto nospace;
+                                       goto nospace;
                                bcopy(s, &data[off], SOF_SPOOL);
                                off += SOF_SPOOL;
-                                       }
                        }
+               }
        }
        err = 0; /* all good */
 nospace:
        IPFW_RUNLOCK(chain);
        if (err == 0) {
-       bcopy(&nat_cnt, data, sizeof(nat_cnt));
-       sooptcopyout(sopt, data, NAT_BUF_LEN);
+               bcopy(&nat_cnt, data, sizeof(nat_cnt));
+               sooptcopyout(sopt, data, NAT_BUF_LEN);
        } else {
-       printf("serialized data buffer not big enough:"
-           "please increase NAT_BUF_LEN\n");
+               printf("serialized data buffer not big enough:"
+                   "please increase NAT_BUF_LEN\n");
        }
        free(data, M_IPFW);
        return (err);
@@ -503,16 +501,16 @@ ipfw_nat_get_log(struct sockopt *sopt)
        /* one pass to count, one to copy the data */
        i = 0;
        LIST_FOREACH(ptr, &chain->nat, _next) {
-               if (ptr->lib->logDesc == NULL) 
+               if (ptr->lib->logDesc == NULL)
                        continue;
                i++;
        }
        size = i * (LIBALIAS_BUF_SIZE + sizeof(int));
        data = malloc(size, M_IPFW, M_NOWAIT | M_ZERO);
-               if (data == NULL) {
+       if (data == NULL) {
                IPFW_RUNLOCK(chain);
-                       return (ENOSPC);
-               }
+               return (ENOSPC);
+       }
        i = 0;
        LIST_FOREACH(ptr, &chain->nat, _next) {
                if (ptr->lib->logDesc == NULL)
@@ -551,7 +549,7 @@ ipfw_nat_destroy(void)
 {
        struct cfg_nat *ptr, *ptr_temp;
        struct ip_fw_chain *chain;
-       
+
        chain = &V_layer3_chain;
        IPFW_WLOCK(chain);
        LIST_FOREACH_SAFE(ptr, &chain->nat, _next, ptr_temp) {