* Converts an address string string into a totem_ip_address. ip_version enum * defines order. */
| 304 | * defines order. |
| 305 | */ |
| 306 | int totemip_parse(struct totem_ip_address *totemip, const char *addr, |
| 307 | enum totem_ip_version_enum ip_version) |
| 308 | { |
| 309 | struct addrinfo *ainfo; |
| 310 | struct addrinfo *ainfo_iter; |
| 311 | struct addrinfo *ainfo_ipv4; |
| 312 | struct addrinfo *ainfo_ipv6; |
| 313 | struct addrinfo *ainfo_final; |
| 314 | struct addrinfo ahints; |
| 315 | struct sockaddr_in *sa; |
| 316 | struct sockaddr_in6 *sa6; |
| 317 | int ret; |
| 318 | int debug_ip_family; |
| 319 | int ai_family; |
| 320 | |
| 321 | memset(&ahints, 0, sizeof(ahints)); |
| 322 | ahints.ai_socktype = SOCK_DGRAM; |
| 323 | ahints.ai_protocol = IPPROTO_UDP; |
| 324 | |
| 325 | ai_family = AF_UNSPEC; |
| 326 | debug_ip_family = 0; |
| 327 | |
| 328 | switch (ip_version) { |
| 329 | case TOTEM_IP_VERSION_4: |
| 330 | ai_family = AF_INET; |
| 331 | debug_ip_family = 4; |
| 332 | break; |
| 333 | case TOTEM_IP_VERSION_6: |
| 334 | ai_family = AF_INET6; |
| 335 | debug_ip_family = 6; |
| 336 | break; |
| 337 | case TOTEM_IP_VERSION_6_4: |
| 338 | case TOTEM_IP_VERSION_4_6: |
| 339 | /* |
| 340 | * ai_family and debug_ip_family are already set correctly |
| 341 | */ |
| 342 | break; |
| 343 | } |
| 344 | |
| 345 | ahints.ai_family = ai_family; |
| 346 | |
| 347 | ret = getaddrinfo(addr, NULL, &ahints, &ainfo); |
| 348 | |
| 349 | if (ret == 0 && ai_family == AF_UNSPEC) { |
| 350 | ainfo_ipv4 = ainfo_ipv6 = NULL; |
| 351 | |
| 352 | /* |
| 353 | * Walk thru results and store first AF_INET and AF_INET6 |
| 354 | */ |
| 355 | for (ainfo_iter = ainfo; ainfo_iter != NULL; ainfo_iter = ainfo_iter->ai_next) { |
| 356 | if (ainfo_iter->ai_family == AF_INET && ainfo_ipv4 == NULL) { |
| 357 | ainfo_ipv4 = ainfo_iter; |
| 358 | } |
| 359 | |
| 360 | if (ainfo_iter->ai_family == AF_INET6 && ainfo_ipv6 == NULL) { |
| 361 | ainfo_ipv6 = ainfo_iter; |
| 362 | } |
| 363 | } |
no test coverage detected