summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryasuoka <yasuoka@openbsd.org>2014-03-22 04:30:31 +0000
committeryasuoka <yasuoka@openbsd.org>2014-03-22 04:30:31 +0000
commit34682664ae5d4327113ce5bfff94b0e36c834919 (patch)
tree8007ae1ccd69b9955d0913b883793663cd851114
parentAdd an assert not to call radius_cancel_request() on callback. If the (diff)
downloadwireguard-openbsd-34682664ae5d4327113ce5bfff94b0e36c834919.tar.xz
wireguard-openbsd-34682664ae5d4327113ce5bfff94b0e36c834919.zip
Reimplement control part of npppd(8) with imsg. Also add "monitor"
command for npppctl(8) to monitor PPP session start/stop events.
-rw-r--r--usr.sbin/npppctl/Makefile4
-rw-r--r--usr.sbin/npppctl/npppctl.837
-rw-r--r--usr.sbin/npppctl/npppctl.c300
-rw-r--r--usr.sbin/npppctl/parser.c17
-rw-r--r--usr.sbin/npppctl/parser.h5
-rw-r--r--usr.sbin/npppd/common/debugutil.h1
-rw-r--r--usr.sbin/npppd/npppd/Makefile8
-rw-r--r--usr.sbin/npppd/npppd/control.c360
-rw-r--r--usr.sbin/npppd/npppd/npppd.c99
-rw-r--r--usr.sbin/npppd/npppd/npppd.h44
-rw-r--r--usr.sbin/npppd/npppd/npppd_config.c5
-rw-r--r--usr.sbin/npppd/npppd/npppd_ctl.c634
-rw-r--r--usr.sbin/npppd/npppd/npppd_ctl.h145
-rw-r--r--usr.sbin/npppd/npppd/npppd_local.h40
-rw-r--r--usr.sbin/npppd/npppd/ppp.c6
15 files changed, 961 insertions, 744 deletions
diff --git a/usr.sbin/npppctl/Makefile b/usr.sbin/npppctl/Makefile
index f2045c6139d..e9f27bd7380 100644
--- a/usr.sbin/npppctl/Makefile
+++ b/usr.sbin/npppctl/Makefile
@@ -1,8 +1,10 @@
-# $Id: Makefile,v 1.1 2012/01/18 03:13:04 yasuoka Exp $
+# $Id: Makefile,v 1.2 2014/03/22 04:30:31 yasuoka Exp $
WARNS= 2
PROG= npppctl
SRCS= npppctl.c parser.c
MAN= npppctl.8
CPPFLAGS+= -I${.CURDIR}/../npppd/npppd -I${.CURDIR}/../npppd/common
+LDADD+= -lutil
+DPADD+= ${LIBUTIL}
.include <bsd.prog.mk>
diff --git a/usr.sbin/npppctl/npppctl.8 b/usr.sbin/npppctl/npppctl.8
index 9814a666860..adbd6b014a3 100644
--- a/usr.sbin/npppctl/npppctl.8
+++ b/usr.sbin/npppctl/npppctl.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: npppctl.8,v 1.2 2012/09/18 13:14:08 yasuoka Exp $
+.\" $OpenBSD: npppctl.8,v 1.3 2014/03/22 04:30:31 yasuoka Exp $
.\"
.\" Copyright (c) 2012 Internet Initiative Japan Inc.
.\"
@@ -14,19 +14,17 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: September 18 2012 $
+.Dd $Mdocdate: March 22 2014 $
.Dt NPPPCTL 8
.Os
.Sh NAME
.Nm npppctl
.Nd control the npppd daemon
-.\" XXX .Xr npppd 8
+.Xr npppd 8
.Sh SYNOPSIS
.Nm
.Op Fl n
-.Op Fl r Ar rcvbuf_size
.Op Fl s Ar socket
-.Op Fl t Ar timeout_sec
.Ar command
.Op Ar argument ...
.Sh DESCRIPTION
@@ -41,26 +39,13 @@ The options are as follows:
.Bl -tag -width Ds
.It Fl n
Show IP addresses instead of their hostnames.
-.It Fl r Ar rcvbuf_size
-.Nm
-may fail if the receive buffer is not large enough for
-the requested information.
-Use
-.Ar rcvbuf_size
-to extend the receive buffer size instead of the default value of 131072.
-This must be greater than or equal to 2048.
.It Fl s Ar socket
Use
.Ar socket
instead of the default
-.Pa /var/run/npppd_ctl
+.Pa /var/run/npppd.sock
to communicate with
-.\" XXX .Xr npppd 8 .
-npppd.
-.It Fl t Ar timeout_sec
-Use
-.Ar timeout_sec
-as the I/O timeout timer value in seconds instead of the default value of 2.
+.Xr npppd 8 .
.El
.Sh NPPPD CONTROL COMMANDS
The following commands are available:
@@ -77,6 +62,18 @@ See
.Cm session all
for the types of
.Ar filter .
+.It Cm monitor all | filter ...
+Monitor start and stop of PPP sessions.
+If
+.Ar filter
+is specified, only matching PPP sessions are monitored.
+If
+.Ar all
+is specified, all PPP sessions are monitored.
+See
+.Cm session all
+for the types of
+.Ar filter .
.It Cm session all Op Ar filter ...
Show detailed information for PPP sessions.
If
diff --git a/usr.sbin/npppctl/npppctl.c b/usr.sbin/npppctl/npppctl.c
index c81a95c0256..b58c080d565 100644
--- a/usr.sbin/npppctl/npppctl.c
+++ b/usr.sbin/npppctl/npppctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: npppctl.c,v 1.1 2012/01/18 03:13:04 yasuoka Exp $ */
+/* $OpenBSD: npppctl.c,v 1.2 2014/03/22 04:30:31 yasuoka Exp $ */
/*
* Copyright (c) 2012 Internet Initiative Japan Inc.
@@ -16,8 +16,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/param.h>
+#include <sys/queue.h>
#include <sys/socket.h>
-#include <sys/time.h>
#include <sys/un.h>
#include <sys/uio.h>
#include <net/if.h>
@@ -32,6 +32,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <imsg.h>
#include <unistd.h>
#include <err.h>
@@ -46,8 +47,8 @@
#define NMAX_DISCONNECT 2048
static void usage (void);
-static void on_exit (void);
static void show_clear_session (struct parse_result *, FILE *);
+static void monitor_session (struct parse_result *, FILE *);
static void clear_session (u_int[], int, int, FILE *);
static void fprint_who_brief (int, struct npppd_who *, FILE *);
static void fprint_who_packets (int, struct npppd_who *, FILE *);
@@ -56,10 +57,11 @@ static const char *peerstr (struct sockaddr *, char *, int);
static const char *humanize_duration (uint32_t, char *, int);
static const char *humanize_bytes (double, char *, int);
static bool filter_match(struct parse_result *, struct npppd_who *);
+static int imsg_wait_command_completion (void);
-static int ctlsock = -1;
-static char ctlsockpath[] = "/tmp/npppctl.XXXXXX";
-static int nflag = 0;
+static int nflag = 0;
+static struct imsgbuf ctl_ibuf;
+static struct imsg ctl_imsg;
static void
usage(void)
@@ -67,44 +69,27 @@ usage(void)
extern char *__progname;
fprintf(stderr,
- "usage: %s [-n] [-r rcvbuf_size] [-s socket] [-t timeout_sec] "
- "command [arg ...]\n", __progname);
+ "usage: %s [-n] [-s socket] command [arg ...]\n", __progname);
}
int
main(int argc, char *argv[])
{
- int ch, timeout_sec, rcvbuf;
+ int ch, ctlsock = -1;
struct parse_result *result;
struct sockaddr_un sun;
- const char *npppd_ctlpath = NPPPD_CTL_SOCK_PATH;
- struct timeval tv;
+ const char *npppd_ctlpath = NPPPD_SOCKET;
extern int optind;
extern char *optarg;
- rcvbuf = NPPPD_CTL_MSGSZ * 64;
- timeout_sec = 2;
- while ((ch = getopt(argc, argv, "nr:s:t:")) != -1)
+ while ((ch = getopt(argc, argv, "ns:")) != -1)
switch (ch) {
case 'n':
nflag = 1;
break;
- case 'r':
- if (sscanf(optarg, "%d", &rcvbuf) != 1 || rcvbuf <= 0)
- errx(EXIT_FAILURE, "invalid rcvbuf_size value");
- if (rcvbuf < NPPPD_CTL_MSGSZ)
- errx(EXIT_FAILURE,
- "rcvbuf_size can not be less than %d",
- NPPPD_CTL_MSGSZ);
- break;
case 's':
npppd_ctlpath = optarg;
break;
- case 't':
- if (sscanf(optarg, "%d", &timeout_sec) != 1 ||
- timeout_sec <= 0)
- errx(EXIT_FAILURE, "invalid timeout value");
- break;
default:
usage();
exit(EXIT_FAILURE);
@@ -116,39 +101,16 @@ main(int argc, char *argv[])
if ((result = parse(argc, argv)) == NULL)
exit(EXIT_FAILURE);
- if ((ctlsock = mkstemp(ctlsockpath)) < 0)
- err(1, "mkstemp");
-
+ if ((ctlsock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+ err(EXIT_FAILURE, "socket");
memset(&sun, 0, sizeof(sun));
sun.sun_family = AF_UNIX;
sun.sun_len = sizeof(sun);
- strlcpy(sun.sun_path, ctlsockpath, sizeof(sun.sun_path));
-
- close(ctlsock);
- unlink(ctlsockpath);
-
- if ((ctlsock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
- err(EXIT_FAILURE, "socket");
- if (bind(ctlsock, (struct sockaddr *)&sun, sizeof(sun)) != 0)
- err(EXIT_FAILURE, "bind");
-
- if (setsockopt(ctlsock, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf))
- != 0)
- err(EXIT_FAILURE, "setsockopt(,,SO_RCVBUF)");
strlcpy(sun.sun_path, npppd_ctlpath, sizeof(sun.sun_path));
- if (connect(ctlsock, (struct sockaddr *)&sun, sizeof(sun)) != 0)
+ if (connect(ctlsock, (struct sockaddr *)&sun, sizeof(sun)) < 0)
err(EXIT_FAILURE, "connect");
- /* setup cleaner */
- atexit(on_exit);
-
- tv.tv_sec = timeout_sec;
- tv.tv_usec = 0L;
- if (setsockopt(ctlsock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)))
- warn("setsockopt(,,SO_SNDTIMEO)");
- tv.tv_sec = timeout_sec;
- tv.tv_usec = 0L;
- if (setsockopt(ctlsock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)))
- warn("setsockopt(,,SO_RCVTIMEO)");
+
+ imsg_init(&ctl_ibuf, ctlsock);
switch (result->action) {
case SESSION_BRIEF:
@@ -165,6 +127,9 @@ main(int argc, char *argv[])
clear_session(ids, 1, 1, stdout);
}
break;
+ case MONITOR_SESSION:
+ monitor_session(result, stdout);
+ break;
case NONE:
break;
}
@@ -173,39 +138,30 @@ main(int argc, char *argv[])
}
static void
-on_exit(void)
-{
- if (ctlsock >= 0)
- close(ctlsock);
- unlink(ctlsockpath);
-}
-
-static void
show_clear_session(struct parse_result *result, FILE *out)
{
- int i, n, sz, ppp_id_idx;
- struct npppd_ctl_who_request req = { .cmd = NPPPD_CTL_CMD_WHO };
- struct npppd_ctl_who_response *res;
- u_char buf[NPPPD_CTL_MSGSZ + BUFSIZ];
- u_int ppp_id[NMAX_DISCONNECT];
-
- res = (struct npppd_ctl_who_response *)buf;
- if (send(ctlsock, &req, sizeof(req), 0) < 0)
- err(1, "send");
- res->count = 0;
- n = 0;
- ppp_id_idx = 0;
- do {
- if ((sz = recv(ctlsock, &buf, sizeof(buf), MSG_WAITALL)) < 0) {
- if (errno == EAGAIN) {
- warn("recv");
- break;
- }
- err(EXIT_FAILURE, "recv");
+ int i, n, ppp_id_idx;
+ struct npppd_who_list *res;
+ u_int ppp_id[NMAX_DISCONNECT];
+
+ if (imsg_compose(&ctl_ibuf, IMSG_CTL_WHO, 0, 0, -1, NULL, 0) == -1)
+ err(EXIT_FAILURE, "failed to componse a message\n");
+ if (imsg_wait_command_completion() < 0)
+ errx(EXIT_FAILURE, "failed to get response");
+ if (ctl_imsg.hdr.type != IMSG_CTL_OK)
+ errx(EXIT_FAILURE, "command was fail");
+ n = ppp_id_idx = 0;
+ while (imsg_wait_command_completion() == IMSG_PPP_START) {
+ res = (struct npppd_who_list *)ctl_imsg.data;
+ if (ctl_imsg.hdr.len - IMSG_HEADER_SIZE <
+ offsetof(struct npppd_who_list,
+ entry[res->entry_count + 1])) {
+ err(1, "response size %d is too small for "
+ "the entry count %d",
+ (int)(ctl_imsg.hdr.len - IMSG_HEADER_SIZE),
+ res->entry_count);
}
- for (i = 0; n < res->count &&
- offsetof(struct npppd_ctl_who_response, entry[i + 1]) <= sz;
- i++, n++)
+ for (i = 0; i < res->entry_count; i++, n++) {
switch (result->action) {
case SESSION_BRIEF:
fprint_who_brief(n, &res->entry[i], out);
@@ -229,14 +185,64 @@ show_clear_session(struct parse_result *result, FILE *out)
warnx("must not reached here");
abort();
}
- } while (n < res->count);
- if (n > 0 && n < res->count)
- warnx("There are %d sessions in total, but we received only %d "
- "sessions. Receive buffer size may not be enough, use -r "
- "option to increase the size.", res->count, n);
- if (result->action == CLEAR_SESSION)
- clear_session(ppp_id, MIN(ppp_id_idx, nitems(ppp_id)),
- ppp_id_idx, out);
+ }
+ if (!res->more_data)
+ break;
+ }
+ if (result->action == CLEAR_SESSION) {
+ if (ppp_id_idx > nitems(ppp_id))
+ warnx(
+ "Disconnection for %d sessions has been requested, "
+ "but cannot disconnect only %d sessions because of "
+ "the implementation limit.",
+ ppp_id_idx, (int)nitems(ppp_id));
+ clear_session(ppp_id, MIN(ppp_id_idx, nitems(ppp_id)),
+ ppp_id_idx, out);
+ }
+}
+
+const char *bar =
+"------------------------------------------------------------------------\n";
+static void
+monitor_session(struct parse_result *result, FILE *out)
+{
+ int i, n;
+ struct npppd_who_list *res;
+
+ if (imsg_compose(&ctl_ibuf, IMSG_CTL_MONITOR, 0, 0, -1, NULL, 0) == -1)
+ err(EXIT_FAILURE, "failed to compose a message");
+ if (imsg_wait_command_completion() < 0)
+ errx(EXIT_FAILURE, "failed to get response");
+ if (ctl_imsg.hdr.type != IMSG_CTL_OK)
+ errx(EXIT_FAILURE, "command was fail");
+ do {
+ if (imsg_wait_command_completion() < 0)
+ break;
+ n = 0;
+ if (ctl_imsg.hdr.type == IMSG_PPP_START ||
+ ctl_imsg.hdr.type == IMSG_PPP_STOP) {
+ res = (struct npppd_who_list *)ctl_imsg.data;
+ for (i = 0; i < res->entry_count; i++) {
+ if (!filter_match(result, &res->entry[i]))
+ continue;
+ if (n == 0)
+ fprintf(out, "PPP %s\n%s",
+ (ctl_imsg.hdr.type ==
+ IMSG_PPP_START)
+ ? "Started"
+ : "Stopped", bar);
+ fprint_who_all(n++, &res->entry[i], out);
+ }
+ if (n > 0)
+ fputs(bar, out);
+ } else {
+ warnx("received unknown message type = %d",
+ ctl_imsg.hdr.type);
+ break;
+ }
+ } while (true);
+
+ return;
}
static void
@@ -274,9 +280,9 @@ fprint_who_packets(int i, struct npppd_who *w, FILE *out)
static void
fprint_who_all(int i, struct npppd_who *w, FILE *out)
{
- struct tm tm;
- char ibytes_buf[48], obytes_buf[48], peer_buf[48],
- time_buf[48], dur_buf[48];
+ struct tm tm;
+ char ibytes_buf[48], obytes_buf[48], peer_buf[48], time_buf[48];
+ char dur_buf[48];
localtime_r(&w->time, &tm);
strftime(time_buf, sizeof(time_buf), "%Y/%m/%d %T", &tm);
@@ -326,42 +332,48 @@ fprint_who_all(int i, struct npppd_who *w, FILE *out)
static void
clear_session(u_int ppp_id[], int ppp_id_count, int total, FILE *out)
{
- int succ, fail, i, n, nmax;
- struct npppd_ctl_disconnect_request req;
- struct npppd_ctl_disconnect_response res;
- struct iovec iov[2];
- struct msghdr msg;
+ int succ, fail, i, n, nmax;
+ struct iovec iov[2];
+ struct npppd_disconnect_request req;
+ struct npppd_disconnect_response *res;
succ = fail = 0;
if (ppp_id_count > 0) {
- nmax = (NPPPD_CTL_MSGSZ -
- offsetof(struct npppd_ctl_disconnect_request, ppp_id[0])) /
+ nmax = (MAX_IMSGSIZE - IMSG_HEADER_SIZE -
+ offsetof(struct npppd_disconnect_request, ppp_id[0])) /
sizeof(u_int);
for (i = 0; i < ppp_id_count; i += n) {
n = MIN(nmax, ppp_id_count - i);
- req.cmd = NPPPD_CTL_CMD_DISCONNECT;
req.count = n;
- memset(&msg, 0, sizeof(msg));
- msg.msg_iov = iov;
- msg.msg_iovlen = nitems(iov);
iov[0].iov_base = &req;
iov[0].iov_len = offsetof(
- struct npppd_ctl_disconnect_request, ppp_id[0]);
+ struct npppd_disconnect_request, ppp_id[0]);
iov[1].iov_base = &ppp_id[i];
iov[1].iov_len = sizeof(u_int) * n;
- if (sendmsg(ctlsock, &msg, 0) < 0)
- err(EXIT_FAILURE, "sendmsg");
- if (recv(ctlsock, &res, sizeof(res), 0) < 0)
- err(EXIT_FAILURE, "recv");
- succ += res.count;
+
+ if (imsg_composev(&ctl_ibuf, IMSG_CTL_DISCONNECT, 0, 0,
+ -1, iov, 2) == -1)
+ err(EXIT_FAILURE,
+ "Failed to compose a message");
+ if (imsg_wait_command_completion() < 0)
+ errx(EXIT_FAILURE, "failed to get response");
+ if (ctl_imsg.hdr.type != IMSG_CTL_OK)
+ errx(EXIT_FAILURE,
+ "Command was fail: msg type = %d",
+ ctl_imsg.hdr.type);
+ if (ctl_imsg.hdr.len - IMSG_HEADER_SIZE <
+ sizeof(struct npppd_disconnect_response))
+ err(EXIT_FAILURE, "response is corrupted");
+ res = (struct npppd_disconnect_response *)ctl_imsg.data;
+ succ += res->count;
}
fail = total - succ;
}
if (succ > 0)
- fprintf(out, "Successfully disconnected %d session%s.\n",
+ fprintf(out, "Successfully disconnected %d session%s.\n",
succ, (succ > 1)? "s" : "");
if (fail > 0)
- fprintf(out, "Failed to disconnect %d session%s.\n",
+ fprintf(out, "Failed to disconnect %d session%s.\n",
fail, (fail > 1)? "s" : "");
if (succ == 0 && fail == 0)
fprintf(out, "No session to disconnect.\n");
@@ -374,42 +386,42 @@ static bool
filter_match(struct parse_result *result, struct npppd_who *who)
{
if (result->has_ppp_id && result->ppp_id != who->ppp_id)
- return false;
+ return (false);
switch (result->address.ss_family) {
case AF_INET:
if (((struct sockaddr_in *)&result->address)->sin_addr.
s_addr != who->framed_ip_address.s_addr)
- return false;
+ return (false);
break;
case AF_INET6:
/* npppd doesn't support IPv6 yet */
- return false;
+ return (false);
}
if (result->interface != NULL &&
strcmp(result->interface, who->ifname) != 0)
- return false;
+ return (false);
if (result->protocol != PROTO_UNSPEC &&
result->protocol != parse_protocol(who->tunnel_proto) )
- return false;
+ return (false);
if (result->realm != NULL && strcmp(result->realm, who->rlmname) != 0)
- return false;
+ return (false);
if (result->username != NULL &&
strcmp(result->username, who->username) != 0)
- return false;
+ return (false);
- return true;
+ return (true);
}
static const char *
peerstr(struct sockaddr *sa, char *buf, int lbuf)
{
- int niflags, hasserv;
- char hoststr[NI_MAXHOST], servstr[NI_MAXSERV];
+ int niflags, hasserv;
+ char hoststr[NI_MAXHOST], servstr[NI_MAXSERV];
niflags = hasserv = 0;
if (nflag)
@@ -431,28 +443,28 @@ peerstr(struct sockaddr *sa, char *buf, int lbuf)
else
getnameinfo(sa, sa->sa_len, hoststr, sizeof(hoststr), servstr,
sizeof(servstr), niflags);
-
+
strlcpy(buf, hoststr, lbuf);
if (hasserv) {
strlcat(buf, ":", lbuf);
strlcat(buf, servstr, lbuf);
}
- return buf;
+ return (buf);
}
static const char *
humanize_duration(uint32_t sec, char *buf, int lbuf)
{
- char fbuf[128];
- int hour, min;
+ char fbuf[128];
+ int hour, min;
hour = sec / (60 * 60);
min = sec / 60;
min %= 60;
if (lbuf <= 0)
- return buf;
+ return (buf);
buf[0] = '\0';
if (hour || min) {
strlcat(buf, "(", lbuf);
@@ -471,14 +483,14 @@ humanize_duration(uint32_t sec, char *buf, int lbuf)
strlcat(buf, ")", lbuf);
}
- return buf;
+ return (buf);
}
static const char *
humanize_bytes(double val, char *buf, int lbuf)
{
if (lbuf <= 0)
- return buf;
+ return (buf);
if (val >= 1000 * 1024 * 1024)
snprintf(buf, lbuf, " (%.1f GB)",
@@ -489,6 +501,26 @@ humanize_bytes(double val, char *buf, int lbuf)
snprintf(buf, lbuf, " (%.1f KB)", (double)val / 1024);
else
buf[0] = '\0';
-
- return buf;
+
+ return (buf);
+}
+
+static int
+imsg_wait_command_completion(void)
+{
+ int n;
+
+ while (ctl_ibuf.w.queued)
+ if (msgbuf_write(&ctl_ibuf.w) < -1)
+ return (-1);
+ do {
+ if ((n = imsg_get(&ctl_ibuf, &ctl_imsg)) == -1)
+ return (-1);
+ if (n != 0)
+ break;
+ if ((n = imsg_read(&ctl_ibuf)) == -1 || n == 0)
+ return (-1);
+ } while (1);
+
+ return (ctl_imsg.hdr.type);
}
diff --git a/usr.sbin/npppctl/parser.c b/usr.sbin/npppctl/parser.c
index 263872d2e8a..69e268af5c3 100644
--- a/usr.sbin/npppctl/parser.c
+++ b/usr.sbin/npppctl/parser.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: parser.c,v 1.1 2012/01/18 03:13:04 yasuoka Exp $ */
+/* $OpenBSD: parser.c,v 1.2 2014/03/22 04:30:31 yasuoka Exp $ */
/* This file is derived from OpenBSD:src/usr.sbin/ikectl/parser.c 1.9 */
/*
@@ -57,6 +57,7 @@ static struct parse_result res;
static const struct token t_main[];
static const struct token t_session[];
static const struct token t_clear[];
+static const struct token t_monitor[];
static const struct token t_filter[];
static const struct token t_ppp_id[];
static const struct token t_address[];
@@ -68,6 +69,7 @@ static const struct token t_username[];
static const struct token t_main[] = {
{ KEYWORD, "session", NONE, t_session },
{ KEYWORD, "clear", NONE, t_clear },
+ { KEYWORD, "monitor", NONE, t_monitor },
{ ENDTOKEN, "", NONE, NULL }
};
@@ -89,6 +91,17 @@ static const struct token t_clear[] = {
{ ENDTOKEN, "", CLEAR_SESSION, NULL }
};
+static const struct token t_monitor[] = {
+ { KEYWORD, "all", MONITOR_SESSION, NULL },
+ { KEYWORD, "ppp-id", MONITOR_SESSION, t_ppp_id },
+ { KEYWORD, "address", MONITOR_SESSION, t_address },
+ { KEYWORD, "interface", MONITOR_SESSION, t_interface },
+ { KEYWORD, "protocol", MONITOR_SESSION, t_protocol },
+ { KEYWORD, "realm", MONITOR_SESSION, t_realm },
+ { KEYWORD, "username", MONITOR_SESSION, t_username },
+ { ENDTOKEN, "", MONITOR_SESSION, NULL }
+};
+
static const struct token t_filter[] = {
{ NOTOKEN, "", NONE, NULL },
{ KEYWORD, "ppp-id", NONE, t_ppp_id },
@@ -232,7 +245,7 @@ match_token(char *word, const struct token table[])
case PROTOCOL:
if (word == NULL)
break;
- if ((res.protocol = parse_protocol(word)) ==
+ if ((res.protocol = parse_protocol(word)) ==
PROTO_UNSPEC)
break;
match++;
diff --git a/usr.sbin/npppctl/parser.h b/usr.sbin/npppctl/parser.h
index c7e3327586a..ccd0bdc9c16 100644
--- a/usr.sbin/npppctl/parser.h
+++ b/usr.sbin/npppctl/parser.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: parser.h,v 1.2 2012/05/08 13:15:11 yasuoka Exp $ */
+/* $OpenBSD: parser.h,v 1.3 2014/03/22 04:30:31 yasuoka Exp $ */
/* This file is derived from OpenBSD:src/usr.sbin/ikectl/parser.h 1.9 */
/*
@@ -25,7 +25,8 @@ enum actions {
SESSION_BRIEF,
SESSION_PKTS,
SESSION_ALL,
- CLEAR_SESSION
+ CLEAR_SESSION,
+ MONITOR_SESSION
};
enum protocol {
diff --git a/usr.sbin/npppd/common/debugutil.h b/usr.sbin/npppd/common/debugutil.h
index bd095bbc981..60fef162d64 100644
--- a/usr.sbin/npppd/common/debugutil.h
+++ b/usr.sbin/npppd/common/debugutil.h
@@ -26,6 +26,7 @@
#ifndef DEBUG_UTIL_H
#define DEBUG_UTIL_H 1
+#include <stdio.h> /* for FILE * */
#include "debugmacro.h"
#define DEBUG_LEVEL_1 ( 1 << 24)
diff --git a/usr.sbin/npppd/npppd/Makefile b/usr.sbin/npppd/npppd/Makefile
index 342275f425f..421db5b7644 100644
--- a/usr.sbin/npppd/npppd/Makefile
+++ b/usr.sbin/npppd/npppd/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.16 2013/02/06 11:45:48 giovanni Exp $
+# $OpenBSD: Makefile,v 1.17 2014/03/22 04:30:31 yasuoka Exp $
NPPPD_COMMON_DIR= ${.CURDIR}/../common
@@ -10,7 +10,7 @@ CPPFLAGS+= -I${.CURDIR}/../pptp -I${.CURDIR}/../l2tp -I${.CURDIR}/../pppoe
SRCS= ccp.c chap.c chap_ms.c fsm.c ipcp.c lcp.c mppe.c pap.c ppp.c
SRCS+= npppd.c npppd_config.c npppd_subr.c npppd_auth.c npppd_iface.c
SRCS+= npppd_pool.c radius+.c radius_req.c npppd_radius.c npppd_ctl.c
-SRCS+= privsep.c parse.y log.c accept.c
+SRCS+= privsep.c parse.y log.c accept.c control.c
SRCS+= debugutil.c net_utils.c radish.c time_utils.c slist.c hash.c
SRCS+= bytebuf.c addr_range.c recvfromto.c
@@ -35,8 +35,8 @@ CPPFLAGS+= -DUSE_SA_COOKIE
CPPFLAGS+= -DGENERIC_USE -DRADISH
-LDADD+= -levent -lcrypto -ly
-DPADD+= ${LIBEVENT} ${LIBCRYPTO} ${LIBY}
+LDADD+= -levent -lcrypto -ly -lutil
+DPADD+= ${LIBEVENT} ${LIBCRYPTO} ${LIBY} ${LIBUTIL}
.ifdef DEBUG
CPPFLAGS+= -DDEBUG=1
diff --git a/usr.sbin/npppd/npppd/control.c b/usr.sbin/npppd/npppd/control.c
new file mode 100644
index 00000000000..19746c4bd68
--- /dev/null
+++ b/usr.sbin/npppd/npppd/control.c
@@ -0,0 +1,360 @@
+/* $OpenBSD: control.c,v 1.1 2014/03/22 04:30:31 yasuoka Exp $ */
+
+/*
+ * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <event.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <imsg.h>
+
+#include "log.h"
+
+#define CONTROL_BACKLOG 5
+
+#include "npppd_local.h"
+#include "npppd_ctl.h"
+
+struct ctl_conn_list ctl_conns;
+
+struct ctl_conn *control_connbyfd(int);
+void control_close(int, struct control_sock *);
+void control_accept (int, short, void *);
+void control_close (int, struct control_sock *);
+void control_dispatch_imsg (int, short, void *);
+void control_imsg_forward (struct imsg *);
+void fd_nonblock(int);
+
+int
+control_init(struct control_sock *cs)
+{
+ struct sockaddr_un sun;
+ int fd;
+ mode_t old_umask, mode;
+
+ if (cs->cs_name == NULL)
+ return (0);
+
+ if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+ log_warn("control_init: socket");
+ return (-1);
+ }
+
+ sun.sun_family = AF_UNIX;
+ if (strlcpy(sun.sun_path, cs->cs_name,
+ sizeof(sun.sun_path)) >= sizeof(sun.sun_path)) {
+ log_warn("control_init: %s name too long", cs->cs_name);
+ close(fd);
+ return (-1);
+ }
+
+ if (unlink(cs->cs_name) == -1)
+ if (errno != ENOENT) {
+ log_warn("control_init: unlink %s", cs->cs_name);
+ close(fd);
+ return (-1);
+ }
+
+ if (cs->cs_restricted) {
+ old_umask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
+ mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
+ } else {
+ old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH);
+ mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP;
+ }
+
+ if (bind(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
+ log_warn("control_init: bind: %s", cs->cs_name);
+ close(fd);
+ (void)umask(old_umask);
+ return (-1);
+ }
+ (void)umask(old_umask);
+
+ if (chmod(cs->cs_name, mode) == -1) {
+ log_warn("control_init: chmod");
+ close(fd);
+ (void)unlink(cs->cs_name);
+ return (-1);
+ }
+ TAILQ_INIT(&ctl_conns);
+
+ fd_nonblock(fd);
+ cs->cs_fd = fd;
+
+ return (0);
+}
+
+int
+control_listen(struct control_sock *cs)
+{
+ if (cs->cs_name == NULL)
+ return (0);
+
+ if (listen(cs->cs_fd, CONTROL_BACKLOG) == -1) {
+ log_warn("control_listen: listen");
+ return (-1);
+ }
+
+ event_set(&cs->cs_ev, cs->cs_fd, EV_READ,
+ control_accept, cs);
+ event_add(&cs->cs_ev, NULL);
+ evtimer_set(&cs->cs_evt, control_accept, cs);
+
+ return (0);
+}
+
+void
+control_cleanup(struct control_sock *cs)
+{
+ if (cs->cs_name == NULL)
+ return;
+ event_del(&cs->cs_ev);
+ event_del(&cs->cs_evt);
+ (void)unlink(cs->cs_name);
+}
+
+#include <stdio.h>
+/* ARGSUSED */
+void
+control_accept(int listenfd, short event, void *arg)
+{
+ struct control_sock *cs = (struct control_sock *)arg;
+ int connfd;
+ socklen_t len;
+ struct sockaddr_un sun;
+ struct ctl_conn *c;
+
+ event_add(&cs->cs_ev, NULL);
+ if ((event & EV_TIMEOUT))
+ return;
+
+ len = sizeof(sun);
+ if ((connfd = accept(listenfd,
+ (struct sockaddr *)&sun, &len)) == -1) {
+ /*
+ * Pause accept if we are out of file descriptors, or
+ * libevent will haunt us here too.
+ */
+ if (errno == ENFILE || errno == EMFILE) {
+ struct timeval evtpause = { 1, 0 };
+
+ event_del(&cs->cs_ev);
+ evtimer_add(&cs->cs_evt, &evtpause);
+ } else if (errno != EWOULDBLOCK && errno != EINTR)
+ log_warn("control_accept: accept");
+ return;
+ }
+
+ fd_nonblock(connfd);
+
+ if ((c = calloc(1, sizeof(struct ctl_conn))) == NULL) {
+ log_warn("control_accept");
+ close(connfd);
+ return;
+ }
+ if ((c->ctx = npppd_ctl_create(cs->cs_ctx)) == NULL) {
+ free(c);
+ log_warn("control_accept");
+ close(connfd);
+ return;
+ }
+
+ imsg_init(&c->iev.ibuf, connfd);
+ c->iev.handler = control_dispatch_imsg;
+ c->iev.events = EV_READ;
+ c->iev.data = cs;
+ event_set(&c->iev.ev, c->iev.ibuf.fd, c->iev.events,
+ c->iev.handler, cs);
+ event_add(&c->iev.ev, NULL);
+
+ TAILQ_INSERT_TAIL(&ctl_conns, c, entry);
+}
+
+struct ctl_conn *
+control_connbyfd(int fd)
+{
+ struct ctl_conn *c;
+
+ for (c = TAILQ_FIRST(&ctl_conns); c != NULL && c->iev.ibuf.fd != fd;
+ c = TAILQ_NEXT(c, entry))
+ ; /* nothing */
+
+ return (c);
+}
+
+void
+control_close(int fd, struct control_sock *cs)
+{
+ struct ctl_conn *c;
+
+ if ((c = control_connbyfd(fd)) == NULL) {
+ log_warn("control_close: fd %d: not found", fd);
+ return;
+ }
+
+ msgbuf_clear(&c->iev.ibuf.w);
+ TAILQ_REMOVE(&ctl_conns, c, entry);
+
+ event_del(&c->iev.ev);
+ close(c->iev.ibuf.fd);
+
+ /* Some file descriptors are available again. */
+ if (evtimer_pending(&cs->cs_evt, NULL)) {
+ evtimer_del(&cs->cs_evt);
+ event_add(&cs->cs_ev, NULL);
+ }
+ npppd_ctl_destroy(c->ctx);
+
+ free(c);
+}
+
+/* ARGSUSED */
+void
+control_dispatch_imsg(int fd, short event, void *arg)
+{
+ struct control_sock *cs = (struct control_sock *)arg;
+ struct ctl_conn *c;
+ struct imsg imsg;
+ int n, retval;
+
+ if ((c = control_connbyfd(fd)) == NULL) {
+ log_warn("control_dispatch_imsg: fd %d: not found", fd);
+ return;
+ }
+
+
+ if (event & EV_WRITE) {
+ if (msgbuf_write(&c->iev.ibuf.w) < 0) {
+ control_close(fd, cs);
+ return;
+ }
+ if (!c->iev.ibuf.w.queued)
+ npppd_ctl_imsg_compose(c->ctx, &c->iev.ibuf);
+ imsg_event_add(&c->iev);
+ if (!(event & EV_READ))
+ return;
+ }
+ if (event & EV_READ) {
+ if ((n = imsg_read(&c->iev.ibuf)) == -1 || n == 0) {
+ control_close(fd, cs);
+ return;
+ }
+ } else
+ fatalx("unknown event");
+
+ for (;;) {
+ if ((n = imsg_get(&c->iev.ibuf, &imsg)) == -1) {
+ control_close(fd, cs);
+ return;
+ }
+
+ if (n == 0)
+ break;
+
+ if (cs->cs_restricted || (c->flags & CTL_CONN_LOCKED)) {
+ switch (imsg.hdr.type) {
+ default:
+ log_debug("control_dispatch_imsg: "
+ "client requested restricted command");
+ imsg_free(&imsg);
+ control_close(fd, cs);
+ return;
+ }
+ }
+
+ switch (imsg.hdr.type) {
+ case IMSG_CTL_NOP:
+ imsg_compose(&c->iev.ibuf, IMSG_CTL_OK, 0, 0, -1,
+ NULL, 0);
+ break;
+
+ case IMSG_CTL_WHO:
+ case IMSG_CTL_MONITOR:
+ case IMSG_CTL_WHO_AND_MONITOR:
+ if (imsg.hdr.type == IMSG_CTL_WHO)
+ retval = npppd_ctl_who(c->ctx);
+ else if (imsg.hdr.type == IMSG_CTL_MONITOR)
+ retval = npppd_ctl_monitor(c->ctx);
+ else
+ retval = npppd_ctl_who_and_monitor(c->ctx);
+ imsg_compose(&c->iev.ibuf,
+ (retval == 0)? IMSG_CTL_OK : IMSG_CTL_FAIL, 0, 0,
+ -1, NULL, 0);
+ break;
+
+ case IMSG_CTL_DISCONNECT:
+ {
+ struct npppd_disconnect_request *req;
+ struct npppd_disconnect_response res;
+
+ req = (struct npppd_disconnect_request *)imsg.data;
+ retval = npppd_ctl_disconnect(c->ctx,
+ req->ppp_id, req->count);
+ res.count = retval;
+ imsg_compose(&c->iev.ibuf, IMSG_CTL_OK, 0, 0,
+ -1, &res, sizeof(res));
+ break;
+ }
+ default:
+ imsg_compose(&c->iev.ibuf, IMSG_CTL_FAIL, 0, 0, -1,
+ NULL, 0);
+ break;
+ }
+ imsg_free(&imsg);
+ }
+ if (!c->iev.ibuf.w.queued)
+ npppd_ctl_imsg_compose(c->ctx, &c->iev.ibuf);
+ imsg_event_add(&c->iev);
+}
+
+void
+control_imsg_forward(struct imsg *imsg)
+{
+ struct ctl_conn *c;
+
+ TAILQ_FOREACH(c, &ctl_conns, entry)
+ if (c->flags & CTL_CONN_NOTIFY)
+ imsg_compose(&c->iev.ibuf, imsg->hdr.type, 0,
+ imsg->hdr.pid, -1, imsg->data,
+ imsg->hdr.len - IMSG_HEADER_SIZE);
+}
+
+void
+fd_nonblock(int fd)
+{
+ int flags;
+
+ if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
+ fatal("fcntl F_GETFL");
+ flags |= O_NONBLOCK;
+ if ((flags = fcntl(fd, F_SETFL, flags)) == -1)
+ fatal("fcntl F_SETFL");
+}
diff --git a/usr.sbin/npppd/npppd/npppd.c b/usr.sbin/npppd/npppd/npppd.c
index 42c795f92dd..3fa9f3ee430 100644
--- a/usr.sbin/npppd/npppd/npppd.c
+++ b/usr.sbin/npppd/npppd/npppd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: npppd.c,v 1.34 2014/03/22 04:23:17 yasuoka Exp $ */
+/* $OpenBSD: npppd.c,v 1.35 2014/03/22 04:30:31 yasuoka Exp $ */
/*-
* Copyright (c) 2005-2008,2009 Internet Initiative Japan Inc.
@@ -29,7 +29,7 @@
* Next pppd(nppd). This file provides a npppd daemon process and operations
* for npppd instance.
* @author Yasuoka Masahiko
- * $Id: npppd.c,v 1.34 2014/03/22 04:23:17 yasuoka Exp $
+ * $Id: npppd.c,v 1.35 2014/03/22 04:30:31 yasuoka Exp $
*/
#include "version.h"
#include <sys/types.h>
@@ -96,21 +96,23 @@
static npppd s_npppd; /* singleton */
-static void npppd_reload0 (npppd *);
-static void npppd_update_pool_reference (npppd *);
-static int npppd_rd_walktree_delete(struct radish_head *);
-static void usage (void);
-static void npppd_stop_really (npppd *);
-static uint32_t str_hash(const void *, int);
-static void npppd_on_sighup (int, short, void *);
-static void npppd_on_sigterm (int, short, void *);
-static void npppd_on_sigint (int, short, void *);
-static void npppd_on_sigchld (int, short, void *);
-static void npppd_reset_timer(npppd *);
-static void npppd_timer(int, short, void *);
-static void npppd_auth_finalizer_periodic(npppd *);
-static int rd2slist_walk (struct radish *, void *);
-static int rd2slist (struct radish_head *, slist *);
+static void npppd_reload0 (npppd *);
+static void npppd_update_pool_reference (npppd *);
+static int npppd_rd_walktree_delete(struct radish_head *);
+static void usage (void);
+static void npppd_stop_really (npppd *);
+static uint32_t str_hash(const void *, int);
+static void npppd_on_sighup (int, short, void *);
+static void npppd_on_sigterm (int, short, void *);
+static void npppd_on_sigint (int, short, void *);
+static void npppd_on_sigchld (int, short, void *);
+static void npppd_reset_timer(npppd *);
+static void npppd_timer(int, short, void *);
+static void npppd_auth_finalizer_periodic(npppd *);
+static int rd2slist_walk (struct radish *, void *);
+static int rd2slist (struct radish_head *, slist *);
+static slist *npppd_get_ppp_by_user (npppd *, const char *);
+static int npppd_get_all_users (npppd *, slist *);
#ifndef NO_ROUTE_FOR_POOLED_ADDRESS
static struct in_addr loop; /* initialize at npppd_init() */
@@ -312,7 +314,18 @@ npppd_init(npppd *_this, const char *config_file)
/* initialize event(3) */
event_init();
-
+ _this->ctl_sock.cs_name = NPPPD_SOCKET;
+ _this->ctl_sock.cs_ctx = _this;
+ if (control_init(&_this->ctl_sock) == -1) {
+ log_printf(LOG_ERR, "control_init() failed %s(): %m",
+ __func__);
+ return (-1);
+ }
+ if (control_listen(&_this->ctl_sock) == -1) {
+ log_printf(LOG_ERR, "control_listen() failed %s(): %m",
+ __func__);
+ return (-1);
+ }
accept_init();
/* ignore signals */
@@ -359,9 +372,6 @@ npppd_init(npppd *_this, const char *config_file)
if (npppd_config_str_equali(_this, "arpd.enabled", "true", ARPD_DEFAULT) == 1)
arp_sock_init();
#endif
- npppd_ctl_init(&_this->ctl, _this, NPPPD_CTL_SOCK_PATH);
- if ((status = npppd_ctl_start(&_this->ctl)) != 0)
- return status;
if ((status = npppd_modules_reload(_this)) != 0)
return status;
@@ -399,12 +409,12 @@ npppd_stop(npppd *_this)
#ifdef USE_NPPPD_PPPOE
pppoed_stop(&_this->pppoed);
#endif
-#ifdef USE_NPPPD_NPPPD_CTL
- npppd_ctl_stop(&_this->ctl);
-#endif
#ifdef USE_NPPPD_ARP
arp_sock_fini();
#endif
+ close(_this->ctl_sock.cs_fd);
+ control_cleanup(&_this->ctl_sock);
+
for (i = countof(_this->iface) - 1; i >= 0; i--) {
if (_this->iface[i].initialized != 0)
npppd_iface_stop(&_this->iface[i]);
@@ -730,7 +740,7 @@ npppd_get_ppp_by_ip(npppd *_this, struct in_addr ipaddr)
* @return {@link slist} that contans the {@link npppd_ppp} instances.
* NULL may be returned if no instance has been found.
*/
-slist *
+static slist *
npppd_get_ppp_by_user(npppd *_this, const char *username)
{
hash_link *hl;
@@ -1764,7 +1774,7 @@ fail:
* This function stores all users to {@link slist} and returns them.
* References to {@link ::npppd_ppp} will be stored in users.
*/
-int
+static int
npppd_get_all_users(npppd *_this, slist *users)
{
int rval;
@@ -2298,3 +2308,40 @@ npppd_get_tunnconf(npppd *_this, const char *name)
return NULL;
}
+void
+npppd_on_ppp_start(npppd *_this, npppd_ppp *ppp)
+{
+ struct ctl_conn *c;
+
+ TAILQ_FOREACH(c, &ctl_conns, entry) {
+ if (npppd_ctl_add_started_ppp_id(c->ctx, ppp->id) == 0) {
+ npppd_ctl_imsg_compose(c->ctx, &c->iev.ibuf);
+ imsg_event_add(&c->iev);
+ }
+ }
+}
+
+void
+npppd_on_ppp_stop(npppd *_this, npppd_ppp *ppp)
+{
+ struct ctl_conn *c;
+
+ TAILQ_FOREACH(c, &ctl_conns, entry) {
+ if (npppd_ctl_add_stopped_ppp(c->ctx, ppp) == 0) {
+ npppd_ctl_imsg_compose(c->ctx, &c->iev.ibuf);
+ imsg_event_add(&c->iev);
+ }
+ }
+}
+
+void
+imsg_event_add(struct imsgev *iev)
+{
+ iev->events = EV_READ;
+ if (iev->ibuf.w.queued)
+ iev->events |= EV_WRITE;
+
+ event_del(&iev->ev);
+ event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev->data);
+ event_add(&iev->ev, NULL);
+}
diff --git a/usr.sbin/npppd/npppd/npppd.h b/usr.sbin/npppd/npppd/npppd.h
index 2a80777afcb..0d2e6954a9e 100644
--- a/usr.sbin/npppd/npppd/npppd.h
+++ b/usr.sbin/npppd/npppd/npppd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: npppd.h,v 1.14 2014/03/22 04:23:17 yasuoka Exp $ */
+/* $OpenBSD: npppd.h,v 1.15 2014/03/22 04:30:31 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -38,7 +38,6 @@
#include <netinet/in.h>
#include <event.h>
-#include "slist.h"
#include "addr_range.h"
#include "l2tp_conf.h"
@@ -223,6 +222,29 @@ typedef struct _npppd npppd;
#include "ppp.h"
+#include <imsg.h>
+
+struct imsgev {
+ struct imsgbuf ibuf;
+ void (*handler)(int, short, void *);
+ struct event ev;
+ void *data;
+ short events;
+};
+
+struct ctl_conn {
+ TAILQ_ENTRY(ctl_conn) entry;
+ struct control_sock *parent;
+ u_int8_t flags;
+#define CTL_CONN_NOTIFY 0x01
+#define CTL_CONN_LOCKED 0x02 /* restricted mode */
+ struct imsgev iev;
+ void *ctx;
+};
+
+TAILQ_HEAD(ctl_conn_list, ctl_conn);
+extern struct ctl_conn_list ctl_conns;
+
__BEGIN_DECLS
npppd *npppd_get_npppd (void);
int npppd_init (npppd *, const char *);
@@ -234,7 +256,6 @@ int npppd_get_user_password (npppd *, npppd_ppp *, const char *, ch
struct in_addr *npppd_get_user_framed_ip_address (npppd *, npppd_ppp *, const char *);
int npppd_check_calling_number (npppd *, npppd_ppp *);
npppd_ppp *npppd_get_ppp_by_ip (npppd *, struct in_addr);
-slist *npppd_get_ppp_by_user (npppd *, const char *);
npppd_ppp *npppd_get_ppp_by_id (npppd *, u_int);
int npppd_check_user_max_session (npppd *, npppd_ppp *);
void npppd_network_output (npppd *, npppd_ppp *, int, u_char *, int);
@@ -245,7 +266,6 @@ void npppd_release_ip (npppd *, npppd_ppp *);
void npppd_set_ip_enabled (npppd *, npppd_ppp *, int);
int npppd_assign_ip_addr (npppd *, npppd_ppp *, uint32_t);
int npppd_set_radish (npppd *, void *);
-int npppd_get_all_users (npppd *, slist *);
int npppd_ppp_bind_realm (npppd *, npppd_ppp *, const char *, int);
int npppd_ppp_is_realm_local (npppd *, npppd_ppp *);
int npppd_ppp_is_realm_radius (npppd *, npppd_ppp *);
@@ -269,6 +289,22 @@ int npppd_conf_parse (struct npppd_conf *, const char *);
void npppd_conf_init (struct npppd_conf *);
void npppd_conf_fini (struct npppd_conf *);
int npppd_config_check (const char *);
+void npppd_on_ppp_start (npppd *, npppd_ppp *);
+void npppd_on_ppp_stop (npppd *, npppd_ppp *);
+void imsg_event_add(struct imsgev *);
+
+int control_init (struct control_sock *);
+int control_listen (struct control_sock *);
+void control_cleanup (struct control_sock *);
+struct npppd_ctl *npppd_ctl_create (npppd *);
+void npppd_ctl_destroy (struct npppd_ctl *);
+int npppd_ctl_who (struct npppd_ctl *);
+int npppd_ctl_monitor (struct npppd_ctl *);
+int npppd_ctl_who_and_monitor (struct npppd_ctl *);
+int npppd_ctl_add_started_ppp_id (struct npppd_ctl *, uint32_t);
+int npppd_ctl_add_stopped_ppp (struct npppd_ctl *, npppd_ppp *);
+int npppd_ctl_imsg_compose (struct npppd_ctl *, struct imsgbuf *);
+int npppd_ctl_disconnect (struct npppd_ctl *, u_int *, int);
__END_DECLS
diff --git a/usr.sbin/npppd/npppd/npppd_config.c b/usr.sbin/npppd/npppd/npppd_config.c
index c68cddbd470..da0d41295b6 100644
--- a/usr.sbin/npppd/npppd/npppd_config.c
+++ b/usr.sbin/npppd/npppd/npppd_config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: npppd_config.c,v 1.11 2013/08/24 23:48:25 mlarkin Exp $ */
+/* $OpenBSD: npppd_config.c,v 1.12 2014/03/22 04:30:31 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-/* $Id: npppd_config.c,v 1.11 2013/08/24 23:48:25 mlarkin Exp $ */
+/* $Id: npppd_config.c,v 1.12 2014/03/22 04:30:31 yasuoka Exp $ */
/*@file
* This file provides functions which operates configuration and so on.
*/
@@ -50,7 +50,6 @@
#include "debugutil.h"
#include "npppd_subr.h"
#include "npppd_local.h"
-#include "npppd_ctl.h"
#include "npppd_auth.h"
#include "npppd_iface.h"
#include "radish.h"
diff --git a/usr.sbin/npppd/npppd/npppd_ctl.c b/usr.sbin/npppd/npppd/npppd_ctl.c
index b99993e750d..70cd7c7e1bb 100644
--- a/usr.sbin/npppd/npppd/npppd_ctl.c
+++ b/usr.sbin/npppd/npppd/npppd_ctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: npppd_ctl.c,v 1.10 2012/09/18 13:14:08 yasuoka Exp $ */
+/* $OpenBSD: npppd_ctl.c,v 1.11 2014/03/22 04:30:31 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -25,435 +25,277 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-/**@file
- * npppd management.
- * This file provides to open UNIX domain socket which located in
- * /var/run/npppd_ctl and accept commmands from the npppdctl command.
- */
-/* $Id: npppd_ctl.c,v 1.10 2012/09/18 13:14:08 yasuoka Exp $ */
-#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
#include <netinet/in.h>
-#include <net/if_dl.h>
-#include <arpa/inet.h>
+#include <net/pipex.h>
#include <errno.h>
#include <event.h>
-#include <fcntl.h>
-#include <netdb.h>
-#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <syslog.h>
-#include <unistd.h>
-#include "npppd_local.h"
-#include "debugutil.h"
-
-#include "pathnames.h"
#include "radish.h"
-#include "npppd_ctl.h"
-
-#include "net_utils.h"
-#include "privsep.h"
-#define sendto(_s, _msg, _len, _flags, _to, _tolen) \
- priv_sendto((_s), (_msg), (_len), (_flags), (_to), (_tolen))
-
+#include "npppd_local.h"
+#include "npppd.h"
+#include "log.h"
+
+struct stopped_ppp {
+ struct npppd_who ppp_who;
+ TAILQ_ENTRY(stopped_ppp) entry;
+};
+
+struct npppd_ctl {
+ u_int *started_ppp;
+ int started_ppp_pos;
+ int started_ppp_siz;
+ TAILQ_HEAD(, stopped_ppp) stopped_ppps;
+ npppd *npppd;
+ bool is_monitoring;
+ bool responding;
+};
+
+static int npppd_ctl_who_walk_rd(struct radish *, void *);
+static int npppd_ctl_who0 (struct npppd_ctl *, bool);
+static void npppd_who_init (struct npppd_who *, npppd_ppp *);
#ifdef USE_NPPPD_PIPEX
-#if defined(__NetBSD__)
-#include <net/if_ether.h>
-#else
-#include <netinet/if_ether.h>
-#endif
-#include <netinet/ip_var.h>
-#include <sys/ioctl.h>
-#include <net/pipex.h>
+static int npppd_ppp_get_pipex_stat(struct npppd_who *_this, npppd_ppp *ppp);
#endif
-#ifndef NPPPD_CTL_SOCK_FILE_MODE
-#define NPPPD_CTL_SOCK_FILE_MODE 0660
-#endif
-#define MSG_SZ_RESERVED 256
-
-#ifdef NPPPD_CTL_DEBUG
-#define NPPPD_CTL_DBG(x) npppd_ctl_log x
-#define NPPPD_CTL_ASSERT(cond) \
- if (!(cond)) { \
- fprintf(stderr, \
- "\nASSERT(" #cond ") failed on %s() at %s:%d.\n"\
- , __func__, __FILE__, __LINE__); \
- abort(); \
- }
-#else
-#define NPPPD_CTL_DBG(x)
-#define NPPPD_CTL_ASSERT(cond)
-#endif
-#include "debugutil.h"
+struct npppd_ctl *
+npppd_ctl_create(npppd *_this)
+{
+ struct npppd_ctl *ctl;
-static void npppd_ctl_command (npppd_ctl *, u_char *, int, struct sockaddr *);
-static void npppd_ctl_io_event (int, short, void *);
-static int npppd_ctl_log (npppd_ctl *, int, const char *, ...) __printflike(3,4);
-static void npppd_who_init(struct npppd_who *, npppd_ctl *, npppd_ppp *);
+ if ((ctl = malloc(sizeof(struct npppd_ctl))) == NULL)
+ return (NULL);
+ memset(ctl, 0, sizeof(struct npppd_ctl));
+ ctl->npppd = _this;
+ TAILQ_INIT(&ctl->stopped_ppps);
-#ifdef USE_NPPPD_PIPEX
-static int npppd_ppp_get_pipex_stat(struct npppd_who *, npppd_ppp *);
-#endif
-static int npppd_ppp_compar(const void *, const void *);
+ return (ctl);
+}
-/** initialize npppd management */
void
-npppd_ctl_init(npppd_ctl *_this, npppd *_npppd, const char *pathname)
+npppd_ctl_destroy(struct npppd_ctl *_this)
{
- memset(_this, 0, sizeof(npppd_ctl));
- if (pathname != NULL)
- strlcat(_this->pathname, pathname, sizeof(_this->pathname));
- _this->sock = -1;
- _this->npppd = _npppd;
+ if (_this != NULL) {
+ if (_this->started_ppp != NULL)
+ free(_this->started_ppp);
+ free(_this);
+ }
}
-/** start npppd management */
int
-npppd_ctl_start(npppd_ctl *_this)
+npppd_ctl_who(struct npppd_ctl *_this)
{
- int flags, dummy, val;
- struct sockaddr_un sun;
+ return (npppd_ctl_who0(_this, false));
+}
- if ((_this->sock = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0) {
- log_printf(LOG_ERR, "socket() failed in %s(): %m", __func__);
- goto fail;
- }
+int
+npppd_ctl_monitor(struct npppd_ctl *_this)
+{
+ _this->is_monitoring = true;
+ return (0);
+}
- val = NPPPD_CTL_MSGSZ;
- if (setsockopt(_this->sock, SOL_SOCKET, SO_SNDBUF, &val, sizeof(val))
- != 0) {
- if (errno == ENOBUFS)
- log_printf(LOG_ERR,
- "ctl.max_msgbuf may beyonds kernel limit. "
- "setsockopt(,SOL_SOCKET, SO_SNDBUF,%d) "
- "failed in %s(): %m", val, __func__);
- /*
- * on NetBSD, need to set value which is less than or equal
- * to kern.sbmax.
- */
- else
- log_printf(LOG_ERR,
- "setsockopt(,SOL_SOCKET, SO_SNDBUF,%d) "
- "failed in %s(): %m", val, __func__);
+int
+npppd_ctl_who_and_monitor(struct npppd_ctl *_this)
+{
+ return (npppd_ctl_who0(_this, true));
+}
- goto fail;
- }
- unlink(_this->pathname);
- memset(&sun, 0, sizeof(sun));
- sun.sun_family = AF_UNIX;
- sun.sun_len = sizeof(sun);
- strlcpy(sun.sun_path, _this->pathname, sizeof(sun.sun_path));
-
- if (bind(_this->sock, (struct sockaddr *)&sun, sizeof(sun)) != 0) {
- log_printf(LOG_ERR, "bind() failed in %s(): %m", __func__);
- goto fail;
- }
+static int
+npppd_ctl_who0(struct npppd_ctl *_this, bool is_monitoring)
+{
+ _this->is_monitoring = is_monitoring;
+ _this->responding = true;
+ if (rd_walktree(_this->npppd->rd, npppd_ctl_who_walk_rd, _this) != 0)
+ return (-1);
+ return (0);
+}
- dummy = 0;
- if ((flags = fcntl(_this->sock, F_GETFL, &dummy)) < 0) {
- log_printf(LOG_ERR, "fcntl(,F_GETFL) failed in %s(): %m",
- __func__);
- goto fail;
- } else if (fcntl(_this->sock, F_SETFL, flags | O_NONBLOCK) < 0) {
- log_printf(LOG_ERR, "fcntl(,F_SETFL,O_NONBLOCK) failed in %s()"
- ": %m", __func__);
- goto fail;
- }
- if (chmod(_this->pathname, NPPPD_CTL_SOCK_FILE_MODE) != 0) {
- log_printf(LOG_ERR, "chmod() failed in %s(): %m", __func__);
- goto fail;
+int
+npppd_ctl_add_started_ppp_id(struct npppd_ctl *_this, u_int ppp_id)
+{
+ int started_ppp_siz;
+ u_int *started_ppp;
+
+ if (!_this->is_monitoring && !_this->responding)
+ return (-1);
+ if (_this->started_ppp_pos + 1 >= _this->started_ppp_siz) {
+ started_ppp_siz = _this->started_ppp_siz + 128;
+ if (_this->started_ppp == NULL)
+ started_ppp = malloc(sizeof(u_int) * started_ppp_siz);
+ else
+ started_ppp = realloc(_this->started_ppp,
+ sizeof(u_int) * started_ppp_siz);
+ if (started_ppp == NULL)
+ return (-1);
+ _this->started_ppp = started_ppp;
+ _this->started_ppp_siz = started_ppp_siz;
}
+ _this->started_ppp[_this->started_ppp_pos++] = ppp_id;
- event_set(&_this->ev_sock, _this->sock, EV_READ | EV_PERSIST,
- npppd_ctl_io_event, _this);
- event_add(&_this->ev_sock, NULL);
+ /* reset the event */
- log_printf(LOG_INFO, "Listening %s (npppd_ctl)", _this->pathname);
+ return (0);
+}
- return 0;
-fail:
- if (_this->sock >= 0)
- close(_this->sock);
- _this->sock = -1;
+int
+npppd_ctl_add_stopped_ppp(struct npppd_ctl *_this, npppd_ppp *ppp)
+{
+ struct stopped_ppp *stopped;
+
+ if (!_this->is_monitoring)
+ return (-1);
+ if ((stopped = malloc(sizeof(struct stopped_ppp))) == NULL) {
+ log_warn("malloc() failed in %s()", __func__);
+ return (-1);
+ }
+ npppd_who_init(&stopped->ppp_who, ppp);
+ TAILQ_INSERT_TAIL(&_this->stopped_ppps, stopped, entry);
- return -1;
+ return (0);
}
-/** stop npppd management */
-void
-npppd_ctl_stop(npppd_ctl *_this)
+static int
+npppd_ctl_who_walk_rd(struct radish *rd, void *ctx)
{
- if (_this->sock >= 0) {
- event_del(&_this->ev_sock);
- close(_this->sock);
- _this->sock = -1;
- log_printf(LOG_INFO, "Shutdown %s (npppd_ctl)",
- _this->pathname);
+ struct npppd_ctl *_this = ctx;
+ struct sockaddr_npppd *snp;
+ npppd_ppp *ppp;
+
+ snp = rd->rd_rtent;
+ if (snp->snp_type == SNP_PPP) {
+ ppp = snp->snp_data_ptr;
+ if (npppd_ctl_add_started_ppp_id(_this, ppp->id) != 0)
+ return (-1);
}
+
+ return (0);
}
-/** execute management procedure on each command */
-static void
-npppd_ctl_command(npppd_ctl *_this, u_char *pkt, int pktlen,
- struct sockaddr *peer)
+int
+npppd_ctl_disconnect(struct npppd_ctl *_this, u_int *ppp_id, int count)
{
- u_char respbuf[NPPPD_CTL_MSGSZ];
- int command;
+ int i, n;
+ npppd_ppp *ppp;
- if (pktlen < sizeof(int)) {
- npppd_ctl_log(_this, LOG_ERR, "Packet too small.");
- return;
- }
- command = *(int *)pkt;
- switch (command) {
- case NPPPD_CTL_CMD_WHO: {
- int i, c, idx, msgsz;
- npppd *_npppd;
- struct npppd_ctl_who_response *res;
- slist users;
-
- res = NULL;
- _npppd = _this->npppd;
- slist_init(&users);
- if (npppd_get_all_users(_npppd, &users) != 0) {
- npppd_ctl_log(_this, LOG_ERR,
- "npppd_get_all_users() failed in %s: %m", __func__);
- goto cmd_who_out;
- }
-#ifdef NPPPD_CTL_DEBUG
-#if 0
- /* for debug, copy the first user 1600 times. */
- if (slist_length(&users) > 0) {
- for (i = 0; i < 1600; i++)
- slist_add(&users, slist_get(&users, 0));
- }
-#endif
-#endif
- res = (struct npppd_ctl_who_response *)respbuf;
-
- /* number of entry per chunk */
- c = NPPPD_CTL_MSGSZ - sizeof(struct npppd_ctl_who_response);
- c /= sizeof(struct npppd_who);
-
- slist_qsort(&users, npppd_ppp_compar);
- res->count = slist_length(&users);
- slist_itr_first(&users);
- for (i = 0, idx = 0; slist_itr_has_next(&users); i++) {
- npppd_who_init(&res->entry[idx++], _this,
- slist_itr_next(&users));
- idx %= c;
- if (idx == 0) {
- /* the last entry this chunk */
- msgsz = offsetof(struct npppd_ctl_who_response,
- entry[c]);
- if (sendto(_this->sock, res, msgsz, 0, peer,
- peer->sa_len) < 0)
- goto cmd_who_send_error;
- }
- }
- if (i == 0 || idx != 0) {
- msgsz = offsetof(struct npppd_ctl_who_response, entry[(i % c)]);
- if (sendto(_this->sock, res, msgsz, 0, peer,
- peer->sa_len) < 0)
- goto cmd_who_send_error;
- }
-cmd_who_out:
- slist_fini(&users);
- break;
-cmd_who_send_error:
- /*
- * FIXME: we should wait until the buffer is available.
- */
- NPPPD_CTL_DBG((_this, LOG_DEBUG, "sendto() failed in %s: %m",
- __func__));
- if (errno == ENOBUFS || errno == EMSGSIZE || errno == EINVAL) {
- npppd_ctl_log(_this, LOG_INFO,
- "'who' is requested, but "
- "the buffer is not enough.");
- } else {
- npppd_ctl_log(_this, LOG_ERR,
- "sendto() failed in %s: %m",
- __func__);
- }
- slist_fini(&users);
- break;
- }
- case NPPPD_CTL_CMD_DISCONNECT_USER: {
- int i, stopped;
- npppd *_npppd;
- struct npppd_ctl_disconnect_user_request *req;
- npppd_ppp *ppp;
- slist *ppplist;
-
- stopped = 0;
- _npppd = _this->npppd;
- req = (struct npppd_ctl_disconnect_user_request *)pkt;
-
- if (sizeof(struct npppd_ctl_disconnect_user_request) > pktlen) {
- npppd_ctl_log(_this, LOG_ERR,
- "'disconnect by user' is requested, "
- " but the request has invalid data length"
- "(%d:%d)", pktlen, (int)sizeof(req->username));
- break;
- }
- for (i = 0; i < sizeof(req->username); i++) {
- if (req->username[i] == '\0')
- break;
- }
- if (i >= sizeof(req->username)) {
- npppd_ctl_log(_this, LOG_ERR,
- "'disconnect by user' is requested, "
- " but the request has invalid user name");
- break;
+ for (n = 0, i = 0; i < count; i++) {
+ if ((ppp = npppd_get_ppp_by_id(_this->npppd, ppp_id[i]))
+ != NULL) {
+ ppp_stop(ppp, NULL);
+ n++;
}
+ }
- if ((ppplist = npppd_get_ppp_by_user(_npppd, req->username))
- == NULL) {
- npppd_ctl_log(_this, LOG_INFO,
- "npppd_get_ppp_by_user() could't find user \"%s\" in %s: %m",
- req->username, __func__);
- goto user_end;
- break;
- }
- slist_itr_first(ppplist);
- while (slist_itr_has_next(ppplist)) {
- ppp = slist_itr_next(ppplist);
- if (ppp == NULL)
- continue;
+ return (n);
+}
- ppp_stop(ppp, NULL);
- stopped++;
- }
-user_end:
-
- npppd_ctl_log(_this, LOG_NOTICE,
- "'disconnect by user' is requested, "
- "stopped %d connections.", stopped);
- snprintf(respbuf, sizeof(respbuf),
- "Disconnected %d ppp connections", stopped);
-
- if (sendto(_this->sock, respbuf, strlen(respbuf), 0, peer,
- peer->sa_len) < 0) {
- npppd_ctl_log(_this, LOG_ERR,
- "sendto() failed in %s: %m", __func__);
- }
- break;
- }
- case NPPPD_CTL_CMD_RESET_ROUTING_TABLE:
- {
- if (npppd_reset_routing_table(_this->npppd, 0) == 0)
- strlcpy(respbuf, "Reset the routing table successfully.",
- sizeof(respbuf));
- else
- snprintf(respbuf, sizeof(respbuf),
- "Failed to reset the routing table.:%s",
- strerror(errno));
-
- if (sendto(_this->sock, respbuf, strlen(respbuf), 0, peer,
- peer->sa_len) < 0) {
- npppd_ctl_log(_this, LOG_ERR,
- "sendto() failed in %s: %m", __func__);
- }
- break;
- }
- case NPPPD_CTL_CMD_DISCONNECT:
- {
- int i, n;
- slist users;
- npppd_ppp *ppp;
- struct npppd_ctl_disconnect_request *req;
- struct npppd_ctl_disconnect_response resp;
-
- req = (struct npppd_ctl_disconnect_request *)pkt;
- if (sizeof(struct npppd_ctl_disconnect_request) > pktlen ||
- offsetof(struct npppd_ctl_disconnect_request,
- ppp_id[req->count]) > pktlen) {
- npppd_ctl_log(_this, LOG_ERR,
- "Disconnect is requested, but the request has "
- "invalid data length(%d).", pktlen);
- break;
+int
+npppd_ctl_imsg_compose(struct npppd_ctl *_this, struct imsgbuf *ibuf)
+{
+ int i, cnt;
+ u_char pktbuf[MAX_IMSGSIZE - IMSG_HEADER_SIZE];
+ struct npppd_who_list *who_list;
+ npppd_ppp *ppp;
+ struct stopped_ppp *e, *t;
+
+ if (ibuf->w.queued)
+ return (0);
+
+ cnt = 0;
+ if (!TAILQ_EMPTY(&_this->stopped_ppps)) {
+ who_list = (struct npppd_who_list *)pktbuf;
+ who_list->more_data = 0;
+ TAILQ_FOREACH_SAFE(e, &_this->stopped_ppps, entry, t) {
+ if (offsetof(struct npppd_who_list, entry[cnt + 1])
+ > sizeof(pktbuf)) {
+ who_list->more_data = 1;
+ break;
+ }
+ TAILQ_REMOVE(&_this->stopped_ppps, e, entry);
+ memcpy(&who_list->entry[cnt], &e->ppp_who,
+ sizeof(who_list->entry[0]));
+ cnt++;
+ free(e);
}
+ who_list->entry_count = cnt;
+ if (imsg_compose(ibuf, IMSG_PPP_STOP, 0, 0, -1, pktbuf,
+ offsetof(struct npppd_who_list, entry[cnt])) == -1)
+ return (-1);
- n = 0;
- slist_init(&users);
- if (npppd_get_all_users(_this->npppd, &users) != 0) {
- npppd_ctl_log(_this, LOG_ERR,
- "npppd_get_all_users() failed at %s(): %m",
- __func__);
- goto cmd_disconnect_fail;
- }
- for (i = 0; i < req->count; i++) {
- slist_itr_first(&users);
- while (slist_itr_has_next(&users)) {
- ppp = slist_itr_next(&users);
- if (ppp->id == req->ppp_id[i]) {
- n++;
- slist_itr_remove(&users);
- ppp_stop(ppp, NULL);
- break;
- }
+ return (0);
+ }
+ if (_this->responding || _this->started_ppp_pos > 0) {
+ who_list = (struct npppd_who_list *)pktbuf;
+ who_list->more_data = 0;
+ for (cnt = 0, i = 0; i < _this->started_ppp_pos; i++) {
+ if (offsetof(struct npppd_who_list, entry[cnt + 1])
+ > sizeof(pktbuf)) {
+ who_list->more_data = 1;
+ break;
}
+ if ((ppp = npppd_get_ppp_by_id(_this->npppd,
+ _this->started_ppp[i])) == NULL)
+ /* may be disconnected */
+ continue;
+ npppd_who_init(&who_list->entry[cnt], ppp);
+ cnt++;
}
-cmd_disconnect_fail:
- npppd_ctl_log(_this, LOG_INFO,
- "Disconnect is requested. Requested %d session%s, "
- "disconnected %d session%s.", req->count,
- (req->count > 1)? "s" : "", n, (n > 1)? "s" : "");
- slist_fini(&users);
- resp.count = n;
- if (sendto(_this->sock, &resp, sizeof(resp), 0, peer,
- peer->sa_len) < 0)
- npppd_ctl_log(_this, LOG_ERR,
- "sendto() failed in %s: %m", __func__);
- }
- break;
- default:
- npppd_ctl_log(_this, LOG_ERR,
- "Received unknown command %04x", command);
+ who_list->entry_count = cnt;
+ if (imsg_compose(ibuf, IMSG_PPP_START, 0, 0, -1, pktbuf,
+ offsetof(struct npppd_who_list, entry[cnt])) == -1)
+ return (-1);
+
+ if (_this->started_ppp_pos > i)
+ memmove(&_this->started_ppp[0],
+ &_this->started_ppp[i],
+ sizeof(u_int) *
+ (_this->started_ppp_pos - i));
+ _this->started_ppp_pos -= i;
+ if (who_list->more_data == 0)
+ _this->responding = false;
+ return (0);
}
- return;
+ return (0);
}
static void
-npppd_who_init(struct npppd_who *_this, npppd_ctl *ctl, npppd_ppp *ppp)
+npppd_who_init(struct npppd_who *_this, npppd_ppp *ppp)
{
- struct timespec curr_time;
+ struct timespec curr_time;
npppd_auth_base *realm = ppp->realm;
- npppd_iface *iface = ppp_iface(ppp);
+ npppd_iface *iface = ppp_iface(ppp);
strlcpy(_this->username, ppp->username, sizeof(_this->username));
_this->time = ppp->start_time;
- if (clock_gettime(CLOCK_MONOTONIC, &curr_time) < 0) {
- NPPPD_CTL_ASSERT(0);
- }
+ clock_gettime(CLOCK_MONOTONIC, &curr_time);
_this->duration_sec = curr_time.tv_sec - ppp->start_monotime;
strlcpy(_this->tunnel_proto, npppd_ppp_tunnel_protocol_name(
ppp->pppd, ppp), sizeof(_this->tunnel_proto));
_this->tunnel_peer.peer_in4.sin_family = AF_UNSPEC;
if (((struct sockaddr *)&ppp->phy_info)->sa_len > 0) {
- NPPPD_CTL_ASSERT(sizeof(_this->tunnel_peer) >=
- ((struct sockaddr *)&ppp->phy_info)->sa_len);
memcpy(&_this->tunnel_peer, &ppp->phy_info,
MIN(sizeof(_this->tunnel_peer),
((struct sockaddr *)&ppp->phy_info)->sa_len));
}
strlcpy(_this->ifname, iface->ifname, sizeof(_this->ifname));
- strlcpy(_this->rlmname, npppd_auth_get_name(realm),
- sizeof(_this->rlmname));
+ if (realm == NULL)
+ _this->rlmname[0] = '\0';
+ else
+ strlcpy(_this->rlmname, npppd_auth_get_name(realm),
+ sizeof(_this->rlmname));
- _this->framed_ip_address = ppp->ppp_framed_ip_address;
+ _this->framed_ip_address = ppp->acct_framed_ip_address;
_this->ipackets = ppp->ipackets;
_this->opackets = ppp->opackets;
_this->ierrors = ppp->ierrors;
@@ -465,8 +307,8 @@ npppd_who_init(struct npppd_who *_this, npppd_ctl *ctl, npppd_ppp *ppp)
#ifdef USE_NPPPD_PIPEX
if (ppp->pipex_enabled != 0) {
if (npppd_ppp_get_pipex_stat(_this, ppp) != 0) {
- npppd_ctl_log(ctl, LOG_NOTICE,
- "npppd_ppp_get_pipex_stat() failed in %s: %m",
+ log_warn(
+ "npppd_ppp_get_pipex_stat() failed in %s",
__func__);
}
}
@@ -477,16 +319,16 @@ npppd_who_init(struct npppd_who *_this, npppd_ctl *ctl, npppd_ppp *ppp)
static int
npppd_ppp_get_pipex_stat(struct npppd_who *_this, npppd_ppp *ppp)
{
- npppd_iface *iface = ppp_iface(ppp);
- struct pipex_session_stat_req req;
+ npppd_iface *iface = ppp_iface(ppp);
+ struct pipex_session_stat_req req;
#ifdef USE_NPPPD_PPPOE
- pppoe_session *pppoe;
+ pppoe_session *pppoe;
#endif
#ifdef USE_NPPPD_PPTP
- pptp_call *call;
+ pptp_call *pptp;
#endif
#ifdef USE_NPPPD_L2TP
- l2tp_call *l2tp;
+ l2tp_call *l2tp;
#endif
if (ppp->pipex_enabled == 0)
@@ -505,10 +347,10 @@ npppd_ppp_get_pipex_stat(struct npppd_who *_this, npppd_ppp *ppp)
#endif
#ifdef USE_NPPPD_PPTP
case NPPPD_TUNNEL_PPTP:
- call = (pptp_call *)ppp->phy_context;
+ pptp = (pptp_call *)ppp->phy_context;
/* PPTP specific information */
- req.psr_session_id = call->id;
+ req.psr_session_id = pptp->id;
req.psr_protocol = PIPEX_PROTO_PPTP;
break;
#endif
@@ -522,7 +364,6 @@ npppd_ppp_get_pipex_stat(struct npppd_who *_this, npppd_ppp *ppp)
break;
#endif
default:
- NPPPD_CTL_ASSERT(0);
errno = EINVAL;
return 1;
}
@@ -541,58 +382,3 @@ npppd_ppp_get_pipex_stat(struct npppd_who *_this, npppd_ppp *ppp)
return 0;
}
#endif
-
-/** IO event handler */
-static void
-npppd_ctl_io_event(int fd, short evmask, void *ctx)
-{
- int sz;
- u_char buf[NPPPD_CTL_MSGSZ];
- npppd_ctl *_this;
- struct sockaddr_storage ss;
- socklen_t sslen;
-
- _this = ctx;
- if ((evmask & EV_READ) != 0) {
- sslen = sizeof(ss);
- if ((sz = recvfrom(_this->sock, buf, sizeof(buf), 0,
- (struct sockaddr *)&ss, &sslen)) < 0) {
- npppd_ctl_log(_this, LOG_ERR,
- "recvfrom() failed in %s(): %m", __func__);
- npppd_ctl_stop(_this);
-
- return;
- }
- npppd_ctl_command(_this, buf, sz, (struct sockaddr *)&ss);
- }
- return;
-}
-
-/** Record log that begins the label based this instance. */
-static int
-npppd_ctl_log(npppd_ctl *_this, int prio, const char *fmt, ...)
-{
- int status;
- char logbuf[BUFSIZ];
- va_list ap;
-
- NPPPD_CTL_ASSERT(_this != NULL);
-
- va_start(ap, fmt);
- snprintf(logbuf, sizeof(logbuf), "npppdctl: %s", fmt);
- status = vlog_printf(prio, logbuf, ap);
- va_end(ap);
-
- return status;
-}
-
-static int
-npppd_ppp_compar(const void *a0, const void *b0)
-{
- npppd_ppp const *a, *b;
-
- a = a0;
- b = b0;
-
- return a->id - b->id;
-}
diff --git a/usr.sbin/npppd/npppd/npppd_ctl.h b/usr.sbin/npppd/npppd/npppd_ctl.h
index fd0386c2712..29a52e1564d 100644
--- a/usr.sbin/npppd/npppd/npppd_ctl.h
+++ b/usr.sbin/npppd/npppd/npppd_ctl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: npppd_ctl.h,v 1.5 2012/05/08 13:15:12 yasuoka Exp $ */
+/* $OpenBSD: npppd_ctl.h,v 1.6 2014/03/22 04:30:31 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -28,115 +28,68 @@
#ifndef NPPPD_CTL_H
#define NPPPD_CTL_H 1
-/** Message size of npppd control protocol messages */
-#define NPPPD_CTL_MSGSZ 2048
+#include <sys/types.h>
+#include <sys/socket.h> /* for <netinet/in.h> */
+#include <net/if.h> /* for IF_NAMESIZE */
+#include <net/if_dl.h> /* for sockaddr_dl */
+#include <netinet/in.h> /* for sockaddr_in{,6} and in_addr */
+#include <imsg.h> /* for imsg */
+#include <time.h> /* for time_t */
-/** Path of npppd control protocol's socket */
-#define NPPPD_CTL_SOCK_PATH "/var/run/npppd_ctl"
-
-/** Size of username */
+#define NPPPD_SOCKET "/var/run/npppd.sock"
#define NPPPD_CTL_USERNAME_SIZE 256
-/** Npppd control protocol command */
-enum npppd_ctl_cmd {
- /** Connected user statistics */
- NPPPD_CTL_CMD_WHO,
-
- /** Disconnect specified user's sessions */
- NPPPD_CTL_CMD_DISCONNECT_USER,
-
- /** Set client authentication information */
- NPPPD_CTL_CMD_TERMID_SET_AUTH,
-
- /** Reset npppd's routing information to the system routing table */
- NPPPD_CTL_CMD_RESET_ROUTING_TABLE,
-
- /** Disconnect specified ppp-id's sessions */
- NPPPD_CTL_CMD_DISCONNECT
-};
-
-struct npppd_ctl_who_request {
- enum npppd_ctl_cmd cmd;
+enum imsg_type {
+ IMSG_NONE,
+ IMSG_CTL_OK, /* answers to npppctl requests */
+ IMSG_CTL_FAIL,
+ IMSG_CTL_NOP, /* npppctl requests */
+ IMSG_CTL_WHO,
+ IMSG_CTL_DISCONNECT,
+ IMSG_CTL_MONITOR,
+ IMSG_CTL_WHO_AND_MONITOR,
+ IMSG_PPP_START, /* notifies from npppd */
+ IMSG_PPP_STOP
};
struct npppd_who {
- /** Ppp Id */
- u_int ppp_id;
-
- /** Username */
- char username[NPPPD_CTL_USERNAME_SIZE];
-
- /** Start time */
- time_t time;
-
- /** Elapsed time */
- uint32_t duration_sec;
-
- /** Concentrated interface */
- char ifname[IF_NAMESIZE];
-
- /** Authenticated realm name */
- char rlmname[32];
-
- /** Tunnel protocol name */
- char tunnel_proto[16];
-
- /** Tunnel peer address */
+ u_int ppp_id; /** Ppp Id */
+ char username[NPPPD_CTL_USERNAME_SIZE];
+ /** Username */
+ time_t time; /** Start time */
+ uint32_t duration_sec; /** Elapsed time */
+ char ifname[IF_NAMESIZE];
+ /** Concentrated interface */
+ char rlmname[32]; /** Authenticated realm name */
+ char tunnel_proto[16];
+ /** Tunnel protocol name */
union {
struct sockaddr_in peer_in4;
struct sockaddr_in6 peer_in6;
struct sockaddr_dl peer_dl;
- } tunnel_peer;
-
- /** Framed IP Address */
- struct in_addr framed_ip_address;
-
- /** Numbers of input packets */
- uint32_t ipackets;
-
- /** Numbers of output packets */
- uint32_t opackets;
-
- /** Numbers of input error packets */
- uint32_t ierrors;
-
- /** Numbers of output error packets */
- uint32_t oerrors;
-
- /** Bytes of input packets */
- uint64_t ibytes;
-
- /** Bytes of output packets */
- uint64_t obytes;
+ } tunnel_peer; /** Tunnel peer address */
+ struct in_addr framed_ip_address;
+ /** Framed IP Address */
+ uint32_t ipackets; /** Numbers of input packets */
+ uint32_t opackets; /** Numbers of output packets */
+ uint32_t ierrors; /** Numbers of input error packets */
+ uint32_t oerrors; /** Numbers of output error packets */
+ uint64_t ibytes; /** Bytes of input packets */
+ uint64_t obytes; /** Bytes of output packets */
};
-struct npppd_ctl_who_response {
- int count;
- struct npppd_who entry[0];
+struct npppd_who_list {
+ int more_data; /** 1 if there is more data */
+ int entry_count; /** count of the entry */
+ struct npppd_who entry[0]; /** entry arrays */
};
-struct npppd_ctl_disconnect_user_request {
- enum npppd_ctl_cmd cmd;
- char username[NPPPD_CTL_USERNAME_SIZE];
-};
-
-struct npppd_ctl_termid_set_auth_request {
- enum npppd_ctl_cmd cmd;
- u_int use_ppp_id:1,
- use_framed_ip_address;
- u_int ppp_id;
- struct in_addr framed_ip_address;
- char authid[33];
-};
+struct npppd_disconnect_request {
+ int count;
+ u_int ppp_id[0];
+} ;
-struct npppd_ctl_disconnect_request {
- enum npppd_ctl_cmd cmd;
- int count;
- u_int ppp_id[0];
+struct npppd_disconnect_response {
+ int count;
};
-
-struct npppd_ctl_disconnect_response {
- int count;
-};
-
#endif
diff --git a/usr.sbin/npppd/npppd/npppd_local.h b/usr.sbin/npppd/npppd/npppd_local.h
index 2e15a8be0fc..b63cc506827 100644
--- a/usr.sbin/npppd/npppd/npppd_local.h
+++ b/usr.sbin/npppd/npppd/npppd_local.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: npppd_local.h,v 1.12 2013/04/16 07:42:27 yasuoka Exp $ */
+/* $OpenBSD: npppd_local.h,v 1.13 2014/03/22 04:30:31 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -71,22 +71,9 @@
#include "privsep.h"
-#include "npppd_ctl.h"
-typedef struct _npppd_ctl {
- /** event context */
- struct event ev_sock;
- /** socket */
- int sock;
- /** enabled or disabled */
- int enabled;
- /** parent of npppd structure */
- void *npppd;
- /** pathname of socket */
- char pathname[MAXPATHLEN];
-} npppd_ctl;
-
#include "addr_range.h"
#include "npppd_pool.h"
+#include "npppd_ctl.h"
/** structure of pool */
struct _npppd_pool {
@@ -106,6 +93,16 @@ struct _npppd_pool {
running:1;
};
+/** structure for control socket. (control.c) */
+struct control_sock {
+ const char *cs_name;
+ struct event cs_ev;
+ struct event cs_evt;
+ int cs_fd;
+ int cs_restricted;
+ void *cs_ctx;
+};
+
/**
* npppd
*/
@@ -160,7 +157,6 @@ struct _npppd {
/** configuration file */
struct npppd_conf conf;
- npppd_ctl ctl;
/** the time in seconds which process was started.*/
uint32_t secs;
@@ -171,6 +167,8 @@ struct _npppd {
int nsession;
+ struct control_sock ctl_sock;
+
u_int /** whether finalizing or not */
finalizing:1,
/** whether finalize completed or not */
@@ -191,16 +189,6 @@ struct _npppd {
: (interval) + NPPPD_TIMER_TICK_IVAL \
- ((interval) % NPPPD_TIMER_TICK_IVAL))
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void npppd_ctl_init (npppd_ctl *, npppd *, const char *);
-int npppd_ctl_start (npppd_ctl *);
-void npppd_ctl_stop (npppd_ctl *);
-
#ifdef __cplusplus
}
#endif
diff --git a/usr.sbin/npppd/npppd/ppp.c b/usr.sbin/npppd/npppd/ppp.c
index 18c86b53601..7c22261b37b 100644
--- a/usr.sbin/npppd/npppd/ppp.c
+++ b/usr.sbin/npppd/npppd/ppp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ppp.c,v 1.18 2013/02/13 22:10:38 yasuoka Exp $ */
+/* $OpenBSD: ppp.c,v 1.19 2014/03/22 04:30:31 yasuoka Exp $ */
/*-
* Copyright (c) 2009 Internet Initiative Japan Inc.
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-/* $Id: ppp.c,v 1.18 2013/02/13 22:10:38 yasuoka Exp $ */
+/* $Id: ppp.c,v 1.19 2014/03/22 04:30:31 yasuoka Exp $ */
/**@file
* This file provides PPP(Point-to-Point Protocol, RFC 1661) and
* {@link :: _npppd_ppp PPP instance} related functions.
@@ -408,6 +408,7 @@ ppp_stop0(npppd_ppp *_this)
#ifdef USE_NPPPD_RADIUS
npppd_ppp_radius_acct_stop(_this->pppd, _this);
#endif
+ npppd_on_ppp_stop(_this->pppd, _this);
npppd_ppp_unbind_iface(_this->pppd, _this);
#ifdef USE_NPPPD_MPPE
mppe_fini(&_this->mppe);
@@ -690,6 +691,7 @@ ppp_ipcp_opened(npppd_ppp *_this)
#ifdef USE_NPPPD_RADIUS
npppd_ppp_radius_acct_start(_this->pppd, _this);
#endif
+ npppd_on_ppp_start(_this->pppd, _this);
_this->logged_acct_start = 1;
ppp_reset_idle_timeout(_this);