All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ice4j.attribute.XorMappedAddressAttribute Maven / Gradle / Ivy

There is a newer version: 3.2-4-g1373788
Show newest version
/*
 * ice4j, the OpenSource Java Solution for NAT and Firewall Traversal.
 *
 * Copyright @ 2015 Atlassian Pty Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.ice4j.attribute;

import java.net.*;

import org.ice4j.*;
import org.ice4j.message.*;

/**
 * The XOR-MAPPED-ADDRESS attribute is only present in Binding
 * Responses.  It provides the same information that is present in the
 * MAPPED-ADDRESS attribute.  However, the information is encoded by
 * performing an exclusive or (XOR) operation between the mapped address
 * and the transaction ID.  Unfortunately, some NAT devices have been
 * found to rewrite binary encoded IP addresses and ports that are
 * present in protocol payloads.  This behavior interferes with the
 * operation of STUN.  By providing the mapped address in an obfuscated
 * form, STUN can continue to operate through these devices.
 *
 * The format of the XOR-MAPPED-ADDRESS is:
 *
 *
 * 0                   1                   2                   3
 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |x x x x x x x x|    Family     |         X-Port                |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |                X-Address (Variable)
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *
 * The Family represents the IP address family, and is encoded
 * identically to the Family in MAPPED-ADDRESS.
 *
 * X-Port is equal to the port in MAPPED-ADDRESS, exclusive or'ed with
 * most significant 16 bits of the transaction ID.  If the IP address
 * family is IPv4, X-Address is equal to the IP address in MAPPED-
 * ADDRESS, exclusive or'ed with the most significant 32 bits of the
 * transaction ID.  If the IP address family is IPv6, the X-Address is
 * equal to the IP address in MAPPED-ADDRESS, exclusive or'ed with the
 * entire 128 bit transaction ID.
 *
 * @author Emil Ivov
 */
public class XorMappedAddressAttribute
    extends AddressAttribute
{
    /**
     * The name of this attribute
     */
    public static final String NAME = "XOR-MAPPED-ADDRESS";

    /**
     * Creates an instance of this attribute
     */
    XorMappedAddressAttribute()
    {
        super(XOR_MAPPED_ADDRESS);
    }

    /**
     * Constructor.
     * @param type other type than XOR-MAPPED-ADDRESS
     */
    XorMappedAddressAttribute(char type)
    {
      super(type);
    }

    /**
     * Returns the result of applying XOR on the specified attribute's address.
     * The method may be used for both encoding and decoding XorMappedAddresses.
     *
     * @param address the address on which XOR should be applied
     * @param transactionID the transaction id to use for the XOR
     *
     * @return the XOR-ed address.
     */
    public static TransportAddress applyXor(TransportAddress address,
                                       byte[] transactionID)
    {
        byte[] addressBytes = address.getAddressBytes();
        char port = (char)address.getPort();

        char portModifier = (char)( (transactionID[0] << 8 & 0x0000FF00)
                                  | (transactionID[1] & 0x000000FF));

        port ^= portModifier;

        for (int i = 0; i < addressBytes.length; i++)
            addressBytes[i] ^= transactionID[i];

        TransportAddress xoredAdd;
        try
        {
            xoredAdd = new TransportAddress(addressBytes, port, Transport.UDP);
        }
        catch (UnknownHostException e)
        {
            //shouldn't happen so just throw an illegal arg
            throw new IllegalArgumentException(e);
        }

        return xoredAdd;
    }

    /**
     * Returns the result of applying XOR on this attribute's address, using the
     * specified transaction ID when converting IPv6 addresses.
     *
     * @param transactionID the transaction ID to use in case this attribute is
     * encapsulating an IPv6 address.
     *
     * @return the XOR-ed address.
     */
    public TransportAddress getAddress(byte[] transactionID)
    {
        byte[] xorMask = new byte[16];

        System.arraycopy(Message.MAGIC_COOKIE, 0, xorMask, 0, 4);
        System.arraycopy(transactionID, 0, xorMask, 4, 12);

        return applyXor(xorMask);
    }

    /**
     * Returns the result of applying XOR on this attribute's address, using the
     * specified XOR mask. The method may be used for both encoding and
     * decoding XorMappedAddresses.
     *
     * @param xorMask the XOR mask to use when obtaining the original address.
     *
     * @return the XOR-ed address.
     */
    public TransportAddress applyXor(byte[] xorMask)
    {
        return applyXor(getAddress(), xorMask);
    }

    /**
     * Applies a XOR mask to the specified address and then sets it as the value
     * transported by this attribute.
     *
     * @param address the address that we should xor and then record in this
     * attribute.
     * @param transactionID the transaction identifier that we should use
     * when creating the XOR mask.
     */
    public void setAddress(TransportAddress address, byte[] transactionID)
    {
        byte[] xorMask = new byte[16];

        System.arraycopy(Message.MAGIC_COOKIE, 0, xorMask, 0, 4);
        System.arraycopy(transactionID, 0, xorMask, 4, 12);

        TransportAddress xorAddress = applyXor(address, xorMask);

        super.setAddress(xorAddress);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy