/** Send using su_vsend(). Map IPv4 addresses as IPv6 addresses, if needed. */ ssize_t tport_send_dgram(tport_t const *self, msg_t *msg, msg_iovec_t iov[], size_t iovused) { su_sockaddr_t su[1]; socklen_t sulen = sizeof su; if (tport_is_connection_oriented(self)) return su_vsend(self->tp_socket, iov, iovused, MSG_NOSIGNAL, NULL, 0); msg_get_address(msg, su, &sulen); #if SU_HAVE_IN6 && defined(IN6_INADDR_TO_V4MAPPED) if (su->su_family == AF_INET && self->tp_addrinfo->ai_family == AF_INET6) { su_sockaddr_t su0[1]; memset(su0, 0, sizeof su0); su0->su_family = self->tp_addrinfo->ai_family; su0->su_port = su->su_port; IN6_INADDR_TO_V4MAPPED(&su->su_sin.sin_addr, &su0->su_sin6.sin6_addr); memcpy(su, su0, sulen = sizeof(su0->su_sin6)); } #endif su_soerror(self->tp_socket); /* XXX - we *still* have a race condition */ return su_vsend(self->tp_socket, iov, iovused, MSG_NOSIGNAL, su, sulen); }
/** Connection is complete. */ int forwarder_connected(proxy_t *pr, su_wait_t *w, forwarder_t *f) { int events, error; forwarder_t *f_peer; events = su_wait_events(w, f->f_socket); error = su_soerror(f->f_socket); if (error) { SU_DEBUG_1(("connect: %s\n", su_strerror(error))); forwarder_destroy(f); return 0; } su_root_unregister(pr->pr_root, f->f_wait + 1, forwarder_connected, f); /* Wait for data, forward it to peer */ assert(f->f_peer); f_peer = f->f_peer; su_root_register(pr->pr_root, f->f_wait, forwarder_recv, f, 0); su_root_register(pr->pr_root, f_peer->f_wait, forwarder_recv, f_peer, 0); return 0; }
int main(int argc, char *argv[]) { su_socket_t s; su_sockaddr_t su = { 0 }; char *host = argv[1]; char *port = host ? argv[2] : NULL; su_addrinfo_t *ai = NULL, hints[1] = {{ 0 }}; int error; if (argv[1] && (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)) usage(argv[0]); if (!port) port = "echo"; if ((error = su_getaddrinfo(host, port, hints, &ai))) { fprintf(stderr, "poll_test: su_getaddrinfo(): %s\n", su_gai_strerror(error)); exit(1); } memcpy(SU_ADDR(&su), ai->ai_addr, ai->ai_addrlen); s = su_socket(ai->ai_family, SOCK_STREAM, 0); if (s == INVALID_SOCKET) { su_perror("socket"); exit(1); } su_freeaddrinfo(ai); su_setblocking(s, 0); /* Don't block */ if (connect(s, &su.su_sa, su_sockaddr_size(&su)) == -1) { if (errno != EINPROGRESS) { su_perror("connect"); exit(1); } } { su_wait_t w; int n, err; su_wait_create(&w, s, SU_WAIT_OUT); n = su_wait(&w, 1, SU_WAIT_FOREVER); printf("su_wait returned %d\n", n); err = su_soerror(s); printf("connect: %s\n", su_strerror(err)); } exit(0); }
int tls_connect(su_root_magic_t *magic, su_wait_t *w, tport_t *self) { tport_master_t *mr = self->tp_master; tport_tls_t *tlstp = (tport_tls_t *)self; tls_t *tls; int events = su_wait_events(w, self->tp_socket); int error; SU_DEBUG_7(("%s(%p): events%s%s%s%s\n", __func__, (void *)self, events & (SU_WAIT_CONNECT) ? " CONNECTING" : "", events & SU_WAIT_IN ? " NEGOTIATING" : "", events & SU_WAIT_ERR ? " ERROR" : "", events & SU_WAIT_HUP ? " HANGUP" : "")); #if HAVE_POLL assert(w->fd == self->tp_socket); #endif if (events & SU_WAIT_ERR) tport_error_event(self); if (events & SU_WAIT_HUP && !self->tp_closed) tport_hup_event(self); if (self->tp_closed) return 0; error = su_soerror(self->tp_socket); if (error) { tport_error_report(self, error, NULL); return 0; } if ((tls = tlstp->tlstp_context) == NULL) { SU_DEBUG_3(("%s(%p): Error: no TLS context data for connected socket.\n", __func__, (void *)tlstp)); tport_close(self); tport_set_secondary_timer(self); return 0; } if (self->tp_is_connected == 0) { int ret, status; ret = self->tp_accepted ? SSL_accept(tls->con) : SSL_connect(tls->con); status = SSL_get_error(tls->con, ret); switch (status) { case SSL_ERROR_WANT_READ: /* OpenSSL is waiting for the peer to send handshake data */ self->tp_events = SU_WAIT_IN | SU_WAIT_ERR | SU_WAIT_HUP; su_root_eventmask(mr->mr_root, self->tp_index, self->tp_socket, self->tp_events); return 0; case SSL_ERROR_WANT_WRITE: /* OpenSSL is waiting for the peer to receive handshake data */ self->tp_events = SU_WAIT_IN | SU_WAIT_ERR | SU_WAIT_HUP | SU_WAIT_OUT; su_root_eventmask(mr->mr_root, self->tp_index, self->tp_socket, self->tp_events); return 0; case SSL_ERROR_NONE: /* TLS Handshake complete */ status = tls_post_connection_check(self, tls); if ( status == X509_V_OK ) { su_wait_t wait[1] = {SU_WAIT_INIT}; tport_master_t *mr = self->tp_master; su_root_deregister(mr->mr_root, self->tp_index); self->tp_index = -1; self->tp_events = SU_WAIT_IN | SU_WAIT_ERR | SU_WAIT_HUP; if ((su_wait_create(wait, self->tp_socket, self->tp_events) == -1) || ((self->tp_index = su_root_register(mr->mr_root, wait, tport_wakeup, self, 0)) == -1)) { tport_close(self); tport_set_secondary_timer(self); return 0; } tls->read_events = SU_WAIT_IN; tls->write_events = 0; self->tp_is_connected = 1; self->tp_verified = tls->x509_verified; self->tp_subjects = tls->subjects; if (tport_has_queued(self)) tport_send_event(self); else tport_set_secondary_timer(self); return 0; } break; default: { char errbuf[64]; ERR_error_string_n(status, errbuf, 64); SU_DEBUG_3(("%s(%p): TLS setup failed (%s)\n", __func__, (void *)self, errbuf)); } break; } } /* TLS Handshake Failed or Peer Certificate did not Verify */ tport_close(self); tport_set_secondary_timer(self); return 0; }
/** Capture the data from the iovec */ void tport_capt_msg(tport_t const *self, msg_t *msg, size_t n, su_iovec_t const iov[], size_t iovused, char const *what) { int buflen = 0, error; su_sockaddr_t const *su, *su_self; struct hep_hdr hep_header; #if __sun__ struct hep_iphdr hep_ipheader = {{{{0}}}}; #else struct hep_iphdr hep_ipheader = {{0}}; #endif #if SU_HAVE_IN6 struct hep_ip6hdr hep_ip6header = {{{{0}}}}; #endif int eth_frame_len = 8000; char* buffer; size_t i, dst = 0; tport_master_t *mr; assert(self); assert(msg); su = msg_addr(msg); su_self = self->tp_pri->pri_primary->tp_addr; mr = self->tp_master; /* If we don't have socket, go out */ if (!mr->mr_capt_sock) { su_log("error: capture socket is not open\n"); return; } /*buffer for ethernet frame*/ buffer = (void*)malloc(eth_frame_len); /* VOIP Header */ hep_header.hp_v = 1; hep_header.hp_f = su->su_family; /* Header Length */ hep_header.hp_l = sizeof(struct hep_hdr); /* PROTOCOL */ if(strcmp(self->tp_name->tpn_proto, "tcp") == 0) hep_header.hp_p = IPPROTO_TCP; else if(strcmp(self->tp_name->tpn_proto, "tls") == 0) hep_header.hp_p = IPPROTO_IDP; /* FAKE*/ else if(strcmp(self->tp_name->tpn_proto, "sctp") == 0) hep_header.hp_p = IPPROTO_SCTP; else if(strcmp(self->tp_name->tpn_proto, "ws") == 0) hep_header.hp_p = IPPROTO_TCP; else if(strcmp(self->tp_name->tpn_proto, "wss") == 0) hep_header.hp_p = IPPROTO_TCP; else hep_header.hp_p = IPPROTO_UDP; /* DEFAULT UDP */ /* Check destination */ if(strncmp("sent", what, 4) == 0) dst = 1; /* copy destination and source IPs*/ if(su->su_family == AF_INET) { memcpy(dst ? &hep_ipheader.hp_dst : &hep_ipheader.hp_src, &su->su_sin.sin_addr.s_addr, sizeof(su->su_sin.sin_addr.s_addr)); memcpy(dst ? &hep_ipheader.hp_src : &hep_ipheader.hp_dst, &su_self->su_sin.sin_addr.s_addr, sizeof(su_self->su_sin.sin_addr.s_addr)); hep_header.hp_l += sizeof(struct hep_iphdr); } #if SU_HAVE_IN6 else { memcpy(dst ? &hep_ip6header.hp6_dst : &hep_ip6header.hp6_src, &su->su_sin.sin_addr.s_addr, sizeof(su->su_sin.sin_addr.s_addr)); memcpy(dst ? &hep_ip6header.hp6_src : &hep_ip6header.hp6_dst, &su_self->su_sin.sin_addr.s_addr, sizeof(su_self->su_sin.sin_addr.s_addr)); hep_header.hp_l += sizeof(struct hep_ip6hdr); } #endif hep_header.hp_dport = dst ? su->su_port : su_self->su_port; hep_header.hp_sport = dst ? su_self->su_port : su->su_port; /* Copy hepheader */ memset(buffer, '\0', eth_frame_len); memcpy(buffer, &hep_header, sizeof(struct hep_hdr)); buflen = sizeof(struct hep_hdr); if(su->su_family == AF_INET) { memcpy(buffer + buflen, &hep_ipheader, sizeof(struct hep_iphdr)); buflen += sizeof(struct hep_iphdr); } #if SU_HAVE_IN6 else if(su->su_family == AF_INET6) { memcpy(buffer+buflen, &hep_ip6header, sizeof(struct hep_ip6hdr)); buflen += sizeof(struct hep_ip6hdr); } #endif else { su_perror("error: tport_logging: capture: unsupported protocol family"); goto done; } for (i = 0; i < iovused && n > 0; i++) { size_t len = iov[i].mv_len; if (len > n) len = n; /* if the packet too big for us */ if((buflen + len) > eth_frame_len) break; memcpy(buffer + buflen , (void*)iov[i].mv_base, len); buflen +=len; n -= len; } /* check if we have error i.e. capture server is down */ if ((error = su_soerror(mr->mr_capt_sock))) { su_perror("error: tport_logging: capture socket error"); goto done; } su_send(mr->mr_capt_sock, buffer, buflen, 0); done: /* Now we release it */ if(buffer) free(buffer); return; }
/** Process UDP error event. */ int tport_udp_error(tport_t const *self, su_sockaddr_t name[1]) { if (tport_is_connection_oriented(self)) name[0] = self->tp_addr[0]; return su_soerror(self->tp_socket); }