Changes in uspace/lib/c/generic/net/inet.c [9d58539:e52b4b5] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/net/inet.c
r9d58539 re52b4b5 1 1 /* 2 * Copyright (c) 20 09 Lukas Mejdrech2 * Copyright (c) 2013 Martin Decky 3 3 * All rights reserved. 4 4 * … … 39 39 #include <net/in6.h> 40 40 #include <net/inet.h> 41 41 #include <inet/addr.h> 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 } else 86 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 47 133 /** Prints the address into the character buffer. 48 134 * 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. 57 */ 58 int 59 inet_ntop(uint16_t family, const uint8_t *data, char *address, size_t length) 60 { 61 if ((!data) || (!address)) 62 return EINVAL; 63 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 * 145 */ 146 int inet_ntop(uint16_t family, const uint8_t *data, char *address, size_t length) 147 { 64 148 switch (family) { 65 149 case AF_INET: 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 150 return inet_ntop4(data, address, length); 76 151 case AF_INET6: 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 152 return inet_ntop6(data, address, length); 91 153 default: 92 154 return ENOTSUP; … … 94 156 } 95 157 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 96 267 /** Parses the character string into the address. 97 268 * 98 * If the string is shorter than the full address, zero bytes are added.99 * 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 dataparameter is NULL.105 * @return ENOENT if the address parameter is NULL.106 * @return ENOTSUP if the address family is not supported.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. 272 * 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 * 107 278 */ 108 279 int inet_pton(uint16_t family, const char *address, uint8_t *data) 109 280 { 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 */127 281 switch (family) { 128 282 case AF_INET: 129 count = 4; 130 base = 10; 131 bytes = 1; 132 break; 133 283 return inet_pton4(address, data); 134 284 case AF_INET6: 135 count = 16; 136 base = 16; 137 bytes = 4; 138 break; 139 285 return inet_pton6(address, data); 140 286 default: 287 /** Unknown address family */ 141 288 return ENOTSUP; 142 289 } 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 character167 * should be either '.' or ':' but is ignored to be168 * more generic169 */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;189 290 } 190 291
Note:
See TracChangeset
for help on using the changeset viewer.