#include <linux/if_tun.h>
#include <linux/sockios.h>
#include <net/if.h>
+#include <net/route.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#define ifreq_offsetof(x) offsetof(struct ifreq, x)
-int connect_tun (MAPEC_addr_t *mapec, char *device_name, char *ip_address)
+int connect_tun (MAPEC_addr_t *mapec, char *device_name, char *local_address, char *remote_address)
{
VERBOSE (mapec, TRACE, PRINTF ("connect_tun\n"));
return -1;
}
- VERBOSE (mapec, INFO, PRINTF ("parse URL -> %s %s\n", device_name, ip_address));
+ VERBOSE (mapec, INFO, PRINTF ("parse URL -> %s %s %s\n", device_name, local_address, (remote_address) ? remote_address : ""));
/* link to named device */
struct ifreq ifr = { 0 };
/* set ip address */
mapec->addrin.sin_family = AF_INET;
mapec->addrin.sin_port = 0;
- mapec->addrin.sin_addr.s_addr = inet_addr (ip_address);
+ mapec->addrin.sin_addr.s_addr = inet_addr (local_address);
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", ip_address, device_name));
+ VERBOSE (mapec, ERROR, PRINTF ("can't set ip address '%s' on tun device '%s'\n", local_address, device_name));
return -1;
}
}
close (sock);
+ /* create route */
+ if (remote_address) {
+ struct rtentry route = {0};
+ struct sockaddr_in *addr = (struct sockaddr_in *) &route.rt_gateway;
+ addr->sin_family = AF_INET;
+ addr->sin_addr.s_addr = inet_addr (local_address);
+ addr = (struct sockaddr_in *) &route.rt_dst;
+ addr->sin_family = AF_INET;
+ addr->sin_addr.s_addr = inet_addr (remote_address);
+ addr = (struct sockaddr_in *) &route.rt_genmask;
+ addr->sin_family = AF_INET;
+ addr->sin_addr.s_addr = inet_addr ("255.255.255.0");
+ route.rt_flags = RTF_UP | RTF_GATEWAY;
+ route.rt_metric = 0;
+
+ sock = socket( PF_INET, SOCK_DGRAM, IPPROTO_IP);
+ if (sock < 0) {
+ VERBOSE (mapec, ERROR, PRINTF ("can't accept socket %d\n", sock));
+ errno = ENOMEM;
+ return -1;
+ }
+ if (ioctl (sock, SIOCADDRT, &route) < 0) {
+ VERBOSE (mapec, ERROR, PRINTF ("can't create route '%s'/24 via '%s'\n", remote_address, local_address));
+ return -1;
+ }
+ close (sock);
+ }
+
return fid;
}
-int MAPEC_Connect (char *arg1, char *arg2)
+int MAPEC_Connect (char *arg1, char *arg2, char *arg3)
{
VERBOSE (mapec, TRACE, PRINTF ("MAPEC_Connect\n"));
/* check type */
int rc = parse_protocol (&mapec.type, arg1);
- if (arg2) {
+ if ((rc > 0) && (arg2)) {
rc = parse_protocol (&mapec.type, arg2);
}
+ if ((rc > 0) && (arg3)) {
+ rc = parse_protocol (&mapec.type, arg3);
+ }
if (rc < 0) {
- VERBOSE (mapec, ERROR, PRINTF ("non coherent protocol '%s' <> '%s'\n", arg1, (arg2) ? arg2 : ""));
+ VERBOSE (mapec, ERROR, PRINTF ("non coherent protocol '%s' <> '%s' <> '%s'\n", arg1, (arg2) ? arg2 : "", (arg3) ? arg3 : ""));
errno = EINVAL;
return -1;
}
int fid;
switch (mapec.type) {
case MAPEC_udp_e:
- fid = connect_udp (&mapec, arg1 + rc, arg2 + rc);
+ fid = connect_udp (&mapec, arg1 + rc, (arg2) ? arg2 + rc : NULL);
break;
case MAPEC_tun_e:
- fid = connect_tun (&mapec, arg1 + rc, arg2 + rc);
+ fid = connect_tun (&mapec, arg1 + rc, (arg2) ? arg2 + rc : NULL, (arg3) ? arg3 + rc : NULL);
break;
default:
/**
@defgroup MAPEC Public API of MAPEC
- This library offers connections over UDP socket or TUN interface. In
- both case, communication is based on packet exchanges.
+ This library offers connections over UDP socket or TUN interface. In both
+ case, communication is based on packet exchanges.
- Values returned by MAPEC_Connect are standard Linux file descriptors
- that can be used in select()/poll() system calls.
+ Values returned by MAPEC_Connect are standard Linux file descriptors that
+ can be used in select()/poll() system calls.
*/
/**
@ingroup MAPEC
- Establish a connection between a local URL and a remote URL. Block
- until connection is established or refused.
+ Establish a connection between a local URL and a remote URL. Block until
+ connection is established or refused.
@param arg1 first argument
@param arg2 second argrument
+ @param arg3 third argrument
- For UDP connection, arguements are local and remote addresses. The
- syntax is 'udp://hostname:port'
- For TUN connection, first argument is an url, second argument is the
- IP address of the tun device. The syntax is tun://device and tun://ip
+ For UDP connection, arguements are local and remote addresses. The syntax is
+ 'udp://hostname:port'
+ For TUN connection, first argument is the device name, second argument is
+ the IP address of the tun device and third argument is the IP adresss of the
+ distant network. The syntax is tun://device, tun://ip, and tun://ip
@return a new file descriptor associated with this connection
@see MAPEC_Send()
@see MAPEC_Receive()
*/
-int MAPEC_Connect (char *arg1, char *arg2);
+int MAPEC_Connect (char *arg1, char *arg2, char *arg3);
/**
@ingroup MAPEC
unsigned char tx_data[10][1500];
int tx_len[10];
- int fid = MAPEC_Connect (client_local_url, client_remote_url);
+ int fid = MAPEC_Connect (client_local_url, client_remote_url, NULL);
if (fid < 0) {
VERBOSE (mapec, WARNING, PRINTF ("client MAPEC_Connect error\n"));
MAPEC_Echo_OK = 0;
VERBOSE (mapec, TRACE, PRINTF ("server\n"));
- int fid = MAPEC_Connect (server_local_url, server_remote_url);
+ int fid = MAPEC_Connect (server_local_url, server_remote_url, NULL);
if (fid < 0) {
VERBOSE (mapec, ERROR, PRINTF ("MAPEC_Connect (%d)\n", fid));
exit (1);
VERBOSE (mapec, ERROR, PRINTF ("missing an url (%s|%s)\n", comm->rxurl, comm->txurl));
return -1;
}
- comm->fid = MAPEC_Connect (comm->rxurl, comm->txurl);
+ comm->fid = MAPEC_Connect (comm->rxurl, comm->txurl, NULL);
if (comm->fid < 0) {
VERBOSE (mapec, ERROR, PRINTF ("can't open communication for %s %s %s\n", comm->serv, comm->rxurl, comm->txurl));
return -1;
/* get values */
char *tmp = line + offset;
TEST_CHARS (tmp, " \t", 0);
- if (strncmp (tmp, "PAYLOAD", 3) != 0) {
+ if (strncmp (tmp, "PAYLOAD", 6) != 0) {
VERBOSE (mapec, WARNING, PRINTF ("can't parse line '%s' (%s)\n", line, tmp));
continue;
}
int txlen = MAPEC_Send (comm->fid, payload, len);
/* check payload */
if (txlen != len) {
- VERBOSE (mapec, WARNING, PRINTF ("T%s: payloads differed %d/%d\n", comm->serv, len, txlen));
+ VERBOSE (mapec, WARNING, PRINTF ("T%s: payload not sent %d/%d\n", comm->serv, len, txlen));
} else {
- VERBOSE (mapec, INFO, PRINTF ("T%s: payloads matched [%d]\n", comm->serv, txlen));
+ VERBOSE (mapec, INFO, PRINTF ("T%s: payload sent [%d]\n", comm->serv, txlen));
}
if (log) {
/* check payload */
if ((rxlen != len) || ((memcmp (rxpayload, payload, rxlen) != 0))) {
- VERBOSE (mapec, WARNING, PRINTF ("R%s: payloads differed %d/%d\n", comm->serv, len, rxlen));
+ VERBOSE (mapec, WARNING, PRINTF ("R%s: payload differed %d/%d\n", comm->serv, len, rxlen));
} else {
- VERBOSE (mapec, INFO, PRINTF ("R%s: payloads matched [%d]\n", comm->serv, rxlen));
+ VERBOSE (mapec, INFO, PRINTF ("R%s: payload matched [%d]\n", comm->serv, rxlen));
}
if (log) {
/* test: mapec_valid.exe -r 2>&1 | grep 'receiver url not specified' */
/* test: mapec_valid.exe -s 2>&1 | grep 'service name not specified' */
/* test: mapec_valid.exe -t 2>&1 | grep 'transmitter url not specified' */
-/* test: mapec_valid.exe -v 2>&1 | grep 'verbose level url not specified' */
+/* test: mapec_valid.exe -v 2>&1 | grep 'verbose level not specified' */
/* test: mapec_valid.exe -s UDP o -r udp://localhost:1234 2>&1 | grep 'missing an url' */
/* test: echo | mapec_valid.exe -s UDP -r udp://localhost:1234 -t udp://localhost:1235 */
-/* test: mapec_valid.exe -s UDP -r udp://localhost:1234 -t udp://localhost:1235 script-udp.marep & mapec_valid.exe -n -s UDP -r udp://localhost:1234 -t udp://localhost:1235 script-udp.marep */
+/* test: mapec_valid.exe -n -s UDP -r udp://localhost:1234 -t udp://localhost:1235 script-udp.mapec & pid=$!; sleep 1; mapec_valid.exe -s UDP -r udp://localhost:1235 -t udp://localhost:1234 script-udp.mapec | awk '{print "<2>", $0}' */
/* test: mapec_valid.exe -s TUN0 -r tun://tun0 2>&1 | grep 'missing an url' */
/* test: echo | mapec_valid.exe -s TUN0 -r tun://tun0 -t tun://1.2.3.4 */
# Test script
TUDP PAYLOAD=@plaintext.txt
-RUDP PAYLOAD=@plaintext.txt
+SLEEP 1000
-TUDP PAYLAOD="This\ is\ a\ text"
-RUDP PAYLAOD="This\ is\ a\ text"
+TUDP PAYLOAD="This\ is\ a\ text"
+SLEEP 1000
-TUDP PAYLAOD=01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10
-RUDP PAYLAOD=01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10
+TUDP PAYLOAD=01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10
+SLEEP 1000
char *devtun = "tun://tun0";
char *loctun = "tun://10.2.0.1";
-char *remtun = "tun://10.2.0.2";
+char *remtun = "tun://10.2.1.0";
char *locudp = "udp://10.1.0.1:1234";
char *remudp = "udp://10.1.0.2:1235";
case 'r':
arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
if (arg == NULL) {
- VERBOSE (ulvpn, ERROR, PRINTF ("%s: remove tun not specified\n", progname));
+ VERBOSE (ulvpn, ERROR, PRINTF ("%s: remote tun not specified\n", progname));
return 1;
}
remtun = arg;
case 'u':
arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
if (arg == NULL) {
- VERBOSE (ulvpn, ERROR, PRINTF ("%s: remove udp not specified\n", progname));
+ VERBOSE (ulvpn, ERROR, PRINTF ("%s: remote udp not specified\n", progname));
return 1;
}
remudp = arg;
}
/* init communication channel */
- int tun_fd = MAPEC_Connect (devtun, loctun);
+ int tun_fd = MAPEC_Connect (devtun, loctun, remtun);
if (tun_fd < 0) {
- VERBOSE (ulvpn, ERROR, PRINTF ("can't open communication for %s %s\n", devtun, loctun));
+ VERBOSE (ulvpn, ERROR, PRINTF ("can't open communication for %s %s %s\n", devtun, loctun, remtun));
return -1;
}
- int udp_fd = MAPEC_Connect (locudp, remudp);
+ int udp_fd = MAPEC_Connect (locudp, remudp, NULL);
if (udp_fd < 0) {
VERBOSE (ulvpn, ERROR, PRINTF ("can't open communication for %s %s\n", locudp, remudp));
return -1;
return rc;
}
-/* test: mapec_valid.exe -h | grep usage */
-/* test: mapec_valid.exe -l 2>&1 | grep 'log file not specified' */
+/* test: ulvpn.exe -h | 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 -t 2>&1 | grep 'local udp 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 -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 */
/* vim: set ts=4 sw=4 si et: */
if $(ip add list dev enp0s4 | fgrep -q 10.1.0.2/); then
title Remote
- {
- sleep 1
- ip addr add 10.3.0.1/24 dev enp0s3
- ip route add 10.4.0.0/24 dev tun0
- title "ready"
- } &
$VPN -v 5 \
-d tun://tun0 \
- -r tun://10.2.0.1 -l tun://10.2.0.2 \
+ -l tun://10.2.1.1 -r tun://10.2.0.0 \
-u udp://10.1.0.1:1234 -t udp://10.1.0.2:1235
else
title Local
- {
- sleep 1
- ip addr add 10.4.0.1/24 dev enp0s3
- ip route add 10.3.0.0/24 dev tun0
- title "ready"
- } &
$VPN -v 5 \
-d tun://tun0 \
- -l tun://10.2.0.1 -r tun://10.2.0.2 \
+ -l tun://10.2.0.1 -r tun://10.2.1.0 \
-t udp://10.1.0.1:1234 -u udp://10.1.0.2:1235
fi