1 /*
2 * Copyright (c) 2017-2018, Texas Instruments Incorporated
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
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /*****************************************************************************/
34 /* Include files */
35 /*****************************************************************************/
36
37 #include <unistd.h> /* needed? */
38 #include <string.h>
39 #include <stdlib.h>
40
41 #include <ti/net/slnetutils.h>
42 #include <ti/net/slnetif.h>
43 #include <ti/net/slneterr.h>
44
45 /*****************************************************************************/
46 /* Macro declarations */
47 /*****************************************************************************/
48
49 #define SLNETUTIL_NORMALIZE_NEEDED 0
50 #if SLNETUTIL_NORMALIZE_NEEDED
51 #define SLNETUTIL_NORMALIZE_RET_VAL(retVal,err) ((retVal < 0)?(retVal = err):(retVal))
52 #else
53 #define SLNETUTIL_NORMALIZE_RET_VAL(retVal,err)
54 #endif
55
56 /* Size needed for getaddrinfo mem allocation */
57 #define SLNETUTIL_ADDRINFO_ALLOCSZ ((sizeof(SlNetUtil_addrInfo_t)) + \
58 (sizeof(SlNetSock_AddrIn6_t)))
59
60 /* Cap number of mem allocations in case of large number of results from DNS */
61 #define SLNETUTIL_ADDRINFO_MAX_DNS_NODES 10
62
63 #define SLNETUTIL_DNSBUFSIZE ((SLNETUTIL_ADDRINFO_MAX_DNS_NODES) * \
64 (sizeof(uint32_t)))
65
66 #define LL_PREFIX 0xFE80
67
68 /*****************************************************************************/
69 /* Structure/Enum declarations */
70 /*****************************************************************************/
71
72
73 /*****************************************************************************/
74 /* Function prototypes */
75 /*****************************************************************************/
76
77 static int32_t SlNetUtil_UTOA(uint16_t value, char * string, uint16_t base);
78 static int32_t SlNetUtil_bin2StrIpV4(SlNetSock_InAddr_t *binaryAddr, char *strAddr, uint16_t strAddrLen);
79 static int32_t SlNetUtil_bin2StrIpV6(SlNetSock_In6Addr_t *binaryAddr, char *strAddr, uint16_t strAddrLen);
80 static int32_t SlNetUtil_strTok(char **string, char *returnstring, int retstringlength, const char *delimiter);
81 static int32_t SlNetUtil_str2BinIpV4(char *strAddr, SlNetSock_InAddr_t *binaryAddr);
82 static int32_t SlNetUtil_str2BinIpV6(char *strAddr, SlNetSock_In6Addr_t *binaryAddr);
83
84 /* Local SlNetUtil_getAddrInfo utility functions */
85 static SlNetUtil_addrInfo_t *setAddrInfo(uint16_t ifID, SlNetSock_Addr_t *addr,
86 int family, const char *service, const SlNetUtil_addrInfo_t *hints);
87
88 static SlNetUtil_addrInfo_t *createAddrInfo(uint16_t ifID,
89 SlNetSock_Addr_t *addr, int family, const char *service, int flags,
90 int socktype, int protocol);
91
92 static int mergeLists(SlNetUtil_addrInfo_t **curList,
93 SlNetUtil_addrInfo_t **newList);
94
95 //*****************************************************************************
96 //
97 // SlNetUtil_init - Initialize the slnetutil module
98 //
99 //*****************************************************************************
SlNetUtil_init(int32_t flags)100 int32_t SlNetUtil_init(int32_t flags)
101 {
102 return 0;
103 }
104
105
106 //*****************************************************************************
107 // SlNetUtil_gaiStrErr
108 //*****************************************************************************
109
110 /*
111 * Error codes for gai_strerror
112 * The order of this array MUST match the numbering of the SLNETUTIL_EAI_CODE
113 * defines in <ti/net/slneterr.h>
114 */
115 static const char *strErrorMsgs[] =
116 {
117 "Temporary failure in name resolution", /* SLNETUTIL_EAI_AGAIN */
118 "Bad value for ai_flags", /* SLNETUTIL_EAI_BADFLAGS */
119 "Non-recoverable failure in name resolution", /* SLNETUTIL_EAI_FAIL */
120 "ai_family not supported", /* SLNETUTIL_EAI_FAMILY */
121 "Memory allocation failure", /* SLNETUTIL_EAI_MEMORY */
122 "Node or service not known, " /* SLNETUTIL_EAI_NONAME */
123 "or both node and service are NULL",
124 "Service (port number) not supported " /* SLNETUTIL_EAI_SERVICE */
125 "for ai_socktype",
126 "ai_socktype not supported", /* SLNETUTIL_EAI_SOCKTYPE */
127 "System error", /* SLNETUTIL_EAI_SYSTEM */
128 "An argument buffer overflowed", /* SLNETUTIL_EAI_OVERFLOW */
129 "Address family for node not supported" /* SLNETUTIL_EAI_ADDRFAMILY */
130 };
131
SlNetUtil_gaiStrErr(int32_t errorCode)132 const char *SlNetUtil_gaiStrErr(int32_t errorCode)
133 {
134 /*
135 * Error codes are negative starting with -3121 so
136 * ~(errorCode - SLNETUTIL_EAI_BASE) takes the one's compliment of the code
137 * minus the base of the error codes to convert the code into a positive
138 * value that matches the StrerrorMsgs array index.
139 */
140 int msgsIndex = ~(errorCode - SLNETUTIL_EAI_BASE);
141 int msgsRange = sizeof(strErrorMsgs) / sizeof(strErrorMsgs[0]);
142
143 if ((msgsIndex < msgsRange) && (msgsIndex >= 0))
144 {
145 return strErrorMsgs[msgsIndex];
146 }
147 else
148 {
149 return "Unknown error";
150 }
151 }
152
153 //*****************************************************************************
154 //
155 // SlNetUtil_getHostByName - Obtain the IP Address of machine on network, by
156 // machine name
157 //
158 //*****************************************************************************
SlNetUtil_getHostByName(uint32_t ifBitmap,char * name,const uint16_t nameLen,uint32_t * ipAddr,uint16_t * ipAddrLen,const uint8_t family)159 int32_t SlNetUtil_getHostByName(uint32_t ifBitmap, char *name, const uint16_t nameLen, uint32_t *ipAddr, uint16_t *ipAddrLen, const uint8_t family)
160 {
161 uint16_t origIpAddrLen;
162 SlNetIf_t *netIf;
163 int32_t retVal;
164
165 /* When ifBitmap is 0, that means automatic selection of all interfaces
166 is required, enable all bits in ifBitmap */
167 if (0 == ifBitmap)
168 {
169 ifBitmap = ~ifBitmap;
170 }
171
172 /*
173 * Save original value of ipAddrLen. If DNS resolution fails, ipAddrLen
174 * will be overwritten with zero, which is problematic for next iteration
175 * of the while loop.
176 */
177 origIpAddrLen = *ipAddrLen;
178
179 /* This loop tries to run get host by name on the required interface
180 only if it in state enable and connected status
181 When multiple interfaces, in addition to the enable and connected it
182 will try to run the function on the interface from the highest
183 priority until an answer will return or until no interfaces left */
184 do
185 {
186 /* Search for the highest priority interface according to the
187 ifBitmap and the queryFlags */
188 netIf = SlNetIf_queryIf(ifBitmap, SLNETIF_QUERY_IF_STATE_BIT | SLNETIF_QUERY_IF_CONNECTION_STATUS_BIT);
189
190 /* Check if the function returned NULL or the requested interface
191 exists */
192 if ( (NULL == netIf) || ( NULL == (netIf->ifConf)->utilGetHostByName) )
193 {
194 /* Interface doesn't exists, return error code */
195 return SLNETERR_RET_CODE_INVALID_INPUT;
196 }
197 else
198 {
199 /* Disable the ifID bit from the ifBitmap after finding the netIf*/
200 ifBitmap &= ~(netIf->ifID);
201
202 /* Use SlNetUtil_inetPton to test if name is already an IP address.
203 If so, point ipAddr to the binary value of the IP and return */
204 if (SlNetUtil_inetPton(family, name, ipAddr)) {
205 /* Convert ipAddr to host byte order as getHostByName requires
206 ipAddr to be in host byte order */
207 *ipAddr = SlNetUtil_ntohl(*ipAddr);
208
209 *ipAddrLen = 1;
210 return netIf->ifID;
211 }
212
213 /* Interface exists, return interface IP address */
214 retVal = (netIf->ifConf)->utilGetHostByName(netIf->ifContext, name, nameLen, ipAddr, ipAddrLen, family);
215 SLNETUTIL_NORMALIZE_RET_VAL(retVal, SLNETUTIL_ERR_UTILGETHOSTBYNAME_FAILED);
216
217 /* Check retVal for error codes */
218 if (retVal < SLNETERR_RET_CODE_OK)
219 {
220 /*
221 * utilGetHostByName failed. Restore the size of the ipAddr
222 * array and continue to the next ifID
223 */
224 *ipAddrLen = origIpAddrLen;
225 continue;
226 }
227 else
228 {
229 /* Return success */
230 return netIf->ifID;
231 }
232 }
233 }while ( ifBitmap > 0 );
234 /* Interface doesn't exists, return error code */
235 return SLNETERR_RET_CODE_INVALID_INPUT;
236 }
237
238 //*****************************************************************************
239 // SlNetUtil_getAddrInfo
240 //*****************************************************************************
SlNetUtil_getAddrInfo(uint16_t ifID,const char * node,const char * service,const struct SlNetUtil_addrInfo_t * hints,struct SlNetUtil_addrInfo_t ** res)241 int32_t SlNetUtil_getAddrInfo(uint16_t ifID, const char *node,
242 const char *service, const struct SlNetUtil_addrInfo_t *hints,
243 struct SlNetUtil_addrInfo_t **res)
244 {
245 int i;
246 int retval = 0;
247 int resolved = 0;
248 int numNodes = 0;
249 char *buffer = NULL;
250 char *currAddr = NULL;
251 uint16_t numIpAddrs;
252 int32_t selectedIfId;
253 int32_t ipv4DnsError = 0;
254 int32_t ipv6DnsError = 0;
255
256 SlNetUtil_addrInfo_t *ai = NULL;
257 SlNetUtil_addrInfo_t *aiTmp = NULL;
258 SlNetSock_AddrIn_t sin;
259 SlNetSock_AddrIn6_t sin6;
260
261 /* check args passed in for errors */
262 if (!node && !service) {
263 /* Error: node and service args cannot both be NULL */
264 return (SLNETUTIL_EAI_NONAME);
265 }
266
267 if (!service) {
268 service = "0";
269 }
270
271 if (!res) {
272 /* Error: res cannot be NULL */
273 return (SLNETUTIL_EAI_NONAME);
274 }
275
276 if (!hints) {
277 /* User passed NULL hints. Create a hints for them with all 0 values */
278 static const SlNetUtil_addrInfo_t defHints = {
279 0, /* ai_flags */
280 SLNETSOCK_AF_UNSPEC, /* ai_family */
281 0, /* ai_socktype */
282 0, /* ai_protocol */
283 0, /* ai_addrlen */
284 NULL, /* ai_addr */
285 NULL, /* ai_canonname */
286 NULL /* ai_next */
287 };
288 hints = &defHints;
289 }
290 else {
291 /* Check the user's hints for invalid settings */
292 if (hints->ai_socktype != SLNETSOCK_SOCK_STREAM &&
293 hints->ai_socktype != SLNETSOCK_SOCK_DGRAM &&
294 hints->ai_socktype != 0) {
295 /* Error: invalid or unknown socktype */
296 return (SLNETUTIL_EAI_SOCKTYPE);
297 }
298 else if (hints->ai_protocol != SLNETSOCK_PROTO_TCP &&
299 hints->ai_protocol != SLNETSOCK_PROTO_UDP &&
300 hints->ai_protocol != 0) {
301 /* Error: invalid or unknown protocol */
302 return (SLNETUTIL_EAI_SOCKTYPE);
303 }
304 else if ((hints->ai_family != SLNETSOCK_AF_INET) &&
305 (hints->ai_family != SLNETSOCK_AF_INET6) &&
306 (hints->ai_family != SLNETSOCK_AF_UNSPEC)) {
307 /* Error: invalid or unknown family */
308 return (SLNETUTIL_EAI_FAMILY);
309 }
310 }
311
312 if (node) {
313 /*
314 * Client case. User needs an address structure to call connect() with.
315 *
316 * Determine what caller has passed to us for 'node'. Should be either:
317 * - an IPv4 address
318 * - an IPv6 address
319 * - or a hostname
320 */
321
322 /* Test if 'node' is an IPv4 address */
323 retval = SlNetUtil_inetAton(node, &(sin.sin_addr));
324 if (retval) {
325 /* Ensure address family matches */
326 if (hints->ai_family != SLNETSOCK_AF_INET &&
327 hints->ai_family != SLNETSOCK_AF_UNSPEC) {
328 return (SLNETUTIL_EAI_ADDRFAMILY);
329 }
330
331 /*
332 * Create addrinfo struct(s) containing this IPv4 address. If ai
333 * is NULL, this will be caught at end of getaddrinfo
334 *
335 * Pass zero for IF ID. This is a don't care for the case of node
336 * being set to an IPv4 address
337 */
338 ai = setAddrInfo(0, (SlNetSock_Addr_t *)&sin, SLNETSOCK_AF_INET,
339 service, hints);
340 }
341 else {
342 /* 'node' is either an IPv6 address or a hostname (or invalid) */
343
344 /* Test if 'node' is an IPv6 address */
345 retval = SlNetUtil_inetPton(SLNETSOCK_AF_INET6, node,
346 &(sin6.sin6_addr));
347 if (retval > 0) {
348 /* Ensure address family matches */
349 if (hints->ai_family != SLNETSOCK_AF_INET6 &&
350 hints->ai_family != SLNETSOCK_AF_UNSPEC) {
351 return (SLNETUTIL_EAI_ADDRFAMILY);
352 }
353
354 /*
355 * If we were given a link local address and corresponding IF,
356 * pass the IF number through. It must be used for the scope ID
357 */
358 if ((SlNetUtil_ntohs(sin6.sin6_addr._S6_un._S6_u16[0]) ==
359 LL_PREFIX) && ifID != 0) {
360 selectedIfId = ifID;
361 }
362 else {
363 /*
364 * Set scope ID to zero for these cases:
365 * - Link local addr and ifID == 0:
366 * (caller responsibe for setting scope ID)
367 *
368 * - Non-local addr with ifID == 0:
369 * - Non-local addr with ifID == 1:
370 * scope ID not used and should be set to 0
371 */
372 selectedIfId = 0;
373 }
374
375 /*
376 * Create addrinfo struct(s) containing this IPv6 address. If
377 * ai is NULL, this will be caught at end of getaddrinfo
378 */
379 ai = setAddrInfo(selectedIfId, (SlNetSock_Addr_t *)&sin6,
380 SLNETSOCK_AF_INET6, service, hints);
381 }
382 else {
383 /* Test if 'node' is a host name. Use DNS to resolve it. */
384
385 /*
386 * Per RFC 2553, if node is not a valid numeric address string
387 * and AI_NUMERICHOST is set, return error (and prevent call to
388 * DNS).
389 */
390 if (hints->ai_flags & SLNETUTIL_AI_NUMERICHOST) {
391 return (SLNETUTIL_EAI_NONAME);
392 }
393
394 buffer = malloc(SLNETUTIL_DNSBUFSIZE);
395 if (!buffer) {
396 /* Error: couldn't alloc DNS buffer */
397 return (SLNETUTIL_EAI_MEMORY);
398 }
399
400 /* IPv4 DNS lookup */
401 if (hints->ai_family == SLNETSOCK_AF_INET ||
402 hints->ai_family == SLNETSOCK_AF_UNSPEC) {
403 /*
404 * Set the size of the buffer to the number of 32-bit IPv4
405 * addresses this buffer can hold
406 */
407 numIpAddrs = SLNETUTIL_DNSBUFSIZE / sizeof(uint32_t);
408
409 selectedIfId = SlNetUtil_getHostByName(ifID, (char *)node,
410 strlen(node), (uint32_t *)buffer, &numIpAddrs,
411 SLNETSOCK_AF_INET);
412
413 if (selectedIfId > 0) {
414
415 /*
416 * Process the results returned by DNS. Upon success,
417 * numIpAddrs contains the number of IP addresses stored
418 * into the buffer
419 */
420 resolved = 1;
421 currAddr = buffer;
422 for (i = 0; i < numIpAddrs &&
423 numNodes < SLNETUTIL_ADDRINFO_MAX_DNS_NODES;
424 i++) {
425 sin.sin_addr.s_addr =
426 SlNetUtil_htonl(*((uint32_t *)currAddr));
427 /*
428 * Create addrinfo struct(s) containing this IPv4
429 * address. This can return a list with multiple
430 * nodes, depending on hints provided. Empty lists
431 * are handled before returning.
432 *
433 * Pass zero for IF ID. This is a don't care for
434 * the case of node being set to an IPv4 address.
435 */
436 aiTmp = setAddrInfo(0, (SlNetSock_Addr_t *)&sin,
437 SLNETSOCK_AF_INET, service, hints);
438
439 if (aiTmp) {
440 /*
441 * Merge the results into the main list
442 * for each loop iteration:
443 */
444 numNodes += mergeLists(&ai, &aiTmp);
445 }
446
447 /* move to the next IPv4 address */
448 currAddr += sizeof(uint32_t);
449 }
450 }
451 else {
452 /* save the IPv4 error code */
453 ipv4DnsError = selectedIfId;
454 }
455 }
456
457 /* IPv6 DNS lookup */
458 if (hints->ai_family == SLNETSOCK_AF_INET6 ||
459 hints->ai_family == SLNETSOCK_AF_UNSPEC) {
460 /*
461 * Set the size of the buffer to the number of 128-bit IPv6
462 * addresses this buffer can hold
463 */
464 numIpAddrs =
465 SLNETUTIL_DNSBUFSIZE / sizeof(SlNetSock_In6Addr_t);
466
467 selectedIfId = SlNetUtil_getHostByName(ifID, (char *)node,
468 strlen(node), (uint32_t *)buffer, &numIpAddrs,
469 SLNETSOCK_AF_INET6);
470
471 if (selectedIfId > 0) {
472
473 /*
474 * Process the results returned by DNS. Upon success,
475 * numIpAddrs contains the number of IP addresses stored
476 * into the buffer
477 */
478 resolved = 1;
479 currAddr = buffer;
480 for (i = 0; i < numIpAddrs &&
481 numNodes < SLNETUTIL_ADDRINFO_MAX_DNS_NODES;
482 i++) {
483
484 /* Copy the IPv6 address out of the buffer */
485 memcpy(&(sin6.sin6_addr), currAddr,
486 sizeof(SlNetSock_In6Addr_t));
487
488 /*
489 * Is this address non-local? If so, IF ID is a
490 * don't care
491 */
492 if (sin6.sin6_addr._S6_un._S6_u16[0] != LL_PREFIX) {
493 selectedIfId = 0;
494 }
495
496 /* Change byte ordering to net byte order */
497 sin6.sin6_addr._S6_un._S6_u16[0] = SlNetUtil_htons(
498 sin6.sin6_addr._S6_un._S6_u16[0]);
499 sin6.sin6_addr._S6_un._S6_u16[1] = SlNetUtil_htons(
500 sin6.sin6_addr._S6_un._S6_u16[1]);
501 sin6.sin6_addr._S6_un._S6_u16[2] = SlNetUtil_htons(
502 sin6.sin6_addr._S6_un._S6_u16[2]);
503 sin6.sin6_addr._S6_un._S6_u16[3] = SlNetUtil_htons(
504 sin6.sin6_addr._S6_un._S6_u16[3]);
505 sin6.sin6_addr._S6_un._S6_u16[4] = SlNetUtil_htons(
506 sin6.sin6_addr._S6_un._S6_u16[4]);
507 sin6.sin6_addr._S6_un._S6_u16[5] = SlNetUtil_htons(
508 sin6.sin6_addr._S6_un._S6_u16[5]);
509 sin6.sin6_addr._S6_un._S6_u16[6] = SlNetUtil_htons(
510 sin6.sin6_addr._S6_un._S6_u16[6]);
511 sin6.sin6_addr._S6_un._S6_u16[7] = SlNetUtil_htons(
512 sin6.sin6_addr._S6_un._S6_u16[7]);
513
514 /*
515 * Create addrinfo struct(s) containing this IPv6
516 * address. This can return a list with multiple
517 * nodes, depending on hints provided. Empty lists
518 * are handled before returning.
519 *
520 * Pass down the appropriate IF number or zero,
521 * depending on whether this address is
522 * local or not
523 */
524
525 aiTmp = setAddrInfo(selectedIfId,
526 (SlNetSock_Addr_t *)&sin6,
527 SLNETSOCK_AF_INET6, service, hints);
528
529 if (aiTmp) {
530 /*
531 * Merge the results into the main list
532 * for each loop iteration:
533 */
534 numNodes += mergeLists(&ai, &aiTmp);
535 }
536
537 /* move to the next IPv6 address */
538 currAddr += sizeof(SlNetSock_In6Addr_t);
539 }
540 }
541 else {
542 /* save the IPv6 error code */
543 ipv6DnsError = selectedIfId;
544 }
545 }
546
547 free(buffer);
548
549 if (!resolved) {
550 /*
551 * Error: couldn't resolve host name
552 * Translate the SlNetSock error code to a GAI error code.
553 * Give the IPv4 error precedence:
554 */
555 retval = (ipv4DnsError != 0) ? ipv4DnsError : ipv6DnsError;
556
557 switch (retval) {
558 case SLNETERR_NET_APP_DNS_ALLOC_ERROR:
559 retval = SLNETUTIL_EAI_MEMORY;
560 break;
561 case SLNETERR_NET_APP_DNS_INVALID_FAMILY_TYPE:
562 retval = SLNETUTIL_EAI_FAMILY;
563 break;
564 case SLNETERR_NET_APP_DNS_IPV6_REQ_BUT_IPV6_DISABLED:
565 retval = SLNETUTIL_EAI_SERVICE;
566 break;
567 case SLNETERR_NET_APP_DNS_PARAM_ERROR:
568 case SLNETERR_NET_APP_DNS_QUERY_FAILED:
569 default:
570 retval = SLNETUTIL_EAI_FAIL;
571 break;
572 }
573 return (retval);
574 }
575 }
576 }
577 }
578 else {
579 /* Server case. User needs an address structure to call bind() with. */
580 if (hints->ai_family == SLNETSOCK_AF_INET ||
581 hints->ai_family == SLNETSOCK_AF_UNSPEC) {
582 if (hints->ai_flags & SLNETUTIL_AI_PASSIVE) {
583 /* Per RFC 2553, accept connections on any IF */
584 sin.sin_addr.s_addr = SlNetUtil_htonl(SLNETSOCK_INADDR_ANY);
585 }
586 else {
587 /* Per RFC 2553, accept connections on loopback IF */
588 retval = SlNetUtil_inetPton(SLNETSOCK_AF_INET, "127.0.0.1",
589 &(sin.sin_addr.s_addr));
590 if (retval <= 0) {
591 return (SLNETUTIL_EAI_SYSTEM);
592 }
593 }
594
595 /*
596 * Create addrinfo struct(s) containing this IPv4 address. If ai
597 * is NULL, this will be caught at end of getaddrinfo
598 *
599 * Pass zero for IF ID. This is a don't care for
600 * the case of setting up a server socket.
601 */
602 ai = setAddrInfo(0, (SlNetSock_Addr_t *)&sin,
603 SLNETSOCK_AF_INET, service, hints);
604 }
605
606 if (hints->ai_family == SLNETSOCK_AF_INET6 ||
607 hints->ai_family == SLNETSOCK_AF_UNSPEC) {
608 if (hints->ai_flags & SLNETUTIL_AI_PASSIVE) {
609 /*
610 * Per RFC 2553, accept connections on any IF
611 * (The IPv6 unspecified address is all zeroes)
612 */
613 /* TODO: use in6addr_any, once available (NS-84) */
614 memset(&(sin6.sin6_addr), 0, sizeof(SlNetSock_In6Addr_t));
615 }
616 else {
617 /*
618 * Per RFC 2553, accept connections on loopback IF
619 * (The IPv6 loopback address is a 1 preceded by all zeroes)
620 */
621 /* TODO: use in6addr_loopback, once available (NS-84) */
622 sin6.sin6_addr._S6_un._S6_u32[0] = 0;
623 sin6.sin6_addr._S6_un._S6_u32[1] = 0;
624 sin6.sin6_addr._S6_un._S6_u32[2] = 0;
625 sin6.sin6_addr._S6_un._S6_u32[3] = SlNetUtil_htonl(1);
626 }
627
628 /*
629 * Create addrinfo struct(s) containing this IPv6 address. If ai
630 * is NULL, this will be caught at end of getaddrinfo
631 *
632 * Pass zero for IF ID. This is a don't care for
633 * the case of setting up a server socket.
634 */
635 aiTmp = setAddrInfo(0, (SlNetSock_Addr_t *)&sin6,
636 SLNETSOCK_AF_INET6, service, hints);
637
638 if (aiTmp) {
639 /*
640 * The current list (ai) may not be empty. Merge the new
641 * results (aiTmp) into the existing ai to handle this case.
642 */
643 mergeLists(&ai, &aiTmp);
644 }
645 }
646 }
647
648 /* Give user our allocated and initialized addrinfo struct(s) */
649 *res = ai;
650
651 if (!ai) {
652 /* Our list is empty - memory allocations failed */
653 return (SLNETUTIL_EAI_MEMORY);
654 }
655
656 return (0);
657 }
658
659 //*****************************************************************************
660 // SlNetUtil_freeAddrInfo
661 //*****************************************************************************
SlNetUtil_freeAddrInfo(struct SlNetUtil_addrInfo_t * res)662 void SlNetUtil_freeAddrInfo(struct SlNetUtil_addrInfo_t *res)
663 {
664 SlNetUtil_addrInfo_t *aiTmp;
665
666 /* Delete all nodes in linked list */
667 while (res) {
668 aiTmp = res->ai_next;
669 free((void *)res);
670 res = aiTmp;
671 }
672 }
673
674 //*****************************************************************************
675 // setAddrInfo
676 // Intermediate step to handle permutations of ai_socktype and ai_protocol
677 // hints fields, passed by the user. If both socktype and protocol are 0, must
678 // create a results struct for each socktype and protocol.
679 // Returns an empty list (NULL) or a list with one or more nodes.
680 //*****************************************************************************
setAddrInfo(uint16_t ifID,SlNetSock_Addr_t * addr,int family,const char * service,const SlNetUtil_addrInfo_t * hints)681 static SlNetUtil_addrInfo_t *setAddrInfo(uint16_t ifID, SlNetSock_Addr_t *addr,
682 int family, const char *service,
683 const SlNetUtil_addrInfo_t *hints)
684 {
685 SlNetUtil_addrInfo_t *ai = NULL;
686 SlNetUtil_addrInfo_t *aiTmp = NULL;
687
688 if ((hints->ai_socktype == 0 && hints->ai_protocol == 0) ||
689 (hints->ai_socktype == 0 && hints->ai_protocol == SLNETSOCK_PROTO_UDP)
690 || (hints->ai_socktype == SLNETSOCK_SOCK_DGRAM &&
691 hints->ai_protocol == 0) || (hints->ai_socktype == SLNETSOCK_SOCK_DGRAM
692 && hints->ai_protocol == SLNETSOCK_PROTO_UDP)) {
693
694 ai = createAddrInfo(ifID, addr, family, service, hints->ai_flags,
695 SLNETSOCK_SOCK_DGRAM, SLNETSOCK_PROTO_UDP);
696 }
697
698 if ((hints->ai_socktype == 0 && hints->ai_protocol == 0) ||
699 (hints->ai_socktype == 0 && hints->ai_protocol == SLNETSOCK_PROTO_TCP)
700 || (hints->ai_socktype == SLNETSOCK_SOCK_STREAM &&
701 hints->ai_protocol == 0) || (hints->ai_socktype == SLNETSOCK_SOCK_STREAM
702 && hints->ai_protocol == SLNETSOCK_PROTO_TCP)) {
703
704 aiTmp = createAddrInfo(ifID, addr, family, service, hints->ai_flags,
705 SLNETSOCK_SOCK_STREAM, SLNETSOCK_PROTO_TCP);
706
707 if (aiTmp) {
708 /* Insert into front of list (assume UDP node was added above) */
709 aiTmp->ai_next = ai;
710 ai = aiTmp;
711 }
712 }
713
714 return (ai);
715 }
716
717 //*****************************************************************************
718 // createAddrInfo
719 // Create new address info structure. Returns a single node.
720 //*****************************************************************************
createAddrInfo(uint16_t ifID,SlNetSock_Addr_t * addr,int family,const char * service,int flags,int socktype,int protocol)721 static SlNetUtil_addrInfo_t *createAddrInfo(uint16_t ifID,
722 SlNetSock_Addr_t *addr, int family, const char *service, int flags,
723 int socktype, int protocol)
724 {
725 SlNetUtil_addrInfo_t *ai = NULL;
726
727 /*
728 * Allocate memory for the addrinfo struct, which we must fill out and
729 * return to the caller. This struct also has a pointer to a generic socket
730 * address struct, which will point to either struct sockaddr_in, or
731 * struct sockaddr_in6, depending. Need to allocate enough space to hold
732 * that struct, too.
733 */
734 ai = (SlNetUtil_addrInfo_t *)calloc(1, SLNETUTIL_ADDRINFO_ALLOCSZ);
735 if (!ai) {
736 /* Error: memory allocation failed */
737 return (NULL);
738 }
739
740 ai->ai_flags = flags;
741 ai->ai_socktype = socktype;
742 ai->ai_protocol = protocol;
743 ai->ai_canonname = NULL;
744 ai->ai_next = NULL;
745
746 /* Store socket addr struct after the addrinfo struct in our memory block */
747 ai->ai_addr = (SlNetSock_Addr_t *)(ai + 1);
748
749 if (family == SLNETSOCK_AF_INET) {
750 /* Fill in structure for IPv4 */
751 ai->ai_family = SLNETSOCK_AF_INET;
752 ai->ai_addrlen = sizeof(SlNetSock_AddrIn_t);
753
754 /* Write values to addrinfo's socket struct as an sockaddr_in struct */
755 ((SlNetSock_AddrIn_t *)ai->ai_addr)->sin_family = SLNETSOCK_AF_INET;
756
757 ((SlNetSock_AddrIn_t *)ai->ai_addr)->sin_port =
758 SlNetUtil_htons(atoi(service));
759
760 ((SlNetSock_AddrIn_t *)ai->ai_addr)->sin_addr =
761 ((SlNetSock_AddrIn_t *)addr)->sin_addr;
762 }
763 else {
764 /* Fill in structure for IPv6 */
765 ai->ai_family = SLNETSOCK_AF_INET6;
766 ai->ai_addrlen = sizeof(SlNetSock_AddrIn6_t);
767
768 /* Write values to addrinfo's socket struct as an sockaddr_in6 struct */
769 ((SlNetSock_AddrIn6_t *)ai->ai_addr)->sin6_family = SLNETSOCK_AF_INET6;
770
771 ((SlNetSock_AddrIn6_t *)ai->ai_addr)->sin6_port =
772 SlNetUtil_htons(atoi(service));
773
774 memcpy(&(((SlNetSock_AddrIn6_t *)ai->ai_addr)->sin6_addr),
775 &(((SlNetSock_AddrIn6_t *)addr)->sin6_addr),
776 sizeof(SlNetSock_In6Addr_t));
777
778 /* Scope ID should have been determined correctly by the caller */
779 ((SlNetSock_AddrIn6_t *)ai->ai_addr)->sin6_scope_id = (uint32_t)ifID;
780 }
781
782 return (ai);
783 }
784
785 //*****************************************************************************
786 // mergeLists
787 // Combines an existing linked list of addrinfo structs (curList) and a newly
788 // obtained list (newList) into a single list. If the existing list is empty,
789 // it will be initialized to the new list. If both lists are empty, no action
790 // is taken.
791 //*****************************************************************************
mergeLists(SlNetUtil_addrInfo_t ** curList,SlNetUtil_addrInfo_t ** newList)792 static int mergeLists(SlNetUtil_addrInfo_t **curList,
793 SlNetUtil_addrInfo_t **newList)
794 {
795 int numNodes = 0;
796 SlNetUtil_addrInfo_t *tail = NULL;
797
798 /* Check params */
799 if (!curList || !newList || !(*newList)) {
800 return (numNodes);
801 }
802
803 /* Update node count & find end of new list */
804 for (tail = *newList; tail != NULL;) {
805 numNodes++;
806 if (tail->ai_next != NULL) {
807 /* Not the tail, keep traversing */
808 tail = tail->ai_next;
809 }
810 else {
811 /* Tail found, quit loop */
812 break;
813 }
814 }
815
816 /* Append current list to end of new list */
817 tail->ai_next = *curList;
818 *curList = *newList;
819
820 return (numNodes);
821 }
822
823 //*****************************************************************************
824 //
825 // SlNetUtil_htonl - Reorder the bytes of a 32-bit unsigned value from host
826 // order to network order(Big endian)
827 //
828 //*****************************************************************************
SlNetUtil_htonl(uint32_t val)829 uint32_t SlNetUtil_htonl(uint32_t val)
830 {
831 uint32_t i = 1;
832 int8_t *p = (int8_t *)&i;
833
834 /* When the LSB of i stored in the smallest address of *p */
835 if (p[0] == 1) /* little endian */
836 {
837 /* Swap the places of the value */
838 p[0] = ((int8_t *)&val)[3];
839 p[1] = ((int8_t *)&val)[2];
840 p[2] = ((int8_t *)&val)[1];
841 p[3] = ((int8_t *)&val)[0];
842
843 /* return the reordered bytes */
844 return i;
845 }
846 else /* big endian */
847 {
848 /* return the input without any changes */
849 return val;
850 }
851 }
852
853
854 //*****************************************************************************
855 //
856 // SlNetUtil_ntohl - Reorder the bytes of a 32-bit unsigned value from network
857 // order(Big endian) to host order
858 //
859 //*****************************************************************************
SlNetUtil_ntohl(uint32_t val)860 uint32_t SlNetUtil_ntohl(uint32_t val)
861 {
862 /* return the reordered bytes */
863 return SlNetUtil_htonl(val);
864 }
865
866
867 //*****************************************************************************
868 //
869 // SlNetUtil_htons - Reorder the bytes of a 16-bit unsigned value from host
870 // order to network order(Big endian)
871 //
872 //*****************************************************************************
SlNetUtil_htons(uint16_t val)873 uint16_t SlNetUtil_htons(uint16_t val)
874 {
875 int16_t i = 1;
876 int8_t *p = (int8_t *)&i;
877
878 /* When the LSB of i stored in the smallest address of *p */
879 if (p[0] == 1) /* little endian */
880 {
881 /* Swap the places of the value */
882 p[0] = ((int8_t *)&val)[1];
883 p[1] = ((int8_t *)&val)[0];
884
885 /* return the reordered bytes */
886 return (uint16_t)i;
887 }
888 else /* big endian */
889 {
890 /* return the input without any changes */
891 return val;
892 }
893 }
894
895
896 //*****************************************************************************
897 //
898 // SlNetUtil_ntohs - Reorder the bytes of a 16-bit unsigned value from network
899 // order(Big endian) to host order
900 //
901 //*****************************************************************************
SlNetUtil_ntohs(uint16_t val)902 uint16_t SlNetUtil_ntohs(uint16_t val)
903 {
904 /* return the reordered bytes */
905 return SlNetUtil_htons(val);
906 }
907
908 //*****************************************************************************
909 //
910 // SlNetUtil_UTOA - converts unsigned 16 bits binary number to string with
911 // maximum of 4 characters + 1 NULL terminated
912 //
913 //*****************************************************************************
SlNetUtil_UTOA(uint16_t value,char * string,uint16_t base)914 static int32_t SlNetUtil_UTOA(uint16_t value, char * string, uint16_t base)
915 {
916 uint16_t Index = 4;
917 char tempString[5] = { 0 };
918 char * ptempString = tempString;
919 char * pString = string;
920
921 /* Check if the inputs valid */
922 if ( (NULL == string) || ((base < 2 ) && (base > 16 )) )
923 {
924 return SLNETERR_RET_CODE_INVALID_INPUT;
925 }
926
927 /* If value is zero, that means that the returned string needs to be zero*/
928 if (0 == value)
929 {
930 *ptempString = '0';
931 ptempString++;
932 Index--;
933 }
934
935 /* Run until all value digits are 0 or until Index get to 0 */
936 for (; (value && (Index > 0)); Index--, value /= base)
937 {
938 *ptempString = "0123456789abcdef"[value % base];
939 ptempString++;
940 }
941 /* Invalid value input */
942 if (0 != value)
943 {
944 return SLNETERR_RET_CODE_INVALID_INPUT;
945 }
946
947 /* Reverse the string and initialize temporary array */
948 while (Index < 4)
949 {
950 *(pString++) = *(--ptempString);
951 *ptempString = '\0';
952 *pString = '\0';
953 Index++;
954 }
955
956 return 0;
957 }
958
959 //*****************************************************************************
960 //
961 // SlNetUtil_bin2StrIpV4 - converts IPv4 address in binary representation
962 // (network byte order) to IP address in string
963 // representation
964 //
965 //*****************************************************************************
SlNetUtil_bin2StrIpV4(SlNetSock_InAddr_t * binaryAddr,char * strAddr,uint16_t strAddrLen)966 static int32_t SlNetUtil_bin2StrIpV4(SlNetSock_InAddr_t *binaryAddr, char *strAddr, uint16_t strAddrLen)
967 {
968 uint8_t tempOctet;
969 uint32_t tempBinAddr;
970 int32_t octetIndex = 0;
971 char tempStrOctet[4] = { 0 };
972
973 /* Check if the strAddr buffer is at least in the minimum required size */
974 if (strAddrLen < SLNETSOCK_INET_ADDRSTRLEN)
975 {
976 /* Return error code */
977 return SLNETERR_RET_CODE_INVALID_INPUT;
978 }
979
980 /* initialize strAddr to an empty string (so we can strcat() later) */
981 strAddr[0] = '\0';
982
983 /* Copy the address value for further use */
984 memcpy(&tempBinAddr, binaryAddr, sizeof(SlNetSock_InAddr_t));
985
986 /* Run over all octets (in network byte order), starting with the
987 most significant octet and ending with the least significant octet */
988 while ( octetIndex <= 3 )
989 {
990 /* Save octet on tempOctet for further usage.
991 When converting from binary representation to string
992 representation, the MSO of the binary number is the first char
993 of the string, so it needs to copied to the first location of
994 the array */
995 tempOctet = ((int8_t *)&tempBinAddr)[octetIndex];
996
997 /* Initialize the octet for validation after copying the value */
998 ((int8_t *)&tempBinAddr)[octetIndex] = 0;
999
1000 /* Convert tempOctet to string */
1001 SlNetUtil_UTOA(tempOctet, tempStrOctet, 10);
1002
1003 /* Appends the tempStrOctet to strAddr */
1004 strcat(strAddr, tempStrOctet);
1005
1006 /* Appends the "." to strAddr for the first 3 octets */
1007 if ( octetIndex < 3)
1008 {
1009 strcat(strAddr, ".");
1010 }
1011
1012 /* Move to the next octet */
1013 octetIndex ++;
1014
1015 }
1016
1017 /* Check if the address had only 4 octets, this was done by initializing
1018 each octet that was copied and than checking if the number equal to 0 */
1019 if ( 0 == tempBinAddr )
1020 {
1021 /* Return success */
1022 return SLNETERR_RET_CODE_OK;
1023 }
1024 else
1025 {
1026 /* Return error code */
1027 return SLNETERR_RET_CODE_INVALID_INPUT;
1028 }
1029 }
1030
1031
1032 //*****************************************************************************
1033 //
1034 // SlNetUtil_bin2StrIpV6 - converts IPv6 address in binary representation to
1035 // IP address in string representation
1036 //
1037 //*****************************************************************************
SlNetUtil_bin2StrIpV6(SlNetSock_In6Addr_t * binaryAddr,char * strAddr,uint16_t strAddrLen)1038 static int32_t SlNetUtil_bin2StrIpV6(SlNetSock_In6Addr_t *binaryAddr, char *strAddr, uint16_t strAddrLen)
1039 {
1040 uint16_t tempHextet;
1041 int32_t hextetIndex = 0;
1042 uint8_t tempBinAddr[16] = { 0 };
1043 char tempStrHextet[5] = { 0 };
1044
1045 /* Check if the strAddr buffer is at least in the minimum required size */
1046 if (strAddrLen < SLNETSOCK_INET6_ADDRSTRLEN)
1047 {
1048 /* Return error code */
1049 return SLNETERR_RET_CODE_INVALID_INPUT;
1050 }
1051
1052 /* initialize strAddr to an empty string (so we can strcat() later) */
1053 strAddr[0] = '\0';
1054
1055 /* Copy the address value for further use */
1056 memcpy(tempBinAddr, binaryAddr, sizeof(SlNetSock_In6Addr_t));
1057
1058 /* Run over all octets, from the latest hextet (the most significant
1059 hextet) until the first one (the least significant hextet) */
1060 while (hextetIndex < 8)
1061 {
1062 /* Save hextet on tempHextet for further usage.
1063 When converting from binary representation to string
1064 representation, the most significant hextet of the binary number
1065 is the first char of the string, so it needs to copied to the
1066 first location of the array */
1067 tempHextet = (tempBinAddr[hextetIndex * 2] << 8) |
1068 (tempBinAddr[(hextetIndex * 2) + 1]);
1069
1070 /* Convert tempHextet to string */
1071 SlNetUtil_UTOA(tempHextet, tempStrHextet, 16);
1072
1073 /* Appends the tempStrHextet to strAddr */
1074 strcat(strAddr, tempStrHextet);
1075
1076 /* Appends the ":" after each hextet (without the last one) */
1077 if (hextetIndex < 7)
1078 {
1079 strcat(strAddr, ":");
1080 }
1081
1082 /* Move to the next hextet */
1083 hextetIndex++;
1084
1085 }
1086
1087 /* Return success */
1088 return SLNETERR_RET_CODE_OK;
1089 }
1090
1091
1092 //*****************************************************************************
1093 //
1094 // SlNetUtil_inetNtop - converts IP address in binary representation to IP
1095 // address in string representation
1096 //
1097 //*****************************************************************************
SlNetUtil_inetNtop(int16_t addrFamily,const void * binaryAddr,char * strAddr,SlNetSocklen_t strAddrLen)1098 const char *SlNetUtil_inetNtop(int16_t addrFamily, const void *binaryAddr, char *strAddr, SlNetSocklen_t strAddrLen)
1099 {
1100 int32_t retVal;
1101
1102 /* Switch according to the address family */
1103 switch(addrFamily)
1104 {
1105 case SLNETSOCK_AF_INET:
1106 /* Convert from IPv4 string to numeric/binary representation */
1107 retVal = SlNetUtil_bin2StrIpV4((SlNetSock_InAddr_t *)binaryAddr, strAddr, strAddrLen);
1108
1109 break;
1110 case SLNETSOCK_AF_INET6:
1111 /* Convert from IPv6 string to numeric/binary representation */
1112 retVal = SlNetUtil_bin2StrIpV6((SlNetSock_In6Addr_t *)binaryAddr, strAddr, strAddrLen);
1113
1114 break;
1115 default:
1116 /* wrong address family - function error, return NULL error */
1117 return NULL;
1118 }
1119
1120 /* Check if conversion was successful */
1121 if (retVal != SLNETERR_RET_CODE_OK)
1122 {
1123 /* Conversion failed, return NULL as error code */
1124 return NULL;
1125 }
1126 /* Conversion success - return strAddr for success */
1127 return strAddr;
1128 }
1129
1130 //*****************************************************************************
1131 //
1132 // SlNetUtil_strTok - Split a valid ipv4 string up into tokens
1133 //
1134 //*****************************************************************************
SlNetUtil_strTok(char ** string,char * returnstring,int retstringlength,const char * delimiter)1135 static int32_t SlNetUtil_strTok(char **string, char *returnstring, int retstringlength, const char *delimiter)
1136 {
1137 char * retStr;
1138 int count = 0;
1139
1140 retStr = returnstring;
1141
1142 while ( (**string !='\0') && (**string != *delimiter) &&
1143 (count != (retstringlength-1)))
1144 {
1145 *retStr = **string;
1146 retStr++;
1147 (*string)++;
1148 count++;
1149 }
1150 /* string portion has to either end with delimiter or null char to be an
1151 ipv4 string */
1152 if (**string !='\0' && **string != *delimiter)
1153 {
1154 return SLNETERR_RET_CODE_INVALID_INPUT;
1155 }
1156 /* skip delimiter chars */
1157 if (**string == *delimiter)
1158 {
1159 (*string)++;
1160 }
1161 *retStr = '\0';
1162
1163 return SLNETERR_RET_CODE_OK;
1164 }
1165
1166 //*****************************************************************************
1167 //
1168 // SlNetUtil_str2BinIpV4 - converts IPv4 address in string representation to
1169 // IP address in binary representation
1170 //
1171 //*****************************************************************************
SlNetUtil_str2BinIpV4(char * strAddr,SlNetSock_InAddr_t * binaryAddr)1172 static int32_t SlNetUtil_str2BinIpV4(char *strAddr, SlNetSock_InAddr_t *binaryAddr)
1173 {
1174 uint32_t decNumber;
1175 char token[4];
1176 char *end;
1177 int32_t retVal;
1178 int32_t ipOctet = 0;
1179 uint32_t ipv4Address = 0;
1180 char *modifiedStr = strAddr;
1181
1182 /* split strAddr into tokens separated by "." */
1183 retVal = SlNetUtil_strTok(&modifiedStr, token, 4, ".");
1184 if (SLNETERR_RET_CODE_OK != retVal)
1185 {
1186 return retVal;
1187 }
1188
1189 /* run 4 times as IPv4 contain of four octets and separated by periods */
1190 while(ipOctet < 4)
1191 {
1192 /* Parses the token strAddr, interpreting its content as an integral
1193 number of the specified base 10 */
1194 decNumber = (int)strtoul(token, &end, 10);
1195
1196 /* Check if the octet holds valid number between the range 0-255.
1197 end points the end of the numeric portion of the input string
1198 for strtoul, so if end == token that means no conversion has
1199 occured as there was no numeric portion detected */
1200 if (decNumber < 256 && end != token)
1201 {
1202 /* manually place each byte in network order */
1203 ((int8_t *)&ipv4Address)[ipOctet] = (uint8_t)decNumber;
1204
1205 /* split strAddr into tokens separated by "." */
1206 SlNetUtil_strTok(&modifiedStr, token, 4, ".");
1207 ipOctet++;
1208 }
1209 else
1210 {
1211 return SLNETERR_RET_CODE_INVALID_INPUT;
1212 }
1213 }
1214
1215 /* Copy the temporary variable to the input variable */
1216 memcpy(binaryAddr, &ipv4Address, sizeof(SlNetSock_InAddr_t));
1217
1218 return SLNETERR_RET_CODE_OK;
1219 }
1220
1221
1222 //*****************************************************************************
1223 //
1224 // SlNetUtil_str2BinIpV6 - converts IPv6 address in string representation to
1225 // IP address in binary representation
1226 //
1227 //*****************************************************************************
SlNetUtil_str2BinIpV6(char * strAddr,SlNetSock_In6Addr_t * binaryAddr)1228 static int32_t SlNetUtil_str2BinIpV6(char *strAddr, SlNetSock_In6Addr_t *binaryAddr)
1229 {
1230
1231 int32_t octetIndex = 0;
1232 int32_t octetTailIndex;
1233 uint8_t *pLocalStr;
1234 uint8_t tmp[16];
1235 int32_t zeroCompressPos = -1;
1236 uint16_t value = 0;
1237 uint8_t asciiCharacter = 0;
1238
1239 /* Copy the first address of the string */
1240 pLocalStr = (uint8_t *)strAddr;
1241
1242 /* Initialize tmp parameter */
1243 memset(tmp, 0, sizeof(tmp));
1244
1245 /* Check if the IP starts with "::" */
1246 if(*pLocalStr==':')
1247 {
1248 /* If the IP starts with ":", check if it doesn't have the second ":"
1249 If so, return an error */
1250 if(*++pLocalStr!=':')
1251 {
1252 return SLNETERR_RET_CODE_INVALID_INPUT;
1253 }
1254 }
1255
1256 /* run over the remaining two octets */
1257 while(*pLocalStr && (octetIndex < 16))
1258 {
1259 /* Check if the ASCII character is a number between "0" to "9" */
1260 if(*pLocalStr >= '0' && *pLocalStr <= '9')
1261 {
1262 /* Each ASCII character can be max 4 bits, shift the number
1263 4 bits and copy the new converted number */
1264 value = (value << 4) | (*pLocalStr - '0');
1265
1266 /* Set the flag for ASCII character */
1267 asciiCharacter = 1;
1268 }
1269 /* Check if the ASCII character is a hex character between "a" to "f"*/
1270 else if(*pLocalStr >= 'a' && *pLocalStr <= 'f')
1271 {
1272 /* Each ASCII character can be max 4 bits, shift the number
1273 4 bits and copy the new converted number */
1274 value = (value << 4) | ((*pLocalStr - 'a') + 10);
1275
1276 /* Set the flag for ASCII character */
1277 asciiCharacter = 1;
1278 }
1279 /* Check if the ASCII character is a hex character between "A" to "F"*/
1280 else if(*pLocalStr >= 'A' && *pLocalStr <= 'F')
1281 {
1282 /* Each ASCII character can be max 4 bits, shift the number
1283 4 bits and copy the new converted number */
1284 value = (value << 4) | ((*pLocalStr - 'A') + 10);
1285
1286 /* Set the flag for ASCII character */
1287 asciiCharacter = 1;
1288 }
1289 /* Check if the hextet (two octets) finished with ":" and still a
1290 part of the IP */
1291 else if((*pLocalStr == ':') && (octetIndex < 14))
1292 {
1293 /* Check if the hextet contain ASCII character */
1294 if(asciiCharacter)
1295 {
1296 /* ASCII character exists, store the converted number in tmp
1297 and reset the value and ascii character parameters */
1298 tmp[octetIndex++] = (value >> 8) & 0xFF;
1299 tmp[octetIndex++] = (value) & 0xFF;
1300 asciiCharacter = 0;
1301 value = 0;
1302 }
1303 else
1304 {
1305 /* ASCII character doesn't exists, compressed hextet found */
1306 if(zeroCompressPos < 0)
1307 {
1308 /* first compressed hextet found, sore the octet Index */
1309 zeroCompressPos = octetIndex;
1310 }
1311 else
1312 {
1313 /* Second compressed hextet found, return error code */
1314 return SLNETERR_RET_CODE_INVALID_INPUT;
1315 }
1316 }
1317 }
1318 /* None of the valid characters have matched so this is not an ipv6
1319 address */
1320 else
1321 {
1322 return SLNETERR_RET_CODE_INVALID_INPUT;
1323 }
1324 /* Continue to the next ASCII character */
1325 pLocalStr++;
1326 }
1327
1328 /* if more than 15 octets found, return error code */
1329 if(octetIndex > 15)
1330 {
1331 return SLNETERR_RET_CODE_INVALID_INPUT;
1332 }
1333 /* if less than 14 octets found, and without any compress hextet,
1334 return error code */
1335 else if(asciiCharacter && (zeroCompressPos < 0) && (octetIndex < 14))
1336 {
1337 return SLNETERR_RET_CODE_INVALID_INPUT;
1338 }
1339 /* if all octets found, but still found compressed hextet,
1340 return error code */
1341 else if((zeroCompressPos >= 0) && octetIndex >= 14)
1342 {
1343 return SLNETERR_RET_CODE_INVALID_INPUT;
1344 }
1345
1346 /* copy the last available hextet to the tmp array */
1347 if((asciiCharacter) && (octetIndex <= 14))
1348 {
1349 /* Store the converted number in tmp and reset the value and
1350 ascii character parameters */
1351 tmp[octetIndex++] = (value >> 8) & 0xFF;
1352 tmp[octetIndex++] = (value) & 0xFF;
1353 asciiCharacter = 0;
1354 value = 0;
1355 }
1356
1357 /* compressed position found, add zeros in the compressed sections */
1358 if(zeroCompressPos >= 0)
1359 {
1360 /* compressed position found, add zeros in the compressed sections */
1361 octetIndex--;
1362 octetTailIndex = 15;
1363 /* Move the converted octets from the position they are located on
1364 to the end of the array and add zero instead */
1365 while(octetIndex >= zeroCompressPos)
1366 {
1367 /* Check if the indexes are still in range */
1368 if ((octetTailIndex >= 0) && (octetIndex >= 0))
1369 {
1370 /* Move all the octets after the zero compress position to
1371 the end of the array */
1372 tmp[octetTailIndex] = tmp[octetIndex];
1373 tmp[octetIndex] = 0;
1374 octetTailIndex--;
1375 octetIndex--;
1376 }
1377 }
1378 }
1379
1380 /* Copy the temporary variable to the input variable */
1381 memcpy(binaryAddr, tmp, sizeof(tmp));
1382
1383 return SLNETERR_RET_CODE_OK;
1384
1385 }
1386
1387 //*****************************************************************************
1388 //
1389 // SlNetUtil_inetAton - Converts a string to a network address structure
1390 //
1391 //*****************************************************************************
SlNetUtil_inetAton(const char * str,SlNetSock_InAddr_t * addr)1392 int SlNetUtil_inetAton(const char *str, SlNetSock_InAddr_t *addr)
1393 {
1394 uint32_t val[4];
1395 uint32_t base;
1396 int sect;
1397 char c;
1398
1399 sect = -1;
1400 while (*str) {
1401 /* New section */
1402 sect++;
1403
1404 /* Get the base for this number */
1405 base = 10;
1406 if (*str == '0')
1407 {
1408 if (*(str + 1) == 'x' || *(str + 1) == 'X') {
1409 base = 16;
1410 str += 2;
1411 }
1412 else {
1413 base = 8;
1414 str++;
1415 }
1416 }
1417
1418 /* Now decode this number */
1419 val[sect] = 0;
1420 for (;;) {
1421 c = *str++;
1422
1423 if ((c >= '0' && c <= '9')) {
1424 val[sect] = (val[sect] * base) + (c - '0');
1425 }
1426 else if (base == 16 && (c >= 'A' && c <= 'F')) {
1427 val[sect] = (val[sect] * 16) + (c - 'A') + 10;
1428 }
1429 else if (base == 16 && (c >= 'a' && c <= 'f')) {
1430 val[sect] = (val[sect] * 16) + (c - 'a') + 10;
1431 }
1432 else if (c == '.') {
1433 /* validate value */
1434 if(val[sect] > 255) {
1435 return (0);
1436 }
1437
1438 /*
1439 * Once we have four sections, quit.
1440 * We want to accept: "1.2.3.4.in-addr.arpa"
1441 */
1442 if (sect == 3) {
1443 goto done;
1444 }
1445
1446 /* Break this section */
1447 break;
1448 }
1449 else if (!c) {
1450 goto done;
1451 }
1452 else if (c != ' ') {
1453 return (0);
1454 }
1455 }
1456 }
1457
1458 done:
1459 /* What we do changes based on the number of sections */
1460 switch (sect) {
1461 case 0:
1462 addr->s_addr = val[0];
1463 break;
1464 case 1:
1465 if (val[1] > 0xffffff) {
1466 return (0);
1467 }
1468 addr->s_addr = val[0] << 24;
1469 addr->s_addr += val[1];
1470 break;
1471 case 2:
1472 if (val[2] > 0xffff) {
1473 return (0);
1474 }
1475 addr->s_addr = val[0] << 24;
1476 addr->s_addr += (val[1] << 16);
1477 addr->s_addr += val[2];
1478 break;
1479 case 3:
1480 if (val[3] > 0xff) {
1481 return (0);
1482 }
1483 addr->s_addr = val[0] << 24;
1484 addr->s_addr += (val[1] << 16);
1485 addr->s_addr += (val[2] << 8);
1486 addr->s_addr += val[3];
1487 break;
1488 default:
1489 return (0);
1490 }
1491
1492 addr->s_addr = SlNetUtil_htonl(addr->s_addr);
1493 return (1);
1494 }
1495
1496 //*****************************************************************************
1497 //
1498 // SlNetUtil_inetPton - converts IP address in string representation to IP
1499 // address in binary representation
1500 //
1501 //*****************************************************************************
SlNetUtil_inetPton(int16_t addrFamily,const char * strAddr,void * binaryAddr)1502 int32_t SlNetUtil_inetPton(int16_t addrFamily, const char *strAddr, void *binaryAddr)
1503 {
1504 int32_t retVal;
1505
1506 /* Switch according to the address family */
1507 switch(addrFamily)
1508 {
1509 case SLNETSOCK_AF_INET:
1510 /* Convert from IPv4 string to numeric/binary representation */
1511 retVal = SlNetUtil_str2BinIpV4((char *)strAddr, (SlNetSock_InAddr_t *)binaryAddr);
1512 break;
1513
1514 case SLNETSOCK_AF_INET6:
1515 /* Convert from IPv6 string to numeric/binary representation */
1516 retVal = SlNetUtil_str2BinIpV6((char *)strAddr, (SlNetSock_In6Addr_t *)binaryAddr);
1517 break;
1518
1519 default:
1520 /* wrong address family - function error, return -1 error */
1521 return -1;
1522 }
1523
1524 /* Check if conversion was successful */
1525 if (retVal != SLNETERR_RET_CODE_OK)
1526 {
1527 /* Conversion failed, that means the input wasn't a
1528 valid IP address, return 0 as error code */
1529 return 0;
1530 }
1531 /* Conversion success - return 1 for success */
1532 return 1;
1533 }
1534