Compare commits

...

11 Commits

Author SHA1 Message Date
Adrien Gallouët
adb791d3ba Update mud 2016-11-25 16:44:00 +00:00
Adrien Gallouët
f1a5d55613 Update mud 2016-11-18 18:03:12 +00:00
Adrien Gallouët
f46305847e Rework buffer 2016-11-18 11:55:21 +00:00
Adrien Gallouët
a75f3b0fd8 Remove STARTED and STOPPED 2016-11-07 15:08:25 +00:00
Adrien Gallouët
2934228005 Remove pull/push of mud 2016-10-27 15:04:11 +00:00
Adrien Gallouët
d599e545f7 Update mud 2016-10-25 09:15:34 +00:00
Frank Denis
048870e280 <linux/if.h> is not required any more (#19) 2016-10-24 11:19:43 +02:00
Frank Denis
31045456fe include <net/if.h> for the ifreq structure (#18)
Required on BSD. Doesn't break anything elsewhere.
2016-10-23 12:38:32 +02:00
Adrien Gallouët
0bb5be63b9 Get ICMP type 3 to set the next-hop MTU 2016-10-18 16:44:20 +00:00
Adrien Gallouët
c9f737197c Remove multiqueue (not used with mud) 2016-10-05 09:49:14 +00:00
Adrien Gallouët
d4e70feddc Update mud 2016-10-05 08:02:48 +00:00
4 changed files with 113 additions and 159 deletions

2
mud

Submodule mud updated: d255074199...72d0573c95

View File

@@ -266,7 +266,6 @@ int main (int argc, char **argv)
{ "dev", &dev, option_str }, { "dev", &dev, option_str },
{ "mtu", &mtu, option_long }, { "mtu", &mtu, option_long },
{ "keyfile", &keyfile, option_str }, { "keyfile", &keyfile, option_str },
{ "multiqueue", NULL, option_option },
{ "statefile", &statefile, option_str }, { "statefile", &statefile, option_str },
{ "timeout", &gt.timeout, option_long }, { "timeout", &gt.timeout, option_long },
{ "time-tolerance", &time_tolerance, option_long }, { "time-tolerance", &time_tolerance, option_long },
@@ -311,6 +310,15 @@ int main (int argc, char **argv)
return 1; return 1;
} }
int icmp_fd = -1;
if (v4) {
icmp_fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (icmp_fd==-1)
gt_log("couldn't create ICMP socket\n");
}
gt.state_fd = state_create(statefile); gt.state_fd = state_create(statefile);
if (statefile && gt.state_fd==-1) if (statefile && gt.state_fd==-1)
@@ -318,7 +326,7 @@ int main (int argc, char **argv)
char *tun_name = NULL; char *tun_name = NULL;
int tun_fd = tun_create(dev, &tun_name, option_is_set(opts, "multiqueue")); int tun_fd = tun_create(dev, &tun_name);
if (tun_fd==-1) { if (tun_fd==-1) {
gt_log("couldn't create tun device\n"); gt_log("couldn't create tun device\n");
@@ -373,153 +381,113 @@ int main (int argc, char **argv)
int mud_fd = mud_get_fd(mud); int mud_fd = mud_get_fd(mud);
fd_set_nonblock(mud_fd);
state_send(gt.state_fd, "INITIALIZED", tun_name); state_send(gt.state_fd, "INITIALIZED", tun_name);
fd_set rfds; fd_set rfds;
FD_ZERO(&rfds); FD_ZERO(&rfds);
int started = 0; unsigned char buf[8*1024];
struct {
unsigned char *buf;
} send, recv;
send.buf = malloc(2*mtu);
recv.buf = malloc(mtu);
size_t send_size = 0;
size_t send_limit = 0;
int send_tc = 0;
int send_next_tc = 0;
while (!gt.quit) { while (!gt.quit) {
FD_SET(tun_fd, &rfds); FD_SET(tun_fd, &rfds);
if (mud_can_pull(mud)) {
FD_SET(mud_fd, &rfds); FD_SET(mud_fd, &rfds);
} else {
FD_CLR(mud_fd, &rfds);
}
struct timeval timeout = { if (icmp_fd!=-1)
.tv_usec = 100000, FD_SET(icmp_fd, &rfds);
};
if (mud_can_push(mud) || send_size) if _0_(select(mud_fd+1, &rfds, NULL, NULL, NULL)==-1) {
timeout.tv_usec = 1000;
if _0_(select(mud_fd+1, &rfds, NULL, NULL, &timeout)==-1) {
if (errno==EINTR) if (errno==EINTR)
continue; continue;
perror("select"); perror("select");
return 1; return 1;
} }
if (mud_is_up(mud)) { if (icmp_fd!=-1 && FD_ISSET(icmp_fd, &rfds)) {
if (!started) { struct sockaddr_storage ss;
state_send(gt.state_fd, "STARTED", tun_name); socklen_t sl = sizeof(ss);
started = 1; ssize_t r = recvfrom(icmp_fd, buf, sizeof(buf), 0, (struct sockaddr *)&ss, &sl);
if (r>=8) {
struct ip_common ic;
if (!ip_get_common(&ic, buf, r) && ic.proto==1) {
unsigned char *data = &buf[ic.hdr_size];
if (data[0]==3) {
int new_mtu = (data[6]<<8)|data[7];
if (new_mtu) {
gt_log("received MTU from ICMP: %i\n", new_mtu);
mud_set_mtu(mud, new_mtu-50); // XXX
}
}
} }
} else {
if (started) {
state_send(gt.state_fd, "STOPPED", tun_name);
started = 0;
} }
} }
if (FD_ISSET(tun_fd, &rfds)) { if (FD_ISSET(tun_fd, &rfds)) {
while (send_size<mtu) { size_t size = 0;
const ssize_t r = tun_read(tun_fd, send.buf+send_size, mtu);
if (r<=0) { while (sizeof(buf)-size>mtu) {
gt.quit |= !r; const ssize_t r = tun_read(tun_fd, &buf[size], sizeof(buf)-size);
if (r<=0)
break; break;
}
struct ip_common ic; struct ip_common ic;
if (ip_get_common(&ic, send.buf+send_size, mtu) || ic.size!=r) { if (ip_get_common(&ic, &buf[size], r) || ic.size!=r)
gt_log("packet dropped: malformed\n"); break;
continue;
size += r;
} }
send_size += r; int p = 0;
if (send_size<=mtu) { while (p<size) {
send_limit = send_size; int tc = 0;
if ((ic.tc&0xFC)>(send_tc&0xFC)) int q = p;
send_tc = ic.tc;
} else { while (q<size) {
if ((ic.tc&0xFC)>(send_next_tc&0xFC)) struct ip_common ic;
send_next_tc = ic.tc;
} if (ip_get_common(&ic, &buf[q], size-q) || ic.size>size-q) {
} size = q;
break;
} }
if (send_limit) { if (q+ic.size>p+mtu)
int r = mud_send(mud, send.buf, send_limit, send_tc); break;
q += ic.size;
if (tc<(ic.tc&0xFC))
tc = ic.tc&0xFC;
}
int r = mud_send(mud, &buf[p], q-p, tc);
if (r==-1 && errno==EMSGSIZE) {
int new_mtu = mud_get_mtu(mud);
if (r==send_limit) {
if (send_size>send_limit)
memmove(send.buf, &send.buf[send_limit], send_size-send_limit);
send_size -= send_limit;
send_limit = send_size;
send_tc = send_next_tc;
send_next_tc = 0;
} else if (r==-1) {
if (errno==EMSGSIZE) {
long new_mtu = mud_get_mtu(mud);
if (new_mtu!=mtu) { if (new_mtu!=mtu) {
size_t total = send_size;
if (tun_set_mtu(tun_name, new_mtu)==-1) {
perror("tun_set_mtu");
gt.quit |= 1;
break;
}
gt_log("MTU changed: %li\n", new_mtu);
mtu = new_mtu; mtu = new_mtu;
send_size = 0;
send_limit = 0;
send_tc = 0;
send_next_tc = 0;
while (send_size<total) { gt_log("MTU changed: %li\n", mtu);
struct ip_common ic;
if (ip_get_common(&ic, send.buf+send_size, mtu)) if (tun_set_mtu(tun_name, mtu)==-1)
break; perror("tun_set_mtu");
}
send_size += ic.size;
if (send_size<=mtu) {
send_limit = send_size;
if ((ic.tc&0xFC)>(send_tc&0xFC))
send_tc = ic.tc;
} else { } else {
if ((ic.tc&0xFC)>(send_next_tc&0xFC)) if (r==-1 && errno!=EAGAIN)
send_next_tc = ic.tc;
}
}
}
} else if (errno!=EAGAIN) {
perror("mud_send"); perror("mud_send");
}
}
}
if (mud_push(mud)==-1 && errno!=EAGAIN) p = q;
perror("mud_push"); }
}
}
if (FD_ISSET(mud_fd, &rfds)) { if (FD_ISSET(mud_fd, &rfds)) {
if (mud_pull(mud)==-1 && errno!=EAGAIN) while (1) {
perror("mud_pull"); const int size = mud_recv(mud, buf, sizeof(buf));
}
while (!gt.quit) {
const int size = mud_recv(mud, recv.buf, mtu);
if (size<=0) { if (size<=0) {
if (size==-1 && errno!=EAGAIN) if (size==-1 && errno!=EAGAIN)
@@ -532,20 +500,16 @@ int main (int argc, char **argv)
while (p<size) { while (p<size) {
struct ip_common ic; struct ip_common ic;
if (ip_get_common(&ic, recv.buf+p, size-p) || ic.size>size-p) if (ip_get_common(&ic, &buf[p], size-p) || ic.size>size-p)
break; break;
const ssize_t r = tun_write(tun_fd, recv.buf+p, ic.size); tun_write(tun_fd, &buf[p], ic.size);
if (r<=0) {
gt.quit |= !r;
break;
}
p += ic.size; p += ic.size;
} }
} }
} }
}
return 0; return 0;
} }

View File

@@ -11,8 +11,9 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <net/if.h>
#ifdef __linux__ #ifdef __linux__
#include <linux/if.h>
#include <linux/if_tun.h> #include <linux/if_tun.h>
#endif #endif
@@ -28,7 +29,7 @@
#ifdef __APPLE__ #ifdef __APPLE__
static int tun_create_by_id (char *name, size_t size, unsigned id, _unused_ int mq) static int tun_create_by_id (char *name, size_t size, unsigned id)
{ {
int fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL); int fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
@@ -63,21 +64,21 @@ static int tun_create_by_id (char *name, size_t size, unsigned id, _unused_ int
return fd; return fd;
} }
static int tun_create_by_name (char *name, size_t size, char *dev_name, int mq) static int tun_create_by_name (char *name, size_t size, char *dev_name)
{ {
unsigned id = 0; unsigned id = 0;
if (sscanf(dev_name, "utun%u", &id)!=1) if (sscanf(dev_name, "utun%u", &id)!=1)
return -1; return -1;
return tun_create_by_id(name, size, id, mq); return tun_create_by_id(name, size, id);
} }
#else /* not __APPLE__ */ #else /* not __APPLE__ */
#ifdef __linux__ #ifdef __linux__
static int tun_create_by_name (char *name, size_t size, char *dev_name, int mq) static int tun_create_by_name (char *name, size_t size, char *dev_name)
{ {
int fd = open("/dev/net/tun", O_RDWR); int fd = open("/dev/net/tun", O_RDWR);
@@ -88,12 +89,6 @@ static int tun_create_by_name (char *name, size_t size, char *dev_name, int mq)
.ifr_flags = IFF_TUN|IFF_NO_PI, .ifr_flags = IFF_TUN|IFF_NO_PI,
}; };
if (mq) {
#ifdef IFF_MULTI_QUEUE
ifr.ifr_flags |= IFF_MULTI_QUEUE;
#endif
}
str_cpy(ifr.ifr_name, dev_name, IFNAMSIZ-1); str_cpy(ifr.ifr_name, dev_name, IFNAMSIZ-1);
if (ioctl(fd, TUNSETIFF, &ifr)) { if (ioctl(fd, TUNSETIFF, &ifr)) {
@@ -108,7 +103,7 @@ static int tun_create_by_name (char *name, size_t size, char *dev_name, int mq)
#else /* not __linux__ not __APPLE__ */ #else /* not __linux__ not __APPLE__ */
static int tun_create_by_name (char *name, size_t size, char *dev_name, _unused_ int mq) static int tun_create_by_name (char *name, size_t size, char *dev_name)
{ {
char path[64]; char path[64];
@@ -120,32 +115,27 @@ static int tun_create_by_name (char *name, size_t size, char *dev_name, _unused_
#endif /* not __APPLE__ */ #endif /* not __APPLE__ */
static int tun_create_by_id (char *name, size_t size, unsigned id, int mq) static int tun_create_by_id (char *name, size_t size, unsigned id)
{ {
char dev_name[64]; char dev_name[64];
snprintf(dev_name, sizeof(dev_name), "tun%u", id); snprintf(dev_name, sizeof(dev_name), "tun%u", id);
return tun_create_by_name(name, size, dev_name, mq); return tun_create_by_name(name, size, dev_name);
} }
#endif #endif
int tun_create (char *dev_name, char **ret_name, int mq) int tun_create (char *dev_name, char **ret_name)
{ {
char name[64] = {0}; char name[64] = {0};
int fd = -1; int fd = -1;
#ifndef IFF_MULTI_QUEUE
if (mq)
gt_na("IFF_MULTI_QUEUE");
#endif
if (str_empty(dev_name)) { if (str_empty(dev_name)) {
for (unsigned id=0; id<32 && fd==-1; id++) for (unsigned id=0; id<32 && fd==-1; id++)
fd = tun_create_by_id(name, sizeof(name), id, mq); fd = tun_create_by_id(name, sizeof(name), id);
} else { } else {
fd = tun_create_by_name(name, sizeof(name), dev_name, mq); fd = tun_create_by_name(name, sizeof(name), dev_name);
} }
if (fd!=-1 && ret_name) if (fd!=-1 && ret_name)

View File

@@ -2,7 +2,7 @@
#include <unistd.h> #include <unistd.h>
int tun_create (char *, char **, int); int tun_create (char *, char **);
ssize_t tun_read (int, void *, size_t); ssize_t tun_read (int, void *, size_t);
ssize_t tun_write (int, const void *, size_t); ssize_t tun_write (int, const void *, size_t);
int tun_set_mtu (char *, int); int tun_set_mtu (char *, int);