#define MAX_MAPEC_NUMBER 4096
+#define MTU 1495
+
/**
List of private descriptor associated to each connected MAPEC.
*/
}
addr->sin_family = AF_INET;
- addr->sin_port = htons (atoi (port));
+ int nport = atoi (port);
+ if (nport <= 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ addr->sin_port = htons (nport);
VERBOSE (mapec, INFO, PRINTF ("parse URL -> %s %s\n", hostname, port));
VERBOSE (mapec, TRACE, PRINTF ("connect_tun\n"));
+ /* parse device name */
+ int mtu = MTU;
+ int device_name_len = strlen (device_name);
+ char *pt = strchr (device_name, ':');
+ if (pt) {
+ mtu = atoi (pt + 1);
+ if (mtu <= 0) {
+ VERBOSE (mapec, ERROR, PRINTF ("can't parse MTU in '%s'\n", device_name));
+ return -1;
+ }
+ device_name_len = pt - device_name;
+ }
+
+ VERBOSE (mapec, DEBUG, PRINTF ("tun device '%.*s' %d\n", device_name_len, device_name, mtu));
+
/* request a TUN device */
int fid = open ("/dev/net/tun", O_RDWR);
if (fid < 0) {
- VERBOSE (mapec, ERROR, PRINTF ("can't open a tun device '%s'\n", device_name));
+ VERBOSE (mapec, ERROR, PRINTF ("can't open a tun device '%.*s'\n", device_name_len, device_name));
return -1;
}
struct ifreq ifr = { 0 };
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
if (ioctl (fid, TUNSETIFF, &ifr) < 0) {
- VERBOSE (mapec, ERROR, PRINTF ("can't link to named device '%s'\n", device_name));
+ VERBOSE (mapec, ERROR, PRINTF ("can't link to named device '%.*s'\n", device_name_len, device_name));
return -1;
}
/* get interface name */
ifr.ifr_flags = 0;
- strncpy(ifr.ifr_name, device_name, IFNAMSIZ);
+ strncpy(ifr.ifr_name, device_name, (IFNAMSIZ < device_name_len) ? IFNAMSIZ : device_name_len);
/* set ip address */
mapec->addrin.sin_family = AF_INET;
mapec->addrin.sin_port = 0;
mapec->addrin.sin_addr.s_addr = inet_addr (local_address);
+ if (mapec->addrin.sin_addr.s_addr == INADDR_NONE) {
+ VERBOSE (mapec, ERROR, PRINTF ("can't find host '%s'\n", local_address));
+ errno = EHOSTUNREACH;
+ return -1;
+ }
memcpy (&ifr.ifr_addr, &mapec->addrin, sizeof (struct sockaddr));
if ((ioctl (sock, SIOCSIFADDR, &ifr) < 0) || (ioctl (sock, SIOCGIFFLAGS, &ifr) < 0)) {
- VERBOSE (mapec, ERROR, PRINTF ("can't set ip address '%s' on tun device '%s'\n", local_address, device_name));
+ VERBOSE (mapec, ERROR, PRINTF ("can't set ip address '%s' on tun device '%.*s'\n", local_address, device_name_len, device_name));
return -1;
}
ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
if (ioctl (sock, SIOCSIFFLAGS, &ifr) < 0) {
- VERBOSE (mapec, ERROR, PRINTF ("can't activate tun interface '%s'\n", device_name));
+ VERBOSE (mapec, ERROR, PRINTF ("can't activate tun interface '%.*s'\n", device_name_len, device_name));
return -1;
}
+
+ ifr.ifr_mtu = mtu;
+ if ((ioctl (sock, SIOCSIFMTU, &ifr) < 0)) {
+ VERBOSE (mapec, ERROR, PRINTF ("can't set MTU to %d on tun device '%.*s'\n", mtu, device_name_len, device_name));
+ return -1;
+ }
+
close (sock);
/* create route */
struct sockaddr_in *addr = (struct sockaddr_in *) &route.rt_gateway;
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = inet_addr (local_address);
+ if (addr->sin_addr.s_addr == INADDR_NONE) {
+ VERBOSE (mapec, ERROR, PRINTF ("can't find host '%s'\n", local_address));
+ errno = EHOSTUNREACH;
+ return -1;
+ }
addr = (struct sockaddr_in *) &route.rt_dst;
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = inet_addr (remote_address);
+ if (addr->sin_addr.s_addr == INADDR_NONE) {
+ VERBOSE (mapec, ERROR, PRINTF ("can't find host '%s'\n", remote_address));
+ errno = EHOSTUNREACH;
+ return -1;
+ }
addr = (struct sockaddr_in *) &route.rt_genmask;
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = inet_addr ("255.255.255.0");
char *progname = NULL;
char *version = "0.1";
-char *devtun = "tun://tun0";
+char *devtun = "tun://tun0:1440";
char *loctun = "tun://10.2.0.1";
char *remtun = "tun://10.2.1.0";
char *locudp = "udp://10.1.0.1:1234";
int max_fd = ((tun_fd > udp_fd) ? tun_fd : udp_fd) + 1;
if (-1 == select(max_fd, &readset, NULL, NULL, NULL)) {
- VERBOSE (ulvpn, ERROR, PRINTF ("select error\n"));
+ if (!stop) {
+ VERBOSE (ulvpn, ERROR, PRINTF ("select error\n"));
+ }
break;
}
}
/* test: ulvpn.exe -h | grep usage */
+/* test: ulvpn.exe help 2>&1 | grep usage */
/* test: ulvpn.exe -d 2>&1 | grep 'dev tun not specified' */
/* test: ulvpn.exe -l 2>&1 | grep 'local tun not specified' */
/* test: ulvpn.exe -r 2>&1 | grep 'remote tun not specified' */
/* test: ulvpn.exe -u 2>&1 | grep 'remote udp not specified' */
/* test: ulvpn.exe -v 2>&1 | grep 'verbose level not specified' */
/* test: ulvpn.exe -V 2>&1 | grep 'verbose level not specified' */
+
+/* test: ulvpn.exe -d tun://tun0:-1; test $? -ne 0 */
+/* test: ulvpn.exe -l udp://localhost:1234; test $? -ne 0 */
+/* test: ulvpn.exe -l tun://nohost.nowhere; test $? -ne 0 */
+/* test: ulvpn.exe -r udp://localhost:1234; test $? -ne 0 */
+/* test: ulvpn.exe -t tun://nohost.nowhere; test $? -ne 0 */
+/* test: ulvpn.exe -t udp://nohost.nowhere:1234; test $? -ne 0 */
+/* test: ulvpn.exe -t udp://localhost:-1; test $? -ne 0 */
+/* test: ulvpn.exe -u tun://localhost; test $? -ne 0 */
+/* test: ulvpn.exe -u udp://nohost.nowhere:1235; test $? -ne 0 */
+/* test: ulvpn.exe -u udp://localhost:-1; test $? -ne 0 */
+
/* test: ulvpn.exe -v 5 & pid=$!; sleep 1; ip route list dev tun0; rc=$?; sleep 1; kill -TERM $pid; test $rc -eq 0 */
-/* test: ulvpn.exe -v 5 & pid=$!; sleep 1; ping -c 1 -W 1 10.2.1.1; kill -TERM $pid */
+
+/* test: ulvpn.exe -v 5 -V 5 -d tun://tun0:1496 & pid=$!; sleep 1; ping -c 1 -W 1 10.2.1.1; kill -TERM $pid */
+
+/* test: ulvpn.exe -v 5 -t udp://localhost:1234 -u udp://localhost:1235 & pid1=$!; sleep 1; nc -ul 1235 > pcap & pid2=$!; sleep 1; echo TEST | nc -Nuq0 10.2.1.1 3000; sleep 1; kill -TERM $pid1 $pid2; strings pcap | grep -q TEST */
+/* test: ulvpn.exe -v 5 -l tun://10.2.1.1 -r tun://10.2.0.0 -t udp://localhost:1234 -u udp://localhost:1235 & pid1=$!; sleep 1; nc -ul 3000 > text & pid2=$!; sleep 1; cat pcap | nc -4Nuq0 -p 1235 localhost 1234; sleep 1; kill -TERM $pid1 $pid2; test "$(cat text)" = TEST */
+/* test: rm -f pcap text */
/* vim: set ts=4 sw=4 si et: */