LVS
lvs-users
Google
 
Web LinuxVirtualServer.org

2.2.19 ipvs patch for ip_masq_ftp

To: lvs-users <lvs-users@xxxxxxxxxxxxxxxxxxxxxx>
Subject: 2.2.19 ipvs patch for ip_masq_ftp
From: Tony Clarke <sam@xxxxxxxxxx>
Date: Fri, 13 Sep 2002 09:42:17 +0100
Hi,

To get active ftp (in both directions) working with ipvs patch for 2.2.19,
I patched ip_masq_ftp.c with the following and loaded with in_ports=21.
Anyone like to cast an eye over it?

This masquerades the port and ip correct. With just in_ports=21 only
the ip gets masqueraded.


--- orig_ip_masq_ftp    Thu Sep 12 12:15:42 2002
+++ ip_masq_ftp.c   Tue Sep 10 16:40:21 2002
@@ -142,6 +142,10 @@
/* Dummy variable */
static int masq_ftp_pasv;

+#ifdef CONFIG_IP_MASQUERADE_VS
+ static int ipvs_ftp_pasv; /* dummy variable for IPVS ftp passive */
+#endif /* CONFIG_IP_MASQUERADE_VS */
+
/*
* This function parses the IP address and Port number found in PORT commands * and PASV responses. This used to be done in-line, but with four cases it
@@ -255,6 +259,9 @@
  struct iphdr *iph;
  struct tcphdr *th;
  char *p, *data, *data0, *data_limit;
+#ifdef CONFIG_IP_MASQUERADE_VS
+   unsigned char p1,p2,p3,p4,p5,p6;
+#endif
  __u32 from=0;
  __u32 from_n;
  __u16 port;
@@ -268,6 +275,106 @@
  if (ms->state != IP_MASQ_S_ESTABLISHED)
      return 0;

+
+#ifdef CONFIG_IP_MASQUERADE_VS
+    if (ms->app_data == &ipvs_ftp_pasv) {
+                skb = *skb_p;
+                iph = skb->nh.iph;
+                th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
+                data = (char *)&th[1];
+                data_limit = skb->h.raw + skb->len;
+
+                while (data < data_limit && *data != ' ')
+                        ++data;
+                while (data < data_limit && *data == ' ')
+                        ++data;
+                data += 22;
+                p = data+1;
+                if (data >= data_limit || *data != '(')
+                        return 0;
+                p1 = simple_strtoul(data+1, &data, 10);
+                if (data >= data_limit || *data != ',')
+                        return 0;
+                p2 = simple_strtoul(data+1, &data, 10);
+                if (data >= data_limit || *data != ',')
+                        return 0;
+                p3 = simple_strtoul(data+1, &data, 10);
+                if (data >= data_limit || *data != ',')
+                        return 0;
+                p4 = simple_strtoul(data+1, &data, 10);
+                if (data >= data_limit || *data != ',')
+                        return 0;
+                p5 = simple_strtoul(data+1, &data, 10);
+                if (data >= data_limit || *data != ',')
+                        return 0;
+                p6 = simple_strtoul(data+1, &data, 10);
+                if (data >= data_limit || *data != ')')
+                        return 0;
+
+                from = (p1<<24) | (p2<<16) | (p3<<8) | p4;
+                port = (p5<<8) | p6;
+
+                port = (p5<<8) | p6;
+
+                /*
+                 * Now update or create an masquerade entry for it
+                 */
+ IP_MASQ_DEBUG(1-debug, "PASV response %lX:%X %X:%X detected\n",
+ntohl(ms->saddr), 0, from, port);
+
+                n_ms = ip_masq_out_get(iph->protocol,
+                                       htonl(from), htons(port),
+                                       ms->daddr, 0);
+                if (!n_ms) {
+                        n_ms = ip_masq_new(IPPROTO_TCP,
+                                           maddr, htons(port),
+                                           htonl(from), htons(port),
+                                           ms->daddr, 0,
+                                           IP_MASQ_F_NO_DPORT);
+
+                        if (n_ms==NULL)
+                                return 0;
+                        ip_masq_control_add(n_ms, ms);
+                }
+
+        /*
+         * Replace the old passive address with the new one
+         */
+        from = ntohl(n_ms->maddr);
+        port = ntohs(n_ms->mport);
+        sprintf(buf,"%d,%d,%d,%d,%d,%d",
+            from>>24&255,from>>16&255,from>>8&255,from&255,
+            port>>8&255,port&255);
+        buf_len = strlen(buf);
+
+        IP_MASQ_DEBUG(1-debug, "new PORT %X:%X\n",from,port);
+
+        /*
+         * Calculate required delta-offset to keep TCP happy
+         */
+
+        diff = buf_len - (data-p);
+
+        /*
+         *  No shift.
+         */
+
+        if (diff==0) {
+            /*
+             * simple case, just replace the old PORT cmd
+             */
+            memcpy(p,buf,buf_len);
+        } else {
+
+ *skb_p = ip_masq_skb_replace(skb, GFP_ATOMIC, p, data-p, buf, buf_len);
+        }
+
+        ms->app_data = NULL;
+        ip_masq_put(n_ms);
+
+                return diff;
+        }
+
+#endif
+
       skb = *skb_p;
  iph = skb->nh.iph;
       th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
@@ -440,6 +547,12 @@
  struct iphdr *iph;
  struct tcphdr *th;
  char *data, *data_limit;
+
+#ifdef CONFIG_IP_MASQUERADE_VS
+   unsigned char p1,p2,p3,p4,p5,p6;
+       char *p;
+#endif
+
  __u32 to;
  __u32 from_n;
  __u16 port;
@@ -448,6 +561,101 @@
  /*  Only useful for established  sessions */
  if (ms->state != IP_MASQ_S_ESTABLISHED)
      return 0;
+
+#ifdef CONFIG_IP_MASQUERADE_VS
+
+    /*
+     * Detecting whether it is passive
+     */
+        skb = *skb_p;
+    iph = skb->nh.iph;
+        th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
+        data = (char *)&th[1];
+        data_limit = skb->h.raw + skb->len;
+
+    while (data < data_limit) {
+ if (memcmp(data, "PASV\r\n", 6) == 0 || memcmp(data, "pasv\r\n", 6) == 0) {
+                        IP_MASQ_DEBUG(1-debug, "got PASV at %d of %d\n",
+ data-(char *)&th[1], data_limit-(char *)&th[1]);
+                        ms->app_data = &ipvs_ftp_pasv;
+
+                        return 0;
+                }
+        data++;
+        }
+
+    /*
+     * To support virtual FTP server, the scenerio is as follows:
+     *       FTP client ----> Load Balancer ----> FTP server
+     * First detect the port number in the application data,
+     * then create a new masquerading entry for the coming data
+     * connection.
+     */
+        data = (char *)&th[1];
+        data_limit = skb->h.raw + skb->len - 18;
+
+    while (data < data_limit)
+    {
+        if (memcmp(data,"PORT ",5) && memcmp(data,"port ",5))
+        {
+            data ++;
+            continue;
+        }
+        p = data+5;
+        p1 = simple_strtoul(data+5,&data,10);
+        if (*data!=',')
+            continue;
+        p2 = simple_strtoul(data+1,&data,10);
+        if (*data!=',')
+            continue;
+        p3 = simple_strtoul(data+1,&data,10);
+        if (*data!=',')
+            continue;
+        p4 = simple_strtoul(data+1,&data,10);
+        if (*data!=',')
+            continue;
+        p5 = simple_strtoul(data+1,&data,10);
+        if (*data!=',')
+            continue;
+        p6 = simple_strtoul(data+1,&data,10);
+        if (*data!='\r' && *data!='\n')
+            continue;
+
+        to = (p1<<24) | (p2<<16) | (p3<<8) | p4;
+        port = (p5<<8) | p6;
+
+        IP_MASQ_DEBUG(1-debug, "PORT %X:%X detected\n",to,port);
+      /*
+         * Now update or create an masquerade entry for it
+         */
+
+ IP_MASQ_DEBUG(1-debug, "protocol %d %lX:%X %X:%X\n", iph->protocol, htonl(to), htons(port), iph->daddr, 0);
+
+        n_ms = ip_masq_in_get(iph->protocol,
+                      htonl(to), htons(port),
+                      iph->daddr, 0);
+        if (!n_ms) {
+            n_ms = ip_masq_new(IPPROTO_TCP,
+                       maddr, htons(ntohs(ms->mport)-1),
+                       ms->saddr, htons(ntohs(ms->sport)-1),
+                       htonl(to), htons(port),
+                       0);
+
+            if (n_ms==NULL)
+                return 0;
+            ip_masq_control_add(n_ms, ms);
+        }
+
+                /*
+                 *  Move tunnel to listen state
+                 */
+        ip_masq_listen(n_ms);
+        ip_masq_put(n_ms);
+
+                return 0;
+    }
+
+#endif

  skb = *skb_p;
  iph = skb->nh.iph;




<Prev in Thread] Current Thread [Next in Thread>