Blob Blame History Raw
This adds support for setting SO_MARK for the PPTP TCP control
connection as well as on the GRE packets. SO_MARK is propagated
to the IP/IPv6 policy routing & netfilter mark.

This makes working with "austrian style" pptp internet dialup
much easier since you can create a separate routing table for
pptpclient. There you put a separate default route for pptp,
and pppd then sets your regular default route as usual.

Note: uses capability CAP_NET_ADMIN.

Signed-off-by: David Lamparter <david.lamparter@adyton.net>
Cc: David Lamparter <equinox@diac24.net>
Cc: Franco Fichtner <franco.fichtner@adyton.net>
--

Attached code is put into public domain affirmed by both me
(David Lamparter, the author) as well as my employer (Adyton
Systems AG) who paid for it to be written. Assigning copyright
to the FSF is impossible under German law.

--
David Lamparter | Software Developer | Adyton Systems AG
Mozartstr. 3 | 04107 Leipzig | Germany
phone +49 341.39 299 343 | fax +49 341.39 299 343-9
trade register: Amtsgericht Leipzig HRB26578

--- pptp-linux/pptp.8.orig	2008-05-14 08:32:52.000000000 +0200
+++ pptp-linux/pptp.8	2011-02-21 14:39:30.017877324 +0100
@@ -82,6 +82,16 @@
 .B \-\-localbind <addr>
 Bind to specified IP address instead of wildcard
 .TP
+.B \-\-rtmark <n>
+Use specified policy routing mark for all packets.
+This causes both the TCP control connection's packets as well as the
+GRE packets to bear the given policy routing / netfilter mark. This
+can be used with
+.I ip rule
+(from iproute2) to use a separate routing table for the pptp client.
+
+(requires root privileges or the CAP_NET_ADMIN capability.)
+.TP
 .B \-\-loglevel <level>
 Sets the debugging level (0=low, 1=default, 2=high)
 
--- pptp-linux/pptp_callmgr.c.orig	2010-06-15 07:04:32.000000000 +0200
+++ pptp-linux/pptp_callmgr.c	2011-02-21 14:32:46.471449998 +0100
@@ -31,6 +31,7 @@
 #include "routing.h"
 
 extern struct in_addr localbind; /* from pptp.c */
+extern int rtmark;
 
 int open_inetsock(struct in_addr inetaddr);
 int open_unixsock(struct in_addr inetaddr);
@@ -321,6 +322,14 @@
         warn("socket: %s", strerror(errno));
         return s;
     }
+#ifdef SO_MARK
+    if (rtmark) {
+        if (setsockopt(s, SOL_SOCKET, SO_MARK, &rtmark, sizeof(rtmark))) {
+            warn("setsockopt(SO_MARK): %s", strerror(errno));
+            close(s); return -1;
+        }
+    }
+#endif
     if (localbind.s_addr != INADDR_NONE) {
         bzero(&src, sizeof(src));
         src.sin_family = AF_INET;
--- pptp-linux/pptp.c.orig	2010-06-16 01:38:04.000000000 +0200
+++ pptp-linux/pptp.c	2011-02-21 14:33:49.210896419 +0100
@@ -118,6 +118,9 @@
             "  --max-echo-wait		Time to wait before giving up on lack of reply\n"
             "  --logstring <name>	Use <name> instead of 'anon' in syslog messages\n"
             "  --localbind <addr>	Bind to specified IP address instead of wildcard\n"
+#ifdef SO_MARK
+            "  --rtmark <n>	Use specified policy routing mark for all packets\n"
+#endif
             "  --loglevel <level>	Sets the debugging level (0=low, 1=default, 2=high)\n"
             "  --test-type <type>	Damage the packet stream by reordering\n"
             "  --test-rate <n>		Do the test every n packets\n",
@@ -132,6 +135,7 @@
 #else
 struct in_addr localbind = { INADDR_NONE };
 #endif
+int rtmark = 0;
 static int signaled = 0;
 
 /*** do nothing signal handler ************************************************/
@@ -212,6 +216,7 @@
 	    {"version", 0, 0, 0},
 	    {"test-type", 1, 0, 0},
 	    {"test-rate", 1, 0, 0},
+	    {"rtmark", 1, 0, 0},
             {0, 0, 0, 0}
         };
         int option_index = 0;
@@ -290,6 +295,14 @@
 		    test_type = atoi(optarg);
 		} else if (option_index == 14) { /* --test-rate */
 		    test_rate = atoi(optarg);
+		} else if (option_index == 15) { /* --rtmark */
+#ifdef SO_MARK
+		    rtmark = atoi(optarg);
+#else
+		    fprintf(stderr, "--rtmark support was missing when "
+				    "this binary was compiled.\n");
+		    exit(2);
+#endif
                 }
                 break;
             case '?': /* unrecognised option */
--- pptp-linux/pptp_gre.c.orig	2008-07-24 07:37:47.000000000 +0200
+++ pptp-linux/pptp_gre.c	2011-02-21 14:32:33.131567611 +0100
@@ -86,8 +86,17 @@
 {
     struct sockaddr_in src_addr, loc_addr;
     extern struct in_addr localbind;
+    extern int rtmark;
     int s = socket(AF_INET, SOCK_RAW, PPTP_PROTO);
     if (s < 0) { warn("socket: %s", strerror(errno)); return -1; }
+#ifdef SO_MARK
+    if (rtmark) {
+        if (setsockopt(s, SOL_SOCKET, SO_MARK, &rtmark, sizeof(rtmark))) {
+            warn("setsockopt(SO_MARK): %s", strerror(errno));
+            close(s); return -1;
+        }
+    }
+#endif
     if (localbind.s_addr != INADDR_NONE) {
         bzero(&loc_addr, sizeof(loc_addr));
         loc_addr.sin_family = AF_INET;