Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <net/if.h>
- #include <linux/if_tun.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/ioctl.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <arpa/inet.h>
- #include <sys/select.h>
- #include <sys/time.h>
- #include <errno.h>
- #include <stdarg.h>
- #include <netinet/ip.h>
- #include <netinet/ip6.h>
- /* for IPPROTO_XXX definitions */
- #include <netinet/in.h>
- /* for TCP header */
- #include <netinet/tcp.h>
- /* for UDP header */
- #include <netinet/udp.h>
- /* the code snippet below is taken "as is" from the openvpn project, file src/openvpn/proto.h
- /* it's used to correct internet checksums for IP, TCP and UDP headers after IP header modifications
- /*
- * The following macro is used to update an
- * internet checksum. "acc" is a 32-bit
- * accumulation of all the changes to the
- * checksum (adding in old 16-bit words and
- * subtracting out new words), and "cksum"
- * is the checksum value to be updated.
- */
- #define ADJUST_CHECKSUM(acc, cksum) { \
- int _acc = acc; \
- _acc += (cksum); \
- if (_acc < 0) { \
- _acc = -_acc; \
- _acc = (_acc >> 16) + (_acc & 0xffff); \
- _acc += _acc >> 16; \
- (cksum) = (uint16_t) ~_acc; \
- } else { \
- _acc = (_acc >> 16) + (_acc & 0xffff); \
- _acc += _acc >> 16; \
- (cksum) = (uint16_t) _acc; \
- } \
- }
- #define ADD_CHECKSUM_32(acc, u32) { \
- acc += (u32) & 0xffff; \
- acc += (u32) >> 16; \
- }
- #define SUB_CHECKSUM_32(acc, u32) { \
- acc -= (u32) & 0xffff; \
- acc -= (u32) >> 16; \
- }
- /* buffer for reading from tun/tap interface, must be >= 1500 */
- #define BUFSIZE 2000
- int tun_alloc(char *dev)
- {
- struct ifreq ifr;
- int fd, err;
- if (!dev) {
- return -1;
- }
- memset(&ifr, 0, sizeof(ifr));
- /* Flags: IFF_TUN - TUN device (no Ethernet headers)
- * IFF_TAP - TAP device
- *
- * IFF_NO_PI - Do not provide packet information
- * IFF_MULTI_QUEUE - Create a queue of multiqueue device
- */
- ifr.ifr_flags = IFF_TUN;
- strcpy(ifr.ifr_name, dev);
- if ((fd = open("/dev/net/tun", O_RDWR)) < 0)
- return fd;
- err = ioctl(fd, TUNSETIFF, (void *)&ifr);
- if (err) {
- close(fd);
- goto err;
- }
- strcpy(dev, ifr.ifr_name);
- return fd;
- err:
- close(fd);
- return err;
- }
- static int set_if_flags(char *ifname, short flags)
- {
- struct ifreq ifr;
- int res = 0;
- ifr.ifr_flags = flags;
- strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
- int skfd = socket (AF_INET, SOCK_RAW, IPPROTO_RAW);
- res = ioctl(skfd, SIOCSIFFLAGS, &ifr);
- if (res < 0) {
- puts("Interface '%s': Error: SIOCSIFFLAGS failed: %s\n");
- } else {
- puts("Interface '%s': flags set to %04X.\n");
- }
- return res;
- }
- int main() {
- char *tun_name;
- tun_name = malloc(IFNAMSIZ);
- tun_name[0] = '\0';
- int tun_fd = tun_alloc(tun_name);
- if (tun_fd < 0) {
- puts("Try as root");
- exit(1);
- }
- if (ioctl(tun_fd, TUNSETPERSIST, 0) < 0) {
- perror("disabling TUNSETPERSIST");
- exit(1);
- }
- printf("Set interface '%s' nonpersistent\n", tun_name);
- set_if_flags(tun_name, IFF_UP);
- /* For now just hardcode the source and replacement IP addresses */
- struct in_addr tun_ip_input, tun_ip_output;
- if (!inet_aton("10.0.0.1", &tun_ip_input) || !inet_aton("10.0.0.2", &tun_ip_output)) {
- printf("inet_aton() failed!\n");
- exit(1);
- }
- struct layer3_frame
- {
- uint16_t flags; // FLAGS from TUN
- uint16_t proto; // PRPTO from TUN
- unsigned char payload[]; // FRAME/PACKET
- } __attribute__((packed));
- int nread;
- char buffer[BUFSIZE];
- while(1) {
- nread = read(tun_fd, buffer, sizeof(buffer));
- if(nread < 0) {
- perror("Reading from interface");
- close(tun_fd);
- exit(1);
- }
- /* Do whatever with the data */
- printf("Read %d bytes from device %s\n", nread, tun_name);
- struct layer3_frame* l3p = (struct layer3_frame*)(buffer);
- printf("FLAGS %x, PROTO %x\n", l3p->flags, ntohs(l3p->proto));
- int ethertype = ntohs(l3p->proto);
- int ipv = 4;
- if (ethertype == 0x800) {
- ipv = 4;
- } else if (ethertype == 0x86DD) {
- ipv = 6;
- } else {
- printf("Unknown ethertype %x", ethertype);
- exit(1);
- }
- if (ipv == 4) {
- puts("PARSING V4!");
- struct ip* ippacket = (struct ip*)(l3p->payload);
- printf("VER:%d\n", ippacket->ip_v);
- struct in_addr ip_dst = ippacket->ip_dst;
- struct sockaddr_in sin;
- sin.sin_family = AF_INET;
- sin.sin_addr = ip_dst;
- printf("The source IP address is %s\n", inet_ntoa(ippacket->ip_src));
- printf("The destination IP address is %s\n", inet_ntoa(ippacket->ip_dst));
- /* Switch IP addresses */
- int accumulate = 0;
- if (ippacket->ip_src.s_addr == tun_ip_input.s_addr) {
- /* pre-adjust IP checksum */
- ADD_CHECKSUM_32(accumulate, ippacket->ip_src.s_addr);
- /* change source IP */
- ippacket->ip_src = tun_ip_output;
- /* post-adjust IP checksum */
- SUB_CHECKSUM_32(accumulate, ippacket->ip_src.s_addr);
- }
- else if (ippacket->ip_dst.s_addr == tun_ip_output.s_addr) {
- /* pre-adjust IP checksum */
- ADD_CHECKSUM_32(accumulate, ippacket->ip_dst.s_addr);
- /* change destination IP */
- ippacket->ip_dst = tun_ip_input;
- /* post-adjust IP checksum */
- SUB_CHECKSUM_32(accumulate, ippacket->ip_dst.s_addr);
- }
- printf("New source IP address is %s\n", inet_ntoa(ippacket->ip_src));
- printf("New destination IP address is %s\n", inet_ntoa(ippacket->ip_dst));
- /* Correct packet checksums */
- ADJUST_CHECKSUM(accumulate, ippacket->ip_sum);
- if (ippacket->ip_p == IPPROTO_TCP &&
- nread >= sizeof(struct layer3_frame) + sizeof(struct ip) + sizeof(struct tcphdr)) {
- struct tcphdr* tcp_hdr = (struct tcphdr*)(l3p->payload + sizeof(struct ip));
- ADJUST_CHECKSUM(accumulate, tcp_hdr->check);
- }
- else if (ippacket->ip_p == IPPROTO_UDP &&
- nread >= sizeof(struct layer3_frame) + sizeof(struct ip) + sizeof(struct udphdr)) {
- struct udphdr* udp_hdr = (struct udphdr*)(l3p->payload + sizeof(struct ip));
- ADJUST_CHECKSUM(accumulate, udp_hdr->check);
- }
- /*
- int s = socket (AF_INET, SOCK_RAW, IPPROTO_RAW);
- int code = sendto (s, ippacket, nread, 0, (struct sockaddr*)&sin, sizeof (sin));
- if (code < 0) {
- perror("Failed to send");
- } else {
- puts("Sent IPV4");
- }
- */
- } else if (ipv == 6) {
- puts("PARSING V6!");
- const struct ip6_hdr* ippacket = (struct ip6_hdr*)(l3p->payload);
- struct in6_addr ip_dst = ippacket->ip6_dst;
- static struct sockaddr_in6 remote;
- remote.sin6_family= AF_INET;
- remote.sin6_addr = ip_dst;
- /*
- int s = socket (AF_INET, SOCK_RAW, IPPROTO_RAW);
- int code = sendto (s, ippacket, nread, 0, (struct sockaddr*)&remote, sizeof (remote));
- if (code < 0) {
- perror("Failed to send");
- } else {
- puts("Sent IPV6");
- }
- */
- }
- write(tun_fd, buffer, nread);
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement