3c3
< * $FreeBSD: head/usr.sbin/rpcbind/util.c 243187 2012-11-17 20:19:00Z hrs $
---
> * $FreeBSD: head/usr.sbin/rpcbind/util.c 293229 2016-01-06 00:00:11Z asomers $
59c59
< static int bitmaskcmp(void *, void *, void *, int);
---
> static int bitmaskcmp(struct sockaddr *, struct sockaddr *, struct sockaddr *);
67c67
< bitmaskcmp(void *dst, void *src, void *mask, int bytelen)
---
> bitmaskcmp(struct sockaddr *dst, struct sockaddr *src, struct sockaddr *mask)
70c70,71
< u_int8_t *p1 = dst, *p2 = src, *netmask = mask;
---
> u_int8_t *p1, *p2, *netmask;
> int bytelen;
71a73,95
> if (dst->sa_family != src->sa_family ||
> dst->sa_family != mask->sa_family)
> return (1);
>
> switch (dst->sa_family) {
> case AF_INET:
> p1 = (uint8_t*) &SA2SINADDR(dst);
> p2 = (uint8_t*) &SA2SINADDR(src);
> netmask = (uint8_t*) &SA2SINADDR(mask);
> bytelen = sizeof(struct in_addr);
> break;
> #ifdef INET6
> case AF_INET6:
> p1 = (uint8_t*) &SA2SIN6ADDR(dst);
> p2 = (uint8_t*) &SA2SIN6ADDR(src);
> netmask = (uint8_t*) &SA2SIN6ADDR(mask);
> bytelen = sizeof(struct in6_addr);
> break;
> #endif
> default:
> return (1);
> }
>
89,90c113,114
< addrmerge(struct netbuf *caller, char *serv_uaddr, char *clnt_uaddr,
< char *netid)
---
> addrmerge(struct netbuf *caller, const char *serv_uaddr, const char *clnt_uaddr,
> const char *netid)
97c121,122
< char *caller_uaddr = NULL, *hint_uaddr = NULL;
---
> char *caller_uaddr = NULL;
> const char *hint_uaddr = NULL;
98a124
> int bestif_goodness;
142,148c168,182
< * Loop through all interfaces. For each interface, see if it
< * is either the loopback interface (which we always listen
< * on) or is one of the addresses the program bound to (the
< * wildcard by default, or a subset if -h is specified) and
< * the network portion of its address is equal to that of the
< * client. If so, we have found the interface that we want to
< * use.
---
> * Loop through all interface addresses. We are listening to an address
> * if any of the following are true:
> * a) It's a loopback address
> * b) It was specified with the -h command line option
> * c) There were no -h command line options.
> *
> * Among addresses on which we are listening, choose in order of
> * preference an address that is:
> *
> * a) Equal to the hint
> * b) A link local address with the same scope ID as the client's
> * address, if the client's address is also link local
> * c) An address on the same subnet as the client's address
> * d) A non-localhost, non-p2p address
> * e) Any usable address
150a185
> bestif_goodness = 0;
154a190
> /* Skip addresses where we don't listen */
162,174c198,206
< switch (hint_sa->sa_family) {
< case AF_INET:
< /*
< * If the hint address matches this interface
< * address/netmask, then we're done.
< */
< if (!bitmaskcmp(&SA2SINADDR(ifsa),
< &SA2SINADDR(hint_sa), &SA2SINADDR(ifmasksa),
< sizeof(struct in_addr))) {
< bestif = ifap;
< goto found;
< }
< break;
---
> if ((hint_sa->sa_family == AF_INET) &&
> ((((struct sockaddr_in*)hint_sa)->sin_addr.s_addr ==
> ((struct sockaddr_in*)ifsa)->sin_addr.s_addr))) {
> const int goodness = 4;
>
> bestif_goodness = goodness;
> bestif = ifap;
> goto found;
> }
176c208,220
< case AF_INET6:
---
> if ((hint_sa->sa_family == AF_INET6) &&
> (0 == memcmp(&((struct sockaddr_in6*)hint_sa)->sin6_addr,
> &((struct sockaddr_in6*)ifsa)->sin6_addr,
> sizeof(struct in6_addr))) &&
> (((struct sockaddr_in6*)hint_sa)->sin6_scope_id ==
> (((struct sockaddr_in6*)ifsa)->sin6_scope_id))) {
> const int goodness = 4;
>
> bestif_goodness = goodness;
> bestif = ifap;
> goto found;
> }
> if (hint_sa->sa_family == AF_INET6) {
187,188c231,236
< bestif = ifap;
< goto found;
---
> const int goodness = 3;
>
> if (bestif_goodness < goodness) {
> bestif = ifap;
> bestif_goodness = goodness;
> }
190,192c238,244
< } else if (!bitmaskcmp(&SA2SIN6ADDR(ifsa),
< &SA2SIN6ADDR(hint_sa), &SA2SIN6ADDR(ifmasksa),
< sizeof(struct in6_addr))) {
---
> }
> }
> #endif /* INET6 */
> if (0 == bitmaskcmp(hint_sa, ifsa, ifmasksa)) {
> const int goodness = 2;
>
> if (bestif_goodness < goodness) {
194c246
< goto found;
---
> bestif_goodness = goodness;
196,199d247
< break;
< #endif
< default:
< continue;
200a249,250
> if (!(ifap->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT))) {
> const int goodness = 1;
202,208c252,257
< /*
< * Remember the first possibly useful interface, preferring
< * "normal" to point-to-point and loopback ones.
< */
< if (bestif == NULL ||
< (!(ifap->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) &&
< (bestif->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT))))
---
> if (bestif_goodness < goodness) {
> bestif = ifap;
> bestif_goodness = goodness;
> }
> }
> if (bestif == NULL)
< * $FreeBSD: head/usr.sbin/rpcbind/util.c 243187 2012-11-17 20:19:00Z hrs $
---
> * $FreeBSD: head/usr.sbin/rpcbind/util.c 293229 2016-01-06 00:00:11Z asomers $
59c59
< static int bitmaskcmp(void *, void *, void *, int);
---
> static int bitmaskcmp(struct sockaddr *, struct sockaddr *, struct sockaddr *);
67c67
< bitmaskcmp(void *dst, void *src, void *mask, int bytelen)
---
> bitmaskcmp(struct sockaddr *dst, struct sockaddr *src, struct sockaddr *mask)
70c70,71
< u_int8_t *p1 = dst, *p2 = src, *netmask = mask;
---
> u_int8_t *p1, *p2, *netmask;
> int bytelen;
71a73,95
> if (dst->sa_family != src->sa_family ||
> dst->sa_family != mask->sa_family)
> return (1);
>
> switch (dst->sa_family) {
> case AF_INET:
> p1 = (uint8_t*) &SA2SINADDR(dst);
> p2 = (uint8_t*) &SA2SINADDR(src);
> netmask = (uint8_t*) &SA2SINADDR(mask);
> bytelen = sizeof(struct in_addr);
> break;
> #ifdef INET6
> case AF_INET6:
> p1 = (uint8_t*) &SA2SIN6ADDR(dst);
> p2 = (uint8_t*) &SA2SIN6ADDR(src);
> netmask = (uint8_t*) &SA2SIN6ADDR(mask);
> bytelen = sizeof(struct in6_addr);
> break;
> #endif
> default:
> return (1);
> }
>
89,90c113,114
< addrmerge(struct netbuf *caller, char *serv_uaddr, char *clnt_uaddr,
< char *netid)
---
> addrmerge(struct netbuf *caller, const char *serv_uaddr, const char *clnt_uaddr,
> const char *netid)
97c121,122
< char *caller_uaddr = NULL, *hint_uaddr = NULL;
---
> char *caller_uaddr = NULL;
> const char *hint_uaddr = NULL;
98a124
> int bestif_goodness;
142,148c168,182
< * Loop through all interfaces. For each interface, see if it
< * is either the loopback interface (which we always listen
< * on) or is one of the addresses the program bound to (the
< * wildcard by default, or a subset if -h is specified) and
< * the network portion of its address is equal to that of the
< * client. If so, we have found the interface that we want to
< * use.
---
> * Loop through all interface addresses. We are listening to an address
> * if any of the following are true:
> * a) It's a loopback address
> * b) It was specified with the -h command line option
> * c) There were no -h command line options.
> *
> * Among addresses on which we are listening, choose in order of
> * preference an address that is:
> *
> * a) Equal to the hint
> * b) A link local address with the same scope ID as the client's
> * address, if the client's address is also link local
> * c) An address on the same subnet as the client's address
> * d) A non-localhost, non-p2p address
> * e) Any usable address
150a185
> bestif_goodness = 0;
154a190
> /* Skip addresses where we don't listen */
162,174c198,206
< switch (hint_sa->sa_family) {
< case AF_INET:
< /*
< * If the hint address matches this interface
< * address/netmask, then we're done.
< */
< if (!bitmaskcmp(&SA2SINADDR(ifsa),
< &SA2SINADDR(hint_sa), &SA2SINADDR(ifmasksa),
< sizeof(struct in_addr))) {
< bestif = ifap;
< goto found;
< }
< break;
---
> if ((hint_sa->sa_family == AF_INET) &&
> ((((struct sockaddr_in*)hint_sa)->sin_addr.s_addr ==
> ((struct sockaddr_in*)ifsa)->sin_addr.s_addr))) {
> const int goodness = 4;
>
> bestif_goodness = goodness;
> bestif = ifap;
> goto found;
> }
176c208,220
< case AF_INET6:
---
> if ((hint_sa->sa_family == AF_INET6) &&
> (0 == memcmp(&((struct sockaddr_in6*)hint_sa)->sin6_addr,
> &((struct sockaddr_in6*)ifsa)->sin6_addr,
> sizeof(struct in6_addr))) &&
> (((struct sockaddr_in6*)hint_sa)->sin6_scope_id ==
> (((struct sockaddr_in6*)ifsa)->sin6_scope_id))) {
> const int goodness = 4;
>
> bestif_goodness = goodness;
> bestif = ifap;
> goto found;
> }
> if (hint_sa->sa_family == AF_INET6) {
187,188c231,236
< bestif = ifap;
< goto found;
---
> const int goodness = 3;
>
> if (bestif_goodness < goodness) {
> bestif = ifap;
> bestif_goodness = goodness;
> }
190,192c238,244
< } else if (!bitmaskcmp(&SA2SIN6ADDR(ifsa),
< &SA2SIN6ADDR(hint_sa), &SA2SIN6ADDR(ifmasksa),
< sizeof(struct in6_addr))) {
---
> }
> }
> #endif /* INET6 */
> if (0 == bitmaskcmp(hint_sa, ifsa, ifmasksa)) {
> const int goodness = 2;
>
> if (bestif_goodness < goodness) {
194c246
< goto found;
---
> bestif_goodness = goodness;
196,199d247
< break;
< #endif
< default:
< continue;
200a249,250
> if (!(ifap->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT))) {
> const int goodness = 1;
202,208c252,257
< /*
< * Remember the first possibly useful interface, preferring
< * "normal" to point-to-point and loopback ones.
< */
< if (bestif == NULL ||
< (!(ifap->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) &&
< (bestif->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT))))
---
> if (bestif_goodness < goodness) {
> bestif = ifap;
> bestif_goodness = goodness;
> }
> }
> if (bestif == NULL)