[SNMP4J] IPv6 Address with Scope

Senthil Muniswamy senthil.muniswamy at gmail.com
Thu Mar 26 18:40:13 CET 2009


Frank,
There is a bug in the getValue() method. When there is scope, port
bytes are not set correctly because of wrong index. It should be:

   retval[addr.length+scopeSize] = (byte)((port >> 8) & 0xFF);
   retval[addr.length+scopeSize+1] = (byte)(port & 0xFF);

Thanks,
Senthil

On Wed, Mar 25, 2009 at 6:03 PM, Frank Fock <fock at agentpp.com> wrote:
> Senthil,
>
> Here is my implementation that works with Java 1.5
> or later and does not break 1.4 compatibility:
>
>  /**
>   * Sets this transport address from an OcetString containing the address
>   * value in format as specified by the TRANSPORT-ADDRESS-MIB.
>   * @param transportAddress
>   *    an OctetString containing the IP address bytes and the two port bytes
>   *    in network byte order.
>   * @throws UnknownHostException
>   *    if the address is invalid.
>   */
>  public void setTransportAddress(OctetString transportAddress) throws
>      UnknownHostException {
>    OctetString inetAddr =
>        transportAddress.substring(0, transportAddress.length()-2);
>    byte[] addr = inetAddr.getValue();
>    if ((addr.length == 8) || (addr.length == 20)) {
>      // address with zone (scope) index
>      byte[] ipaddr = new byte[addr.length-4];
>      System.arraycopy(addr, 0, ipaddr, 0, ipaddr.length);
>      int sz = ipaddr.length;
>      int scope = ((addr[sz] << 24) +
>                   ((addr[sz+1] & 0xff) << 16) +
>                   ((addr[sz+2] & 0xFF) << 8) +
>                   (addr[sz+3] & 0xFF));
>      try {
>        Class[] params = new Class[] { String.class, byte[].class, int.class
> };
>        Method m = Inet6Address.class.getMethod("getByAddress", params);
>        Object[] args = new Object[] { null, ipaddr, new Integer(scope) };
>        Object o = m.invoke(Inet6Address.class, args);
>        setInetAddress((InetAddress)o);
>      }
>      catch (Exception ex) {
>        logger.warn("Java < 1.5 does not support scoped IPv6 addresses, "+
>                    "ignoring scope ID for " + transportAddress);
>        setInetAddress(InetAddress.getByAddress(ipaddr));
>      }
>    }
>    else {
>      setInetAddress(InetAddress.getByAddress(addr));
>    }
>    port = ((transportAddress.get(transportAddress.length()-2) & 0xFF) << 8);
>    port += (transportAddress.get(transportAddress.length()-1) & 0xFF);
>  }
>
>  /**
>   * Returns the address value as a byte array.
>   * @return
>   *    a byte array with IP address bytes and two additional bytes
> containing
>   *    the port in network byte order. If the address is a zoned (scoped) IP
>   *    address, four additional bytes with the scope ID are returned between
>   *    address and port bytes.
>   * @since 1.5
>   */
>  public byte[] getValue() {
>    byte[] addr = getInetAddress().getAddress();
>    int scopeSize = 0;
>    int scopeID = 0;
>    if (getInetAddress() instanceof Inet6Address) {
>      try {
>        Inet6Address ip6Addr = (Inet6Address) getInetAddress();
>        Method m = Inet6Address.class.getMethod("getScopeId", null);
>        Object scope = m.invoke(ip6Addr, null);
>        scopeID = ((Number)scope).intValue();
>        scopeSize = 4;
>      }
>      catch (Exception ex) {
>        // ignore
>      }
>    }
>    byte[] retval = new byte[addr.length+2+scopeSize];
>    System.arraycopy(addr, 0, retval, 0, addr.length);
>    if (scopeSize > 0) {
>      int offset = addr.length;
>      retval[offset++] = (byte)((scopeID & 0xFF000000) >> 24);
>      retval[offset++] = (byte)((scopeID & 0x00FF0000) >> 16);
>      retval[offset++] = (byte)((scopeID & 0x0000FF00) >> 8);
>      retval[offset++] = (byte) (scopeID & 0x000000FF);
>    }
>    retval[addr.length  ] = (byte)((port >> 8) & 0xFF);
>    retval[addr.length+1] = (byte)(port & 0xFF);
>    return retval;
>  }
>
> Please let me know if it works for you.
>
> Best regards,
> Frank
>
> Frank Fock wrote:
>>
>> Senthil,
>>
>> Thanks for your fix. However, IPv4 zoned addresses
>> are not handled correctly by it. I am working on
>> solution that covers those too.
>>
>> Best regards,
>> Frank
>>
>> Senthil Muniswamy wrote:
>>>
>>> Frank,
>>> I am using SNMP4J-Agent and
>>> TransportIpAddress.setTransportAddress(OctetString transportAddress)
>>> causes exception if snmpTargetAddrTAddress is set with TAddress (IPv6
>>> Address with Scope).
>>>
>>> I have made below changes to TransportIpAddress to handle the scope,
>>> could you please confirm if this is correct?
>>>
>>>  public void setTransportAddress(OctetString transportAddress) throws
>>>      UnknownHostException {
>>>    OctetString inetAddr =
>>>        transportAddress.substring(0, transportAddress.length()-2);
>>>    byte[] addr = inetAddr.getValue();
>>>    if(addr.length <= 16) {
>>>        setInetAddress(InetAddress.getByAddress(addr));
>>>    }
>>>    else {
>>>        byte[] ip6addr = new byte[16];
>>>        System.arraycopy(addr, 0, ip6addr, 0, ip6addr.length);
>>>        int scope = ((addr[16] << 24) + ((addr[17] & 0xff) << 16) +
>>> ((addr[18] & 0xFF) << 8) +
>>>                (addr[19] & 0xFF));
>>>        setInetAddress(Inet6Address.getByAddress(null, ip6addr, scope));
>>>    }
>>>    port = ((transportAddress.get(transportAddress.length()-2) & 0xFF) <<
>>> 8);
>>>    port += (transportAddress.get(transportAddress.length()-1) & 0xFF);
>>>  }
>>>
>>>  public byte[] getValue() {
>>>        byte[] addr = getInetAddress().getAddress();
>>>        int size = 2;
>>>        if(getInetAddress() instanceof Inet6Address &&
>>>                ((Inet6Address)getInetAddress()).getScopeId() > 0) {
>>>            size = size+4;
>>>        }
>>>        byte[] retval = new byte[addr.length+size];
>>>        System.arraycopy(addr, 0, retval, 0, addr.length);
>>>        if(size > 2) {
>>>            int scope = ((Inet6Address)getInetAddress()).getScopeId();
>>>            retval[addr.length] = (byte)((scope & 0xFF000000) >> 24);
>>>            retval[addr.length+1] = (byte)((scope & 0x00FF0000) >> 16);
>>>            retval[addr.length+2] = (byte)((scope & 0x0000FF00) >> 8);
>>>            retval[addr.length+3] = (byte)(scope & 0x000000FF);
>>>        }
>>>        retval[retval.length-2] = (byte)((port >> 8) & 0xFF);
>>>        retval[retval.length-1] = (byte)(port & 0xFF);
>>>    return retval;
>>>  }
>>>
>>>  public int getBERLength() {
>>>    return getValue().length;
>>>  }
>>>
>>>
>>> Thanks,
>>> Senthil
>>> _______________________________________________
>>> SNMP4J mailing list
>>> SNMP4J at agentpp.org
>>> http://lists.agentpp.org/mailman/listinfo/snmp4j
>>
>
> --
> AGENT++
> http://www.agentpp.com
> http://www.mibexplorer.com
> http://www.mibdesigner.com
>
>



More information about the SNMP4J mailing list