562__BIONIC_WEAK_FOR_NATIVE_BRIDGE
563int
564getaddrinfo(const char *hostname, const char *servname,
565 const struct addrinfo *hints, struct addrinfo **res)
566{
567 return android_getaddrinfofornet(hostname, servname, hints, NETID_UNSET, MARK_UNSET, res);
568}
570__BIONIC_WEAK_FOR_NATIVE_BRIDGE
571int
572android_getaddrinfofornet(const char *hostname, const char *servname,
573 const struct addrinfo *hints, unsigned netid, unsigned mark, struct addrinfo **res)
574{
575 struct android_net_context netcontext = {
576 .app_netid = netid,
577 .app_mark = mark,
578 .dns_netid = netid,
579 .dns_mark = mark,
580 .uid = NET_CONTEXT_INVALID_UID,
581 };
582 return android_getaddrinfofornetcontext(hostname, servname, hints, &netcontext, res);
583}
584
585__BIONIC_WEAK_FOR_NATIVE_BRIDGE
586int
587android_getaddrinfofornetcontext(const char *hostname, const char *servname,
588 const struct addrinfo *hints, const struct android_net_context *netcontext,
589 struct addrinfo **res)
590{
591 struct addrinfo sentinel;
592 struct addrinfo *cur;
593 int error = 0;
594 struct addrinfo ai;
595 struct addrinfo ai0;
596 struct addrinfo *pai;
597 const struct explore *ex;
598
599 /* hostname is allowed to be NULL */
600 /* servname is allowed to be NULL */
601 /* hints is allowed to be NULL */
602 assert(res != NULL);
603 assert(netcontext != NULL);
604 memset(&sentinel, 0, sizeof(sentinel));
605 cur = &sentinel;
606 pai = &ai;
607 pai->ai_flags = 0;
608 pai->ai_family = PF_UNSPEC;
609 pai->ai_socktype = ANY;
610 pai->ai_protocol = ANY;
611 pai->ai_addrlen = 0;
612 pai->ai_canonname = NULL;
613 pai->ai_addr = NULL;
614 pai->ai_next = NULL;
615
616 if (hostname == NULL && servname == NULL)
617 return EAI_NONAME;
618 if (hints) {
619 /* error check for hints */
620 if (hints->ai_addrlen || hints->ai_canonname ||
621 hints->ai_addr || hints->ai_next)
622 ERR(EAI_BADHINTS); /* xxx */
623 if (hints->ai_flags & ~AI_MASK)
624 ERR(EAI_BADFLAGS);
625 switch (hints->ai_family) {
626 case PF_UNSPEC:
627 case PF_INET:
628#ifdef INET6
629 case PF_INET6:
630#endif
631 break;
632 default:
633 ERR(EAI_FAMILY);
634 }
635 memcpy(pai, hints, sizeof(*pai));
636
637 /*
638 * if both socktype/protocol are specified, check if they
639 * are meaningful combination.
640 */
641 if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
642 for (ex = explore; ex->e_af >= 0; ex++) {
643 if (pai->ai_family != ex->e_af)
644 continue;
645 if (ex->e_socktype == ANY)
646 continue;
647 if (ex->e_protocol == ANY)
648 continue;
649 if (pai->ai_socktype == ex->e_socktype
650 && pai->ai_protocol != ex->e_protocol) {
651 ERR(EAI_BADHINTS);
652 }
653 }
654 }
655 }
656
657 /*
658 * check for special cases. (1) numeric servname is disallowed if
659 * socktype/protocol are left unspecified. (2) servname is disallowed
660 * for raw and other inet{,6} sockets.
661 */
662 if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
663#ifdef PF_INET6
664 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
665#endif
666 ) {
667 ai0 = *pai; /* backup *pai */
668
669 if (pai->ai_family == PF_UNSPEC) {
670#ifdef PF_INET6
671 pai->ai_family = PF_INET6;
672#else
673 pai->ai_family = PF_INET;
674#endif
675 }
676 error = get_portmatch(pai, servname);
677 if (error)
678 ERR(error);
679
680 *pai = ai0;
681 }
682
683 ai0 = *pai;
684
685 /* NULL hostname, or numeric hostname */
686 for (ex = explore; ex->e_af >= 0; ex++) {
687 *pai = ai0;
688
689 /* PF_UNSPEC entries are prepared for DNS queries only */
690 if (ex->e_af == PF_UNSPEC)
691 continue;
692
693 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
694 continue;
695 if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
696 continue;
697 if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
698 continue;
699
700 if (pai->ai_family == PF_UNSPEC)
701 pai->ai_family = ex->e_af;
702 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
703 pai->ai_socktype = ex->e_socktype;
704 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
705 pai->ai_protocol = ex->e_protocol;
706
707 if (hostname == NULL)
708 error = explore_null(pai, servname, &cur->ai_next);
709 else
710 error = explore_numeric_scope(pai, hostname, servname,
711 &cur->ai_next);
712
713 if (error)
714 goto free;
715
716 while (cur->ai_next)
717 cur = cur->ai_next;
718 }
719
720 /*
721 * XXX
722 * If numeric representation of AF1 can be interpreted as FQDN
723 * representation of AF2, we need to think again about the code below.
724 */
725 if (sentinel.ai_next)
726 goto good;
727
728 if (hostname == NULL)
729 ERR(EAI_NODATA);
730 if (pai->ai_flags & AI_NUMERICHOST)
731 ERR(EAI_NONAME);
732
733#if defined(__ANDROID__)
734 int gai_error = android_getaddrinfo_proxy(
735 hostname, servname, hints, res, netcontext->app_netid);
736 if (gai_error != EAI_SYSTEM) {
737 return gai_error;
738 }
739#endif
740
741 /*
742 * hostname as alphabetical name.
743 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
744 * outer loop by AFs.
745 */
746 for (ex = explore; ex->e_af >= 0; ex++) {
747 *pai = ai0;
748
749 /* require exact match for family field */
750 if (pai->ai_family != ex->e_af)
751 continue;
752
753 if (!MATCH(pai->ai_socktype, ex->e_socktype,
754 WILD_SOCKTYPE(ex))) {
755 continue;
756 }
757 if (!MATCH(pai->ai_protocol, ex->e_protocol,
758 WILD_PROTOCOL(ex))) {
759 continue;
760 }
761
762 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
763 pai->ai_socktype = ex->e_socktype;
764 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
765 pai->ai_protocol = ex->e_protocol;
766
767 error = explore_fqdn(
768 pai, hostname, servname, &cur->ai_next, netcontext);
769
770 while (cur && cur->ai_next)
771 cur = cur->ai_next;
772 }
773
774 /* XXX */
775 if (sentinel.ai_next)
776 error = 0;
777
778 if (error)
779 goto free;
780 if (error == 0) {
781 if (sentinel.ai_next) {
782 good:
783 *res = sentinel.ai_next;
784 return SUCCESS;
785 } else
786 error = EAI_FAIL;
787 }
788 free:
789 bad:
790 if (sentinel.ai_next)
791 freeaddrinfo(sentinel.ai_next);
792 *res = NULL;
793 return error;
794}