From 3f2fe49d822135c209e9896f666b748cf2234f2e Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 13 Apr 2000 12:06:00 +0000 Subject: [PATCH] Multilink cleanups and fixes. We don't need to include multilink.o now if HAVE_MULTILINK is not defined. --- pppd/Makefile.sol2 | 5 +-- pppd/auth.c | 10 +++-- pppd/lcp.c | 6 ++- pppd/main.c | 68 +++++++++++++++++++++++---------- pppd/multilink.c | 93 +++++++++++++++++++++++++++++++++------------- pppd/sys-linux.c | 53 +++++++++++++------------- 6 files changed, 156 insertions(+), 79 deletions(-) diff --git a/pppd/Makefile.sol2 b/pppd/Makefile.sol2 index a25fd17..835acc2 100644 --- a/pppd/Makefile.sol2 +++ b/pppd/Makefile.sol2 @@ -1,6 +1,6 @@ # # Makefile for pppd under Solaris 2. -# $Id: Makefile.sol2,v 1.17 2000/04/06 23:03:28 masputra Exp $ +# $Id: Makefile.sol2,v 1.18 2000/04/13 12:05:57 paulus Exp $ # include ../svr4/Makedefs @@ -10,8 +10,7 @@ CFLAGS = -I../include -DSVR4 -DSOL2 $(COPTS) LIBS = -lsocket -lnsl OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o \ - ccp.o auth.o options.o demand.o utils.o sys-svr4.o tdb.o \ - multilink.o + ccp.o auth.o options.o demand.o utils.o sys-svr4.o tdb.o # # uncomment the following to enable plugins diff --git a/pppd/auth.c b/pppd/auth.c index e97b48e..023653d 100644 --- a/pppd/auth.c +++ b/pppd/auth.c @@ -32,7 +32,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define RCSID "$Id: auth.c,v 1.63 2000/04/04 07:06:49 paulus Exp $" +#define RCSID "$Id: auth.c,v 1.64 2000/04/13 12:05:57 paulus Exp $" #include #include @@ -511,9 +511,13 @@ start_networks() new_phase(PHASE_NETWORK); #ifdef HAVE_MULTILINK - if (multilink) - if (mp_join_bundle()) + if (multilink) { + if (mp_join_bundle()) { + if (updetach && !nodetach) + detach(); return; + } + } #endif /* HAVE_MULTILINK */ #if 0 diff --git a/pppd/lcp.c b/pppd/lcp.c index 1241bfb..ff17fb0 100644 --- a/pppd/lcp.c +++ b/pppd/lcp.c @@ -17,7 +17,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define RCSID "$Id: lcp.c,v 1.50 2000/04/05 00:58:28 paulus Exp $"; +#define RCSID "$Id: lcp.c,v 1.51 2000/04/13 12:05:57 paulus Exp $"; /* * TODO: @@ -1955,6 +1955,7 @@ lcp_printpkt(p, plen, printer, arg) } break; case CI_EPDISC: +#ifdef HAVE_MULTILINK if (olen >= CILEN_CHAR) { struct epdisc epd; p += 2; @@ -1968,6 +1969,9 @@ lcp_printpkt(p, plen, printer, arg) } printer(arg, "endpoint [%s]", epdisc_to_str(&epd)); } +#else + printer(arg, "endpoint"); +#endif break; } while (p < optend) { diff --git a/pppd/main.c b/pppd/main.c index 5b57e99..ca6e50a 100644 --- a/pppd/main.c +++ b/pppd/main.c @@ -17,7 +17,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define RCSID "$Id: main.c,v 1.92 2000/04/04 07:06:51 paulus Exp $" +#define RCSID "$Id: main.c,v 1.93 2000/04/13 12:05:59 paulus Exp $" #include #include @@ -179,6 +179,7 @@ static void record_child __P((int, char *, void (*) (void *), void *)); static void update_db_entry __P((void)); static void add_db_key __P((const char *)); static void delete_db_key __P((const char *)); +static void cleanup_db __P((void)); static int open_socket __P((char *)); static int start_charshunt __P((int, int)); static void charshunt_done __P((void *)); @@ -416,7 +417,7 @@ main(argc, argv) if (debug) setlogmask(LOG_UPTO(LOG_DEBUG)); - pppdb = tdb_open(_PATH_PPPDB, 0, TDB_CLEAR_IF_FIRST, O_RDWR|O_CREAT, 0644); + pppdb = tdb_open(_PATH_PPPDB, 0, 0, O_RDWR|O_CREAT, 0644); if (pppdb != NULL) { slprintf(db_key, sizeof(db_key), "pppd%d", getpid()); update_db_entry(); @@ -448,6 +449,8 @@ main(argc, argv) if (devnam[0]) script_setenv("DEVICE", devnam, 1); + slprintf(numbuf, sizeof(numbuf), "%d", getpid()); + script_setenv("PPPD_PID", numbuf, 1); setup_signals(); @@ -462,8 +465,10 @@ main(argc, argv) /* * Open the loopback channel and set it up to be the ppp interface. */ + tdb_writelock(pppdb); fd_loop = open_ppp_loopback(); set_ifunit(1); + tdb_writeunlock(pppdb); /* * Configure the interface and mark it up, etc. @@ -720,14 +725,17 @@ main(argc, argv) } /* set up the serial device as a ppp interface */ + tdb_writelock(pppdb); fd_ppp = establish_ppp(ttyfd); if (fd_ppp < 0) { + tdb_writeunlock(pppdb); status = EXIT_FATAL_ERROR; goto disconnect; } if (!demand && ifunit >= 0) set_ifunit(1); + tdb_writeunlock(pppdb); /* * Start opening the connection and wait for @@ -822,6 +830,8 @@ main(argc, argv) fd_ppp = -1; if (!hungup) lcp_lowerdown(0); + if (!demand) + script_unsetenv("IFNAME"); /* * Run disconnector script, if requested. @@ -1018,6 +1028,7 @@ void detach() { int pid; + char numbuf[16]; if (detached) return; @@ -1037,12 +1048,15 @@ detach() close(1); close(2); detached = 1; - log_to_fd = -1; + if (!log_to_file && !log_to_specific_fd) + log_to_fd = -1; /* update pid files if they have been written already */ if (pidfilename[0]) create_pidfile(); if (linkpidfile[0]) create_linkpidfile(); + slprintf(numbuf, sizeof(numbuf), "%d", getpid()); + script_setenv("PPPD_PID", numbuf, 1); } /* @@ -1066,7 +1080,6 @@ static void create_pidfile() { FILE *pidfile; - char numbuf[16]; slprintf(pidfilename, sizeof(pidfilename), "%s%s.pid", _PATH_VARRUN, ifname); @@ -1077,8 +1090,6 @@ create_pidfile() error("Failed to create pid file %s: %m", pidfilename); pidfilename[0] = 0; } - slprintf(numbuf, sizeof(numbuf), "%d", getpid()); - script_setenv("PPPD_PID", numbuf, 1); } static void @@ -1088,6 +1099,7 @@ create_linkpidfile() if (linkname[0] == 0) return; + script_setenv("LINKNAME", linkname, 1); slprintf(linkpidfile, sizeof(linkpidfile), "%sppp-%s.pid", _PATH_VARRUN, linkname); if ((pidfile = fopen(linkpidfile, "w")) != NULL) { @@ -1099,7 +1111,6 @@ create_linkpidfile() error("Failed to create pid file %s: %m", linkpidfile); linkpidfile[0] = 0; } - script_setenv("LINKNAME", linkname, 1); } /* @@ -1327,13 +1338,8 @@ cleanup() if (locked) unlock(); - if (pppdb != NULL) { - TDB_DATA key; - - key.dptr = db_key; - key.dsize = strlen(db_key); - tdb_delete(pppdb, key); - } + if (pppdb != NULL) + cleanup_db(); } /* @@ -1934,21 +1940,23 @@ script_setenv(var, value, iskey) int i; char *p, *newstring; - newstring = (char *) malloc(vl); + newstring = (char *) malloc(vl+1); if (newstring == 0) return; + *newstring++ = iskey; slprintf(newstring, vl, "%s=%s", var, value); /* check if this variable is already set */ if (script_env != 0) { for (i = 0; (p = script_env[i]) != 0; ++i) { if (strncmp(p, var, varl) == 0 && p[varl] == '=') { - if (iskey && pppdb != NULL) { + if (p[-1] && pppdb != NULL) delete_db_key(p); - add_db_key(newstring); - } - free(p); + free(p-1); script_env[i] = newstring; + if (iskey && pppdb != NULL) + add_db_key(newstring); + update_db_entry(); return; } } @@ -1998,7 +2006,9 @@ script_unsetenv(var) return; for (i = 0; (p = script_env[i]) != 0; ++i) { if (strncmp(p, var, vl) == 0 && p[vl] == '=') { - free(p); + if (p[-1] && pppdb != NULL) + delete_db_key(p); + free(p-1); while ((script_env[i] = script_env[i+1]) != 0) ++i; break; @@ -2070,6 +2080,24 @@ delete_db_key(str) tdb_delete(pppdb, key); } +/* + * cleanup_db - delete all the entries we put in the database. + */ +static void +cleanup_db() +{ + TDB_DATA key; + int i; + char *p; + + key.dptr = db_key; + key.dsize = strlen(db_key); + tdb_delete(pppdb, key); + for (i = 0; (p = script_env[i]) != 0; ++i) + if (p[-1]) + delete_db_key(p); +} + /* * open_socket - establish a stream socket connection to the nominated * host and port. diff --git a/pppd/multilink.c b/pppd/multilink.c index 596fd81..546fcae 100644 --- a/pppd/multilink.c +++ b/pppd/multilink.c @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include "pppd.h" @@ -31,6 +33,8 @@ extern TDB_CONTEXT *pppdb; extern char db_key[]; static int get_default_epdisc __P((struct epdisc *)); +static int parse_num __P((char *str, const char *key, int *valp)); +static int owns_unit __P((TDB_DATA pid, int unit)); #define set_ip_epdisc(ep, addr) do { \ ep->length = 4; \ @@ -45,7 +49,8 @@ static int get_default_epdisc __P((struct epdisc *)); || ((addr) & 0xfff00000) == 0xac100000 /* 172.16.x.x */ \ || ((addr) & 0xffff0000) == 0xc0a80000) /* 192.168.x.x */ -#ifdef HAVE_MULTILINK +#define process_exists(n) (kill(0, (n)) == 0 || errno != ESRCH) + void mp_check_options() { @@ -67,13 +72,11 @@ mp_check_options() /* get a default endpoint value */ wo->neg_endpoint = get_default_epdisc(&wo->endpoint); if (wo->neg_endpoint) - info("using default endpoint %s", - epdisc_to_str(&wo->endpoint)); + dbglog("using default endpoint %s", + epdisc_to_str(&wo->endpoint)); } } -#endif /* HAVE_MULTILINK */ -#ifdef HAVE_MULTILINK /* * Make a new bundle or join us to an existing bundle * if we are doing multilink. @@ -83,9 +86,9 @@ mp_join_bundle() { lcp_options *go = &lcp_gotoptions[0]; lcp_options *ho = &lcp_hisoptions[0]; - int unit; - int i, l; - char *p, *endp; + int unit, pppd_pid; + int l; + char *p; TDB_DATA key, pid, rec; if (!go->neg_mrru || !ho->neg_mrru) { @@ -122,38 +125,39 @@ mp_join_bundle() epdisc_to_str(&ho->endpoint)); if (bundle_name) p += slprintf(p, bundle_id+l-p, "/%v", bundle_name); - info("bundle_id = %s", bundle_id+7); + dbglog("bundle_id = %s", bundle_id+7); /* * Check if the bundle ID is already in the database. */ unit = -1; + pppd_pid = -1; key.dptr = bundle_id; key.dsize = p - bundle_id; + tdb_writelock(pppdb); pid = tdb_fetch(pppdb, key); if (pid.dptr != NULL) { /* bundle ID exists, see if the pppd record still exists */ rec = tdb_fetch(pppdb, pid); if (rec.dptr != NULL) { /* it is, parse the interface number */ - p = strstr(rec.dptr, "IFNAME=ppp"); - if (p != 0) { - p += 10; /* skip to unit number */ - i = strtol(p, &endp, 10); - if (endp != p && (*endp == 0 || *endp == ';')) - unit = i; - } + parse_num(rec.dptr, "IFNAME=ppp", &unit); + /* check the pid value */ + parse_num(rec.dptr, "PPPD_PID=", &pppd_pid); + if (!process_exists(pppd_pid) || !owns_unit(pid, unit)) + unit = -1; free(rec.dptr); } free(pid.dptr); } if (unit >= 0) { - /* attach to existing unit */ + /* attach to existing unit, if the pid still exists */ if (bundle_attach(unit)) { - info("attached link to interface %d", ifunit); + dbglog("attached link to interface %d", ifunit); set_ifunit(0); script_setenv("BUNDLE", bundle_id + 7, 0); + tdb_writeunlock(pppdb); return 1; } /* attach failed because bundle doesn't exist */ @@ -163,11 +167,55 @@ mp_join_bundle() make_new_bundle(go->mrru, ho->mrru, go->neg_ssnhf, ho->neg_ssnhf); set_ifunit(1); script_setenv("BUNDLE", bundle_id + 7, 1); + tdb_writeunlock(pppdb); + return 0; +} + +static int +parse_num(str, key, valp) + char *str; + const char *key; + int *valp; +{ + char *p, *endp; + int i; + + p = strstr(str, key); + if (p != 0) { + p += strlen(key); + i = strtol(p, &endp, 10); + if (endp != p && (*endp == 0 || *endp == ';')) { + *valp = i; + return 1; + } + } return 0; } -#endif /* HAVE_MULTILINK */ -#ifdef /* HAVE_MULTILINK */ +/* + * Check whether the pppd identified by `key' still owns ppp unit `unit'. + */ +static int +owns_unit(key, unit) + TDB_DATA key; + int unit; +{ + char ifkey[32]; + TDB_DATA kd, vd; + int ret = 0; + + slprintf(ifkey, sizeof(ifkey), "IFNAME=ppp%d", unit); + kd.dptr = ifkey; + kd.dsize = strlen(ifkey); + vd = tdb_fetch(pppdb, kd); + if (vd.dptr != NULL) { + ret = vd.dsize == key.dsize + && memcmp(vd.dptr, key.dptr, vd.dsize) == 0; + free(vd.dptr); + } + return ret; +} + static int get_default_epdisc(ep) struct epdisc *ep; @@ -200,7 +248,6 @@ get_default_epdisc(ep) return 0; } -#endif /* HAVE_MULTILINK */ /* * epdisc_to_str - make a printable string from an endpoint discriminator. @@ -252,7 +299,6 @@ epdisc_to_str(ep) return str; } -#ifdef HAVE_MULTILINK static int hexc_val(int c) { if (c >= 'a') @@ -261,9 +307,7 @@ static int hexc_val(int c) return c - 'A' + 10; return c - '0'; } -#endif /* HAVE_MULTILINK */ -#ifdef HAVE_MULTILINK int str_to_epdisc(ep, str) struct epdisc *ep; @@ -332,5 +376,4 @@ str_to_epdisc(ep, str) dbglog("str_to_epdisc -> %s", epdisc_to_str(ep)); return 1; } -#endif /* HAVE_MULTILINK */ diff --git a/pppd/sys-linux.c b/pppd/sys-linux.c index 532fb13..88ab9dd 100644 --- a/pppd/sys-linux.c +++ b/pppd/sys-linux.c @@ -1846,35 +1846,34 @@ int ppp_available(void) sscanf(utsname.release, "%d.%d.%d", &osmaj, &osmin, &ospatch); kernel_version = KVERSION(osmaj, osmin, ospatch); - if (kernel_version >= KVERSION(2,3,13)) { - fd = open("/dev/ppp", O_RDWR); + fd = open("/dev/ppp", O_RDWR); #if 0 - if (fd < 0 && errno == ENOENT) { - /* try making it and see if that helps. */ - if (mknod("/dev/ppp", S_IFCHR | S_IRUSR | S_IWUSR, - makedev(108, 0)) >= 0) { - fd = open("/dev/ppp", O_RDWR); - if (fd >= 0) - info("Created /dev/ppp device node"); - else - unlink("/dev/ppp"); /* didn't work, undo the mknod */ - } else if (errno == EEXIST) { - fd = open("/dev/ppp", O_RDWR); - } + if (fd < 0 && errno == ENOENT) { + /* try making it and see if that helps. */ + if (mknod("/dev/ppp", S_IFCHR | S_IRUSR | S_IWUSR, + makedev(108, 0)) >= 0) { + fd = open("/dev/ppp", O_RDWR); + if (fd >= 0) + info("Created /dev/ppp device node"); + else + unlink("/dev/ppp"); /* didn't work, undo the mknod */ + } else if (errno == EEXIST) { + fd = open("/dev/ppp", O_RDWR); } + } #endif /* 0 */ - if (fd >= 0) { - new_style_driver = 1; - - /* XXX should get from driver */ - driver_version = 2; - driver_modification = 4; - driver_patch = 0; - close(fd); - return 1; - } - return 0; + if (fd >= 0) { + new_style_driver = 1; + + /* XXX should get from driver */ + driver_version = 2; + driver_modification = 4; + driver_patch = 0; + close(fd); + return 1; } + if (kernel_version >= KVERSION(2,3,13)) + return 0; /* * Open a socket for doing the ioctl operations. @@ -2671,8 +2670,8 @@ sys_check_options(void) return 0; } if (multilink && !new_style_driver) { - option_error("multilink is not supported by the kernel driver"); - return 0; + warn("Warning: multilink is not supported by the kernel driver"); + multilink = 0; } return 1; } -- 2.39.2