NOTE: this starts off as a diald configuration issue, but leads to a pppd 
source question (with diffs attached)

I have been trying to get diald and pppd to work correctly on my machine 
in regards to how they handle default routes. I am now running 2.0.36 (RH 
5.2) which has ppp 2.3.5 (which looking at sunsite is only at 2.3.4... is 
this a different ppp?). I am using diald 0.16.5.

Diald creates a proxy interface and default route (device sl0). The 
default route has a gateway address of 0.0.0.0 and a metric of 1. When 
pppd kicks in as the real physical link, it was my reading of the docs 
that diald creates a default route for ppp link. In a email discussion 
with someone with much older versions of diald/ppp/linux, it appears the 
route on his system is added by diald and has a lower metric than the sl0 
default route. In fact his sl0 is 2000 and the pp0 route is 500. 

In examining my syslogs, I got the following error message:
    pppd[951]: not replacing existing default route to sl0 [0.0.0.0]

Here pppd is trying to add a default route (due to the defaultroute 
option in the ppp options file). It fails because of an existing default 
route (the sl0 device route). From what I can tell with diald running, 
ppp shouldn't even be trying to add its own route, and if someone can 
tell me how to make this happen I would appreciate it. I have taken 
defaultroute and many other options in and out of both diald.conf and the 
ppp options file (and I have read the Warning in the diald man page about 
taking out almost all ppp options). I think that ultimately there is a 
diald issue to be resolved in setting the default route for the physical 
link.

In the meantime, I looked at the pppd source and in particular the file 
sys_linux.c. In this file I noticed (in sifdefaultroute()) that default 
routes are added after checking for existing default routes. If a default 
route exists and it has a different gateway address then pppd will not 
add the new default route. It would seem better to check the metric value 
and if the metric value is different then it should be safe to add the 
route, especially when the gateway *is* different between the 
pre-existing default routes and the new one. Also I think there is a bug 
in this same area, because after checking for existing default routes it 
goes through an extra if-case to check the gateway address and if its not 
a match then it logs the error (the one seen above in this message). Then 
it drops out of the if-case and does a return 0 (no add of default 
route). This seems strange... why not a syslog for all default routes not 
being added (due to a pre-existing route) versus a message for just the 
ones with a different gateway and silence for the rest. I think the 
return was meant to be in the same if-case as the syslog message.

In order to check metrics the read_route_table() routine had to be 
slightly extended to read the value and stuff it into the route data 
structure.

When I looked at the other sys_*.c files, none of the other OS versions 
seem to reject adding default routes, especially with such pre-checking.

I made changes to use metrics as well as the gateway name to check if it 
is okay to add a default route in the pppd code (sys_linux.c). I am 
attaching it here, and would be interested in feedback on what I think I 
am seeing as a problem.

Thanks,

-Art

*** sys-linux.c.ORIG    Thu Mar 18 22:01:29 1999
--- sys-linux.c Fri Mar 19 22:18:04 1999
***************
*** 1215,1220 ****
--- 1215,1221 ----
    {
      static char delims[] = " \t\n";
      char *dev_ptr, *dst_ptr, *gw_ptr, *flag_ptr;
+     char *refcnt_ptr, *use_ptr, *metric_ptr;
        
      memset (rt, '\0', sizeof (struct rtentry));
  
***************
*** 1230,1235 ****
--- 1231,1239 ----
        dst_ptr  = strtok (NULL,         delims); /* destination address */
        gw_ptr   = strtok (NULL,         delims); /* gateway */
        flag_ptr = strtok (NULL,         delims); /* flags */
+       refcnt_ptr = strtok (NULL,         delims); /* reference count */
+       use_ptr  = strtok (NULL,         delims); /* use */
+       metric_ptr = strtok (NULL,         delims); /* metric */
      
        if (flag_ptr == (char *) 0) /* assume that we failed, somewhere. */
          {
***************
*** 1251,1256 ****
--- 1255,1261 ----
        strtoul (gw_ptr, NULL, 16);
  
      rt->rt_flags = (short) strtoul (flag_ptr, NULL, 16);
+     rt->rt_metric = (short) strtoul (metric_ptr, NULL, 16);
      rt->rt_dev   = dev_ptr;
  
      return 1;
***************
*** 1302,1315 ****
        struct in_addr old_gateway =
          ((struct sockaddr_in *) (&rt.rt_gateway))-> sin_addr;
  
!       if (old_gateway.s_addr != gateway)
          {
            syslog (LOG_ERR,
                    "not replacing existing default route to %s [%s]",
                    rt.rt_dev,
                    inet_ntoa (old_gateway));
          }
-       return 0;
        }
  
      memset (&rt, '\0', sizeof (rt));
--- 1307,1327 ----
        struct in_addr old_gateway =
          ((struct sockaddr_in *) (&rt.rt_gateway))-> sin_addr;
  
!       /* if the existing default route is for another gateway, check
!            the metric value and if it is the same metric do not add
!            the new route or that would cause a route conflict
!          NOTE: Can this all be reduced to just checking the metric and
!                 not the gateway addr? Why does linux only do the 
checking
!               for conflicts?
!          */
!       if ((old_gateway.s_addr != gateway) && (rt.rt_metric==0))
          {
            syslog (LOG_ERR,
                    "not replacing existing default route to %s [%s]",
                    rt.rt_dev,
                    inet_ntoa (old_gateway));
+           return 0;   /* do not add only if it creates a clear conflict */
          }
        }
  
      memset (&rt, '\0', sizeof (rt));


-
To unsubscribe from this list: send the line "unsubscribe linux-ppp" in
the body of a message to [EMAIL PROTECTED]

Reply via email to