1 /*
2  * Copyright (C) 2015 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 #define LOG_TAG "IpPrefix"
18 
19 #include <binder/IpPrefix.h>
20 #include <vector>
21 
22 #include <binder/IBinder.h>
23 #include <binder/Parcel.h>
24 #include <log/log.h>
25 #include <utils/Errors.h>
26 
27 using android::BAD_TYPE;
28 using android::BAD_VALUE;
29 using android::NO_ERROR;
30 using android::Parcel;
31 using android::status_t;
32 using android::UNEXPECTED_NULL;
33 using namespace ::android::binder;
34 
35 namespace android {
36 
37 namespace net {
38 
39 #define RETURN_IF_FAILED(calledOnce)                                     \
40     {                                                                    \
41         status_t returnStatus = calledOnce;                              \
42         if (returnStatus) {                                              \
43             ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
44             return returnStatus;                                         \
45          }                                                               \
46     }
47 
writeToParcel(Parcel * parcel) const48 status_t IpPrefix::writeToParcel(Parcel* parcel) const {
49     /*
50      * Keep implementation in sync with writeToParcel() in
51      * frameworks/base/core/java/android/net/IpPrefix.java.
52      */
53     std::vector<uint8_t> byte_vector;
54 
55     if (mIsIpv6) {
56         const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&mUnion.mIn6Addr);
57         byte_vector.insert(byte_vector.end(), bytes, bytes+sizeof(mUnion.mIn6Addr));
58     } else {
59         const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&mUnion.mInAddr);
60         byte_vector.insert(byte_vector.end(), bytes, bytes+sizeof(mUnion.mIn6Addr));
61     }
62 
63     RETURN_IF_FAILED(parcel->writeByteVector(byte_vector));
64     RETURN_IF_FAILED(parcel->writeInt32(static_cast<int32_t>(mPrefixLength)));
65 
66     return NO_ERROR;
67 }
68 
readFromParcel(const Parcel * parcel)69 status_t IpPrefix::readFromParcel(const Parcel* parcel) {
70     /*
71      * Keep implementation in sync with readFromParcel() in
72      * frameworks/base/core/java/android/net/IpPrefix.java.
73      */
74     std::vector<uint8_t> byte_vector;
75 
76     RETURN_IF_FAILED(parcel->readByteVector(&byte_vector));
77     RETURN_IF_FAILED(parcel->readInt32(&mPrefixLength));
78 
79     if (byte_vector.size() == 16) {
80         mIsIpv6 = true;
81         memcpy((void*)&mUnion.mIn6Addr, &byte_vector[0], sizeof(mUnion.mIn6Addr));
82 
83     } else if (byte_vector.size() == 4) {
84         mIsIpv6 = false;
85         memcpy((void*)&mUnion.mInAddr, &byte_vector[0], sizeof(mUnion.mInAddr));
86 
87     } else {
88         ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
89         return BAD_VALUE;
90     }
91 
92     return NO_ERROR;
93 }
94 
getAddressAsIn6Addr() const95 const struct in6_addr& IpPrefix::getAddressAsIn6Addr() const
96 {
97     return mUnion.mIn6Addr;
98 }
99 
getAddressAsInAddr() const100 const struct in_addr& IpPrefix::getAddressAsInAddr() const
101 {
102     return mUnion.mInAddr;
103 }
104 
getAddressAsIn6Addr(struct in6_addr * addr) const105 bool IpPrefix::getAddressAsIn6Addr(struct in6_addr* addr) const
106 {
107     if (isIpv6()) {
108         *addr = mUnion.mIn6Addr;
109         return true;
110     }
111     return false;
112 }
113 
getAddressAsInAddr(struct in_addr * addr) const114 bool IpPrefix::getAddressAsInAddr(struct in_addr* addr) const
115 {
116     if (isIpv4()) {
117         *addr = mUnion.mInAddr;
118         return true;
119     }
120     return false;
121 }
122 
isIpv6() const123 bool IpPrefix::isIpv6() const
124 {
125     return mIsIpv6;
126 }
127 
isIpv4() const128 bool IpPrefix::isIpv4() const
129 {
130     return !mIsIpv6;
131 }
132 
getPrefixLength() const133 int32_t IpPrefix::getPrefixLength() const
134 {
135     return mPrefixLength;
136 }
137 
setAddress(const struct in6_addr & addr)138 void IpPrefix::setAddress(const struct in6_addr& addr)
139 {
140     mUnion.mIn6Addr = addr;
141     mIsIpv6 = true;
142 }
143 
setAddress(const struct in_addr & addr)144 void IpPrefix::setAddress(const struct in_addr& addr)
145 {
146     mUnion.mInAddr = addr;
147     mIsIpv6 = false;
148 }
149 
setPrefixLength(int32_t prefix)150 void IpPrefix::setPrefixLength(int32_t prefix)
151 {
152     mPrefixLength = prefix;
153 }
154 
operator ==(const IpPrefix & lhs,const IpPrefix & rhs)155 bool operator==(const IpPrefix& lhs, const IpPrefix& rhs)
156 {
157     if (lhs.mIsIpv6 != rhs.mIsIpv6) {
158         return false;
159     }
160 
161     if (lhs.mPrefixLength != rhs.mPrefixLength) {
162         return false;
163     }
164 
165     if (lhs.mIsIpv6) {
166         return 0 == memcmp(lhs.mUnion.mIn6Addr.s6_addr, rhs.mUnion.mIn6Addr.s6_addr, sizeof(struct in6_addr));
167     }
168 
169     return 0 == memcmp(&lhs.mUnion.mInAddr, &rhs.mUnion.mInAddr, sizeof(struct in_addr));
170 }
171 
172 }  // namespace net
173 
174 }  // namespace android
175