Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020 Project CHIP Authors
4 : * Copyright (c) 2013-2017 Nest Labs, Inc.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 :
19 : /**
20 : * @file
21 : * This file implements the human-readable string formatting and
22 : * parsing methods from class <tt>Inet::IPAddress</tt>.
23 : *
24 : */
25 :
26 : #include <algorithm>
27 : #include <limits>
28 : #include <stdint.h>
29 : #include <stdio.h>
30 : #include <string.h>
31 :
32 : #include <inet/IPAddress.h>
33 : #include <lib/support/CodeUtils.h>
34 :
35 : #if CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS
36 : #include <arpa/inet.h>
37 : #endif
38 :
39 : namespace chip {
40 : namespace Inet {
41 :
42 10080 : char * IPAddress::ToString(char * buf, uint32_t bufSize) const
43 : {
44 : #if CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT
45 : #if INET_CONFIG_ENABLE_IPV4
46 : if (IsIPv4())
47 : {
48 : ip4_addr_t ip4_addr = ToIPv4();
49 : ip4addr_ntoa_r(&ip4_addr, buf, (int) bufSize);
50 : }
51 : else
52 : #endif // INET_CONFIG_ENABLE_IPV4
53 : {
54 : ip6_addr_t ip6_addr = ToIPv6();
55 : ip6addr_ntoa_r(&ip6_addr, buf, (int) bufSize);
56 : }
57 : #elif CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK
58 : // socklen_t is sometimes signed, sometimes not, so the only safe way to do
59 : // this is to promote everything to an unsigned type that's known to be big
60 : // enough for everything, then cast back to uint32_t after taking the min.
61 10080 : bufSize = static_cast<uint32_t>(
62 10080 : std::min(static_cast<uintmax_t>(std::numeric_limits<socklen_t>::max()), static_cast<uintmax_t>(bufSize)));
63 : #if INET_CONFIG_ENABLE_IPV4
64 10080 : if (IsIPv4())
65 : {
66 105 : const void * addr = &Addr[3];
67 105 : const char * s = inet_ntop(AF_INET, addr, buf, static_cast<socklen_t>(bufSize));
68 : // This cast is safe because |s| points into |buf| which is not const.
69 105 : buf = const_cast<char *>(s);
70 : }
71 : else
72 : #endif // INET_CONFIG_ENABLE_IPV4
73 : {
74 9975 : const void * addr = &Addr[0];
75 9975 : const char * s = inet_ntop(AF_INET6, addr, buf, static_cast<socklen_t>(bufSize));
76 : // This cast is safe because |s| points into |buf| which is not const.
77 9975 : buf = const_cast<char *>(s);
78 : }
79 : #elif CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT
80 : otIp6Address addr = ToIPv6();
81 : otIp6AddressToString(&addr, buf, static_cast<uint16_t>(bufSize));
82 : #endif // !CHIP_SYSTEM_CONFIG_USE_LWIP
83 :
84 10080 : return buf;
85 : }
86 :
87 867 : bool IPAddress::FromString(const char * str, IPAddress & output)
88 : {
89 : #if INET_CONFIG_ENABLE_IPV4
90 867 : if (strchr(str, ':') == nullptr)
91 : {
92 : #if CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT
93 : ip4_addr_t ipv4Addr;
94 : if (!ip4addr_aton(str, &ipv4Addr))
95 : return false;
96 : #elif CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK
97 : struct in_addr ipv4Addr;
98 251 : if (inet_pton(AF_INET, str, &ipv4Addr) < 1)
99 0 : return false;
100 : #endif // !CHIP_SYSTEM_CONFIG_USE_LWIP
101 251 : output = IPAddress(ipv4Addr);
102 : }
103 : else
104 : #endif // INET_CONFIG_ENABLE_IPV4
105 : {
106 : #if CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT
107 : ip6_addr_t ipv6Addr;
108 : if (!ip6addr_aton(str, &ipv6Addr))
109 : return false;
110 : #elif CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK
111 : struct in6_addr ipv6Addr;
112 616 : if (inet_pton(AF_INET6, str, &ipv6Addr) < 1)
113 0 : return false;
114 : #elif CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT
115 : otIp6Address ipv6Addr;
116 : if (OT_ERROR_NONE != otIp6AddressFromString(str, &ipv6Addr))
117 : return false;
118 : #endif
119 616 : output = IPAddress(ipv6Addr);
120 : }
121 :
122 867 : return true;
123 : }
124 :
125 55 : bool IPAddress::FromString(const char * str, size_t strLen, IPAddress & output)
126 : {
127 55 : bool res = false;
128 :
129 55 : if (strLen < INET6_ADDRSTRLEN)
130 : {
131 : char hostNameBuf[INET6_ADDRSTRLEN];
132 55 : memcpy(hostNameBuf, str, strLen);
133 55 : hostNameBuf[strLen] = 0;
134 55 : res = IPAddress::FromString(hostNameBuf, output);
135 : }
136 :
137 55 : return res;
138 : }
139 :
140 0 : bool IPAddress::FromString(const char * str, IPAddress & addrOutput, class InterfaceId & ifaceOutput)
141 : {
142 0 : char * addrStr = const_cast<char *>(str);
143 0 : char * addrPart = nullptr;
144 0 : char * scopePart = nullptr;
145 0 : char * strtokContext = nullptr;
146 :
147 0 : addrPart = strtok_r(addrStr, "%", &strtokContext);
148 0 : if (addrPart != nullptr)
149 : {
150 0 : scopePart = strtok_r(nullptr, "%", &strtokContext);
151 : }
152 :
153 0 : if (addrPart == nullptr || scopePart == nullptr)
154 : {
155 0 : ifaceOutput = Inet::InterfaceId();
156 0 : return Inet::IPAddress::FromString(addrStr, addrOutput);
157 : }
158 :
159 0 : CHIP_ERROR err = Inet::InterfaceId::InterfaceNameToId(scopePart, ifaceOutput);
160 0 : if (err != CHIP_NO_ERROR)
161 : {
162 0 : return false;
163 : }
164 0 : return Inet::IPAddress::FromString(addrPart, addrOutput);
165 : }
166 :
167 : } // namespace Inet
168 : } // namespace chip
|