1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/* Copyright 2013 The Chromium Authors. All rights reserved. 2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be 3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * found in the LICENSE file. */ 4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "nacl_io/ossocket.h" 6c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) && !defined(__BIONIC__) 7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <ctype.h> 9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <errno.h> 10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <stdlib.h> 11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <string.h> 12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "sdk_util/macros.h" 14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)enum { 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kIpv4AddressSize = sizeof(in_addr_t), 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kIpv6AddressSize = sizeof(struct in6_addr), 18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/* Helper function for inet_pton() for IPv4 addresses. */ 21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)static int inet_pton_v4(const char* src, void* dst) { 22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const char* pos = src; 23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) uint8_t result[kIpv4AddressSize] = {0}; 24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int i; 26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for (i = 0; i < kIpv4AddressSize; ++i) { 27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) /* strtol() won't treat whitespace characters in the beginning as an error, 28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * so check to ensure this is started with digit before passing to strtol(). 29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) */ 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (isspace((int)(*pos))) 31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 0; 32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) char* end_pos; 33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) unsigned long value = strtoul(pos, &end_pos, 10); 34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (value > 255 || pos == end_pos) 35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 0; 36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) result[i] = (unsigned char)value; 37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) pos = end_pos; 38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (i < (kIpv4AddressSize - 1)) { 40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (*pos != '.') 41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 0; 42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ++pos; 43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (*pos != '\0') 46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 0; 47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) memcpy(dst, result, sizeof(result)); 48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 1; 49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/* Helper function for inet_pton() for IPv6 addresses. */ 52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)int inet_pton_v6(const char* src, void* dst) { 53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) /* strtol() skips 0x in from of a number, while it's not allowed in IPv6 54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * addresses. Check that there is no 'x' in the string. */ 55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const char* pos = src; 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) while (*pos != '\0') { 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (*pos == 'x') 58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 0; 59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) pos++; 60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) pos = src; 62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) uint8_t result[kIpv6AddressSize]; 64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) memset(&result, 0, sizeof(result)); 65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int double_colon_pos = -1; 66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int result_pos = 0; 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (*pos == ':') { 69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (*(pos + 1) != ':') 70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 0; 71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) pos += 2; 72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) double_colon_pos = 0; 73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) while (*pos != '\0') { 76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) /* strtol() won't treat whitespace characters in the beginning as an error, 77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * so check to ensure this is started with digit before passing to strtol(). 78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) */ 79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (isspace((int)(*pos))) 80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 0; 81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) char* end_pos; 82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) unsigned long word = strtoul(pos, &end_pos, 16); 83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (word > 0xffff || pos == end_pos) 84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 0; 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (*end_pos == '.') { 87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (result_pos + kIpv4AddressSize > kIpv6AddressSize) 88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 0; 89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) /* Parse rest of address as IPv4 address. */ 90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!inet_pton_v4(pos, result + result_pos)) 91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 0; 92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) result_pos += 4; 93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (result_pos > kIpv6AddressSize - 2) 97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 0; 98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) result[result_pos] = (word & 0xFF00) >> 8; 99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) result[result_pos + 1] = word & 0xFF; 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) result_pos += 2; 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (*end_pos == '\0') 103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (*end_pos != ':') 106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 0; 107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) pos = end_pos + 1; 109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (*pos == ':') { 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (double_colon_pos != -1) 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 0; 112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) double_colon_pos = result_pos; 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ++pos; 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) /* Finally move the data to the end in case the address contained '::'. */ 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (result_pos < kIpv6AddressSize) { 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (double_colon_pos == -1) 120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 0; 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int move_size = result_pos - double_colon_pos; 122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int gap_size = kIpv6AddressSize - result_pos; 123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) memmove(result + kIpv6AddressSize - move_size, 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) result + double_colon_pos, move_size); 125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) memset(result + double_colon_pos, 0, gap_size); 126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) /* Finally copy the result to the output buffer. */ 129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) memcpy(dst, result, sizeof(result)); 130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 1; 132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)int inet_pton(int af, const char *src, void *dst) { 135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!src || !dst) { 136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 0; 137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (af == AF_INET) { 139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return inet_pton_v4(src, dst); 140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else if (af == AF_INET6) { 141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return inet_pton_v6(src, dst); 142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) errno = EAFNOSUPPORT; 144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return -1; 145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 147c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#endif /* defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) ... */ 148