Пример #1
0
/* Remember that pcap descriptor is in nonblocking state. */
int do_actual_pcap_read(msevent *nse) {
  mspcap *mp = (mspcap *)nse->iod->pcap;
  nsock_pcap npp;
  nsock_pcap *n;
  struct pcap_pkthdr *pkt_header;
  const unsigned char *pkt_data = NULL;
  int rc;

  memset(&npp, 0, sizeof(nsock_pcap));

  if (nse->iod->nsp->tracelevel > 2)
    nsock_trace(nse->iod->nsp, "PCAP do_actual_pcap_read TEST (IOD #%li) (EID #%li)",
                nse->iod->id, nse->id);

  assert( FILESPACE_LENGTH(&(nse->iobuf)) == 0 );

  rc = pcap_next_ex(mp->pt, &pkt_header, &pkt_data);
  switch(rc) {
    case 1: /* read good packet  */
      #ifdef PCAP_RECV_TIMEVAL_VALID
      npp.ts     = pkt_header->ts;
      #else
      /* on these platforms time received from pcap is invalid. It's better to set current time */
      memcpy(&npp.ts, nsock_gettimeofday(), sizeof(struct timeval));
      #endif
      npp.len    = pkt_header->len;
      npp.caplen = pkt_header->caplen;
      npp.packet = pkt_data;

      fscat(&(nse->iobuf), (char *)&npp, sizeof(npp));
      fscat(&(nse->iobuf), (char *)pkt_data, npp.caplen);
      n = (nsock_pcap *)FILESPACE_STR(&(nse->iobuf));
      n->packet = (unsigned char *)FILESPACE_STR(&(nse->iobuf)) + sizeof(npp);

      if (nse->iod->nsp->tracelevel > 2)
        nsock_trace(nse->iod->nsp, "PCAP do_actual_pcap_read READ (IOD #%li) (EID #%li) size=%i",
                    nse->iod->id, nse->id, pkt_header->caplen);
      return(1);

    case 0: /* timeout */
      return(0);

    case -1: /* error */
      fatal("pcap_next_ex() fatal error while reading from pcap: %s\n", pcap_geterr(mp->pt));
      break;

    case -2: /* no more packets in savefile (if reading from one) */
    default:
      assert(0);
  }
  return 0;
}
Пример #2
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 (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;
}
Пример #3
0
void test_fscat()
{
	char c[PATH_MAX + 1];
	char *d, *f, *res = "directory/file";

	d = "directory";
	f = "file";
	fscat(d, f, c);
	if (strcmp(res, c) != 0) {
		fprintf(stderr, "%s + %s = %s\n", d, f, c);
		fprintf(stderr, "Invalid fscatination\n");
		abort();
	}

	d = "directory/";
	f = "file";
	fscat(d, f, c);
	if (strcmp(res, c) != 0) {
		fprintf(stderr, "%s + %s = %s\n", d, f, c);
		fprintf(stderr, "Invalid fscatination\n");
		abort();
	}

	d = "directory";
	f = "/file";
	fscat(d, f, c);
	if (strcmp(res, c) != 0) {
		fprintf(stderr, "%s + %s = %s\n", d, f, c);
		fprintf(stderr, "Invalid fscatination\n");
		abort();
	}

	d = "directory///";
	f = "file";
	fscat(d, f, c);
	if (strcmp(res, c) != 0) {
		fprintf(stderr, "%s + %s = %s\n", d, f, c);
		fprintf(stderr, "Invalid fscatination\n");
		abort();
	}

	d = "directory";
	f = "///file";
	fscat(d, f, c);
	if (strcmp(res, c) != 0) {
		fprintf(stderr, "%s + %s = %s\n", d, f, c);
		fprintf(stderr, "Invalid fscatination\n");
		abort();
	}

	d = "directory///";
	f = "///file";
	fscat(d, f, c);
	if (strcmp(res, c) != 0) {
		fprintf(stderr, "%s + %s = %s\n", d, f, c);
		fprintf(stderr, "Invalid fscatination\n");
		abort();
	}
}
Пример #4
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->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;
}
Пример #5
0
/* Returns -1 if an error, otherwise the number of newly written bytes */
static int do_actual_read(mspool *ms, msevent *nse) {
  char buf[8192];
  int buflen = 0;
  msiod *iod = nse->iod;
  int err = 0;
  int max_chunk = NSOCK_READ_CHUNK_SIZE;
  int startlen = FILESPACE_LENGTH(&nse->iobuf);

  if (nse->readinfo.read_type == NSOCK_READBYTES)
    max_chunk = nse->readinfo.num;

  if (!iod->ssl) {
    do {
      struct sockaddr_storage peer;
      socklen_t peerlen;

      peerlen = sizeof(peer);
      buflen = recvfrom(iod->sd, buf, sizeof(buf), 0, (struct sockaddr *)&peer, &peerlen);

      /* Using recv() was failing, at least on UNIX, for non-network sockets
       * (i.e. stdin) in this case, a read() is done - as on ENOTSOCK we may
       * have a non-network socket */
      if (buflen == -1) {
        if (socket_errno() == ENOTSOCK) {
          peer.ss_family = AF_UNSPEC;
          peerlen = 0;
          buflen = read(iod->sd, buf, sizeof(buf));
        }
      }
      if (buflen == -1) {
        err = socket_errno();
        break;
      }
      if (peerlen > 0) {
        assert(peerlen <= sizeof(iod->peer));
        memcpy(&iod->peer, &peer, peerlen);
        iod->peerlen = peerlen;
      }
      if (buflen > 0) {
        if (fscat(&nse->iobuf, buf, buflen) == -1) {
          nse->event_done = 1;
          nse->status = NSE_STATUS_ERROR;
          nse->errnum = ENOMEM;
          return -1;
        }

        /* Sometimes a service just spews and spews data.  So we return after a
         * somewhat large amount to avoid monopolizing resources and avoid DOS
         * attacks. */
        if (FILESPACE_LENGTH(&nse->iobuf) > max_chunk)
          return FILESPACE_LENGTH(&nse->iobuf) - startlen;

        /* No good reason to read again if we we were successful in the read but
         * didn't fill up the buffer.  Especially for UDP, where we want to
         * return only one datagram at a time. The consistency of the above
         * assignment of iod->peer depends on not consolidating more than one
         * UDP read buffer. */
        if (buflen > 0 && buflen < sizeof(buf))
          return FILESPACE_LENGTH(&nse->iobuf) - startlen;
      }
    } while (buflen > 0 || (buflen == -1 && err == EINTR));

    if (buflen == -1) {
      if (err != EINTR && err != EAGAIN) {
        nse->event_done = 1;
        nse->status = NSE_STATUS_ERROR;
        nse->errnum = err;
        return -1;
      }
    }
  } else {
#if HAVE_OPENSSL
    /* OpenSSL read */
    while ((buflen = SSL_read(iod->ssl, buf, sizeof(buf))) > 0) {

      if (fscat(&nse->iobuf, buf, buflen) == -1) {
        nse->event_done = 1;
        nse->status = NSE_STATUS_ERROR;
        nse->errnum = ENOMEM;
        return -1;
      }

      /* Sometimes a service just spews and spews data.  So we return
       * after a somewhat large amount to avoid monopolizing resources
       * and avoid DOS attacks. */
      if (FILESPACE_LENGTH(&nse->iobuf) > max_chunk)
        return FILESPACE_LENGTH(&nse->iobuf) - startlen;
    }

    if (buflen == -1) {
      err = SSL_get_error(iod->ssl, buflen);
      if (err == SSL_ERROR_WANT_READ) {
        int evclr;

        evclr = socket_count_dec_ssl_desire(nse);
        socket_count_read_inc(iod);
        update_events(iod, ms, EV_READ, evclr);
        nse->sslinfo.ssl_desire = err;
      } else if (err == SSL_ERROR_WANT_WRITE) {
        int evclr;

        evclr = socket_count_dec_ssl_desire(nse);
        socket_count_write_inc(iod);
        update_events(iod, ms, EV_WRITE, evclr);
        nse->sslinfo.ssl_desire = err;
      } else {
        /* Unexpected error */
        nse->event_done = 1;
        nse->status = NSE_STATUS_ERROR;
        nse->errnum = EIO;
        if (ms->tracelevel > 2)
          nsock_trace(ms, "SSL_read() failed for reason %s on NSI %li",
                      ERR_reason_error_string(err), iod->id);
        return -1;
      }
    }
#endif /* HAVE_OPENSSL */
  }

  if (buflen == 0) {
    nse->event_done = 1;
    nse->eof = 1;
    if (FILESPACE_LENGTH(&nse->iobuf) > 0) {
      nse->status = NSE_STATUS_SUCCESS;
      return FILESPACE_LENGTH(&nse->iobuf) - startlen;
    } else {
      nse->status = NSE_STATUS_EOF;
      return 0;
    }
  }

  return FILESPACE_LENGTH(&nse->iobuf) - startlen;
}
Пример #6
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 {    
      fscat(&nse->iobuf, buf2, strlength);
    }
  }

  if (nsp->tracelevel > 0) {
    if (nsp->tracelevel > 1 && 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';
    if (nsi->peerlen > 0)
      nsock_trace(nsp, "Write request for %d bytes to IOD #%li EID %li [%s:%hu]%s", strlength, 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", strlength, 
		  nsi->id, nse->id, displaystr);
  }

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

  nsp_add_event(nsp, nse);

  return nse->id;
}