1 /**
2  * Copyright (C) 2022 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 <errno.h>
18 #include <arpa/inet.h>
19 #include <ImsMediaNetworkUtil.h>
20 #include <ImsMediaTrace.h>
21 
22 #define V4MAPPED_OFFSET   12
23 #define NUM_OF_BYTES_IPV4 4
24 #define NUM_OF_BYTES_IPV6 6
25 
GetIpPortFromSockAddr(const sockaddr_storage & ss,char * ipAddress,int len,unsigned int & port)26 static bool GetIpPortFromSockAddr(
27         const sockaddr_storage& ss, char* ipAddress, int len, unsigned int& port)
28 {
29     const sockaddr_in6& sin6 = reinterpret_cast<const sockaddr_in6&>(ss);
30     if (ss.ss_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sin6.sin6_addr))
31     {
32         // Copy the IPv6 address into the temporary sockaddr_storage.
33         sockaddr_storage tmp;
34         memset(&tmp, 0, sizeof(tmp));
35         memcpy(&tmp, &ss, sizeof(sockaddr_in6));
36         // Unmap it into an IPv4 address.
37         sockaddr_in& sin = reinterpret_cast<sockaddr_in&>(tmp);
38         sin.sin_family = AF_INET;
39         sin.sin_port = sin6.sin6_port;
40         memcpy(&sin.sin_addr.s_addr, &sin6.sin6_addr.s6_addr[V4MAPPED_OFFSET], NUM_OF_BYTES_IPV4);
41         // Do the regular conversion using the unmapped address.
42         return GetIpPortFromSockAddr(tmp, ipAddress, len, port);
43     }
44 
45     if (ss.ss_family == AF_INET)
46     {
47         const sockaddr_in& sin = reinterpret_cast<const sockaddr_in&>(ss);
48         strncpy(ipAddress, inet_ntoa(sin.sin_addr), len);
49         // memcpy(ipAddress, &(sin.sin_addr.s_addr), sizeof(struct in_addr));
50         port = ntohs(sin.sin_port);
51     }
52     else if (ss.ss_family == AF_INET6)
53     {
54         inet_ntop(AF_INET6, sin6.sin6_addr.s6_addr, ipAddress, len);
55         port = ntohs(sin6.sin6_port);
56     }
57     else
58     {
59         return false;
60     }
61 
62     IMLOGD2("[GetIpPortFromSockAddr] %s:%u", ipAddress, port);
63     return true;
64 }
65 
getLocalIpPortFromSocket(const int nSocketFD,char * pIPAddress,int len,unsigned int & port)66 bool ImsMediaNetworkUtil::getLocalIpPortFromSocket(
67         const int nSocketFD, char* pIPAddress, int len, unsigned int& port)
68 {
69     if (pIPAddress == nullptr)
70     {
71         return false;
72     }
73 
74     sockaddr_storage ss;
75     sockaddr* sa = reinterpret_cast<sockaddr*>(&ss);
76     socklen_t byteCount = sizeof(ss);
77     errno = 0;
78     int res = getsockname(nSocketFD, sa, &byteCount);
79     if (res == -1)
80     {
81         IMLOGE1("[getLocalIpPortFromSocket] getsockname failed. Error[%d]", errno);
82         return false;
83     }
84 
85     return GetIpPortFromSockAddr(ss, pIPAddress, len, port);
86 }
87 
getRemoteIpPortFromSocket(const int nSocketFD,char * pIPAddress,int len,unsigned int & port)88 bool ImsMediaNetworkUtil::getRemoteIpPortFromSocket(
89         const int nSocketFD, char* pIPAddress, int len, unsigned int& port)
90 {
91     if (pIPAddress == nullptr)
92     {
93         return false;
94     }
95 
96     sockaddr_storage ss;
97     sockaddr* sa = reinterpret_cast<sockaddr*>(&ss);
98     socklen_t byteCount = sizeof(ss);
99     errno = 0;
100     int res = getpeername(nSocketFD, sa, &byteCount);
101     if (res == -1)
102     {
103         IMLOGE1("[getRemoteIpPortFromSocket] getpeername failed. Error[%d]", errno);
104         return false;
105     }
106 
107     return GetIpPortFromSockAddr(ss, pIPAddress, len, port);
108 }
109 
openSocket(const char * pIPAddr,unsigned int port,int af)110 int ImsMediaNetworkUtil::openSocket(const char* pIPAddr, unsigned int port, int af)
111 {
112     int soc = 0;
113     if ((soc = socket(af, SOCK_DGRAM, IPPROTO_UDP)) < 0)
114     {
115         IMLOGE1("[openSocket] error[%d]", errno);
116         return -1;
117     }
118 
119     if (af == AF_INET)
120     {
121         sockaddr_in sin;
122         sin.sin_family = AF_INET;
123         sin.sin_port = htons(port);
124 
125         if (inet_pton(AF_INET, pIPAddr, &sin.sin_addr) <= 0)
126         {
127             IMLOGE1("[openSocket] inet_pton error[%d]", errno);
128             return -1;
129         }
130 
131         if (bind(soc, (struct sockaddr*)&sin, sizeof(sin)) < 0)
132         {
133             IMLOGE1("[openSocket] bind error[%d]", errno);
134             return -1;
135         }
136     }
137     else if (af == AF_INET6)
138     {
139         sockaddr_in6 sin6;
140         sin6.sin6_family = AF_INET6;
141         sin6.sin6_port = htons(port);
142 
143         if (inet_pton(AF_INET6, pIPAddr, &sin6.sin6_addr) <= 0)
144         {
145             IMLOGE1("[openSocket] error[%d]", errno);
146             return -1;
147         }
148 
149         if (bind(soc, (struct sockaddr*)&sin6, sizeof(sin6)) < 0)
150         {
151             IMLOGE1("[openSocket] bind error[%d]", errno);
152             return -1;
153         }
154     }
155 
156     return soc;
157 }
158 
connectSocket(const int socketFd,const char * pIPAddr,unsigned int port,int af)159 bool ImsMediaNetworkUtil::connectSocket(
160         const int socketFd, const char* pIPAddr, unsigned int port, int af)
161 {
162     if (socketFd == -1)
163     {
164         IMLOGE0("[connectSocket] invalid socket fd");
165         return false;
166     }
167 
168     if (af == AF_INET)
169     {
170         sockaddr_in sin;
171         sin.sin_family = AF_INET;
172         sin.sin_port = htons(port);
173 
174         if (inet_pton(AF_INET, pIPAddr, &sin.sin_addr) <= 0)
175         {
176             IMLOGE1("[connectSocket] inet_pton error[%d]", errno);
177             return -1;
178         }
179 
180         if (connect(socketFd, (struct sockaddr*)&sin, sizeof(sockaddr_in)) < 0)
181         {
182             IMLOGE1("[connectSocket] connect error[%d]", errno);
183             return false;
184         }
185     }
186     else if (af == AF_INET6)
187     {
188         sockaddr_in6 sin6;
189         sin6.sin6_family = AF_INET6;
190         sin6.sin6_port = htons(port);
191 
192         if (inet_pton(AF_INET6, pIPAddr, &sin6.sin6_addr) <= 0)
193         {
194             IMLOGE1("[connectSocket] error[%d]", errno);
195             return -1;
196         }
197 
198         if (connect(socketFd, (struct sockaddr*)&sin6, sizeof(sockaddr_in6)) < 0)
199         {
200             IMLOGE1("[connectSocket] error[%d]", errno);
201             return false;
202         }
203     }
204 
205     return true;
206 }
207 
closeSocket(int & socketFd)208 void ImsMediaNetworkUtil::closeSocket(int& socketFd)
209 {
210     shutdown(socketFd, SHUT_RDWR);
211     close(socketFd);
212     socketFd = -1;
213 }