static void test_atreadeof(abts_case *tc, void *data) { apr_status_t rv; apr_socket_t *sock; apr_socket_t *sock2; apr_proc_t proc; apr_size_t length = STRLEN; char datastr[STRLEN]; int atreadeof = -1; sock = setup_socket(tc); if (!sock) return; launch_child(tc, &proc, "write", p); rv = apr_socket_accept(&sock2, sock, p); APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv); /* Check that the remote socket is still open */ rv = apr_socket_atreadeof(sock2, &atreadeof); APR_ASSERT_SUCCESS(tc, "Determine whether at EOF, #1", rv); ABTS_INT_EQUAL(tc, 0, atreadeof); memset(datastr, 0, STRLEN); apr_socket_recv(sock2, datastr, &length); /* Make sure that the server received the data we sent */ ABTS_STR_EQUAL(tc, DATASTR, datastr); ABTS_SIZE_EQUAL(tc, strlen(datastr), wait_child(tc, &proc)); /* The child is dead, so should be the remote socket */ rv = apr_socket_atreadeof(sock2, &atreadeof); APR_ASSERT_SUCCESS(tc, "Determine whether at EOF, #2", rv); ABTS_INT_EQUAL(tc, 1, atreadeof); rv = apr_socket_close(sock2); APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv); launch_child(tc, &proc, "close", p); rv = apr_socket_accept(&sock2, sock, p); APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv); /* The child closed the socket as soon as it could... */ rv = apr_socket_atreadeof(sock2, &atreadeof); APR_ASSERT_SUCCESS(tc, "Determine whether at EOF, #3", rv); if (!atreadeof) { /* ... but perhaps not yet; wait a moment */ apr_sleep(apr_time_from_msec(5)); rv = apr_socket_atreadeof(sock2, &atreadeof); APR_ASSERT_SUCCESS(tc, "Determine whether at EOF, #4", rv); } ABTS_INT_EQUAL(tc, 1, atreadeof); wait_child(tc, &proc); rv = apr_socket_close(sock2); APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv); rv = apr_socket_close(sock); APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv); }
static void test_timeout(abts_case *tc, void *data) { apr_status_t rv; apr_socket_t *sock; apr_socket_t *sock2; apr_proc_t proc; int protocol; int exit; sock = setup_socket(tc); if (!sock) return; launch_child(tc, &proc, "read", p); rv = apr_socket_accept(&sock2, sock, p); APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv); apr_socket_protocol_get(sock2, &protocol); ABTS_INT_EQUAL(tc, APR_PROTO_TCP, protocol); exit = wait_child(tc, &proc); ABTS_INT_EQUAL(tc, SOCKET_TIMEOUT, exit); /* We didn't write any data, so make sure the child program returns * an error. */ rv = apr_socket_close(sock2); APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv); rv = apr_socket_close(sock); APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv); }
static void test_recv(abts_case *tc, void *data) { apr_status_t rv; apr_socket_t *sock; apr_socket_t *sock2; apr_proc_t proc; int protocol; apr_size_t length = STRLEN; char datastr[STRLEN]; sock = setup_socket(tc); if (!sock) return; launch_child(tc, &proc, "write", p); rv = apr_socket_accept(&sock2, sock, p); APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv); apr_socket_protocol_get(sock2, &protocol); ABTS_INT_EQUAL(tc, APR_PROTO_TCP, protocol); memset(datastr, 0, STRLEN); apr_socket_recv(sock2, datastr, &length); /* Make sure that the server received the data we sent */ ABTS_STR_EQUAL(tc, DATASTR, datastr); ABTS_SIZE_EQUAL(tc, strlen(datastr), wait_child(tc, &proc)); rv = apr_socket_close(sock2); APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv); rv = apr_socket_close(sock); APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv); }
static void test_send(abts_case *tc, void *data) { apr_status_t rv; apr_socket_t *sock; apr_socket_t *sock2; apr_proc_t proc; int protocol; apr_size_t length; sock = setup_socket(tc); if (!sock) return; launch_child(tc, &proc, "read", p); rv = apr_socket_accept(&sock2, sock, p); APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv); apr_socket_protocol_get(sock2, &protocol); ABTS_INT_EQUAL(tc, APR_PROTO_TCP, protocol); length = strlen(DATASTR); apr_socket_send(sock2, DATASTR, &length); /* Make sure that the client received the data we sent */ ABTS_SIZE_EQUAL(tc, strlen(DATASTR), wait_child(tc, &proc)); rv = apr_socket_close(sock2); APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv); rv = apr_socket_close(sock); APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv); }
bool setup_udp_handle (xmmsc_result_t *res) { bool ret; xmmsc_vis_udp_t *t; xmmsc_visualization_t *visc; visc = xmmsc_result_visc_get (res); if (!visc) { x_api_error_if (1, "non vis result?", -1); } t = &visc->transport.udp; if (!xmmsc_result_iserror (res)) { xmmsv_t *val; int port; val = xmmsc_result_get_value (res); xmmsv_get_int (val, &port); ret = setup_socket (xmmsc_result_get_connection (res), t, visc->id, port); } else { ret = false; } return ret; }
TcpServer::TcpServer(unsigned short port) : m_port(port) { setup_socket(); m_highest_socket = m_socket_number; FD_SET(m_socket_number, &m_server_set); }
/* Main */ int main( int argc, char *argv[] ) { init_node( argc, argv ); //rt_args_t args; printf( "I am node %lu and I listen on port %d for new users\n", curr_nodeID, curr_node_config_entry->irc_port ); setup_socket(); return 0; }
int main() { struct epoll_event ev; struct epoll_event events[MAX_EVENTS]; char buffer[1024]; if ((epfd = epoll_create(MAX_EVENTS)) < 0) { die("epoll_create"); } listener = setup_socket(); memset(&ev, 0, sizeof ev); ev.events = EPOLLIN; ev.data.fd = listener; epoll_ctl(epfd, EPOLL_CTL_ADD, listener, &ev); for (;;) { int i; int nfd = epoll_wait(epfd, events, MAX_EVENTS, -1); for (i = 0; i < nfd; i++) { if (events[i].data.fd == listener) { struct sockaddr_in client_addr; socklen_t client_addr_len = sizeof client_addr; int client = accept(listener, (struct sockaddr *) &client_addr, &client_addr_len); if (client < 0) { perror("accept"); continue; } setnonblocking(client); memset(&ev, 0, sizeof ev); ev.events = EPOLLIN | EPOLLET; ev.data.fd = client; epoll_ctl(epfd, EPOLL_CTL_ADD, client, &ev); } else { int client = events[i].data.fd; int n = read(client, buffer, sizeof buffer); if (n < 0) { perror("read"); epoll_ctl(epfd, EPOLL_CTL_DEL, client, &ev); close(client); } else if (n == 0) { epoll_ctl(epfd, EPOLL_CTL_DEL, client, &ev); close(client); } else { write(client, buffer, n); } } } } return 0; }
static void test_create_bind_listen(abts_case *tc, void *data) { apr_status_t rv; apr_socket_t *sock = setup_socket(tc); if (!sock) return; rv = apr_socket_close(sock); APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv); }
int main(int argc, char **argv) { int nchildren = 1; char *socket_url = NULL; int c; while ((c = getopt(argc, argv, "c:hfs:")) != -1) { switch (c) { case 'f': stderr_to_fastcgi++; break; case 'h': printf("Usage: %s [OPTION]\nInvokes CGI scripts as FCGI.\n\n" PACKAGE_NAME" version "PACKAGE_VERSION"\n\n" "Options are:\n" " -c <number>\t\tNumber of processes to prefork\n" " -s <socket_url>\tSocket to bind to (say -s help for help)\n" " -h\t\t\tShow this help message and exit\n" "\nReport bugs to Grzegorz Nosek <"PACKAGE_BUGREPORT">.\n" PACKAGE_NAME" home page: <http://nginx.localdomain.pl/wiki/FcgiWrap>\n", argv[0] ); return 0; case 'c': nchildren = atoi(optarg); break; case 's': socket_url = strdup(optarg); break; case '?': if (optopt == 'c' || optopt == 's') fprintf(stderr, "Option -%c requires an argument.\n", optopt); else if (isprint(optopt)) fprintf(stderr, "Unknown option `-%c'.\n", optopt); else fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt); return 1; default: abort(); } } if (socket_url) { if (setup_socket(socket_url) < 0) { return 1; } free(socket_url); } prefork(nchildren); fcgiwrap_main(); return 0; }
int setup_and_bind(int * socket_fd, struct sockaddr_in * server_addr, int * len){ setup_socket(socket_fd); *len = sizeof(struct sockaddr_in); server_addr->sin_family = AF_INET; server_addr->sin_port = htons(PORT_IN); server_addr->sin_addr.s_addr = INADDR_ANY; int bind_err = bind(*socket_fd, (struct sockaddr *) server_addr, *len); if(bind_err < 0){ perror("Error binding socket"); exit(1); } }
/** * Initialize a SSDP listener. This parses and sets the forwarder address, * creates a socket and sets all applicable configuration values to it. * * @param listener The listener to initialize. * @param conf The configuration to use. * @param active TRUE if an active SSDP listener is to be initialized. * @param port The port to listen on. 0 will set the port to the SSDP port. * @param recv_timeout The timeout to set for receiveing/waiting for SSDP * nodes to respond to a SEARCH query. * * @return 0 on success, errno otherwise. */ static int ssdp_listener_init(ssdp_listener_s *listener, configuration_s *conf, BOOL is_active, int port, int recv_timeout) { PRINT_DEBUG("ssdp_listener_init()"); SOCKET sock = SOCKET_ERROR; if (!listener) { PRINT_ERROR("No listener specified"); return 1; } memset(listener, 0, sizeof *listener); /* If set, parse the forwarder address */ if (conf->forward_address) { if (parse_address(conf->forward_address, &listener->forwarder)) { PRINT_WARN("Errnoeous forward address"); return 1; } } int listen_queue_len = is_active ? ACTIVE_LISTEN_QUEUE_LENGTH : PASSIVE_LISTEN_QUEUE_LENGTH; socket_conf_s sock_conf = { conf->use_ipv6, // BOOL is_ipv6 TRUE, // BOOL is_udp is_active, // BOOL is_multicast conf->interface, // char interface conf->ip, // the IP we want to bind to NULL, // struct sockaddr_storage *sa SSDP_ADDR, // The IP we wnat to send to port, // The port we want to send to (?) TRUE, // BOOL is_server listen_queue_len, // the length of the listen queue FALSE, // BOOL keepalive conf->ttl, // time to live (router hops) conf->enable_loopback,// see own messages on multicast 0, // set the send timeout for the socket (0 = default) recv_timeout // set the receive timeout for the socket }; sock = setup_socket(&sock_conf); if (sock == SOCKET_ERROR) { PRINT_DEBUG("[%d] %s", errno, strerror(errno)); return errno; } listener->sock = sock; PRINT_DEBUG("ssdp_listener has been initialized"); return 0; }
int main (int argc, char **argv) { int listen_fd = setup_socket("127.0.0.1", 8080); if (listen_fd < 0) { return 1; } log_write (0, "listen_fd: %d\n", listen_fd); event_init(); struct event *accept_ev = setup_accept_event(listen_fd); event_dispatch(); return 0; }
int serve_http(char* port) { // Info about the client's address struct sockaddr_storage clientaddr; socklen_t addr_size; struct sigaction sa; struct addrinfo *servinfo = NULL; // Gonna fill this out with getaddrinfo int sockdesc, newsock; ROOT = getenv("PWD"); sockdesc = setup_socket(port, servinfo); freeaddrinfo(servinfo); // Free the addrinfo struct sa.sa_handler = sig_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; if (sigaction(SIGCHLD, &sa, NULL) == -1) { perror("listen"); return 1; } printf("Server listening on port %s...\n", port); for (;;) { listen(sockdesc, BACKLOG); addr_size = sizeof(clientaddr); newsock = accept(sockdesc, ((struct sockaddr *) &clientaddr), &addr_size); if (newsock == -1) { perror("accept"); return 1; } if (!fork()) { close(sockdesc); respond(newsock); close(newsock); exit(0); } close(newsock); } close(sockdesc); return 0; }
int main(int argc, char ** argv) { if (argc == 1 || argc > 3) { print_usage(); printf("Error: invalid number of parameters!\n"); exit(1); } else if (argc == 3) { serverName = argv[2]; // get UDP server's IP address } platName = argv[1]; // get mote platform's name open_input(); if (serverName != NULL) setup_socket(); while(1){ read_forward(); } }
void jdk_inet_client_socket::force_connection( jdk_socket_handle fd ) { close(); sock_id=fd; if( sock_id!=JDK_SOCKET_ERROR ) { readable=true; writable=true; // set socket options for the socket setup_socket(); } }
int create_server_socket() { // The socket on which the server receives // all incoming connections int server_socket; if ((server_socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { throw("Error opening server-socket on server-side"); } setup_socket(server_socket); // server_once(NOTIFY); return server_socket; }
/* Connect the daemon, and return a socketfd */ int connect_daemon() { struct sockaddr_un sun; int fd = setup_socket(&sun); if (connect(fd, (struct sockaddr*) &sun, sizeof(sun))) { /* If we cannot access the daemon, we start the daemon * since there is no clear entry point when the daemon should be started */ LOGD("client: connect fail, try launching new daemon process\n"); start_daemon(fd); do { // Wait for 10ms usleep(10); } while (connect(fd, (struct sockaddr*) &sun, sizeof(sun))); } return fd; }
int create_socket (int *err) { int fd = socket (PF_INET, SOCK_STREAM, 0); if (fd < 0) { *err = errno; return -1; } if (!setup_socket (fd)) { *err = errno; close (fd); return -1; } return fd; }
int manos_socket_accept (int fd, manos_socket_info_t *info, int *err) { struct sockaddr_storage addr; socklen_t len = sizeof (struct sockaddr_storage); int res; res = accept (fd, (struct sockaddr *) &addr, &len); if (res < 0) { if (errno == EAGAIN || errno == ECONNABORTED) { *err = 0; return -1; } *err = errno; return -1; } if (!setup_socket (res)) { *err = errno; close (res); return -1; } info->fd = res; struct sockaddr_in *in4; struct sockaddr_in6 *in6; switch (addr.ss_family) { case AF_INET: in4 = (struct sockaddr_in *) &addr; info->port = ntohs (in4->sin_port); info->addr1 = in4->sin_addr.s_addr; info->addr2 = 0; break; case AF_INET6: in6 = (struct sockaddr_in6 *) &addr; info->port = ntohs (in6->sin6_port); break; } return res; }
int main() { int ret; common_data_t common_data; pthread_t recv_tid; pthread_t write_tid; queue_init(&common_data); ret = init_audio_device(&common_data); if(ret == -1){ dbg("init audio device error.\n"); exit(1); } ret = setup_socket(&common_data); if(ret == -1){ dbg("setup socket error.\n"); return 0; } /* create two threads: socket recv thread and pcm write thread */ ret = pthread_create(&recv_tid, NULL, recv_pcmdata, (void *)&common_data); if (0 != ret){ dbg("can't create recv_pcmdata thread\n"); } ret = pthread_create(&write_tid, NULL, write_pcmdata, (void *)&common_data); if (0 != ret){ dbg("can't create write_thread\n"); } pthread_join(recv_tid, NULL); // pthread_join(write_tid, NULL); close(common_data.client_socket); close(common_data.server_socket); //free(g_buf); snd_pcm_drain(common_data.handle); snd_pcm_close(common_data.handle); return 0; }
int main(int argc, char **argv) { state_t *app = calloc(1, sizeof(state_t)); app->lcmurl = strdup(get_default_lcm_url()); if (0 != lcm_parse_url(app->lcmurl, &app->mc_addr, &app->mc_port)) { fprintf (stderr, "invalid URL [%s]\n", app->lcmurl); return 1; } struct in_addr ia; ia = app->mc_addr; printf("MC group: %s port: %d\n", inet_ntoa(ia), app->mc_port); if(0 != setup_socket(app)) { return 1; } app->hosts = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, (GDestroyNotify)host_destroy); app->mainloop = g_main_loop_new(NULL, FALSE); app->ioc = g_io_channel_unix_new(app->recvfd); app->sid = g_io_add_watch(app->ioc, G_IO_IN, (GIOFunc)on_message_ready, app); g_timeout_add(100, on_timer, app); app->report_interval_usec = DEFAULT_REPORT_INTERVAL_SECONDS * 1000000; app->next_report_utime = timestamp_now() + 1000000; bot_signal_pipe_glib_quit_on_kill(app->mainloop); g_main_loop_run(app->mainloop); g_io_channel_unref(app->ioc); g_source_remove(app->sid); shutdown(app->recvfd, SHUT_RDWR); g_hash_table_destroy(app->hosts); free(app->lcmurl); free(app); return 0; }
int main(int argc, char**argv){ char *host,*port; char* messages[5]; messages[0] = "C is quirky flawed and an enormous success - Dennis M. Ritchie"; messages[1] = "The question of whether computers can think is like the question of whether submarines can swim - Edsger W. Dijkstra"; messages[2] = "Typing is no substitute for thinking. - Dartmouth Basic Manual"; messages[3] = "Any C programmer here ? Yeah i got a C in programming class. That counts ? - Unknown"; messages[4] = "The Internet? Is that thing still around? - Homer Simpson"; int num_msgs = 5; if(argc < 3 || argc > 3){ printf("Incorrect number of args.\n"); print_use_and_exit(); }else{ host = argv[1]; port = argv[2]; } CONN_INFO* connection = setup_socket(host, port); if(connection == NULL) print_use_and_exit(); for(int i = 0; i < num_msgs; i++){ MESSAGE*msg = malloc(sizeof(MESSAGE)); msg->buffer = messages[i]; msg->length = strlen(messages[i])+1; rtp_send_message(connection, msg); printf("Sent message %i to server...\n", i); MESSAGE*response = rtp_receive_message(connection); if(response) printf("Received reponse:\n\t%s\n\n", response->buffer); else{ perror("Error must have occurred while receiving response. No message returned\n"); free(connection); exit(EXIT_FAILURE); } free(msg); } shutdown_socket(connection); free(connection); return 0; }
void new_client(struct pkg_conn *pcp) { int i; if ( pcp == PKC_ERROR ) return; for ( i = MAX_CLIENTS-1; i >= 0; i-- ) { if ( clients[i] != NULL ) continue; /* Found an available slot */ clients[i] = pcp; FD_SET(pcp->pkc_fd, &select_list); V_MAX(max_fd, pcp->pkc_fd); setup_socket( pcp->pkc_fd ); return; } fprintf(stderr, "fbserv: too many clients\n"); pkg_close(pcp); }
int ws_init(wsh_t *wsh, ws_socket_t sock, SSL_CTX *ssl_ctx, int close_sock, int block, int stay_open) { memset(wsh, 0, sizeof(*wsh)); wsh->sock = sock; wsh->block = block; wsh->sanity = 5000; wsh->ssl_ctx = ssl_ctx; wsh->stay_open = stay_open; if (!ssl_ctx) { ssl_ctx = ws_globals.ssl_ctx; } if (close_sock) { wsh->close_sock = 1; } wsh->buflen = 1024 * 64; wsh->bbuflen = wsh->buflen; wsh->buffer = malloc(wsh->buflen); wsh->bbuffer = malloc(wsh->bbuflen); //printf("init %p %ld\n", (void *) wsh->bbuffer, wsh->bbuflen); //memset(wsh->buffer, 0, wsh->buflen); //memset(wsh->bbuffer, 0, wsh->bbuflen); wsh->secure = ssl_ctx ? 1 : 0; setup_socket(sock); if (establish_logical_layer(wsh) == -1) { return -1; } if (wsh->down) { return -1; } return 0; }
void setup(int * socket_fd, struct addrinfo * hints, struct addrinfo * res, char * ip, char * port, struct sockaddr_storage * server_addr, int * len){ bzero (hints, sizeof hints); hints->ai_family = AF_UNSPEC; hints->ai_socktype = SOCK_DGRAM; hints->ai_protocol = IPPROTO_UDP; bzero(port, 6); sprintf(port, "%d", SERVER_PORT); int err = getaddrinfo(ip, port, hints, &res); //check error if(err != 0){ perror("Error getaddrinfo @setup()"); exit(1); } setup_socket(socket_fd, res); setup_server_addr(server_addr, res); *len = (res)->ai_addrlen; free(res); }
void running() { char rcv_str[SIZE]; ssize_t length, cmd_length; size_t cmd_length_ntohl; char *send_str1 = "sorry, pending, please wait."; char *send_str2 = "hello, world! from server"; int socket_fd = setup_socket(); while(1){ int fd = accept(socket_fd, NULL, NULL); if(fd == -1) oops("accept error..."); length = read(fd, (void*)&cmd_length, sizeof(uint32_t)); if(length == -1) oops("read error..."); cmd_length_ntohl = ntohl(cmd_length); printf("length = %d\n", cmd_length_ntohl); //read the cmd, its length is cmd_length_ntohl, including '\0' length = read(fd, (void*)rcv_str, cmd_length_ntohl); if(length == -1) oops("read error..."); printf("rcv_str = %s\n", rcv_str); printf("ok1"); // length = write(fd, send_str1, strlen(send_str1)+1); // printf("ok2"); // if(length == -1) oops("write error..."); // // printf("ok3"); // length = write(fd, send_str2, strlen(send_str2)+1); // if(length == -1) oops("write error..."); // fclose(fp); } }
static int send_command(int argc, char *argv[], int type) { struct sockaddr_un addr; int sock; int n, len = 0, off = 0, ret, recvd; char data[BUF_SIZE]; sock = setup_socket(addr); n = snprintf(data, sizeof(data) - (2 * sizeof(char)), "%c%c", type, 0); len += n; off += n; for (; argc > 0 && sizeof(data) - off > 0; off += n, argc--, argv++) { n = snprintf(data + off, sizeof(data) - off, "%s%c", *argv, 0); len += n; } ret = write(sock, data, len); if (ret == -1) perror("Failed to send command"); recvd = read(sock, &ret, sizeof(ret)); if (recvd == -1) { perror("Failed to receive response"); ret = -1; } if (ret != IPC_ERR_NONE) handle_error(ret); if (close(sock) == -1) { perror("Failed to close socket.\n"); exit(EXIT_FAILURE); } return ret; }
int main (int argc, char **argv) { struct nl_sock *sk; int err; sk = setup_socket (); g_assert (sk); err = nl_send_simple (sk, XFRM_MSG_GETPOLICY, NLM_F_DUMP, NULL, 0); if (err < 0) { g_warning ("Error sending: %d %s", err, nl_geterror (err)); return 1; } nl_socket_modify_cb (sk, NL_CB_VALID, NL_CB_CUSTOM, parse_reply, NULL); err = nl_recvmsgs_default (sk); if (err < 0) { g_warning ("Error parsing: %d %s", err, nl_geterror (err)); return 1; } return 0; }
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; }