diff options
author | YASUOKA Masahiko <yasuoka@cvs.openbsd.org> | 2014-03-22 04:30:32 +0000 |
---|---|---|
committer | YASUOKA Masahiko <yasuoka@cvs.openbsd.org> | 2014-03-22 04:30:32 +0000 |
commit | 4cc6857371113f98a8ac2b75230c3bf093f9b6f7 (patch) | |
tree | 421f5fe22aa8787fb8a5ff43059766cfe6052ed3 | |
parent | ed901d4d4c813fcea0da17718dbc0b1d0a3220ab (diff) |
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/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/npppctl/npppctl.8 | 37 | ||||
-rw-r--r-- | usr.sbin/npppctl/npppctl.c | 300 | ||||
-rw-r--r-- | usr.sbin/npppctl/parser.c | 17 | ||||
-rw-r--r-- | usr.sbin/npppctl/parser.h | 5 | ||||
-rw-r--r-- | usr.sbin/npppd/common/debugutil.h | 1 | ||||
-rw-r--r-- | usr.sbin/npppd/npppd/Makefile | 8 | ||||
-rw-r--r-- | usr.sbin/npppd/npppd/control.c | 360 | ||||
-rw-r--r-- | usr.sbin/npppd/npppd/npppd.c | 99 | ||||
-rw-r--r-- | usr.sbin/npppd/npppd/npppd.h | 44 | ||||
-rw-r--r-- | usr.sbin/npppd/npppd/npppd_config.c | 5 | ||||
-rw-r--r-- | usr.sbin/npppd/npppd/npppd_ctl.c | 634 | ||||
-rw-r--r-- | usr.sbin/npppd/npppd/npppd_ctl.h | 145 | ||||
-rw-r--r-- | usr.sbin/npppd/npppd/npppd_local.h | 40 | ||||
-rw-r--r-- | usr.sbin/npppd/npppd/ppp.c | 6 |
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); |