1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "netdutils/InternetAddresses.h"
18 
19 #include <string>
20 
21 #include <android-base/stringprintf.h>
22 #include <arpa/inet.h>
23 #include <netdb.h>
24 #include <sys/socket.h>
25 #include <sys/types.h>
26 
27 namespace android {
28 
29 using base::StringPrintf;
30 
31 namespace netdutils {
32 
toString() const33 std::string IPAddress::toString() const noexcept {
34     char repr[INET6_ADDRSTRLEN] = "\0";
35 
36     switch (mData.family) {
37         case AF_UNSPEC:
38             return "<unspecified>";
39         case AF_INET: {
40             const in_addr v4 = mData.ip.v4;
41             inet_ntop(AF_INET, &v4, repr, sizeof(repr));
42             break;
43         }
44         case AF_INET6: {
45             const in6_addr v6 = mData.ip.v6;
46             inet_ntop(AF_INET6, &v6, repr, sizeof(repr));
47             break;
48         }
49         default:
50             return "<unknown_family>";
51     }
52 
53     if (mData.family == AF_INET6 && mData.scope_id > 0) {
54         return StringPrintf("%s%%%u", repr, mData.scope_id);
55     }
56 
57     return repr;
58 }
59 
forString(const std::string & repr,IPAddress * ip)60 bool IPAddress::forString(const std::string& repr, IPAddress* ip) {
61     const addrinfo hints = {
62             .ai_flags = AI_NUMERICHOST | AI_NUMERICSERV,
63     };
64     addrinfo* res;
65     const int ret = getaddrinfo(repr.c_str(), nullptr, &hints, &res);
66     ScopedAddrinfo res_cleanup(res);
67     if (ret != 0) {
68         return false;
69     }
70 
71     bool rval = true;
72     switch (res[0].ai_family) {
73         case AF_INET: {
74             sockaddr_in* sin = (sockaddr_in*) res[0].ai_addr;
75             if (ip) *ip = IPAddress(sin->sin_addr);
76             break;
77         }
78         case AF_INET6: {
79             sockaddr_in6* sin6 = (sockaddr_in6*) res[0].ai_addr;
80             if (ip) *ip = IPAddress(sin6->sin6_addr, sin6->sin6_scope_id);
81             break;
82         }
83         default:
84             rval = false;
85             break;
86     }
87 
88     return rval;
89 }
90 
IPPrefix(const IPAddress & ip,int length)91 IPPrefix::IPPrefix(const IPAddress& ip, int length) : IPPrefix(ip) {
92     // Silently treat CIDR lengths like "-1" as meaning the full bit length
93     // appropriate to the address family.
94     if (length < 0) return;
95     if (length >= mData.cidrlen) return;
96 
97     switch (mData.family) {
98         case AF_UNSPEC:
99             break;
100         case AF_INET: {
101             const in_addr_t mask = (length > 0) ? (~0U) << (IPV4_ADDR_BITS - length) : 0U;
102             mData.ip.v4.s_addr &= htonl(mask);
103             mData.cidrlen = static_cast<uint8_t>(length);
104             break;
105         }
106         case AF_INET6: {
107             // The byte in which this CIDR length falls.
108             const int which = length / 8;
109             const int mask = (length % 8 == 0) ? 0 : 0xff << (8 - length % 8);
110             mData.ip.v6.s6_addr[which] &= mask;
111             for (int i = which + 1; i < IPV6_ADDR_LEN; i++) {
112                 mData.ip.v6.s6_addr[i] = 0U;
113             }
114             mData.cidrlen = static_cast<uint8_t>(length);
115             break;
116         }
117         default:
118             // TODO: Complain bitterly about possible data corruption?
119             return;
120     }
121 }
122 
isUninitialized() const123 bool IPPrefix::isUninitialized() const noexcept {
124     static const internal_::compact_ipdata empty{};
125     return mData == empty;
126 }
127 
forString(const std::string & repr,IPPrefix * prefix)128 bool IPPrefix::forString(const std::string& repr, IPPrefix* prefix) {
129     size_t index = repr.find('/');
130     if (index == std::string::npos) return false;
131 
132     // Parse the IP address.
133     IPAddress ip;
134     if (!IPAddress::forString(repr.substr(0, index), &ip)) return false;
135 
136     // Parse the prefix length. Can't use base::ParseUint because it accepts non-base 10 input.
137     const char* prefixString = repr.c_str() + index + 1;
138     if (!isdigit(*prefixString)) return false;
139     char* endptr;
140     unsigned long prefixlen = strtoul(prefixString, &endptr, 10);
141     if (*endptr != '\0') return false;
142 
143     uint8_t maxlen = (ip.family() == AF_INET) ? 32 : 128;
144     if (prefixlen > maxlen) return false;
145 
146     *prefix = IPPrefix(ip, prefixlen);
147     return true;
148 }
149 
toString() const150 std::string IPPrefix::toString() const noexcept {
151     return StringPrintf("%s/%d", ip().toString().c_str(), mData.cidrlen);
152 }
153 
toString() const154 std::string IPSockAddr::toString() const noexcept {
155     switch (mData.family) {
156         case AF_INET6:
157             return StringPrintf("[%s]:%u", ip().toString().c_str(), mData.port);
158         default:
159             return StringPrintf("%s:%u", ip().toString().c_str(), mData.port);
160     }
161 }
162 
163 }  // namespace netdutils
164 }  // namespace android
165