diff --git a/mud b/mud index d5297b8..d255074 160000 --- a/mud +++ b/mud @@ -1 +1 @@ -Subproject commit d5297b8a70a593cc3d65d499ddb1a7909fa16782 +Subproject commit d2550741992d085b9e0d0551d28390429ebf799a diff --git a/src/main.c b/src/main.c index f24aea9..affc589 100644 --- a/src/main.c +++ b/src/main.c @@ -325,11 +325,16 @@ int main (int argc, char **argv) return 1; } + if (tun_set_mtu(tun_name, mtu)==-1) { + perror("tun_set_mtu"); + return 1; + } + fd_set_nonblock(tun_fd); int chacha = option_is_set(opts, "chacha20"); - struct mud *mud = mud_create(bind_port, v4, v6, !chacha); + struct mud *mud = mud_create(bind_port, v4, v6, !chacha, mtu); if (!mud) { gt_log("couldn't create mud\n"); @@ -440,8 +445,6 @@ int main (int argc, char **argv) send_size += r; - int update_tc = (ic.tc&0xFC)>(send_tc&0xFC); - if (send_size<=mtu) { send_limit = send_size; if ((ic.tc&0xFC)>(send_tc&0xFC)) @@ -455,15 +458,55 @@ int main (int argc, char **argv) if (send_limit) { int r = mud_send(mud, send.buf, send_limit, send_tc); - if (r==-1 && errno!=EAGAIN) { - perror("mud_send"); - } else if (r==send_limit) { + + if (r==send_limit) { if (send_size>send_limit) - memmove(&send.buf[0], &send.buf[send_limit], 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) { + 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; + send_size = 0; + send_limit = 0; + send_tc = 0; + send_next_tc = 0; + + while (send_size(send_tc&0xFC)) + send_tc = ic.tc; + } else { + if ((ic.tc&0xFC)>(send_next_tc&0xFC)) + send_next_tc = ic.tc; + } + } + } + } else if (errno!=EAGAIN) { + perror("mud_send"); + } } } diff --git a/src/tun.c b/src/tun.c index 3d6204c..6c9d617 100644 --- a/src/tun.c +++ b/src/tun.c @@ -240,3 +240,25 @@ ssize_t tun_write (int fd, const void *data, size_t size) return ret; #endif } + +int tun_set_mtu (char *dev_name, int mtu) +{ + struct ifreq ifr = { + .ifr_mtu = mtu, + }; + + str_cpy(ifr.ifr_name, dev_name, IFNAMSIZ-1); + + int fd = socket(AF_INET, SOCK_DGRAM, 0); + + if (fd==-1) + return -1; + + int ret = ioctl(fd, SIOCSIFMTU, &ifr); + + int err = errno; + close(fd); + errno = err; + + return ret; +} diff --git a/src/tun.h b/src/tun.h index e800025..0a92a9c 100644 --- a/src/tun.h +++ b/src/tun.h @@ -2,6 +2,7 @@ #include -int tun_create (char *, char **, int); -ssize_t tun_read (int, void *, size_t); -ssize_t tun_write (int, const void *, size_t); +int tun_create (char *, char **, int); +ssize_t tun_read (int, void *, size_t); +ssize_t tun_write (int, const void *, size_t); +int tun_set_mtu (char *, int);