Skip to content

Instantly share code, notes, and snippets.

@danielinux
Created February 23, 2018 08:26
Show Gist options
  • Save danielinux/d1e92978356c4727bbf0a4a555a46232 to your computer and use it in GitHub Desktop.
Save danielinux/d1e92978356c4727bbf0a4a555a46232 to your computer and use it in GitHub Desktop.
/* vn.c generic virtual network client/server
* via UDP
* Author: Daniele Lacamera
* License MIT
*/
#include <sys/socket.h>
#include <sys/types.h>
#include <linux/if_tun.h>
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <stdlib.h>
#include <netinet/ip.h>
#include <fcntl.h>
#include <poll.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <string.h>
#include <sys/poll.h>
#include <arpa/inet.h>
#define MTU 1500
uint8_t buf[MTU];
int main(int argc, char *argv[])
{
int sd = socket(AF_INET, SOCK_DGRAM, 0);
int td = open("/dev/net/tun", O_RDWR);
struct sockaddr_in saddr = { }, daddr = { };
struct ifreq ifr;
socklen_t sl = sizeof(struct sockaddr_in);
int r;
struct pollfd pfd[2];
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
strncpy(ifr.ifr_name, "vn0", IFNAMSIZ);
if(ioctl(td, TUNSETIFF, &ifr) < 0) {
perror("ioctl");
exit(3);
}
if (argc == 1) {
printf("Running as server\n");
} else if (argc == 2) {
printf("Running as client\n");
daddr.sin_family = AF_INET;
daddr.sin_port = ntohs(12122);
daddr.sin_addr.s_addr = inet_addr(argv[1]);
} else {
printf("Too many arguments.\n");
exit(1);
}
saddr.sin_port = ntohs(12122);
if (sd < 0) {
perror("socket");
exit(1);
}
if (bind(sd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)) < 0) {
perror("bind");
exit(2);
}
while (1) {
pfd[0].fd = sd;
pfd[1].fd = td;
pfd[0].events = POLLIN;
pfd[1].events = POLLIN;
r = poll(pfd, 2, -1);
if (r > 0) {
if ((pfd[0].revents & POLLIN) == POLLIN) {
r = recvfrom(sd, buf, MTU, 0, (struct sockaddr *)&daddr, &sl);
if (r > 0) {
printf("> %d\n", r);
write(td, buf, r);
}
}
if ((pfd[1].revents & POLLIN) == POLLIN) {
r = read(td, buf, MTU);
if ((r > 0) && (daddr.sin_addr.s_addr != 0)) {
printf("< %d\n", r);
sendto(sd, buf, r, 0, (struct sockaddr *)&daddr, sizeof(struct sockaddr_in));
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment