• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <android-base/stringprintf.h>
20 #include <arpa/inet.h>
21 #include <netdb.h>
22 #include <sys/socket.h>
23 #include <sys/types.h>
24 
25 namespace android {
26 
27 using base::StringPrintf;
28 
29 namespace netdutils {
30 
toString() const31 std::string IPAddress::toString() const noexcept {
32     char repr[INET6_ADDRSTRLEN] = "\0";
33 
34     switch (mData.family) {
35         case AF_UNSPEC:
36             return "<unspecified>";
37         case AF_INET: {
38             const in_addr v4 = mData.ip.v4;
39             inet_ntop(AF_INET, &v4, repr, sizeof(repr));
40             break;
41         }
42         case AF_INET6: {
43             const in6_addr v6 = mData.ip.v6;
44             inet_ntop(AF_INET6, &v6, repr, sizeof(repr));
45             break;
46         }
47         default:
48             return "<unknown_family>";
49     }
50 
51     if (mData.family == AF_INET6 && mData.scope_id > 0) {
52         return StringPrintf("%s%%%u", repr, mData.scope_id);
53     }
54 
55     return repr;
56 }
57 
forString(const std::string & repr,IPAddress * ip)58 bool IPAddress::forString(const std::string& repr, IPAddress* ip) {
59     const addrinfo hints = {
60             .ai_flags = AI_NUMERICHOST | AI_NUMERICSERV,
61     };
62     addrinfo* res;
63     const int ret = getaddrinfo(repr.c_str(), nullptr, &hints, &res);
64     // TODO: move ScopedAddrinfo into libnetdutils and use it here.
65     if (ret != 0) {
66         freeaddrinfo(res);
67         return false;
68     }
69 
70     bool rval = true;
71     switch (res[0].ai_family) {
72         case AF_INET: {
73             sockaddr_in* sin = (sockaddr_in*) res[0].ai_addr;
74             if (ip) *ip = IPAddress(sin->sin_addr);
75             break;
76         }
77         case AF_INET6: {
78             sockaddr_in6* sin6 = (sockaddr_in6*) res[0].ai_addr;
79             if (ip) *ip = IPAddress(sin6->sin6_addr, sin6->sin6_scope_id);
80             break;
81         }
82         default:
83             rval = false;
84             break;
85     }
86 
87     freeaddrinfo(res);
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 
toString() const128 std::string IPPrefix::toString() const noexcept {
129     return StringPrintf("%s/%d", ip().toString().c_str(), mData.cidrlen);
130 }
131 
toString() const132 std::string IPSockAddr::toString() const noexcept {
133     switch (mData.family) {
134         case AF_INET6:
135             return StringPrintf("[%s]:%u", ip().toString().c_str(), mData.port);
136         default:
137             return StringPrintf("%s:%u", ip().toString().c_str(), mData.port);
138     }
139 }
140 
141 }  // namespace netdutils
142 }  // namespace android
143