Beispiel #1
0
/* Write some data to the socket.  If the write is not COMPLETED within
 * timeout_msecs , NSE_STATUS_TIMEOUT will be returned.  If you are supplying
 * NUL-terminated data, you can optionally pass -1 for datalen and nsock_write
 * will figure out the length itself */
nsock_event_id nsock_write(nsock_pool ms_pool, nsock_iod ms_iod,
          nsock_ev_handler handler, int timeout_msecs, void *userdata, const char *data, int datalen) {
  mspool *nsp = (mspool *)ms_pool;
  msiod *nsi = (msiod *)ms_iod;
  msevent *nse;
  char displaystr[256];

  nse = msevent_new(nsp, NSE_TYPE_WRITE, nsi, timeout_msecs, handler, userdata);
  assert(nse);

  nse->writeinfo.dest.ss_family = AF_UNSPEC;

  if (datalen < 0)
    datalen = (int)strlen(data);

    if (nsp->loglevel == NSOCK_LOG_DBG_ALL && datalen < 80) {
      memcpy(displaystr, ": ", 2);
      memcpy(displaystr + 2, data, datalen);
      displaystr[2 + datalen] = '\0';
      replacenonprintable(displaystr + 2, datalen, '.');
    } else {
      displaystr[0] = '\0';
    }

    nsock_log_debug(nsp, "Write request for %d bytes to IOD #%li EID %li [%s]%s",
                    datalen, nsi->id, nse->id, get_peeraddr_string(nsi), displaystr);

  fs_cat(&nse->iobuf, data, datalen);

  nsp_add_event(nsp, nse);

  return nse->id;
}
nsock_event_id nsock_sendto(nsock_pool ms_pool, nsock_iod ms_iod,
              nsock_ev_handler handler, int timeout_msecs,
              void *userdata, struct sockaddr *saddr, size_t sslen,
              unsigned short port, const char *data, int datalen) {
  mspool *nsp = (mspool *) ms_pool;
  msiod *nsi = (msiod *) ms_iod;
  msevent *nse;
  char displaystr[256];
  struct sockaddr_in *sin = (struct sockaddr_in *) saddr;
#if HAVE_IPV6
  struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) saddr;
#endif

  nse = msevent_new(nsp, NSE_TYPE_WRITE, nsi, timeout_msecs, handler,
		    userdata);
  assert(nse);

  if (sin->sin_family == AF_INET) {
    sin->sin_port = htons(port);
  } else {
      assert(sin->sin_family == AF_INET6);
#if HAVE_IPV6
    sin6->sin6_port = htons(port);
#else
    fatal("IPv6 address passed to nsock_connect_* call, but nsock was not compiled w/IPv6 support");
#endif
  }

  assert(sslen <= sizeof(nse->writeinfo.dest));
  memcpy(&nse->writeinfo.dest, saddr, sslen);
  nse->writeinfo.destlen = sslen;

  assert(sslen <= sizeof(nse->iod->peer));
  memcpy(&nse->iod->peer, saddr, sslen);
  nse->iod->peerlen = sslen;

  if (datalen < 0)
    datalen = (int) strlen(data);	

  if (nsp->tracelevel > 0) {
    if (nsp->tracelevel > 1 && datalen < 80) {
      memcpy(displaystr, ": ", 2);
      memcpy(displaystr + 2, data, datalen);
      displaystr[2 + datalen] = '\0';
      replacenonprintable(displaystr + 2, datalen, '.');
    } else {
      displaystr[0] = '\0';
    }
    nsock_trace(nsp, "Sendto request for %d bytes to IOD #%li EID %li [%s:%hu]%s",
      datalen, nsi->id, nse->id,
      inet_ntop_ez(&nse->writeinfo.dest, nse->writeinfo.destlen), port,
      displaystr);
  }
	
  fscat(&nse->iobuf, data, datalen);

  nsp_add_event(nsp, nse);

  return nse->id;
}
Beispiel #3
0
/* Same as above, except it tries to read at least 'nbytes' instead of 'nlines'. */
nsock_event_id nsock_readbytes(nsock_pool nsp, nsock_iod ms_iod, nsock_ev_handler handler, int timeout_msecs,
                               void *userdata, int nbytes) {

  msiod *nsi = (msiod *)ms_iod;
  mspool *ms = (mspool *)nsp;
  msevent *nse;

  nse = msevent_new(ms, NSE_TYPE_READ, nsi, timeout_msecs, handler, userdata);
  assert(nse);

  if (ms->tracelevel > 0) {
    if (nsi->peerlen > 0)
      nsock_trace(ms, "Read request for %d bytes from IOD #%li [%s:%d] EID %li",
                  nbytes, nsi->id, inet_ntop_ez(&nsi->peer, nsi->peerlen), nsi_peerport(nsi), nse->id);
    else
      nsock_trace(ms, "Read request for %d bytes from IOD #%li (peer unspecified) EID %li",
                  nbytes, nsi->id, nse->id);
  }

  nse->readinfo.read_type = NSOCK_READBYTES;
  nse->readinfo.num = nbytes;

  nsp_add_event(ms, nse);

  return nse->id;
}
/* Request ssl connection over already established connection.  nsiod must be
 * socket that is already connected to target using nsock_connect_tcp or
 * nsock_connect_sctp.  All parameters have the same meaning as in
 * 'nsock_connect_ssl' */
nsock_event_id nsock_reconnect_ssl(nsock_pool nsp, nsock_iod nsiod, nsock_ev_handler handler, int timeout_msecs,
                                   void *userdata, nsock_ssl_session ssl_session) {

#ifndef HAVE_OPENSSL
  fatal("nsock_reconnect_ssl called - but nsock was built w/o SSL support.  QUITTING");
  return (nsock_event_id) 0; /* UNREACHED */
#else
  msiod *nsi = (msiod *)nsiod;
  mspool *ms = (mspool *)nsp;
  msevent *nse;

  if (!ms->sslctx)
    nsp_ssl_init(ms);

  nse = msevent_new(ms, NSE_TYPE_CONNECT_SSL, nsi, timeout_msecs, handler, userdata);
  assert(nse);

  /* Set our SSL_SESSION so we can benefit from session-id reuse. */
  nsi_set_ssl_session(nsi, (SSL_SESSION *)ssl_session);

  nsock_log_info(ms, "SSL reconnection requested (IOD #%li) EID %li",
                 nsi->id, nse->id);

  /* Do the actual connect() */
  nse->event_done = 0;
  nse->status = NSE_STATUS_SUCCESS;
  nsp_add_event(ms, nse);

  return nse->id;
#endif /* HAVE_OPENSSL */
}
/* Request an SSL over TCP/SCTP connection to another system (by IP address).
 * The in_addr is normal network byte order, but the port number should be given
 * in HOST BYTE ORDER.  This function will call back only after it has made the
 * connection AND done the initial SSL negotiation.  From that point on, you use
 * the normal read/write calls and decryption will happen transparently. ss
 * should be a sockaddr_storage, sockaddr_in6, or sockaddr_in as appropriate
 * (just like what you would pass to connect).  sslen should be the sizeof the
 * structure you are passing in. */
nsock_event_id nsock_connect_ssl(nsock_pool nsp, nsock_iod nsiod, nsock_ev_handler handler, int timeout_msecs,
                                 void *userdata, struct sockaddr *saddr, size_t sslen, int proto, unsigned short port, nsock_ssl_session ssl_session) {

#ifndef HAVE_OPENSSL
  fatal("nsock_connect_ssl called - but nsock was built w/o SSL support.  QUITTING");
  return (nsock_event_id)0; /* UNREACHED */
#else
  struct sockaddr_storage *ss = (struct sockaddr_storage *)saddr;
  msiod *nsi = (msiod *)nsiod;
  mspool *ms = (mspool *)nsp;
  msevent *nse;

  if (!ms->sslctx)
    nsp_ssl_init(ms);

  assert(nsi->state == NSIOD_STATE_INITIAL || nsi->state == NSIOD_STATE_UNKNOWN);

  nse = msevent_new(ms, NSE_TYPE_CONNECT_SSL, nsi, timeout_msecs, handler, userdata);
  assert(nse);

  /* Set our SSL_SESSION so we can benefit from session-id reuse. */
  nsi_set_ssl_session(nsi, (SSL_SESSION *)ssl_session);

  nsock_log_info(ms, "SSL connection requested to %s:%hu/%s (IOD #%li) EID %li",
                 inet_ntop_ez(ss, sslen), port, (proto == IPPROTO_TCP ? "tcp" : "sctp"),
                 nsi->id, nse->id);

  /* Do the actual connect() */
  nsock_connect_internal(ms, nse, SOCK_STREAM, proto, ss, sslen, port);
  nsp_add_event(ms, nse);

  return nse->id;
#endif /* HAVE_OPENSSL */
}
Beispiel #6
0
nsock_event_id nsock_sendto(nsock_pool ms_pool, nsock_iod ms_iod, nsock_ev_handler handler, int timeout_msecs,
                            void *userdata, struct sockaddr *saddr, size_t sslen, unsigned short port, const char *data, int datalen) {
  mspool *nsp = (mspool *)ms_pool;
  msiod *nsi = (msiod *)ms_iod;
  msevent *nse;
  char displaystr[256];
  struct sockaddr_in *sin = (struct sockaddr_in *)saddr;
#if HAVE_IPV6
  struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)saddr;
#endif

  nse = msevent_new(nsp, NSE_TYPE_WRITE, nsi, timeout_msecs, handler, userdata);
  assert(nse);

  if (saddr->sa_family == AF_INET) {
    sin->sin_port = htons(port);
#if HAVE_SYS_UN_H
  } else if (saddr->sa_family == AF_INET6) {
#else
  } else {
#endif
    assert(saddr->sa_family == AF_INET6);
#if HAVE_IPV6
    sin6->sin6_port = htons(port);
#else
    fatal("IPv6 address passed to %s call, but nsock was not compiled w/IPv6 support", __func__);
#endif
  }

  assert(sslen <= sizeof(nse->writeinfo.dest));
  memcpy(&nse->writeinfo.dest, saddr, sslen);
  nse->writeinfo.destlen = sslen;

  assert(sslen <= sizeof(nse->iod->peer));
  memcpy(&nse->iod->peer, saddr, sslen);
  nse->iod->peerlen = sslen;

  if (datalen < 0)
    datalen = (int) strlen(data);

  if (nsp->loglevel == NSOCK_LOG_DBG_ALL && datalen < 80) {
    memcpy(displaystr, ": ", 2);
    memcpy(displaystr + 2, data, datalen);
    displaystr[2 + datalen] = '\0';
    replacenonprintable(displaystr + 2, datalen, '.');
  } else {
    displaystr[0] = '\0';
  }
  nsock_log_debug(nsp, "Sendto request for %d bytes to IOD #%li EID %li [%s]%s",
                  datalen, nsi->id, nse->id, get_peeraddr_string(nse->iod), displaystr);

  fs_cat(&nse->iobuf, data, datalen);

  nsp_add_event(nsp, nse);

  return nse->id;
}
Beispiel #7
0
/* Send back an NSE_TYPE_TIMER after the number of milliseconds specified.  Of
 * course it can also return due to error, cancellation, etc. */
nsock_event_id nsock_timer_create(nsock_pool ms_pool, nsock_ev_handler handler,
                                  int timeout_msecs, void *userdata) {
    mspool *nsp = (mspool *)ms_pool;
    msevent *nse;

    nse = msevent_new(nsp, NSE_TYPE_TIMER, NULL, timeout_msecs, handler, userdata);
    assert(nse);

    nsock_log_info(nsp, "Timer created - %dms from now.  EID %li", timeout_msecs,
                   nse->id);

    nsp_add_event(nsp, nse);

    return nse->id;
}
Beispiel #8
0
/* Requests exactly one packet to be captured. */
nsock_event_id nsock_pcap_read_packet(nsock_pool nsp, nsock_iod nsiod,
                                      nsock_ev_handler handler,
                                      int timeout_msecs, void *userdata) {
  struct niod *nsi = (struct niod *)nsiod;
  struct npool *ms = (struct npool *)nsp;
  struct nevent *nse;

  nse = event_new(ms, NSE_TYPE_PCAP_READ, nsi, timeout_msecs, handler, userdata);
  assert(nse);

  nsock_log_info(ms, "Pcap read request from IOD #%li  EID %li", nsi->id, nse->id);

  nsp_add_event(ms, nse);

  return nse->id;
}
Beispiel #9
0
/* Requests exactly one packet to be captured. */
nsock_event_id nsock_pcap_read_packet(nsock_pool nsp, nsock_iod nsiod,
                                      nsock_ev_handler handler, int timeout_msecs, void *userdata) {
  msiod *nsi = (msiod *)nsiod;
  mspool *ms = (mspool *)nsp;
  msevent *nse;

  nse = msevent_new(ms, NSE_TYPE_PCAP_READ, nsi, timeout_msecs, handler, userdata);
  assert(nse);

  if (ms->tracelevel > 0)
    nsock_trace(ms, "Pcap read request from IOD #%li  EID %li",
                nsi->id, nse->id);

  nsp_add_event(ms, nse);

  return nse->id;
}
Beispiel #10
0
/* The simplest read function -- returns NSE_STATUS_SUCCESS when it
 * reads anything, otherwise it returns timeout, eof, or error as appropriate */
nsock_event_id nsock_read(nsock_pool nsp, nsock_iod ms_iod,
                          nsock_ev_handler handler, int timeout_msecs,
                          void *userdata) {
  struct niod *nsi = (struct niod *)ms_iod;
  struct npool *ms = (struct npool *)nsp;
  struct nevent *nse;

  nse = event_new(ms, NSE_TYPE_READ, nsi, timeout_msecs, handler, userdata);
  assert(nse);

  nsock_log_info(ms, "Read request from IOD #%li [%s] (timeout: %dms) EID %li",
                 nsi->id, get_peeraddr_string(nsi), timeout_msecs, nse->id);

  nse->readinfo.read_type = NSOCK_READ;

  nsp_add_event(ms, nse);

  return nse->id;
}
Beispiel #11
0
/* Read up to nlines lines (terminated with \n, which of course includes \r\n),
 * or until EOF, or until the timeout, whichever comes first.  Note that
 * NSE_STATUS_SUCCESS will be returned in the case of EOF or timeout if at least
 * 1 char has been read.  Also note that you may get more than 'nlines' back --
 * we just stop once "at least" 'nlines' is read */
nsock_event_id nsock_readlines(nsock_pool nsp, nsock_iod ms_iod,
                               nsock_ev_handler handler, int timeout_msecs,
                               void *userdata, int nlines) {
  msiod *nsi = (msiod *)ms_iod;
  mspool *ms = (mspool *)nsp;
  msevent *nse;

  nse = msevent_new(ms, NSE_TYPE_READ, nsi, timeout_msecs, handler, userdata);
  assert(nse);

  nsock_log_info(ms, "Read request for %d lines from IOD #%li [%s] EID %li",
                 nlines, nsi->id, get_peeraddr_string(nsi), nse->id);

  nse->readinfo.read_type = NSOCK_READLINES;
  nse->readinfo.num = nlines;

  nsp_add_event(ms, nse);

  return nse->id;
}
/* Request a UNIX domain sockets connection to the same system (by path to socket).
 * This function connects to the socket of type SOCK_DGRAM.  ss should be a
 * sockaddr_storage, sockaddr_un as appropriate (just like what you would pass to
 * connect).  sslen should be the sizeof the structure you are passing in. */
nsock_event_id nsock_connect_unixsock_datagram(nsock_pool nsp, nsock_iod nsiod, nsock_ev_handler handler,
                                               void *userdata, struct sockaddr *saddr, size_t sslen) {
  msiod *nsi = (msiod *)nsiod;
  mspool *ms = (mspool *)nsp;
  msevent *nse;
  struct sockaddr_storage *ss = (struct sockaddr_storage *)saddr;

  assert(nsi->state == NSIOD_STATE_INITIAL || nsi->state == NSIOD_STATE_UNKNOWN);

  nse = msevent_new(ms, NSE_TYPE_CONNECT, nsi, -1, handler, userdata);
  assert(nse);

  nsock_log_info(ms, "UNIX domain socket (DGRAM) connection requested to %s (IOD #%li) EID %li",
                 get_unixsock_path(ss), nsi->id, nse->id);

  nsock_connect_internal(ms, nse, SOCK_DGRAM, 0, ss, sslen, 0);
  nsp_add_event(ms, nse);

  return nse->id;
}
/* Request a UDP "connection" to another system (by IP address).  The in_addr is
 * normal network byte order, but the port number should be given in HOST BYTE
 * ORDER.  Since this is UDP, no packets are actually sent.  The destination IP
 * and port are just associated with the nsiod (an actual OS connect() call is
 * made).  You can then use the normal nsock write calls on the socket.  There
 * is no timeout since this call always calls your callback at the next
 * opportunity.  The advantages to having a connected UDP socket (as opposed to
 * just specifying an address with sendto() are that we can now use a consistent
 * set of write/read calls for TCP/UDP, received packets from the non-partner
 * are automatically dropped by the OS, and the OS can provide asynchronous
 * errors (see Unix Network Programming pp224).  ss should be a
 * sockaddr_storage, sockaddr_in6, or sockaddr_in as appropriate (just like what
 * you would pass to connect).  sslen should be the sizeof the structure you are
 * passing in. */
nsock_event_id nsock_connect_udp(nsock_pool nsp, nsock_iod nsiod, nsock_ev_handler handler, void *userdata,
                                 struct sockaddr *saddr, size_t sslen, unsigned short port) {

  msiod *nsi = (msiod *)nsiod;
  mspool *ms = (mspool *)nsp;
  msevent *nse;
  struct sockaddr_storage *ss = (struct sockaddr_storage *)saddr;

  assert(nsi->state == NSIOD_STATE_INITIAL || nsi->state == NSIOD_STATE_UNKNOWN);

  nse = msevent_new(ms, NSE_TYPE_CONNECT, nsi, -1, handler, userdata);
  assert(nse);

  nsock_log_info(ms, "UDP connection requested to %s:%hu (IOD #%li) EID %li",
                 inet_ntop_ez(ss, sslen), port, nsi->id, nse->id);

  nsock_connect_internal(ms, nse, SOCK_DGRAM, IPPROTO_UDP, ss, sslen, port);
  nsp_add_event(ms, nse);

  return nse->id;
}
/* Request an SCTP association to another system (by IP address).  The in_addr
 * is normal network byte order, but the port number should be given in HOST
 * BYTE ORDER.  ss should be a sockaddr_storage, sockaddr_in6, or sockaddr_in as
 * appropriate (just like what you would pass to connect).  sslen should be the
 * sizeof the structure you are passing in. */
nsock_event_id nsock_connect_sctp(nsock_pool nsp, nsock_iod ms_iod, nsock_ev_handler handler, int timeout_msecs,
                                  void *userdata, struct sockaddr *saddr, size_t sslen, unsigned short port) {

  msiod *nsi = (msiod *)ms_iod;
  mspool *ms = (mspool *)nsp;
  msevent *nse;
  struct sockaddr_storage *ss = (struct sockaddr_storage *)saddr;

  assert(nsi->state == NSIOD_STATE_INITIAL || nsi->state == NSIOD_STATE_UNKNOWN);

  nse = msevent_new(ms, NSE_TYPE_CONNECT, nsi, timeout_msecs, handler, userdata);
  assert(nse);

  nsock_log_info(ms, "SCTP association requested to %s:%hu (IOD #%li) EID %li",
                 inet_ntop_ez(ss, sslen), port, nsi->id, nse->id);

  /* Do the actual connect() */
  nsock_connect_internal(ms, nse, SOCK_STREAM, IPPROTO_SCTP, ss, sslen, port);
  nsp_add_event(ms, nse);

  return nse->id;
}
/* Write some data to the socket.  If the write is not COMPLETED within timeout_msecs , NSE_STATUS_TIMEOUT will be returned.  If you are supplying NUL-terminated data, you can optionally pass -1 for datalen and nsock_write will figure out the length itself */
nsock_event_id  nsock_write(nsock_pool ms_pool, nsock_iod ms_iod, 
		      nsock_ev_handler handler, int timeout_msecs, 
		      void *userdata, const char *data, int datalen) {
  mspool *nsp = (mspool *) ms_pool;
  msiod *nsi = (msiod *) ms_iod;
  msevent *nse;
  char displaystr[256];

  nse = msevent_new(nsp, NSE_TYPE_WRITE, nsi, timeout_msecs, handler,
		    userdata);
  assert(nse);

  nse->writeinfo.dest.ss_family = AF_UNSPEC;

  if (datalen < 0)
    datalen = (int) strlen(data);

  if (nsp->tracelevel > 0) {
    if (nsp->tracelevel > 1 && datalen < 80) {
      memcpy(displaystr, ": ", 2);
      memcpy(displaystr + 2, data, datalen);
      displaystr[2 + datalen] = '\0';
      replacenonprintable(displaystr + 2, datalen, '.');
    } else displaystr[0] = '\0';
    if (nsi->peerlen > 0)
      nsock_trace(nsp, "Write request for %d bytes to IOD #%li EID %li [%s:%hu]%s", datalen, nsi->id, 
		  nse->id, inet_ntop_ez(&nsi->peer, nsi->peerlen), nsi_peerport(nsi), displaystr);
    else 
      nsock_trace(nsp, "Write request for %d bytes to IOD #%li EID %li (peer unspecified)%s", datalen, 
		  nsi->id, nse->id, displaystr);
  }

  fscat(&nse->iobuf, data, datalen);

  nsp_add_event(nsp, nse);
  
  return nse->id;
}
Beispiel #16
0
/* Same as nsock_write except you can use a printf-style format and you can only use this for ASCII strings */
nsock_event_id nsock_printf(nsock_pool ms_pool, nsock_iod ms_iod,
          nsock_ev_handler handler, int timeout_msecs, void *userdata, char *format, ...) {
  mspool *nsp = (mspool *)ms_pool;
  msiod *nsi = (msiod *)ms_iod;
  msevent *nse;
  char buf[4096];
  char *buf2 = NULL;
  int res, res2;
  int strlength = 0;
  char displaystr[256];

  va_list ap;
  va_start(ap,format);

  nse = msevent_new(nsp, NSE_TYPE_WRITE, nsi, timeout_msecs, handler, userdata);
  assert(nse);

  res = Vsnprintf(buf, sizeof(buf), format, ap);
  va_end(ap);

  if (res != -1) {
    if (res > sizeof(buf)) {
      buf2 = (char * )safe_malloc(res + 16);
      res2 = Vsnprintf(buf2, sizeof(buf), format, ap);
      if (res2 == -1 || res2 > res) {
        free(buf2);
        buf2 = NULL;
      } else
        strlength = res2;
    } else {
      buf2 = buf;
      strlength = res;
    }
  }

  if (!buf2) {
    nse->event_done = 1;
    nse->status = NSE_STATUS_ERROR;
    nse->errnum = EMSGSIZE;
  } else {
    if (strlength == 0) {
      nse->event_done = 1;
      nse->status = NSE_STATUS_SUCCESS;
    } else {
      fs_cat(&nse->iobuf, buf2, strlength);
    }
  }

  if (nsp->loglevel == NSOCK_LOG_DBG_ALL && nse->status != NSE_STATUS_ERROR && strlength < 80) {
    memcpy(displaystr, ": ", 2);
    memcpy(displaystr + 2, buf2, strlength);
    displaystr[2 + strlength] = '\0';
    replacenonprintable(displaystr + 2, strlength, '.');
  } else {
    displaystr[0] = '\0';
  }

  nsock_log_debug(nsp, "Write request for %d bytes to IOD #%li EID %li [%s]%s",
                  strlength, nsi->id, nse->id, get_peeraddr_string(nsi), displaystr);

  if (buf2 != buf)
    free(buf2);

  nsp_add_event(nsp, nse);

  return nse->id;
}