Simon 'corecode' Schubert wrote:
This is a multi-part message in MIME format.
--------------000808030508040705030804
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable

YONETANI Tomokazu wrote:
$ w
 6:13PM  up  2:52, 1 user, load averages: 0.19, 0.25, 0.13
USER             TTY      FROM              LOGIN@  IDLE WHAT
(press control+Z here, as it's stuck on reverse name resolution)
$ netstat -anfinet |fgrep .53
udp4       0      0 64.125.66.215.1119    192.168.2.175.53
                    ~~~~~~~~~~~~~
                    this address doesn't belong to our network.

I found a stack reference bug and took the chance to clean up the code.  =
Please have a look at attached patch.  If victor agrees, I'll commit this=
=2E

sorry for the broken MIME.  My enigmail from cvs seems to be quite broken.  
patch attached again.

somebody please commit this if it works.

cheers
 simon

--
Serve - BSD     +++  RENT this banner advert  +++    ASCII Ribbon   /"\
Work - Mac      +++  space for low €€€ NOW!1  +++      Campaign     \ /
Party Enjoy Relax   |   http://dragonflybsd.org      Against  HTML   \
Dude 2c 2 the max   !   http://golden-apple.biz       Mail + News   / \
Index: sys/jail.h
===================================================================
RCS file: /home/dcvs/src/sys/sys/jail.h,v
retrieving revision 1.9
diff -u -p -r1.9 jail.h
--- sys/jail.h  29 Dec 2006 18:02:56 -0000      1.9
+++ sys/jail.h  17 Jan 2007 12:45:47 -0000
@@ -68,8 +68,8 @@ MALLOC_DECLARE(M_PRISON);
 /* Used to store the IPs of the jail */
 
 struct jail_ip_storage {
-       SLIST_ENTRY(jail_ip_storage) entries;
        struct sockaddr_storage ip;
+       SLIST_ENTRY(jail_ip_storage) entries;
 };
 
 /*
@@ -85,10 +85,10 @@ struct prison {
        struct nchandle pr_root;                        /* namecache entry of 
root */
        char            pr_host[MAXHOSTNAMELEN];        /* host name */
        SLIST_HEAD(iplist, jail_ip_storage) pr_ips;     /* list of IP addresses 
*/
-       struct sockaddr_storage *local_ip4;             /* cache for a loopback 
ipv4 address */
-       struct sockaddr_storage *nonlocal_ip4;          /* cache for a non 
loopback ipv4 address */
-       struct sockaddr_storage *local_ip6;             /* cache for a loopback 
ipv6 address */
-       struct sockaddr_storage *nonlocal_ip6;          /* cache for a non 
loopback ipv6 address */
+       struct sockaddr_in      *local_ip4;             /* cache for a loopback 
ipv4 address */
+       struct sockaddr_in      *nonlocal_ip4;          /* cache for a non 
loopback ipv4 address */
+       struct sockaddr_in6     *local_ip6;             /* cache for a loopback 
ipv6 address */
+       struct sockaddr_in6     *nonlocal_ip6;          /* cache for a non 
loopback ipv6 address */
        void            *pr_linux;                      /* Linux ABI emulation 
*/
        int              pr_securelevel;                /* jail securelevel */
        struct varsymset pr_varsymset;                  /* jail varsyms */
@@ -105,8 +105,10 @@ extern int jail_chflags_allowed;
 void   prison_hold(struct prison *);
 void   prison_free(struct prison *);
 int    jailed_ip(struct prison *, struct sockaddr *);
-int    prison_get_local(struct prison *pr, struct sockaddr *);
-int    prison_get_nonlocal(struct prison *pr, struct sockaddr *);
+struct sockaddr *
+       prison_get_local(struct prison *pr, sa_family_t, struct sockaddr *);
+struct sockaddr *
+       prison_get_nonlocal(struct prison *pr, sa_family_t, struct sockaddr *);
 
 /*
  * Return 1 if the passed credential is in a jail, otherwise 0.
Index: kern/kern_jail.c
===================================================================
RCS file: /home/dcvs/src/sys/kern/kern_jail.c,v
retrieving revision 1.16
diff -u -p -r1.16 kern_jail.c
--- kern/kern_jail.c    1 Jan 2007 19:45:54 -0000       1.16
+++ kern/kern_jail.c    17 Jan 2007 12:53:16 -0000
@@ -59,6 +59,7 @@
 #include <netinet6/in6_var.h>
 
 static struct prison   *prison_find(int);
+static void            prison_ipcache_init(struct prison *);
 
 MALLOC_DEFINE(M_PRISON, "prison", "Prison structures");
 
@@ -195,6 +196,7 @@ sys_jail(struct jail_args *uap)
        cache_copy(&nd.nl_nch, &pr->pr_root);
 
        varsymset_init(&pr->pr_varsymset, NULL);
+       prison_ipcache_init(pr);
 
        tryprid = lastprid + 1;
        if (tryprid == JAIL_MAX)
@@ -255,6 +257,45 @@ sys_jail_attach(struct jail_attach_args 
        return(kern_jail_attach(uap->jid));
 }
 
+static void
+prison_ipcache_init(struct prison *pr)
+{
+       struct jail_ip_storage *jis;
+       struct sockaddr_in *ip4;
+       struct sockaddr_in6 *ip6;
+
+       SLIST_FOREACH(jis, &pr->pr_ips, entries) {
+               switch (jis->ip.ss_family) {
+               case AF_INET:
+                       ip4 = (struct sockaddr_in *)&jis->ip;
+                       if ((ntohl(ip4->sin_addr.s_addr) >> IN_CLASSA_NSHIFT) ==
+                           IN_LOOPBACKNET) {
+                               /* loopback address */
+                               if (pr->local_ip4 == NULL)
+                                       pr->local_ip4 = ip4;
+                       } else {
+                               /* public address */
+                               if (pr->nonlocal_ip4 == NULL)
+                                       pr->nonlocal_ip4 = ip4;
+                       }
+                       break;
+
+               case AF_INET6:
+                       ip6 = (struct sockaddr_in6 *)&jis->ip;
+                       if (IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr)) {
+                               /* loopback address */
+                               if (pr->local_ip6 == NULL)
+                                       pr->local_ip6 = ip6;
+                       } else {
+                               /* public address */
+                               if (pr->nonlocal_ip6 == NULL)
+                                       pr->nonlocal_ip6 = ip6;
+                       }
+                       break;
+               }
+       }
+}
+
 /* 
  * Changes INADDR_LOOPBACK for a valid jail address.
  * ip is in network byte order.
@@ -284,7 +325,8 @@ prison_replace_wildcards(struct thread *
            ip4->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) ||
            (ip->sa_family == AF_INET6 &&
            IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr))) {
-               if (!prison_get_local(pr, ip) && !prison_get_nonlocal(pr, ip))
+               if (!prison_get_local(pr, ip->sa_family, ip) &&
+                   !prison_get_nonlocal(pr, ip->sa_family, ip))
                        return(0);
                else
                        return(1);
@@ -309,7 +351,8 @@ prison_remote_ip(struct thread *td, stru
            ip4->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) ||
            (ip->sa_family == AF_INET6 &&
            IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr))) {
-               if (!prison_get_local(pr, ip) && !prison_get_nonlocal(pr, ip))
+               if (!prison_get_local(pr, ip->sa_family, ip) &&
+                   !prison_get_nonlocal(pr, ip->sa_family, ip))
                        return(0);
                else
                        return(1);
@@ -319,135 +362,68 @@ prison_remote_ip(struct thread *td, stru
 
 /*
  * Prison get non loopback ip:
- * Put on *ip the first IP address that is not a loopback address.
- * af is the address family of the ip we want (AF_INET|AF_INET6).
+ * - af is the address family of the ip we want (AF_INET|AF_INET6).
+ * - If ip != NULL, put the first IP address that is not a loopback address
+ *   into *ip.
+ *
  * ip is in network by order and we don't touch it unless we find a valid ip.
- * Return 1 if we've found a non loopback ip, else return 0.
+ * No matter if ip == NULL or not, we return either a valid struct sockaddr *,
+ * or NULL.  This struct may not be modified.
  */
-int
-prison_get_nonlocal(struct prison *pr, struct sockaddr *ip)
+struct sockaddr *
+prison_get_nonlocal(struct prison *pr, sa_family_t af, struct sockaddr *ip)
 {
-       struct jail_ip_storage *jis;
-       struct sockaddr_in *jip4, *ip4;
-       struct sockaddr_in6 *jip6, *ip6;
+       struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
+       struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
 
-       ip4 = (struct sockaddr_in *)ip;
-       ip6 = (struct sockaddr_in6 *)ip;
        /* Check if it is cached */
-       switch(ip->sa_family) {
-               case AF_INET:
-                       /* -1 Means that we don't have any address */
-                       if (pr->nonlocal_ip4 == (struct sockaddr_storage *)-1)
-                               return(0);
-                       if (pr->nonlocal_ip4 != NULL) {
-                               jip4 = (struct sockaddr_in *) pr->nonlocal_ip4;
-                               ip4->sin_addr.s_addr = jip4->sin_addr.s_addr;
-                       }
-               break;
-               case AF_INET6:
-                       /* -1 Means that we don't have any address */
-                       if (pr->nonlocal_ip6 == (struct sockaddr_storage *)-1)
-                               return(0);
-                       if (pr->nonlocal_ip6 != NULL) {
-                               jip6 = (struct sockaddr_in6 *) pr->nonlocal_ip6;
-                               ip6->sin6_addr = jip6->sin6_addr;
-                       }
-               break;
-       };
-       SLIST_FOREACH(jis, &pr->pr_ips, entries) {
-               switch (ip->sa_family) {
-               case AF_INET:
-                       jip4 = (struct sockaddr_in *) &jis->ip;
-                       if (jip4->sin_family == AF_INET &&
-    ((ntohl(jip4->sin_addr.s_addr) >> IN_CLASSA_NSHIFT) != IN_LOOPBACKNET)) {
-                               pr->nonlocal_ip4 = &jis->ip;
-                               ip4->sin_addr.s_addr = jip4->sin_addr.s_addr;
-                               return(1);
-                       }
-                       break;
-               case AF_INET6:
-                       jip6 = (struct sockaddr_in6 *) &jis->ip;
-                       if ( jip6->sin6_family == AF_INET6 &&
-                            !IN6_IS_ADDR_LOOPBACK(&jip6->sin6_addr)) {
-                               pr->nonlocal_ip6 = &jis->ip;
-                               ip6->sin6_addr = jip6->sin6_addr;
-                               return(1);
-                       }
-                       break;
-               }
+       switch(af) {
+       case AF_INET:
+               if (ip4 != NULL && pr->nonlocal_ip4 != NULL)
+                       ip4->sin_addr.s_addr = 
pr->nonlocal_ip4->sin_addr.s_addr;
+               return (struct sockaddr *)pr->nonlocal_ip4;
+
+       case AF_INET6:
+               if (ip6 != NULL && pr->nonlocal_ip6 != NULL)
+                       ip6->sin6_addr = pr->nonlocal_ip6->sin6_addr;
+               return (struct sockaddr *)pr->nonlocal_ip6;
        }
-       if (ip->sa_family == AF_INET)
-               pr->nonlocal_ip4 = (struct sockaddr_storage *)-1;
-       else
-               pr->nonlocal_ip6 = (struct sockaddr_storage *)-1;
-       return(0);
+
+       /* NOTREACHED */
+       return NULL;
 }
 
 /*
  * Prison get loopback ip.
- * Put on *ip the first loopback IP address.
- * af is the address family of the ip we want (AF_INET|PF_INET).
- * *ip is in network by order and we don't touch it unless we find a valid ip.
- * return 1 if we've found a loopback ip, else return 0.
+ * - af is the address family of the ip we want (AF_INET|AF_INET6).
+ * - If ip != NULL, put the first IP address that is not a loopback address
+ *   into *ip.
+ *
+ * ip is in network by order and we don't touch it unless we find a valid ip.
+ * No matter if ip == NULL or not, we return either a valid struct sockaddr *,
+ * or NULL.  This struct may not be modified.
  */
-int
-prison_get_local(struct prison *pr, struct sockaddr *ip)
+struct sockaddr *
+prison_get_local(struct prison *pr, sa_family_t af, struct sockaddr *ip)
 {
-       struct jail_ip_storage *jis;
-       struct sockaddr_in *jip4, *ip4;
-       struct sockaddr_in6 *jip6, *ip6;
+       struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
+       struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
 
-       ip4 = (struct sockaddr_in *)ip;
-       ip6 = (struct sockaddr_in6 *)ip;
        /* Check if it is cached */
-       switch(ip->sa_family) {
-               case AF_INET:
-                       /* -1 Means that we don't have any address */
-                       if (pr->local_ip4 == (struct sockaddr_storage *)-1)
-                               return(0);
-                       if (pr->local_ip4 != NULL) {
-                               jip4 = (struct sockaddr_in *) pr->local_ip4;
-                               ip4->sin_addr.s_addr = jip4->sin_addr.s_addr;
-                       }
-               break;
-               case AF_INET6:
-                       /* -1 Means that we don't have any address */
-                       if (pr->local_ip6 == (struct sockaddr_storage *)-1)
-                               return(0);
-                       if (pr->local_ip6 != NULL) {
-                               jip6 = (struct sockaddr_in6 *) pr->local_ip6;
-                               ip6->sin6_addr = jip6->sin6_addr;
-                       }
-               break;
-       };
-       SLIST_FOREACH(jis, &pr->pr_ips, entries) {
-               switch(ip->sa_family) {
-               case AF_INET:
-                       jip4 = (struct sockaddr_in *) &jis->ip;
-                       if (jip4->sin_family == AF_INET &&
-                           ((ntohl(jip4->sin_addr.s_addr) >> IN_CLASSA_NSHIFT)
-                           == IN_LOOPBACKNET)) {
-                               pr->local_ip4 = &jis->ip;
-                               ip4->sin_addr.s_addr = jip4->sin_addr.s_addr;
-                               return(1);
-                       }
-                       break;
-               case AF_INET6:
-                       jip6 = (struct sockaddr_in6 *) &jis->ip;
-                       if (jip6->sin6_family == AF_INET6 &&
-                            IN6_IS_ADDR_LOOPBACK(&jip6->sin6_addr)) {
-                               pr->local_ip6 = &jis->ip;
-                               ip6->sin6_addr = jip6->sin6_addr;
-                               return(1);
-                       }
-                       break;
-               }
+       switch(af) {
+       case AF_INET:
+               if (ip4 != NULL && pr->local_ip4 != NULL)
+                       ip4->sin_addr.s_addr = pr->local_ip4->sin_addr.s_addr;
+               return (struct sockaddr *)pr->local_ip4;
+
+       case AF_INET6:
+               if (ip6 != NULL && pr->local_ip6 != NULL)
+                       ip6->sin6_addr = pr->local_ip6->sin6_addr;
+               return (struct sockaddr *)pr->local_ip6;
        }
-       if (ip->sa_family == AF_INET)
-               pr->local_ip4 = (struct sockaddr_storage *)-1;
-       else
-               pr->local_ip6 = (struct sockaddr_storage *)-1;
-       return(0);
+
+       /* NOTREACHED */
+       return NULL;
 }
 
 /* Check if the IP is among ours, if it is return 1, else 0 */
Index: netinet/in_pcb.c
===================================================================
RCS file: /home/dcvs/src/sys/netinet/in_pcb.c,v
retrieving revision 1.41
diff -u -p -r1.41 in_pcb.c
--- netinet/in_pcb.c    29 Dec 2006 18:02:56 -0000      1.41
+++ netinet/in_pcb.c    17 Jan 2007 12:58:07 -0000
@@ -457,7 +457,7 @@ in_pcbladdr(struct inpcb *inp, struct so
        struct in_ifaddr *ia;
        struct ucred *cred = NULL;
        struct sockaddr_in *sin = (struct sockaddr_in *)nam;
-       struct sockaddr_in jsin;
+       struct sockaddr *jsin;
        int jailed = 0;
 
        if (nam->sa_len != sizeof *sin)
@@ -579,14 +579,13 @@ in_pcbladdr(struct inpcb *inp, struct so
                 * Don't do pcblookup call here; return interface in plocal_sin
                 * and exit to caller, that will do the lookup.
                 */
-               if (jailed) {
-                       jsin.sin_family = AF_INET;
-                       if (!prison_get_nonlocal(cred->cr_prison,
-                           sintosa(&jsin)) &&
-                           !prison_get_local(cred->cr_prison, sintosa(&jsin)))
-                                       /* IPv6 only Jail */
-                                       return (EADDRNOTAVAIL);
-                       *plocal_sin = &jsin;
+               if (ia == NULL && jailed) {
+                       if ((jsin = prison_get_nonlocal(cred->cr_prison, 
AF_INET, NULL)) != NULL ||
+                           (jsin = prison_get_local(cred->cr_prison, AF_INET, 
NULL)) != NULL)
+                               *plocal_sin = satosin(jsin);
+                       else
+                               /* IPv6 only Jail */
+                               return (EADDRNOTAVAIL);
                } else {
                        *plocal_sin = &ia->ia_addr;
                }

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to