aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile26
-rw-r--r--src/doexec.112
-rw-r--r--src/doexec.c6
-rw-r--r--src/netreport.122
-rw-r--r--src/netreport.c45
-rw-r--r--src/testd.c7
-rwxr-xr-xsrc/testdinit44
-rw-r--r--src/usernetctl.118
-rw-r--r--src/usernetctl.c130
-rw-r--r--src/usleep.120
-rw-r--r--src/usleep.c37
11 files changed, 367 insertions, 0 deletions
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 00000000..b3324ef6
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,26 @@
+CFLAGS+=-Wall
+
+PROGS=usernetctl doexec netreport testd usleep
+
+all: $(PROGS)
+
+clean:
+ rm -f $(PROGS)
+
+install:
+ mkdir -p $(ROOT)/bin $(ROOT)/usr/sbin $(ROOT)/usr/man/man1
+ install -o 0 -g 0 -s -m 755 doexec $(ROOT)/bin/doexec
+ install -o 0 -g 0 -s -m 755 usleep $(ROOT)/bin/usleep
+ install -o 0 -g 0 -s -m 4755 usernetctl $(ROOT)/usr/sbin/usernetctl
+ install -o 0 -g 0 -s -m 2755 netreport $(ROOT)/sbin/netreport
+ install -m 644 doexec.1 $(ROOT)/usr/man/man1
+ install -m 644 netreport.1 $(ROOT)/usr/man/man1
+ install -m 644 usleep.1 $(ROOT)/usr/man/man1
+ install -m 644 usernetctl.1 $(ROOT)/usr/man/man1
+
+# this daemon and initscript are useful for testing the up/down/status stuff
+# not installed by default, only comes from sources.
+install-test:
+ install -o 0 -g 0 -s -m 755 testd $(ROOT)/usr/sbin/testd
+ install -o 0 -g 0 -m 755 testdinit $(ROOT)/etc/rc.d/init.d/testd
+
diff --git a/src/doexec.1 b/src/doexec.1
new file mode 100644
index 00000000..59b8b91e
--- /dev/null
+++ b/src/doexec.1
@@ -0,0 +1,12 @@
+.TH DOEXEC 1 "Red Hat Software" "RHS" \" -*- nroff -*-
+.SH NAME
+doexec \- run an executable with an arbitrary argv[0]
+.SH SYNOPSIS
+.B doexec
+\fI/path/to/executable\fP \fIargv[0]\fP [\fIargv[1-n]\fP]
+.SH DESCRIPTION
+.B doexec
+simply runs the executable with the argv list provided. It allows you
+to specify an argv[0] other than the name of the executable.
+.SH OPTIONS
+All options are passed in the argv list to the executable being run.
diff --git a/src/doexec.c b/src/doexec.c
new file mode 100644
index 00000000..a488be13
--- /dev/null
+++ b/src/doexec.c
@@ -0,0 +1,6 @@
+#include <unistd.h>
+
+int main(int argc, char ** argv) {
+ execvp(argv[1], argv + 2);
+ return 1;
+}
diff --git a/src/netreport.1 b/src/netreport.1
new file mode 100644
index 00000000..ff52e91b
--- /dev/null
+++ b/src/netreport.1
@@ -0,0 +1,22 @@
+.TH USERNETCTL 1 "Red Hat Software" "RHS" \" -*- nroff -*-
+.SH NAME
+netreport \- request notification of network interface changes
+.SH SYNOPSIS
+.B netreport
+\fI[\fP-r\fI]\fP
+.SH DESCRIPTION
+.B netreport
+tells the network management scripts to send a SIGIO signal
+to the process which called netreport when any network interface
+status changes occur.
+.SH OPTIONS
+.TP
+.B -r
+Remove the current request (if any) for the calling process.
+.PP
+.SH NOTES
+If a program does not call netreport with the
+.B -r
+option before it exits, and another process is created with the
+same PID before any changes take place in interface status, it
+is possible that the new process will receive a spurious SIGIO.
diff --git a/src/netreport.c b/src/netreport.c
new file mode 100644
index 00000000..56088ec1
--- /dev/null
+++ b/src/netreport.c
@@ -0,0 +1,45 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+/* this will be running setgid root, so be careful! */
+
+void usage(void) {
+ fprintf(stderr, "usage: netreport [-r]\n");
+ exit(1);
+}
+
+#define ADD 1
+#define DEL 0
+int main(int argc, char ** argv) {
+ int action = ADD;
+ /* more than long enough for "/var/run/netreport/<pid>\0" */
+ char netreport_name[64];
+ int netreport_file;
+
+ if (argc > 2) usage();
+
+ if ((argc > 1) && !strcmp(argv[1], "-r")) {
+ action = DEL;
+ }
+
+ sprintf(netreport_name, "/var/run/netreport/%d", getppid());
+ if (action == ADD) {
+ netreport_file = creat(netreport_name, 0);
+ if (netreport_file < 0) {
+ if (errno != EEXIST) {
+ perror("Could not create netreport file");
+ exit (1);
+ }
+ } else {
+ close(netreport_file);
+ }
+ } else {
+ /* ignore errors; not much we can do, won't hurt anything */
+ unlink(netreport_name);
+ }
+
+ exit(0);
+}
diff --git a/src/testd.c b/src/testd.c
new file mode 100644
index 00000000..f512cec9
--- /dev/null
+++ b/src/testd.c
@@ -0,0 +1,7 @@
+#include <sys/signal.h>
+#include <unistd.h>
+
+void main() {
+ signal(SIGTERM, SIG_IGN);
+ while (1) sleep(20);
+}
diff --git a/src/testdinit b/src/testdinit
new file mode 100755
index 00000000..f2f4a85b
--- /dev/null
+++ b/src/testdinit
@@ -0,0 +1,44 @@
+#!/bin/sh
+#
+# lpd This shell script takes care of starting and stopping
+# lpd (printer daemon).
+#
+
+# Source function library.
+. /etc/rc.d/init.d/functions
+
+# See how we were called.
+case "$1" in
+ start)
+ # Start daemons.
+ echo -n "Starting testd: "
+ testd &
+ echo
+ touch /var/lock/subsys/testd
+ ;;
+ stop)
+ # Stop daemons.
+ echo -n "Shutting down testd: "
+ killproc testd
+ echo
+ rm -f /var/lock/subsys/testd
+ ;;
+ status)
+ # Am I alive?
+ status testd
+ exit $?
+ ;;
+ restart)
+ echo -n "Shutting down testd: "
+ killproc testd
+ echo
+ echo -n "Starting testd: "
+ testd &
+ echo
+ ;;
+ *)
+ echo "Usage: testd {start|stop|status|restart}"
+ exit 1
+esac
+
+exit 0
diff --git a/src/usernetctl.1 b/src/usernetctl.1
new file mode 100644
index 00000000..1602f7b5
--- /dev/null
+++ b/src/usernetctl.1
@@ -0,0 +1,18 @@
+.TH USERNETCTL 1 "Red Hat Software" "RHS" \" -*- nroff -*-
+.SH NAME
+usernetctl \- allow a user to manipulate a network interface if permitted
+.SH SYNOPSIS
+.B usernetctl
+\fIconfig-file-name\fP up\fI|\fPdown
+.SH DESCRIPTION
+.B usernetctl
+checks to see if users are allowed to manipulate the network interface
+specified by \fIconfig-file-name\fP, and then tries to bring the network
+interface up or down, as specified.
+.SH OPTIONS
+.TP
+.I "\fIconfig-file-name"
+The name of the network configuration file to read; for example, ifcfg-ppp0
+.TP
+up\fI|\fPdown
+Attempt to bring the interface up or down.
diff --git a/src/usernetctl.c b/src/usernetctl.c
new file mode 100644
index 00000000..1139a8c5
--- /dev/null
+++ b/src/usernetctl.c
@@ -0,0 +1,130 @@
+#include <alloca.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/* this will be running setuid root, so be careful! */
+
+void usage(void) {
+ fprintf(stderr, "usage: usernetctl <interface-config> <up|down>\n");
+ exit(1);
+}
+
+static char * safeEnviron[] = {
+ "PATH=/bin:/sbin:/usr/bin:/usr/sbin",
+ "HOME=/root",
+ NULL
+};
+
+int userCtl(char * file, int size) {
+ char * contents;
+ char * chptr;
+ char * end;
+ int fd;
+
+ contents = alloca(size + 2);
+
+ if ((fd = open(file, O_RDONLY)) < 0) {
+ fprintf(stderr, "failed to open %s: %s\n", file, strerror(errno));
+ exit(1);
+ }
+
+ if (read(fd, contents, size) != size) {
+ perror("error reading device configuration");
+ exit(1);
+ }
+ close(fd);
+
+ contents[size] = '\n';
+ contents[size + 1] = '\0';
+
+ /* each pass parses a single line (until an answer is found), contents
+ itself points to the beginning of the current line */
+ while (*contents) {
+ chptr = contents;
+ while (*chptr != '\n') chptr++;
+ end = chptr + 1;
+ while (chptr > contents && isspace(*chptr)) chptr--;
+ *(++chptr) = '\0';
+
+ if (!strcmp(contents, "USERCTL=yes")) return 1;
+
+ contents = end;
+ }
+
+ return 0;
+}
+
+int main(int argc, char ** argv) {
+ char * ifaceConfig;
+ char * chptr;
+ struct stat sb;
+ char * cmd;
+
+ if (argc != 3) usage();
+
+ if (!strcmp(argv[2], "up")) {
+ cmd = "./ifup";
+ } else if (!strcmp(argv[2], "down")) {
+ cmd = "./ifdown";
+ } else {
+ usage();
+ }
+
+ if (chdir("/etc/sysconfig/network-scripts")) {
+ fprintf(stderr, "error switching to /etc/sysconfig/network-scripts: "
+ "%s\n", strerror(errno));
+ exit(1);
+ }
+
+ /* force the interface configuration to be in the current directory */
+ chptr = ifaceConfig = argv[1];
+ while (*chptr) {
+ if (*chptr == '/')
+ ifaceConfig = chptr + 1;
+ chptr++;
+ }
+
+ /* these shouldn't be symbolic links -- anal, but that's fine w/ me */
+ if (lstat(ifaceConfig, &sb)) {
+ fprintf(stderr, "failed to stat %s: %s\n", ifaceConfig,
+ strerror(errno));
+ exit(1);
+ }
+
+ /* safety checks */
+ if (!S_ISREG(sb.st_mode)) {
+ fprintf(stderr, "%s is not a normal file\n", ifaceConfig);
+ exit(1);
+ }
+
+ if (sb.st_uid) {
+ fprintf(stderr, "%s should be owned by root\n", ifaceConfig);
+ exit(1);
+ }
+
+ if (sb.st_mode & S_IWOTH) {
+ fprintf(stderr, "%s should not be world writeable\n", ifaceConfig);
+ exit(1);
+ }
+
+ if (!userCtl(ifaceConfig, sb.st_size)) {
+ fprintf(stderr, "Users are not allowed to control this interface.\n");
+ exit(1);
+ }
+
+ /* looks good to me -- let's go for it */
+
+ /* pppd wants the real uid to be the same as the effective (god only
+ knows why when it works fine setuid out of the box) */
+ setuid(geteuid());
+
+ execle(cmd, cmd, ifaceConfig, NULL, safeEnviron);
+ fprintf(stderr, "exec of %s failed: %s\n", cmd, strerror(errno));
+
+ exit(1);
+}
diff --git a/src/usleep.1 b/src/usleep.1
new file mode 100644
index 00000000..f1e19025
--- /dev/null
+++ b/src/usleep.1
@@ -0,0 +1,20 @@
+.TH USLEEP 1 "Red Hat Software" "RHS" \" -*- nroff -*-
+.SH NAME
+usleep \- sleep some number of microseconds
+.SH SYNOPSIS
+.B usleep
+[\fInumber\fP]
+.SH DESCRIPTION
+.B usleep
+sleeps some number of microseconds. The default is 1.
+.SH OPTIONS
+\fI--help\fP
+Print help information.
+.TP
+\fI-v\fP
+Print version information.
+.SH BUGS
+Probably not accurate on many machines down to the microsecond. Count
+on precision only to -4 or maybe -5.
+.SH AUTHOR
+Donald Barnes <djb@redhat.com>
diff --git a/src/usleep.c b/src/usleep.c
new file mode 100644
index 00000000..dbffc850
--- /dev/null
+++ b/src/usleep.c
@@ -0,0 +1,37 @@
+/*
+ * usleep
+ *
+ * Written by Donald Barnes <djb@redhat.com> for Red Hat Software.
+ *
+ */
+
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+void main(int argc, char **argv)
+{
+
+ double count;
+
+ if (argc == 1) count=1;
+ else if (!strcmp(argv[1], "--help"))
+ {
+ printf("usleep [number]\n sleep [number] of microseconds\n the default number to sleep is 1 microsecond\n");
+ exit(0);
+ }
+ else if (!strcmp(argv[1], "-v"))
+ {
+ printf("usleep version 1.0 by Donald Barnes <djb@redhat.com>\n usleep --help for more info\n");
+ exit(0);
+ }
+ else
+ count = strtod(argv[1], NULL);
+
+ usleep(count);
+ exit(0);
+
+
+}