예제 #1
0
int handle_create_tap()
{
	char name[CINDER_MAX_NAMELEN], id[12];
	char *retstr;
	unsigned int len;
	int ret, srcReserve, destReserve;

	printf("Please enter the name for the tap: ");
	retstr = fgets(name, sizeof(name), stdin);
	if (!retstr) {
		printf("Error reading name.\n");
		return -EINVAL;
	}
	name[CINDER_MAX_NAMELEN - 1] = 0;
	chomp(name);
	len = strlen(name) + 1;

	memset(id, 0, sizeof(id));
	printf("Please enter the source reserve id.\n");
	retstr = fgets(id, sizeof(id), stdin);
	if (!retstr) {
		printf("Error reading id.\n");
		return -EINVAL;
	}
	srcReserve = atoi(id);
	
	memset(id, 0, sizeof(id));
	printf("Please enter the destination reserve id.\n");
	retstr = fgets(id, sizeof(id), stdin);
	if (!retstr) {
		printf("Error reading id.\n");
		return -EINVAL;
	}
	destReserve = atoi(id);

	ret = create_tap(name, len, srcReserve, destReserve);

	if (ret < 0) {
		printf("Error creating tap: %d\n", ret);
	}
	else
		printf("Created tap with id %d\n", ret);

	return ret;
}
예제 #2
0
int main(int argc, char *argv[])
{
	const char *ifname = "xxx";
	struct pollfd p;
	int fd;

	fd = create_tap(ifname);
	if (fd < 0)
		return 1;

	if (inet_ifup(ifname) < 0) {
		close(fd);
		return 1;
	}

	memset(&p, 0, sizeof(p));
	p.fd = fd;
	p.events = POLLHUP | POLLIN;

	while (1) {
		unsigned char buf[2048];
		int len;

		len = poll(&p, 1, -1);
		if (len < 0)
			break;
		if (len == 0)
			continue;

		len = read(fd, buf, sizeof(buf));
		if (len < 0)
			break;

		decode_packet(buf, len);
	}

	return 0;
}
예제 #3
0
파일: tap2tap.c 프로젝트: Yuanyiis/tap2tap
int run_tunnel(struct args *args, sigset_t *orig_mask) {
    char device[IFNAMSIZ];
    int fd = create_tap(args->iface, device, args->mtu);
    if (fd < 0) {
        fprintf(stderr, "unable to create tap device\n");
        return 1;
    }
    printf("tap device is: %s\n", device);

    if (args->up_script) {
        int ret = run_updown(args->up_script, device);
        if (ret != 0) {
            fprintf(stderr, "up script exited with status: %d\n", ret);
            return 1;
        }
    }

    // TODO: make the port and bind address configurable
    int sockfd = setup_socket(inet_addr("0.0.0.0"), 1234);
    if (sockfd < 0) {
        fprintf(stderr, "unable to create socket\n");
        return 1;
    }

    if (drop_privileges(args->uid, args->gid) != 0) {
        fprintf(stderr, "couldn't drop privileges\n");
        return 1;
    }

    // circular queues
    struct frame recv_queue[RECV_QUEUE] = {0};
    size_t recv_idx = 0;
    size_t recv_len = 0;

    struct frame send_queue[SEND_QUEUE] = {0};
    size_t send_idx = 0;
    size_t send_len = 0;

    struct timespec tm;
    memset(&tm, 0, sizeof tm);
    tm.tv_nsec = 10000000;  // 0.01 seconds

    struct pollfd fds[2];
    memset(&fds, 0, sizeof fds);
    fds[0].fd = fd;
    fds[1].fd = sockfd;

    struct sockaddr_in remote;
    memset(&remote, 0, sizeof remote);
    char has_remote = 0;

    if (args->remote) {
        remote.sin_family = AF_INET;
        remote.sin_port = htons(1234);
        has_remote = 1;

        remote.sin_addr.s_addr = inet_addr(args->remote);
        if (remote.sin_addr.s_addr == INADDR_NONE) {
            fprintf(stderr, "failed to parse remote: %s\n", args->remote);
            return 2;
        }
        fprintf(stderr, "running in client mode with remote: %s\n", args->remote);
    }


    fprintf(stderr, "tunnel is up\n");
    for (;;) {
        fds[0].events = POLLIN;
        if (recv_len > 0) {
            fds[0].events |= POLLOUT;
        }

        fds[1].events = POLLIN;
        if (send_len > 0 && has_remote) {
            fds[1].events |= POLLOUT;
        }

        int result = ppoll(fds, 2, &tm, orig_mask);
        if (result < 0) {
            if (errno != EINTR) {
                perror("ppoll");
                return 3;
            }
        }

        if (exit_wanted) {
            fprintf(stderr, "\nreceived signal %d, stopping tunnel\n", received_signal);
            break;
        }

        // tap can handle a write
        if (fds[0].revents & POLLOUT) {
            struct frame *f = &recv_queue[recv_idx];
            assert(f->len <= args->mtu + ETHERNET_HEADER);
            recv_idx = (recv_idx + 1) % RECV_QUEUE;
            recv_len -= 1;

            ssize_t n = write(fd, f->data, f->len);
            if (n < 0) {
                if (errno == EINVAL) {
                    fprintf(stderr, "received garbage frame\n");
                } else {
                    perror("write");
                    return 4;
                }
            } else if (n < f->len) {
                printf("[error] only wrote %zd bytes to tap (out of %zd bytes)\n", n, f->len);
            }
        }

        // udp socket can handle a write
        if (fds[1].revents & POLLOUT) {
            struct frame *f = &send_queue[send_idx];
            assert(f->len <= args->mtu + ETHERNET_HEADER);
            send_idx = (send_idx + 1) % SEND_QUEUE;
            send_len -= 1;

            ssize_t n = sendto(sockfd, f->data, f->len, 0, (struct sockaddr *) &remote, sizeof remote);
            if (n < 0) {
                perror("sendto");
                return 4;
            } else if (n < f->len) {
                printf("[error] only sent %zd bytes to peer (out of %zd bytes)\n", n, f->len);
            }
        }

        // tap has data for us to read
        if (fds[0].revents & POLLIN) {
            size_t idx = (send_idx + send_len) % SEND_QUEUE;

            if (send_len < SEND_QUEUE) {
                send_len += 1;
            } else {
                assert(send_len == SEND_QUEUE);
                printf("dropping frame from send queue\n");

                // put this packet at the end of the queue;
                // drop the first frame in the queue
                send_idx += 1;
            }

            struct frame *f = &send_queue[idx];
            memset(f, 0, sizeof(struct frame));
            ssize_t n = read(fd, &f->data, args->mtu + ETHERNET_HEADER);
            f->len = n;
        }

        // udp socket has data for us to read
        if (fds[1].revents & POLLIN) {
            size_t idx = (recv_idx + recv_len) % RECV_QUEUE;

            if (recv_len < RECV_QUEUE) {
                recv_len += 1;
            } else {
                assert(recv_len == RECV_QUEUE);
                printf("dropping frame from recv queue\n");

                // put this packet at the end of the queue;
                // drop the first frame in the queue
                recv_idx += 1;
            }

            struct frame *f = &recv_queue[idx];
            memset(f, 0, sizeof(struct frame));

            // TODO: handle case where remote changes, in both server+client mode
            socklen_t l = sizeof(remote);
            has_remote = 1;
            ssize_t n = recvfrom(
                sockfd,
                &f->data,
                args->mtu + ETHERNET_HEADER,
                0,
                (struct sockaddr *) &remote,
                &l
            );
            f->len = n;
        }
    }

    if (args->down_script) {
        int ret = run_updown(args->down_script, device);
        if (ret != 0) {
            fprintf(stderr, "down script exited with status: %d\n", ret);
            return 1;
        }
    }

    return 0;
}