- Add startup-config(5) manpage [FIXME].
- Revise nsctl to allow arbitrary strings/args to be passed to plugins.
This commit is contained in:
parent
5d4d6bb059
commit
5e01d2924d
17 changed files with 796 additions and 415 deletions
10
Changes
10
Changes
|
|
@ -1,12 +1,12 @@
|
||||||
* ?
|
* Wed Nov 17 2004 Brendan O'Dea <bod@optusnet.com.au> 2.0.8
|
||||||
- Add manpages from Jonathan McDowell
|
|
||||||
- Remove reference to old -a command line argument
|
|
||||||
|
|
||||||
* Tue Nov 16 2004 Brendan O'Dea <bod@optusnet.com.au> 2.0.8
|
|
||||||
- Ignore gateway address in Framed-Route (from Jonathan McDowell).
|
- Ignore gateway address in Framed-Route (from Jonathan McDowell).
|
||||||
- Call sessionshutdown() when a tunnel is dropped rather than
|
- Call sessionshutdown() when a tunnel is dropped rather than
|
||||||
sessionkill() to ensure that RADIUS stop records are sent.
|
sessionkill() to ensure that RADIUS stop records are sent.
|
||||||
- Cleanup: make a bunch of global functions/variables static.
|
- Cleanup: make a bunch of global functions/variables static.
|
||||||
|
- Remove reference to old -a command line argument.
|
||||||
|
- Add l2tpns(8) and nsctl(8) manpages from Jonathan McDowell.
|
||||||
|
- Add startup-config(5) manpage [FIXME].
|
||||||
|
- Revise nsctl to allow arbitrary strings/args to be passed to plugins.
|
||||||
|
|
||||||
* Mon Nov 15 2004 Brendan O'Dea <bod@optusnet.com.au> 2.0.7
|
* Mon Nov 15 2004 Brendan O'Dea <bod@optusnet.com.au> 2.0.7
|
||||||
- Fix socket creation in host_unreachable() (thanks to Bjørn Augestad)
|
- Fix socket creation in host_unreachable() (thanks to Bjørn Augestad)
|
||||||
|
|
|
||||||
64
Docs/l2tpns.8
Normal file
64
Docs/l2tpns.8
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
.\" -*- nroff -*-
|
||||||
|
.de Id
|
||||||
|
.ds Dt \\$4 \\$5
|
||||||
|
..
|
||||||
|
.Id $Id: l2tpns.8,v 1.1 2004-11-17 08:23:35 bodea Exp $
|
||||||
|
.TH L2TPNS 8 "\*(Dt" L2TPNS "System Management Commands"
|
||||||
|
.SH NAME
|
||||||
|
l2tpns \- L2TP LNS daemon
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B l2tpns
|
||||||
|
.RB [ \-d ]
|
||||||
|
.RB [ \-v ]
|
||||||
|
.RB [ \-c
|
||||||
|
.IR file ]
|
||||||
|
.RB [ \-h
|
||||||
|
.IR hostname ]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
This manual page documents briefly the
|
||||||
|
.B l2tpns
|
||||||
|
command.
|
||||||
|
.PP
|
||||||
|
.B l2tpns
|
||||||
|
is an L2TP LNS daemon that doesn't require kernel support for PPP or
|
||||||
|
L2TP, nor any kernel patches. For more information on L2TP see RFC
|
||||||
|
2661.
|
||||||
|
.PP
|
||||||
|
Once running,
|
||||||
|
.B l2tpns
|
||||||
|
may be controlled by telnetting to port 23 on the machine running the
|
||||||
|
daemon and with the
|
||||||
|
.B nsctl
|
||||||
|
utility.
|
||||||
|
.SH OPTIONS
|
||||||
|
.TP
|
||||||
|
.B \-d
|
||||||
|
Detach from terminal and fork into the background. By default l2tpns
|
||||||
|
will stay in the foreground.
|
||||||
|
.TP
|
||||||
|
.B \-v
|
||||||
|
Increase verbosity for debugging. Can be used multiple times.
|
||||||
|
.TP
|
||||||
|
.BI "\-c " file
|
||||||
|
Specify configuration file.
|
||||||
|
.TP
|
||||||
|
.BI "\-h " hostname
|
||||||
|
Force hostname to
|
||||||
|
.IR hostname .
|
||||||
|
.SH FILES
|
||||||
|
.TP
|
||||||
|
.I /etc/l2tpns/startup-config
|
||||||
|
The default configuration file.
|
||||||
|
.TP
|
||||||
|
.I /etc/l2tpns/ip_pool
|
||||||
|
IP address pool configuration.
|
||||||
|
.TP
|
||||||
|
.I /etc/l2tpns/users
|
||||||
|
Username/password configuration for access to admin interface.
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR startup-config (5),
|
||||||
|
and
|
||||||
|
.BR nsctl (8)
|
||||||
|
.SH AUTHOR
|
||||||
|
This manual page was written by Jonathan McDowell <noodles@earth.li>,
|
||||||
|
for the Debian GNU/Linux system (but may be used by others).
|
||||||
67
Docs/nsctl.8
Normal file
67
Docs/nsctl.8
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
.\" -*- nroff -*-
|
||||||
|
.de Id
|
||||||
|
.ds Dt \\$4 \\$5
|
||||||
|
..
|
||||||
|
.Id $Id: nsctl.8,v 1.1 2004-11-17 08:23:35 bodea Exp $
|
||||||
|
.TH NSCTL 8 "\*(Dt" L2TPNS "System Management Commands"
|
||||||
|
.SH NAME
|
||||||
|
nsctl \- Issue commands to l2tpns plugins
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B nsctl
|
||||||
|
.RB [ \-d ]
|
||||||
|
.RB [ \-h
|
||||||
|
.IR host [: port ]]
|
||||||
|
.RB [ \-t
|
||||||
|
.IR timeout ]
|
||||||
|
.I command
|
||||||
|
.RI [ arg " ...]"
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B nsctl
|
||||||
|
is part of the
|
||||||
|
.B l2tpns
|
||||||
|
package. It allows the system administrator to send manage plugin
|
||||||
|
features of a running l2tpns process.
|
||||||
|
.SH OPTIONS
|
||||||
|
.TP
|
||||||
|
.B \-d
|
||||||
|
Enable debugging output.
|
||||||
|
.TP
|
||||||
|
.B \-h \fIhost\fR[:\fIport\fR]
|
||||||
|
The host running
|
||||||
|
.B l2tpns
|
||||||
|
that should receive the message. By default the message is sent to
|
||||||
|
UDP port 1702 on
|
||||||
|
.BR localhost .
|
||||||
|
.TP
|
||||||
|
.B \-t \fItimeout\fR
|
||||||
|
Timeout in seconds to wait for a response from the server.
|
||||||
|
.SH COMMANDS
|
||||||
|
The first argument specifies the command to send to
|
||||||
|
.B l2tpns .
|
||||||
|
The following commands are as defined:
|
||||||
|
.TP
|
||||||
|
.BI "load_plugin " plugin
|
||||||
|
Load the named
|
||||||
|
.IR plugin .
|
||||||
|
.TP
|
||||||
|
.BI "unload_plugin " plugin
|
||||||
|
Unload the named
|
||||||
|
.IR plugin .
|
||||||
|
.TP
|
||||||
|
.B help
|
||||||
|
Each loaded plugin is queried for what commands it supports and the
|
||||||
|
synopsis for each is output.
|
||||||
|
.PP
|
||||||
|
Any other value of
|
||||||
|
.I command
|
||||||
|
(and
|
||||||
|
.I args
|
||||||
|
if any)
|
||||||
|
are sent to
|
||||||
|
.B l2tpns
|
||||||
|
as-is, to be passed to each plugin in turn (and possibly acted upon).
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR l2tpns (8)
|
||||||
|
.SH AUTHOR
|
||||||
|
This manual page was written by Jonathan McDowell <noodles@the.earth.li>,
|
||||||
|
for the Debian GNU/Linux system (but may be used by others).
|
||||||
14
Makefile
14
Makefile
|
|
@ -2,7 +2,8 @@ DESTDIR =
|
||||||
bindir = /usr/sbin
|
bindir = /usr/sbin
|
||||||
etcdir = /etc/l2tpns
|
etcdir = /etc/l2tpns
|
||||||
libdir = /usr/lib/l2tpns
|
libdir = /usr/lib/l2tpns
|
||||||
mandir = /usr/share/man/man8
|
man5dir = /usr/share/man/man5
|
||||||
|
man8dir = /usr/share/man/man8
|
||||||
statedir = /var/lib/l2tpns
|
statedir = /var/lib/l2tpns
|
||||||
|
|
||||||
DEFINES =
|
DEFINES =
|
||||||
|
|
@ -84,9 +85,14 @@ bounce: test/bounce.o
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
$(INSTALL) -m 0755 l2tpns $(DESTDIR)$(bindir)/l2tpns
|
$(INSTALL) -m 0755 l2tpns $(DESTDIR)$(bindir)/l2tpns
|
||||||
$(INSTALL) -m 0644 l2tpns.8 $(DESTDIR)$(mandir)/l2tpns.8
|
|
||||||
$(INSTALL) -m 0755 nsctl $(DESTDIR)$(bindir)/nsctl
|
$(INSTALL) -m 0755 nsctl $(DESTDIR)$(bindir)/nsctl
|
||||||
$(INSTALL) -m 0644 nsctl.8 $(DESTDIR)$(mandir)/nsctl.8
|
|
||||||
|
$(INSTALL) -m 0644 Docs/startup-config.5 $(DESTDIR)$(man5dir)/startup-config.5
|
||||||
|
$(INSTALL) -m 0644 Docs/l2tpns.8 $(DESTDIR)$(man8dir)/l2tpns.8
|
||||||
|
$(INSTALL) -m 0644 Docs/nsctl.8 $(DESTDIR)$(man8dir)/nsctl.8
|
||||||
|
|
||||||
|
gzip $(DESTDIR)$(man5dir)/*.5 $(DESTDIR)$(man8dir)/*.8
|
||||||
|
|
||||||
@if [ -f $(DESTDIR)$(etcdir)/startup-config ]; then \
|
@if [ -f $(DESTDIR)$(etcdir)/startup-config ]; then \
|
||||||
echo '***' Installing default config files in $(DESTDIR)$(etcdir) as .defaults; \
|
echo '***' Installing default config files in $(DESTDIR)$(etcdir) as .defaults; \
|
||||||
suffix=.default; \
|
suffix=.default; \
|
||||||
|
|
@ -115,7 +121,7 @@ bgp.o: bgp.c l2tpns.h bgp.h util.h
|
||||||
cli.o: cli.c l2tpns.h util.h cluster.h tbf.h ll.h bgp.h
|
cli.o: cli.c l2tpns.h util.h cluster.h tbf.h ll.h bgp.h
|
||||||
cluster.o: cluster.c l2tpns.h cluster.h util.h tbf.h bgp.h
|
cluster.o: cluster.c l2tpns.h cluster.h util.h tbf.h bgp.h
|
||||||
constants.o: constants.c constants.h
|
constants.o: constants.c constants.h
|
||||||
control.o: control.c control.h
|
control.o: control.c l2tpns.h control.h
|
||||||
icmp.o: icmp.c l2tpns.h
|
icmp.o: icmp.c l2tpns.h
|
||||||
l2tpns.o: l2tpns.c md5.h l2tpns.h cluster.h plugin.h ll.h constants.h \
|
l2tpns.o: l2tpns.c md5.h l2tpns.h cluster.h plugin.h ll.h constants.h \
|
||||||
control.h util.h tbf.h bgp.h
|
control.h util.h tbf.h bgp.h
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@
|
||||||
|
|
||||||
/* set up intercept based on RADIUS reply */
|
/* set up intercept based on RADIUS reply */
|
||||||
|
|
||||||
char const *cvs_id = "$Id: autosnoop.c,v 1.7 2004-11-09 08:05:02 bodea Exp $";
|
char const *cvs_id = "$Id: autosnoop.c,v 1.8 2004-11-17 08:23:34 bodea Exp $";
|
||||||
|
|
||||||
int __plugin_api_version = PLUGIN_API_VERSION;
|
int plugin_api_version = PLUGIN_API_VERSION;
|
||||||
struct pluginfuncs *p;
|
struct pluginfuncs *p;
|
||||||
|
|
||||||
int plugin_radius_response(struct param_radius_response *data)
|
int plugin_radius_response(struct param_radius_response *data)
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@
|
||||||
|
|
||||||
/* set up throttling based on RADIUS reply */
|
/* set up throttling based on RADIUS reply */
|
||||||
|
|
||||||
char const *cvs_id = "$Id: autothrottle.c,v 1.8 2004-11-09 08:05:02 bodea Exp $";
|
char const *cvs_id = "$Id: autothrottle.c,v 1.9 2004-11-17 08:23:34 bodea Exp $";
|
||||||
|
|
||||||
int __plugin_api_version = PLUGIN_API_VERSION;
|
int plugin_api_version = PLUGIN_API_VERSION;
|
||||||
struct pluginfuncs *p;
|
struct pluginfuncs *p;
|
||||||
|
|
||||||
#define THROTTLE_KEY "lcp:interface-config"
|
#define THROTTLE_KEY "lcp:interface-config"
|
||||||
|
|
|
||||||
195
control.c
195
control.c
|
|
@ -1,74 +1,163 @@
|
||||||
// L2TPNS: control
|
// L2TPNS: control
|
||||||
|
|
||||||
char const *cvs_id_control = "$Id: control.c,v 1.2 2004-06-28 02:43:13 fred_nerk Exp $";
|
char const *cvs_id_control = "$Id: control.c,v 1.3 2004-11-17 08:23:34 bodea Exp $";
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <malloc.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/time.h>
|
#include "l2tpns.h"
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
|
|
||||||
int new_packet(short type, char *packet)
|
int pack_control(char *data, int len, u8 type, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int id = (time(NULL) ^ (rand() * 1024*1024));
|
struct nsctl_packet pkt;
|
||||||
|
struct nsctl_args arg;
|
||||||
|
char *p = pkt.argv;
|
||||||
|
int sz = (p - (char *) &pkt);
|
||||||
|
|
||||||
*(short *)(packet + 0) = ntohs(0x9012);
|
if (len > sizeof(pkt))
|
||||||
*(short *)(packet + 2) = ntohs(type);
|
len = sizeof(pkt);
|
||||||
*(int *)(packet + 6) = ntohl(id);
|
|
||||||
|
|
||||||
return 10;
|
if (argc > 0xff)
|
||||||
|
argc = 0xff; // paranoia
|
||||||
|
|
||||||
|
pkt.magic = ntohs(NSCTL_MAGIC);
|
||||||
|
pkt.type = type;
|
||||||
|
pkt.argc = argc;
|
||||||
|
|
||||||
|
while (argc-- > 0)
|
||||||
|
{
|
||||||
|
char *a = *argv++;
|
||||||
|
int s = strlen(a);
|
||||||
|
|
||||||
|
if (s > sizeof(arg.value))
|
||||||
|
s = sizeof(arg.value); // silently truncate
|
||||||
|
|
||||||
|
arg.len = s;
|
||||||
|
s += sizeof(arg.len);
|
||||||
|
|
||||||
|
if (sz + s > len)
|
||||||
|
return -1; // overflow
|
||||||
|
|
||||||
|
if (arg.len)
|
||||||
|
memcpy(arg.value, a, arg.len);
|
||||||
|
|
||||||
|
memcpy(p, &arg, s);
|
||||||
|
sz += s;
|
||||||
|
p += s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* terminate: this is both a sanity check and additionally
|
||||||
|
* ensures that there's a spare byte in the packet to null
|
||||||
|
* terminate the last argument when unpacking (see unpack_control)
|
||||||
|
*/
|
||||||
|
if (sz + sizeof(arg.len) > len)
|
||||||
|
return -1; // overflow
|
||||||
|
|
||||||
|
arg.len = 0xff;
|
||||||
|
memcpy(p, &arg.len, sizeof(arg.len));
|
||||||
|
|
||||||
|
sz += sizeof(arg.len);
|
||||||
|
memcpy(data, &pkt, sz);
|
||||||
|
|
||||||
|
return sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
int send_packet(int sockfd, int dest_ip, int dest_port, char *packet, int len)
|
int unpack_control(struct nsctl *control, char *data, int len)
|
||||||
{
|
{
|
||||||
struct sockaddr_in addr;
|
struct nsctl_packet pkt;
|
||||||
|
char *p = pkt.argv;
|
||||||
|
int sz = (p - (char *) &pkt);
|
||||||
|
int i;
|
||||||
|
|
||||||
*(short *)(packet + 4) = ntohs(len);
|
if (len < sz)
|
||||||
|
return NSCTL_ERR_SHORT;
|
||||||
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
if (len > sizeof(pkt))
|
||||||
addr.sin_family = AF_INET;
|
return NSCTL_ERR_LONG;
|
||||||
*(int*)&addr.sin_addr = htonl(dest_ip);
|
|
||||||
addr.sin_port = htons(dest_port);
|
memcpy(&pkt, data, len);
|
||||||
if (sendto(sockfd, packet, len, 0, (void *) &addr, sizeof(addr)) < 0)
|
if (ntohs(pkt.magic) != NSCTL_MAGIC)
|
||||||
|
return NSCTL_ERR_MAGIC;
|
||||||
|
|
||||||
|
switch (pkt.type)
|
||||||
|
{
|
||||||
|
case NSCTL_REQ_LOAD:
|
||||||
|
case NSCTL_REQ_UNLOAD:
|
||||||
|
case NSCTL_REQ_HELP:
|
||||||
|
case NSCTL_REQ_CONTROL:
|
||||||
|
case NSCTL_RES_OK:
|
||||||
|
case NSCTL_RES_ERR:
|
||||||
|
control->type = pkt.type;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return NSCTL_ERR_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
control->argc = pkt.argc;
|
||||||
|
for (i = 0; i <= control->argc; i++)
|
||||||
|
{
|
||||||
|
unsigned s;
|
||||||
|
|
||||||
|
if (len < sz + 1)
|
||||||
|
return NSCTL_ERR_SHORT;
|
||||||
|
|
||||||
|
s = (u8) *p;
|
||||||
|
*p++ = 0; // null terminate previous arg
|
||||||
|
sz++;
|
||||||
|
|
||||||
|
if (i < control->argc)
|
||||||
{
|
{
|
||||||
perror("sendto");
|
if (len < sz + s)
|
||||||
return 0;
|
return NSCTL_ERR_SHORT;
|
||||||
|
|
||||||
|
control->argv[i] = p;
|
||||||
|
p += s;
|
||||||
|
sz += s;
|
||||||
}
|
}
|
||||||
return 1;
|
else
|
||||||
}
|
|
||||||
|
|
||||||
int read_packet(int sockfd, char *packet)
|
|
||||||
{
|
|
||||||
struct sockaddr_in addr;
|
|
||||||
int alen = sizeof(addr);
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
|
||||||
return recvfrom(sockfd, packet, 1400, 0, (void *) &addr, &alen);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dump_packet(char *packet, FILE *stream)
|
|
||||||
{
|
|
||||||
if (htons(*(short *)(packet + 0)) != 0x9012)
|
|
||||||
{
|
{
|
||||||
fprintf(stream, "Invalid packet identifier %x\n", htons(*(short *)(packet + 0)));
|
/* check for terminator */
|
||||||
return;
|
if (s != 0xff)
|
||||||
|
return NSCTL_ERR_SHORT;
|
||||||
}
|
}
|
||||||
fprintf(stream, "Control packet:\n");
|
}
|
||||||
fprintf(stream, " Type: %d\n", htons(*(short *)(packet + 2)));
|
|
||||||
fprintf(stream, " Length: %d\n", htons(*(short *)(packet + 4)));
|
if (sz != len)
|
||||||
fprintf(stream, " Identifier: %x\n", htonl(*(int *)(packet + 6)));
|
return NSCTL_ERR_LONG; // trailing cr*p
|
||||||
fprintf(stream, "\n");
|
|
||||||
|
return control->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dump_control(struct nsctl *control, FILE *stream)
|
||||||
|
{
|
||||||
|
char *type = "*unknown*";
|
||||||
|
|
||||||
|
if (!stream)
|
||||||
|
stream = stdout;
|
||||||
|
|
||||||
|
switch (control->type)
|
||||||
|
{
|
||||||
|
case NSCTL_REQ_LOAD: type = "NSCTL_REQ_LOAD"; break;
|
||||||
|
case NSCTL_REQ_UNLOAD: type = "NSCTL_REQ_UNLOAD"; break;
|
||||||
|
case NSCTL_REQ_HELP: type = "NSCTL_REQ_HELP"; break;
|
||||||
|
case NSCTL_REQ_CONTROL: type = "NSCTL_REQ_CONTROL"; break;
|
||||||
|
case NSCTL_RES_OK: type = "NSCTL_RES_OK"; break;
|
||||||
|
case NSCTL_RES_ERR: type = "NSCTL_RES_ERR"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stream, "Control packet:\n");
|
||||||
|
fprintf(stream, " Type: %d (%s)\n", (int) control->type, type);
|
||||||
|
fprintf(stream, " Args: %d", (int) control->argc);
|
||||||
|
if (control->argc)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
fprintf(stream, " (\"");
|
||||||
|
for (i = 0; i < control->argc; i++)
|
||||||
|
fprintf(stream, "%s%s", i ? "\", \"" : "", control->argv[i]);
|
||||||
|
|
||||||
|
fprintf(stream, "\")");
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stream, "\n\n");
|
||||||
|
}
|
||||||
|
|
|
||||||
56
control.h
56
control.h
|
|
@ -1,18 +1,54 @@
|
||||||
#ifndef __CONTROL_H__
|
#ifndef __CONTROL_H__
|
||||||
#define __CONTROL_H__
|
#define __CONTROL_H__
|
||||||
|
|
||||||
#define PKT_RESP_OK 1
|
#define NSCTL_PORT 1702
|
||||||
#define PKT_RESP_ERROR 2
|
#define NSCTL_MAGIC 0x9013
|
||||||
|
|
||||||
#define PKT_LOAD_PLUGIN 5
|
/* builtin commands */
|
||||||
#define PKT_UNLOAD_PLUGIN 6
|
#define NSCTL_REQUEST (1 << 4)
|
||||||
|
#define NSCTL_REQ_LOAD (NSCTL_REQUEST | 1)
|
||||||
|
#define NSCTL_REQ_UNLOAD (NSCTL_REQUEST | 2)
|
||||||
|
#define NSCTL_REQ_HELP (NSCTL_REQUEST | 3)
|
||||||
|
|
||||||
#define PKT_GARDEN 1000
|
/* general control message, passed to plugins */
|
||||||
#define PKT_UNGARDEN 1001
|
#define NSCTL_REQ_CONTROL (NSCTL_REQUEST | 4)
|
||||||
|
|
||||||
int new_packet(short type, char *packet);
|
/* response messages */
|
||||||
int send_packet(int sockfd, int dest_ip, int dest_port, char *packet, int len);
|
#define NSCTL_RESPONSE (1 << 5)
|
||||||
void dump_packet(char *packet, FILE *stream);
|
#define NSCTL_RES_OK (NSCTL_RESPONSE | 1)
|
||||||
int read_packet(int sockfd, char *packet);
|
#define NSCTL_RES_ERR (NSCTL_RESPONSE | 2)
|
||||||
|
|
||||||
|
/* unpack errors */
|
||||||
|
#define NSCTL_ERR_SHORT -1 // short packet
|
||||||
|
#define NSCTL_ERR_LONG -2 // packet exceeds max, or trailing cr*p
|
||||||
|
#define NSCTL_ERR_MAGIC -3 // invalid magic number
|
||||||
|
#define NSCTL_ERR_TYPE -4 // unrecognised type
|
||||||
|
|
||||||
|
#define NSCTL_MAX_PKT_SZ 4096
|
||||||
|
|
||||||
|
struct nsctl_packet {
|
||||||
|
u16 magic;
|
||||||
|
u8 type;
|
||||||
|
u8 argc;
|
||||||
|
char argv[NSCTL_MAX_PKT_SZ - 4];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
#define NSCTL_MAX_ARG_SZ 512
|
||||||
|
|
||||||
|
struct nsctl_args {
|
||||||
|
u8 len;
|
||||||
|
char value[NSCTL_MAX_ARG_SZ - 1];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
/* parsed packet */
|
||||||
|
struct nsctl {
|
||||||
|
u8 type;
|
||||||
|
u8 argc;
|
||||||
|
char *argv[0xff];
|
||||||
|
};
|
||||||
|
|
||||||
|
int pack_control(char *data, int len, u8 type, int argc, char *argv[]);
|
||||||
|
int unpack_control(struct nsctl *packet, char *data, int len);
|
||||||
|
void dump_control(struct nsctl *control, FILE *stream);
|
||||||
|
|
||||||
#endif /* __CONTROL_H__ */
|
#endif /* __CONTROL_H__ */
|
||||||
|
|
|
||||||
79
garden.c
79
garden.c
|
|
@ -9,9 +9,9 @@
|
||||||
|
|
||||||
/* walled garden */
|
/* walled garden */
|
||||||
|
|
||||||
char const *cvs_id = "$Id: garden.c,v 1.12 2004-11-09 08:05:02 bodea Exp $";
|
char const *cvs_id = "$Id: garden.c,v 1.13 2004-11-17 08:23:34 bodea Exp $";
|
||||||
|
|
||||||
int __plugin_api_version = PLUGIN_API_VERSION;
|
int plugin_api_version = PLUGIN_API_VERSION;
|
||||||
static struct pluginfuncs *p = 0;
|
static struct pluginfuncs *p = 0;
|
||||||
|
|
||||||
static int iam_master = 0; // We're all slaves! Slaves I tell you!
|
static int iam_master = 0; // We're all slaves! Slaves I tell you!
|
||||||
|
|
@ -75,46 +75,62 @@ int plugin_kill_session(struct param_new_session *data)
|
||||||
return PLUGIN_RET_OK;
|
return PLUGIN_RET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *plugin_control_help[] = {
|
||||||
|
" garden USER|SID Put user into the walled garden",
|
||||||
|
" ungarden USER|SID Release user",
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
int plugin_control(struct param_control *data)
|
int plugin_control(struct param_control *data)
|
||||||
{
|
{
|
||||||
sessiont *s;
|
|
||||||
sessionidt session;
|
sessionidt session;
|
||||||
|
sessiont *s = 0;
|
||||||
|
int flag;
|
||||||
|
char *end;
|
||||||
|
|
||||||
|
if (data->argc < 1 || (strcmp(data->argv[0], "garden") && strcmp(data->argv[0], "ungarden")))
|
||||||
|
return PLUGIN_RET_OK; // not for us
|
||||||
|
|
||||||
|
flag = data->argv[0][0] == 'g';
|
||||||
|
|
||||||
if (!iam_master) // All garden processing happens on the master.
|
if (!iam_master) // All garden processing happens on the master.
|
||||||
return PLUGIN_RET_OK;
|
|
||||||
|
|
||||||
if (data->type != PKT_GARDEN && data->type != PKT_UNGARDEN)
|
|
||||||
return PLUGIN_RET_OK;
|
|
||||||
|
|
||||||
if (!data->data && data->data_length)
|
|
||||||
return PLUGIN_RET_OK;
|
|
||||||
|
|
||||||
session = atoi((char*)(data->data));
|
|
||||||
if (!session)
|
|
||||||
return PLUGIN_RET_OK;
|
|
||||||
|
|
||||||
data->send_response = 1;
|
|
||||||
s = p->get_session_by_id(session);
|
|
||||||
if (!s || !s->ip)
|
|
||||||
{
|
{
|
||||||
char *errormsg = "Session not connected";
|
data->response = NSCTL_RES_ERR;
|
||||||
*(short *)(data->response + 2) = ntohs(PKT_RESP_ERROR);
|
data->additional = "must be run on the cluster master";
|
||||||
sprintf((data->response + data->response_length), "%s", errormsg);
|
|
||||||
data->response_length += strlen(errormsg) + 1;
|
|
||||||
|
|
||||||
p->log(3, 0, 0, 0, "Unknown session %d\n", session);
|
|
||||||
return PLUGIN_RET_STOP;
|
return PLUGIN_RET_STOP;
|
||||||
}
|
}
|
||||||
*(short *)(data->response + 2) = ntohs(PKT_RESP_OK);
|
|
||||||
|
|
||||||
if (!(garden_session(s, (data->type == PKT_GARDEN))))
|
if (data->argc != 2)
|
||||||
{
|
{
|
||||||
char *errormsg = "User not connected";
|
data->response = NSCTL_RES_ERR;
|
||||||
*(short *)(data->response + 2) = ntohs(PKT_RESP_ERROR);
|
data->additional = "one argument required: username or session id";
|
||||||
sprintf((data->response + data->response_length), "%s", errormsg);
|
return PLUGIN_RET_STOP;
|
||||||
data->response_length += strlen(errormsg) + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(session = strtol(data->argv[0], &end, 10)) || *end)
|
||||||
|
session = p->get_session_by_username(data->argv[0]);
|
||||||
|
|
||||||
|
if (session)
|
||||||
|
s = p->get_session_by_id(session);
|
||||||
|
|
||||||
|
if (!s || !s->ip)
|
||||||
|
{
|
||||||
|
data->response = NSCTL_RES_ERR;
|
||||||
|
data->additional = "session not found";
|
||||||
|
return PLUGIN_RET_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->walled_garden == flag)
|
||||||
|
{
|
||||||
|
data->response = NSCTL_RES_ERR;
|
||||||
|
data->additional = flag ? "already in walled garden" : "not in walled garden";
|
||||||
|
return PLUGIN_RET_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
garden_session(s, flag);
|
||||||
|
data->response = NSCTL_RES_OK;
|
||||||
|
data->additional = 0;
|
||||||
|
|
||||||
return PLUGIN_RET_STOP;
|
return PLUGIN_RET_STOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,7 +152,10 @@ int plugin_become_master(void)
|
||||||
int plugin_new_session_master(sessiont * s)
|
int plugin_new_session_master(sessiont * s)
|
||||||
{
|
{
|
||||||
if (s->walled_garden)
|
if (s->walled_garden)
|
||||||
|
{
|
||||||
|
s->walled_garden = 0;
|
||||||
garden_session(s, 1);
|
garden_session(s, 1);
|
||||||
|
}
|
||||||
|
|
||||||
return PLUGIN_RET_OK;
|
return PLUGIN_RET_OK;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
68
l2tpns.8
68
l2tpns.8
|
|
@ -1,68 +0,0 @@
|
||||||
.\" Hey, EMACS: -*- nroff -*-
|
|
||||||
.\" First parameter, NAME, should be all caps
|
|
||||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
|
||||||
.\" other parameters are allowed: see man(7), man(1)
|
|
||||||
.TH L2TPNS 8 "November 16, 2004"
|
|
||||||
.\" Please adjust this date whenever revising the manpage.
|
|
||||||
.\"
|
|
||||||
.\" Some roff macros, for reference:
|
|
||||||
.\" .nh disable hyphenation
|
|
||||||
.\" .hy enable hyphenation
|
|
||||||
.\" .ad l left justify
|
|
||||||
.\" .ad b justify to both left and right margins
|
|
||||||
.\" .nf disable filling
|
|
||||||
.\" .fi enable filling
|
|
||||||
.\" .br insert line break
|
|
||||||
.\" .sp <n> insert n+1 empty lines
|
|
||||||
.\" for manpage-specific macros, see man(7)
|
|
||||||
.SH NAME
|
|
||||||
l2tpns \- L2TP LNS daemon
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B l2tpns
|
|
||||||
[ \fB-d\fR ] [ \fB-c\fR \fI<file>\fR ] [ \fB-h\fR \fI<hostname>\fR ] [ \fB-a\fR \fI<address>\fR ] [ \fB-v\fR ]
|
|
||||||
.br
|
|
||||||
.SH DESCRIPTION
|
|
||||||
This manual page documents briefly the
|
|
||||||
.B l2tpns
|
|
||||||
command.
|
|
||||||
.PP
|
|
||||||
.\" TeX users may be more comfortable with the \fB<whatever>\fP and
|
|
||||||
.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
|
|
||||||
.\" respectively.
|
|
||||||
\fBl2tpns\fP is an L2TP LNS daemon that doesn't require kernel support
|
|
||||||
for PPP or L2TP, nor any kernel patches. For more information on L2TP see
|
|
||||||
RFC 2661.
|
|
||||||
.PP
|
|
||||||
Once running l2tpns can be controlled by telnetting to port 23 on the
|
|
||||||
machine running the daemon.
|
|
||||||
.SH OPTIONS
|
|
||||||
.TP
|
|
||||||
.B \-d
|
|
||||||
Detach from terminal and fork into the background. By default l2tpns
|
|
||||||
will stay in the foreground.
|
|
||||||
.TP
|
|
||||||
.B \-c <file>
|
|
||||||
Specify config file.
|
|
||||||
.TP
|
|
||||||
.B \-h <hostname>
|
|
||||||
Force hostname to <hostname>.
|
|
||||||
.TP
|
|
||||||
.B \-v
|
|
||||||
Increase verbosity for debugging. Can be used multiple times.
|
|
||||||
.br
|
|
||||||
.SH FILES
|
|
||||||
.TP
|
|
||||||
\fB\fI/etc/l2tpns/startup-config\fR
|
|
||||||
The default configuration file.
|
|
||||||
.TP
|
|
||||||
\fB\fI/etc/l2tpns/ip_pool\fR
|
|
||||||
IP address pool configuration.
|
|
||||||
.TP
|
|
||||||
\fB\fI/etc/l2tpns/users\fR
|
|
||||||
Username/password configuration for access to admin interface.
|
|
||||||
.SH SEE ALSO
|
|
||||||
\fInsctl\fR(8)
|
|
||||||
.SH AUTHOR
|
|
||||||
This manual page was written by Jonathan McDowell <noodles@earth.li>,
|
|
||||||
for the Debian GNU/Linux system (but may be used by others).
|
|
||||||
|
|
||||||
256
l2tpns.c
256
l2tpns.c
|
|
@ -4,7 +4,7 @@
|
||||||
// Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced
|
// Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced
|
||||||
// vim: sw=8 ts=8
|
// vim: sw=8 ts=8
|
||||||
|
|
||||||
char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.50 2004-11-16 21:54:46 fred_nerk Exp $";
|
char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.51 2004-11-17 08:23:34 bodea Exp $";
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
@ -167,10 +167,10 @@ static void build_chap_response(char *challenge, u8 id, u16 challenge_length, ch
|
||||||
static void update_config(void);
|
static void update_config(void);
|
||||||
static void read_config_file(void);
|
static void read_config_file(void);
|
||||||
static void initplugins(void);
|
static void initplugins(void);
|
||||||
static void add_plugin(char *plugin_name);
|
static int add_plugin(char *plugin_name);
|
||||||
static void remove_plugin(char *plugin_name);
|
static int remove_plugin(char *plugin_name);
|
||||||
static void plugins_done(void);
|
static void plugins_done(void);
|
||||||
static void processcontrol(u8 * buf, int len, struct sockaddr_in *addr);
|
static void processcontrol(u8 * buf, int len, struct sockaddr_in *addr, int alen);
|
||||||
static tunnelidt new_tunnel(void);
|
static tunnelidt new_tunnel(void);
|
||||||
static int unhide_avp(u8 *avp, tunnelidt t, sessionidt s, u16 length);
|
static int unhide_avp(u8 *avp, tunnelidt t, sessionidt s, u16 length);
|
||||||
|
|
||||||
|
|
@ -434,8 +434,8 @@ static void initudp(void)
|
||||||
// Control
|
// Control
|
||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_port = htons(1702);
|
addr.sin_port = htons(NSCTL_PORT);
|
||||||
controlfd = socket(AF_INET, SOCK_DGRAM, 17);
|
controlfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
setsockopt(controlfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
setsockopt(controlfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
||||||
if (bind(controlfd, (void *) &addr, sizeof(addr)) < 0)
|
if (bind(controlfd, (void *) &addr, sizeof(addr)) < 0)
|
||||||
{
|
{
|
||||||
|
|
@ -2324,7 +2324,7 @@ static void mainloop(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FD_ISSET(controlfd, &r))
|
if (FD_ISSET(controlfd, &r))
|
||||||
processcontrol(buf, recvfrom(controlfd, buf, sizeof(buf), MSG_WAITALL, (void *) &addr, &alen), &addr);
|
processcontrol(buf, recvfrom(controlfd, buf, sizeof(buf), MSG_WAITALL, (void *) &addr, &alen), &addr, alen);
|
||||||
|
|
||||||
if (FD_ISSET(clifd, &r))
|
if (FD_ISSET(clifd, &r))
|
||||||
{
|
{
|
||||||
|
|
@ -2934,31 +2934,31 @@ int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
switch (i)
|
switch (i)
|
||||||
{
|
{
|
||||||
case 'd':
|
case 'd':
|
||||||
if (fork()) exit(0);
|
if (fork()) exit(0);
|
||||||
setsid();
|
setsid();
|
||||||
freopen("/dev/null", "r", stdin);
|
freopen("/dev/null", "r", stdin);
|
||||||
freopen("/dev/null", "w", stdout);
|
freopen("/dev/null", "w", stdout);
|
||||||
freopen("/dev/null", "w", stderr);
|
freopen("/dev/null", "w", stderr);
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
optdebug++;
|
optdebug++;
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
optconfig = optarg;
|
optconfig = optarg;
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
snprintf(hostname, sizeof(hostname), "%s", optarg);
|
snprintf(hostname, sizeof(hostname), "%s", optarg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Args are:\n"
|
printf("Args are:\n"
|
||||||
"\t-d\t\tDetach from terminal\n"
|
"\t-d\t\tDetach from terminal\n"
|
||||||
"\t-c <file>\tConfig file\n"
|
"\t-c <file>\tConfig file\n"
|
||||||
"\t-h <hostname>\tForce hostname\n"
|
"\t-h <hostname>\tForce hostname\n"
|
||||||
"\t-v\t\tDebug\n");
|
"\t-v\t\tDebug\n");
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3751,7 +3751,7 @@ static void *getconfig(char *key, enum config_typet type)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_plugin(char *plugin_name)
|
static int add_plugin(char *plugin_name)
|
||||||
{
|
{
|
||||||
static struct pluginfuncs funcs = {
|
static struct pluginfuncs funcs = {
|
||||||
_log,
|
_log,
|
||||||
|
|
@ -3773,22 +3773,22 @@ static void add_plugin(char *plugin_name)
|
||||||
if (!p)
|
if (!p)
|
||||||
{
|
{
|
||||||
LOG(1, 0, 0, 0, " Plugin load failed: %s\n", dlerror());
|
LOG(1, 0, 0, 0, " Plugin load failed: %s\n", dlerror());
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ll_contains(loaded_plugins, p))
|
if (ll_contains(loaded_plugins, p))
|
||||||
{
|
{
|
||||||
dlclose(p);
|
dlclose(p);
|
||||||
return;
|
return 0; // already loaded
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
int *v = dlsym(p, "__plugin_api_version");
|
int *v = dlsym(p, "plugin_api_version");
|
||||||
if (!v || *v != PLUGIN_API_VERSION)
|
if (!v || *v != PLUGIN_API_VERSION)
|
||||||
{
|
{
|
||||||
LOG(1, 0, 0, 0, " Plugin load failed: API version mismatch: %s\n", dlerror());
|
LOG(1, 0, 0, 0, " Plugin load failed: API version mismatch: %s\n", dlerror());
|
||||||
dlclose(p);
|
dlclose(p);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3798,7 +3798,7 @@ static void add_plugin(char *plugin_name)
|
||||||
{
|
{
|
||||||
LOG(1, 0, 0, 0, " Plugin load failed: plugin_init() returned FALSE: %s\n", dlerror());
|
LOG(1, 0, 0, 0, " Plugin load failed: plugin_init() returned FALSE: %s\n", dlerror());
|
||||||
dlclose(p);
|
dlclose(p);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3815,6 +3815,7 @@ static void add_plugin(char *plugin_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(2, 0, 0, 0, " Loaded plugin %s\n", plugin_name);
|
LOG(2, 0, 0, 0, " Loaded plugin %s\n", plugin_name);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void run_plugin_done(void *plugin)
|
static void run_plugin_done(void *plugin)
|
||||||
|
|
@ -3825,29 +3826,32 @@ static void run_plugin_done(void *plugin)
|
||||||
donefunc();
|
donefunc();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void remove_plugin(char *plugin_name)
|
static int remove_plugin(char *plugin_name)
|
||||||
{
|
{
|
||||||
void *p = open_plugin(plugin_name, 0);
|
void *p = open_plugin(plugin_name, 0);
|
||||||
int i;
|
int loaded = 0;
|
||||||
|
|
||||||
if (!p)
|
if (!p)
|
||||||
return;
|
return -1;
|
||||||
|
|
||||||
for (i = 0; i < max_plugin_functions; i++)
|
|
||||||
{
|
|
||||||
void *x;
|
|
||||||
if (plugin_functions[i] && (x = dlsym(p, plugin_functions[i])))
|
|
||||||
ll_delete(plugins[i], x);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ll_contains(loaded_plugins, p))
|
if (ll_contains(loaded_plugins, p))
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < max_plugin_functions; i++)
|
||||||
|
{
|
||||||
|
void *x;
|
||||||
|
if (plugin_functions[i] && (x = dlsym(p, plugin_functions[i])))
|
||||||
|
ll_delete(plugins[i], x);
|
||||||
|
}
|
||||||
|
|
||||||
ll_delete(loaded_plugins, p);
|
ll_delete(loaded_plugins, p);
|
||||||
run_plugin_done(p);
|
run_plugin_done(p);
|
||||||
|
loaded = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
dlclose(p);
|
dlclose(p);
|
||||||
LOG(2, 0, 0, 0, "Removed plugin %s\n", plugin_name);
|
LOG(2, 0, 0, 0, "Removed plugin %s\n", plugin_name);
|
||||||
|
return loaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
int run_plugins(int plugin_type, void *data)
|
int run_plugins(int plugin_type, void *data)
|
||||||
|
|
@ -3875,39 +3879,149 @@ static void plugins_done()
|
||||||
run_plugin_done(p);
|
run_plugin_done(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void processcontrol(u8 * buf, int len, struct sockaddr_in *addr)
|
static void processcontrol(u8 * buf, int len, struct sockaddr_in *addr, int alen)
|
||||||
{
|
{
|
||||||
char *resp;
|
struct nsctl request;
|
||||||
int l;
|
struct nsctl response;
|
||||||
struct param_control param = { buf, len, ntohl(addr->sin_addr.s_addr), ntohs(addr->sin_port), NULL, 0, 0 };
|
int type = unpack_control(&request, buf, len);
|
||||||
|
int r;
|
||||||
|
void *p;
|
||||||
|
|
||||||
if (log_stream && config->debug >= 4)
|
if (log_stream && config->debug >= 4)
|
||||||
{
|
{
|
||||||
LOG(4, ntohl(addr->sin_addr.s_addr), 0, 0, "Received ");
|
if (type < 0)
|
||||||
dump_packet(buf, log_stream);
|
{
|
||||||
|
LOG(4, ntohl(addr->sin_addr.s_addr), 0, 0, "Bogus control message (%d)\n", type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG(4, ntohl(addr->sin_addr.s_addr), 0, 0, "Received ");
|
||||||
|
dump_control(&request, log_stream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resp = calloc(1400, 1);
|
switch (type)
|
||||||
l = new_packet(PKT_RESP_ERROR, resp);
|
|
||||||
*(int *)(resp + 6) = *(int *)(buf + 6);
|
|
||||||
|
|
||||||
param.type = ntohs(*(short *)(buf + 2));
|
|
||||||
param.id = ntohl(*(int *)(buf + 6));
|
|
||||||
param.data_length = ntohs(*(short *)(buf + 4)) - 10;
|
|
||||||
param.data = (param.data_length > 0) ? (char *)(buf + 10) : NULL;
|
|
||||||
param.response = resp;
|
|
||||||
param.response_length = l;
|
|
||||||
|
|
||||||
run_plugins(PLUGIN_CONTROL, ¶m);
|
|
||||||
|
|
||||||
if (param.send_response)
|
|
||||||
{
|
{
|
||||||
send_packet(controlfd, ntohl(addr->sin_addr.s_addr), ntohs(addr->sin_port), param.response, param.response_length);
|
case NSCTL_REQ_LOAD:
|
||||||
LOG(4, ntohl(addr->sin_addr.s_addr), 0, 0, "Sent Control packet response\n");
|
if (request.argc != 1)
|
||||||
|
{
|
||||||
|
response.type = NSCTL_RES_ERR;
|
||||||
|
response.argc = 1;
|
||||||
|
response.argv[0] = "name of plugin required";
|
||||||
|
}
|
||||||
|
else if ((r = add_plugin(request.argv[0])) < 1)
|
||||||
|
{
|
||||||
|
response.type = NSCTL_RES_ERR;
|
||||||
|
response.argc = 1;
|
||||||
|
response.argv[0] = !r
|
||||||
|
? "plugin already loaded"
|
||||||
|
: "error loading plugin";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response.type = NSCTL_RES_OK;
|
||||||
|
response.argc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NSCTL_REQ_UNLOAD:
|
||||||
|
if (request.argc != 1)
|
||||||
|
{
|
||||||
|
response.type = NSCTL_RES_ERR;
|
||||||
|
response.argc = 1;
|
||||||
|
response.argv[0] = "name of plugin required";
|
||||||
|
}
|
||||||
|
else if ((r = remove_plugin(request.argv[0])) < 1)
|
||||||
|
{
|
||||||
|
response.type = NSCTL_RES_ERR;
|
||||||
|
response.argc = 1;
|
||||||
|
response.argv[0] = !r
|
||||||
|
? "plugin not loaded"
|
||||||
|
: "plugin not found";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response.type = NSCTL_RES_OK;
|
||||||
|
response.argc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NSCTL_REQ_HELP:
|
||||||
|
response.type = NSCTL_RES_OK;
|
||||||
|
response.argc = 0;
|
||||||
|
|
||||||
|
ll_reset(loaded_plugins);
|
||||||
|
while ((p = ll_next(loaded_plugins)))
|
||||||
|
{
|
||||||
|
char **help = dlsym(p, "plugin_control_help");
|
||||||
|
while (response.argc < 0xff && help && *help)
|
||||||
|
response.argv[response.argc++] = *help++;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NSCTL_REQ_CONTROL:
|
||||||
|
{
|
||||||
|
struct param_control param = { request.argc, request.argv, 0, NULL };
|
||||||
|
if (!run_plugins(PLUGIN_CONTROL, ¶m))
|
||||||
|
{
|
||||||
|
response.type = NSCTL_RES_ERR;
|
||||||
|
response.argc = 1;
|
||||||
|
response.argv[0] = param.additional
|
||||||
|
? param.additional
|
||||||
|
: "error returned by plugin";
|
||||||
|
}
|
||||||
|
else if (!(param.response & NSCTL_RESPONSE))
|
||||||
|
{
|
||||||
|
response.type = NSCTL_RES_ERR;
|
||||||
|
response.argc = 1;
|
||||||
|
response.argv[0] = param.response
|
||||||
|
? "unrecognised response value from plugin"
|
||||||
|
: "unhandled action";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response.type = param.response;
|
||||||
|
response.argc = 0;
|
||||||
|
if (param.additional)
|
||||||
|
{
|
||||||
|
response.argc = 1;
|
||||||
|
response.argv[0] = param.additional;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
response.type = NSCTL_RES_ERR;
|
||||||
|
response.argc = 1;
|
||||||
|
response.argv[0] = "error unpacking control packet";
|
||||||
}
|
}
|
||||||
|
|
||||||
free(resp);
|
buf = calloc(NSCTL_MAX_PKT_SZ, 1);
|
||||||
|
if (!buf)
|
||||||
|
{
|
||||||
|
LOG(2, ntohl(addr->sin_addr.s_addr), 0, 0, "Failed to allocate nsctl response\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = pack_control(buf, NSCTL_MAX_PKT_SZ, response.type, response.argc, response.argv);
|
||||||
|
if (r > 0)
|
||||||
|
{
|
||||||
|
sendto(controlfd, buf, r, 0, (const struct sockaddr *) addr, alen);
|
||||||
|
if (log_stream && config->debug >= 4)
|
||||||
|
{
|
||||||
|
LOG(4, ntohl(addr->sin_addr.s_addr), 0, 0, "Sent ");
|
||||||
|
dump_control(&response, log_stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LOG(2, ntohl(addr->sin_addr.s_addr), 0, 0, "Failed to pack nsctl response (%d)\n", r);
|
||||||
|
|
||||||
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static tunnelidt new_tunnel()
|
static tunnelidt new_tunnel()
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,8 @@ rm -rf %{buildroot}
|
||||||
%config(noreplace) /etc/l2tpns/ip_pool
|
%config(noreplace) /etc/l2tpns/ip_pool
|
||||||
%attr(700,root,root) /usr/sbin/l2tpns
|
%attr(700,root,root) /usr/sbin/l2tpns
|
||||||
%attr(755,root,root) /usr/lib/l2tpns
|
%attr(755,root,root) /usr/lib/l2tpns
|
||||||
|
%attr(644,root,root) /usr/share/man/man[58]/*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Mon Nov 15 2004 Brendan O'Dea <bod@optusnet.com.au> 2.0.8-1
|
* Wed Nov 17 2004 Brendan O'Dea <bod@optusnet.com.au> 2.0.8-1
|
||||||
- 2.0.8 release, see /usr/share/doc/l2tpns-2.0.8/Changes
|
- 2.0.8 release, see /usr/share/doc/l2tpns-2.0.8/Changes
|
||||||
|
|
|
||||||
41
nsctl.8
41
nsctl.8
|
|
@ -1,41 +0,0 @@
|
||||||
.\" Hey, EMACS: -*- nroff -*-
|
|
||||||
.\" First parameter, NAME, should be all caps
|
|
||||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
|
||||||
.\" other parameters are allowed: see man(7), man(1)
|
|
||||||
.TH NSCTL 8 "November 16, 2004"
|
|
||||||
.\" Please adjust this date whenever revising the manpage.
|
|
||||||
.\"
|
|
||||||
.\" Some roff macros, for reference:
|
|
||||||
.\" .nh disable hyphenation
|
|
||||||
.\" .hy enable hyphenation
|
|
||||||
.\" .ad l left justify
|
|
||||||
.\" .ad b justify to both left and right margins
|
|
||||||
.\" .nf disable filling
|
|
||||||
.\" .fi enable filling
|
|
||||||
.\" .br insert line break
|
|
||||||
.\" .sp <n> insert n+1 empty lines
|
|
||||||
.\" for manpage-specific macros, see man(7)
|
|
||||||
.SH NAME
|
|
||||||
nsctl \- Issue commands to l2tpns plugins
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B nsctl \fI<host>\fP \fI<command>\fP [ \fIargs...\fP ]
|
|
||||||
.SH DESCRIPTION
|
|
||||||
nsctl is part of the l2tpns package. It allows the system administrator
|
|
||||||
to allow messages to be passed to l2tpns plugins.
|
|
||||||
.SH OPTIONS
|
|
||||||
.TP
|
|
||||||
.B <host>
|
|
||||||
The host running l2tpns that should receive the message.
|
|
||||||
.TP
|
|
||||||
.B <command>
|
|
||||||
The command to send. Currently one of \fIload_plugin\fP,
|
|
||||||
\fIunload_plugin\fP, \fIgarden\fP or \fIungarden\fP.
|
|
||||||
\fIgarden\fP/\fIungarden\fP enable or disable the walled garden plugin
|
|
||||||
for a particular user; they take a single argument which is the session
|
|
||||||
id to affect.
|
|
||||||
.SH SEE ALSO
|
|
||||||
.BR l2tpns(8)
|
|
||||||
.SH AUTHOR
|
|
||||||
This manual page was written by Jonathan McDowell <noodles@the.earth.li>,
|
|
||||||
for the Debian GNU/Linux system (but may be used by others).
|
|
||||||
|
|
||||||
325
nsctl.c
325
nsctl.c
|
|
@ -1,138 +1,239 @@
|
||||||
|
/* l2tpns plugin control */
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <malloc.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <time.h>
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include "l2tpns.h"
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
|
|
||||||
struct { char *command; int pkt_type; int params; } commands[] = {
|
struct {
|
||||||
{ "load_plugin", PKT_LOAD_PLUGIN, 1 },
|
char *command;
|
||||||
{ "unload_plugin", PKT_UNLOAD_PLUGIN, 1 },
|
char *usage;
|
||||||
{ "garden", PKT_GARDEN, 1 },
|
int action;
|
||||||
{ "ungarden", PKT_UNGARDEN, 1 },
|
} builtins[] = {
|
||||||
|
{ "load_plugin", " PLUGIN Load named plugin", NSCTL_REQ_LOAD },
|
||||||
|
{ "unload_plugin", " PLUGIN Unload named plugin", NSCTL_REQ_UNLOAD },
|
||||||
|
{ "help", " List available commands", NSCTL_REQ_HELP },
|
||||||
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
char *dest_host = NULL;
|
|
||||||
unsigned int dest_port = 1702;
|
static int debug = 0;
|
||||||
int udpfd;
|
static int timeout = 2; // 2 seconds
|
||||||
|
static char *me;
|
||||||
|
|
||||||
|
#define USAGE() fprintf(stderr, "Usage: %s [-d] [-h HOST[:PORT]] [-t TIMEOUT] COMMAND [ARG ...]\n", me)
|
||||||
|
|
||||||
|
static struct nsctl *request(char *host, int port, int type, int argc, char *argv[]);
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int len = 0;
|
int req_type = 0;
|
||||||
int dest_ip = 0;
|
char *host = 0;
|
||||||
int pkt_type = 0;
|
int port;
|
||||||
char *packet = NULL;
|
int i;
|
||||||
int i;
|
char *p;
|
||||||
|
struct nsctl *res;
|
||||||
|
|
||||||
setbuf(stdout, NULL);
|
if ((p = strrchr((me = argv[0]), '/')))
|
||||||
|
me = p + 1;
|
||||||
|
|
||||||
if (argc < 3)
|
opterr = 0;
|
||||||
|
while ((i = getopt(argc, argv, "dh:t:")) != -1)
|
||||||
|
switch (i)
|
||||||
{
|
{
|
||||||
printf("Usage: %s <host> <command> [args...]\n", argv[0]);
|
case 'd':
|
||||||
return 1;
|
debug++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
host = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 't':
|
||||||
|
timeout = atoi(optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
USAGE();
|
||||||
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
dest_host = strdup(argv[1]);
|
argc -= optind;
|
||||||
|
argv += optind;
|
||||||
|
|
||||||
|
if (argc < 1 || !argv[0][0])
|
||||||
|
{
|
||||||
|
USAGE();
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!host)
|
||||||
|
host = "127.0.0.1";
|
||||||
|
|
||||||
|
if ((p = strchr(host, ':')))
|
||||||
|
{
|
||||||
|
port = atoi(p + 1);
|
||||||
|
if (!port)
|
||||||
{
|
{
|
||||||
// Init socket
|
fprintf(stderr, "%s: invalid port `%s'\n", me, p + 1);
|
||||||
int on = 1;
|
return EXIT_FAILURE;
|
||||||
struct sockaddr_in addr;
|
|
||||||
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
addr.sin_port = htons(1703);
|
|
||||||
udpfd = socket(AF_INET, SOCK_DGRAM, 17);
|
|
||||||
setsockopt(udpfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
|
||||||
if (bind(udpfd, (void *) &addr, sizeof(addr)) < 0)
|
|
||||||
{
|
|
||||||
perror("bind");
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*p = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
port = NSCTL_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; !req_type && builtins[i].command; i++)
|
||||||
|
if (!strcmp(argv[0], builtins[i].command))
|
||||||
|
req_type = builtins[i].action;
|
||||||
|
|
||||||
|
if (req_type == NSCTL_REQ_HELP)
|
||||||
|
{
|
||||||
|
printf("Available commands:\n");
|
||||||
|
for (i = 0; builtins[i].command; i++)
|
||||||
|
printf(" %s%s\n", builtins[i].command, builtins[i].usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req_type)
|
||||||
|
{
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
req_type = NSCTL_REQ_CONTROL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((res = request(host, port, req_type, argc, argv)))
|
||||||
|
{
|
||||||
|
FILE *stream = stderr;
|
||||||
|
int status = EXIT_FAILURE;
|
||||||
|
|
||||||
|
if (res->type == NSCTL_RES_OK)
|
||||||
{
|
{
|
||||||
struct hostent *h = gethostbyname(dest_host);
|
stream = stdout;
|
||||||
if (h) dest_ip = ntohl(*(unsigned int *)h->h_addr);
|
status = EXIT_SUCCESS;
|
||||||
if (!dest_ip) dest_ip = ntohl(inet_addr(dest_host));
|
|
||||||
if (!dest_ip)
|
|
||||||
{
|
|
||||||
printf("Can't resolve \"%s\"\n", dest_host);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(packet = calloc(1400, 1)))
|
for (i = 0; i < res->argc; i++)
|
||||||
{
|
fprintf(stream, "%s\n", res->argv[i]);
|
||||||
perror("calloc");
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
srand(time(NULL));
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
// Deal with command & params
|
return EXIT_FAILURE;
|
||||||
for (i = 0; i < (sizeof(commands) / sizeof(commands[0])); i++)
|
|
||||||
{
|
|
||||||
if (strcasecmp(commands[i].command, argv[2]) == 0)
|
|
||||||
{
|
|
||||||
int p;
|
|
||||||
pkt_type = commands[i].pkt_type;
|
|
||||||
len = new_packet(pkt_type, packet);
|
|
||||||
if (argc < (commands[i].params + 3))
|
|
||||||
{
|
|
||||||
printf("Not enough parameters for %s\n", argv[2]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
for (p = 0; p < commands[i].params; p++)
|
|
||||||
{
|
|
||||||
strncpy((packet + len), argv[p + 3], 1400 - len - 1);
|
|
||||||
len += strlen(argv[p + 3]) + 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!pkt_type)
|
|
||||||
{
|
|
||||||
printf("Unknown command\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
send_packet(udpfd, dest_ip, dest_port, packet, len);
|
|
||||||
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
fd_set r;
|
|
||||||
struct timeval timeout;
|
|
||||||
|
|
||||||
FD_ZERO(&r);
|
|
||||||
FD_SET(udpfd, &r);
|
|
||||||
timeout.tv_sec = 1;
|
|
||||||
timeout.tv_usec = 0;
|
|
||||||
|
|
||||||
n = select(udpfd + 1, &r, 0, 0, &timeout);
|
|
||||||
if (n <= 0)
|
|
||||||
{
|
|
||||||
printf("Timeout waiting for packet\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((len = read_packet(udpfd, packet)))
|
|
||||||
{
|
|
||||||
printf("Received ");
|
|
||||||
dump_packet(packet, stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sigalrm_handler(int sig) { }
|
||||||
|
|
||||||
|
static struct nsctl *request(char *host, int port, int type, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
static struct nsctl res;
|
||||||
|
struct sockaddr_in peer;
|
||||||
|
socklen_t len = sizeof(peer);
|
||||||
|
struct hostent *h = gethostbyname(host);
|
||||||
|
int fd;
|
||||||
|
char buf[NSCTL_MAX_PKT_SZ];
|
||||||
|
int sz;
|
||||||
|
char *err;
|
||||||
|
|
||||||
|
if (!h || h->h_addrtype != AF_INET)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: invalid host `%s'\n", me, host);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: can't create udp socket (%s)\n", me, strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&peer, 0, len);
|
||||||
|
peer.sin_family = AF_INET;
|
||||||
|
peer.sin_port = htons(port);
|
||||||
|
memcpy(&peer.sin_addr.s_addr, h->h_addr, sizeof(peer.sin_addr.s_addr));
|
||||||
|
|
||||||
|
if (connect(fd, (struct sockaddr *) &peer, sizeof(peer)) < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: udp connect failed (%s)\n", me, strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sz = pack_control(buf, sizeof(buf), type, argc, argv)) < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: error packing request\n", me);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
struct nsctl req;
|
||||||
|
if (unpack_control(&req, buf, sz) == type)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Sending ");
|
||||||
|
dump_control(&req, stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (send(fd, buf, sz, 0) < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: error sending request (%s)\n", me, strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set timer */
|
||||||
|
if (timeout)
|
||||||
|
{
|
||||||
|
struct sigaction alrm;
|
||||||
|
alrm.sa_handler = sigalrm_handler;
|
||||||
|
sigemptyset(&alrm.sa_mask);
|
||||||
|
alrm.sa_flags = 0;
|
||||||
|
|
||||||
|
sigaction(SIGALRM, &alrm, 0);
|
||||||
|
alarm(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
sz = recv(fd, buf, sizeof(buf), 0);
|
||||||
|
alarm(0);
|
||||||
|
|
||||||
|
if (sz < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: error receiving response (%s)\n", me,
|
||||||
|
errno == EINTR ? "timed out" : strerror(errno));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((type = unpack_control(&res, buf, sz)) > 0 && type & NSCTL_RESPONSE)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Received ");
|
||||||
|
dump_control(&res, stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return &res;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = "unknown error";
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case NSCTL_ERR_SHORT: err = "short packet"; break;
|
||||||
|
case NSCTL_ERR_LONG: err = "extra data"; break;
|
||||||
|
case NSCTL_ERR_MAGIC: err = "bad magic"; break;
|
||||||
|
case NSCTL_ERR_TYPE: err = "invalid type"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "%s: %s\n", me, err);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
17
plugin.h
17
plugin.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __PLUGIN_H__
|
#ifndef __PLUGIN_H__
|
||||||
#define __PLUGIN_H__
|
#define __PLUGIN_H__
|
||||||
|
|
||||||
#define PLUGIN_API_VERSION 2
|
#define PLUGIN_API_VERSION 3
|
||||||
#define MAX_PLUGIN_TYPES 30
|
#define MAX_PLUGIN_TYPES 30
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
|
@ -79,17 +79,10 @@ struct param_timer
|
||||||
|
|
||||||
struct param_control
|
struct param_control
|
||||||
{
|
{
|
||||||
char *buf;
|
int argc;
|
||||||
int l;
|
char **argv;
|
||||||
unsigned int source_ip;
|
int response;
|
||||||
unsigned short source_port;
|
char *additional;
|
||||||
char *response;
|
|
||||||
int response_length;
|
|
||||||
int send_response;
|
|
||||||
short type;
|
|
||||||
int id;
|
|
||||||
char *data;
|
|
||||||
int data_length;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct param_new_session
|
struct param_new_session
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@
|
||||||
|
|
||||||
/* fudge up session rx speed if not set */
|
/* fudge up session rx speed if not set */
|
||||||
|
|
||||||
char const *cvs_id = "$Id: setrxspeed.c,v 1.2 2004-11-09 08:05:03 bodea Exp $";
|
char const *cvs_id = "$Id: setrxspeed.c,v 1.3 2004-11-17 08:23:35 bodea Exp $";
|
||||||
|
|
||||||
int __plugin_api_version = PLUGIN_API_VERSION;
|
int plugin_api_version = PLUGIN_API_VERSION;
|
||||||
static struct pluginfuncs *p = 0;
|
static struct pluginfuncs *p = 0;
|
||||||
|
|
||||||
int plugin_post_auth(struct param_post_auth *data)
|
int plugin_post_auth(struct param_post_auth *data)
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@
|
||||||
|
|
||||||
/* strip domain part of username before sending RADIUS requests */
|
/* strip domain part of username before sending RADIUS requests */
|
||||||
|
|
||||||
char const *cvs_id = "$Id: stripdomain.c,v 1.5 2004-11-09 08:05:03 bodea Exp $";
|
char const *cvs_id = "$Id: stripdomain.c,v 1.6 2004-11-17 08:23:35 bodea Exp $";
|
||||||
|
|
||||||
int __plugin_api_version = PLUGIN_API_VERSION;
|
int plugin_api_version = PLUGIN_API_VERSION;
|
||||||
static struct pluginfuncs *p = 0;
|
static struct pluginfuncs *p = 0;
|
||||||
|
|
||||||
int plugin_pre_auth(struct param_pre_auth *data)
|
int plugin_pre_auth(struct param_pre_auth *data)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue