From 7b6f872d110924a8437349cf70a322dd6f8bb823 Mon Sep 17 00:00:00 2001 From: martin Date: Thu, 10 Jan 2002 20:21:50 +0000 Subject: [PATCH] Add, #ifdef SPPP_IF_SUPPORT, special case treatment for sys/net/if_spppsubr.c based interfaces. Note: all other interface types work the same as before, and no names are hardcoded. When a if_spppsubr.c based interface is marked IFF_UP, but has not yet reached phase NETWORK (i.e. it didn't connect yet or authentication has not yet completed) do not call the ip-up script for it on the initial pass over all IFF_UP interfaces. This fixes a race condition on startup when ip-up/ip-down are statefull and need to be called pairwise (for example if ip-up adds and ip-down removes a default route). --- usr.sbin/ifwatchd/ifwatchd.c | 51 +++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/usr.sbin/ifwatchd/ifwatchd.c b/usr.sbin/ifwatchd/ifwatchd.c index e97a4d8b4ef0..c82158512fcf 100644 --- a/usr.sbin/ifwatchd/ifwatchd.c +++ b/usr.sbin/ifwatchd/ifwatchd.c @@ -1,7 +1,7 @@ -/* $NetBSD: ifwatchd.c,v 1.4 2002/01/10 19:38:51 martin Exp $ */ +/* $NetBSD: ifwatchd.c,v 1.5 2002/01/10 20:21:50 martin Exp $ */ /* - * Copyright (c) 2001 Martin Husemann + * Copyright (c) 2001-2002 Martin Husemann * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,6 +24,11 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* + * Define this for special treatment of sys/net/if_spppsubr.c based interfaces. + */ +#define SPPP_IF_SUPPORT + #include #include #include @@ -31,6 +36,9 @@ #include #include #include +#ifdef SPPP_IF_SUPPORT +#include +#endif #include #include #include @@ -54,6 +62,12 @@ static void free_interfaces(void); static int find_interface(int index); static void run_initial_ups(void); +#ifdef SPPP_IF_SUPPORT +static int if_is_connected(const char * ifname); +#else +#define if_is_connected(X) 1 +#endif + /* stolen from /sbin/route */ #define ROUNDUP(a) \ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) @@ -339,7 +353,8 @@ static void run_initial_ups() continue; SLIST_FOREACH(ifd, &ifs, next) { if (strcmp(ifd->ifname, p->ifa_name) == 0) { - invoke_script(p->ifa_addr, p->ifa_dstaddr, 1, ifd->index); + if (if_is_connected(ifd->ifname)) + invoke_script(p->ifa_addr, p->ifa_dstaddr, 1, ifd->index); break; } } @@ -347,3 +362,33 @@ static void run_initial_ups() freeifaddrs(res); } } + +#ifdef SPPP_IF_SUPPORT +/* + * Special case support for in-kernel PPP interfaces. + * If these are IFF_UP, but have not yet connected or completed authentication + * we don't want to call the up script in the initial interface scan (there + * will be an UP event generated later, when IPCP completes, anyway). + * + * If this is no if_spppsubr.c based interface, this ioctl just fails and we + * treat is as connected. + */ +static int +if_is_connected(const char * ifname) +{ + int s, err; + struct spppstatus status; + + memset(&status, 0, sizeof status); + strncpy(status.ifname, ifname, sizeof status.ifname); + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s < 0) + return 1; /* no idea how to handle this... */ + err = ioctl(s, SPPPGETSTATUS, &status); + if (err != 0) + /* not if_spppsubr.c based - call it connected */ + status.phase = SPPP_PHASE_NETWORK; + close(s); + return status.phase == SPPP_PHASE_NETWORK; +} +#endif