Changes in uspace/lib/c/generic/net/inet.c [e52b4b5:9d58539] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/net/inet.c
re52b4b5 r9d58539 1 1 /* 2 * Copyright (c) 20 13 Martin Decky2 * Copyright (c) 2009 Lukas Mejdrech 3 3 * All rights reserved. 4 4 * … … 39 39 #include <net/in6.h> 40 40 #include <net/inet.h> 41 #include <inet/addr.h> 41 42 42 #include <errno.h> 43 43 #include <mem.h> … … 45 45 #include <str.h> 46 46 47 const in6_addr_t in6addr_any = {48 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }49 };50 51 static int inet_ntop4(const uint8_t *data, char *address, size_t length)52 {53 /* Check output buffer size */54 if (length < INET_ADDRSTRLEN)55 return ENOMEM;56 57 /* Fill buffer with IPv4 address */58 snprintf(address, length,59 "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8,60 data[0], data[1], data[2], data[3]);61 62 return EOK;63 }64 65 static int inet_ntop6(const uint8_t *data, char *address, size_t length)66 {67 /* Check output buffer size */68 if (length < INET6_ADDRSTRLEN)69 return ENOMEM;70 71 /* Find the longest zero subsequence */72 73 uint16_t zeroes[8];74 uint16_t bioctets[8];75 76 for (size_t i = 8; i > 0; i--) {77 size_t j = i - 1;78 79 bioctets[j] = (data[j << 1] << 8) | data[(j << 1) + 1];80 81 if (bioctets[j] == 0) {82 zeroes[j] = 1;83 if (j < 7)84 zeroes[j] += zeroes[j + 1];85 } else86 zeroes[j] = 0;87 }88 89 size_t wildcard_pos = (size_t) -1;90 size_t wildcard_size = 0;91 92 for (size_t i = 0; i < 8; i++) {93 if (zeroes[i] > wildcard_size) {94 wildcard_pos = i;95 wildcard_size = zeroes[i];96 }97 }98 99 char *cur = address;100 size_t rest = length;101 bool tail_zero = false;102 int ret;103 104 for (size_t i = 0; i < 8; i++) {105 if ((i == wildcard_pos) && (wildcard_size > 1)) {106 ret = snprintf(cur, rest, ":");107 i += wildcard_size - 1;108 tail_zero = true;109 } else if (i == 0) {110 ret = snprintf(cur, rest, "%" PRIx16, bioctets[i]);111 tail_zero = false;112 } else {113 ret = snprintf(cur, rest, ":%" PRIx16, bioctets[i]);114 tail_zero = false;115 }116 117 if (ret < 0)118 return EINVAL;119 120 cur += ret;121 rest -= ret;122 }123 124 if (tail_zero) {125 ret = snprintf(cur, rest, ":");126 if (ret < 0)127 return EINVAL;128 }129 130 return EOK;131 }132 133 47 /** Prints the address into the character buffer. 134 48 * 135 * @param[in] family Address family. 136 * @param[in] data Address data. 137 * @param[out] address Character buffer to be filled. 138 * @param[in] length Buffer length. 139 * 140 * @return EOK on success. 141 * @return EINVAL if the data or address parameter is NULL. 142 * @return ENOMEM if the character buffer is not long enough. 143 * @return ENOTSUP if the address family is not supported. 144 * 49 * @param[in] family The address family. 50 * @param[in] data The address data. 51 * @param[out] address The character buffer to be filled. 52 * @param[in] length The buffer length. 53 * @return EOK on success. 54 * @return EINVAL if the data or address parameter is NULL. 55 * @return ENOMEM if the character buffer is not long enough. 56 * @return ENOTSUP if the address family is not supported. 145 57 */ 146 int inet_ntop(uint16_t family, const uint8_t *data, char *address, size_t length) 58 int 59 inet_ntop(uint16_t family, const uint8_t *data, char *address, size_t length) 147 60 { 61 if ((!data) || (!address)) 62 return EINVAL; 63 148 64 switch (family) { 149 65 case AF_INET: 150 return inet_ntop4(data, address, length); 66 /* Check output buffer size */ 67 if (length < INET_ADDRSTRLEN) 68 return ENOMEM; 69 70 /* Fill buffer with IPv4 address */ 71 snprintf(address, length, "%hhu.%hhu.%hhu.%hhu", 72 data[0], data[1], data[2], data[3]); 73 74 return EOK; 75 151 76 case AF_INET6: 152 return inet_ntop6(data, address, length); 77 /* Check output buffer size */ 78 if (length < INET6_ADDRSTRLEN) 79 return ENOMEM; 80 81 /* Fill buffer with IPv6 address */ 82 snprintf(address, length, 83 "%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx:" 84 "%hhx%hhx:%hhx%hhx", 85 data[0], data[1], data[2], data[3], data[4], data[5], 86 data[6], data[7], data[8], data[9], data[10], data[11], 87 data[12], data[13], data[14], data[15]); 88 89 return EOK; 90 153 91 default: 154 92 return ENOTSUP; … … 156 94 } 157 95 158 static int inet_pton4(const char *address, uint8_t *data)159 {160 memset(data, 0, 4);161 162 const char *cur = address;163 size_t i = 0;164 165 while (i < 4) {166 int rc = str_uint8_t(cur, &cur, 10, false, &data[i]);167 if (rc != EOK)168 return rc;169 170 i++;171 172 if (*cur == 0)173 break;174 175 if (*cur != '.')176 return EINVAL;177 178 if (i < 4)179 cur++;180 }181 182 if ((i == 4) && (*cur != 0))183 return EINVAL;184 185 return EOK;186 }187 188 static int inet_pton6(const char *address, uint8_t *data)189 {190 memset(data, 0, 16);191 192 const char *cur = address;193 size_t i = 0;194 size_t wildcard_pos = (size_t) -1;195 size_t wildcard_size = 0;196 197 /* Handle initial wildcard */198 if ((address[0] == ':') && (address[1] == ':')) {199 cur = address + 2;200 wildcard_pos = 0;201 wildcard_size = 16;202 203 /* Handle empty address */204 if (*cur == 0)205 return EOK;206 }207 208 while (i < 16) {209 uint16_t bioctet;210 int rc = str_uint16_t(cur, &cur, 16, false, &bioctet);211 if (rc != EOK)212 return rc;213 214 data[i] = (bioctet >> 8) & 0xff;215 data[i + 1] = bioctet & 0xff;216 217 if (wildcard_pos != (size_t) -1) {218 if (wildcard_size < 2)219 return EINVAL;220 221 wildcard_size -= 2;222 }223 224 i += 2;225 226 if (*cur == 0)227 break;228 229 if (*cur != ':')230 return EINVAL;231 232 if (i < 16) {233 cur++;234 235 /* Handle wildcard */236 if (*cur == ':') {237 if (wildcard_pos != (size_t) -1)238 return EINVAL;239 240 wildcard_pos = i;241 wildcard_size = 16 - i;242 cur++;243 244 if (*cur == 0)245 break;246 }247 }248 }249 250 if ((i == 16) && (*cur != 0))251 return EINVAL;252 253 /* Create wildcard positions */254 if ((wildcard_pos != (size_t) -1) && (wildcard_size > 0)) {255 size_t wildcard_shift = 16 - wildcard_size;256 257 for (i = wildcard_pos + wildcard_shift; i > wildcard_pos; i--) {258 size_t j = i - 1;259 data[j + wildcard_size] = data[j];260 data[j] = 0;261 }262 }263 264 return EOK;265 }266 267 96 /** Parses the character string into the address. 268 97 * 269 * @param[in] family The address family. 270 * @param[in] address The character buffer to be parsed. 271 * @param[out] data The address data to be filled. 98 * If the string is shorter than the full address, zero bytes are added. 272 99 * 273 * @return EOK on success. 274 * @return EINVAL if the data parameter is NULL. 275 * @return ENOENT if the address parameter is NULL. 276 * @return ENOTSUP if the address family is not supported. 277 * 100 * @param[in] family The address family. 101 * @param[in] address The character buffer to be parsed. 102 * @param[out] data The address data to be filled. 103 * @return EOK on success. 104 * @return EINVAL if the data parameter is NULL. 105 * @return ENOENT if the address parameter is NULL. 106 * @return ENOTSUP if the address family is not supported. 278 107 */ 279 108 int inet_pton(uint16_t family, const char *address, uint8_t *data) 280 109 { 110 /** The base number of the values. */ 111 int base; 112 /** The number of bytes per a section. */ 113 size_t bytes; 114 /** The number of bytes of the address data. */ 115 int count; 116 117 const char *next; 118 char *last; 119 int index; 120 size_t shift; 121 unsigned long value; 122 123 if (!data) 124 return EINVAL; 125 126 /* Set processing parameters */ 281 127 switch (family) { 282 128 case AF_INET: 283 return inet_pton4(address, data); 129 count = 4; 130 base = 10; 131 bytes = 1; 132 break; 133 284 134 case AF_INET6: 285 return inet_pton6(address, data); 135 count = 16; 136 base = 16; 137 bytes = 4; 138 break; 139 286 140 default: 287 /** Unknown address family */288 141 return ENOTSUP; 289 142 } 143 144 /* Erase if no address */ 145 if (!address) { 146 bzero(data, count); 147 return ENOENT; 148 } 149 150 /* Process string from the beginning */ 151 next = address; 152 index = 0; 153 do { 154 /* If the actual character is set */ 155 if (next && *next) { 156 157 /* If not on the first character */ 158 if (index) { 159 /* Move to the next character */ 160 ++next; 161 } 162 163 /* Parse the actual integral value */ 164 value = strtoul(next, &last, base); 165 /* 166 * Remember the last problematic character 167 * should be either '.' or ':' but is ignored to be 168 * more generic 169 */ 170 next = last; 171 172 /* Fill the address data byte by byte */ 173 shift = bytes - 1; 174 do { 175 /* like little endian */ 176 data[index + shift] = value; 177 value >>= 8; 178 } while(shift --); 179 180 index += bytes; 181 } else { 182 /* Erase the rest of the address */ 183 bzero(data + index, count - index); 184 return EOK; 185 } 186 } while (index < count); 187 188 return EOK; 290 189 } 291 190
Note:
See TracChangeset
for help on using the changeset viewer.