110-debian_defaultroute.patch 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. pppd: Add "replacedefaultroute" and "noreplacedefaultroute" options
  2. This patch implements two new options, "replacedefaultroute" to replace any
  3. existing system default route when specified and "noreplacedefaultroute" to
  4. disable the "replacedefaultroute" option, which is useful in multi user
  5. environments where the administrator wants to allow users to dial pppd
  6. connections but not allow them to change the system default route.
  7. The patch originated from the Debian project.
  8. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
  9. --- a/pppd/ipcp.c
  10. +++ b/pppd/ipcp.c
  11. @@ -198,6 +198,14 @@ static option_t ipcp_option_list[] = {
  12. "disable defaultroute option", OPT_ALIAS | OPT_A2CLR,
  13. &ipcp_wantoptions[0].default_route },
  14. + { "replacedefaultroute", o_bool,
  15. + &ipcp_wantoptions[0].replace_default_route,
  16. + "Replace default route", 1
  17. + },
  18. + { "noreplacedefaultroute", o_bool,
  19. + &ipcp_allowoptions[0].replace_default_route,
  20. + "Never replace default route", OPT_A2COPY,
  21. + &ipcp_wantoptions[0].replace_default_route },
  22. { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp,
  23. "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp },
  24. { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp,
  25. @@ -271,7 +279,7 @@ struct protent ipcp_protent = {
  26. ip_active_pkt
  27. };
  28. -static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t));
  29. +static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t, bool));
  30. static void ipcp_script __P((char *, int)); /* Run an up/down script */
  31. static void ipcp_script_done __P((void *));
  32. @@ -1761,7 +1769,8 @@ ip_demand_conf(u)
  33. if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))
  34. return 0;
  35. if (wo->default_route)
  36. - if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr))
  37. + if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr,
  38. + wo->replace_default_route))
  39. default_route_set[u] = 1;
  40. if (wo->proxy_arp)
  41. if (sifproxyarp(u, wo->hisaddr))
  42. @@ -1849,7 +1858,8 @@ ipcp_up(f)
  43. */
  44. if (demand) {
  45. if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) {
  46. - ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr);
  47. + ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr,
  48. + wo->replace_default_route);
  49. if (go->ouraddr != wo->ouraddr) {
  50. warn("Local IP address changed to %I", go->ouraddr);
  51. script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0);
  52. @@ -1874,7 +1884,8 @@ ipcp_up(f)
  53. /* assign a default route through the interface if required */
  54. if (ipcp_wantoptions[f->unit].default_route)
  55. - if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
  56. + if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr,
  57. + wo->replace_default_route))
  58. default_route_set[f->unit] = 1;
  59. /* Make a proxy ARP entry if requested. */
  60. @@ -1924,7 +1935,8 @@ ipcp_up(f)
  61. /* assign a default route through the interface if required */
  62. if (ipcp_wantoptions[f->unit].default_route)
  63. - if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
  64. + if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr,
  65. + wo->replace_default_route))
  66. default_route_set[f->unit] = 1;
  67. /* Make a proxy ARP entry if requested. */
  68. @@ -2002,7 +2014,7 @@ ipcp_down(f)
  69. sifnpmode(f->unit, PPP_IP, NPMODE_DROP);
  70. sifdown(f->unit);
  71. ipcp_clear_addrs(f->unit, ipcp_gotoptions[f->unit].ouraddr,
  72. - ipcp_hisoptions[f->unit].hisaddr);
  73. + ipcp_hisoptions[f->unit].hisaddr, 0);
  74. }
  75. /* Execute the ip-down script */
  76. @@ -2018,16 +2030,25 @@ ipcp_down(f)
  77. * proxy arp entries, etc.
  78. */
  79. static void
  80. -ipcp_clear_addrs(unit, ouraddr, hisaddr)
  81. +ipcp_clear_addrs(unit, ouraddr, hisaddr, replacedefaultroute)
  82. int unit;
  83. u_int32_t ouraddr; /* local address */
  84. u_int32_t hisaddr; /* remote address */
  85. + bool replacedefaultroute;
  86. {
  87. if (proxy_arp_set[unit]) {
  88. cifproxyarp(unit, hisaddr);
  89. proxy_arp_set[unit] = 0;
  90. }
  91. - if (default_route_set[unit]) {
  92. + /* If replacedefaultroute, sifdefaultroute will be called soon
  93. + * with replacedefaultroute set and that will overwrite the current
  94. + * default route. This is the case only when doing demand, otherwise
  95. + * during demand, this cifdefaultroute would restore the old default
  96. + * route which is not what we want in this case. In the non-demand
  97. + * case, we'll delete the default route and restore the old if there
  98. + * is one saved by an sifdefaultroute with replacedefaultroute.
  99. + */
  100. + if (!replacedefaultroute && default_route_set[unit]) {
  101. cifdefaultroute(unit, ouraddr, hisaddr);
  102. default_route_set[unit] = 0;
  103. }
  104. --- a/pppd/ipcp.h
  105. +++ b/pppd/ipcp.h
  106. @@ -70,6 +70,7 @@ typedef struct ipcp_options {
  107. bool old_addrs; /* Use old (IP-Addresses) option? */
  108. bool req_addr; /* Ask peer to send IP address? */
  109. bool default_route; /* Assign default route through interface? */
  110. + bool replace_default_route; /* Replace default route through interface? */
  111. bool proxy_arp; /* Make proxy ARP entry for peer? */
  112. bool neg_vj; /* Van Jacobson Compression? */
  113. bool old_vj; /* use old (short) form of VJ option? */
  114. --- a/pppd/pppd.8
  115. +++ b/pppd/pppd.8
  116. @@ -127,6 +127,11 @@ is no other default route with the same
  117. value of -1, the route is only added if there is no default route at
  118. all.
  119. .TP
  120. +.B replacedefaultroute
  121. +This option is a flag to the defaultroute option. If defaultroute is
  122. +set and this flag is also set, pppd replaces an existing default route
  123. +with the new default route.
  124. +.TP
  125. .B disconnect \fIscript
  126. Execute the command specified by \fIscript\fR, by passing it to a
  127. shell, after
  128. @@ -740,7 +745,12 @@ disable both forms of hardware flow cont
  129. .TP
  130. .B nodefaultroute
  131. Disable the \fIdefaultroute\fR option. The system administrator who
  132. -wishes to prevent users from creating default routes with pppd
  133. +wishes to prevent users from adding a default route with pppd
  134. +can do so by placing this option in the /etc/ppp/options file.
  135. +.TP
  136. +.B noreplacedefaultroute
  137. +Disable the \fIreplacedefaultroute\fR option. The system administrator who
  138. +wishes to prevent users from replacing a default route with pppd
  139. can do so by placing this option in the /etc/ppp/options file.
  140. .TP
  141. .B nodeflate
  142. --- a/pppd/pppd.h
  143. +++ b/pppd/pppd.h
  144. @@ -681,7 +681,7 @@ int sif6addr __P((int, eui64_t, eui64_t
  145. int cif6addr __P((int, eui64_t, eui64_t));
  146. /* Remove an IPv6 address from i/f */
  147. #endif
  148. -int sifdefaultroute __P((int, u_int32_t, u_int32_t));
  149. +int sifdefaultroute __P((int, u_int32_t, u_int32_t, bool replace_default_rt));
  150. /* Create default route through i/f */
  151. int cifdefaultroute __P((int, u_int32_t, u_int32_t));
  152. /* Delete default route through i/f */
  153. --- a/pppd/sys-linux.c
  154. +++ b/pppd/sys-linux.c
  155. @@ -207,6 +207,8 @@ static unsigned char inbuf[512]; /* buff
  156. static int if_is_up; /* Interface has been marked up */
  157. static int if6_is_up; /* Interface has been marked up for IPv6, to help differentiate */
  158. static int have_default_route; /* Gateway for default route added */
  159. +static struct rtentry old_def_rt; /* Old default route */
  160. +static int default_rt_repl_rest; /* replace and restore old default rt */
  161. static u_int32_t proxy_arp_addr; /* Addr for proxy arp entry added */
  162. static char proxy_arp_dev[16]; /* Device for proxy arp entry */
  163. static u_int32_t our_old_addr; /* for detecting address changes */
  164. @@ -1570,6 +1572,9 @@ static int read_route_table(struct rtent
  165. p = NULL;
  166. }
  167. + SET_SA_FAMILY (rt->rt_dst, AF_INET);
  168. + SET_SA_FAMILY (rt->rt_gateway, AF_INET);
  169. +
  170. SIN_ADDR(rt->rt_dst) = strtoul(cols[route_dest_col], NULL, 16);
  171. SIN_ADDR(rt->rt_gateway) = strtoul(cols[route_gw_col], NULL, 16);
  172. SIN_ADDR(rt->rt_genmask) = strtoul(cols[route_mask_col], NULL, 16);
  173. @@ -1642,20 +1647,52 @@ int have_route_to(u_int32_t addr)
  174. /********************************************************************
  175. *
  176. * sifdefaultroute - assign a default route through the address given.
  177. - */
  178. -
  179. -int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
  180. -{
  181. - struct rtentry rt;
  182. -
  183. - if (defaultroute_exists(&rt, dfl_route_metric) && strcmp(rt.rt_dev, ifname) != 0) {
  184. - if (rt.rt_flags & RTF_GATEWAY)
  185. - error("not replacing existing default route via %I with metric %d",
  186. - SIN_ADDR(rt.rt_gateway), dfl_route_metric);
  187. - else
  188. + *
  189. + * If the global default_rt_repl_rest flag is set, then this function
  190. + * already replaced the original system defaultroute with some other
  191. + * route and it should just replace the current defaultroute with
  192. + * another one, without saving the current route. Use: demand mode,
  193. + * when pppd sets first a defaultroute it it's temporary ppp0 addresses
  194. + * and then changes the temporary addresses to the addresses for the real
  195. + * ppp connection when it has come up.
  196. + */
  197. +
  198. +int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway, bool replace)
  199. +{
  200. + struct rtentry rt, tmp_rt;
  201. + struct rtentry *del_rt = NULL;
  202. +
  203. + if (default_rt_repl_rest) {
  204. + /* We have already reclaced the original defaultroute, if we
  205. + are called again, we will delete the current default route
  206. + and set the new default route in this function.
  207. + - this is normally only the case the doing demand: */
  208. + if (defaultroute_exists(&tmp_rt, dfl_route_metric))
  209. + del_rt = &tmp_rt;
  210. + } else if (defaultroute_exists(&old_def_rt, dfl_route_metric) &&
  211. + strcmp(old_def_rt.rt_dev, ifname) != 0) {
  212. + /* We did not yet replace an existing default route, let's
  213. + check if we should save and replace a default route: */
  214. + if (old_def_rt.rt_flags & RTF_GATEWAY) {
  215. + if (!replace) {
  216. + error("not replacing existing default route via %I with metric %d",
  217. + SIN_ADDR(old_def_rt.rt_gateway), dfl_route_metric);
  218. + return 0;
  219. + } else {
  220. + /* we need to copy rt_dev because we need it permanent too: */
  221. + char *tmp_dev = malloc(strlen(old_def_rt.rt_dev) + 1);
  222. + strcpy(tmp_dev, old_def_rt.rt_dev);
  223. + old_def_rt.rt_dev = tmp_dev;
  224. +
  225. + notice("replacing old default route to %s [%I] with metric %d",
  226. + old_def_rt.rt_dev, SIN_ADDR(old_def_rt.rt_gateway),
  227. + dfl_route_metric);
  228. + default_rt_repl_rest = 1;
  229. + del_rt = &old_def_rt;
  230. + }
  231. + } else
  232. error("not replacing existing default route through %s with metric %d",
  233. - rt.rt_dev, dfl_route_metric);
  234. - return 0;
  235. + old_def_rt.rt_dev, dfl_route_metric);
  236. }
  237. memset (&rt, 0, sizeof (rt));
  238. @@ -1671,10 +1708,16 @@ int sifdefaultroute (int unit, u_int32_t
  239. rt.rt_flags = RTF_UP;
  240. if (ioctl(sock_fd, SIOCADDRT, &rt) < 0) {
  241. - if ( ! ok_error ( errno ))
  242. + if (!ok_error(errno))
  243. error("default route ioctl(SIOCADDRT): %m");
  244. return 0;
  245. }
  246. + if (default_rt_repl_rest && del_rt)
  247. + if (ioctl(sock_fd, SIOCDELRT, del_rt) < 0) {
  248. + if (!ok_error(errno))
  249. + error("del old default route ioctl(SIOCDELRT): %m");
  250. + return 0;
  251. + }
  252. have_default_route = 1;
  253. return 1;
  254. @@ -1708,11 +1751,21 @@ int cifdefaultroute (int unit, u_int32_t
  255. rt.rt_flags = RTF_UP;
  256. if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH) {
  257. if (still_ppp()) {
  258. - if ( ! ok_error ( errno ))
  259. + if (!ok_error(errno))
  260. error("default route ioctl(SIOCDELRT): %m");
  261. return 0;
  262. }
  263. }
  264. + if (default_rt_repl_rest) {
  265. + notice("restoring old default route to %s [%I]",
  266. + old_def_rt.rt_dev, SIN_ADDR(old_def_rt.rt_gateway));
  267. + if (ioctl(sock_fd, SIOCADDRT, &old_def_rt) < 0) {
  268. + if (!ok_error(errno))
  269. + error("restore default route ioctl(SIOCADDRT): %m");
  270. + return 0;
  271. + }
  272. + default_rt_repl_rest = 0;
  273. + }
  274. return 1;
  275. }
  276. --- a/pppd/sys-solaris.c
  277. +++ b/pppd/sys-solaris.c
  278. @@ -2039,12 +2039,18 @@ cifaddr(u, o, h)
  279. * sifdefaultroute - assign a default route through the address given.
  280. */
  281. int
  282. -sifdefaultroute(u, l, g)
  283. +sifdefaultroute(u, l, g, replace)
  284. int u;
  285. u_int32_t l, g;
  286. + bool replace;
  287. {
  288. struct rtentry rt;
  289. + if (replace) {
  290. + error("replacedefaultroute not supported on this platform");
  291. + return 0;
  292. + }
  293. +
  294. #if defined(__USLC__)
  295. g = l; /* use the local address as gateway */
  296. #endif