/**
   * Create an SNMP trap, based on the content of the specified event, and forward the trap to the
   * specified address and port. It is assumed that the specified event represents an SNMP V1 or V2
   * trap that was received by OpenNMS (TrapD). The type of trap to be created depends on the type
   * of the original trap (i.e. if the original trap was an SNMP V1 trap, an SNMP V1 trap will be
   * created; if the original trap was an SNMP V2 trap, an SNMP V2 trap will be created).
   *
   * @param event The event upon which the trap content should be based
   * @param destAddr The address to which the trap should be forwarded
   * @param destPort The port to which the trap should be forwarded
   * @exception Throws SnmpTrapHelperException if the variable binding cannot be added to the trap
   *     for any reason.
   * @throws org.opennms.netmgt.scriptd.helper.SnmpTrapHelperException if any.
   */
  public void forwardTrap(Event event, String destAddr, int destPort)
      throws SnmpTrapHelperException {

    Snmp snmpInfo = event.getSnmp();

    if (snmpInfo == null) {
      throw new SnmpTrapHelperException(
          "Cannot forward an event with no SNMP info: " + event.getUei());
    }

    String version = snmpInfo.getVersion();

    if ("v1".equals(version)) {
      forwardV1Trap(event, destAddr, destPort);
    } else if ("v2".equals(version)) {
      forwardV2Trap(event, destAddr, destPort);
    } else {
      throw new SnmpTrapHelperException("Invalid SNMP version: " + version);
    }
  }
  /**
   * Create an SNMP V2 trap, based on the content of the specified event, and forward the trap to
   * the specified address and port. It is assumed that the specified event represents an SNMP V1 or
   * V2 trap that was received by OpenNMS (TrapD).
   *
   * @param event The event upon which the trap content should be based
   * @param destAddr The address to which the trap should be forwarded
   * @param destPort The port to which the trap should be forwarded
   * @exception Throws SnmpTrapHelperException if the variable binding cannot be added to the trap
   *     for any reason.
   * @throws org.opennms.netmgt.scriptd.helper.SnmpTrapHelperException if any.
   */
  public void forwardV2Trap(Event event, String destAddr, int destPort)
      throws SnmpTrapHelperException {

    // the event must correspond to an SNMP trap

    Snmp snmpInfo = event.getSnmp();

    if (snmpInfo == null) {
      throw new SnmpTrapHelperException(
          "Cannot forward an event with no SNMP info: " + event.getUei());
    }

    // check the version of the original trap

    String version = snmpInfo.getVersion();

    SnmpTrapBuilder packet = SnmpUtils.getV2TrapBuilder();

    if ("v1".equals(version)) {

      // converting V1 trap to V2 (see RFC2576)

      addVarBinding(
          packet,
          SNMP_SYSUPTIME_OID,
          EventConstants.TYPE_SNMP_TIMETICKS,
          Long.toString(snmpInfo.getTimeStamp()));

      String oid;

      if (snmpInfo.getGeneric() == ENTERPRISE_SPECIFIC && snmpInfo.hasSpecific()) {
        oid = snmpInfo.getId() + ".0." + snmpInfo.getSpecific();
      } else {
        oid = SNMP_TRAPS + '.' + (snmpInfo.getGeneric() + 1);
      }

      addVarBinding(packet, SNMP_TRAP_OID, EventConstants.TYPE_SNMP_OBJECT_IDENTIFIER, oid);

      // add the V1 var bindings

      boolean addrPresent = false;
      boolean communityPresent = false;
      boolean enterprisePresent = false;

      int i = 0;
      for (Parm parm : event.getParmCollection()) {
        Value value = parm.getValue();

        try {
          addVarBinding(
              packet, parm.getParmName(), value.getType(), value.getEncoding(), value.getContent());
        } catch (SnmpTrapHelperException e) {
          throw new SnmpTrapHelperException(e.getMessage() + " in event parm[" + i + "]");
        }

        if (SNMP_TRAP_ADDRESS_OID.equals(parm.getParmName())) {
          addrPresent = true;
        } else if (SNMP_TRAP_COMMUNITY_OID.equals(parm.getParmName())) {
          communityPresent = true;
        } else if (SNMP_TRAP_ENTERPRISE_OID.equals(parm.getParmName())) {
          enterprisePresent = true;
        }
        i++;
      }

      if (!addrPresent) {
        addVarBinding(
            packet, SNMP_TRAP_ADDRESS_OID, EventConstants.TYPE_SNMP_IPADDRESS, event.getSnmphost());
      }

      if (!communityPresent) {
        addVarBinding(
            packet,
            SNMP_TRAP_COMMUNITY_OID,
            EventConstants.TYPE_SNMP_OCTET_STRING,
            snmpInfo.getCommunity());
      }

      if (!enterprisePresent) {
        addVarBinding(
            packet,
            SNMP_TRAP_ENTERPRISE_OID,
            EventConstants.TYPE_SNMP_OBJECT_IDENTIFIER,
            snmpInfo.getId());
      }
    } else if ("v2".equals(version)) {

      addVarBinding(
          packet,
          SNMP_SYSUPTIME_OID,
          EventConstants.TYPE_SNMP_TIMETICKS,
          Long.toString(snmpInfo.getTimeStamp()));

      String oid;

      if (snmpInfo.getGeneric() == ENTERPRISE_SPECIFIC) {
        oid = snmpInfo.getId() + "." + snmpInfo.getSpecific();
      } else {
        oid = SNMP_TRAPS + '.' + (snmpInfo.getGeneric() + 1);
      }

      addVarBinding(packet, SNMP_TRAP_OID, EventConstants.TYPE_SNMP_OBJECT_IDENTIFIER, oid);

      int i = 0;
      for (Parm parm : event.getParmCollection()) {
        Value value = parm.getValue();

        try {
          addVarBinding(
              packet, parm.getParmName(), value.getType(), value.getEncoding(), value.getContent());
        } catch (SnmpTrapHelperException e) {
          throw new SnmpTrapHelperException(e.getMessage() + " in event parm[" + i + "]");
        }

        i++;
      }
    } else {
      throw new SnmpTrapHelperException("Invalid SNMP version: " + version);
    }

    // send the trap

    sendTrap(destAddr, destPort, snmpInfo.getCommunity(), packet);
  }
  /**
   * Create an SNMP V1 trap, based on the content of the specified event, and forward the trap to
   * the specified address and port. It is assumed that the specified event represents an SNMP V1 or
   * V2 trap that was received by OpenNMS (TrapD).
   *
   * @param event The event upon which the trap content should be based
   * @param destAddr The address to which the trap should be forwarded
   * @param destPort The port to which the trap should be forwarded
   * @exception Throws SnmpTrapHelperException if the variable binding cannot be added to the trap
   *     for any reason.
   * @throws org.opennms.netmgt.scriptd.helper.SnmpTrapHelperException if any.
   */
  public void forwardV1Trap(Event event, String destAddr, int destPort)
      throws SnmpTrapHelperException {
    // the event must correspond to an SNMP trap

    Snmp snmpInfo = event.getSnmp();

    if (snmpInfo == null) {
      throw new SnmpTrapHelperException(
          "Cannot forward an event with no SNMP info: " + event.getUei());
    }

    // check the version of the original trap

    String version = snmpInfo.getVersion();

    SnmpV1TrapBuilder trap = SnmpUtils.getV1TrapBuilder();

    if ("v1".equals(version)) {

      trap.setEnterprise(SnmpObjId.get(snmpInfo.getId()));

      InetAddress agentAddress;
      agentAddress = InetAddressUtils.addr(event.getSnmphost());
      if (agentAddress == null) {
        throw new SnmpTrapHelperException("Invalid ip address.");
      }

      trap.setAgentAddress(agentAddress);

      if (snmpInfo.hasGeneric()) {
        trap.setGeneric(snmpInfo.getGeneric());
      }

      if (snmpInfo.hasSpecific()) {
        trap.setSpecific(snmpInfo.getSpecific());
      }

      trap.setTimeStamp(snmpInfo.getTimeStamp());

      // varbinds

      int i = 0;
      for (Parm parm : event.getParmCollection()) {
        try {
          Value value = parm.getValue();
          addVarBinding(
              trap, parm.getParmName(), value.getType(), value.getEncoding(), value.getContent());
        } catch (SnmpTrapHelperException e) {
          throw new SnmpTrapHelperException(e.getMessage() + " in event parm[" + i + "]");
        } finally {
          i++;
        }
      }
    } else if ("v2".equals(version)) {

      // converting V2 trap to V1 (see RFC2576)

      trap.setEnterprise(SnmpObjId.get(snmpInfo.getId()));

      String addr = null;

      for (Parm parm : event.getParmCollection()) {
        if (SNMP_TRAP_ADDRESS_OID.equals(parm.getParmName())) {
          addr = parm.getValue().getContent();
          break;
        }
      }

      if (addr == null) {
        addr = "0.0.0.0";
      }

      InetAddress agentAddress;
      agentAddress = InetAddressUtils.addr(addr);
      if (agentAddress == null) {
        throw new SnmpTrapHelperException("Invalid ip address.");
      }

      trap.setAgentAddress(agentAddress);

      trap.setGeneric(snmpInfo.getGeneric());

      trap.setSpecific(snmpInfo.getSpecific());

      trap.setTimeStamp(snmpInfo.getTimeStamp());

      // varbinds

      int i = 0;
      for (Parm parm : event.getParmCollection()) {
        Value value = parm.getValue();

        // omit any parms with type=Counter64

        if (!(EventConstants.TYPE_SNMP_COUNTER64.equals(value.getType()))) {

          try {
            addVarBinding(
                trap, parm.getParmName(), value.getType(), value.getEncoding(), value.getContent());
          } catch (SnmpTrapHelperException e) {
            throw new SnmpTrapHelperException(e.getMessage() + " in event parm[" + i + "]");
          }
        }

        i++;
      }

    } else {
      throw new SnmpTrapHelperException("Invalid SNMP version: " + version);
    }

    // send the trap

    sendTrap(destAddr, destPort, snmpInfo.getCommunity(), trap);
  }