OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
address.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <base/address.h>
6 
7 #include <map>
8 #include <boost/assign/list_of.hpp>
9 
10 using namespace std;
11 
13 }
14 
15 static const std::map<string, Address::Family>
16  fromString = boost::assign::map_list_of
17  ("unspecified", Address::UNSPEC)
18  ("inet", Address::INET)
19  ("inet-labeled", Address::INETMPLS)
20  ("inet6", Address::INET6)
21  ("inet-vpn", Address::INETVPN)
22  ("inet6-vpn", Address::INET6VPN)
23  ("route-target", Address::RTARGET)
24  ("e-vpn", Address::EVPN)
25  ("inet-mvpn", Address::MVPN)
26  ("erm-vpn", Address::ERMVPN);
27 
28 static const std::map<Address::Family, string>
29  toString = boost::assign::map_list_of
30  (Address::UNSPEC, "unspecified")
31  (Address::INET, "inet")
32  (Address::INETMPLS, "inet-labeled")
33  (Address::INET6, "inet6")
34  (Address::INETVPN, "inet-vpn")
35  (Address::INET6VPN, "inet6-vpn")
36  (Address::RTARGET, "route-target")
37  (Address::EVPN, "e-vpn")
38  (Address::MVPN, "inet-mvpn")
39  (Address::ERMVPN, "erm-vpn");
40 
41 static const std::map<Address::Family, string>
42  toTableName = boost::assign::map_list_of
43  (Address::UNSPEC, "unspecified")
44  (Address::INET, "inet")
45  (Address::INETMPLS, "inet")
46  (Address::INET6, "inet6")
47  (Address::INETVPN, "l3vpn")
48  (Address::INET6VPN, "l3vpn-inet6")
49  (Address::RTARGET, "rtarget")
50  (Address::EVPN, "evpn")
51  (Address::MVPN, "mvpn")
52  (Address::ERMVPN, "ermvpn");
53 
54 Address::Family Address::FamilyFromString(const std::string &family) {
55  std::map<string, Address::Family>::const_iterator loc =
56  fromString.find(family);
57  if (loc != fromString.end()) {
58  return loc->second;
59  }
60  return Address::UNSPEC;
61 }
62 
64  return toString.find(family)->second;
65 }
66 
68  return toTableName.find(family)->second;
69 }
70 
72  switch (family) {
73  case Address::INET:
74  case Address::INETVPN:
75  return Address::INETVPN;
76  case Address::INET6:
77  case Address::INET6VPN:
78  return Address::INET6VPN;
79  case Address::EVPN:
80  return Address::EVPN;
81  case Address::MVPN:
82  return Address::MVPN;
83  case Address::ERMVPN:
84  return Address::ERMVPN;
85  default:
86  return Address::UNSPEC;
87  }
88  return Address::UNSPEC;
89 }
90 
91 static int CountDots(const string &str) {
92  int count = 0;
93  size_t pos = 0;
94  while (pos < str.size()) {
95  pos = str.find('.', pos);
96  if (pos == string::npos) {
97  break;
98  }
99  count++;
100  pos++;
101  }
102  return count;
103 }
104 
105 // Return the IP address part as it is i.e. 1.2.3.4/24 will return 1.2.3.4 and
106 // 24.
107 boost::system::error_code Ip4PrefixParse(const string &str, Ip4Address *addr,
108  int *plen) {
109  size_t pos = str.find('/');
110  if (pos == string::npos) {
111  return make_error_code(boost::system::errc::invalid_argument);
112  }
113  *plen = atoi(str.c_str() + pos + 1);
114  if ((*plen < 0) || (*plen > Address::kMaxV4PrefixLen)) {
115  return make_error_code(boost::system::errc::invalid_argument);
116  }
117 
118  string addrstr = str.substr(0, pos);
119  int dots = CountDots(addrstr);
120  while (dots < 3) {
121  addrstr.append(".0");
122  dots++;
123  }
124 
125  boost::system::error_code err;
126  *addr = Ip4Address::from_string(addrstr, err);
127  return err;
128 }
129 
130 // Return the bitwise and of IP and mask.
131 boost::system::error_code Ip4SubnetParse(const string &str, Ip4Address *addr,
132  int *plen) {
133  Ip4Address address;
134  boost::system::error_code err;
135  err = Ip4PrefixParse(str, &address, plen);
136  if (!err) {
137  *addr = Address::GetIp4SubnetAddress(address, *plen);
138  }
139  return err;
140 }
141 
142 // Return the IP address part as it is i.e. 2001:db8:85a3:aaaa::b:c:d/64 will
143 // return 2001:db8:85a3:aaaa::b:c:d and 64.
144 boost::system::error_code Inet6PrefixParse(const string &str, Ip6Address *addr,
145  int *plen) {
146  size_t pos = str.find('/');
147  if (pos == string::npos) {
148  return make_error_code(boost::system::errc::invalid_argument);
149  }
150  *plen = atoi(str.c_str() + pos + 1);
151  if ((*plen < 0) || (*plen > Address::kMaxV6PrefixLen)) {
152  return make_error_code(boost::system::errc::invalid_argument);
153  }
154 
155  string addrstr = str.substr(0, pos);
156  boost::system::error_code err;
157  *addr = Ip6Address::from_string(addrstr, err);
158  return err;
159 }
160 
161 // Return the bitwise and of IP and mask.
162 boost::system::error_code Inet6SubnetParse(const string &str, Ip6Address *addr,
163  int *plen) {
164  Ip6Address address;
165  boost::system::error_code err;
166  err = Inet6PrefixParse(str, &address, plen);
167  if (!err) {
168  *addr = Address::GetIp6SubnetAddress(address, *plen);
169  }
170  return err;
171 }
172 
173 /* Returns IPv4 subnet address for a given IPv4 address and prefix length. The
174  * IPv4 address and prefix lengths are converted to u32 numbers and then bitwise
175  * AND operation is performed between those 2 numbers and the resulting u32
176  * number is converted to IPv4Address object and returned. If prefix length is 0
177  * then 0 is converted to IPv4Address object and returned.
178  */
179 Ip4Address Address::GetIp4SubnetAddress(const Ip4Address &prefix, uint16_t plen) {
180  if (plen == 0) {
181  return boost::asio::ip::address_v4(0);
182  }
183 
184  Ip4Address subnet(prefix.to_ulong() & (0xFFFFFFFF << (32 - plen)));
185  return subnet;
186 }
187 
188 /* Returns IPv6 subnet address for a given IPv6 address and prefix length. The
189  * input IPv6 address is first converted into an array of 8 two byte integers.
190  * Based on prefix length we first figure out the array index position from
191  * where the masking of bits needs to start. Once the array index is found we
192  * have 16 possible bit positions from where masking has to start. For each of
193  * the 16 positions we have a unique 16 byte constant that we use to mask the
194  * two byte integer. Once the array position is appropriately masked we mask
195  * the rest of two byte integers till the array ends. The resulting array is
196  * converted to IPv6 object and returned. If the prefix length is 0 then we
197  * return an IPv6 object constructed using its default constructors which
198  * assumes all bits as 0s.
199  */
200 Ip6Address Address::GetIp6SubnetAddress(const Ip6Address &prefix, uint16_t plen) {
201  if (plen == 0) {
202  return boost::asio::ip::address_v6();
203  }
204 
205  if (plen == 128) {
206  return prefix;
207  }
208 
209  uint16_t ip6[8], in_ip6[8];
210  unsigned char bytes[16];
211 
212  inet_pton(AF_INET6, prefix.to_string().c_str(), ip6);
213 
214  for (int i = 0; i < 8; ++i) {
215  in_ip6[i] = ntohs(ip6[i]);
216  }
217 
218  int index = (int) (plen / 16);
219  int remain_mask = plen % 16;
220 
221  switch (remain_mask) {
222  case 0:
223  in_ip6[index++] = 0;
224  break;
225  case 1:
226  in_ip6[index++] &= 0x8000;
227  break;
228  case 2:
229  in_ip6[index++] &= 0xc000;
230  break;
231  case 3:
232  in_ip6[index++] &= 0xe000;
233  break;
234  case 4:
235  in_ip6[index++] &= 0xf000;
236  break;
237  case 5:
238  in_ip6[index++] &= 0xf800;
239  break;
240  case 6:
241  in_ip6[index++] &= 0xfc00;
242  break;
243  case 7:
244  in_ip6[index++] &= 0xfe00;
245  break;
246  case 8:
247  in_ip6[index++] &= 0xff00;
248  break;
249  case 9:
250  in_ip6[index++] &= 0xff80;
251  break;
252  case 10:
253  in_ip6[index++] &= 0xffc0;
254  break;
255  case 11:
256  in_ip6[index++] &= 0xffe0;
257  break;
258  case 12:
259  in_ip6[index++] &= 0xfff0;
260  break;
261  case 13:
262  in_ip6[index++] &= 0xfff8;
263  break;
264  case 14:
265  in_ip6[index++] &= 0xfffc;
266  break;
267  case 15:
268  in_ip6[index++] &= 0xfffe;
269  break;
270  }
271 
272  for (int i = index; i < 8; ++i) {
273  in_ip6[i] = 0;
274  }
275 
276  for (int i = 0; i < 8; ++i) {
277  ip6[i] = htons(in_ip6[i]);
278  }
279  memcpy(bytes, ip6, sizeof(ip6));
280  Ip6Address::bytes_type to_bytes;
281  for (int i = 0; i < 16; ++i) {
282  to_bytes.at(i) = bytes[i];
283  }
284  return boost::asio::ip::address_v6(to_bytes);
285 }
286 
287 // Ip6Address.to_v4() has exceptions. Plus, we dont have a to_v4() version
288 // without exceptions that takes an boost::error_code.
289 // If the v6-address is v4_mapped, return the ipv4 equivalent address. Else
290 // return a 'zero' ipv4 address.
292  Ip4Address v4_address;
293  if (v6_address.is_v4_mapped()) {
294  Ip6Address::bytes_type v6_bt = v6_address.to_bytes();
295  Ip4Address::bytes_type v4_bt =
296  { { v6_bt[12], v6_bt[13], v6_bt[14], v6_bt[15] } };
297  v4_address = Ip4Address(v4_bt);
298  }
299  return v4_address;
300 }
static Family VpnFamilyFromFamily(Family family)
Definition: address.cc:71
static const uint8_t kMaxV6PrefixLen
Definition: address.h:22
boost::system::error_code Ip4PrefixParse(const string &str, Ip4Address *addr, int *plen)
Definition: address.cc:107
Family
Definition: address.h:24
static Family FamilyFromString(const std::string &family)
Definition: address.cc:54
static const uint8_t kMaxV4PrefixLen
Definition: address.h:20
static std::string FamilyToTableString(Family family)
Definition: address.cc:67
static Ip4Address GetIp4SubnetAddress(const Ip4Address &prefix, uint16_t plen)
Definition: address.cc:179
static Ip6Address GetIp6SubnetAddress(const Ip6Address &prefix, uint16_t plen)
Definition: address.cc:200
static int CountDots(const string &str)
Definition: address.cc:91
boost::asio::ip::address_v6 Ip6Address
Definition: address.h:15
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
boost::system::error_code Ip4SubnetParse(const string &str, Ip4Address *addr, int *plen)
Definition: address.cc:131
static const std::map< Address::Family, string > toTableName
Definition: address.cc:42
static std::string FamilyToString(Family fmly)
Definition: address.cc:63
boost::system::error_code Inet6PrefixParse(const string &str, Ip6Address *addr, int *plen)
Definition: address.cc:144
static const std::map< Address::Family, string > toString
Definition: address.cc:29
Address()
Definition: address.cc:12
static Ip4Address V4FromV4MappedV6(const Ip6Address &v6_address)
Definition: address.cc:291
static const std::map< string, Address::Family > fromString
Definition: address.cc:16
boost::system::error_code Inet6SubnetParse(const string &str, Ip6Address *addr, int *plen)
Definition: address.cc:162