Project Alice
Loading...
Searching...
No Matches
sock_ntop.c
Go to the documentation of this file.
1/*
2 Copyright (c) 2014 by Cisco Systems, Inc.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 1. Redistributions of source code must retain the above copyright notice, this
9 list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright notice,
11 this list of conditions and the following disclaimer in the documentation
12 and/or other materials provided with the distribution.
13
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifdef HAVE_CONFIG_H
27#include "config.h"
28#else
29#include "default_config.h"
30#endif
31
32#ifdef _MSC_VER
33#define _CRT_SECURE_NO_WARNINGS 1
34#endif
35
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <sys/types.h> /* basic system data types */
40#ifdef WIN32
42#else
43#include <sys/socket.h> /* basic socket definitions */
44#include <netinet/in.h> /* sockaddr_in{} and other Internet defns */
45#include <arpa/inet.h> /* inet(3) functions */
46#include <netdb.h>
47#endif
48#include <errno.h>
49#include <ctype.h>
50#include "pcp_utils.h"
51#include "unp.h"
52
53#ifdef HAVE_SOCKADDR_DL_STRUCT
54#include <net/if_dl.h>
55#endif
56
57/* include sock_ntop */
58char *sock_ntop(const struct sockaddr *sa, socklen_t salen)
59{
60 char portstr[8];
61 static char str[128]; /* Unix domain is largest */
62
63 switch (sa->sa_family) {
64 case AF_INET: {
65 const struct sockaddr_in *sin=(const struct sockaddr_in *)sa;
66
67 if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL)
68 return (NULL);
69 if (ntohs(sin->sin_port) != 0) {
70 snprintf(portstr, sizeof(portstr) - 1, ":%d",
71 ntohs(sin->sin_port));
72 portstr[sizeof(portstr) - 1]='\0';
73 strcat(str, portstr);
74 }
75 return (str);
76 }
77 /* end sock_ntop */
78
79#ifdef AF_INET6
80 case AF_INET6: {
81 const struct sockaddr_in6 *sin6=(const struct sockaddr_in6 *)sa;
82
83 str[0]='[';
84 if (inet_ntop(AF_INET6, &sin6->sin6_addr, str + 1,
85 sizeof(str) - 1) == NULL)
86 return (NULL);
87 if (ntohs(sin6->sin6_port) != 0) {
88 snprintf(portstr, sizeof(portstr), "]:%d",
89 ntohs(sin6->sin6_port));
90 portstr[sizeof(portstr) - 1]='\0';
91 strcat(str, portstr);
92 return (str);
93 }
94 return (str + 1);
95 }
96#endif
97
98 default:
99 snprintf(str, sizeof(str) - 1,
100 "sock_ntop: unknown AF_xxx: %d, len %d", sa->sa_family,
101 salen);
102 str[sizeof(str) - 1]='\0';
103 return (str);
104 }
105 // return (NULL);
106}
107
108char *
109Sock_ntop(const struct sockaddr *sa, socklen_t salen)
110{
111 char *ptr;
112
113 if ( (ptr = sock_ntop(sa, salen)) == NULL)
114 perror("sock_ntop"); /* inet_ntop() sets errno */ //LCOV_EXCL_LINE
115 return(ptr);
116}
117
118int
119sock_pton(const char* cp, struct sockaddr *sa)
120{
121 const char * ip_end;
122 char * host_name = NULL;
123 const char* port=NULL;
124 if ((!cp)||(!sa)) {
125 return -1;
126 }
127
128 //skip ws
129 while ((cp)&&(isspace(*cp))) {
130 ++cp;
131 }
132
133 ip_end = cp;
134 if (*cp=='[') { //find matching bracket ']'
135 ++cp;
136 while ((*ip_end)&&(*ip_end!=']')) {
137 ++ip_end;
138 }
139
140 if (!*ip_end) {
141 return -2;
142 }
143 host_name=strndup(cp, ip_end-cp);
144 ++ip_end;
145 }
146 { //find start of port part
147 while (*ip_end) {
148 if (*ip_end==':') {
149 if (!port) {
150 port = ip_end+1;
151 } else if (host_name==NULL) { // means addr has [] block
152 port=NULL; // more than 1 ":" => assume the whole addr is IPv6 address w/o port
153 host_name=strdup(cp);
154 break;
155 }
156 }
157 ++ip_end;
158 }
159 if (!host_name) {
160 if ((*ip_end==0)&&(port!=NULL)) {
161 if (port-cp>1) { //only port entered
162 host_name=strndup(cp, port-cp-1);
163 }
164 } else {
165 host_name=strndup(cp, ip_end-cp);
166 }
167 }
168 }
169
170 // getaddrinfo for host
171 {
172 struct addrinfo hints, *servinfo, *p;
173 int rv;
174
175 memset(&hints, 0, sizeof hints);
176 hints.ai_family = AF_UNSPEC;
177 hints.ai_socktype = SOCK_DGRAM;
178 hints.ai_flags = AI_V4MAPPED;
179
180 if ((rv = getaddrinfo(host_name, port, &hints, &servinfo)) != 0) {
181 fprintf(stderr, "getaddrinfo: %s\n",
182 gai_strerrorA(rv));
183 if (host_name)
184 free (host_name);
185 return -2;
186 }
187
188 for(p = servinfo; p != NULL; p = p->ai_next) {
189 if ((p->ai_family == AF_INET)||(p->ai_family == AF_INET6)) {
190 memcpy(sa, p->ai_addr, SA_LEN(p->ai_addr));
191 if(host_name==NULL) { // getaddrinfo returns localhost ip if hostname is null
192 switch (p->ai_family) {
193 case AF_INET:
194 ((struct sockaddr_in*)sa)->sin_addr.s_addr = INADDR_ANY;
195 break;
196 case AF_INET6:
197 memset(&((struct sockaddr_in6*)sa)->sin6_addr, 0,
198 sizeof(struct sockaddr_in6));
199 break;
200 default: // Should never happen LCOV_EXCL_START
201 if (host_name)
202 free (host_name);
203 return -2;
204 } //LCOV_EXCL_STOP
205 }
206 break;
207 }
208 }
209 freeaddrinfo(servinfo);
210 }
211
212 if (host_name)
213 free (host_name);
214 return 0;
215}
216
217struct sockaddr *Sock_pton(const char* cp)
218{
219 static struct sockaddr_storage sa_s;
220 if (sock_pton(cp, (struct sockaddr *)&sa_s)==0) {
221 return (struct sockaddr *)&sa_s;
222 } else {
223 return NULL;
224 }
225}
226
227int
228sock_pton_with_prefix(const char* cp, struct sockaddr *sa, int *int_prefix)
229{
230 const char * prefix_begin = NULL;
231 char * prefix = NULL;
232
233 const char * ip_end;
234 char * host_name = NULL;
235 const char* port=NULL;
236
237 if ((!cp)||(!sa)||(!int_prefix)) {
238 return -1;
239 }
240
241 //skip ws
242 while ((cp)&&(isspace(*cp))) {
243 ++cp;
244 }
245
246 ip_end = cp;
247 if (*cp=='[') { //find matching bracket ']'
248 ++cp;
249 while ((*ip_end)&&(*ip_end!=']')) {
250 if (*ip_end == '/' ){
251 prefix_begin = ip_end+1;
252 }
253 ++ip_end;
254 }
255
256 if (!*ip_end) {
257 return -2;
258 }
259
260 if (prefix_begin){
261 host_name=strndup(cp, prefix_begin-cp-1);
262 prefix = strndup(prefix_begin, ip_end-prefix_begin);
263 if (prefix) {
264 *int_prefix = atoi(prefix);
265 free(prefix);
266 }
267 } else {
268 host_name=strndup(cp, ip_end-cp);
269 *int_prefix=128;
270 }
271 ++ip_end;
272 } else {
273 return -2;
274 }
275
276 { //find start of port part
277 while (*ip_end) {
278 if (*ip_end==':') {
279 if (!port) {
280 port = ip_end+1;
281 } else if (host_name==NULL) { // means addr has [] block
282 port=NULL; // more than 1 ":" => assume the whole addr is IPv6 address w/o port
283 host_name=strdup(cp);
284 break;
285 }
286 }
287 ++ip_end;
288 }
289 if (!host_name) {
290 if ((*ip_end==0)&&(port!=NULL)) {
291 if (port-cp>1) { //only port entered
292 host_name=strndup(cp, port-cp-1);
293 }
294 } else {
295 host_name=strndup(cp, ip_end-cp);
296 }
297 }
298 }
299
300 // getaddrinfo for host
301 {
302 struct addrinfo hints, *servinfo, *p;
303 int rv;
304
305 memset(&hints, 0, sizeof hints);
306 hints.ai_family = AF_UNSPEC;
307 hints.ai_socktype = SOCK_DGRAM;
308 hints.ai_flags = AI_V4MAPPED;
309
310 if ((rv = getaddrinfo(host_name, port, &hints, &servinfo)) != 0) {
311 fprintf(stderr, "getaddrinfo: %s\n",
312 gai_strerrorA(rv));
313 if (host_name)
314 free (host_name);
315 return -2;
316 }
317
318 for(p = servinfo; p != NULL; p = p->ai_next) {
319 if ((p->ai_family == AF_INET)||(p->ai_family == AF_INET6)) {
320 memcpy(sa, p->ai_addr, SA_LEN(p->ai_addr));
321 if(host_name==NULL) { // getaddrinfo returns localhost ip if hostname is null
322 switch (p->ai_family) {
323 case AF_INET6:
324 memset(&((struct sockaddr_in6*)sa)->sin6_addr, 0,
325 sizeof(struct sockaddr_in6));
326 break;
327 default: // Should never happen LCOV_EXCL_START
328 if (host_name)
329 free (host_name);
330 return -2;
331 } //LCOV_EXCL_STOP
332 }
333 break;
334 }
335 }
336 freeaddrinfo(servinfo);
337 }
338
339 if (host_name)
340 free (host_name);
341
342 if ((sa->sa_family==AF_INET)&&(*int_prefix > 32)) {
343
344 return -2;
345 }
346
347 if ((sa->sa_family==AF_INET6)&&(*int_prefix > 128)) {
348
349 return -2;
350 }
351
352 return 0;
353}
#define SA_LEN(addr)
Definition: pcp_socket.h:112
#define strndup
Definition: pcp_utils.h:233
#define inet_ntop
#define strdup
#define snprintf
struct sockaddr * Sock_pton(const char *cp)
Definition: sock_ntop.c:217
char * sock_ntop(const struct sockaddr *sa, socklen_t salen)
Definition: sock_ntop.c:58
int sock_pton(const char *cp, struct sockaddr *sa)
Definition: sock_ntop.c:119
char * Sock_ntop(const struct sockaddr *sa, socklen_t salen)
Definition: sock_ntop.c:109
int sock_pton_with_prefix(const char *cp, struct sockaddr *sa, int *int_prefix)
Definition: sock_ntop.c:228