summaryrefslogtreecommitdiffstats
path: root/openwrt/package/ppp/patches/108-debian_defaultroute.patch
blob: 76b444e4b24f5265eabfb77e1f0acfe6d0cc57f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
--- ppp/pppd/ipcp.c	Wed May 31 17:20:41 2000
+++ ppp/pppd/ipcp.c	Wed May 31 17:27:19 2000
@@ -145,7 +145,17 @@
     { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route,
       "disable defaultroute option", OPT_A2COPY,
       &ipcp_wantoptions[0].default_route },

+#ifdef __linux__
+    { "replacedefaultroute", o_bool,
+				&ipcp_wantoptions[0].replace_default_route,
+      "Replace default route", 1
+    },
+    { "noreplacedefaultroute", o_bool,
+				&ipcp_allowoptions[0].replace_default_route,
+      "Never replace default route", OPT_A2COPY,
+				&ipcp_wantoptions[0].replace_default_route },
+#endif
     { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp,
       "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp },
     { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp,
@@ -195,7 +205,7 @@
     ip_active_pkt
 };
 
-static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t));
+static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t, bool));
 static void ipcp_script __P((char *));		/* Run an up/down script */
 static void ipcp_script_done __P((void *));
 
@@ -1344,7 +1354,12 @@
     if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))
 	return 0;
     if (wo->default_route)
+#ifndef __linux__
 	if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr))
+#else
+	if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr,
+					    wo->replace_default_route))
+#endif
 	    default_route_set[u] = 1;
     if (wo->proxy_arp)
 	if (sifproxyarp(u, wo->hisaddr))
@@ -1420,7 +1435,8 @@
      */
     if (demand) {
 	if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) {
-	    ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr);
+	    ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr,
+				      wo->replace_default_route);
 	    if (go->ouraddr != wo->ouraddr) {
 		warn("Local IP address changed to %I", go->ouraddr);
 		script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr));
@@ -1445,7 +1461,12 @@
 
 	    /* assign a default route through the interface if required */
 	    if (ipcp_wantoptions[f->unit].default_route) 
+#ifndef __linux__
 		if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
+#else
+		if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr,
+					     wo->replace_default_route))
+#endif
 		    default_route_set[f->unit] = 1;
 
 	    /* Make a proxy ARP entry if requested. */
@@ -1492,7 +1513,12 @@
 
 	/* assign a default route through the interface if required */
 	if (ipcp_wantoptions[f->unit].default_route) 
+#ifndef __linux__
 	    if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
+#else
+	    if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr,
+					 wo->replace_default_route))
+#endif
 		default_route_set[f->unit] = 1;
 
 	/* Make a proxy ARP entry if requested. */
@@ -1559,7 +1585,7 @@
 	sifnpmode(f->unit, PPP_IP, NPMODE_DROP);
 	sifdown(f->unit);
 	ipcp_clear_addrs(f->unit, ipcp_gotoptions[f->unit].ouraddr,
-			 ipcp_hisoptions[f->unit].hisaddr);
+			 ipcp_hisoptions[f->unit].hisaddr, 0);
     }
 
     /* Execute the ip-down script */
@@ -1575,16 +1601,25 @@
  * proxy arp entries, etc.
  */
 static void
-ipcp_clear_addrs(unit, ouraddr, hisaddr)
+ipcp_clear_addrs(unit, ouraddr, hisaddr, replacedefaultroute)
     int unit;
     u_int32_t ouraddr;  /* local address */
     u_int32_t hisaddr;  /* remote address */
+    bool replacedefaultroute;
 {
     if (proxy_arp_set[unit]) {
 	cifproxyarp(unit, hisaddr);
 	proxy_arp_set[unit] = 0;
     }
-    if (default_route_set[unit]) {
+    /* If replacedefaultroute, sifdefaultroute will be called soon
+     * with replacedefaultroute set and that will overwrite the current
+     * default route. This is the case only when doing demand, otherwise
+     * during demand, this cifdefaultroute would restore the old default
+     * route which is not what we want in this case. In the non-demand
+     * case, we'll delete the default route and restore the old if there
+     * is one saved by an sifdefaultroute with replacedefaultroute.
+     */
+    if (!replacedefaultroute && default_route_set[unit]) {
 	cifdefaultroute(unit, ouraddr, hisaddr);
 	default_route_set[unit] = 0;
     }
--- ppp/pppd/ipcp.h	Wed May 31 17:20:41 2000
+++ ppp/pppd/ipcp.h	Wed May 31 15:56:17 2000
@@ -47,6 +47,7 @@
     bool old_addrs;		/* Use old (IP-Addresses) option? */
     bool req_addr;		/* Ask peer to send IP address? */
     bool default_route;		/* Assign default route through interface? */
+    bool replace_default_route;	/* Replace default route through interface? */
     bool proxy_arp;		/* Make proxy ARP entry for peer? */
     bool neg_vj;		/* Van Jacobson Compression? */
     bool old_vj;		/* use old (short) form of VJ option? */
--- ppp/pppd/pppd.h	Wed May 31 17:20:41 2000
+++ ppp/pppd/pppd.h	Wed May 31 15:56:17 2000
@@ -416,7 +416,11 @@
 int  cif6addr __P((int, eui64_t, eui64_t));
 				/* Remove an IPv6 address from i/f */
 #endif
+#ifndef __linux__
 int  sifdefaultroute __P((int, u_int32_t, u_int32_t));
+#else
+int  sifdefaultroute __P((int, u_int32_t, u_int32_t, bool replace_default_rt));
+#endif
 				/* Create default route through i/f */
 int  cifdefaultroute __P((int, u_int32_t, u_int32_t));
 				/* Delete default route through i/f */
--- ppp/pppd/sys-linux.c	Wed May 31 17:20:41 2000
+++ ppp/pppd/sys-linux.c	Wed May 31 17:37:23 2000
@@ -143,6 +143,8 @@
 
 static int	if_is_up;	/* Interface has been marked up */
 static u_int32_t default_route_gateway;	/* Gateway for default route added */
+static struct rtentry old_def_rt;       /* Old default route */
+static int       default_rt_repl_rest;  /* replace and restore old default rt */
 static u_int32_t proxy_arp_addr;	/* Addr for proxy arp entry added */
 static char proxy_arp_dev[16];		/* Device for proxy arp entry */
 static u_int32_t our_old_addr;		/* for detecting address changes */
@@ -1209,6 +1211,9 @@
 	p = NULL;
     }
 
+    SET_SA_FAMILY (rt->rt_dst,     AF_INET);
+    SET_SA_FAMILY (rt->rt_gateway, AF_INET);
+
     SIN_ADDR(rt->rt_dst) = strtoul(cols[route_dest_col], NULL, 16);
     SIN_ADDR(rt->rt_gateway) = strtoul(cols[route_gw_col], NULL, 16);
     SIN_ADDR(rt->rt_genmask) = strtoul(cols[route_mask_col], NULL, 16);
@@ -1278,19 +1283,53 @@
 /********************************************************************
  *
  * sifdefaultroute - assign a default route through the address given.
+ *
+ * If the global default_rt_repl_rest flag is set, then this function
+ * already replaced the original system defaultroute with some other
+ * route and it should just replace the current defaultroute with
+ * another one, without saving the current route. Use: demand mode,
+ * when pppd sets first a defaultroute it it's temporary ppp0 addresses
+ * and then changes the temporary addresses to the addresses for the real
+ * ppp connection when it has come up.
  */
 
-int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
+int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway, bool replace)
 {
-    struct rtentry rt;
-
-    if (defaultroute_exists(&rt) && strcmp(rt.rt_dev, ifname) != 0) {
-	u_int32_t old_gateway = SIN_ADDR(rt.rt_gateway);
+    struct rtentry rt, tmp_rt;
+    struct rtentry *del_rt = NULL;
 
-	if (old_gateway != gateway)
-	    error("not replacing existing default route to %s [%I]",
-		  rt.rt_dev, old_gateway);
-	return 0;
+    
+    if (default_rt_repl_rest) {
+	/* We have already reclaced the original defaultroute, if we
+         * are called again, we will delete the current default route
+         * and set the new default route in this function.  
+         * - this is normally only the case the doing demand: */
+	if (defaultroute_exists( &tmp_rt ))
+		del_rt = &tmp_rt;
+    } else if ( defaultroute_exists( &old_def_rt                ) &&
+	                     strcmp(  old_def_rt.rt_dev, ifname ) != 0) {
+	/* We did not yet replace an existing default route, let's
+	 * check if we should save and replace a default route:
+         */
+	u_int32_t old_gateway = SIN_ADDR(old_def_rt.rt_gateway);
+
+	if (old_gateway != gateway) {
+	    if (!replace) {
+	        error("not replacing default route to %s [%I]",
+			old_def_rt.rt_dev, old_gateway);
+		return 0;
+	    } else {
+		// we need to copy rt_dev because we need it permanent too:
+		char * tmp_dev = malloc(strlen(old_def_rt.rt_dev)+1);
+		strcpy(tmp_dev, old_def_rt.rt_dev);
+		old_def_rt.rt_dev = tmp_dev;
+
+		notice("replacing old default route to %s [%I]",
+			old_def_rt.rt_dev, old_gateway);
+	        default_rt_repl_rest = 1;
+		del_rt = &old_def_rt;
+	    }
+	}
     }
 
     memset (&rt, '\0', sizeof (rt));
@@ -1310,6 +1349,12 @@
 	    error("default route ioctl(SIOCADDRT): %m(%d)", errno);
 	return 0;
     }
+    if (default_rt_repl_rest && del_rt)
+        if (ioctl(sock_fd, SIOCDELRT, del_rt) < 0) {
+	    if ( ! ok_error ( errno ))
+	        error("del old default route ioctl(SIOCDELRT): %m(%d)", errno);
+	    return 0;
+        }
 
     default_route_gateway = gateway;
     return 1;
@@ -1344,6 +1389,16 @@
 		error("default route ioctl(SIOCDELRT): %m (%d)", errno);
 	    return 0;
 	}
+    }
+    if (default_rt_repl_rest) {
+	notice("restoring old default route to %s [%I]",
+			old_def_rt.rt_dev, SIN_ADDR(old_def_rt.rt_gateway));
+        if (ioctl(sock_fd, SIOCADDRT, &old_def_rt) < 0) {
+	    if ( ! ok_error ( errno ))
+	        error("restore default route ioctl(SIOCADDRT): %m(%d)", errno);
+	    return 0;
+        }
+        default_rt_repl_rest = 0;
     }
 
     return 1;