about summary refs log tree commit diff
path: root/sysdeps/unix/sysv/linux/check_pf.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2007-11-12 23:55:58 +0000
committerUlrich Drepper <drepper@redhat.com>2007-11-12 23:55:58 +0000
commit6f3914d5a3269c00e70506bd95f816fef6b635ce (patch)
tree282916b72b33748f124aad021f5fc706184a1c13 /sysdeps/unix/sysv/linux/check_pf.c
parentc1600ce36dc0c58185ec67327316d02639da628b (diff)
downloadglibc-6f3914d5a3269c00e70506bd95f816fef6b635ce.tar.gz
glibc-6f3914d5a3269c00e70506bd95f816fef6b635ce.tar.xz
glibc-6f3914d5a3269c00e70506bd95f816fef6b635ce.zip
* include/ifaddrs.c (struct in6addrinfo): Add prefixlen field.
	* sysdeps/unix/sysv/linux/check_pf.c (make_request): Always return
	list of interfaces.  Also store prefix length.
	* sysdeps/posix/getaddrinfo.c (sort_result): Add prefixlen element.
	(rfc3484_sort): In rule 9, for IPv4 addresses count only matching
	prefix if source and destination address are in the same subnet.
	(getaddrinfo): Always call __check_pf.  Fill in prefixlen field.
	Always look for matching record in in6ai list.
	Correct source_addr_len value for IPv6->IPv4 converted records.
Diffstat (limited to 'sysdeps/unix/sysv/linux/check_pf.c')
-rw-r--r--sysdeps/unix/sysv/linux/check_pf.c123
1 files changed, 50 insertions, 73 deletions
diff --git a/sysdeps/unix/sysv/linux/check_pf.c b/sysdeps/unix/sysv/linux/check_pf.c
index df7cbb1897..532e1d923d 100644
--- a/sysdeps/unix/sysv/linux/check_pf.c
+++ b/sysdeps/unix/sysv/linux/check_pf.c
@@ -145,92 +145,69 @@ make_request (int fd, pid_t pid, bool *seen_ipv4, bool *seen_ipv6,
 	      struct rtattr *rta = IFA_RTA (ifam);
 	      size_t len = nlmh->nlmsg_len - NLMSG_LENGTH (sizeof (*ifam));
 
-	      switch (ifam->ifa_family)
-		{
-		  const void *local;
-		  const void *address;
+	      if (ifam->ifa_family != AF_INET
+		  && ifam->ifa_family != AF_INET6)
+		continue;
 
-		case AF_INET:
-		  local = NULL;
-		  address = NULL;
-		  while (RTA_OK (rta, len))
+	      const void *local = NULL;
+	      const void *address = NULL;
+	      while (RTA_OK (rta, len))
+		{
+		  switch (rta->rta_type)
 		    {
-		      switch (rta->rta_type)
-			{
-			case IFA_LOCAL:
-			  local = RTA_DATA (rta);
-			  break;
-
-			case IFA_ADDRESS:
-			  address = RTA_DATA (rta);
-			  goto out_v4;
-			}
-
-		      rta = RTA_NEXT (rta, len);
+		    case IFA_LOCAL:
+		      local = RTA_DATA (rta);
+		      break;
+
+		    case IFA_ADDRESS:
+		      address = RTA_DATA (rta);
+		      goto out;
 		    }
 
-		  if (local != NULL)
+		  rta = RTA_NEXT (rta, len);
+		}
+
+	      if (local != NULL)
+		{
+		  address = local;
+		out:
+		  if (ifam->ifa_family != AF_INET)
 		    {
-		    out_v4:
-		      if (*(const in_addr_t *) (address ?: local)
+		      if (*(const in_addr_t *) address
 			  != htonl (INADDR_LOOPBACK))
 			*seen_ipv4 = true;
 		    }
-		  break;
-
-		case AF_INET6:
-		  local = NULL;
-		  address = NULL;
-		  while (RTA_OK (rta, len))
-		    {
-		      switch (rta->rta_type)
-			{
-			case IFA_LOCAL:
-			  local = RTA_DATA (rta);
-			  break;
-
-			case IFA_ADDRESS:
-			  address = RTA_DATA (rta);
-			  goto out_v6;
-			}
-
-		      rta = RTA_NEXT (rta, len);
-		    }
-
-		  if (local != NULL)
+		  else
 		    {
-		    out_v6:
-		      if (!IN6_IS_ADDR_LOOPBACK (address ?: local))
+		      if (!IN6_IS_ADDR_LOOPBACK (address))
 			*seen_ipv6 = true;
 		    }
+		}
 
-		  if (ifam->ifa_flags & (IFA_F_DEPRECATED
-					 | IFA_F_TEMPORARY
-					 | IFA_F_HOMEADDRESS
-					 | IFA_F_OPTIMISTIC))
-		    {
-		      struct in6ailist *newp = alloca (sizeof (*newp));
-		      newp->info.flags = (((ifam->ifa_flags
-					    & (IFA_F_DEPRECATED
-					       | IFA_F_OPTIMISTIC))
-					   ? in6ai_deprecated : 0)
-					  | ((ifam->ifa_flags
-					      & IFA_F_TEMPORARY)
-					     ? in6ai_temporary : 0)
-					  | ((ifam->ifa_flags
-					      & IFA_F_HOMEADDRESS)
-					     ? in6ai_homeaddress : 0));
-		      memcpy (newp->info.addr, address ?: local,
-			      sizeof (newp->info.addr));
-		      newp->next = in6ailist;
-		      in6ailist = newp;
-		      ++in6ailistlen;
-		    }
-		  break;
-		default:
-		  /* Ignore.  */
-		  break;
+	      struct in6ailist *newp = alloca (sizeof (*newp));
+	      newp->info.flags = (((ifam->ifa_flags
+				    & (IFA_F_DEPRECATED
+				       | IFA_F_OPTIMISTIC))
+				   ? in6ai_deprecated : 0)
+				  | ((ifam->ifa_flags
+				      & IFA_F_TEMPORARY)
+				     ? in6ai_temporary : 0)
+				  | ((ifam->ifa_flags
+				      & IFA_F_HOMEADDRESS)
+				     ? in6ai_homeaddress : 0));
+	      newp->info.prefixlen = ifam->ifa_prefixlen;
+	      if (ifam->ifa_family == AF_INET)
+		{
+		  newp->info.addr[0] = 0;
+		  newp->info.addr[1] = 0;
+		  newp->info.addr[2] = htonl (0xffff);
+		  newp->info.addr[3] = *(const in_addr_t *) address;
 		}
+	      else
+		memcpy (newp->info.addr, address, sizeof (newp->info.addr));
+	      newp->next = in6ailist;
+	      in6ailist = newp;
+	      ++in6ailistlen;
 	    }
 	  else if (nlmh->nlmsg_type == NLMSG_DONE)
 	    /* We found the end, leave the loop.  */