Skip to content

Commit

Permalink
Merge pull request xelerance#9 from sigwall/kernel
Browse files Browse the repository at this point in the history
Fix kernel support for 2.6.23+
  • Loading branch information
xelerance committed Jan 11, 2013
2 parents 7a481bc + ee2dda8 commit 5199a2f
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 80 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ OSFLAGS?= -DLINUX -I$(KERNELSRC)/include/
# are packages seperately (eg kernel-headers on Fedora)
# Note: 2.6.23+ support still needs some changes in the xl2tpd source
#
#OSFLAGS+= -DUSE_KERNEL
OSFLAGS+= -DUSE_KERNEL
#
#
# Uncomment the next line for FreeBSD
Expand Down
2 changes: 2 additions & 0 deletions call.c
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,8 @@ struct call *get_call (int tunnel, int call, struct in_addr addr, int port,
st->peer.sin_port = port;
st->refme = refme;
st->refhim = refhim;
st->udp_fd = -1;
st->pppox_fd = -1;
bcopy (&addr, &st->peer.sin_addr, sizeof (addr));
st->next = tunnels.head;
tunnels.head = st;
Expand Down
11 changes: 11 additions & 0 deletions control.c
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,11 @@ int control_finish (struct tunnel *t, struct call *c)
if (gconfig.debug_state)
l2tp_log (LOG_DEBUG, "%s: sending SCCCN\n", __FUNCTION__);
control_xmit (buf);

#ifdef USE_KERNEL
connect_pppol2tp(t);
#endif

/* Schedule a HELLO */
tv.tv_sec = HELLO_DELAY;
tv.tv_usec = 0;
Expand All @@ -608,6 +613,7 @@ int control_finish (struct tunnel *t, struct call *c)
"Connection established to %s, %d. Local: %d, Remote: %d (ref=%u/%u).\n",
IPADDY (t->peer.sin_addr),
ntohs (t->peer.sin_port), t->ourtid, t->tid, t->refme, t->refhim);

if (t->lac)
{
/* This is part of a LAC, so we want to go ahead
Expand Down Expand Up @@ -635,6 +641,11 @@ int control_finish (struct tunnel *t, struct call *c)
IPADDY (t->peer.sin_addr),
ntohs (t->peer.sin_port), t->ourtid, t->tid, t->refme, t->refhim,
t->lns->entname);

#ifdef USE_KERNEL
connect_pppol2tp(t);
#endif

/* Schedule a HELLO */
tv.tv_sec = HELLO_DELAY;
tv.tv_usec = 0;
Expand Down
1 change: 1 addition & 0 deletions file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1154,6 +1154,7 @@ int set_ipsec_saref (char *word, char *value, int context, void *item)
}
if(g->forceuserspace != 1) {
l2tp_log(LOG_WARNING, "IPsec SAref does not work with L2TP kernel mode yet, enabling forceuserspace=yes\n");
g->forceuserspace = 1;
}
break;
default:
Expand Down
7 changes: 6 additions & 1 deletion l2tp.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ struct tunnel
int ourrws; /* Receive Window Size */
int rxspeed; /* Receive bps */
int txspeed; /* Transmit bps */
int udp_fd; /* UDP fd */
int pppox_fd; /* PPPOX tunnel fd */
struct call *self;
struct lns *lns; /* LNS that owns us */
struct lac *lac; /* LAC that owns us */
Expand Down Expand Up @@ -206,7 +208,6 @@ extern struct tunnel_list tunnels;
extern void tunnel_close (struct tunnel *t);
extern void network_thread ();
extern int init_network ();
extern int kernel_support;
extern int server_socket;
extern struct tunnel *new_tunnel ();
extern struct packet_queue xmit_udp;
Expand All @@ -220,6 +221,10 @@ extern void control_xmit (void *);
extern int ppd;
extern int switch_io; /* jz */
extern int control_fd;
#ifdef USE_KERNEL
extern int kernel_support;
extern int connect_pppol2tp (struct tunnel *t);
#endif
extern int start_pppd (struct call *c, struct ppp_opts *);
extern void magic_lac_dial (void *);
extern int get_entropy (unsigned char *, int);
Expand Down
69 changes: 0 additions & 69 deletions linux/include/linux/if_pppol2tp.h

This file was deleted.

122 changes: 118 additions & 4 deletions network.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#ifndef LINUX
# include <sys/uio.h>
#endif
Expand All @@ -36,7 +37,6 @@ int server_socket; /* Server socket */
int kernel_support; /* Kernel Support there or not? */
#endif


int init_network (void)
{
long arg;
Expand All @@ -45,13 +45,18 @@ int init_network (void)
server.sin_family = AF_INET;
server.sin_addr.s_addr = gconfig.listenaddr;
server.sin_port = htons (gconfig.port);
int flags;
if ((server_socket = socket (PF_INET, SOCK_DGRAM, 0)) < 0)
{
l2tp_log (LOG_CRIT, "%s: Unable to allocate socket. Terminating.\n",
__FUNCTION__);
return -EINVAL;
};

flags = 1;
setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags));
setsockopt(server_socket, SOL_SOCKET, SO_NO_CHECK, &flags, sizeof(flags));

if (bind (server_socket, (struct sockaddr *) &server, sizeof (server)))
{
close (server_socket);
Expand Down Expand Up @@ -94,7 +99,7 @@ int init_network (void)
int kernel_fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP);
if (kernel_fd < 0)
{
l2tp_log (LOG_INFO, "L2TP kernel support not detected.\n");
l2tp_log (LOG_INFO, "L2TP kernel support not detected (try modprobing l2tp_ppp and pppol2tp)\n");
kernel_support = 0;
}
else
Expand Down Expand Up @@ -321,6 +326,11 @@ int build_fdset (fd_set *readfds)

while (tun)
{
if (tun->udp_fd > -1) {
if (tun->udp_fd > max)
max = tun->udp_fd;
FD_SET (tun->udp_fd, readfds);
}
call = tun->call_head;
while (call)
{
Expand Down Expand Up @@ -390,6 +400,8 @@ void network_thread ()
struct iovec iov;
char cbuf[256];
unsigned int refme, refhim;
int * currentfd;
int server_socket_processed;

/* This one buffer can be recycled for everything except control packets */
buf = new_buf (MAX_RECV_SIZE);
Expand Down Expand Up @@ -428,7 +440,21 @@ void network_thread ()
{
do_control ();
}
if (FD_ISSET (server_socket, &readfds))
server_socket_processed = 0;
currentfd = NULL;
st = tunnels.head;
while (st || !server_socket_processed) {
if (st && (st->udp_fd == -1)) {
st=st->next;
continue;
}
if (st) {
currentfd = &st->udp_fd;
} else {
currentfd = &server_socket;
server_socket_processed = 1;
}
if (FD_ISSET (*currentfd, &readfds))
{
/*
* Okay, now we're ready for reading and processing new data.
Expand Down Expand Up @@ -456,12 +482,19 @@ void network_thread ()
msgh.msg_flags = 0;

/* Receive one packet. */
recvsize = recvmsg(server_socket, &msgh, 0);
recvsize = recvmsg(*currentfd, &msgh, 0);

if (recvsize < MIN_PAYLOAD_HDR_LEN)
{
if (recvsize < 0)
{
if (errno == ECONNREFUSED) {
close(*currentfd);
}
if ((errno == ECONNREFUSED) ||
(errno == EBADF)) {
*currentfd = -1;
}
if (errno != EAGAIN)
l2tp_log (LOG_WARNING,
"%s: recvfrom returned error %d (%s)\n",
Expand Down Expand Up @@ -566,6 +599,8 @@ void network_thread ()
}
};
}
if (st) st=st->next;
}

/*
* finished obvious sources, look for data from PPP connections.
Expand Down Expand Up @@ -638,3 +673,82 @@ void network_thread ()
}

}

#ifdef USE_KERNEL
int connect_pppol2tp(struct tunnel *t) {
if (kernel_support) {
int ufd = -1, fd2 = -1;
int flags;
struct sockaddr_pppol2tp sax;

struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_addr.s_addr = gconfig.listenaddr;
server.sin_port = htons (gconfig.port);
if ((ufd = socket (PF_INET, SOCK_DGRAM, 0)) < 0)
{
l2tp_log (LOG_CRIT, "%s: Unable to allocate UDP socket. Terminating.\n",
__FUNCTION__);
return -EINVAL;
};

flags=1;
setsockopt(ufd, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags));
setsockopt(ufd, SOL_SOCKET, SO_NO_CHECK, &flags, sizeof(flags));

if (bind (ufd, (struct sockaddr *) &server, sizeof (server)))
{
close (ufd);
l2tp_log (LOG_CRIT, "%s: Unable to bind UDP socket: %s. Terminating.\n",
__FUNCTION__, strerror(errno), errno);
return -EINVAL;
};
server = t->peer;
flags = fcntl(ufd, F_GETFL);
if (flags == -1 || fcntl(ufd, F_SETFL, flags | O_NONBLOCK) == -1) {
l2tp_log (LOG_WARNING, "%s: Unable to set UDP socket nonblock.\n",
__FUNCTION__);
return -EINVAL;
}
if (connect (ufd, (struct sockaddr *) &server, sizeof(server)) < 0) {
l2tp_log (LOG_CRIT, "%s: Unable to connect UDP peer. Terminating.\n",
__FUNCTION__);
return -EINVAL;
}

t->udp_fd=ufd;

fd2 = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP);
if (fd2 < 0) {
l2tp_log (LOG_WARNING, "%s: Unable to allocate PPPoL2TP socket.\n",
__FUNCTION__);
return -EINVAL;
}
flags = fcntl(fd2, F_GETFL);
if (flags == -1 || fcntl(fd2, F_SETFL, flags | O_NONBLOCK) == -1) {
l2tp_log (LOG_WARNING, "%s: Unable to set PPPoL2TP socket nonblock.\n",
__FUNCTION__);
return -EINVAL;
}
sax.sa_family = AF_PPPOX;
sax.sa_protocol = PX_PROTO_OL2TP;
sax.pppol2tp.pid = 0;
sax.pppol2tp.fd = t->udp_fd;
sax.pppol2tp.addr.sin_addr.s_addr = t->peer.sin_addr.s_addr;
sax.pppol2tp.addr.sin_port = t->peer.sin_port;
sax.pppol2tp.addr.sin_family = AF_INET;
sax.pppol2tp.s_tunnel = t->ourtid;
sax.pppol2tp.s_session = 0;
sax.pppol2tp.d_tunnel = t->tid;
sax.pppol2tp.d_session = 0;
if ((connect(fd2, (struct sockaddr *)&sax, sizeof(sax))) < 0) {
l2tp_log (LOG_WARNING, "%s: Unable to connect PPPoL2TP socket. %d %s\n",
__FUNCTION__, errno, strerror(errno));
close(fd2);
return -EINVAL;
}
t->pppox_fd = fd2;
}
return 0;
}
#endif
Loading

0 comments on commit 5199a2f

Please sign in to comment.