BUG-2825: use IetfInetUtil to instantiate addresses
[bgpcep.git] / util / src / main / java / org / opendaylight / protocol / util / Ipv4Util.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.protocol.util;
9
10 import com.google.common.base.Preconditions;
11 import com.google.common.net.InetAddresses;
12 import com.google.common.primitives.UnsignedBytes;
13 import io.netty.buffer.ByteBuf;
14 import io.netty.buffer.Unpooled;
15 import java.net.InetAddress;
16 import java.net.InetSocketAddress;
17 import java.util.ArrayList;
18 import java.util.Arrays;
19 import java.util.Collections;
20 import java.util.List;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IetfInetUtil;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
26
27 /**
28  * Util class for creating generated Ipv4Address.
29  */
30 public final class Ipv4Util {
31     public static final int IP4_LENGTH = 4;
32     private static final Ipv4Prefix EMPTY_PREFIX = new Ipv4Prefix("0.0.0.0/0");
33
34     private Ipv4Util() {
35         throw new UnsupportedOperationException();
36     }
37
38     /**
39      * Reads from ByteBuf buffer and converts bytes to Ipv4Address.
40      *
41      * @param buffer containing Ipv4 address, starting at reader index
42      * @return Ipv4Address
43      */
44     public static Ipv4Address addressForByteBuf(final ByteBuf buffer) {
45         return IetfInetUtil.INSTANCE.ipv4AddressFor(ByteArray.readBytes(buffer, IP4_LENGTH));
46     }
47
48     /**
49      * From string ipAddress creates an InetAddress and puts it into ByteBuf.
50      * @param ipAddress Ipv4 address
51      * @return ByteBuf with filled in bytes from ipAddress
52      */
53     public static ByteBuf byteBufForAddress(final Ipv4Address ipAddress) {
54         return Unpooled.wrappedBuffer(bytesForAddress(ipAddress));
55     }
56
57     /**
58      * Converts Ipv4Address to byte array.
59      *
60      * @param address Ipv4Address to be converted
61      * @return byte array
62      */
63     public static byte[] bytesForAddress(final Ipv4Address address) {
64         return IetfInetUtil.INSTANCE.ipv4AddressBytes(address);
65     }
66
67     public static int prefixBitsToBytes(final int bits) {
68         if (bits % Byte.SIZE != 0) {
69             return (bits / Byte.SIZE) + 1;
70         }
71         return bits / Byte.SIZE;
72     }
73
74     /**
75      * Returns number of minimum bytes needed to cover all bits of prefix.
76      *
77      * @param prefix
78      * @return
79      */
80     public static int getPrefixLengthBytes(final String prefix) {
81         return prefixBitsToBytes(Ipv4Util.getPrefixLength(prefix));
82     }
83
84     /**
85      * Converts Ipv4Prefix to byte array. Prefix length at the end.
86      *
87      * @param prefix Ipv4Prefix to be converted
88      * @return byte array with prefix length at the end
89      */
90     public static byte[] bytesForPrefix(final Ipv4Prefix prefix) {
91         return IetfInetUtil.INSTANCE.ipv4PrefixToBytes(prefix);
92     }
93
94     /**
95      * Converts Ipv4Prefix to byte array. Prefix length at the beginning.
96      * Prefix bytes are trimmed from the end to match prefix length.
97      *
98      * @param prefix Ipv4Prefix to be converted
99      * @return byte array with the prefix length at the beginning
100      *
101      * @deprecated This is inefficient, refactor code to use {@link #bytesForAddress(Ipv4Address)} or
102      *             {@link ByteBufWriteUtil#writeMinimalPrefix(Ipv4Prefix, ByteBuf)}.
103      */
104     @Deprecated
105     public static byte[] bytesForPrefixBegin(final Ipv4Prefix prefix) {
106         final byte[] addrWithPrefix = bytesForPrefix(prefix);
107         return prefixedBytes(addrWithPrefix[IP4_LENGTH], addrWithPrefix);
108     }
109
110     static byte[] prefixedBytes(final byte prefixBits, final byte[] address) {
111         if (prefixBits != 0) {
112             final int prefixBytes = prefixBitsToBytes(Byte.toUnsignedInt(prefixBits));
113             final byte[] ret = new byte[prefixBytes + 1];
114             ret[0] = prefixBits;
115             System.arraycopy(address, 0, ret, 1, prefixBytes);
116             return ret;
117         } else {
118             return new byte[] { 0 };
119         }
120     }
121
122     /**
123      * Creates an Ipv4Prefix object from given byte array.
124      *
125      * @param bytes  IPv4 address
126      * @param length prefix length
127      * @return Ipv4Prefix object
128      */
129     public static Ipv4Prefix prefixForBytes(final byte[] bytes, final int length) {
130         Preconditions.checkArgument(length <= bytes.length * Byte.SIZE);
131         final byte[] tmp = Arrays.copyOfRange(bytes, 0, IP4_LENGTH);
132         return IetfInetUtil.INSTANCE.ipv4PrefixFor(tmp, length);
133     }
134
135     /**
136      * Creates an Ipv4Prefix object from given ByteBuf. Prefix length is assumed to
137      * be in the left most byte of the buffer.
138      *
139      * @param bytes IPv4 address
140      * @return Ipv4Prefix object
141      */
142     public static Ipv4Prefix prefixForByteBuf(final ByteBuf bytes) {
143         final int prefixLength = bytes.readByte();
144         final int size = prefixLength / Byte.SIZE + ((prefixLength % Byte.SIZE == 0) ? 0 : 1);
145         Preconditions.checkArgument(size <= bytes.readableBytes(), "Illegal length of IP prefix: %s", bytes.readableBytes());
146         return prefixForBytes(ByteArray.readBytes(bytes, size), prefixLength);
147     }
148
149     /**
150      * Creates a list of Ipv4 Prefixes from given byte array.
151      *
152      * @param bytes to be converted to List of Ipv4Prefixes.
153      * @return A list of Ipv4Prefixes
154      */
155     public static List<Ipv4Prefix> prefixListForBytes(final byte[] bytes) {
156         if (bytes.length == 0) {
157             return Collections.emptyList();
158         }
159         final List<Ipv4Prefix> list = new ArrayList<>();
160         int byteOffset = 0;
161         while (byteOffset < bytes.length) {
162             final int bitLength = UnsignedBytes.toInt(bytes[byteOffset]);
163             byteOffset += 1;
164             // if length == 0, default route will be added
165             if (bitLength == 0) {
166                 list.add(EMPTY_PREFIX);
167                 continue;
168             }
169             final int byteCount = (bitLength % Byte.SIZE != 0) ? (bitLength / Byte.SIZE) + 1 : bitLength / Byte.SIZE;
170             list.add(prefixForBytes(ByteArray.subByte(bytes, byteOffset, byteCount), bitLength));
171             byteOffset += byteCount;
172
173         }
174         return list;
175     }
176
177     /**
178      * Obtains prefix length from given string prefix.
179      *
180      * @param prefixValue value of prefix
181      * @return prefix length
182      */
183     protected static int getPrefixLength(final String prefixValue) {
184         final int sep = prefixValue.indexOf('/');
185         return Integer.parseInt(prefixValue.substring(sep + 1, prefixValue.length()));
186     }
187
188     /**
189      * Converts InetAddress to IpAddress.
190      *
191      * @param inetAddress
192      * @return IpAddress
193      */
194     public static IpAddress getIpAddress(final InetAddress inetAddress) {
195         return IetfInetUtil.INSTANCE.ipAddressFor(inetAddress);
196     }
197
198     /**
199      * Converts IpAddress and PortNumber to InetSocketAddress
200      *
201      * @param ipAddress
202      * @param port
203      * @return InetSocketAddress
204      */
205     public static InetSocketAddress toInetSocketAddress(final IpAddress ipAddress, final PortNumber port) {
206         final String ipString;
207         if (ipAddress.getIpv4Address() != null) {
208             ipString = ipAddress.getIpv4Address().getValue();
209         } else {
210             ipString = ipAddress.getIpv6Address().getValue();
211         }
212         return new InetSocketAddress(InetAddresses.forString(ipString), port.getValue());
213     }
214 }