static struct passive_connection * create_conn(struct uinet_demo_passive *passive, struct uinet_socket *so, int server) { struct passive_connection *conn = NULL; struct ev_uinet_ctx *soctx = NULL; struct uinet_sockaddr_in *sin1, *sin2; char buf1[32], buf2[32]; conn = calloc(1, sizeof(*conn)); if (NULL == conn) { printf("%s: Failed to alloc connection context for new connection\n", passive->cfg.name); goto fail; } soctx = ev_uinet_attach(so); if (NULL == soctx) { printf("%s: Failed to alloc libev context for new connection socket\n", passive->cfg.name); goto fail; } uinet_sogetsockaddr(so, (struct uinet_sockaddr **)&sin1); uinet_sogetpeeraddr(so, (struct uinet_sockaddr **)&sin2); snprintf(conn->label, sizeof(conn->label), "%s (%s:%u <- %s:%u)", server ? "SERVER" : "CLIENT", uinet_inet_ntoa(sin1->sin_addr, buf1, sizeof(buf1)), ntohs(sin1->sin_port), uinet_inet_ntoa(sin2->sin_addr, buf2, sizeof(buf2)), ntohs(sin2->sin_port)); uinet_free_sockaddr((struct uinet_sockaddr *)sin1); uinet_free_sockaddr((struct uinet_sockaddr *)sin2); conn->verbose = passive->cfg.verbose; conn->server = passive; ev_init(&conn->watcher, passive_receive_cb); ev_uinet_set(&conn->watcher, soctx, EV_READ); conn->watcher.data = conn; ev_init(&conn->connected_watcher, passive_connected_cb); ev_uinet_set(&conn->connected_watcher, soctx, EV_WRITE); conn->connected_watcher.data = conn; return (conn); fail: if (conn) free(conn); if (soctx) ev_uinet_detach(soctx); return (NULL); }
static void nproxy_outbound_connected_cb(struct ev_loop *loop, ev_uinet *w, int revents) { struct nproxy_splice *splice = w->data; struct uinet_demo_nproxy *nproxy = splice->nproxy; struct uinet_sockaddr_in *sin1, *sin2; char buf1[32], buf2[32]; ev_uinet_stop(loop, w); if (splice->verbose) { uinet_sogetsockaddr(w->so, (struct uinet_sockaddr **)&sin1); uinet_sogetpeeraddr(w->so, (struct uinet_sockaddr **)&sin2); printf("%s: splice %llu: outbound connection established (local=%s:%u foreign=%s:%u)\n", nproxy->cfg.name, (unsigned long long)splice->id, uinet_inet_ntoa(sin1->sin_addr, buf1, sizeof(buf1)), ntohs(sin1->sin_port), uinet_inet_ntoa(sin2->sin_addr, buf2, sizeof(buf2)), ntohs(sin2->sin_port)); uinet_free_sockaddr((struct uinet_sockaddr *)sin1); uinet_free_sockaddr((struct uinet_sockaddr *)sin2); } ev_uinet_start(loop, &splice->inbound.copy_watcher); ev_uinet_start(loop, &splice->outbound.copy_watcher); }
static struct connection_context * create_conn(struct passive_context *passive, struct uinet_socket *so, int server) { struct connection_context *conn = NULL; struct ev_uinet_ctx *soctx = NULL; struct uinet_sockaddr_in *sin1, *sin2; char buf1[32], buf2[32]; time_t now_timet; struct tm now; #define EXTRACT_BUFFER_SIZE 1024 conn = calloc(1, sizeof(*conn)); if (NULL == conn) { printf("Failed to alloc connection context for new connection\n"); goto fail; } soctx = ev_uinet_attach(so); if (NULL == soctx) { printf("Failed to alloc libev context for new connection socket\n"); goto fail; } uinet_sogetsockaddr(so, (struct uinet_sockaddr **)&sin1); uinet_sogetpeeraddr(so, (struct uinet_sockaddr **)&sin2); snprintf(conn->label, sizeof(conn->label), "%s (%s:%u <- %s:%u)", server ? "SERVER" : "CLIENT", uinet_inet_ntoa(sin1->sin_addr, buf1, sizeof(buf1)), ntohs(sin1->sin_port), uinet_inet_ntoa(sin2->sin_addr, buf2, sizeof(buf2)), ntohs(sin2->sin_port)); #ifdef ENABLE_EXTRACT if (passive->extract && !server) { time(&now_timet); localtime_r(&now_timet, &now); snprintf(conn->filename_prefix, sizeof(conn->filename_prefix), "extract-%04d%02d%02d-%02d%02d.%02d-%s.%u-%s.%u", now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec, uinet_inet_ntoa(sin1->sin_addr, buf1, sizeof(buf1)), ntohs(sin1->sin_port), uinet_inet_ntoa(sin2->sin_addr, buf2, sizeof(buf2)), ntohs(sin2->sin_port)); } #endif uinet_free_sockaddr((struct uinet_sockaddr *)sin1); uinet_free_sockaddr((struct uinet_sockaddr *)sin2); conn->verbose = passive->verbose; conn->server = passive; if (passive->extract) { #ifdef ENABLE_EXTRACT if (0 != parser_init(conn, server ? HTTP_REQUEST : HTTP_RESPONSE)) goto fail; conn->buffer_size = EXTRACT_BUFFER_SIZE; conn->buffer = malloc(conn->buffer_size); if (NULL == conn->buffer) goto fail; ev_init(&conn->watcher, passive_extract_cb); #else goto fail; #endif } else { ev_init(&conn->watcher, passive_receive_cb); } ev_uinet_set(&conn->watcher, soctx, EV_READ); conn->watcher.data = conn; return (conn); fail: #ifdef ENABLE_EXTRACT if (conn->buffer) free(conn->buffer); if (conn->parser) free(conn->parser); #endif if (conn) free(conn); if (soctx) ev_uinet_detach(soctx); return (NULL); }
static void nproxy_inbound_connected_cb(struct ev_loop *loop, ev_uinet *w, int revents) { struct nproxy_splice *splice = w->data; struct uinet_demo_nproxy *nproxy = splice->nproxy; struct uinet_sockaddr_in *sin_local, *sin_foreign; struct uinet_socket *outbound_socket = NULL; struct ev_uinet_ctx *soctx = NULL; struct uinet_in_l2info l2i; char buf1[32], buf2[32]; int optlen, optval; int error; uinet_sogetsockaddr(w->so, (struct uinet_sockaddr **)&sin_local); uinet_sogetpeeraddr(w->so, (struct uinet_sockaddr **)&sin_foreign); if (splice->verbose) printf("%s: splice %llu: inbound connection established (local=%s:%u foreign=%s:%u)\n", nproxy->cfg.name, (unsigned long long)splice->id, uinet_inet_ntoa(sin_local->sin_addr, buf1, sizeof(buf1)), ntohs(sin_local->sin_port), uinet_inet_ntoa(sin_foreign->sin_addr, buf2, sizeof(buf2)), ntohs(sin_foreign->sin_port)); if ((nproxy->cfg.copy_mode & UINET_IP_COPY_MODE_MAYBE) && ((uinet_sogetserialno(w->so) % nproxy->cfg.copy_every) == 0)){ if ((error = uinet_sosetcopymode(w->so, UINET_IP_COPY_MODE_RX|UINET_IP_COPY_MODE_ON, nproxy->cfg.copy_limit, nproxy->cfg.copy_uif))) printf("%s: splice %llu: Failed to set copy mode (%d)\n", nproxy->cfg.name, (unsigned long long)splice->id, error); } /* don't need this watcher anymore */ ev_uinet_stop(loop, w); /* Create the outbound connection */ error = uinet_socreate(nproxy->cfg.uinst, UINET_PF_INET, &outbound_socket, UINET_SOCK_STREAM, 0); if (error != 0) { printf("%s: splice %llu: outbound socket creation failed (%d)\n", nproxy->cfg.name, (unsigned long long)splice->id, error); goto fail; } if ((error = uinet_make_socket_promiscuous(outbound_socket, nproxy->outbound_if))) { printf("%s: splice %llu: failed to make outbound socket promiscuous (%d)\n", nproxy->cfg.name, (unsigned long long)splice->id, error); goto fail; } /* * Socket needs to be non-blocking to work with the event system */ uinet_sosetnonblocking(outbound_socket, 1); optlen = sizeof(optval); optval = 1; error = uinet_sosetsockopt(outbound_socket, UINET_IPPROTO_TCP, UINET_TCP_NODELAY, &optval, optlen); if (error != 0) { printf("%s: splice %llu: failed to set TCP_NODELAY on outbound socket (%d)\n", nproxy->cfg.name, (unsigned long long)splice->id, error); goto fail; } /* Bind to the foreign address of the inbound connection */ error = uinet_sobind(outbound_socket, (struct uinet_sockaddr *)sin_foreign); if (error != 0) { printf("%s: splice %llu: outbound socket bind failed (%d)\n", nproxy->cfg.name, (unsigned long long)splice->id, error); goto fail; } /* * Use the same MAC addrs and VLAN tag stack as the inbound * connection, which requires swapping the local and foreign MAC * addrs. */ error = uinet_getl2info(w->so, &l2i); if (error != 0) { printf("%s: splice %llu: unable to get l2info from inbound socket (%d)\n", nproxy->cfg.name, (unsigned long long)splice->id, error); goto fail; } error = uinet_setl2info2(outbound_socket, l2i.inl2i_foreign_addr, l2i.inl2i_local_addr, l2i.inl2i_flags, &l2i.inl2i_tagstack); if (error != 0) { printf("%s: splice %llu: unable to set l2info for outbound socket (%d)\n", nproxy->cfg.name, (unsigned long long)splice->id, error); goto fail; } soctx = ev_uinet_attach(outbound_socket); if (NULL == soctx) { printf("%s: splice %llu: failed to alloc libev context for outbound socket\n", nproxy->cfg.name, (unsigned long long)splice->id); goto fail; } /* The connection target is the local address of the inbound connection */ error = uinet_soconnect(outbound_socket, (struct uinet_sockaddr *)sin_local); if ((error != 0) && (error != UINET_EINPROGRESS)) { printf("%s: splice %llu: outbound socket connect failed (%d)\n", nproxy->cfg.name, (unsigned long long)splice->id, error); goto fail; } uinet_free_sockaddr((struct uinet_sockaddr *)sin_local); uinet_free_sockaddr((struct uinet_sockaddr *)sin_foreign); ev_init(&splice->outbound.connected_watcher, nproxy_outbound_connected_cb); ev_uinet_set(&splice->outbound.connected_watcher, soctx, EV_WRITE); splice->outbound.connected_watcher.data = splice; ev_uinet_start(loop, &splice->outbound.connected_watcher); ev_init(&splice->outbound.writable_watcher, nproxy_writable_cb); ev_uinet_set(&splice->outbound.writable_watcher, soctx, EV_WRITE); splice->outbound.writable_watcher.data = &splice->outbound; /* will be started as necessary by the inbound copy watcher */ ev_init(&splice->outbound.copy_watcher, nproxy_copy_cb); ev_uinet_set(&splice->outbound.copy_watcher, soctx, EV_READ); splice->outbound.copy_watcher.data = &splice->outbound; /* will be started when the outbound connection is established */ return; fail: uinet_free_sockaddr((struct uinet_sockaddr *)sin_local); uinet_free_sockaddr((struct uinet_sockaddr *)sin_foreign); if (soctx) ev_uinet_detach(soctx); if (outbound_socket) uinet_soclose(outbound_socket); free(splice); }