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