Fixed MacAddress toString function for different formats; Introduced even more MacAdd...
[public/netxms.git] / src / libnetxms / macaddr.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Utility Library
4 ** Copyright (C) 2003-2017 Raden Solutions
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU Lesser General Public License as published
8 ** by the Free Software Foundation; either version 3 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU Lesser General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: macaddr.cpp
21 **
22 **/
23
24 #include "libnetxms.h"
25 #include <nxcpapi.h>
26 #include <netxms-regex.h>
27
28 /**
29 * Returns true if it is the multicast address
30 */
31 bool MacAddress::isMulticast() const
32 {
33 return (m_length == 6) ? (m_value[0] & 0x01) != 0 : false;
34 }
35
36 /**
37 * Returns true if it is the broadcast address
38 */
39 bool MacAddress::isBroadcast() const
40 {
41 return (m_length == 6) ? !memcmp(m_value, "\xFF\xFF\xFF\xFF\xFF\xFF", 6) : false;
42 }
43
44 /**
45 * Returns true if addrese are equals
46 */
47 bool MacAddress::equals(const MacAddress &a) const
48 {
49 if(a.length() == m_length)
50 {
51 return !memcmp(m_value, a.value(), m_length);
52 }
53 return false;
54 }
55
56 /**
57 * Returns string representaiton of mac address
58 */
59 TCHAR *MacAddress::toString(TCHAR *buffer, MacAddressNotation notation) const
60 {
61 switch(notation)
62 {
63 case MAC_ADDR_FLAT_STRING:
64 BinToStr(m_value, m_length, buffer);
65 break;
66 case MAC_ADDR_COLON_SEPARATED:
67 toStringInternal(buffer, _T(':'));
68 break;
69 case MAC_ADDR_BYTEPAIR_COLON_SEPARATED:
70 toStringInternal(buffer, _T(':'), true);
71 break;
72 case MAC_ADDR_HYPHEN_SEPARATED:
73 toStringInternal(buffer, _T('-'));
74 break;
75 case MAC_ADDR_DOT_SEPARATED:
76 toStringInternal3(buffer, _T('.'));
77 break;
78 case MAC_ADDR_BYTEPAIR_DOT_SEPARATED:
79 toStringInternal(buffer, _T('.'), true);
80 break;
81 }
82 return buffer;
83 }
84
85 /**
86 * Internal method to string for inserting separator every third char
87 */
88 TCHAR *MacAddress::toStringInternal3(TCHAR *buffer, const TCHAR separator) const
89 {
90 TCHAR *curr = buffer;
91
92 for(int i = 0; i < m_length; i++)
93 {
94 *curr++ = bin2hex(m_value[i] >> 4);
95 if (((curr+1) - buffer) % 4 == 0)
96 *curr++ = separator;
97 *curr++ = bin2hex(m_value[i] & 15);
98 if (((curr+1) - buffer) % 4 == 0)
99 *curr++ = separator;
100 }
101 *(curr - 1) = 0;
102 return buffer;
103 }
104
105 /**
106 * Internal method to string
107 */
108 TCHAR *MacAddress::toStringInternal(TCHAR *buffer, const TCHAR separator, bool bytePair) const
109 {
110 TCHAR *curr = buffer;
111
112 for(int i = 0; i < m_length; i++)
113 {
114 *curr++ = bin2hex(m_value[i] >> 4);
115 *curr++ = bin2hex(m_value[i] & 15);
116 if (!bytePair || (((i+1) % 2 == 0)))
117 *curr++ = separator;
118 }
119 *(curr - 1) = 0;
120 return buffer;
121 }
122
123 /**
124 * Returns string representaiton of mac address
125 */
126 String MacAddress::toString(MacAddressNotation notation) const
127 {
128 if (m_length == 0)
129 return String();
130
131 int stringSize;
132 switch(notation)
133 {
134 case MAC_ADDR_FLAT_STRING:
135 stringSize = m_length * 2;
136 break;
137 case MAC_ADDR_COLON_SEPARATED:
138 case MAC_ADDR_HYPHEN_SEPARATED:
139 case MAC_ADDR_DOT_SEPARATED:
140 stringSize = m_length * 2 + m_length; //-1 separator +1 for 0 termination
141 break;
142 case MAC_ADDR_BYTEPAIR_DOT_SEPARATED:
143 case MAC_ADDR_BYTEPAIR_COLON_SEPARATED:
144 stringSize = m_length * 2 + m_length/2; //-1 separator +1 for 0 termination
145 break;
146 }
147 _tprintf(_T("\n Stringsize: %d\n"), stringSize);
148 TCHAR *buf = (TCHAR *)malloc(stringSize * sizeof(TCHAR));
149 String str(toString(buf, notation));
150 free(buf);
151 return str;
152 }
153
154 /**
155 * Parse string as MAC address
156 */
157 MacAddress MacAddress::parse(const char *str)
158 {
159 if (str == NULL || strlen(str) > 23)
160 return MacAddress();
161
162 regex_t compRegex;
163 char exp1[254] = { "^([0-9a-fA-F]{2})[ :-]?"
164 "([0-9a-fA-F]{2})[ .:-]?"
165 "([0-9a-fA-F]{2})[ :-]?"
166 "([0-9a-fA-F]{2})[ .:-]?"
167 "([0-9a-fA-F]{2})[ :-]?"
168 "([0-9a-fA-F]{2})[ .:-]?"
169 "([0-9a-fA-F]{2})?[ :-]?"
170 "([0-9a-fA-F]{2})?$" };
171
172 char exp2[128] = { "^([0-9a-fA-F]{3})\\."
173 "([0-9a-fA-F]{3})\\."
174 "([0-9a-fA-F]{3})\\."
175 "([0-9a-fA-F]{3})$" };
176
177 String mac;
178 if (tre_regcomp(&compRegex, exp1, REG_EXTENDED) == 0)
179 {
180 regmatch_t match[9];
181 if (tre_regexec(&compRegex, str, 9, match, 0) == 0)
182 {
183 for(int i = 1; i < 9; i++)
184 mac.appendMBString(str+match[i].rm_so, (match[i].rm_eo - match[i].rm_so), CP_ACP);
185 }
186 else
187 {
188 regfree(&compRegex);
189 if (tre_regcomp(&compRegex, exp2, REG_EXTENDED) == 0)
190 {
191 regmatch_t match[5];
192 if (tre_regexec(&compRegex, str, 5, match, 0) == 0)
193 {
194 for(int i = 1; i < 5; i++)
195 mac.appendMBString(str+match[i].rm_so, (match[i].rm_eo - match[i].rm_so), CP_ACP);
196 }
197 }
198 }
199 regfree(&compRegex);
200 }
201
202 if (mac.length() > 0)
203 {
204 BYTE buffer[16];
205 size_t size = StrToBin(mac, buffer, mac.length());
206 return MacAddress(buffer, size);
207 }
208
209 return MacAddress();
210 }
211
212 /**
213 * Parse string as MAC address (WCHAR version)
214 */
215 MacAddress MacAddress::parse(const WCHAR *str)
216 {
217 char mb[256];
218 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR, str, -1, mb, 256, NULL, NULL);
219 return parse(mb);
220 }