예제 #1
0
/** 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);
}
예제 #2
0
/** 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;
}
예제 #3
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);
}
예제 #4
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;
}
예제 #5
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;
}
예제 #6
0
/** 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);
}