Skip to content

Commit f965118

Browse files
util: cleanup old mac address code
Cleanup old mac address handling code to use JDK11 lib instead of hacks. Also really strange to see some basic string parsing code was written by hand, replaced with Long.parseValue(str, 16) to convert hex string to long. Signed-off-by: Rohit Yadav <[email protected]>
1 parent e409c6d commit f965118

File tree

2 files changed

+34
-205
lines changed

2 files changed

+34
-205
lines changed

utils/src/main/java/com/cloud/utils/net/MacAddress.java

Lines changed: 27 additions & 198 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,18 @@
1919

2020
package com.cloud.utils.net;
2121

22-
import static com.cloud.utils.AutoCloseableUtil.closeAutoCloseable;
23-
24-
import java.io.BufferedReader;
25-
import java.io.File;
26-
import java.io.IOException;
27-
import java.io.InputStreamReader;
2822
import java.net.InetAddress;
23+
import java.net.NetworkInterface;
24+
import java.net.SocketException;
2925
import java.net.UnknownHostException;
26+
import java.util.Enumeration;
3027
import java.util.Formatter;
3128

32-
import org.apache.log4j.Logger;
33-
3429
/**
3530
* This class retrieves the (first) MAC address for the machine is it is loaded on and stores it statically for retrieval.
3631
* It can also be used for formatting MAC addresses.
37-
* copied fnd addpeted rom the public domain utility from John Burkard.
3832
**/
3933
public class MacAddress {
40-
private static final Logger s_logger = Logger.getLogger(MacAddress.class);
4134
private long _addr = 0;
4235

4336
protected MacAddress() {
@@ -79,209 +72,45 @@ public String toString() {
7972
static {
8073
String macAddress = null;
8174

82-
Process p = null;
83-
BufferedReader in = null;
84-
8575
try {
86-
String osname = System.getProperty("os.name");
87-
88-
if (osname.startsWith("Windows")) {
89-
p = Runtime.getRuntime().exec(new String[] {"ipconfig", "/all"}, null);
90-
} else if (osname.startsWith("Solaris") || osname.startsWith("SunOS")) {
91-
// Solaris code must appear before the generic code
92-
String hostName = MacAddress.getFirstLineOfCommand(new String[] {"uname", "-n"});
93-
if (hostName != null) {
94-
p = Runtime.getRuntime().exec(new String[] {"/usr/sbin/arp", hostName}, null);
95-
}
96-
} else if (new File("/usr/sbin/lanscan").exists()) {
97-
p = Runtime.getRuntime().exec(new String[] {"/usr/sbin/lanscan"}, null);
98-
} else if (new File("/sbin/ifconfig").exists()) {
99-
p = Runtime.getRuntime().exec(new String[] {"/sbin/ifconfig", "-a"}, null);
100-
}
101-
102-
if (p != null) {
103-
in = new BufferedReader(new InputStreamReader(p.getInputStream()), 128);
104-
String l = null;
105-
while ((l = in.readLine()) != null) {
106-
macAddress = MacAddress.parse(l);
107-
if (macAddress != null) {
108-
short parsedShortMacAddress = MacAddress.parseShort(macAddress);
109-
if (parsedShortMacAddress != 0xff && parsedShortMacAddress != 0x00)
110-
break;
111-
}
112-
macAddress = null;
113-
}
114-
}
115-
116-
} catch (SecurityException ex) {
117-
s_logger.info("[ignored] security exception in static initializer of MacAddress", ex);
118-
} catch (IOException ex) {
119-
s_logger.info("[ignored] io exception in static initializer of MacAddress");
120-
} finally {
121-
if (p != null) {
122-
closeAutoCloseable(in, "closing init process input stream");
123-
closeAutoCloseable(p.getErrorStream(), "closing init process error output stream");
124-
closeAutoCloseable(p.getOutputStream(), "closing init process std output stream");
125-
p.destroy();
126-
}
76+
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
77+
while (networkInterfaces.hasMoreElements()) {
78+
NetworkInterface network = networkInterfaces.nextElement();
79+
final byte [] mac = network.getHardwareAddress();
80+
if (mac != null && !network.isVirtual() &&
81+
!network.getName().startsWith("br-") &&
82+
!network.getName().startsWith("veth") &&
83+
!network.getName().startsWith("vnet")) {
84+
StringBuilder macAddressBuilder = new StringBuilder();
85+
for (byte b : mac) {
86+
macAddressBuilder.append(String.format("%02X", b));
87+
}
88+
macAddress = macAddressBuilder.toString();
89+
}
90+
}
91+
} catch (SocketException ignore) {
12792
}
12893

129-
long clockSeqAndNode = 0;
94+
long macAddressInLong = 0;
13095

13196
if (macAddress != null) {
132-
if (macAddress.indexOf(':') != -1) {
133-
clockSeqAndNode |= MacAddress.parseLong(macAddress);
134-
} else if (macAddress.startsWith("0x")) {
135-
clockSeqAndNode |= MacAddress.parseLong(macAddress.substring(2));
136-
}
97+
macAddressInLong = Long.parseLong(macAddress, 16);
13798
} else {
13899
try {
139100
byte[] local = InetAddress.getLocalHost().getAddress();
140-
clockSeqAndNode |= (local[0] << 24) & 0xFF000000L;
141-
clockSeqAndNode |= (local[1] << 16) & 0xFF0000;
142-
clockSeqAndNode |= (local[2] << 8) & 0xFF00;
143-
clockSeqAndNode |= local[3] & 0xFF;
101+
macAddressInLong |= (local[0] << 24) & 0xFF000000L;
102+
macAddressInLong |= (local[1] << 16) & 0xFF0000;
103+
macAddressInLong |= (local[2] << 8) & 0xFF00;
104+
macAddressInLong |= local[3] & 0xFF;
144105
} catch (UnknownHostException ex) {
145-
clockSeqAndNode |= (long)(Math.random() * 0x7FFFFFFF);
106+
macAddressInLong |= (long)(Math.random() * 0x7FFFFFFF);
146107
}
147108
}
148109

149-
s_address = new MacAddress(clockSeqAndNode);
110+
s_address = new MacAddress(macAddressInLong);
150111
}
151112

152113
public static MacAddress getMacAddress() {
153114
return s_address;
154115
}
155-
156-
private static String getFirstLineOfCommand(String[] commands) throws IOException {
157-
158-
Process p = null;
159-
BufferedReader reader = null;
160-
161-
try {
162-
p = Runtime.getRuntime().exec(commands);
163-
reader = new BufferedReader(new InputStreamReader(p.getInputStream()), 128);
164-
165-
return reader.readLine();
166-
} finally {
167-
if (p != null) {
168-
closeAutoCloseable(reader, "closing process input stream");
169-
closeAutoCloseable(p.getErrorStream(), "closing process error output stream");
170-
closeAutoCloseable(p.getOutputStream(), "closing process std output stream");
171-
p.destroy();
172-
}
173-
}
174-
175-
}
176-
177-
/**
178-
* The MAC address parser attempts to find the following patterns:
179-
* <ul>
180-
* <li>.{1,2}:.{1,2}:.{1,2}:.{1,2}:.{1,2}:.{1,2}</li>
181-
* <li>.{1,2}-.{1,2}-.{1,2}-.{1,2}-.{1,2}-.{1,2}</li>
182-
* </ul>
183-
*
184-
* This is copied from the author below. The author encouraged copying
185-
* it.
186-
*
187-
*/
188-
static String parse(String in) {
189-
190-
// lanscan
191-
192-
int hexStart = in.indexOf("0x");
193-
if (hexStart != -1) {
194-
int hexEnd = in.indexOf(' ', hexStart);
195-
if (hexEnd != -1) {
196-
return in.substring(hexStart, hexEnd);
197-
}
198-
}
199-
200-
int octets = 0;
201-
int lastIndex, old, end;
202-
203-
if (in.indexOf('-') > -1) {
204-
in = in.replace('-', ':');
205-
}
206-
207-
lastIndex = in.lastIndexOf(':');
208-
209-
if (lastIndex > in.length() - 2)
210-
return null;
211-
212-
end = Math.min(in.length(), lastIndex + 3);
213-
214-
++octets;
215-
old = lastIndex;
216-
while (octets != 5 && lastIndex != -1 && lastIndex > 1) {
217-
lastIndex = in.lastIndexOf(':', --lastIndex);
218-
if (old - lastIndex == 3 || old - lastIndex == 2) {
219-
++octets;
220-
old = lastIndex;
221-
}
222-
}
223-
224-
if (octets == 5 && lastIndex > 1) {
225-
return in.substring(lastIndex - 2, end).trim();
226-
}
227-
return null;
228-
}
229-
230-
/**
231-
* Parses a <code>long</code> from a hex encoded number. This method will skip
232-
* all characters that are not 0-9 and a-f (the String is lower cased first).
233-
* Returns 0 if the String does not contain any interesting characters.
234-
*
235-
* @param s the String to extract a <code>long</code> from, may not be <code>null</code>
236-
* @return a <code>long</code>
237-
* @throws NullPointerException if the String is <code>null</code>
238-
*/
239-
private static long parseLong(String s) throws NullPointerException {
240-
s = s.toLowerCase();
241-
long out = 0;
242-
byte shifts = 0;
243-
char c;
244-
for (int i = 0; i < s.length() && shifts < 16; i++) {
245-
c = s.charAt(i);
246-
if ((c > 47) && (c < 58)) {
247-
out <<= 4;
248-
++shifts;
249-
out |= c - 48;
250-
} else if ((c > 96) && (c < 103)) {
251-
++shifts;
252-
out <<= 4;
253-
out |= c - 87;
254-
}
255-
}
256-
return out;
257-
}
258-
259-
/**
260-
* Parses a <code>short</code> from a hex encoded number. This method will skip
261-
* all characters that are not 0-9 and a-f (the String is lower cased first).
262-
* Returns 0 if the String does not contain any interesting characters.
263-
*
264-
* @param s the String to extract a <code>short</code> from, may not be <code>null</code>
265-
* @return a <code>short</code>
266-
* @throws NullPointerException if the String is <code>null</code>
267-
*/
268-
private static short parseShort(String s) throws NullPointerException {
269-
s = s.toLowerCase();
270-
short out = 0;
271-
byte shifts = 0;
272-
char c;
273-
for (int i = 0; i < s.length() && shifts < 4; i++) {
274-
c = s.charAt(i);
275-
if ((c > 47) && (c < 58)) {
276-
out <<= 4;
277-
++shifts;
278-
out |= c - 48;
279-
} else if ((c > 96) && (c < 103)) {
280-
++shifts;
281-
out <<= 4;
282-
out |= c - 87;
283-
}
284-
}
285-
return out;
286-
}
287116
}

utils/src/test/java/com/cloud/utils/net/MacAddressTest.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,14 @@ public final void testMacAddressLong() throws Exception {
4141
public final void testMacAddressToLong() throws Exception {
4242
// TODO this test should fail this address is beyond the acceptable range for macaddresses
4343
MacAddress mac = new MacAddress(Long.MAX_VALUE);
44-
assertEquals(Long.MAX_VALUE,mac.toLong());
44+
assertEquals(Long.MAX_VALUE, mac.toLong());
4545
System.out.println(mac.toString());
4646
}
4747

48-
// TODO public final void testToLong() throws Exception {
49-
// TODO public final void testToByteArray() throws Exception {
50-
// TODO public final void testToStringString() throws Exception {
51-
// TODO public final void testToString() throws Exception {
52-
// TODO public final void testGetMacAddress() throws Exception {
53-
// TODO public final void testParse() throws Exception {
48+
@Test
49+
public final void testSpecificMacAddress() throws Exception {
50+
// Test specific mac address 76:3F:76:EB:02:81
51+
MacAddress mac = new MacAddress(130014950130305L);
52+
assertEquals("76:3f:76:eb:02:81", mac.toString());
53+
}
5454
}

0 commit comments

Comments
 (0)