-
-
Save danielinux/d1e92978356c4727bbf0a4a555a46232 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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