blob: 43ebf436b2238c50f01f421064922fa7d4a2a6a9 [file] [log] [blame]
Ratan Gupta8804feb2017-05-25 10:49:57 +05301#include <arpa/inet.h>
2#include <dirent.h>
3#include <net/if.h>
Ratan Gupta11cef802017-05-29 08:41:48 +05304#include "xyz/openbmc_project/Common/error.hpp"
5
6#include <phosphor-logging/log.hpp>
7#include <phosphor-logging/elog-errors.hpp>
Ratan Gupta8804feb2017-05-25 10:49:57 +05308
9#include <iostream>
10#include <list>
11#include <string>
12#include <algorithm>
Ratan Gupta8804feb2017-05-25 10:49:57 +053013
14namespace phosphor
15{
16namespace network
17{
18namespace
19{
20
21using namespace phosphor::logging;
Ratan Gupta11cef802017-05-29 08:41:48 +053022using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Ratan Gupta8804feb2017-05-25 10:49:57 +053023
24uint8_t toV6Cidr(const std::string& subnetMask)
25{
26 uint8_t pos = 0;
27 uint8_t prevPos = 0;
28 uint8_t cidr = 0;
29 uint16_t buff {};
30 do
31 {
32 //subnet mask look like ffff:ffff::
33 // or ffff:c000::
34 pos = subnetMask.find(":", prevPos);
35 if (pos == std::string::npos)
36 {
37 break;
38 }
39
40 auto str = subnetMask.substr(prevPos, (pos - prevPos));
41 prevPos = pos + 1;
42
43 // String length is 0
44 if (!str.length())
45 {
46 return cidr;
47 }
48 //converts it into number.
49 if (sscanf(str.c_str(), "%hx", &buff) <= 0)
50 {
51 log<level::ERR>("Invalid Mask",
52 entry("SUBNETMASK=%s", subnetMask));
53
54 return 0;
55 }
56
57 // convert the number into bitset
58 // and check for how many ones are there.
59 // if we don't have all the ones then make
60 // sure that all the ones should be left justify.
61
62 if (__builtin_popcount(buff) != 16)
63 {
64 if (((sizeof(buff) * 8) - (__builtin_ctz(buff))) != __builtin_popcount(buff))
65 {
66 log<level::ERR>("Invalid Mask",
67 entry("SUBNETMASK=%s", subnetMask));
68
69 return 0;
70 }
71 cidr += __builtin_popcount(buff);
72 return cidr;
73 }
74
75 cidr += 16;
76 }
77 while (1);
78
79 return cidr;
80}
81}// anonymous namespace
82
83uint8_t toCidr(int addressFamily, const std::string& subnetMask)
84{
85 if (addressFamily == AF_INET6)
86 {
87 return toV6Cidr(subnetMask);
88 }
89
90 uint32_t buff;
91
92 auto rc = inet_pton(addressFamily, subnetMask.c_str(), &buff);
93 if (rc <= 0)
94 {
95 log<level::ERR>("inet_pton failed:",
Ratan Gupta11cef802017-05-29 08:41:48 +053096 entry("SUBNETMASK=%s", subnetMask));
Ratan Gupta8804feb2017-05-25 10:49:57 +053097 return 0;
98 }
99
100 buff = be32toh(buff);
101 // total no of bits - total no of leading zero == total no of ones
102 if (((sizeof(buff) * 8) - (__builtin_ctz(buff))) == __builtin_popcount(buff))
103 {
104 return __builtin_popcount(buff);
105 }
106 else
107 {
108 log<level::ERR>("Invalid Mask",
Ratan Gupta11cef802017-05-29 08:41:48 +0530109 entry("SUBNETMASK=%s", subnetMask));
Ratan Gupta8804feb2017-05-25 10:49:57 +0530110 return 0;
111 }
112}
113
114std::string toMask(int addressFamily, uint8_t prefix)
115{
116 if (addressFamily == AF_INET6)
117 {
118 //TODO:- conversion for v6
119 return "";
120 }
121
122 if (prefix < 1 || prefix > 30)
123 {
124 log<level::ERR>("Invalid Prefix",
125 entry("PREFIX=%d", prefix));
126 return "";
127 }
128 /* Create the netmask from the number of bits */
129 unsigned long mask = 0;
130 for (auto i = 0 ; i < prefix ; i++)
131 {
132 mask |= 1 << (31 - i);
133 }
134 struct in_addr netmask;
135 netmask.s_addr = htonl(mask);
136 return inet_ntoa(netmask);
137}
138
Ratan Gupta11cef802017-05-29 08:41:48 +0530139std::string getNetworkID(int addressFamily, const std::string& ipaddress,
140 uint8_t prefix)
141{
142 unsigned char* pntMask = nullptr;
143 unsigned char* pntNetwork = nullptr;
144 int bit {};
145 int offset {};
146 struct in6_addr netmask {};
147 const u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
148 0xf8, 0xfc, 0xfe, 0xff
149 };
150
151 pntMask = reinterpret_cast<unsigned char*>(&netmask);
152
153 offset = prefix / 8;
154 bit = prefix % 8;
155
156 while (offset--)
157 {
158 *pntMask++ = 0xff;
159 }
160
161 if (bit)
162 {
163 *pntMask = maskbit[bit];
164 }
165
166 // convert ipaddres string into network address
167 struct in6_addr ipaddressNetwork;
168 if (inet_pton(addressFamily, ipaddress.c_str(), &ipaddressNetwork) <= 0)
169 {
170 log<level::ERR>("inet_pton failure",
171 entry("IPADDRESS=%s",ipaddress.c_str()));
172 report<InternalFailure>();
173
174 return "";
175 }
176
177 // Now bit wise and gets you the network address
178 pntMask = reinterpret_cast<unsigned char*>(&netmask);
179 pntNetwork = reinterpret_cast<unsigned char*>(&ipaddressNetwork);
180
181 for (int i = 0; i < 16 ; i++)
182 {
183 pntNetwork[i] = pntNetwork[i] & pntMask[i];
184 }
185
186 //convert the network address into string fomat.
187 char networkString[INET6_ADDRSTRLEN] = { 0 };
188 if (inet_ntop(addressFamily, &ipaddressNetwork, networkString,
189 INET6_ADDRSTRLEN) == NULL)
190 {
191 log<level::ERR>("inet_ntop failure");
192 report<InternalFailure>();
193 }
194 return networkString;
195}
196
Ratan Gupta8804feb2017-05-25 10:49:57 +0530197bool isLinkLocal(const std::string& address)
198{
199 std::string linklocal = "fe80";
200 return std::mismatch(linklocal.begin(), linklocal.end(),
201 address.begin()).first == linklocal.end() ?
202 true : false;
203}
204
205}//namespace network
206}//namespace phosphor