예제 #1
0
/* An event has been completed and the handler is about to be called. This
 * function writes out tracing data about the event if necessary */
void nsock_trace_handler_callback(struct npool *ms, struct nevent *nse) {
  struct niod *nsi;
  char *str;
  int strlength = 0;
  char displaystr[256];
  char errstr[256];

  if (NsockLogLevel > NSOCK_LOG_INFO)
    return;

  nsi = nse->iod;

  if (nse->status == NSE_STATUS_ERROR)
    Snprintf(errstr, sizeof(errstr), "[%s (%d)] ", socket_strerror(nse->errnum),
             nse->errnum);
  else
    errstr[0] = '\0';

  /* Some types have special tracing treatment */
  switch (nse->type) {
    case NSE_TYPE_CONNECT:
    case NSE_TYPE_CONNECT_SSL:
      nsock_log_info("Callback: %s %s %sfor EID %li [%s]",
                     nse_type2str(nse->type), nse_status2str(nse->status),
                     errstr, nse->id, get_peeraddr_string(nsi));
      break;

    case NSE_TYPE_READ:
      if (nse->status != NSE_STATUS_SUCCESS) {
        nsock_log_info("Callback: %s %s %sfor EID %li [%s]",
                       nse_type2str(nse->type), nse_status2str(nse->status),
                       errstr, nse->id, get_peeraddr_string(nsi));
      } else {
        str = nse_readbuf(nse, &strlength);
        if (strlength < 80) {
          memcpy(displaystr, ": ", 2);
          memcpy(displaystr + 2, str, strlength);
          displaystr[2 + strlength] = '\0';
          replacenonprintable(displaystr + 2, strlength, '.');
        } else {
          displaystr[0] = '\0';
        }
        nsock_log_info("Callback: %s %s for EID %li [%s] %s(%d bytes)%s",
                       nse_type2str(nse->type), nse_status2str(nse->status),
                       nse->id,
                       get_peeraddr_string(nsi),
                       nse_eof(nse) ? "[EOF]" : "", strlength, displaystr);
      }
      break;

    case NSE_TYPE_WRITE:
      nsock_log_info("Callback: %s %s %sfor EID %li [%s]",
                     nse_type2str(nse->type), nse_status2str(nse->status),
                     errstr, nse->id, get_peeraddr_string(nsi));
      break;

    case NSE_TYPE_TIMER:
      nsock_log_info("Callback: %s %s %sfor EID %li",
                     nse_type2str(nse->type), nse_status2str(nse->status),
                     errstr, nse->id);
      break;

#if HAVE_PCAP
    case NSE_TYPE_PCAP_READ:
      nsock_log_info("Callback: %s %s %sfor EID %li ",
                     nse_type2str(nse->type), nse_status2str(nse->status),
                     errstr, nse->id);
      break;
#endif

    default:
      fatal("Invalid nsock event type (%d)", nse->type);
  }
}
예제 #2
0
파일: nsock_telnet.c 프로젝트: 6e6f36/nmap
void telnet_event_handler(nsock_pool nsp, nsock_event nse, void *mydata) {
  nsock_iod nsi = nse_iod(nse);
  enum nse_status status = nse_status(nse);
  enum nse_type type = nse_type(nse);
  struct sockaddr_in peer;
  struct telnet_state *ts;
  int nbytes;
  char *str;
  int read_timeout = -1;
  int write_timeout = 2000;
  ts = (struct telnet_state *)mydata;

  printf("telnet_event_handler: Received callback of type %s with status %s\n", nse_type2str(type), nse_status2str(status));

  if (status == NSE_STATUS_SUCCESS) {
    switch (type) {
    case NSE_TYPE_CONNECT:
    case NSE_TYPE_CONNECT_SSL:
      nsi_getlastcommunicationinfo(nsi, NULL, NULL, NULL, (struct sockaddr *)&peer, sizeof peer);
      printf("Successfully connected %sto %s:%hu -- start typing lines\n", (type == NSE_TYPE_CONNECT_SSL) ? "(SSL!) " : "", inet_ntoa(peer.sin_addr), peer.sin_port);
      /* First of all, lets add STDIN to our list of watched filehandles */
      if ((ts->stdin_nsi = nsi_new2(nsp, STDIN_FILENO, NULL)) == NULL) {
        fprintf(stderr, "Failed to create stdin msi\n");
        exit(1);
      }

      /* Now lets read from stdin and the network, line buffered (by nsock) */
      ts->latest_readtcpev = nsock_readlines(nsp, ts->tcp_nsi, telnet_event_handler, read_timeout, ts, 1);
      ts->latest_readstdinev = nsock_readlines(nsp, ts->stdin_nsi, telnet_event_handler, read_timeout, ts, 1);
      break;
    case NSE_TYPE_READ:
      str = nse_readbuf(nse, &nbytes);
      if (nsi == ts->tcp_nsi) {
        printf("%s", str);
        /*       printf("Read from tcp socket (%d bytes):\n%s", nbytes, str); */
        ts->latest_readtcpev = nsock_readlines(nsp, ts->tcp_nsi, telnet_event_handler, read_timeout, ts, 1);
      } else {
        /*       printf("Read from  stdin (%d bytes):\n%s", nbytes, str); */
        nsock_write(nsp, ts->tcp_nsi, telnet_event_handler, write_timeout, ts, str, nbytes);
        ts->latest_readstdinev = nsock_readlines(nsp, ts->stdin_nsi, telnet_event_handler, read_timeout, ts, 1);
      }
      break;
    case NSE_TYPE_WRITE:
      /* Nothing to do, really */
      break;
    case NSE_TYPE_TIMER:
      break;
    default:
      fprintf(stderr, "telnet_event_handler: Got bogus type -- quitting\n");
      exit(1);
      break;
    }
  } else if (status == NSE_STATUS_EOF) {
    printf("Got EOF from %s\nCancelling outstanding readevents.\n", (nsi == ts->tcp_nsi) ? "tcp socket" : "stdin");
    /* One of these is the event I am currently handling!  But I wanted to
       be evil when testing this out... */
    if (nsock_event_cancel(nsp, ts->latest_readtcpev, 1) != 0) {
      printf("Cancelled tcp event: %li\n", ts->latest_readtcpev);
    }
    if (nsock_event_cancel(nsp, ts->latest_readstdinev, 1) != 0) {
      printf("Cancelled stdin event: %li\n", ts->latest_readstdinev);
    }
  } else if (status == NSE_STATUS_ERROR) {
    if (nsi_checkssl(nsi)) {
      printf("SSL %s failed: %s\n", nse_type2str(type), ERR_error_string(ERR_get_error(), NULL));
    } else {
      int err;

      err = nse_errorcode(nse);
      printf("%s failed: (%d) %s\n", nse_type2str(type), err, strerror(err));
    }
  }
  return;
}
예제 #3
0
파일: nsock_core.c 프로젝트: alex-chan/nmap
/* An event has been completed and the handler is about to be called. This
 * function writes out tracing data about the event if necessary */
void nsock_trace_handler_callback(mspool *ms, msevent *nse) {
  msiod *nsi;
  char *str;
  int strlength = 0;
  char displaystr[256];
  char errstr[256];

  if (ms->tracelevel == 0)
    return;

  nsi = nse->iod;

  if (nse->status == NSE_STATUS_ERROR)
    Snprintf(errstr, sizeof(errstr), "[%s (%d)] ", socket_strerror(nse->errnum), nse->errnum);
  else
    errstr[0] = '\0';

  /* Some types have special tracing treatment */
  switch(nse->type) {
    case NSE_TYPE_CONNECT:
    case NSE_TYPE_CONNECT_SSL:
      nsock_trace(ms, "Callback: %s %s %sfor EID %li [%s]",
                  nse_type2str(nse->type), nse_status2str(nse->status),
                  errstr, nse->id, get_peeraddr_string(nsi));
      break;

    case NSE_TYPE_READ:
      if (nse->status != NSE_STATUS_SUCCESS) {
        if (nsi->peerlen > 0) {
          nsock_trace(ms, "Callback: %s %s %sfor EID %li [%s]",
                      nse_type2str(nse->type), nse_status2str(nse->status),
                      errstr, nse->id, get_peeraddr_string(nsi));
        } else {
          nsock_trace(ms, "Callback: %s %s %sfor EID %li (peer unspecified)",
                      nse_type2str(nse->type), nse_status2str(nse->status),
                      errstr, nse->id);
        }
      } else {
        str = nse_readbuf(nse, &strlength);
        if (ms->tracelevel > 1 && strlength < 80) {
          memcpy(displaystr, ": ", 2);
          memcpy(displaystr + 2, str, strlength);
          displaystr[2 + strlength] = '\0';
          replacenonprintable(displaystr + 2, strlength, '.');
        } else {
          displaystr[0] = '\0';
        }

        if (nsi->peerlen > 0) {
          nsock_trace(ms, "Callback: %s %s for EID %li [%s] %s(%d bytes)%s",
                      nse_type2str(nse->type), nse_status2str(nse->status),
                      nse->id, get_peeraddr_string(nsi),
                      nse_eof(nse)? "[EOF]" : "", strlength, displaystr);
        } else {
          nsock_trace(ms, "Callback %s %s for EID %li (peer unspecified) %s(%d bytes)%s",
                      nse_type2str(nse->type), nse_status2str(nse->status),
                      nse->id, nse_eof(nse)? "[EOF]" : "", strlength, displaystr);
        }
      }
      break;

    case NSE_TYPE_WRITE:
      nsock_trace(ms, "Callback: %s %s %sfor EID %li [%s]",
                  nse_type2str(nse->type), nse_status2str(nse->status), errstr,
                  nse->id, get_peeraddr_string(nsi));
      break;

    case NSE_TYPE_TIMER:
      nsock_trace(ms, "Callback: %s %s %sfor EID %li",
                  nse_type2str(nse->type), nse_status2str(nse->status), errstr,
                  nse->id);
      break;

#if HAVE_PCAP
    case NSE_TYPE_PCAP_READ:
      nsock_trace(ms, "Callback: %s %s %sfor EID %li ",
                  nse_type2str(nse->type), nse_status2str(nse->status),
                  errstr, nse->id);
      break;
#endif

    default:
      assert(0);
      break;
  }
}
예제 #4
0
void timer_handler(nsock_pool nsp, nsock_event nse, void *mydata) {
  enum nse_status status = nse_status(nse);
  enum nse_type type = nse_type(nse);
  int rnd, rnd2;

  printf("%ld:timer_handler: Received callback of type %s; status %s; id %li\n", time(NULL), nse_type2str(type), nse_status2str(status), nse_id(nse));

  rnd = rand() % num_ids;
  rnd2 = rand() % 3;

  if (num_ids > (sizeof(ev_ids) / sizeof(nsock_event_id)) - 3) {
    printf("\n\nSUCCEEDED DUE TO CREATING ENOUGH EVENTS THAT IT WAS GOING TO OVERFLOW MY BUFFER :)\n\n");
    exit(0);
  }

  if (status == NSE_STATUS_SUCCESS) {
    switch (rnd2) {
    case 0:
      /* do nothing */
      /* Actually I think I'll create two timers :) */
      ev_ids[num_ids++] = request_timer(nsp, timer_handler, rand() % 3000, NULL);
      ev_ids[num_ids++] = request_timer(nsp, timer_handler, rand() % 3000, NULL);
      break;
    case 1:
      /* Kill another id (which may or may not be active */
      try_cancel_timer(nsp, rnd, rand() % 2);
      break;
    case 2:
      /* Create a new timer */
      ev_ids[num_ids++] = request_timer(nsp, timer_handler, rand() % 3000, NULL);
      break;
    default:
      assert(0);
    }
  }
}
예제 #5
0
/* An internal function for cancelling an event when you already have a pointer
 * to the msevent (use nsock_event_cancel if you just have an ID). The
 * event_list passed in should correspond to the type of the event. For example,
 * with NSE_TYPE_READ, you would pass in &nsp->read_events;. elem is the list
 * element in event_list which holds the event.  Pass a nonzero for notify if
 * you want the program owning the event to be notified that it has been
 * cancelled */
int msevent_cancel(mspool *nsp, msevent *nse, gh_list_t *event_list,
                   gh_lnode_t *elem, int notify) {
  if (nse->event_done) {
    /* This event has already been marked for death somewhere else -- it will be
     * gone soon (and if we try to kill it now all hell will break loose due to
     * reentrancy. */
    return 0;
  }

  nsock_log_info(nsp, "msevent_cancel on event #%li (type %s)",
                 nse->id, nse_type2str(nse->type));

  /* Now that we found the event... we go through the motions of cleanly
   * cancelling it */
  switch (nse->type) {
    case NSE_TYPE_CONNECT:
    case NSE_TYPE_CONNECT_SSL:
      handle_connect_result(nsp, nse, NSE_STATUS_CANCELLED);
      break;

    case NSE_TYPE_READ:
      handle_read_result(nsp, nse, NSE_STATUS_CANCELLED);
      break;

    case NSE_TYPE_WRITE:
      handle_write_result(nsp, nse, NSE_STATUS_CANCELLED);
      break;

    case NSE_TYPE_TIMER:
      handle_timer_result(nsp, nse, NSE_STATUS_CANCELLED);
      break;

#if HAVE_PCAP
    case NSE_TYPE_PCAP_READ:
      handle_pcap_read_result(nsp, nse, NSE_STATUS_CANCELLED);
      break;
#endif

    default:
      fatal("Invalid nsock event type (%d)", nse->type);
  }

  assert(nse->event_done);

  if (nse->timeout.tv_sec)
    gh_heap_remove(&nsp->expirables, &nse->expire);

  if (event_list) {
    update_first_events(nse);
    gh_list_remove(event_list, elem);
  }

  gh_list_append(&nsp->free_events, &nse->nodeq_io);

  nsock_log_debug_all(nsp, "NSE #%lu: Removing event from list", nse->id);

#if HAVE_PCAP
#if PCAP_BSD_SELECT_HACK
  if (nse->type == NSE_TYPE_PCAP_READ) {
    nsock_log_debug_all(nsp, "PCAP NSE #%lu: CANCEL TEST pcap=%p read=%p curr=%p sd=%i",
                        nse->id, &nsp->pcap_read_events, &nsp->read_events,
                        event_list,((mspcap *)nse->iod->pcap)->pcap_desc);

    /* If event occurred, and we're in BSD_HACK mode, then this event was added to
     * two queues. read_event and pcap_read_event Of course we should
     * destroy it only once.  I assume we're now in read_event, so just unlink
     * this event from pcap_read_event */
    if (((mspcap *)nse->iod->pcap)->pcap_desc >= 0 && event_list == &nsp->read_events) {
      /* event is done, list is read_events and we're in BSD_HACK mode. So unlink
       * event from pcap_read_events */
      gh_list_remove(&nsp->pcap_read_events, &nse->nodeq_pcap);
      nsock_log_debug_all(nsp, "PCAP NSE #%lu: Removing event from PCAP_READ_EVENTS", nse->id);
    }

    if (((mspcap *)nse->iod->pcap)->pcap_desc >= 0 && event_list == &nsp->pcap_read_events) {
      /* event is done, list is read_events and we're in BSD_HACK mode.
       * So unlink event from read_events */
      gh_list_remove(&nsp->read_events, &nse->nodeq_io);

      nsock_log_debug_all(nsp, "PCAP NSE #%lu: Removing event from READ_EVENTS", nse->id);
    }
  }
#endif
#endif
  msevent_dispatch_and_delete(nsp, nse, notify);
  return 1;
}
예제 #6
0
/* Cancel an event (such as a timer or read request).  If notify is nonzero, the
 * requester will be sent an event CANCELLED status back to the given handler.
 * But in some cases there is no need to do this (like if the function deleting
 * it is the one which created it), in which case 0 can be passed to skip the
 * step.  This function returns zero if the event is not found, nonzero
 * otherwise. */
int nsock_event_cancel(nsock_pool ms_pool, nsock_event_id id, int notify) {
  mspool *nsp = (mspool *)ms_pool;
  enum nse_type type;
  unsigned int i;
  gh_list_t *event_list = NULL, *event_list2 = NULL;
  gh_lnode_t *current, *next;
  msevent *nse = NULL;

  assert(nsp);

  type = get_event_id_type(id);
  nsock_log_info(nsp, "Event #%li (type %s) cancelled", id, nse_type2str(type));

  /* First we figure out what list it is in */
  switch (type) {
    case NSE_TYPE_CONNECT:
    case NSE_TYPE_CONNECT_SSL:
      event_list = &nsp->connect_events;
      break;

    case NSE_TYPE_READ:
      event_list = &nsp->read_events;
      break;

    case NSE_TYPE_WRITE:
      event_list = &nsp->write_events;
      break;

    case NSE_TYPE_TIMER:
      for (i = 0; i < gh_heap_count(&nsp->expirables); i++) {
        gh_hnode_t *hnode;

        hnode = gh_heap_find(&nsp->expirables, i);
        nse = container_of(hnode, msevent, expire);
        if (nse->id == id)
          return msevent_cancel(nsp, nse, NULL, NULL, notify);
      }
      return 0;

#if HAVE_PCAP
    case NSE_TYPE_PCAP_READ:
      event_list  = &nsp->read_events;
      event_list2 = &nsp->pcap_read_events;
      break;
#endif

    default:
      fatal("Bogus event type in nsock_event_cancel"); break;
  }

  /* Now we try to find the event in the list */
  for (current = gh_list_first_elem(event_list); current != NULL; current = next) {
    next = gh_lnode_next(current);
    nse = lnode_msevent(current);
    if (nse->id == id)
      break;
  }

  if (current == NULL && event_list2) {
    event_list = event_list2;
    for (current = gh_list_first_elem(event_list); current != NULL; current = next) {
      next = gh_lnode_next(current);
      nse = lnode_msevent2(current);
      if (nse->id == id)
        break;
    }
  }
  if (current == NULL)
    return 0;

  return msevent_cancel(nsp, nse, event_list, current, notify);
}
예제 #7
0
/* Cancel an event (such as a timer or read request).  If notify is nonzero, the
 * requester will be sent an event CANCELLED status back to the given handler.
 * But in some cases there is no need to do this (like if the function deleting
 * it is the one which created it), in which case 0 can be passed to skip the
 * step.  This function returns zero if the event is not found, nonzero
 * otherwise. */
int nsock_event_cancel(nsock_pool ms_pool, nsock_event_id id, int notify) {
  mspool *nsp = (mspool *)ms_pool;
  enum nse_type type;
  gh_list *event_list = NULL, *event_list2 = NULL;
  gh_list_elem *current, *next;
  msevent *nse = NULL;

  assert(nsp);

  type = get_event_id_type(id);
  nsock_log_info(nsp, "Event #%li (type %s) cancelled", id, nse_type2str(type));

  /* First we figure out what list it is in */
  switch(type) {
    case NSE_TYPE_CONNECT:
      event_list = &nsp->connect_events;
      break;

    case NSE_TYPE_READ:
      event_list = &nsp->read_events;
      break;

    case NSE_TYPE_WRITE:
      event_list = &nsp->write_events;
      break;

    case NSE_TYPE_TIMER:
      event_list = &nsp->timer_events;
      break;

#if HAVE_PCAP
    case NSE_TYPE_PCAP_READ:
      event_list  = &nsp->read_events;
      event_list2 = &nsp->pcap_read_events;
      break;
#endif

    default:
      fatal("Bogus event type in nsock_event_cancel"); break;
  }

  /* Now we try to find the event in the list */
  for (current = GH_LIST_FIRST_ELEM(event_list); current != NULL;  current = next) {
    next = GH_LIST_ELEM_NEXT(current);
    nse = (msevent *)GH_LIST_ELEM_DATA(current);
    if (nse->id == id)
      break;
  }

  if (current == NULL && event_list2){
    event_list = event_list2;
    for (current = GH_LIST_FIRST_ELEM(event_list); current != NULL; current = next) {
      next = GH_LIST_ELEM_NEXT(current);
      nse = (msevent *)GH_LIST_ELEM_DATA(current);
      if (nse->id == id)
        break;
    }
  }
  if (current == NULL)
    return 0;

  return msevent_cancel(nsp, nse, event_list, current, notify);
}