/*
 * Create two connections to bent pipe and make sure they reflect
 */
LONGBOW_TEST_CASE(System, two_connections)
{
    struct fdstate state[CONN_COUNT];
    fd_set fdset, readset;
    int number_writes = 100;
    int count_writes = 0;
    int i;
    struct timeval timeout = { 0, 10000 };
    unsigned pending_expected = 0;

    assertNotNull(system_bp, "%s running with null system_bp\n", __func__);

    FD_ZERO(&fdset);
    for (i = 0; i < CONN_COUNT; i++) {
        memset(&state[i], 0, sizeof(struct fdstate));
        state[i].fd = connect_to_bentpipe(local_name);
        FD_SET(state[i].fd, &fdset);
    }

    sleep(1);

    assertTrue(system_bp->conn_count == CONN_COUNT, "bp conn count wrong");

    while (count_writes < number_writes || pending_expected > 0) {
        int res;
		memcpy(&readset, &fdset, sizeof(readset));

        res = select(FD_SETSIZE, &readset, NULL, NULL, &timeout);
        if (res < 0) {
            perror("select");
            abort();
        }

        if (res > 0) {
            if (CHATTY) {
                printf("%s got res %d\n", __func__, res);
            }
            for (i = 0; i < CONN_COUNT; i++) {
                if (FD_ISSET(state[i].fd, &readset)) {
                    ssize_t res;
                    localhdr *hdr = (localhdr *) state[i].pbuff;

                    if (state[i].total_read_length == 0) {
                        size_t remaining = sizeof(localhdr) - state[i].current_read_length;
                        // we need to read a header
                        res = read(state[i].fd,
                                   state[i].pbuff + state[i].current_read_length,
                                   remaining);

                        assertFalse(res < 0, "%s got read error: %s", __func__, strerror(errno));

                        state[i].current_read_length += res;
                        if (state[i].current_read_length == sizeof(localhdr)) {
                            state[i].total_read_length = sizeof(localhdr) + hdr->length;

                            if (CHATTY) {
                                printf("%s conn %d fd %d set total length %zu\n",
                                       __func__,
                                       i,
                                       state[i].fd,
                                       state[i].total_read_length);
                            }
                        }
                    }

                    if (state[i].current_read_length < state[i].total_read_length) {
                        size_t remaining = state[i].total_read_length - state[i].current_read_length;
                        // we need to read a header
                        res = read(state[i].fd,
                                   state[i].pbuff + state[i].current_read_length,
                                   remaining);

                        assertFalse(res < 0, "%s got read error: %s", __func__, strerror(errno));
                        state[i].current_read_length += res;
                    }

                    if (state[i].current_read_length == state[i].total_read_length) {
                        // verify that it's the same as the top expected stack
                        res = compare_sends(&state[i], state[i].pbuff, state[i].total_read_length);

                        assertTrue(res == 0, "%s invalid receive compare\n", __func__);

                        state[i].count_recv++;
                        state[i].count_expected--;

                        if (CHATTY) {
                            printf("%s conn %d fd %d cnt_recv %u cnt_expected %u\n",
                                   __func__,
                                   i, state[i].fd, state[i].count_recv, state[i].count_expected);
                        }

                        // done with it
                        state[i].current_read_length = 0;
                        state[i].total_read_length = 0;
                    }
                }
            }
        }

        if ((random() % 4) == 0) {
            // do a write
            int out = random() % CONN_COUNT;

            if (CHATTY) {
                printf("%s sendbuffer for conn %d fd %d\n", __func__, out, state[out].fd);
            }

            sendbuffer(state[out].fd, state);
            count_writes++;
        }

        pending_expected = 0;
        for (i = 0; i < CONN_COUNT; i++) {
            pending_expected += state[i].count_expected;
        }
    }

    for (i = 0; i < CONN_COUNT; i++) {
        printf("conn %2d fd %2d send %4u recv %4u\n",
               i,
               state[i].fd,
               state[i].count_send,
               state[i].count_recv);

        assertTrue(state[i].count_recv == number_writes - state[i].count_send + 1,
                   "%s conn %d incorrect counts\n",
                   __func__);
        close(state[i].fd);
    }
}
Example #2
0
// Send a report message.
int v3MP::send_report(unsigned char* scopedPDU, int scopedPDULength,
		      struct snmp_pdu *pdu, int errorCode, int sLevel,
		      int sModel, OctetStr &sName,
		      UdpAddress &destination, Snmp *snmp_session)
{
  debugprintf(2, "v3MP::send_report: Sending report message.");

  unsigned char *data;
  int dataLength;
  int pdu_type = 0;
  unsigned char cEngineID[MAXLENGTH_ENGINEID+1];
  unsigned char cName[MAXLENGTH_CONTEXT_NAME+1];
  int cEngineIDLength = MAXLENGTH_ENGINEID+1;
  int cNameLength = MAXLENGTH_CONTEXT_NAME+1;

  debugprintf(2, "v3MP::send_report: securityLevel %d",sLevel);

  if (scopedPDULength != MAX_SNMP_PACKET)
  {
    // try to get scopedPDU and PDU
    data = asn1_parse_scoped_pdu(scopedPDU, &scopedPDULength,
				 cEngineID, &cEngineIDLength,
				 cName, &cNameLength);
    if (data == NULL) {
      debugprintf(1, "mp: Error while trying to parse  scopedPDU!");
      cEngineID[0] = '\0';
      cEngineIDLength = 0;
      cName[0] = '\0';
      cNameLength = 0;
      // Dont send encrypted report if decryption failed:
      //if (sLevel == SNMP_SECURITY_LEVEL_AUTH_PRIV)
     //   sLevel = SNMP_SECURITY_LEVEL_AUTH_NOPRIV;
    }
    else { // data != NULL
      dataLength = scopedPDULength;

      // parse data of scopedPDU
      snmp_parse_data_pdu(pdu, data, dataLength);
      pdu_type = pdu->command;

      if (!data) {
        debugprintf(0, "mp: Error while trying to parse PDU!");
      }
    } // end of: if (data == NULL)
  } // end if (scopedPDULength != MAX_SNMP_PACKET)
  else { // scopedPDULength == MAX_SNMP_PACKET
    cEngineID[0] = '\0';
    cEngineIDLength = 0;
    cName[0] = '\0';
    cNameLength = 0;
    pdu->reqid = 0;
  }

  clear_pdu(pdu);   // Clear pdu and free all content

  debugprintf(4, "pdu->reqid = %ld",pdu->reqid);
  pdu->errstat = 0;
  pdu->errindex = 0;
  pdu->command = REPORT_MSG;

  Vb counterVb;
  Oid counterOid;
  SmiLPOID smioid;
  SmiVALUE smival;

  switch (errorCode) {
    case SNMPv3_MP_INVALID_MESSAGE:
    case SNMPv3_USM_PARSE_ERROR: {
      counterVb.set_oid(oidSnmpInvalidMsgs);
      counterVb.set_value(Counter32(get_stats_invalid_msgs()));
      break;
    }
    case SNMPv3_USM_NOT_IN_TIME_WINDOW:
    case SNMPv3_MP_NOT_IN_TIME_WINDOW: {
      counterVb.set_oid(oidUsmStatsNotInTimeWindows);
      counterVb.set_value(Counter32(usm->get_stats_not_in_time_windows()));
      break;
    }
    case SNMPv3_USM_DECRYPTION_ERROR: {
      counterVb.set_oid(oidUsmStatsDecryptionErrors);
      counterVb.set_value(Counter32(usm->get_stats_decryption_errors()));
      //sLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV;
      break;
    }
    case SNMPv3_USM_AUTHENTICATION_ERROR:
    case SNMPv3_USM_AUTHENTICATION_FAILURE: {
      counterVb.set_oid(oidUsmStatsWrongDigests);
      counterVb.set_value(Counter32(usm->get_stats_wrong_digests()));
      //sLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV;
      break;
    }
    case SNMPv3_USM_UNKNOWN_ENGINEID:
    case SNMPv3_MP_INVALID_ENGINEID: {
      //sLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV;
      counterVb.set_oid(oidUsmStatsUnknownEngineIDs);
      counterVb.set_value(Counter32(usm->get_stats_unknown_engine_ids()));
      break;
    }
    case SNMPv3_MP_UNSUPPORTED_SECURITY_MODEL: {
      counterVb.set_oid(oidSnmpUnknownSecurityModels);
      counterVb.set_value(Counter32(get_stats_unknown_security_models()));
      sModel = SNMP_SECURITY_MODEL_USM;
      sLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV;
    break;
    }
    case SNMPv3_USM_UNKNOWN_SECURITY_NAME: {
      counterVb.set_oid(oidUsmStatsUnknownUserNames);
      counterVb.set_value(Counter32(usm->get_stats_unknown_user_names()));
      sLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV;
      debugprintf(2, "Report: SecurityName: %s",sName.get_printable());
      break;
    }
    case SNMPv3_USM_UNSUPPORTED_SECURITY_LEVEL: {
      counterVb.set_oid(oidUsmStatsUnsupportedSecLevels);
      counterVb.set_value(Counter32(usm->get_stats_unsupported_sec_levels()));
      sLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV;
      break;
    }
    default: {
      counterVb.set_oid(oidSnmpInvalidMsgs);
      counterVb.set_value(Counter32(get_stats_invalid_msgs()));
      sModel = SNMP_SECURITY_MODEL_USM;
      sLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV;
      sName.set_data(0, 0);

      debugprintf(2, "ErrorCode was %i in snmp_parse", errorCode);
    }
  } // end switch

  counterVb.get_oid(counterOid);
  smioid = counterOid.oidval();

  int status = convertVbToSmival(counterVb, &smival);
  if (status != SNMP_CLASS_SUCCESS) {
    return SNMPv3_MP_ERROR;
  }
  snmp_add_var(pdu, smioid->ptr,
               (int) smioid->len, &smival);
  freeSmivalDescriptor(&smival);

  Buffer<unsigned char> sendbuffer(MAX_SNMP_PACKET);
  int sendbufferlen= MAX_SNMP_PACKET;
  status = snmp_build( pdu, sendbuffer.get_ptr(), &sendbufferlen,
		       own_engine_id_oct, sName, sModel, sLevel,
		       OctetStr(cEngineID, cEngineIDLength),
		       OctetStr(cName, cNameLength));
  if (status != SNMPv3_MP_OK) {
    debugprintf(2, "v3MP::send_report: error serializing message (mpSnmpBuild returns: %i).", status);
    return SNMPv3_MP_ERROR;
  }
  SnmpSocket send_fd = INVALID_SOCKET;
  if (pdu_type == sNMP_PDU_INFORM)
  {
    debugprintf(4, "Received a snmpInform pdu.");
    if (snmp_session->get_eventListHolder()->notifyEventList())
      send_fd = snmp_session->get_eventListHolder()->notifyEventList()->get_notify_fd();
  }

  status = snmp_session->send_raw_data(sendbuffer.get_ptr(),
                                       (size_t)sendbufferlen,// pdu to send
			               destination,          // target address
			               send_fd);             // the fd to use
  if ( status != 0)
  {
    debugprintf(1, "v3MP::send_report: error sending message (%i)", status);
    return SNMPv3_MP_ERROR;
  }
  debugprintf(3, "v3MP::send_report: Report sent.");
  return SNMPv3_MP_OK;
}