#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <limits.h>
#include <inttypes.h>
+#include <net/if.h>
-#include "pppd.h"
+#include "pppd-private.h"
+#include "options.h"
#include "magic.h"
#include "fsm.h"
#include "lcp.h"
#include "ipcp.h"
-#ifdef INET6
+#ifdef PPP_WITH_IPV6CP
#include "ipv6cp.h"
#endif
#include "upap.h"
-#include "chap-new.h"
+#include "chap.h"
#include "eap.h"
#include "ccp.h"
#include "ecp.h"
#include "pathnames.h"
+#include "crypto.h"
+#include "multilink.h"
-#ifdef USE_TDB
+#ifdef PPP_WITH_TDB
#include "tdb.h"
#endif
-#ifdef CBCP_SUPPORT
+#ifdef PPP_WITH_CBCP
#include "cbcp.h"
#endif
-#ifdef IPX_CHANGE
-#include "ipxcp.h"
-#endif /* IPX_CHANGE */
#ifdef AT_CHANGE
#include "atcp.h"
#endif
-
/* interface vars */
char ifname[IFNAMSIZ]; /* Interface name */
int ifunit; /* Interface unit number */
char hostname[MAXNAMELEN]; /* Our hostname */
static char pidfilename[MAXPATHLEN]; /* name of pid file */
static char linkpidfile[MAXPATHLEN]; /* name of linkname pid file */
-char ppp_devnam[MAXPATHLEN]; /* name of PPP tty (maybe ttypx) */
uid_t uid; /* Our real user-id */
struct notifier *pidchange = NULL;
struct notifier *phasechange = NULL;
int privileged; /* we're running as real uid root */
int need_holdoff; /* need holdoff period before restarting */
int detached; /* have detached from terminal */
-volatile int status; /* exit status for pppd */
+volatile int code; /* exit status for pppd */
int unsuccess; /* # unsuccessful connection attempts */
int do_callback; /* != 0 if we should do callback next */
int doing_callback; /* != 0 if we are doing callback */
concept (eg PPPoE) */
int childwait_done; /* have timed out waiting for children */
-#ifdef USE_TDB
+#ifdef PPP_WITH_TDB
TDB_CONTEXT *pppdb; /* database for storing status etc. */
#endif
int fd_devnull; /* fd for /dev/null */
int devfd = -1; /* fd of underlying device */
int fd_ppp = -1; /* fd for talking PPP */
-int phase; /* where the link is at */
+ppp_phase_t phase; /* where the link is at */
int kill_link;
int asked_to_quit;
int open_ccp_flag;
struct pppd_stats link_stats;
unsigned link_connect_time;
int link_stats_valid;
+int link_stats_print;
int error_count;
static int reap_kids(void);
static void childwait_end(void *);
-#ifdef USE_TDB
+#ifdef PPP_WITH_TDB
static void update_db_entry(void);
static void add_db_key(const char *);
static void delete_db_key(const char *);
extern char *getlogin(void);
int main(int, char *[]);
+const char *ppp_hostname()
+{
+ return hostname;
+}
+
+bool ppp_signaled(int sig)
+{
+ if (sig == SIGTERM)
+ return !!got_sigterm;
+ if (sig == SIGUSR2)
+ return !!got_sigusr2;
+ if (sig == SIGHUP)
+ return !!got_sighup;
+ return false;
+}
+
+ppp_exit_code_t ppp_status()
+{
+ return code;
+}
+
+void ppp_set_status(ppp_exit_code_t value)
+{
+ code = value;
+}
+
+void ppp_set_session_number(int number)
+{
+ ppp_session_number = number;
+}
+
+int ppp_get_session_number()
+{
+ return ppp_session_number;
+}
+
+const char *ppp_ifname()
+{
+ return ifname;
+}
+
+int ppp_get_ifname(char *buf, size_t bufsz)
+{
+ if (buf) {
+ return strlcpy(buf, ifname, bufsz);
+ }
+ return false;
+}
+
+void ppp_set_ifname(const char *name)
+{
+ if (name) {
+ strlcpy(ifname, name, sizeof(ifname));
+ }
+}
+
+int ppp_ifunit()
+{
+ return ifunit;
+}
+
+int ppp_get_link_uptime()
+{
+ return link_connect_time;
+}
+
/*
* PPP Data Link Layer "protocol" table.
* One entry per supported protocol.
&lcp_protent,
&pap_protent,
&chap_protent,
-#ifdef CBCP_SUPPORT
+#ifdef PPP_WITH_CBCP
&cbcp_protent,
#endif
&ipcp_protent,
-#ifdef INET6
+#ifdef PPP_WITH_IPV6CP
&ipv6cp_protent,
#endif
&ccp_protent,
&ecp_protent,
-#ifdef IPX_CHANGE
- &ipxcp_protent,
-#endif
#ifdef AT_CHANGE
&atcp_protent,
#endif
struct protent *protp;
char numbuf[16];
- strlcpy(path_ipup, _PATH_IPUP, sizeof(path_ipup));
- strlcpy(path_ipdown, _PATH_IPDOWN, sizeof(path_ipdown));
+ PPP_crypto_init();
+
+ strlcpy(path_ipup, PPP_PATH_IPUP, MAXPATHLEN);
+ strlcpy(path_ipdown, PPP_PATH_IPDOWN, MAXPATHLEN);
-#ifdef INET6
- strlcpy(path_ipv6up, _PATH_IPV6UP, sizeof(path_ipv6up));
- strlcpy(path_ipv6down, _PATH_IPV6DOWN, sizeof(path_ipv6down));
+#ifdef PPP_WITH_IPV6CP
+ strlcpy(path_ipv6up, PPP_PATH_IPV6UP, MAXPATHLEN);
+ strlcpy(path_ipv6down, PPP_PATH_IPV6DOWN, MAXPATHLEN);
#endif
link_stats_valid = 0;
+ link_stats_print = 1;
new_phase(PHASE_INITIALIZE);
script_env = NULL;
/* Initialize syslog facilities */
reopen_log();
- if (gethostname(hostname, MAXNAMELEN) < 0 ) {
- option_error("Couldn't get hostname: %m");
+ if (gethostname(hostname, sizeof(hostname)) < 0 ) {
+ ppp_option_error("Couldn't get hostname: %m");
exit(1);
}
hostname[MAXNAMELEN-1] = 0;
uid = getuid();
privileged = uid == 0;
slprintf(numbuf, sizeof(numbuf), "%d", uid);
- script_setenv("ORIG_UID", numbuf, 0);
+ ppp_script_setenv("ORIG_UID", numbuf, 0);
ngroups = getgroups(NGROUPS_MAX, groups);
* Parse, in order, the system options file, the user's options file,
* and the command line arguments.
*/
- if (!options_from_file(_PATH_SYSOPTIONS, !privileged, 0, 1)
+ if (!ppp_options_from_file(PPP_PATH_SYSOPTIONS, !privileged, 0, 1)
|| !options_from_user()
|| !parse_args(argc-1, argv+1))
exit(EXIT_OPTION_ERROR);
if (debug)
setlogmask(LOG_UPTO(LOG_DEBUG));
+ if (show_options) {
+ showopts();
+ die(0);
+ }
+
/*
* Check that we are running as root.
*/
if (geteuid() != 0) {
- option_error("must be root to run %s, since it is not setuid-root",
+ ppp_option_error("must be root to run %s, since it is not setuid-root",
argv[0]);
exit(EXIT_NOT_ROOT);
}
- if (!ppp_available()) {
- option_error("%s", no_ppp_msg);
+ if (!ppp_check_kernel_support()) {
+ ppp_option_error("%s", no_ppp_msg);
exit(EXIT_NO_KERNEL_SUPPORT);
}
if (!sys_check_options())
exit(EXIT_OPTION_ERROR);
auth_check_options();
-#ifdef HAVE_MULTILINK
mp_check_options();
-#endif
for (i = 0; (protp = protocols[i]) != NULL; ++i)
if (protp->check_options != NULL)
(*protp->check_options)();
die(0);
/* Make sure fds 0, 1, 2 are open to somewhere. */
- fd_devnull = open(_PATH_DEVNULL, O_RDWR);
+ fd_devnull = open(PPP_DEVNULL, O_RDWR);
if (fd_devnull < 0)
- fatal("Couldn't open %s: %m", _PATH_DEVNULL);
+ fatal("Couldn't open %s: %m", PPP_DEVNULL);
while (fd_devnull <= 2) {
i = dup(fd_devnull);
if (i < 0)
*/
sys_init();
-#ifdef USE_TDB
- pppdb = tdb_open(_PATH_PPPDB, 0, 0, O_RDWR|O_CREAT, 0644);
+#ifdef PPP_WITH_TDB
+ pppdb = tdb_open(PPP_PATH_PPPDB, 0, 0, O_RDWR|O_CREAT, 0644);
if (pppdb != NULL) {
slprintf(db_key, sizeof(db_key), "pppd%d", getpid());
update_db_entry();
} else {
- warn("Warning: couldn't open ppp database %s", _PATH_PPPDB);
+ warn("Warning: couldn't open ppp database %s", PPP_PATH_PPPDB);
if (multilink) {
warn("Warning: disabling multilink");
multilink = 0;
p = "(unknown)";
}
syslog(LOG_NOTICE, "pppd %s started by %s, uid %d", VERSION, p, uid);
- script_setenv("PPPLOGNAME", p, 0);
+ ppp_script_setenv("PPPLOGNAME", p, 0);
if (devnam[0])
- script_setenv("DEVICE", devnam, 1);
+ ppp_script_setenv("DEVICE", devnam, 1);
slprintf(numbuf, sizeof(numbuf), "%d", getpid());
- script_setenv("PPPD_PID", numbuf, 1);
+ ppp_script_setenv("PPPD_PID", numbuf, 1);
setup_signals();
listen_time = 0;
need_holdoff = 1;
devfd = -1;
- status = EXIT_OK;
+ code = EXIT_OK;
++unsuccess;
doing_callback = do_callback;
do_callback = 0;
info("Starting link");
}
- get_time(&start_time);
- script_unsetenv("CONNECT_TIME");
- script_unsetenv("BYTES_SENT");
- script_unsetenv("BYTES_RCVD");
+ ppp_get_time(&start_time);
+ ppp_script_unsetenv("CONNECT_TIME");
+ ppp_script_unsetenv("BYTES_SENT");
+ ppp_script_unsetenv("BYTES_RCVD");
lcp_open(0); /* Start protocol */
start_link(0);
}
}
- die(status);
+ PPP_crypto_deinit();
+ die(code);
return 0;
}
info("Hangup (SIGHUP)");
kill_link = 1;
got_sighup = 0;
- if (status != EXIT_HANGUP)
- status = EXIT_USER_REQUEST;
+ if (code != EXIT_HANGUP)
+ code = EXIT_USER_REQUEST;
}
if (got_sigterm) {
info("Terminating on signal %d", got_sigterm);
kill_link = 1;
asked_to_quit = 1;
persist = 0;
- status = EXIT_USER_REQUEST;
+ code = EXIT_USER_REQUEST;
got_sigterm = 0;
}
if (got_sigchld) {
else
slprintf(ifname, sizeof(ifname), "%s%d", PPP_DRV_NAME, ifunit);
info("Using interface %s", ifname);
- script_setenv("IFNAME", ifname, iskey);
+ ppp_script_setenv("IFNAME", ifname, iskey);
slprintf(ifkey, sizeof(ifkey), "%d", ifunit);
- script_setenv("UNIT", ifkey, iskey);
+ ppp_script_setenv("UNIT", ifkey, iskey);
if (iskey) {
create_pidfile(getpid()); /* write pid to file */
create_linkpidfile(getpid());
if (log_default)
log_to_fd = -1;
slprintf(numbuf, sizeof(numbuf), "%d", getpid());
- script_setenv("PPPD_PID", numbuf, 1);
+ ppp_script_setenv("PPPD_PID", numbuf, 1);
/* wait for parent to finish updating pid & lock files and die */
close(pipefd[1]);
FILE *pidfile;
slprintf(pidfilename, sizeof(pidfilename), "%s%s.pid",
- _PATH_VARRUN, ifname);
+ PPP_PATH_VARRUN, ifname);
if ((pidfile = fopen(pidfilename, "w")) != NULL) {
fprintf(pidfile, "%d\n", pid);
(void) fclose(pidfile);
if (linkname[0] == 0)
return;
- script_setenv("LINKNAME", linkname, 1);
+ ppp_script_setenv("LINKNAME", linkname, 1);
slprintf(linkpidfile, sizeof(linkpidfile), "%sppp-%s.pid",
- _PATH_VARRUN, linkname);
+ PPP_PATH_VARRUN, linkname);
if ((pidfile = fopen(linkpidfile, "w")) != NULL) {
fprintf(pidfile, "%d\n", pid);
if (ifname[0])
return;
if (len == 0) {
- if (bundle_eof && multilink_master) {
+ if (bundle_eof && mp_master()) {
notice("Last channel has disconnected");
mp_bundle_terminated();
return;
}
notice("Modem hangup");
hungup = 1;
- status = EXIT_HANGUP;
+ code = EXIT_HANGUP;
lcp_lowerdown(0); /* serial link is no longer available */
link_terminated(0);
return;
* new_phase - signal the start of a new phase of pppd's operation.
*/
void
-new_phase(int p)
+new_phase(ppp_phase_t p)
{
phase = p;
if (new_phase_hook)
notify(phasechange, p);
}
+bool
+in_phase(ppp_phase_t p)
+{
+ return (phase == p);
+}
+
/*
* die - clean up state and exit with the specified status.
*/
void
die(int status)
{
- if (!doing_multilink || multilink_master)
+
+ if (!mp_on() || mp_master())
print_link_stats();
cleanup();
notify(exitnotify, status);
(*the_channel->cleanup)();
remove_pidfiles();
-#ifdef USE_TDB
+#ifdef PPP_WITH_TDB
if (pppdb != NULL)
cleanup_db();
#endif
/*
* Print connect time and statistics.
*/
- if (link_stats_valid) {
+ if (link_stats_print && link_stats_valid) {
int t = (link_connect_time + 5) / 6; /* 1/10ths of minutes */
info("Connect time %d.%d minutes.", t/10, t%10);
info("Sent %u bytes, received %u bytes.",
link_stats.bytes_out, link_stats.bytes_in);
- link_stats_valid = 0;
+ link_stats_print = 0;
}
}
{
if (!get_ppp_stats(u, &old_link_stats))
return;
- get_time(&start_time);
+ ppp_get_time(&start_time);
}
/*
char numbuf[32];
if (!get_ppp_stats(u, &link_stats)
- || get_time(&now) < 0)
+ || ppp_get_time(&now) < 0)
return;
link_connect_time = now.tv_sec - start_time.tv_sec;
link_stats_valid = 1;
link_stats.pkts_out -= old_link_stats.pkts_out;
slprintf(numbuf, sizeof(numbuf), "%u", link_connect_time);
- script_setenv("CONNECT_TIME", numbuf, 0);
+ ppp_script_setenv("CONNECT_TIME", numbuf, 0);
snprintf(numbuf, sizeof(numbuf), "%" PRIu64, link_stats.bytes_out);
- script_setenv("BYTES_SENT", numbuf, 0);
+ ppp_script_setenv("BYTES_SENT", numbuf, 0);
snprintf(numbuf, sizeof(numbuf), "%" PRIu64, link_stats.bytes_in);
- script_setenv("BYTES_RCVD", numbuf, 0);
+ ppp_script_setenv("BYTES_RCVD", numbuf, 0);
+}
+
+bool
+ppp_get_link_stats(ppp_link_stats_st *stats)
+{
+ update_link_stats(0);
+ if (stats != NULL &&
+ link_stats_valid) {
+
+ memcpy(stats, &link_stats, sizeof(*stats));
+ return true;
+ }
+ return false;
}
* timeout - Schedule a timeout.
*/
void
-timeout(void (*func)(void *), void *arg, int secs, int usecs)
+ppp_timeout(void (*func)(void *), void *arg, int secs, int usecs)
{
struct callout *newp, *p, **pp;
fatal("Out of memory in timeout()!");
newp->c_arg = arg;
newp->c_func = func;
- get_time(&timenow);
+ ppp_get_time(&timenow);
newp->c_time.tv_sec = timenow.tv_sec + secs;
newp->c_time.tv_usec = timenow.tv_usec + usecs;
if (newp->c_time.tv_usec >= 1000000) {
* untimeout - Unschedule a timeout.
*/
void
-untimeout(void (*func)(void *), void *arg)
+ppp_untimeout(void (*func)(void *), void *arg)
{
struct callout **copp, *freep;
while (callout != NULL) {
p = callout;
- if (get_time(&timenow) < 0)
+ if (ppp_get_time(&timenow) < 0)
fatal("Failed to get time of day: %m");
if (!(p->c_time.tv_sec < timenow.tv_sec
|| (p->c_time.tv_sec == timenow.tv_sec
if (callout == NULL)
return NULL;
- get_time(&timenow);
+ ppp_get_time(&timenow);
tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec;
tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec;
if (tvp->tv_usec < 0) {
}
/*
- * safe_fork - Create a child process. The child closes all the
+ * ppp_safe_fork - Create a child process. The child closes all the
* file descriptors that we don't want to leak to a script.
* The parent waits for the child to do this before returning.
* This also arranges for the specified fds to be dup'd to
* fds 0, 1, 2 in the child.
*/
pid_t
-safe_fork(int infd, int outfd, int errfd)
+ppp_safe_fork(int infd, int outfd, int errfd)
{
pid_t pid;
int fd, pipefd[2];
}
/* Executing in the child */
- sys_close();
-#ifdef USE_TDB
+ ppp_sys_close();
+#ifdef PPP_WITH_TDB
if (pppdb != NULL)
tdb_close(pppdb);
#endif
/*
* device_script - run a program to talk to the specified fds
* (e.g. to run the connector or disconnector script).
- * stderr gets connected to the log fd or to the _PATH_CONNERRS file.
+ * stderr gets connected to the log fd or to the PPP_PATH_CONNERRS file.
*/
int
device_script(char *program, int in, int out, int dont_wait)
if (log_to_fd >= 0)
errfd = log_to_fd;
else
- errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0644);
+ errfd = open(PPP_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0644);
++conn_running;
- pid = safe_fork(in, out, errfd);
+ pid = ppp_safe_fork(in, out, errfd);
if (pid != 0 && log_to_fd < 0)
close(errfd);
* and update the script environment. Note that we intentionally do
* not update the TDB. These changes are layered on top right before
* exec. It is not possible to use script_setenv() or
- * script_unsetenv() safely after this routine is run.
+ * ppp_script_unsetenv() safely after this routine is run.
*/
static void
update_script_environment(void)
* reap_kids) iff the return value is > 0.
*/
pid_t
-run_program(char *prog, char **args, int must_exist, void (*done)(void *), void *arg, int wait)
+run_program(char *prog, char * const *args, int must_exist, void (*done)(void *), void *arg, int wait)
{
int pid, status, ret;
struct stat sbuf;
return 0;
}
- pid = safe_fork(fd_devnull, fd_devnull, fd_devnull);
+ pid = ppp_safe_fork(fd_devnull, fd_devnull, fd_devnull);
if (pid == -1) {
error("Failed to create child process for %s: %m", prog);
return -1;
return 0;
}
+
+struct notifier **get_notifier_by_type(ppp_notify_t type)
+{
+ struct notifier **list[NF_MAX_NOTIFY] = {
+ [NF_PID_CHANGE ] = &pidchange,
+ [NF_PHASE_CHANGE] = &phasechange,
+ [NF_EXIT ] = &exitnotify,
+ [NF_SIGNALED ] = &sigreceived,
+ [NF_IP_UP ] = &ip_up_notifier,
+ [NF_IP_DOWN ] = &ip_down_notifier,
+#ifdef PPP_WITH_IPV6CP
+ [NF_IPV6_UP ] = &ipv6_up_notifier,
+ [NF_IPV6_DOWN ] = &ipv6_down_notifier,
+#endif
+ [NF_AUTH_UP ] = &auth_up_notifier,
+ [NF_LINK_DOWN ] = &link_down_notifier,
+ [NF_FORK ] = &fork_notifier,
+ };
+ return list[type];
+}
+
/*
* add_notifier - add a new function to be called when something happens.
*/
void
-add_notifier(struct notifier **notif, notify_func func, void *arg)
+ppp_add_notify(ppp_notify_t type, ppp_notify_fn *func, void *arg)
{
- struct notifier *np;
-
- np = malloc(sizeof(struct notifier));
- if (np == 0)
- novm("notifier struct");
- np->next = *notif;
- np->func = func;
- np->arg = arg;
- *notif = np;
+ struct notifier **notif = get_notifier_by_type(type);
+ if (notif) {
+
+ struct notifier *np = malloc(sizeof(struct notifier));
+ if (np == 0)
+ novm("notifier struct");
+ np->next = *notif;
+ np->func = func;
+ np->arg = arg;
+ *notif = np;
+ } else {
+ error("Could not find notifier function for: %d", type);
+ }
}
/*
* be called when something happens.
*/
void
-remove_notifier(struct notifier **notif, notify_func func, void *arg)
+ppp_del_notify(ppp_notify_t type, ppp_notify_fn *func, void *arg)
{
- struct notifier *np;
-
- for (; (np = *notif) != 0; notif = &np->next) {
- if (np->func == func && np->arg == arg) {
- *notif = np->next;
- free(np);
- break;
+ struct notifier **notif = get_notifier_by_type(type);
+ if (notif) {
+ struct notifier *np;
+
+ for (; (np = *notif) != 0; notif = &np->next) {
+ if (np->func == func && np->arg == arg) {
+ *notif = np->next;
+ free(np);
+ break;
+ }
}
+ } else {
+ error("Could not find notifier function for: %d", type);
}
}
}
/*
- * script_setenv - set an environment variable value to be used
+ * ppp_script_setenv - set an environment variable value to be used
* for scripts that we run (e.g. ip-up, auth-up, etc.)
*/
void
-script_setenv(char *var, char *value, int iskey)
+ppp_script_setenv(char *var, char *value, int iskey)
{
size_t varl = strlen(var);
size_t vl = varl + strlen(value) + 2;
if (script_env != 0) {
for (i = 0; (p = script_env[i]) != 0; ++i) {
if (strncmp(p, var, varl) == 0 && p[varl] == '=') {
-#ifdef USE_TDB
+#ifdef PPP_WITH_TDB
if (p[-1] && pppdb != NULL)
delete_db_key(p);
#endif
free(p-1);
script_env[i] = newstring;
-#ifdef USE_TDB
+#ifdef PPP_WITH_TDB
if (pppdb != NULL) {
if (iskey)
add_db_key(newstring);
if (!add_script_env(i, newstring))
return;
-#ifdef USE_TDB
+#ifdef PPP_WITH_TDB
if (pppdb != NULL) {
if (iskey)
add_db_key(newstring);
}
/*
- * script_unsetenv - remove a variable from the environment
+ * ppp_script_unsetenv - remove a variable from the environment
* for scripts.
*/
void
-script_unsetenv(char *var)
+ppp_script_unsetenv(char *var)
{
int vl = strlen(var);
int i;
return;
for (i = 0; (p = script_env[i]) != 0; ++i) {
if (strncmp(p, var, vl) == 0 && p[vl] == '=') {
-#ifdef USE_TDB
+#ifdef PPP_WITH_TDB
if (p[-1] && pppdb != NULL)
delete_db_key(p);
#endif
break;
}
}
-#ifdef USE_TDB
+#ifdef PPP_WITH_TDB
if (pppdb != NULL)
update_db_entry();
#endif
*/
void lock_db(void)
{
-#ifdef USE_TDB
+#ifdef PPP_WITH_TDB
TDB_DATA key;
key.dptr = PPPD_LOCK_KEY;
*/
void unlock_db(void)
{
-#ifdef USE_TDB
+#ifdef PPP_WITH_TDB
TDB_DATA key;
key.dptr = PPPD_LOCK_KEY;
#endif
}
-#ifdef USE_TDB
+#ifdef PPP_WITH_TDB
/*
* update_db_entry - update our entry in the database.
*/
if (p[-1])
delete_db_key(p);
}
-#endif /* USE_TDB */
+#endif /* PPP_WITH_TDB */