]> git.saurik.com Git - apple/libinfo.git/commitdiff
Libinfo-129.tar.gz mac-os-x-102 v129
authorApple <opensource@apple.com>
Sat, 27 Jul 2002 18:24:28 +0000 (18:24 +0000)
committerApple <opensource@apple.com>
Sat, 27 Jul 2002 18:24:28 +0000 (18:24 +0000)
155 files changed:
Makefile
PB.project
dns.subproj/gethnamaddr.c
dns.subproj/getnetbyaddr.c
dns.subproj/getnetbyname.c
dns.subproj/getnetent.c
dns.subproj/getnetnamadr.c
dns.subproj/herror.c
dns.subproj/inet.h
dns.subproj/res_comp.c
dns.subproj/res_debug.c
dns.subproj/res_init.c
gen.subproj/Makefile
gen.subproj/Makefile.postamble [new file with mode: 0644]
gen.subproj/Makefile.preamble
gen.subproj/PB.project
gen.subproj/fstab.c
gen.subproj/getaddrinfo.3 [new file with mode: 0644]
gen.subproj/getaddrinfo.c
gen.subproj/getgrent.c
gen.subproj/gethostbyname.3 [new file with mode: 0644]
gen.subproj/getifaddrs.3 [new file with mode: 0644]
gen.subproj/getifaddrs.c [new file with mode: 0644]
gen.subproj/getipnodebyname.3 [new file with mode: 0644]
gen.subproj/getnameinfo.3 [new file with mode: 0644]
gen.subproj/getnameinfo.c [new file with mode: 0644]
gen.subproj/getnetent.3 [new file with mode: 0644]
gen.subproj/getproto.c
gen.subproj/getprotoent.3 [new file with mode: 0644]
gen.subproj/getprotoent.c
gen.subproj/getprotoname.c
gen.subproj/getservbyname.c
gen.subproj/getservbyport.c
gen.subproj/getservent.3 [new file with mode: 0644]
gen.subproj/getservent.c
gen.subproj/if_indextoname.3 [new file with mode: 0644]
gen.subproj/if_indextoname.c [new file with mode: 0644]
gen.subproj/if_nameindex.c [new file with mode: 0644]
gen.subproj/if_nametoindex.c [new file with mode: 0644]
gen.subproj/ifaddrs.h [new file with mode: 0644]
gen.subproj/inet6_option_space.3 [new file with mode: 0644]
gen.subproj/inet6_rthdr_space.3 [new file with mode: 0644]
gen.subproj/inet_ntop.c [new file with mode: 0644]
gen.subproj/inet_pton.c [new file with mode: 0644]
gen.subproj/initgroups.c
gen.subproj/ip6opt.c [new file with mode: 0644]
gen.subproj/linkaddr.3 [new file with mode: 0644]
gen.subproj/map_v4v6.c [new file with mode: 0644]
gen.subproj/printerdb.c
gen.subproj/rthdr.c [new file with mode: 0644]
gen.subproj/vars.c [new file with mode: 0644]
lookup.subproj/Makefile
lookup.subproj/Makefile.postamble
lookup.subproj/Makefile.preamble
lookup.subproj/PB.project
lookup.subproj/lookup.defs
lookup.subproj/lu_alias.c
lookup.subproj/lu_bootp.c
lookup.subproj/lu_bootparam.c
lookup.subproj/lu_fstab.c
lookup.subproj/lu_group.c
lookup.subproj/lu_host.c
lookup.subproj/lu_host.h [new file with mode: 0644]
lookup.subproj/lu_host_async.c [new file with mode: 0644]
lookup.subproj/lu_netgroup.c
lookup.subproj/lu_network.c
lookup.subproj/lu_printer.c
lookup.subproj/lu_protocol.c
lookup.subproj/lu_rpc.c
lookup.subproj/lu_service.c
lookup.subproj/lu_user.c
lookup.subproj/lu_utils.c
lookup.subproj/lu_utils.h
lookup.subproj/netdb_async.h [new file with mode: 0644]
mdns.subproj/DNSServiceDiscovery.c [new file with mode: 0644]
mdns.subproj/DNSServiceDiscovery.h [new file with mode: 0644]
mdns.subproj/DNSServiceDiscoveryDefines.h [new file with mode: 0644]
mdns.subproj/DNSServiceDiscoveryReply.defs [new file with mode: 0644]
mdns.subproj/DNSServiceDiscoveryRequest.defs [new file with mode: 0644]
mdns.subproj/Makefile [new file with mode: 0644]
mdns.subproj/Makefile.postamble [new file with mode: 0644]
mdns.subproj/Makefile.preamble [new file with mode: 0644]
mdns.subproj/PB.project [new file with mode: 0644]
netinfo.subproj/Makefile
netinfo.subproj/Makefile.postamble
netinfo.subproj/Makefile.preamble
netinfo.subproj/PB.project
netinfo.subproj/netinfo.3 [new file with mode: 0644]
netinfo.subproj/netinfo.5 [new file with mode: 0644]
netinfo.subproj/ni_glue.c
netinfo.subproj/ni_util.c
netinfo.subproj/sys_interfaces.c
netinfo.subproj/sys_interfaces.h
nis.subproj/Makefile
nis.subproj/Makefile.preamble
nis.subproj/PB.project
nis.subproj/innetgr.c
nis.subproj/yp_all.3 [new file with mode: 0644]
nis.subproj/yp_bind.3 [new file with mode: 0644]
nis.subproj/yp_first.3 [new file with mode: 0644]
nis.subproj/yp_get_default_domain.3 [new file with mode: 0644]
nis.subproj/yp_master.3 [new file with mode: 0644]
nis.subproj/yp_match.3 [new file with mode: 0644]
nis.subproj/yp_next.3 [new file with mode: 0644]
nis.subproj/yp_order.3 [new file with mode: 0644]
nis.subproj/yp_unbind.3 [new file with mode: 0644]
nis.subproj/ypclnt.3 [new file with mode: 0644]
nis.subproj/yperr_string.3 [new file with mode: 0644]
nis.subproj/yppasswdd_xdr.c
nis.subproj/ypprot_err.3 [new file with mode: 0644]
nis.subproj/ypserv.acl.5 [new file with mode: 0644]
rpc.subproj/auth_none.c
rpc.subproj/auth_unix.c
rpc.subproj/authunix_prot.c
rpc.subproj/bindresvport.c
rpc.subproj/clnt_generic.c
rpc.subproj/clnt_perror.c
rpc.subproj/clnt_raw.c
rpc.subproj/clnt_simple.c
rpc.subproj/clnt_tcp.c
rpc.subproj/clnt_udp.c
rpc.subproj/get_myaddress.c
rpc.subproj/getrpcent.c
rpc.subproj/getrpcport.c
rpc.subproj/pmap_clnt.c
rpc.subproj/pmap_getmaps.c
rpc.subproj/pmap_getport.c
rpc.subproj/pmap_prot2.c
rpc.subproj/pmap_rmt.c
rpc.subproj/rpc_callmsg.c
rpc.subproj/rpc_commondata.c
rpc.subproj/rpc_dtablesize.c
rpc.subproj/svc.c
rpc.subproj/svc_auth.c
rpc.subproj/svc_auth_unix.c
rpc.subproj/svc_raw.c
rpc.subproj/svc_run.c
rpc.subproj/svc_simple.c
rpc.subproj/svc_tcp.c
rpc.subproj/svc_udp.c
rpc.subproj/types.h
rpc.subproj/xdr.c
rpc.subproj/xdr_array.c
rpc.subproj/xdr_mem.c
rpc.subproj/xdr_rec.c
rpc.subproj/xdr_reference.c
util.subproj/Makefile
util.subproj/Makefile.postamble [new file with mode: 0644]
util.subproj/Makefile.preamble [new file with mode: 0644]
util.subproj/PB.project
util.subproj/getgrouplist.c
util.subproj/pwcache.c
util.subproj/rcmd.3 [new file with mode: 0644]
util.subproj/rcmd.c
util.subproj/rcmdsh.c

index 578460079a4fb42449fb52c98fe15526de3095f2..cbb3bca5e808b1a5bbaa3b869dfb50a0c84261df 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
 #
-# Generated by the NeXT Project Builder.
+# Generated by the Apple Project Builder.
 #
 # NOTE: Do NOT change this file -- Project Builder maintains it.
 #
@@ -13,7 +13,7 @@ PROJECTVERSION = 2.8
 PROJECT_TYPE = Library
 
 SUBPROJECTS = dns.subproj gen.subproj lookup.subproj netinfo.subproj\
-              nis.subproj rpc.subproj util.subproj
+              nis.subproj rpc.subproj util.subproj mdns.subproj
 
 OTHERSRCS = Makefile.preamble Makefile Makefile.postamble
 
index 5ebc657aa16a90b2e24a6248add688a084fc676f..bda43305c35504db20c86c9ae571cd85cd5bbf3f 100644 (file)
             netinfo.subproj, 
             nis.subproj, 
             rpc.subproj, 
-            util.subproj
+            util.subproj, 
+            mdns.subproj
         ); 
     }; 
     LANGUAGE = English; 
     MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
-    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_BUILDTOOL = /usr/bin/gnumake; 
     NEXTSTEP_INSTALLDIR = /usr/local/lib/system; 
     NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
     NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
-    NEXTSTEP_PUBLICHEADERSDIR = /usr/include;
+    NEXTSTEP_PUBLICHEADERSDIR = /usr/include; 
     PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
     PDO_UNIX_INSTALLDIR = /lib; 
     PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; 
index 1d6aba593cb6fe7d3c36c60e2fdac497df254592..250a3c4cbfe65c91fa5c3c5baf7ae903a4a6c656 100644 (file)
@@ -78,7 +78,7 @@
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)gethostnamadr.c    8.1 (Berkeley) 6/4/93";
-static char rcsid[] = "$Id: gethnamaddr.c,v 1.2 1999/10/14 21:56:44 wsanchez Exp $";
+static char rcsid[] = "$Id: gethnamaddr.c,v 1.6 2002/06/13 01:04:37 majka Exp $";
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/param.h>
@@ -88,6 +88,7 @@ static char rcsid[] = "$Id: gethnamaddr.c,v 1.2 1999/10/14 21:56:44 wsanchez Exp
 #include <arpa/nameser.h>
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <netdb.h>
 #include <resolv.h>
 #include <ctype.h>
@@ -111,6 +112,7 @@ static char rcsid[] = "$Id: gethnamaddr.c,v 1.2 1999/10/14 21:56:44 wsanchez Exp
 
 #define        MAXALIASES      35
 #define        MAXADDRS        35
+#define        MAXHOSTBUF      8*1024
 
 static const char AskedForGot[] =
                          "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
@@ -120,7 +122,7 @@ static struct hostent *gethostbyname_ipv4 __P((const char *));
 
 static struct hostent host;
 static char *host_aliases[MAXALIASES];
-static char hostbuf[8*1024];
+static char *hostbuf = NULL;
 static struct in_addr host_addr;
 static FILE *hostf = NULL;
 static int stayopen = 0;
@@ -147,6 +149,8 @@ typedef union {
 
 extern int h_errno;
 
+extern int _lu_running(void);
+
 #ifdef DEBUG
 static void
 dprintf(msg, num)
@@ -182,6 +186,13 @@ getanswer(answer, anslen, qname, qclass, qtype)
        char tbuf[MAXDNAME+1];
        const char *tname;
 
+       if (hostbuf == NULL) {
+               hostbuf = malloc(MAXHOSTBUF);
+               if (hostbuf == NULL)
+                       return (NULL);
+       }
+       buflen = MAXHOSTBUF;
+
        tname = qname;
        host.h_name = NULL;
        eom = answer->buf + anslen;
@@ -192,7 +203,6 @@ getanswer(answer, anslen, qname, qclass, qtype)
        ancount = ntohs(hp->ancount);
        qdcount = ntohs(hp->qdcount);
        bp = hostbuf;
-       buflen = sizeof hostbuf;
        cp = answer->buf + HFIXEDSZ;
        if (qdcount != 1) {
                h_errno = NO_RECOVERY;
@@ -361,7 +371,7 @@ getanswer(answer, anslen, qname, qclass, qtype)
 
                        bp += sizeof(align) - ((u_long)bp % sizeof(align));
 
-                       if (bp + n >= &hostbuf[sizeof hostbuf]) {
+                       if (bp + n >= &hostbuf[MAXHOSTBUF]) {
                                dprintf("size (%d) too big\n", n);
                                had_error++;
                                continue;
@@ -437,13 +447,18 @@ gethostbyname2(name, af)
        const char *name;
        int af;
 {
-       switch (af) {
-       case AF_INET:
-               return (gethostbyname_ipv4(name));
+       if (_lu_running())
+       {
+               return getipnodebyname(name, af, 0, &h_errno);
+       }
+       else
+       {
+               if (af == AF_INET) return gethostbyname_ipv4(name);
+
+               errno = EAFNOSUPPORT;
+               h_errno = NETDB_INTERNAL;
+               return NULL;
        }
-       errno = EAFNOSUPPORT;
-       h_errno = NETDB_INTERNAL;
-       return (NULL);
 }
 
 static struct hostent *
@@ -457,6 +472,15 @@ gethostbyname_ipv4(name)
        extern struct hostent *_gethtbyname();
 #endif /* !NeXT */
 
+       if (hostbuf == NULL)
+       {
+               hostbuf = malloc(MAXHOSTBUF);
+               if (hostbuf == NULL) {
+                       h_errno = NETDB_INTERNAL;
+                       return (NULL);
+               }
+       }
+
        if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
                h_errno = NETDB_INTERNAL;
                return (NULL);
@@ -633,8 +657,15 @@ _gethtent()
                h_errno = NETDB_INTERNAL;
                return (NULL);
        }
+       if (hostbuf == NULL) {
+               hostbuf = malloc(MAXHOSTBUF);
+               if (hostbuf == NULL) {
+                       h_errno = NETDB_INTERNAL;
+                       return (NULL);
+               }
+       }
 again:
-       if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) {
+       if (!(p = fgets(hostbuf, MAXHOSTBUF, hostf))) {
                h_errno = HOST_NOT_FOUND;
                return (NULL);
        }
@@ -662,7 +693,7 @@ again:
                cp++;
        host.h_name = cp;
        q = host.h_aliases = host_aliases;
-       if (cp = strpbrk(cp, " \t"))
+       if ((cp = strpbrk(cp, " \t")))
                *cp++ = '\0';
        while (cp && *cp) {
                if (*cp == ' ' || *cp == '\t') {
@@ -671,7 +702,7 @@ again:
                }
                if (q < &host_aliases[MAXALIASES - 1])
                        *q++ = cp;
-               if (cp = strpbrk(cp, " \t"))
+               if ((cp = strpbrk(cp, " \t")))
                        *cp++ = '\0';
        }
        *q = NULL;
@@ -687,7 +718,7 @@ _gethtbyname(name)
        register char **cp;
        
        _sethtent(0);
-       while (p = _gethtent()) {
+       while ((p = _gethtent())) {
                if (strcasecmp(p->h_name, name) == 0)
                        break;
                for (cp = p->h_aliases; *cp != 0; cp++)
@@ -707,7 +738,7 @@ _gethtbyaddr(addr, len, type)
        register struct hostent *p;
 
        _sethtent(0);
-       while (p = _gethtent())
+       while ((p = _gethtent()))
                if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len))
                        break;
        _endhtent();
index 415aa1b485dcf97b7014646f882104493b6e7057..94068094944db91e96638e926764756235329143 100644 (file)
@@ -56,7 +56,7 @@
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)getnetbyaddr.c     1.1 (Coimbra) 93/06/02";
-static char rcsid[] = "$Id: getnetbyaddr.c,v 1.2 1999/10/14 21:56:44 wsanchez Exp $";
+static char rcsid[] = "$Id: getnetbyaddr.c,v 1.3 2002/02/19 20:36:12 epeyton Exp $";
 #endif /* LIBC_SCCS and not lint */
 
 #include <netdb.h>
@@ -71,7 +71,7 @@ _getnetbyaddr(net, type)
        register struct netent *p;
 
        setnetent(_net_stayopen);
-       while (p = getnetent())
+       while ((p = getnetent()))
                if (p->n_addrtype == type && p->n_net == net)
                        break;
        if (!_net_stayopen)
index fe5ac4d4c26102a599d2407c2f80bd4e56a808bd..24cf4a6c0b9247ad2ff66f6aa4eb806570c4b894 100644 (file)
@@ -57,7 +57,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)getnetbyname.c     8.1 (Berkeley) 6/4/93";
 static char sccsid_[] = "from getnetbyname.c   1.1 (Coimbra) 93/06/02";
-static char rcsid[] = "$Id: getnetbyname.c,v 1.2 1999/10/14 21:56:44 wsanchez Exp $";
+static char rcsid[] = "$Id: getnetbyname.c,v 1.3 2002/02/19 20:36:12 epeyton Exp $";
 #endif /* LIBC_SCCS and not lint */
 
 #include <netdb.h>
@@ -73,7 +73,7 @@ _getnetbyname(name)
        register char **cp;
 
        setnetent(_net_stayopen);
-       while (p = getnetent()) {
+       while ((p = getnetent())) {
                if (strcasecmp(p->n_name, name) == 0)
                        break;
                for (cp = p->n_aliases; *cp != 0; cp++)
index 00f9d6e294c98747b7ab67c3bf15116ef809339d..9240a1b918adc957b5a217979497ad8a02d6aa0c 100644 (file)
@@ -66,7 +66,7 @@
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)getnetent.c        8.1 (Berkeley) 6/4/93";
-static char rcsid[] = "$Id: getnetent.c,v 1.2 1999/10/14 21:56:44 wsanchez Exp $";
+static char rcsid[] = "$Id: getnetent.c,v 1.3 2002/06/12 17:40:29 epeyton Exp $";
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/param.h>
@@ -76,6 +76,7 @@ static char rcsid[] = "$Id: getnetent.c,v 1.2 1999/10/14 21:56:44 wsanchez Exp $
 #include <arpa/nameser.h>
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <resolv.h>
 #include <netdb.h>
 #include <string.h>
@@ -87,7 +88,6 @@ static char rcsid[] = "$Id: getnetent.c,v 1.2 1999/10/14 21:56:44 wsanchez Exp $
 #define        MAXALIASES      35
 
 static FILE *netf;
-static char line[BUFSIZ+1];
 static struct netent net;
 static char *net_aliases[MAXALIASES];
 #if defined(__APPLE__)
@@ -142,10 +142,17 @@ struct netent *
 getnetent()
 {
        char *p;
+       static char *line = NULL;
        register char *cp, **q;
 
        if (netf == NULL && (netf = fopen(_PATH_NETWORKS, "r" )) == NULL)
                return (NULL);
+
+       if (line == NULL) {
+               line = malloc(BUFSIZ+1);
+               if (line == NULL)
+                       return (NULL);
+       }
 again:
        p = fgets(line, BUFSIZ, netf);
        if (p == NULL)
index f3d3265a4f61a11fdea57751268e2a6d8652c4d1..40bc224bb5ba59fdd759e5abb0d283a4c4d2721f 100644 (file)
@@ -64,7 +64,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)getnetbyaddr.c     8.1 (Berkeley) 6/4/93";
 static char sccsid_[] = "from getnetnamadr.c   1.4 (Coimbra) 93/06/03";
-static char rcsid[] = "$Id: getnetnamadr.c,v 1.2 1999/10/14 21:56:44 wsanchez Exp $";
+static char rcsid[] = "$Id: getnetnamadr.c,v 1.3 2002/06/12 17:40:29 epeyton Exp $";
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/param.h>
@@ -74,6 +74,7 @@ static char rcsid[] = "$Id: getnetnamadr.c,v 1.2 1999/10/14 21:56:44 wsanchez Ex
 #include <arpa/nameser.h>
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <netdb.h>
 #include <resolv.h>
 #include <ctype.h>
@@ -124,7 +125,14 @@ getnetanswer(answer, anslen, net_i)
        char aux1[30], aux2[30], ans[30], *in, *st, *pauxt, *bp, **ap,
                *paux1 = &aux1[0], *paux2 = &aux2[0], flag = 0;
 static struct netent net_entry;
-static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1];
+static char *net_aliases[MAXALIASES], *netbuf = NULL;
+
+       if (netbuf == NULL) {
+               netbuf = malloc(BUFSIZ+1);
+               if (netbuf == NULL)
+                       return (NULL);
+       }
+       buflen = BUFSIZ+1;
 
        /*
         * find first satisfactory answer
@@ -145,7 +153,6 @@ static      char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1];
        ancount = ntohs(hp->ancount); /* #/records in the answer section */
        qdcount = ntohs(hp->qdcount); /* #/entries in the question section */
        bp = netbuf;
-       buflen = sizeof(netbuf);
        cp = answer->buf + HFIXEDSZ;
        if (!qdcount) {
                if (hp->aa)
index dcfe6562eaa59d254cf9bddce677d31ac27786e2..580f847968b357191cd019c05364edf51f6d442d 100644 (file)
@@ -78,7 +78,7 @@
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)herror.c   8.1 (Berkeley) 6/4/93";
-static char rcsid[] = "$Id: herror.c,v 1.2 1999/10/14 21:56:44 wsanchez Exp $";
+static char rcsid[] = "$Id: herror.c,v 1.3 2002/02/19 20:36:12 epeyton Exp $";
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/param.h>
@@ -140,6 +140,6 @@ hstrerror(err)
        if (err < 0)
                return ("Resolver internal error");
        else if (err < h_nerr)
-               return (h_errlist[err]);
+               return ((char *)h_errlist[err]);
        return ("Unknown resolver error");
 }
index ae203b2b9a1c239339bb104f10572eaca59fb2a1..c07ca4fe2ef7279cbfed56a301c865440300e348 100644 (file)
@@ -78,7 +78,7 @@
 
 /*
  *     @(#)inet.h      8.1 (Berkeley) 6/2/93
- *     $Id: inet.h,v 1.2 1999/10/14 21:56:45 wsanchez Exp $
+ *     $Id: inet.h,v 1.3 2002/04/19 20:38:01 majka Exp $
  */
 
 #ifndef _INET_H_
@@ -102,6 +102,9 @@ struct in_addr       inet_makeaddr __P((u_long , u_long));
 unsigned long   inet_netof __P((struct in_addr));
 unsigned long   inet_network __P((const char *));
 char           *inet_ntoa __P((struct in_addr));
+int             inet_pton __P((int, const char *, void *));
+const char     *inet_ntop __P((int, const void *, char *, size_t));
+
 
 u_int   inet_nsap_addr __P((const char *, u_char *, int maxlen));
 char   *inet_nsap_ntoa __P((int, const u_char *, char *ascii));
index 7c07818e824039863501ffe3ec2721a77ce3ff36..805630dd566604618b5de5aee793b8fe4cac56db 100644 (file)
@@ -78,7 +78,7 @@
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93";
-static char rcsid[] = "$Id: res_comp.c,v 1.2 1999/10/14 21:56:45 wsanchez Exp $";
+static char rcsid[] = "$Id: res_comp.c,v 1.3 2002/02/19 20:36:12 epeyton Exp $";
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/param.h>
@@ -124,7 +124,7 @@ dn_expand(msg, eomorig, comp_dn, exp_dn, length)
        /*
         * fetch next label in domain name
         */
-       while (n = *cp++) {
+       while ((n = *cp++)) {
                /*
                 * Check for indirection
                 */
@@ -327,7 +327,7 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr)
        for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
                dn = exp_dn;
                sp = cp = *cpp;
-               while (n = *cp++) {
+               while ((n = *cp++)) {
                        /*
                         * check for indirection
                         */
index 519104a008d3f5e53e92593c39590d19e88060dd..656797de824362d03655d7b28ff7331940e21ae5 100644 (file)
@@ -78,7 +78,7 @@
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)res_debug.c        8.1 (Berkeley) 6/4/93";
-static char rcsid[] = "$Id: res_debug.c,v 1.2 1999/10/14 21:56:45 wsanchez Exp $";
+static char rcsid[] = "$Id: res_debug.c,v 1.3 2002/02/19 20:36:12 epeyton Exp $";
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/param.h>
@@ -233,7 +233,7 @@ do_rrset(msg, len, cp, cnt, pflag, file, hs)
         * Print answer records.
         */
        sflag = (_res.pfcode & pflag);
-       if (n = ntohs(cnt)) {
+       if ((n = ntohs(cnt))) {
                if ((!_res.pfcode) ||
                    ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
                        fprintf(file, hs);
@@ -359,7 +359,7 @@ __fp_nquery(msg, len, file)
        /*
         * Print question records.
         */
-       if (n = ntohs(hp->qdcount)) {
+       if ((n = ntohs(hp->qdcount))) {
                if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
                        fprintf(file, ";; QUESTIONS:\n");
                while (--n >= 0) {
@@ -547,7 +547,7 @@ __p_rr(cp, msg, file)
        case T_HINFO:
        case T_ISDN:
                cp2 = cp + dlen;
-               if (n = *cp++) {
+               if ((n = *cp++)) {
                        fprintf(file, "\t%.*s", n, cp);
                        cp += n;
                }
@@ -606,7 +606,7 @@ __p_rr(cp, msg, file)
                (void) fputs("\t\"", file);
                cp2 = cp1 + dlen;
                while (cp < cp2) {
-                       if (n = (unsigned char) *cp++) {
+                       if ((n = (unsigned char) *cp++)) {
                                for (c = n; c > 0 && cp < cp2; c--)
                                        if ((*cp == '\n') || (*cp == '"')) {
                                            (void) putc('\\', file);
index 5eb64dde03fb0ed4705b588815042295a78c615d..f9e8ad21ec77e92ba075769ed7a7d13fab28cae4 100644 (file)
@@ -78,7 +78,7 @@
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
-static char rcsid[] = "$Id: res_init.c,v 1.3 2000/08/01 23:12:13 lindak Exp $";
+static char rcsid[] = "$Id: res_init.c,v 1.5 2002/03/26 20:12:06 ajn Exp $";
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/param.h>
@@ -121,7 +121,7 @@ static char rcsid[] = "$Id: res_init.c,v 1.3 2000/08/01 23:12:13 lindak Exp $";
  * - Internal resolver variables can be set from the value of the "options"
  *   property.
  */
-#if defined(__APPLE__)
+#if defined(__APPLE__) && defined(CONFIGURE_RESOLVER_FROM_NETINFO)
 #  include <netinfo/ni.h>
 #  define NI_PATH_RESCONF "/locations/resolver"
 #  define NI_TIMEOUT 10
@@ -403,7 +403,7 @@ res_init()
 #endif
            (void) fclose(fp);
        }
-#ifdef __APPLE__
+#if defined(__APPLE__) && defined(CONFIGURE_RESOLVER_FROM_NETINFO)
        else netinfo_res_init(&haveenv, &havesearch);
 #endif
 
@@ -510,7 +510,7 @@ net_mask(in)                /* XXX - should really use system's version of this */
 }
 #endif
 
-#ifdef __APPLE__
+#if defined(__APPLE__) && defined(CONFIGURE_RESOLVER_FROM_NETINFO)
 static int
 netinfo_res_init(haveenv, havesearch)
        int *haveenv;
@@ -602,7 +602,7 @@ netinfo_res_init(haveenv, havesearch)
                    for (n = 0;
                         n < nl.ni_namelist_len && nsort < MAXRESOLVSORT;
                         n++) {
-                       char ch;
+                       char ch = '\0';
                        char *cp;
                        const char *sp;
                        struct in_addr a;
index 3e5945706b3cb17e315a34e905250633e11ba914..e05996d74e2ec30f09273e8cc9e28cab6d61f5a8 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Generated by the NeXT Project Builder.
+# Generated by the Apple Project Builder.
 #
 # NOTE: Do NOT change this file -- Project Builder maintains it.
 #
@@ -12,22 +12,36 @@ NAME = gen
 PROJECTVERSION = 2.8
 PROJECT_TYPE = Component
 
-CFILES = aliasdb.c ether_addr.c fstab.c getaddrinfo.c getgrent.c getproto.c\
-         getprotoent.c getprotoname.c getpwent.c getservbyname.c\
-         getservbyport.c getservent.c initgroups.c printerdb.c
+HFILES = ifaddrs.h
 
-OTHERSRCS = Makefile.preamble Makefile
+CFILES = aliasdb.c ether_addr.c fstab.c getaddrinfo.c getgrent.c\
+         getifaddrs.c getnameinfo.c getproto.c getprotoent.c\
+         getprotoname.c getpwent.c getservbyname.c getservbyport.c\
+         getservent.c if_indextoname.c if_nameindex.c if_nametoindex.c\
+         inet_ntop.c inet_pton.c initgroups.c printerdb.c\
+         map_v4v6.c ip6opt.c rthdr.c vars.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble getaddrinfo.3\
+            getifaddrs.3 if_indextoname.3 inet6_rthdr_space.3\
+            gethostbyname.3 getnameinfo.3 inet6_option_space.3\
+            linkaddr.3 getprotoent.3 gethostbyname.3 getipnodebyname.3\
+            getnetent.3 getservent.3 inet6_option_space.3
 
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
 CODE_GEN_STYLE = DYNAMIC
 MAKEFILE = subproj.make
+NEXTSTEP_INSTALLDIR = /usr/local/lib/system
 LIBS = 
 DEBUG_LIBS = $(LIBS)
 PROF_LIBS = $(LIBS)
 
 
+PUBLIC_HEADERS = ifaddrs.h
+
+
 
+NEXTSTEP_PUBLIC_HEADERS_DIR = /usr/include
 
 NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
 WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
diff --git a/gen.subproj/Makefile.postamble b/gen.subproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..cc40951
--- /dev/null
@@ -0,0 +1,165 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES    # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+#COMPATIBILITY_PROJECT_VERSION = 1
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wall
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User/group ownership 
+#INSTALL_AS_GROUP = wheel      # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S   # for .a archives
+#DYNAMIC_STRIP_OPTS = -S   # for bundles and shared libraries
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
+install-man-page:
+       mkdir -p "$(DSTROOT)/usr/share/man/man3"
+       install -c -m 644 getaddrinfo.3 "$(DSTROOT)/usr/share/man/man3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/getaddrinfo.3" "$(DSTROOT)/usr/share/man/man3/freeaddrinfo.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/getaddrinfo.3" "$(DSTROOT)/usr/share/man/man3/gai_strerror.3"
+       install -c -m 644 getnameinfo.3 "$(DSTROOT)/usr/share/man/man3"
+       install -c -m 644 gethostbyname.3 "$(DSTROOT)/usr/share/man/man3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/gethostbyname.3" "$(DSTROOT)/usr/share/man/man3/endhostent.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/gethostbyname.3" "$(DSTROOT)/usr/share/man/man3/gethostbyaddr.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/gethostbyname.3" "$(DSTROOT)/usr/share/man/man3/gethostbyname2.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/gethostbyname.3" "$(DSTROOT)/usr/share/man/man3/gethostent.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/gethostbyname.3" "$(DSTROOT)/usr/share/man/man3/herror.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/gethostbyname.3" "$(DSTROOT)/usr/share/man/man3/hstrerror.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/gethostbyname.3" "$(DSTROOT)/usr/share/man/man3/sethostent.3"
+       install -c -m 644 getifaddrs.3 "$(DSTROOT)/usr/share/man/man3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/getifaddrs.3" "$(DSTROOT)/usr/share/man/man3/freeifaddrs.3"
+       install -c -m 644 getipnodebyname.3 "$(DSTROOT)/usr/share/man/man3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/getipnodebyname.3" "$(DSTROOT)/usr/share/man/man3/freehostent.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/getipnodebyname.3" "$(DSTROOT)/usr/share/man/man3/getipnodebyaddr.3"
+       install -c -m 644 getnetent.3 "$(DSTROOT)/usr/share/man/man3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/getnetent.3" "$(DSTROOT)/usr/share/man/man3/endnetent.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/getnetent.3" "$(DSTROOT)/usr/share/man/man3/getnetbyaddr.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/getnetent.3" "$(DSTROOT)/usr/share/man/man3/getnetbyname.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/getnetent.3" "$(DSTROOT)/usr/share/man/man3/setnetent.3"
+       install -c -m 644 getprotoent.3 "$(DSTROOT)/usr/share/man/man3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/getprotoent.3" "$(DSTROOT)/usr/share/man/man3/endprotoent.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/getprotoent.3" "$(DSTROOT)/usr/share/man/man3/getprotobyname.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/getprotoent.3" "$(DSTROOT)/usr/share/man/man3/getprotobynumber.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/getprotoent.3" "$(DSTROOT)/usr/share/man/man3/setprotoent.3"
+       install -c -m 644 getservent.3 "$(DSTROOT)/usr/share/man/man3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/getservent.3" "$(DSTROOT)/usr/share/man/man3/endservent.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/getservent.3" "$(DSTROOT)/usr/share/man/man3/getservbyname.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/getservent.3" "$(DSTROOT)/usr/share/man/man3/getservbyport.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/getservent.3" "$(DSTROOT)/usr/share/man/man3/setservent.3"
+       install -c -m 644 if_indextoname.3 "$(DSTROOT)/usr/share/man/man3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/if_indextoname.3" "$(DSTROOT)/usr/share/man/man3/if_freenameindex.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/if_indextoname.3" "$(DSTROOT)/usr/share/man/man3/if_nameindex.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/if_indextoname.3" "$(DSTROOT)/usr/share/man/man3/if_nametoindex.3"
+       install -c -m 644 inet6_option_space.3 "$(DSTROOT)/usr/share/man/man3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_option_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_option_alloc.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_option_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_option_append.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_option_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_option_find.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_option_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_option_init.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_option_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_option_next.3"
+       install -c -m 644 inet6_rthdr_space.3 "$(DSTROOT)/usr/share/man/man3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_add.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_getaddr.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_getflags.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_init.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_lasthop.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_reverse.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_segments.3"
+       install -c -m 644 linkaddr.3 "$(DSTROOT)/usr/share/man/man3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/linkaddr.3" "$(DSTROOT)/usr/share/man/man3/link_addr.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/linkaddr.3" "$(DSTROOT)/usr/share/man/man3/link_ntoa.3"
index 8bcebdcf3fc195472c285cf26a12285ed45022d0..97b5bb5ccc8aeca52907b74948f086b1332b156d 100644 (file)
@@ -1,4 +1,6 @@
+AFTER_POSTINSTALL += install-man-page
 OTHER_CFLAGS = \
+       -DINET6=1 \
        -Dsetservent=_old_setservent \
        -Dgetservent=_old_getservent \
        -Dendservent=_old_endservent \
index 5e70c18f5985863223410e8f8e1815b5a6e33aa2..19a76169197e82c3294228592f00af317a1179f7 100644 (file)
@@ -1,13 +1,15 @@
 {
     DYNAMIC_CODE_GEN = YES; 
     FILESTABLE = {
-        H_FILES = (); 
+        H_FILES = (ifaddrs.h); 
         OTHER_LINKED = (
             aliasdb.c, 
             ether_addr.c, 
             fstab.c, 
             getaddrinfo.c, 
             getgrent.c, 
+            getifaddrs.c, 
+            getnameinfo.c, 
             getproto.c, 
             getprotoent.c, 
             getprotoname.c, 
             getservbyname.c, 
             getservbyport.c, 
             getservent.c, 
+            if_indextoname.c, 
+            if_nameindex.c, 
+            if_nametoindex.c, 
+            inet_ntop.c, 
+            inet_pton.c, 
             initgroups.c, 
-            printerdb.c
+            printerdb.c, 
+            map_v4v6.c, 
+            ip6opt.c, 
+            rthdr.c, 
+            vars.c
         ); 
-        OTHER_SOURCES = (Makefile.preamble, Makefile); 
+        OTHER_SOURCES = (
+            Makefile.preamble, 
+            Makefile, 
+            Makefile.postamble, 
+            getaddrinfo.3, 
+            getifaddrs.3, 
+            if_indextoname.3, 
+            inet6_rthdr_space.3, 
+            gethostbyname.3, 
+            getnameinfo.3, 
+            inet6_option_space.3, 
+            getprotoent.3, 
+            gethostbyname.3, 
+            getipnodebyname.3, 
+            getnetent.3, 
+            getservent.3, 
+            inet6_option_space.3, 
+            linkaddr.3
+        ); 
+        PUBLIC_HEADERS = (ifaddrs.h); 
     }; 
     LANGUAGE = English; 
     MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
-    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_BUILDTOOL = /usr/bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/local/lib/system; 
     NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
     NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    NEXTSTEP_PUBLICHEADERSDIR = /usr/include; 
     PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
     PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; 
     PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
index 09a2f7b1166fcd3a7a146529033f8e858b2e6429..5d8d78cbd4c5486a7851b5f0140c009bfdb50f26 100644 (file)
@@ -53,8 +53,7 @@ static char _root_fstype[MFSNAMELEN];
 static int firstTime = 1;
 static int returnedRoot = 0;
 static void error __P((int));
-static fstabscan __P((void));
-static char *getRootDev(void);
+static int fstabscan __P((void));
 static const char *slash = "/";
 static const char *remountedroot = "/root";
 
@@ -66,9 +65,15 @@ static const char *remountedroot = "/root";
 */
 
 static char *getDevPath(dev_t target_dev) {
-    static char dev[MAXPATHLEN];
+    static char *dev = NULL;
     char *name;
 
+    if (dev == NULL) {
+       dev = malloc(MAXPATHLEN);
+       if (dev == NULL)
+           return NULL;
+    }
+
     strcpy(dev, _PATH_DEV);
 
     /* The root device in fstab should always be a block special device */
@@ -106,10 +111,9 @@ static char *getDevPath(dev_t target_dev) {
 
 static int initrootentry(struct fstab *rootentry)
 {
-     char *rootpath = slash;
+     char *rootpath = (char *)slash;
      struct stat rootstat;
      struct statfs rootfsinfo;
-     char *rootdevname;
      
      if (stat(rootpath, &rootstat) < 0) {
         perror("stat");
@@ -122,7 +126,7 @@ static int initrootentry(struct fstab *rootentry)
      
      /* Check to make sure we're not looking at a synthetic root: */
      if (strcmp(rootfsinfo.f_fstypename, "synthfs") == 0) {
-       rootpath = remountedroot;
+       rootpath = (char *)remountedroot;
         if (stat(rootpath, &rootstat) < 0) {
            perror("stat");
            return -1;
@@ -151,7 +155,7 @@ static int fstabscan()
 {
        register char *cp;
 #define        MAXLINELENGTH   1024
-       static char line[MAXLINELENGTH];
+       static char *line = NULL;
        char subline[MAXLINELENGTH];
        int typexx;
 
@@ -169,6 +173,13 @@ static int fstabscan()
        if (!_fs_fp) {
                return(0);
        }
+
+       if (line == NULL) {
+               line = malloc(MAXLINELENGTH);
+               if (line == NULL)
+                       return 0;
+       }
+
         for (;;) {
                if (!(cp = fgets(line, sizeof(line), _fs_fp)))
                        return(0);
diff --git a/gen.subproj/getaddrinfo.3 b/gen.subproj/getaddrinfo.3
new file mode 100644 (file)
index 0000000..c51fcac
--- /dev/null
@@ -0,0 +1,612 @@
+.\"    $FreeBSD: src/lib/libc/net/getaddrinfo.3,v 1.2.2.8 2001/08/17 15:42:38 ru Exp $
+.\"    $KAME: getaddrinfo.3,v 1.22 2000/08/09 21:16:17 itojun Exp $
+.\"
+.\" Copyright (c) 1983, 1987, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     From: @(#)gethostbyname.3      8.4 (Berkeley) 5/25/95
+.\"
+.Dd May 25, 1995
+.Dt GETADDRINFO 3
+.Os
+.\"
+.Sh NAME
+.Nm getaddrinfo ,
+.Nm freeaddrinfo ,
+.Nm gai_strerror
+.Nd nodename-to-address translation in protocol-independent manner
+.\"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/socket.h>
+.Fd #include <netdb.h>
+.Ft int
+.Fn getaddrinfo "const char *nodename" "const char *servname" \
+"const struct addrinfo *hints" "struct addrinfo **res"
+.Ft void
+.Fn freeaddrinfo "struct addrinfo *ai"
+.Ft "char *"
+.Fn gai_strerror "int ecode"
+.\"
+.Sh DESCRIPTION
+The
+.Fn getaddrinfo
+function is defined for protocol-independent nodename-to-address translation.
+It performs the functionality of
+.Xr gethostbyname 3
+and
+.Xr getservbyname 3 ,
+but in a more sophisticated manner.
+.Pp
+The
+.Li addrinfo
+structure is defined as a result of including the
+.Aq Pa netdb.h
+header:
+.Bd -literal -offset
+struct addrinfo {
+     int     ai_flags;     /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
+     int     ai_family;    /* PF_xxx */
+     int     ai_socktype;  /* SOCK_xxx */
+     int     ai_protocol;  /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+     size_t  ai_addrlen;   /* length of ai_addr */
+     char   *ai_canonname; /* canonical name for nodename */
+     struct sockaddr  *ai_addr; /* binary address */
+     struct addrinfo  *ai_next; /* next structure in linked list */
+};
+.Ed
+.Pp
+The
+.Fa nodename
+and
+.Fa servname
+arguments are pointers to null-terminated strings or
+.Dv NULL .
+One or both of these two arguments must be a
+.Pf non Dv -NULL
+pointer.
+In the normal client scenario, both the
+.Fa nodename
+and
+.Fa servname
+are specified.
+In the normal server scenario, only the
+.Fa servname
+is specified.
+A
+.Pf non Dv -NULL
+.Fa nodename
+string can be either a node name or a numeric host address string
+(i.e., a dotted-decimal IPv4 address or an IPv6 hex address).
+A
+.Pf non Dv -NULL
+.Fa servname
+string can be either a service name or a decimal port number.
+.Pp
+The caller can optionally pass an
+.Li addrinfo
+structure, pointed to by the third argument,
+to provide hints concerning the type of socket that the caller supports.
+In this
+.Fa hints
+structure all members other than
+.Fa ai_flags ,
+.Fa ai_family ,
+.Fa ai_socktype ,
+and
+.Fa ai_protocol
+must be zero or a
+.Dv NULL
+pointer.
+A value of
+.Dv PF_UNSPEC
+for
+.Fa ai_family
+means the caller will accept any protocol family.
+A value of 0 for
+.Fa ai_socktype
+means the caller will accept any socket type.
+A value of 0 for
+.Fa ai_protocol
+means the caller will accept any protocol.
+For example, if the caller handles only TCP and not UDP, then the
+.Fa ai_socktype
+member of the hints structure should be set to
+.Dv SOCK_STREAM
+when
+.Fn getaddrinfo
+is called.
+If the caller handles only IPv4 and not IPv6, then the
+.Fa ai_family
+member of the
+.Fa hints
+structure should be set to
+.Dv PF_INET
+when
+.Fn getaddrinfo
+is called.
+If the third argument to
+.Fn getaddrinfo
+is a
+.Dv NULL
+pointer, this is the same as if the caller had filled in an
+.Li addrinfo
+structure initialized to zero with
+.Fa ai_family
+set to
+.Dv PF_UNSPEC .
+.Pp
+Upon successful return a pointer to a linked list of one or more
+.Li addrinfo
+structures is returned through the final argument.
+The caller can process each
+.Li addrinfo
+structure in this list by following the
+.Fa ai_next
+pointer, until a
+.Dv NULL
+pointer is encountered.
+In each returned
+.Li addrinfo
+structure the three members
+.Fa ai_family ,
+.Fa ai_socktype ,
+and
+.Fa ai_protocol
+are the corresponding arguments for a call to the
+.Fn socket
+function.
+In each
+.Li addrinfo
+structure the
+.Fa ai_addr
+member points to a filled-in socket address structure whose length is
+specified by the
+.Fa ai_addrlen
+member.
+.Pp
+If the
+.Dv AI_PASSIVE
+bit is set in the
+.Fa ai_flags
+member of the
+.Fa hints
+structure, then the caller plans to use the returned socket address
+structure in a call to
+.Fn bind .
+In this case, if the
+.Fa nodename
+argument is a
+.Dv NULL
+pointer, then the IP address portion of the socket
+address structure will be set to
+.Dv INADDR_ANY
+for an IPv4 address or
+.Dv IN6ADDR_ANY_INIT
+for an IPv6 address.
+.Pp
+If the
+.Dv AI_PASSIVE
+bit is not set in the
+.Fa ai_flags
+member of the
+.Fa hints
+structure, then the returned socket address structure will be ready for a
+call to
+.Fn connect
+(for a connection-oriented protocol)
+or either
+.Fn connect ,
+.Fn sendto ,
+or
+.Fn sendmsg
+(for a connectionless protocol).
+In this case, if the
+.Fa nodename
+argument is a
+.Dv NULL
+pointer, then the IP address portion of the
+socket address structure will be set to the loopback address.
+.Pp
+If the
+.Dv AI_CANONNAME
+bit is set in the
+.Fa ai_flags
+member of the
+.Fa hints
+structure, then upon successful return the
+.Fa ai_canonname
+member of the first
+.Li addrinfo
+structure in the linked list will point to a null-terminated string
+containing the canonical name of the specified
+.Fa nodename .
+.Pp
+If the
+.Dv AI_NUMERICHOST
+bit is set in the
+.Fa ai_flags
+member of the
+.Fa hints
+structure, then a
+.Pf non Dv -NULL
+.Fa nodename
+string must be a numeric host address string.
+Otherwise an error of
+.Dv EAI_NONAME
+is returned.
+This flag prevents any type of name resolution service (e.g., the DNS)
+from being called.
+.Pp
+The arguments to
+.Fn getaddrinfo
+must be sufficiently consistent and unambiguous.
+Here are some problem cases you may encounter:
+.Bl -bullet
+.It
+.Fn getaddrinfo
+will fail if the members in the
+.Fa hints
+structure are not consistent.
+For example, for internet address families,
+.Fn getaddrinfo
+will fail if you specify
+.Dv SOCK_STREAM
+to
+.Fa ai_socktype
+while you specify
+.Dv IPPROTO_UDP
+to
+.Fa ai_protocol .
+.It
+If you specify a
+.Fa servname
+which is defined only for certain
+.Fa ai_socktype ,
+.Fn getaddrinfo
+will fail because the arguments are not consistent.
+For example,
+.Fn getaddrinfo
+will return an error if you ask for
+.Dq Li tftp
+service on
+.Dv SOCK_STREAM .
+.It
+For internet address families, if you specify
+.Fa servname
+while you set
+.Fa ai_socktype
+to
+.Dv SOCK_RAW ,
+.Fn getaddrinfo
+will fail, because service names are not defined for the internet
+.Dv SOCK_RAW
+space.
+.It
+If you specify numeric
+.Fa servname ,
+while leaving
+.Fa ai_socktype
+and
+.Fa ai_protocol
+unspecified,
+.Fn getaddrinfo
+will fail.
+This is because the numeric
+.Fa servname
+does not identify any socket type, and
+.Fn getaddrinfo
+is not allowed to glob the argument in such case.
+.El
+.Pp
+All of the information returned by
+.Fn getaddrinfo
+is dynamically allocated:
+the
+.Li addrinfo
+structures, the socket address structures, and canonical node name
+strings pointed to by the addrinfo structures.
+To return this information to the system the function
+.Fn freeaddrinfo
+is called.
+The
+.Fa addrinfo
+structure pointed to by the
+.Fa ai argument
+is freed, along with any dynamic storage pointed to by the structure.
+This operation is repeated until a
+.Dv NULL
+.Fa ai_next
+pointer is encountered.
+.Pp
+To aid applications in printing error messages based on the
+.Dv EAI_xxx
+codes returned by
+.Fn getaddrinfo ,
+.Fn gai_strerror
+is defined.
+The argument is one of the
+.Dv EAI_xxx
+values defined earlier and the return value points to a string describing
+the error.
+If the argument is not one of the
+.Dv EAI_xxx
+values, the function still returns a pointer to a string whose contents
+indicate an unknown error.
+.\"
+.Sh EXTENSIONS
+This implementation supports numeric IPv6 address notation with the
+experimental scope identifier.
+By appending a percent sign and scope identifier to the address, you
+can specify the value of the
+.Li sin6_scope_id
+field of the socket address.
+This makes management of scoped address easier,
+and allows cut-and-paste input of scoped addresses.
+.Pp
+At the moment the code supports only link-local addresses in this format.
+The scope identifier is hardcoded to name of hardware interface associated
+with the link,
+(such as
+.Li ne0 ) .
+For example,
+.Dq Li fe80::1%ne0 ,
+which means
+.Do
+.Li fe80::1
+on the link associated with the
+.Li ne0
+interface
+.Dc .
+.Pp
+This implementation is still very experimental and non-standard.
+The current implementation assumes a one-to-one relationship between
+interfaces and links, which is not necessarily true according to the
+specification.
+.\"
+.Sh EXAMPLES
+The following code tries to connect to
+.Dq Li www.kame.net
+service
+.Dq Li http .
+via stream socket.
+It loops through all the addresses available, regardless of the address family.
+If the destination resolves to an IPv4 address, it will use an
+.Dv AF_INET
+socket.
+Similarly, if it resolves to IPv6, an
+.Dv AF_INET6
+socket is used.
+Observe that there is no hardcoded reference to particular address family.
+The code works even if
+.Fn getaddrinfo
+returns addresses that are not IPv4/v6.
+.Bd -literal -offset indent
+struct addrinfo hints, *res, *res0;
+int error;
+int s;
+const char *cause = NULL;
+
+memset(&hints, 0, sizeof(hints));
+hints.ai_family = PF_UNSPEC;
+hints.ai_socktype = SOCK_STREAM;
+error = getaddrinfo("www.kame.net", "http", &hints, &res0);
+if (error) {
+       errx(1, "%s", gai_strerror(error));
+       /*NOTREACHED*/
+}
+s = -1;
+cause = "no addresses";
+errno = EADDRNOTAVAIL;
+for (res = res0; res; res = res->ai_next) {
+       s = socket(res->ai_family, res->ai_socktype,
+           res->ai_protocol);
+       if (s < 0) {
+               cause = "socket";
+               continue;
+       }
+
+       if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
+               cause = "connect";
+               close(s);
+               s = -1;
+               continue;
+       }
+
+       break;  /* okay we got one */
+}
+if (s < 0) {
+       err(1, cause);
+       /*NOTREACHED*/
+}
+freeaddrinfo(res0);
+.Ed
+.Pp
+The following example tries to open a wildcard listening socket onto service
+.Dq Li http ,
+for all the address families available.
+.Bd -literal -offset indent
+struct addrinfo hints, *res, *res0;
+int error;
+int s[MAXSOCK];
+int nsock;
+const char *cause = NULL;
+
+memset(&hints, 0, sizeof(hints));
+hints.ai_family = PF_UNSPEC;
+hints.ai_socktype = SOCK_STREAM;
+hints.ai_flags = AI_PASSIVE;
+error = getaddrinfo(NULL, "http", &hints, &res0);
+if (error) {
+       errx(1, "%s", gai_strerror(error));
+       /*NOTREACHED*/
+}
+nsock = 0;
+for (res = res0; res && nsock < MAXSOCK; res = res->ai_next) {
+       s[nsock] = socket(res->ai_family, res->ai_socktype,
+           res->ai_protocol);
+       if (s[nsock] < 0) {
+               cause = "socket";
+               continue;
+       }
+
+       if (bind(s[nsock], res->ai_addr, res->ai_addrlen) < 0) {
+               cause = "bind";
+               close(s[nsock]);
+               continue;
+       }
+
+       if (listen(s[nsock], SOMAXCONN) < 0) {
+               cause = "listen";
+               close(s[nsock]);
+               continue;
+       }
+
+       nsock++;
+}
+if (nsock == 0) {
+       err(1, cause);
+       /*NOTREACHED*/
+}
+freeaddrinfo(res0);
+.Ed
+.\"
+.Sh FILES
+.Bl -tag -width /etc/resolv.conf -compact
+.It Pa /etc/hosts
+.It Pa /etc/host.conf
+.It Pa /etc/resolv.conf
+.El
+.\"
+.Sh DIAGNOSTICS
+Error return status from
+.Fn getaddrinfo
+is zero on success and non-zero on errors.
+Non-zero error codes are defined in
+.Aq Pa netdb.h ,
+and as follows:
+.Pp
+.Bl -tag -width EAI_ADDRFAMILY -compact
+.It Dv EAI_ADDRFAMILY
+Address family for
+.Fa nodename
+not supported.
+.It Dv EAI_AGAIN
+Temporary failure in name resolution.
+.It Dv EAI_BADFLAGS
+Invalid value for
+.Fa ai_flags .
+.It Dv EAI_FAIL
+Non-recoverable failure in name resolution.
+.It Dv EAI_FAMILY
+.Fa ai_family
+not supported.
+.It Dv EAI_MEMORY
+Memory allocation failure.
+.It Dv EAI_NODATA
+No address associated with
+.Fa nodename .
+.It Dv EAI_NONAME
+.Fa nodename
+nor
+.Fa servname
+provided, or not known.
+.It Dv EAI_SERVICE
+.Fa servname
+not supported for
+.Fa ai_socktype .
+.It Dv EAI_SOCKTYPE
+.Fa ai_socktype
+not supported.
+.It Dv EAI_SYSTEM
+System error returned in
+.Va errno .
+.El
+.Pp
+If called with an appropriate argument,
+.Fn gai_strerror
+returns a pointer to a string describing the given error code.
+If the argument is not one of the
+.Dv EAI_xxx
+values, the function still returns a pointer to a string whose contents
+indicate an unknown error.
+.\"
+.Sh SEE ALSO
+.Xr gethostbyname 3 ,
+.Xr getnameinfo 3 ,
+.Xr getservbyname 3 ,
+.Xr hosts 5 ,
+.Xr services 5 ,
+.Xr hostname 7 ,
+.Xr named 8
+.Pp
+.Rs
+.%A R. Gilligan
+.%A S. Thomson
+.%A J. Bound
+.%A W. Stevens
+.%T Basic Socket Interface Extensions for IPv6
+.%R RFC2553
+.%D March 1999
+.Re
+.Rs
+.%A Tatsuya Jinmei
+.%A Atsushi Onoe
+.%T "An Extension of Format for IPv6 Scoped Addresses"
+.%R internet draft
+.%N draft-ietf-ipngwg-scopedaddr-format-02.txt
+.%O work in progress material
+.Re
+.Rs
+.%A Craig Metz
+.%T Protocol Independence Using the Sockets API
+.%B "Proceedings of the freenix track: 2000 USENIX annual technical conference"
+.%D June 2000
+.Re
+.\"
+.Sh HISTORY
+The implementation first appeared in WIDE Hydrangea IPv6 protocol stack kit.
+.\"
+.Sh STANDARDS
+The
+.Fn getaddrinfo
+function is defined in
+.St -p1003.1g-2000 ,
+and documented in
+.Dq Basic Socket Interface Extensions for IPv6
+(RFC2553).
+.\"
+.Sh BUGS
+The current implementation is not thread-safe.
+.Pp
+The text was shamelessly copied from RFC2553.
index 0d105eada28f5dc9173701a5114e81e82b7ce5a7..ab0fa147c07a1f52a9872c8e153006d50b83d888 100644 (file)
 #include <servers/bootstrap.h>
 #include <nameser.h>
 #include <resolv.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <ifaddrs.h>
 
 #define SOCK_UNSPEC 0
 #define IPPROTO_UNSPEC 0
 
+#define WANT_A4_ONLY 1
+#define WANT_A6_ONLY 2
+#define WANT_A6_PLUS_MAPPED_A4 3
+#define WANT_A6_OR_MAPPED4_IF_NO_A6 4
+
 #define LONG_STRING_LENGTH 8192
 #define _LU_MAXLUSTRLEN 256
 
-static char *LOOKUPD_NAME = "lookup daemon";
-
+extern int _lu_running(void);
+extern mach_port_t _lookupd_port();
 extern int _lookup_link();
 extern int _lookup_one();
 extern int _lookup_all();
@@ -90,31 +98,38 @@ static int supported_family_count = 3;
 
 static int supported_socket[] =
 {
+       SOCK_RAW,
        SOCK_UNSPEC,
        SOCK_DGRAM,
        SOCK_STREAM
 };
-static int supported_socket_count = 3;
+static int supported_socket_count = 4;
 
 static int supported_protocol[] =
 {
        IPPROTO_UNSPEC,
+       IPPROTO_ICMPV6,
        IPPROTO_UDP,
        IPPROTO_TCP
 };
-static int supported_protocol_count = 3;
+static int supported_protocol_count = 4;
 
 static int supported_socket_protocol_pair[] =
 {
-       SOCK_UNSPEC,    IPPROTO_UNSPEC,
-       SOCK_UNSPEC,    IPPROTO_UDP,
-       SOCK_UNSPEC,    IPPROTO_TCP,
-       SOCK_DGRAM,     IPPROTO_UNSPEC,
-       SOCK_DGRAM,     IPPROTO_UDP,
-       SOCK_STREAM,    IPPROTO_UNSPEC,
-       SOCK_STREAM,    IPPROTO_TCP
+       SOCK_RAW,    IPPROTO_UNSPEC,
+       SOCK_RAW,    IPPROTO_UDP,
+       SOCK_RAW,    IPPROTO_TCP,
+       SOCK_RAW,    IPPROTO_ICMPV6,
+       SOCK_UNSPEC, IPPROTO_UNSPEC,
+       SOCK_UNSPEC, IPPROTO_UDP,
+       SOCK_UNSPEC, IPPROTO_TCP,
+       SOCK_UNSPEC, IPPROTO_ICMPV6,
+       SOCK_DGRAM,  IPPROTO_UNSPEC,
+       SOCK_DGRAM,  IPPROTO_UDP,
+       SOCK_STREAM, IPPROTO_UNSPEC,
+       SOCK_STREAM, IPPROTO_TCP
 };
-static int supported_socket_protocol_pair_count = 7;
+static int supported_socket_protocol_pair_count = 12;
 
 static int
 gai_family_type_check(int f)
@@ -173,70 +188,9 @@ gai_socket_protocol_type_check(int s, int p)
 static int
 gai_inet_pton(const char *s, struct in6_addr *a6)
 {
-       int run, ncolon;
-       unsigned short x[8];
-       char *p, buf[4];
-
        if (s == NULL) return 0;
        if (a6 == NULL) return 0;
-
-       for (ncolon = 0; ncolon < 8; ncolon++) x[ncolon] = 0;
-       memset(buf, 0, 4);
-
-       ncolon = 0;
-       run = 0;
-       for (p = (char *)s; *p != '\0'; p++)
-       {
-               if (*p == ':')
-               {
-                       if (run > 0) sscanf(buf, "%hx", &(x[ncolon]));
-                       ncolon++;
-                       if (ncolon > 7) return 0;
-                       run = 0;
-                       memset(buf, 0, 4);
-               }
-               else if (((*p >= '0') && (*p <= '9')) || ((*p >= 'a') && (*p <= 'f')) || ((*p >= 'A') && (*p <= 'F')))
-               {
-                       buf[run] = *p;
-                       run++;
-                       if (run > 4) return 0;
-               }
-       }
-       
-       if (ncolon != 7) return 0;
-
-       if (run > 0) sscanf(buf, "%hx", &(x[7]));
-
-       a6->__u6_addr.__u6_addr32[0] = (x[0] << 16) + x[1];
-       a6->__u6_addr.__u6_addr32[1] = (x[2] << 16) + x[3];
-       a6->__u6_addr.__u6_addr32[2] = (x[4] << 16) + x[5];
-       a6->__u6_addr.__u6_addr32[3] = (x[6] << 16) + x[7];
-
-       return 1;
-}
-
-static char *
-gai_inet_ntop(struct in6_addr a)
-{
-       static char buf[128];
-       char t[32];
-       unsigned short x;
-       char *p;
-       int i;
-
-       memset(buf, 0, 128);
-
-       p = (char *)&a.__u6_addr.__u6_addr32;
-       for (i = 0; i < 8; i++, x += 1)
-       {
-               memmove(&x, p, 2);
-               p += 2;
-               sprintf(t, "%hx", x);
-               strcat(buf, t);
-               if (i < 7) strcat(buf, ":");
-       }
-
-       return buf;
+       return inet_pton(AF_INET6, s, (void *)&a6->__u6_addr.__u6_addr32[0]);
 }
 
 char *
@@ -295,8 +249,26 @@ append_addrinfo(struct addrinfo **l, struct addrinfo *a)
        }
 
        x = *l;
-       while (x->ai_next != NULL) x = x->ai_next;
-       x->ai_next = a;
+
+       if (a->ai_family == PF_INET6)
+       {
+               if (x->ai_family == PF_INET)
+               {
+                       *l = a;
+                       a->ai_next = x;
+                       return;
+               }
+
+               while ((x->ai_next != NULL) && (x->ai_next->ai_family != PF_INET)) x = x->ai_next;
+               a->ai_next = x->ai_next;
+               x->ai_next = a;
+       }
+       else
+       {
+               while (x->ai_next != NULL) x = x->ai_next;
+               a->ai_next = NULL;
+               x->ai_next = a;
+       }
 }
 
 static void
@@ -324,10 +296,78 @@ free_lu_dict(struct lu_dict *d)
        }
 }
 
+static int
+_lu_str_equal(char *a, char *b)
+{
+       if (a == NULL)
+       {
+               if (b == NULL) return 1;
+               return 0;
+       }
+
+       if (b == NULL) return 0;
+
+       if (!strcmp(a, b)) return 1;
+       return 0;
+}
+
+static int
+lu_dict_equal(struct lu_dict *a, struct lu_dict *b)
+{
+       if (a == NULL) return 0;
+       if (b == NULL) return 0;
+
+       if (_lu_str_equal(a->type, b->type) == 0) return 0;
+       if (_lu_str_equal(a->name, b->name) == 0) return 0;
+       if (_lu_str_equal(a->cname, b->cname) == 0) return 0;
+       if (_lu_str_equal(a->mx, b->mx) == 0) return 0;
+       if (_lu_str_equal(a->ipv4, b->ipv4) == 0) return 0;
+       if (_lu_str_equal(a->ipv6, b->ipv6) == 0) return 0;
+       if (_lu_str_equal(a->service, b->service) == 0) return 0;
+       if (_lu_str_equal(a->port, b->port) == 0) return 0;
+       if (_lu_str_equal(a->protocol, b->protocol) == 0) return 0;
+       if (_lu_str_equal(a->target, b->target) == 0) return 0;
+       if (_lu_str_equal(a->priority, b->priority) == 0) return 0;
+       if (_lu_str_equal(a->weight, b->weight) == 0) return 0;
+       return 1;
+}
+
+/*
+ * Append a single dictionary to a list if it is unique.
+ * Free it if it is not appended.
+ */
+static void
+merge_lu_dict(struct lu_dict **l, struct lu_dict *d)
+{
+       struct lu_dict *x, *e;
+
+       if (l == NULL) return;
+       if (d == NULL) return;
+
+       if (*l == NULL)
+       {
+               *l = d;
+               return;
+       }
+
+       e = *l;
+       for (x = *l; x != NULL; x = x->lu_next)
+       {
+               e = x;
+               if (lu_dict_equal(x, d))
+               {
+                       free_lu_dict(d);
+                       return;
+               }
+       }
+
+       e->lu_next = d;
+}
+
 static void
 append_lu_dict(struct lu_dict **l, struct lu_dict *d)
 {
-       struct lu_dict *x;
+       struct lu_dict *x, *next;
 
        if (l == NULL) return;
        if (d == NULL) return;
@@ -338,9 +378,15 @@ append_lu_dict(struct lu_dict **l, struct lu_dict *d)
                return;
        }
 
-       x = *l;
-       while (x->lu_next != NULL) x = x->lu_next;
-       x->lu_next = d;
+       x = d;
+
+       while (x != NULL)
+       {
+               next = x->lu_next;
+               x->lu_next = NULL;
+               merge_lu_dict(l, x);
+               x = next;
+       }
 }
 
 /*
@@ -424,18 +470,7 @@ lookupd_process_dictionary(XDR *inxdr, struct lu_dict **l)
                }
        }
 
-       append_lu_dict(l, d);
-}
-
-static mach_port_t
-lookupd_port(char *name)
-{
-       mach_port_t p;
-       kern_return_t status;
-
-       status = bootstrap_look_up(bootstrap_port, name, &p);
-       if (status == KERN_SUCCESS) return p;
-       return MACH_PORT_NULL;
+       merge_lu_dict(l, d);
 }
 
 static int
@@ -457,7 +492,7 @@ gai_files(struct lu_dict *q, struct lu_dict **list)
        struct servent *s;
        struct hostent *h;
        struct lu_dict *d;
-       char str[64];
+       char str[64], portstr[64];
        struct in_addr a4;
 
        if (!strcmp(q->type, "service"))
@@ -482,12 +517,26 @@ gai_files(struct lu_dict *q, struct lu_dict **list)
                d->port = strdup(str);
                if (s->s_proto != NULL) d->protocol = strdup(s->s_proto);
 
-               append_lu_dict(list, d);
+               merge_lu_dict(list, d);
                return 1;
        }
 
-       else if (!strcmp(q->type, "host"))
+       if (!strcmp(q->type, "host"))
        {
+               s = NULL;
+               if (q->service != NULL)
+               {
+                       s = getservbyname(q->service, q->protocol);
+               }
+               else if (q->port != NULL)
+               {
+                       port = atoi(q->port);
+                       s = getservbyport(port, q->protocol);
+               }
+
+               sprintf(portstr, "0");
+               if (s != NULL) sprintf(portstr, "%u", ntohl(s->s_port));
+
                h = NULL;
                if (q->name != NULL)
                {
@@ -511,13 +560,23 @@ gai_files(struct lu_dict *q, struct lu_dict **list)
                        d = (struct lu_dict *)malloc(sizeof(struct lu_dict));
                        memset(d, 0, sizeof(struct lu_dict));
 
-                       if (h->h_name != NULL) d->name = strdup(h->h_name);
+                       if (h->h_name != NULL)
+                       {
+                               d->name = strdup(h->h_name);
+                               d->target = strdup(h->h_name);
+                       }
                        memmove((void *)&a4.s_addr, h->h_addr_list[i], h->h_length);
 
                        sprintf(str, "%s", inet_ntoa(a4));
                        d->ipv4 = strdup(str);
 
-                       append_lu_dict(list, d);
+                       if (s != NULL)
+                       {
+                               if (s->s_name != NULL) d->service = strdup(s->s_name);
+                               d->port = strdup(portstr);
+                       }
+
+                       merge_lu_dict(list, d);
                }
                return i;
        }
@@ -543,9 +602,11 @@ gai_lookupd(struct lu_dict *q, struct lu_dict **list)
        if (q->type == NULL) return 0;
        
        if (list == NULL) return -1;
-       
-       server_port = lookupd_port(LOOKUPD_NAME);
-       if (server_port == NULL) return gai_files(q, list);
+
+       server_port = MACH_PORT_NULL;
+       if (_lu_running()) server_port = _lookupd_port(0);
+
+       if (server_port == MACH_PORT_NULL) return gai_files(q, list);
 
        status = _lookup_link(server_port, "query", &proc);
        if (status != KERN_SUCCESS) return gai_files(q, list);
@@ -633,10 +694,8 @@ gai_lookupd(struct lu_dict *q, struct lu_dict **list)
 
        xdr_destroy(&outxdr);
 
-#ifdef NOTDEF
-/* NOTDEF because OOL buffers are counted in bytes with untyped IPC */
        datalen *= BYTES_PER_XDR_UNIT;
-#endif
+
        xdrmem_create(&inxdr, listbuf, datalen, XDR_DECODE);
 
        if (!xdr_int(&inxdr, &n))
@@ -777,8 +836,7 @@ grok_service(const char *servname, struct lu_dict *q)
                if (!isdigit(*p)) port = -1;
        }
 
-       if (port == 0) port = atoi(servname);
-       if ((port > 0) && (port < 0xffff)) q->port = (char *)servname;
+       if (port == 0) q->port = (char *)servname;
        else q->service = (char *)servname;
 }
 
@@ -798,7 +856,7 @@ gai_numerichost(struct lu_dict *h, struct lu_dict **list)
                a = (struct lu_dict *)malloc(sizeof(struct lu_dict));
                memset(a, 0, sizeof(struct lu_dict));
                a->ipv4 = strdup(h->ipv4);
-               append_lu_dict(list, a);
+               merge_lu_dict(list, a);
                n++;
        }
 
@@ -807,7 +865,7 @@ gai_numerichost(struct lu_dict *h, struct lu_dict **list)
                a = (struct lu_dict *)malloc(sizeof(struct lu_dict));
                memset(a, 0, sizeof(struct lu_dict));
                a->ipv6 = strdup(h->ipv6);
-               append_lu_dict(list, a);
+               merge_lu_dict(list, a);
                n++;
        }
 
@@ -826,7 +884,7 @@ gai_numericserv(struct lu_dict *s, struct lu_dict **list)
        a = (struct lu_dict *)malloc(sizeof(struct lu_dict));
        memset(a, 0, sizeof(struct lu_dict));
        a->port = strdup(s->port);
-       append_lu_dict(list, a);
+       merge_lu_dict(list, a);
        return 1;       
 }
 
@@ -1358,7 +1416,7 @@ gai_node_pp(const char *nodename, unsigned short port, int proto, int family, in
        {
                if (d->cname != NULL)
                {
-                       cname = strdup(d->cname);
+                       if (cname == NULL) cname = strdup(d->cname);
                        gai_node_lookupd(d->cname, family, 0, &list);
                }
        }
@@ -1597,15 +1655,22 @@ getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *h
        if (nodename == NULL)
        {
                /* If node is NULL, find service */
-               return gai_serv(servname, hints, res);
+               status = gai_serv(servname, hints, res);
+               if ((status == 0) && (*res == NULL)) status = EAI_NODATA;
+               return status;
        }
 
        if (servname == NULL)
        {
                /* If service is NULL, find node */
-               return gai_node(nodename, hints, res);
+               status = gai_node(nodename, hints, res);
+               if ((status == 0) && (*res == NULL)) status = EAI_NODATA;
+               return status;
        }
 
        /* Find node + service */
-       return gai_nodeserv(nodename, servname, hints, res);
+       status = gai_nodeserv(nodename, servname, hints, res);
+       if ((status == 0) && (*res == NULL)) status = EAI_NODATA;
+       return status;
 }
+
index e9552d4dc72d81eb44a9d36f92e18bdd637ceab1..36a01d2906be1c8bbde96e6cc8eb276f05c2d0b0 100644 (file)
@@ -61,6 +61,7 @@ static char sccsid[] = "@(#)getgrent.c        8.2 (Berkeley) 3/21/94";
 #include <sys/types.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <grp.h>
 
 static FILE *_gr_fp;
@@ -76,7 +77,7 @@ static char line[MAXLINELENGTH];
 struct group *
 getgrent()
 {
-       if (!_gr_fp && !start_gr() || !grscan(0, 0, NULL))
+       if ((!_gr_fp && !start_gr()) || !grscan(0, 0, NULL))
                return(NULL);
        return(&_gr_group);
 }
@@ -113,7 +114,7 @@ getgrgid(gid)
        return(rval ? &_gr_group : NULL);
 }
 
-static
+static int
 start_gr()
 {
        if (_gr_fp) {
@@ -148,7 +149,7 @@ endgrent()
        }
 }
 
-static
+static int
 grscan(search, gid, name)
        register int search, gid;
        register char *name;
diff --git a/gen.subproj/gethostbyname.3 b/gen.subproj/gethostbyname.3
new file mode 100644 (file)
index 0000000..8f23b28
--- /dev/null
@@ -0,0 +1,318 @@
+.\" Copyright (c) 1983, 1987, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     From: @(#)gethostbyname.3      8.4 (Berkeley) 5/25/95
+.\" $FreeBSD: src/lib/libc/net/gethostbyname.3,v 1.12.2.6 2001/08/17 15:42:38 ru Exp $
+.\"
+.Dd May 25, 1995
+.Dt GETHOSTBYNAME 3
+.Os
+.Sh NAME
+.Nm gethostbyname ,
+.Nm gethostbyname2 ,
+.Nm gethostbyaddr ,
+.Nm gethostent ,
+.Nm sethostent ,
+.Nm endhostent ,
+.Nm herror ,
+.Nm hstrerror
+.Nd get network host entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.Fd #include <netdb.h>
+.Vt extern int h_errno ;
+.Ft struct hostent *
+.Fn gethostbyname "const char *name"
+.Ft struct hostent *
+.Fn gethostbyname2 "const char *name" "int af"
+.Ft struct hostent *
+.Fn gethostbyaddr "const char *addr" "int len" "int type"
+.Ft struct hostent *
+.Fn gethostent void
+.Ft void
+.Fn sethostent "int stayopen"
+.Ft void
+.Fn endhostent void
+.Ft void
+.Fn herror "const char *string"
+.Ft const char *
+.Fn hstrerror "int err"
+.Sh DESCRIPTION
+The
+.Fn gethostbyname ,
+.Fn gethostbyname2
+and
+.Fn gethostbyaddr
+functions
+each return a pointer to an object with the
+following structure describing an internet host
+referenced by name or by address, respectively.
+This structure contains either the information obtained from the name server,
+.Xr named 8 ,
+or broken-out fields from a line in
+.Pa /etc/hosts .
+If the local name server is not running these routines do a lookup in
+.Pa /etc/hosts .
+.Bd -literal
+struct hostent {
+       char    *h_name;        /* official name of host */
+       char    **h_aliases;    /* alias list */
+       int     h_addrtype;     /* host address type */
+       int     h_length;       /* length of address */
+       char    **h_addr_list;  /* list of addresses from name server */
+};
+#define        h_addr  h_addr_list[0]  /* address, for backward compatibility */
+.Ed
+.Pp
+The members of this structure are:
+.Bl -tag -width h_addr_list
+.It Va h_name
+Official name of the host.
+.It Va h_aliases
+A
+.Dv NULL Ns -terminated
+array of alternate names for the host.
+.It Va h_addrtype
+The type of address being returned; usually
+.Dv AF_INET .
+.It Va h_length
+The length, in bytes, of the address.
+.It Va h_addr_list
+A
+.Dv NULL Ns -terminated
+array of network addresses for the host.
+Host addresses are returned in network byte order.
+.It Va h_addr
+The first address in
+.Va h_addr_list ;
+this is for backward compatibility.
+.El
+.Pp
+When using the nameserver,
+.Fn gethostbyname
+and
+.Fn gethostbyname2
+will search for the named host in the current domain and its parents
+unless the name ends in a dot.
+If the name contains no dot, and if the environment variable
+.Dq Ev HOSTALIASES
+contains the name of an alias file, the alias file will first be searched
+for an alias matching the input name.
+See
+.Xr hostname 7
+for the domain search procedure and the alias file format.
+.Pp
+The
+.Fn gethostbyname2
+function is an evolution of
+.Fn gethostbyname
+which is intended to allow lookups in address families other than
+.Dv AF_INET ,
+for example
+.Dv AF_INET6 .
+Currently the
+.Fa af
+argument must be specified as
+.Dv AF_INET
+else the function will return
+.Dv NULL
+after having set
+.Va h_errno
+to
+.Dv NETDB_INTERNAL
+.Pp
+The
+.Fn sethostent
+function
+may be used to request the use of a connected
+.Tn TCP
+socket for queries.
+If the
+.Fa stayopen
+flag is non-zero,
+this sets the option to send all queries to the name server using
+.Tn TCP
+and to retain the connection after each call to
+.Fn gethostbyname ,
+.Fn gethostbyname2
+or
+.Fn gethostbyaddr .
+Otherwise, queries are performed using
+.Tn UDP
+datagrams.
+.Pp
+The
+.Fn endhostent
+function
+closes the
+.Tn TCP
+connection.
+.Pp
+The
+.Fn herror
+function writes a message to the diagnostic output consisting of the
+string parameter
+.Fa s ,
+the constant string
+.Qq Li ":\ " ,
+and a message corresponding to the value of
+.Va h_errno .
+.Pp
+The
+.Fn hstrerror
+function returns a string which is the message text corresponding to the
+value of the
+.Fa err
+parameter.
+.Sh FILES
+.Bl -tag -width /etc/resolv.conf -compact
+.It Pa /etc/hosts
+.It Pa /etc/host.conf
+.It Pa /etc/resolv.conf
+.El
+.Sh DIAGNOSTICS
+Error return status from
+.Fn gethostbyname ,
+.Fn gethostbyname2
+and
+.Fn gethostbyaddr
+is indicated by return of a
+.Dv NULL
+pointer.
+The external integer
+.Va h_errno
+may then be checked to see whether this is a temporary failure
+or an invalid or unknown host.
+The routine
+.Fn herror
+can be used to print an error message describing the failure.
+If its argument
+.Fa string
+is
+.Pf non- Dv NULL ,
+it is printed, followed by a colon and a space.
+The error message is printed with a trailing newline.
+.Pp
+The variable
+.Va h_errno
+can have the following values:
+.Bl -tag -width HOST_NOT_FOUND
+.It Dv HOST_NOT_FOUND
+No such host is known.
+.It Dv TRY_AGAIN
+This is usually a temporary error
+and means that the local server did not receive
+a response from an authoritative server.
+A retry at some later time may succeed.
+.It Dv NO_RECOVERY
+Some unexpected server failure was encountered.
+This is a non-recoverable error.
+.It Dv NO_DATA
+The requested name is valid but does not have an IP address;
+this is not a temporary error.
+This means that the name is known to the name server but there is no address
+associated with this name.
+Another type of request to the name server using this domain name
+will result in an answer;
+for example, a mail-forwarder may be registered for this domain.
+.El
+.Sh SEE ALSO
+.Xr getaddrinfo 3 ,
+.Xr resolver 3 ,
+.Xr hosts 5 ,
+.Xr hostname 7 ,
+.Xr named 8
+.Sh CAVEAT
+The
+.Fn gethostent
+function
+is defined, and
+.Fn sethostent
+and
+.Fn endhostent
+are redefined,
+when
+.Xr libc 3
+is built to use only the routines to lookup in
+.Pa /etc/hosts
+and not the name server.
+.Pp
+The
+.Fn gethostent
+function
+reads the next line of
+.Pa /etc/hosts ,
+opening the file if necessary.
+.Pp
+The
+.Fn sethostent
+function
+opens and/or rewinds the file
+.Pa /etc/hosts .
+If the
+.Fa stayopen
+argument is non-zero,
+the file will not be closed after each call to
+.Fn gethostbyname ,
+.Fn gethostbyname2
+or
+.Fn gethostbyaddr .
+.Pp
+The
+.Fn endhostent
+function
+closes the file.
+.Sh HISTORY
+The
+.Fn herror
+function appeared in
+.Bx 4.3 .
+The
+.Fn endhostent ,
+.Fn gethostbyaddr ,
+.Fn gethostbyname ,
+.Fn gethostent ,
+and
+.Fn sethostent
+functions appeared in
+.Bx 4.2 .
+The
+.Fn gethostbyname2
+function first appeared in
+.Tn BIND
+version 4.9.4.
+.Sh BUGS
+These functions use static data storage;
+if the data is needed for future use, it should be
+copied before any subsequent calls overwrite it.
+Only the Internet
+address format is currently understood.
diff --git a/gen.subproj/getifaddrs.3 b/gen.subproj/getifaddrs.3
new file mode 100644 (file)
index 0000000..7409e90
--- /dev/null
@@ -0,0 +1,164 @@
+.\"    $FreeBSD: src/lib/libc/net/getifaddrs.3,v 1.1.2.4 2001/08/31 10:15:14 ru Exp $
+.\"    $KAME: getifaddrs.3,v 1.4 2000/05/17 14:13:14 itojun Exp $
+.\"    BSDI    getifaddrs.3,v 2.5 2000/02/23 14:51:59 dab Exp
+.\"
+.\" Copyright (c) 1995, 1999
+.\"    Berkeley Software Design, Inc.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.Dd October 12, 1995
+.Dt GETIFADDRS 3
+.Os
+.Sh NAME
+.Nm getifaddrs
+.Nd get interface addresses
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/socket.h>
+.Fd #include <ifaddrs.h>
+.Ft int
+.Fn getifaddrs "struct ifaddrs **ifap"
+.Ft void
+.Fn freeifaddrs "struct ifaddrs *ifp"
+.Sh DESCRIPTION
+The
+.Fn getifaddrs
+function stores a reference to a linked list of the network interfaces
+on the local machine in the memory referenced by
+.Fa ifap .
+The list consists of
+.Nm ifaddrs
+structures, as defined in the include file
+.Aq Pa ifaddrs.h .
+The
+.Nm ifaddrs
+structure contains at least the following entries:
+.Bd -literal
+    struct ifaddrs   *ifa_next;         /* Pointer to next struct */
+    char             *ifa_name;         /* Interface name */
+    u_int             ifa_flags;        /* Interface flags */
+    struct sockaddr  *ifa_addr;         /* Interface address */
+    struct sockaddr  *ifa_netmask;      /* Interface netmask */
+    struct sockaddr  *ifa_broadaddr;    /* Interface broadcast address */
+    struct sockaddr  *ifa_dstaddr;      /* P2P interface destination */
+    void             *ifa_data;                /* Address specific data */
+.Ed
+.Pp
+The
+.Li ifa_next
+field contains a pointer to the next structure on the list.
+This field is
+.Dv NULL
+in last structure on the list.
+.Pp
+The
+.Li ifa_name
+field contains the interface name.
+.Pp
+The
+.Li ifa_flags
+field contains the interface flags, as set by
+.Xr ifconfig 8
+utility.
+.Pp
+The
+.Li ifa_addr
+field references either the address of the interface or the link level
+address of the interface, if one exists, otherwise it is NULL.
+(The
+.Li sa_family
+field of the
+.Li ifa_addr
+field should be consulted to determine the format of the
+.Li ifa_addr
+address.)
+.Pp
+The
+.Li ifa_netmask
+field references the netmask associated with
+.Li ifa_addr ,
+if one is set, otherwise it is NULL.
+.Pp
+The
+.Li ifa_broadaddr
+field,
+which should only be referenced for non-P2P interfaces,
+references the broadcast address associated with
+.Li ifa_addr ,
+if one exists, otherwise it is NULL.
+.Pp
+The
+.Li ifa_dstaddr
+field references the destination address on a P2P interface,
+if one exists, otherwise it is NULL.
+.Pp
+The
+.Li ifa_data
+field references address family specific data.  For
+.Dv AF_LINK
+addresses it contains a pointer to the
+.Fa struct if_data
+(as defined in include file
+.Aq Pa net/if.h )
+which contains various interface attributes and statistics.
+For all other address families, it contains a pointer to the
+.Fa struct ifa_data
+(as defined in include file
+.Aq Pa net/if.h )
+which contains per-address interface statistics.
+.Pp
+The data returned by
+.Fn getifaddrs
+is dynamically allocated and should be freed using
+.Fn freeifaddrs
+when no longer needed.
+.Sh RETURN VALUES
+.Rv -std getifaddrs
+.Sh ERRORS
+The
+.Fn getifaddrs
+may fail and set
+.Va errno
+for any of the errors specified for the library routines
+.Xr ioctl 2 ,
+.Xr socket 2 ,
+.Xr malloc 3
+or
+.Xr sysctl 3 .
+.Sh BUGS
+If both
+.Aq Pa net/if.h
+and
+.Aq Pa ifaddrs.h
+are being included,
+.Aq Pa net/if.h
+.Em must
+be included before
+.Aq Pa ifaddrs.h .
+.Sh SEE ALSO
+.Xr ioctl 2 ,
+.Xr socket 2 ,
+.Xr sysctl 3 ,
+.Xr networking 4 ,
+.Xr ifconfig 8
+.Sh HISTORY
+The
+.Nm
+implementation first appeared in BSDi
+.Bsx .
diff --git a/gen.subproj/getifaddrs.c b/gen.subproj/getifaddrs.c
new file mode 100644 (file)
index 0000000..9522032
--- /dev/null
@@ -0,0 +1,382 @@
+/*
+ * Copyright (c) 1995, 1999
+ *     Berkeley Software Design, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     BSDI getifaddrs.c,v 2.12 2000/02/23 14:51:59 dab Exp
+ */
+/*
+ * NOTE: SIOCGIFCONF case is not LP64 friendly.  it also does not perform
+ * try-and-error for region size.
+ */
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#ifdef NET_RT_IFLIST
+#include <sys/param.h>
+#include <net/route.h>
+#include <sys/sysctl.h>
+#include <net/if_dl.h>
+#endif
+
+#include <errno.h>
+#include <ifaddrs.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if !defined(AF_LINK)
+#define        SA_LEN(sa)      sizeof(struct sockaddr)
+#endif
+
+#if !defined(SA_LEN)
+#define        SA_LEN(sa)      (sa)->sa_len
+#endif
+
+#define        SALIGN  (sizeof(long) - 1)
+#define        SA_RLEN(sa)     ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : (SALIGN + 1))
+
+#ifndef        ALIGNBYTES
+/*
+ * On systems with a routing socket, ALIGNBYTES should match the value
+ * that the kernel uses when building the messages.
+ */
+#define        ALIGNBYTES      XXX
+#endif
+#ifndef        ALIGN
+#define        ALIGN(p)        (((u_long)(p) + ALIGNBYTES) &~ ALIGNBYTES)
+#endif
+
+#if    _BSDI_VERSION >= 199701
+#define        HAVE_IFM_DATA
+#endif
+
+#if    _BSDI_VERSION >= 199802
+/* ifam_data is very specific to recent versions of bsdi */
+#define        HAVE_IFAM_DATA
+#endif
+
+#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
+#define        HAVE_IFM_DATA
+#endif
+
+int
+getifaddrs(struct ifaddrs **pif)
+{
+       int icnt = 1;
+       int dcnt = 0;
+       int ncnt = 0;
+#ifdef NET_RT_IFLIST
+       int mib[6];
+       size_t needed;
+       char *buf;
+       char *next;
+       struct ifaddrs *cif = 0;
+       char *p, *p0;
+       struct rt_msghdr *rtm;
+       struct if_msghdr *ifm;
+       struct ifa_msghdr *ifam;
+       struct sockaddr_dl *dl;
+       struct sockaddr *sa;
+       struct ifaddrs *ifa, *ift;
+       u_short index = 0;
+#else  /* NET_RT_IFLIST */
+       char buf[1024];
+       int m, sock;
+       struct ifconf ifc;
+       struct ifreq *ifr;
+       struct ifreq *lifr;
+#endif /* NET_RT_IFLIST */
+       int i;
+       size_t len, alen;
+       char *data;
+       char *names;
+
+#ifdef NET_RT_IFLIST
+       mib[0] = CTL_NET;
+       mib[1] = PF_ROUTE;
+       mib[2] = 0;             /* protocol */
+       mib[3] = 0;             /* wildcard address family */
+       mib[4] = NET_RT_IFLIST;
+       mib[5] = 0;             /* no flags */
+       if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
+               return (-1);
+       if ((buf = malloc(needed)) == NULL)
+               return (-1);
+       if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
+               free(buf);
+               return (-1);
+       }
+
+       for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
+               rtm = (struct rt_msghdr *)next;
+               if (rtm->rtm_version != RTM_VERSION)
+                       continue;
+               switch (rtm->rtm_type) {
+               case RTM_IFINFO:
+                       ifm = (struct if_msghdr *)rtm;
+                       if (ifm->ifm_addrs & RTA_IFP) {
+                               index = ifm->ifm_index;
+                               ++icnt;
+                               dl = (struct sockaddr_dl *)(ifm + 1);
+                               dcnt += SA_RLEN((struct sockaddr *)dl) +
+                                       ALIGNBYTES;
+#ifdef HAVE_IFM_DATA
+                               dcnt += sizeof(ifm->ifm_data);
+#endif /* HAVE_IFM_DATA */
+                               ncnt += dl->sdl_nlen + 1;
+                       } else
+                               index = 0;
+                       break;
+
+               case RTM_NEWADDR:
+                       ifam = (struct ifa_msghdr *)rtm;
+                       if (index && ifam->ifam_index != index)
+                               abort();        /* this cannot happen */
+
+#define        RTA_MASKS       (RTA_NETMASK | RTA_IFA | RTA_BRD)
+                       if (index == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0)
+                               break;
+                       p = (char *)(ifam + 1);
+                       ++icnt;
+#ifdef HAVE_IFAM_DATA
+                       dcnt += sizeof(ifam->ifam_data) + ALIGNBYTES;
+#endif /* HAVE_IFAM_DATA */
+                       /* Scan to look for length of address */
+                       alen = 0;
+                       for (p0 = p, i = 0; i < RTAX_MAX; i++) {
+                               if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
+                                   == 0)
+                                       continue;
+                               sa = (struct sockaddr *)p;
+                               len = SA_RLEN(sa);
+                               if (i == RTAX_IFA) {
+                                       alen = len;
+                                       break;
+                               }
+                               p += len;
+                       }
+                       for (p = p0, i = 0; i < RTAX_MAX; i++) {
+                               if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
+                                   == 0)
+                                       continue;
+                               sa = (struct sockaddr *)p;
+                               len = SA_RLEN(sa);
+                               if (i == RTAX_NETMASK && SA_LEN(sa) == 0)
+                                       dcnt += alen;
+                               else
+                                       dcnt += len;
+                               p += len;
+                       }
+                       break;
+               }
+       }
+#else  /* NET_RT_IFLIST */
+       ifc.ifc_buf = buf;
+       ifc.ifc_len = sizeof(buf);
+
+       if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+               return (-1);
+       i =  ioctl(sock, SIOCGIFCONF, (char *)&ifc);
+       close(sock);
+       if (i < 0)
+               return (-1);
+
+       ifr = ifc.ifc_req;
+       lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];
+
+       while (ifr < lifr) {
+               struct sockaddr *sa;
+
+               sa = &ifr->ifr_addr;
+               ++icnt;
+               dcnt += SA_RLEN(sa);
+               ncnt += sizeof(ifr->ifr_name) + 1;
+               
+               ifr = (struct ifreq *)(((char *)sa) + SA_LEN(sa));
+       }
+#endif /* NET_RT_IFLIST */
+
+       if (icnt + dcnt + ncnt == 1) {
+               *pif = NULL;
+               free(buf);
+               return (0);
+       }
+       data = malloc(sizeof(struct ifaddrs) * icnt + dcnt + ncnt);
+       if (data == NULL) {
+               free(buf);
+               return(-1);
+       }
+
+       ifa = (struct ifaddrs *)data;
+       data += sizeof(struct ifaddrs) * icnt;
+       names = data + dcnt;
+
+       memset(ifa, 0, sizeof(struct ifaddrs) * icnt);
+       ift = ifa;
+
+#ifdef NET_RT_IFLIST
+       index = 0;
+       for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
+               rtm = (struct rt_msghdr *)next;
+               if (rtm->rtm_version != RTM_VERSION)
+                       continue;
+               switch (rtm->rtm_type) {
+               case RTM_IFINFO:
+                       ifm = (struct if_msghdr *)rtm;
+                       if (ifm->ifm_addrs & RTA_IFP) {
+                               index = ifm->ifm_index;
+                               dl = (struct sockaddr_dl *)(ifm + 1);
+
+                               cif = ift;
+                               ift->ifa_name = names;
+                               ift->ifa_flags = (int)ifm->ifm_flags;
+                               memcpy(names, dl->sdl_data, dl->sdl_nlen);
+                               names[dl->sdl_nlen] = 0;
+                               names += dl->sdl_nlen + 1;
+
+                               ift->ifa_addr = (struct sockaddr *)data;
+                               memcpy(data, dl, SA_LEN((struct sockaddr *)dl));
+                               data += SA_RLEN((struct sockaddr *)dl);
+
+#ifdef HAVE_IFM_DATA
+                               /* ifm_data needs to be aligned */
+                               ift->ifa_data = data = (void *)ALIGN(data);
+                               memcpy(data, &ifm->ifm_data, sizeof(ifm->ifm_data));
+                               data += sizeof(ifm->ifm_data);
+#else  /* HAVE_IFM_DATA */
+                               ift->ifa_data = NULL;
+#endif /* HAVE_IFM_DATA */
+
+                               ift = (ift->ifa_next = ift + 1);
+                       } else
+                               index = 0;
+                       break;
+
+               case RTM_NEWADDR:
+                       ifam = (struct ifa_msghdr *)rtm;
+                       if (index && ifam->ifam_index != index)
+                               abort();        /* this cannot happen */
+
+                       if (index == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0)
+                               break;
+                       ift->ifa_name = cif->ifa_name;
+                       ift->ifa_flags = cif->ifa_flags;
+                       ift->ifa_data = NULL;
+                       p = (char *)(ifam + 1);
+                       /* Scan to look for length of address */
+                       alen = 0;
+                       for (p0 = p, i = 0; i < RTAX_MAX; i++) {
+                               if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
+                                   == 0)
+                                       continue;
+                               sa = (struct sockaddr *)p;
+                               len = SA_RLEN(sa);
+                               if (i == RTAX_IFA) {
+                                       alen = len;
+                                       break;
+                               }
+                               p += len;
+                       }
+                       for (p = p0, i = 0; i < RTAX_MAX; i++) {
+                               if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
+                                   == 0)
+                                       continue;
+                               sa = (struct sockaddr *)p;
+                               len = SA_RLEN(sa);
+                               switch (i) {
+                               case RTAX_IFA:
+                                       ift->ifa_addr = (struct sockaddr *)data;
+                                       memcpy(data, p, len);
+                                       data += len;
+                                       break;
+
+                               case RTAX_NETMASK:
+                                       ift->ifa_netmask =
+                                           (struct sockaddr *)data;
+                                       if (SA_LEN(sa) == 0) {
+                                               memset(data, 0, alen);
+                                               data += alen;
+                                               break;
+                                       }
+                                       memcpy(data, p, len);
+                                       data += len;
+                                       break;
+
+                               case RTAX_BRD:
+                                       ift->ifa_broadaddr =
+                                           (struct sockaddr *)data;
+                                       memcpy(data, p, len);
+                                       data += len;
+                                       break;
+                               }
+                               p += len;
+                       }
+
+#ifdef HAVE_IFAM_DATA
+                       /* ifam_data needs to be aligned */
+                       ift->ifa_data = data = (void *)ALIGN(data);
+                       memcpy(data, &ifam->ifam_data, sizeof(ifam->ifam_data));
+                       data += sizeof(ifam->ifam_data);
+#endif /* HAVE_IFAM_DATA */
+
+                       ift = (ift->ifa_next = ift + 1);
+                       break;
+               }
+       }
+
+       free(buf);
+#else  /* NET_RT_IFLIST */
+       ifr = ifc.ifc_req;
+       lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];
+
+       while (ifr < lifr) {
+               struct sockaddr *sa;
+
+               ift->ifa_name = names;
+               names[sizeof(ifr->ifr_name)] = 0;
+               strncpy(names, ifr->ifr_name, sizeof(ifr->ifr_name));
+               while (*names++)
+                       ;
+
+               ift->ifa_addr = (struct sockaddr *)data;
+               sa = &ifr->ifr_addr;
+               memcpy(data, sa, SA_LEN(sa));
+               data += SA_RLEN(sa);
+               
+               ifr = (struct ifreq *)(((char *)sa) + SA_LEN(sa));
+               ift = (ift->ifa_next = ift + 1);
+       }
+#endif /* NET_RT_IFLIST */
+       if (--ift >= ifa) {
+               ift->ifa_next = NULL;
+               *pif = ifa;
+       } else {
+               *pif = NULL;
+               free(ifa);
+       }
+       return (0);
+}
+
+void
+freeifaddrs(struct ifaddrs *ifp)
+{
+       free(ifp);
+}
diff --git a/gen.subproj/getipnodebyname.3 b/gen.subproj/getipnodebyname.3
new file mode 100644 (file)
index 0000000..7d52521
--- /dev/null
@@ -0,0 +1,460 @@
+.\"    $FreeBSD: src/lib/libc/net/getipnodebyname.3,v 1.2.2.3 2001/08/17 15:42:38 ru Exp $
+.\"    $KAME: getipnodebyname.3,v 1.6 2000/08/09 21:16:17 itojun Exp $
+.\"
+.\" Copyright (c) 1983, 1987, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     From: @(#)gethostbyname.3      8.4 (Berkeley) 5/25/95
+.\"
+.Dd May 25, 1995
+.Dt GETIPNODEBYNAME 3
+.Os
+.\"
+.Sh NAME
+.Nm getipnodebyname ,
+.Nm getipnodebyaddr ,
+.Nm freehostent
+.Nd nodename-to-address and address-to-nodename translation
+.\"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/socket.h>
+.Fd #include <netdb.h>
+.Ft "struct hostent *"
+.Fn getipnodebyname "const char *name" "int af" "int flags" "int *error_num"
+.Ft "struct hostent *"
+.Fn getipnodebyaddr "const void *src" "size_t len" "int af" "int *error_num"
+.Ft void
+.Fn freehostent "struct hostent *ptr"
+.\"
+.Sh DESCRIPTION
+.Fn getipnodebyname
+and
+.Fn getipnodebyaddr
+functions are very similar to
+.Xr gethostbyname 3 ,
+.Xr gethostbyname2 3
+and
+.Xr gethostbyaddr 3 .
+The functions cover all the functionalities provided by the older ones,
+and provide better interface to programmers.
+The functions require additional arguments,
+.Ar af ,
+and
+.Ar flags ,
+for specifying address family and operation mode.
+The additional arguments allow programmer to get address for a nodename,
+for specific address family
+(such as
+.Dv AF_INET
+or
+.Dv AF_INET6 ) .
+The functions also require an additional pointer argument,
+.Ar error_num
+to return the appropriate error code,
+to support thread safe error code returns.
+.Pp
+The type and usage of the return value,
+.Li "struct hostent"
+is described in
+.Xr gethostbyname 3 .
+.Pp
+For
+.Fn getipnodebyname ,
+the
+.Ar name
+argument can be either a node name or a numeric address
+string
+(i.e., a dotted-decimal IPv4 address or an IPv6 hex address).
+The
+.Ar af
+argument specifies the address family, either
+.Dv AF_INET
+or
+.Dv AF_INET6 .
+The
+.Ar flags
+argument specifies the types of addresses that are searched for,
+and the types of addresses that are returned.
+We note that a special flags value of
+.Dv AI_DEFAULT
+(defined below)
+should handle most applications.
+That is, porting simple applications to use IPv6 replaces the call
+.Bd -literal -offset
+   hptr = gethostbyname(name);
+.Ed
+.Pp
+with
+.Bd -literal -offset
+   hptr = getipnodebyname(name, AF_INET6, AI_DEFAULT, &error_num);
+.Ed
+.Pp
+Applications desiring finer control over the types of addresses
+searched for and returned, can specify other combinations of the
+.Ar flags
+argument.
+.Pp
+A
+.Ar flags
+of
+.Li 0
+implies a strict interpretation of the
+.Ar af
+argument:
+.Bl -bullet
+.It
+If
+.Ar flags
+is 0 and
+.Ar af
+is
+.Dv AF_INET ,
+then the caller wants only IPv4 addresses.
+A query is made for
+.Li A
+records.
+If successful, the IPv4 addresses are returned and the
+.Li h_length
+member of the
+.Li hostent
+structure will be 4, else the function returns a
+.Dv NULL
+pointer.
+.It
+If
+.Ar flags
+is 0 and if
+.Ar af
+is
+.Li AF_INET6 ,
+then the caller wants only IPv6 addresses.
+A query is made for
+.Li AAAA
+records.
+If successful, the IPv6 addresses are returned and the
+.Li h_length
+member of the
+.Li hostent
+structure will be 16, else the function returns a
+.Dv NULL
+pointer.
+.El
+.Pp
+Other constants can be logically-ORed into the
+.Ar flags
+argument, to modify the behavior of the function.
+.Bl -bullet
+.It
+If the
+.Dv AI_V4MAPPED
+flag is specified along with an
+.Ar af
+of
+.Dv AF_INET6 ,
+then the caller will accept IPv4-mapped IPv6 addresses.
+That is, if no
+.Li AAAA
+records are found then a query is made for
+.Li A
+records and any found are returned as IPv4-mapped IPv6 addresses
+.Li ( h_length
+will be 16).
+The
+.Dv AI_V4MAPPED
+flag is ignored unless
+.Ar af
+equals
+.Dv AF_INET6 .
+.It
+The
+.Dv AI_V4MAPPED_CFG
+flag is exact same as the
+.Dv AI_V4MAPPED
+flag only if the kernel supports IPv4-mapped IPv6 address.
+.It
+If the
+.Dv AI_ALL
+flag is used in conjunction with the
+.Dv AI_V4MAPPED
+flag, and only used with the IPv6 address family.
+When
+.Dv AI_ALL
+is logically or'd with
+.Dv AI_V4MAPPED
+flag then the caller wants all addresses: IPv6 and IPv4-mapped IPv6.
+A query is first made for
+.Li AAAA
+records and if successful, the
+IPv6 addresses are returned.  Another query is then made for
+.Li A
+records and any found are returned as IPv4-mapped IPv6 addresses.
+.Li h_length
+will be 16.  Only if both queries fail does the function
+return a
+.Dv NULL
+pointer.  This flag is ignored unless af equals
+AF_INET6.  If both
+.Dv AI_ALL
+and
+.Dv AI_V4MAPPED
+are specified,
+.Dv AI_ALL
+takes precedence.
+.It
+The
+.Dv AI_ADDRCONFIG
+flag specifies that a query for
+.Li AAAA
+records
+should occur only if the node has at least one IPv6 source
+address configured and a query for
+.Li A
+records should occur only if the node has at least one IPv4 source address
+configured.
+.Pp
+For example, if the node has no IPv6 source addresses configured,
+and
+.Ar af
+equals AF_INET6, and the node name being looked up has both
+.Li AAAA
+and
+.Li A
+records, then:
+(a) if only
+.Dv AI_ADDRCONFIG
+is
+specified, the function returns a
+.Dv NULL
+pointer;
+(b) if
+.Dv AI_ADDRCONFIG
+|
+.Dv AI_V4MAPPED
+is specified, the
+.Li A
+records are returned as IPv4-mapped IPv6 addresses;
+.El
+.Pp
+The special flags value of
+.Dv AI_DEFAULT
+is defined as
+.Bd -literal -offset
+   #define  AI_DEFAULT  (AI_V4MAPPED_CFG | AI_ADDRCONFIG)
+.Ed
+.Pp
+We noted that the
+.Fn getipnodebyname
+function must allow the
+.Ar name
+argument to be either a node name or a literal address string
+(i.e., a dotted-decimal IPv4 address or an IPv6 hex address).
+This saves applications from having to call
+.Xr inet_pton 3
+to handle literal address strings.
+When the
+.Ar name
+argument is a literal address string,
+the
+.Ar flags
+argument is always ignored.
+.Pp
+There are four scenarios based on the type of literal address string
+and the value of the
+.Ar af
+argument.
+The two simple cases are when
+.Ar name
+is a dotted-decimal IPv4 address and
+.Ar af
+equals
+.Dv AF_INET ,
+or when
+.Ar name
+is an IPv6 hex address and
+.Ar af
+equals
+.Dv AF_INET6 .
+The members of the
+returned hostent structure are:
+.Li h_name
+points to a copy of the
+.Ar name
+argument,
+.Li h_aliases
+is a
+.Dv NULL
+pointer,
+.Li h_addrtype
+is a copy of the
+.Ar af
+argument,
+.Li h_length
+is either 4
+(for
+.Dv AF_INET )
+or 16
+(for
+.Dv AF_INET6 ) ,
+.Li h_addr_list[0]
+is a pointer to the 4-byte or 16-byte binary address,
+and
+.Li h_addr_list[1]
+is a
+.Dv NULL
+pointer.
+.Pp
+When
+.Ar name
+is a dotted-decimal IPv4 address and
+.Ar af
+equals
+.Dv AF_INET6 ,
+and
+.Dv AI_V4MAPPED
+is specified,
+an IPv4-mapped IPv6 address is returned:
+.Li h_name
+points to an IPv6 hex address containing the IPv4-mapped IPv6 address,
+.Li h_aliases
+is a
+.Dv NULL
+pointer,
+.Li h_addrtype
+is
+.Dv AF_INET6 ,
+.Li h_length
+is 16,
+.Li h_addr_list[0]
+is a pointer to the 16-byte binary address, and
+.Li h_addr_list[1]
+is a
+.Dv NULL
+pointer.
+.Pp
+It is an error when
+.Ar name
+is an IPv6 hex address and
+.Ar af
+equals
+.Dv AF_INET .
+The function's return value is a
+.Dv NULL
+pointer and the value pointed to by
+.Ar error_num
+equals
+.Dv HOST_NOT_FOUND .
+.Pp
+.Fn getipnodebyaddr
+takes almost the same argument as
+.Xr gethostbyaddr 3 ,
+but adds a pointer to return an error number.
+Additionally it takes care of IPv4-mapped IPv6 addresses,
+and IPv4-compatible IPv6 addresses.
+.Pp
+.Fn getipnodebyname
+and
+.Fn getipnodebyaddr
+dynamically allocate the structure to be returned to the caller.
+.Fn freehostent
+reclaims memory region allocated and returned by
+.Fn getipnodebyname
+or
+.Fn getipnodebyaddr .
+.\"
+.Sh FILES
+.Bl -tag -width /etc/resolv.conf -compact
+.It Pa /etc/hosts
+.It Pa /etc/host.conf
+.It Pa /etc/resolv.conf
+.El
+.\"
+.Sh DIAGNOSTICS
+.Fn getipnodebyname
+and
+.Fn getipnodebyaddr
+returns
+.Dv NULL
+on errors.
+The integer values pointed to by
+.Ar error_num
+may then be checked to see whether this is a temporary failure
+or an invalid or unknown host.
+The meanings of each error code are described in
+.Xr gethostbyname 3 .
+.\"
+.Sh SEE ALSO
+.Xr gethostbyaddr 3 ,
+.Xr gethostbyname 3 ,
+.Xr hosts 5 ,
+.Xr services 5 ,
+.Xr hostname 7 ,
+.Xr named 8
+.Pp
+.Rs
+.%A R. Gilligan
+.%A S. Thomson
+.%A J. Bound
+.%A W. Stevens
+.%T Basic Socket Interface Extensions for IPv6
+.%R RFC2553
+.%D March 1999
+.Re
+.\"
+.Sh HISTORY
+The implementation first appeared in KAME advanced networking kit.
+.\"
+.Sh STANDARDS
+.Fn getipnodebyname
+and
+.Fn getipnodebyaddr
+are documented in
+.Dq Basic Socket Interface Extensions for IPv6
+(RFC2553).
+.\"
+.Sh BUGS
+.Fn getipnodebyname
+and
+.Fn getipnodebyaddr
+do not handle scoped IPv6 address properly.
+If you use these functions,
+your program will not be able to handle scoped IPv6 addresses.
+For IPv6 address manipulation,
+.Fn getaddrinfo 3
+and
+.Fn getnameinfo 3
+are recommended.
+.Pp
+The current implementation is not thread-safe.
+.Pp
+The text was shamelessly copied from RFC2553.
diff --git a/gen.subproj/getnameinfo.3 b/gen.subproj/getnameinfo.3
new file mode 100644 (file)
index 0000000..ce36d8a
--- /dev/null
@@ -0,0 +1,311 @@
+.\"    $FreeBSD: src/lib/libc/net/getnameinfo.3,v 1.2.2.7 2001/08/17 15:42:38 ru Exp $
+.\"    $KAME: getnameinfo.3,v 1.17 2000/08/09 21:16:17 itojun Exp $
+.\"
+.\" Copyright (c) 1983, 1987, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     From: @(#)gethostbyname.3      8.4 (Berkeley) 5/25/95
+.\"
+.Dd May 25, 1995
+.Dt GETNAMEINFO 3
+.Os
+.\"
+.Sh NAME
+.Nm getnameinfo
+.Nd address-to-nodename translation in protocol-independent manner
+.\"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/socket.h>
+.Fd #include <netdb.h>
+.Ft int
+.Fn getnameinfo "const struct sockaddr *sa" "socklen_t salen" \
+"char *host" "size_t hostlen" "char *serv" "size_t servlen" "int flags"
+.\"
+.Sh DESCRIPTION
+The
+.Fn getnameinfo
+function is defined for protocol-independent address-to-nodename translation.
+Its functionality is a reverse conversion of
+.Xr getaddrinfo 3 ,
+and implements similar functionality with
+.Xr gethostbyaddr 3
+and
+.Xr getservbyport 3
+in more sophisticated manner.
+.Pp
+This function looks up an IP address and port number provided by the
+caller in the DNS and system-specific database, and returns text
+strings for both in buffers provided by the caller.
+The function indicates successful completion by a zero return value;
+a non-zero return value indicates failure.
+.Pp
+The first argument,
+.Fa sa ,
+points to either a
+.Li sockaddr_in
+structure (for IPv4) or a
+.Li sockaddr_in6
+structure (for IPv6) that holds the IP address and port number.
+The
+.Fa salen
+argument gives the length of the
+.Li sockaddr_in
+or
+.Li sockaddr_in6
+structure.
+.Pp
+The function returns the nodename associated with the IP address in
+the buffer pointed to by the
+.Fa host
+argument.
+The caller provides the size of this buffer via the
+.Fa hostlen
+argument.
+The service name associated with the port number is returned in the buffer
+pointed to by
+.Fa serv ,
+and the
+.Fa servlen
+argument gives the length of this buffer.
+The caller specifies not to return either string by providing a zero
+value for the
+.Fa hostlen
+or
+.Fa servlen
+arguments.
+Otherwise, the caller must provide buffers large enough to hold the
+nodename and the service name, including the terminating null characters.
+.Pp
+Unfortunately most systems do not provide constants that specify the
+maximum size of either a fully-qualified domain name or a service name.
+Therefore to aid the application in allocating buffers for these two
+returned strings the following constants are defined in
+.Aq Pa netdb.h :
+.Bd -literal -offset
+#define NI_MAXHOST  1025
+#define NI_MAXSERV    32
+.Ed
+.Pp
+The first value is actually defined as the constant
+.Dv MAXDNAME
+in recent versions of BIND's
+.Aq Pa arpa/nameser.h
+header
+(older versions of BIND define this constant to be 256)
+and the second is a guess based on the services listed in the current
+Assigned Numbers RFC.
+.Pp
+The final argument is a
+.Fa flag
+that changes the default actions of this function.
+By default the fully-qualified domain name (FQDN) for the host is
+looked up in the DNS and returned.
+If the flag bit
+.Dv NI_NOFQDN
+is set, only the nodename portion of the FQDN is returned for local hosts.
+.Pp
+If the
+.Fa flag
+bit
+.Dv NI_NUMERICHOST
+is set, or if the host's name cannot be located in the DNS,
+the numeric form of the host's address is returned instead of its name
+(e.g., by calling
+.Fn inet_ntop
+instead of
+.Fn getnodebyaddr ) .
+If the
+.Fa flag
+bit
+.Dv NI_NAMEREQD
+is set, an error is returned if the host's name cannot be located in the DNS.
+.Pp
+If the flag bit
+.Dv NI_NUMERICSERV
+is set, the numeric form of the service address is returned
+(e.g., its port number)
+instead of its name.
+The two
+.Dv NI_NUMERICxxx
+flags are required to support the
+.Fl n
+flag that many commands provide.
+.Pp
+A fifth flag bit,
+.Dv NI_DGRAM ,
+specifies that the service is a datagram service, and causes
+.Fn getservbyport
+to be called with a second argument of
+.Dq udp
+instead of its default of
+.Dq tcp .
+This is required for the few ports (512-514)
+that have different services for UDP and TCP.
+.Pp
+These
+.Dv NI_xxx
+flags are defined in
+.Aq Pa netdb.h .
+.\"
+.Sh EXTENSION
+The implementation allows experimental numeric IPv6 address notation with
+scope identifier.
+IPv6 link-local address will appear as string like
+.Dq Li fe80::1%ne0 ,
+if
+.Dv NI_WITHSCOPEID
+bit is enabled in
+.Ar flags
+argument.
+Refer to
+.Xr getaddrinfo 3
+for the notation.
+.\"
+.Sh EXAMPLES
+The following code tries to get numeric hostname, and service name,
+for given socket address.
+Observe that there is no hardcoded reference to particular address family.
+.Bd -literal -offset indent
+struct sockaddr *sa;   /* input */
+char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
+
+if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), sbuf,
+    sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
+       errx(1, "could not get numeric hostname");
+       /*NOTREACHED*/
+}
+printf("host=%s, serv=%s\\n", hbuf, sbuf);
+.Ed
+.Pp
+The following version checks if the socket address has reverse address mapping.
+.Bd -literal -offset indent
+struct sockaddr *sa;   /* input */
+char hbuf[NI_MAXHOST];
+
+if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
+    NI_NAMEREQD)) {
+       errx(1, "could not resolve hostname");
+       /*NOTREACHED*/
+}
+printf("host=%s\\n", hbuf);
+.Ed
+.\"
+.Sh FILES
+.Bl -tag -width /etc/resolv.conf -compact
+.It Pa /etc/hosts
+.It Pa /etc/host.conf
+.It Pa /etc/resolv.conf
+.El
+.\"
+.Sh DIAGNOSTICS
+The function indicates successful completion by a zero return value;
+a non-zero return value indicates failure.
+Error codes are as below:
+.Bl -tag -width Er
+.It Bq Er EAI_AGAIN
+The name could not be resolved at this time.
+Future attempts may succeed.
+.It Bq Er EAI_BADFLAGS
+The flags had an invalid value.
+.It Bq Er EAI_FAIL
+A non-recoverable error occurred.
+.It Bq Er EAI_FAMILY
+The address family was not recognized or the address length was invalid
+for the specified family.
+.It Bq Er EAI_MEMORY
+There was a memory allocation failure.
+.It Bq Er EAI_NONAME
+The name does not resolve for the supplied parameters.
+.Dv NI_NAMEREQD
+is set and the host's name cannot be located,
+or both nodename and servname were null.
+.It Bq Er EAI_SYSTEM
+A system error occurred.
+The error code can be found in errno.
+.El
+.\"
+.Sh SEE ALSO
+.Xr getaddrinfo 3 ,
+.Xr gethostbyaddr 3 ,
+.Xr getservbyport 3 ,
+.Xr hosts 5 ,
+.Xr services 5 ,
+.Xr hostname 7 ,
+.Xr named 8
+.Pp
+.Rs
+.%A R. Gilligan
+.%A S. Thomson
+.%A J. Bound
+.%A W. Stevens
+.%T Basic Socket Interface Extensions for IPv6
+.%R RFC2553
+.%D March 1999
+.Re
+.Rs
+.%A Tatsuya Jinmei
+.%A Atsushi Onoe
+.%T "An Extension of Format for IPv6 Scoped Addresses"
+.%R internet draft
+.%N draft-ietf-ipngwg-scopedaddr-format-02.txt
+.%O work in progress material
+.Re
+.Rs
+.%A Craig Metz
+.%T Protocol Independence Using the Sockets API
+.%B "Proceedings of the freenix track: 2000 USENIX annual technical conference"
+.%D June 2000
+.Re
+.\"
+.Sh HISTORY
+The implementation first appeared in WIDE Hydrangea IPv6 protocol stack kit.
+.\"
+.Sh STANDARDS
+The
+.Fn getaddrinfo
+function is defined in
+.St -p1003.1g-2000 ,
+and documented in
+.Dq Basic Socket Interface Extensions for IPv6
+(RFC2553).
+.\"
+.Sh BUGS
+The current implementation is not thread-safe.
+.Pp
+The text was shamelessly copied from RFC2553.
+.Pp
+The type of the 2nd argument should be
+.Li socklen_t
+for RFC2553 conformance.
+The current code is based on pre-RFC2553 specification.
diff --git a/gen.subproj/getnameinfo.c b/gen.subproj/getnameinfo.c
new file mode 100644 (file)
index 0000000..2f71a73
--- /dev/null
@@ -0,0 +1,384 @@
+/*     $FreeBSD: src/lib/libc/net/getnameinfo.c,v 1.5 2000/07/05 05:09:17 itojun Exp $ */
+/*     $KAME: getnameinfo.c,v 1.43 2000/06/12 04:27:03 itojun Exp $    */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Issues to be discussed:
+ * - Thread safe-ness must be checked
+ * - Return values.  There seems to be no standard for return value (RFC2553)
+ *   but INRIA implementation returns EAI_xxx defined for getaddrinfo().
+ * - RFC2553 says that we should raise error on short buffer.  X/Open says
+ *   we need to truncate the result.  We obey RFC2553 (and X/Open should be
+ *   modified).
+ * - What is "local" in NI_FQDN?
+ * - NI_NAMEREQD and NI_NUMERICHOST conflict with each other.
+ * - (KAME extension) NI_WITHSCOPEID when called with global address,
+ *   and sin6_scope_id filled
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <string.h>
+#include <stddef.h>
+#include <errno.h>
+
+#define SUCCESS 0
+#define ANY 0
+#define YES 1
+#define NO  0
+
+static struct afd {
+       int a_af;
+       int a_addrlen;
+       int a_socklen;
+       int a_off;
+} afdl [] = {
+#ifdef INET6
+       {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
+               offsetof(struct sockaddr_in6, sin6_addr)},
+#endif
+       {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
+               offsetof(struct sockaddr_in, sin_addr)},
+       {0, 0, 0},
+};
+
+struct sockinet {
+       u_char  si_len;
+       u_char  si_family;
+       u_short si_port;
+};
+
+
+#ifdef INET6
+static int ip6_parsenumeric __P((const struct sockaddr *, const char *, char *,
+                                size_t, int));
+static int ip6_sa2str __P((const struct sockaddr_in6 *, char *, size_t, int));
+#endif
+
+#define ENI_NOSOCKET   EAI_FAIL                /*XXX*/
+#define ENI_NOSERVNAME EAI_NONAME
+#define ENI_NOHOSTNAME EAI_NONAME
+#define ENI_MEMORY     EAI_MEMORY
+#define ENI_SYSTEM     EAI_SYSTEM
+#define ENI_FAMILY     EAI_FAMILY
+#define ENI_SALEN      EAI_FAMILY
+
+int
+getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
+       const struct sockaddr *sa;
+       size_t salen;
+       char *host;
+       size_t hostlen;
+       char *serv;
+       size_t servlen;
+       int flags;
+{
+       struct afd *afd;
+       struct servent *sp;
+       struct hostent *hp;
+       u_short port;
+       int family, i;
+       const char *addr;
+       u_int32_t v4a;
+       char numserv[512];
+       char numaddr[512];
+
+       if (sa == NULL)
+               return ENI_NOSOCKET;
+
+#ifdef NOTDEF
+       if (sa->sa_len != salen)
+               return ENI_SALEN;
+#endif
+       
+       family = sa->sa_family;
+       for (i = 0; afdl[i].a_af; i++)
+               if (afdl[i].a_af == family) {
+                       afd = &afdl[i];
+                       goto found;
+               }
+       return ENI_FAMILY;
+       
+ found:
+       if (salen != afd->a_socklen)
+               return ENI_SALEN;
+       
+       /* network byte order */
+       port = ((const struct sockinet *)sa)->si_port;
+       addr = (const char *)sa + afd->a_off;
+
+       if (serv == NULL || servlen == 0) {
+               /*
+                * do nothing in this case.
+                * in case you are wondering if "&&" is more correct than
+                * "||" here: RFC2553 says that serv == NULL OR servlen == 0
+                * means that the caller does not want the result.
+                */
+       } else {
+               if (flags & NI_NUMERICSERV)
+                       sp = NULL;
+               else {
+                       sp = getservbyport(port,
+                               (flags & NI_DGRAM) ? "udp" : "tcp");
+               }
+               if (sp) {
+                       if (strlen(sp->s_name) > servlen)
+                               return ENI_MEMORY;
+                       strcpy(serv, sp->s_name);
+               } else {
+                       snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
+                       if (strlen(numserv) > servlen)
+                               return ENI_MEMORY;
+                       strcpy(serv, numserv);
+               }
+       }
+
+       switch (sa->sa_family) {
+       case AF_INET:
+               v4a = (u_int32_t)
+                   ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr);
+               if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
+                       flags |= NI_NUMERICHOST;
+               v4a >>= IN_CLASSA_NSHIFT;
+               if (v4a == 0)
+                       flags |= NI_NUMERICHOST;                        
+               break;
+#ifdef INET6
+       case AF_INET6:
+           {
+               const struct sockaddr_in6 *sin6;
+               sin6 = (const struct sockaddr_in6 *)sa;
+               switch (sin6->sin6_addr.s6_addr[0]) {
+               case 0x00:
+                       if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
+                               ;
+                       else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
+                               ;
+                       else
+                               flags |= NI_NUMERICHOST;
+                       break;
+               default:
+                       if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+                               flags |= NI_NUMERICHOST;
+                       }
+                       else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
+                               flags |= NI_NUMERICHOST;
+                       break;
+               }
+           }
+               break;
+#endif
+       }
+       if (host == NULL || hostlen == 0) {
+               /*
+                * do nothing in this case.
+                * in case you are wondering if "&&" is more correct than
+                * "||" here: RFC2553 says that host == NULL OR hostlen == 0
+                * means that the caller does not want the result.
+                */
+       } else if (flags & NI_NUMERICHOST) {
+               int numaddrlen;
+
+               /* NUMERICHOST and NAMEREQD conflicts with each other */
+               if (flags & NI_NAMEREQD)
+                       return ENI_NOHOSTNAME;
+
+               switch(afd->a_af) {
+#ifdef INET6
+               case AF_INET6:
+               {
+                       int error;
+
+                       if ((error = ip6_parsenumeric(sa, addr, host,
+                                                     hostlen, flags)) != 0)
+                               return(error);
+                       break;
+               }
+#endif
+               default:
+                       if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
+                           == NULL)
+                               return ENI_SYSTEM;
+                       numaddrlen = strlen(numaddr);
+                       if (numaddrlen + 1 > hostlen) /* don't forget terminator */
+                               return ENI_MEMORY;
+                       strcpy(host, numaddr);
+                       break;
+               }
+       } else {
+#if 0
+               int h_error;
+               hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
+#else
+               hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
+#endif
+
+               if (hp) {
+#if 0
+                       /*
+                        * commented out, since "for local host" is not
+                        * implemented here - see RFC2553 p30
+                        */
+                       if (flags & NI_NOFQDN) {
+                               char *p;
+                               p = strchr(hp->h_name, '.');
+                               if (p)
+                                       *p = '\0';
+                       }
+#endif
+                       if (strlen(hp->h_name) > hostlen) {
+#if 0
+                               freehostent(hp);
+#endif
+                               return ENI_MEMORY;
+                       }
+                       strcpy(host, hp->h_name);
+#if 0
+                       freehostent(hp);
+#endif
+               } else {
+                       if (flags & NI_NAMEREQD)
+                               return ENI_NOHOSTNAME;
+                       switch(afd->a_af) {
+#ifdef INET6
+                       case AF_INET6:
+                       {
+                               int error;
+
+                               if ((error = ip6_parsenumeric(sa, addr, host,
+                                                             hostlen,
+                                                             flags)) != 0)
+                                       return(error);
+                               break;
+                       }
+#endif
+                       default:
+                               if (inet_ntop(afd->a_af, addr, host,
+                                   hostlen) == NULL)
+                                       return ENI_SYSTEM;
+                               break;
+                       }
+               }
+       }
+       return SUCCESS;
+}
+
+#ifdef INET6
+static int
+ip6_parsenumeric(sa, addr, host, hostlen, flags)
+       const struct sockaddr *sa;
+       const char *addr;
+       char *host;
+       size_t hostlen;
+       int flags;
+{
+       int numaddrlen;
+       char numaddr[512];
+
+       if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr))
+           == NULL)
+               return ENI_SYSTEM;
+
+       numaddrlen = strlen(numaddr);
+       if (numaddrlen + 1 > hostlen) /* don't forget terminator */
+               return ENI_MEMORY;
+       strcpy(host, numaddr);
+
+#ifdef NI_WITHSCOPEID
+       if (
+#ifdef DONT_OPAQUE_SCOPEID
+           (IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)addr) ||
+            IN6_IS_ADDR_MULTICAST((struct in6_addr *)addr)) &&
+#endif
+           ((const struct sockaddr_in6 *)sa)->sin6_scope_id) {
+#ifndef ALWAYS_WITHSCOPE
+               if (flags & NI_WITHSCOPEID)
+#endif /* !ALWAYS_WITHSCOPE */
+               {
+                       char scopebuf[MAXHOSTNAMELEN];
+                       int scopelen;
+
+                       /* ip6_sa2str never fails */
+                       scopelen = ip6_sa2str((const struct sockaddr_in6 *)sa,
+                                             scopebuf, sizeof(scopebuf),
+                                             flags);
+                       if (scopelen + 1 + numaddrlen + 1 > hostlen)
+                               return ENI_MEMORY;
+                       /*
+                        * construct <numeric-addr><delim><scopeid>
+                        */
+                       memcpy(host + numaddrlen + 1, scopebuf,
+                              scopelen);
+                       host[numaddrlen] = SCOPE_DELIMITER;
+                       host[numaddrlen + 1 + scopelen] = '\0';
+               }
+       }
+#endif /* NI_WITHSCOPEID */
+
+       return 0;
+}
+
+/* ARGSUSED */
+static int
+ip6_sa2str(sa6, buf, bufsiz, flags)
+       const struct sockaddr_in6 *sa6;
+       char *buf;
+       size_t bufsiz;
+       int flags;
+{
+       unsigned int ifindex = (unsigned int)sa6->sin6_scope_id;
+       const struct in6_addr *a6 = &sa6->sin6_addr;
+
+#ifdef NI_NUMERICSCOPE
+       if (flags & NI_NUMERICSCOPE) {
+               return(snprintf(buf, bufsiz, "%d", sa6->sin6_scope_id));
+       }
+#endif
+
+       /* if_indextoname() does not take buffer size.  not a good api... */
+       if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) &&
+           bufsiz >= IF_NAMESIZE) {
+               char *p = if_indextoname(ifindex, buf);
+               if (p) {
+                       return(strlen(p));
+               }
+       }
+
+       /* last resort */
+       return(snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id));
+}
+#endif /* INET6 */
diff --git a/gen.subproj/getnetent.3 b/gen.subproj/getnetent.3
new file mode 100644 (file)
index 0000000..d53c5c9
--- /dev/null
@@ -0,0 +1,162 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)getnetent.3        8.1 (Berkeley) 6/4/93
+.\" $FreeBSD: src/lib/libc/net/getnetent.3,v 1.11.2.3 2001/08/17 15:42:38 ru Exp $
+.\"
+.Dd June 4, 1993
+.Dt GETNETENT 3
+.Os
+.Sh NAME
+.Nm getnetent ,
+.Nm getnetbyaddr ,
+.Nm getnetbyname ,
+.Nm setnetent ,
+.Nm endnetent
+.Nd get network entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.Fd #include <netdb.h>
+.Ft struct netent *
+.Fn getnetent void
+.Ft struct netent *
+.Fn getnetbyname "const char *name"
+.Ft struct netent *
+.Fn getnetbyaddr "unsigned long net" "int type"
+.Ft void
+.Fn setnetent "int stayopen"
+.Ft void
+.Fn endnetent void
+.Sh DESCRIPTION
+The
+.Fn getnetent ,
+.Fn getnetbyname ,
+and
+.Fn getnetbyaddr
+functions
+each return a pointer to an object with the
+following structure
+containing the broken-out
+fields of a line in the network data base,
+.Pa /etc/networks .
+.Bd -literal -offset indent
+struct netent {
+       char            *n_name;        /* official name of net */
+       char            **n_aliases;    /* alias list */
+       int             n_addrtype;     /* net number type */
+       unsigned long   n_net;          /* net number */
+};
+.Ed
+.Pp
+The members of this structure are:
+.Bl -tag -width n_addrtype
+.It Fa n_name
+The official name of the network.
+.It Fa n_aliases
+A zero terminated list of alternate names for the network.
+.It Fa n_addrtype
+The type of the network number returned; currently only AF_INET.
+.It Fa n_net
+The network number.  Network numbers are returned in machine byte
+order.
+.El
+.Pp
+The
+.Fn getnetent
+function
+reads the next line of the file, opening the file if necessary.
+.Pp
+The
+.Fn setnetent
+function
+opens and rewinds the file.  If the
+.Fa stayopen
+flag is non-zero,
+the net data base will not be closed after each call to
+.Fn getnetbyname
+or
+.Fn getnetbyaddr .
+.Pp
+The
+.Fn endnetent
+function
+closes the file.
+.Pp
+The
+.Fn getnetbyname
+function
+and
+.Fn getnetbyaddr
+sequentially search from the beginning
+of the file until a matching
+net name or
+net address and type is found,
+or until
+.Dv EOF
+is encountered.
+The
+.Fa type
+must be
+.Dv AF_INET .
+Network numbers are supplied in host order.
+.Sh FILES
+.Bl -tag -width /etc/networks -compact
+.It Pa /etc/networks
+.El
+.Sh DIAGNOSTICS
+Null pointer
+(0) returned on
+.Dv EOF
+or error.
+.Sh SEE ALSO
+.Xr networks 5
+.Pp
+.%T RFC 1101
+.Sh HISTORY
+The
+.Fn getnetent ,
+.Fn getnetbyaddr ,
+.Fn getnetbyname ,
+.Fn setnetent ,
+and
+.Fn endnetent
+functions appeared in
+.Bx 4.2 .
+.Sh BUGS
+The data space used by
+these functions is static; if future use requires the data, it should be
+copied before any subsequent calls to these functions overwrite it.
+Only Internet network
+numbers are currently understood.
+Expecting network numbers to fit
+in no more than 32 bits is probably
+naive.
index 0c3634ef055a08afecb7923cff6879b482d20e7e..1f09b7c6203897dfc2dde0d44946bad0e5eee3db 100644 (file)
@@ -69,7 +69,7 @@ getprotobynumber(proto)
        register struct protoent *p;
 
        setprotoent(_proto_stayopen);
-       while (p = getprotoent())
+       while ((p = getprotoent()))
                if (p->p_proto == proto)
                        break;
        if (!_proto_stayopen)
diff --git a/gen.subproj/getprotoent.3 b/gen.subproj/getprotoent.3
new file mode 100644 (file)
index 0000000..e0fd91c
--- /dev/null
@@ -0,0 +1,149 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)getprotoent.3      8.1 (Berkeley) 6/4/93
+.\" $FreeBSD: src/lib/libc/net/getprotoent.3,v 1.4.2.3 2001/08/17 15:42:38 ru Exp $
+.\"
+.Dd June 4, 1993
+.Dt GETPROTOENT 3
+.Os
+.Sh NAME
+.Nm getprotoent ,
+.Nm getprotobynumber ,
+.Nm getprotobyname ,
+.Nm setprotoent ,
+.Nm endprotoent
+.Nd get protocol entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.Fd #include <netdb.h>
+.Ft struct protoent *
+.Fn getprotoent void
+.Ft struct protoent *
+.Fn getprotobyname "const char *name"
+.Ft struct protoent *
+.Fn getprotobynumber "int proto"
+.Ft void
+.Fn setprotoent "int stayopen"
+.Ft void
+.Fn endprotoent void
+.Sh DESCRIPTION
+The
+.Fn getprotoent ,
+.Fn getprotobyname ,
+and
+.Fn getprotobynumber
+functions
+each return a pointer to an object with the
+following structure
+containing the broken-out
+fields of a line in the network protocol data base,
+.Pa /etc/protocols .
+.Bd -literal -offset indent
+.Pp
+struct protoent {
+       char    *p_name;        /* official name of protocol */
+       char    **p_aliases;    /* alias list */
+       int     p_proto;        /* protocol number */
+};
+.Ed
+.Pp
+The members of this structure are:
+.Bl -tag -width p_aliases
+.It Fa p_name
+The official name of the protocol.
+.It Fa p_aliases
+A zero terminated list of alternate names for the protocol.
+.It Fa p_proto
+The protocol number.
+.El
+.Pp
+The
+.Fn getprotoent
+function
+reads the next line of the file, opening the file if necessary.
+.Pp
+The
+.Fn setprotoent
+function
+opens and rewinds the file.  If the
+.Fa stayopen
+flag is non-zero,
+the net data base will not be closed after each call to
+.Fn getprotobyname
+or
+.Fn getprotobynumber .
+.Pp
+The
+.Fn endprotoent
+function
+closes the file.
+.Pp
+The
+.Fn getprotobyname
+function
+and
+.Fn getprotobynumber
+sequentially search from the beginning
+of the file until a matching
+protocol name or
+protocol number is found,
+or until
+.Dv EOF
+is encountered.
+.Sh RETURN VALUES
+Null pointer
+(0) returned on
+.Dv EOF
+or error.
+.Sh FILES
+.Bl -tag -width /etc/protocols -compact
+.It Pa /etc/protocols
+.El
+.Sh SEE ALSO
+.Xr protocols 5
+.Sh HISTORY
+The
+.Fn getprotoent ,
+.Fn getprotobynumber ,
+.Fn getprotobyname ,
+.Fn setprotoent ,
+and
+.Fn endprotoent
+functions appeared in
+.Bx 4.2 .
+.Sh BUGS
+These functions use a static data space;
+if the data is needed for future use, it should be
+copied before any subsequent calls overwrite it.
+Only the Internet
+protocols are currently understood.
index 0320109deaf489e87aecdd1cc3c078e6aa35d166..ed158c9d29181e01017a9a13be2730c9f13b9933 100644 (file)
@@ -68,7 +68,6 @@ static char sccsid[] = "@(#)getprotoent.c     8.1 (Berkeley) 6/4/93";
 #define        MAXALIASES      35
 
 static FILE *protof = NULL;
-static char line[BUFSIZ+1];
 static struct protoent proto;
 static char *proto_aliases[MAXALIASES];
 int _proto_stayopen;
@@ -98,10 +97,17 @@ struct protoent *
 getprotoent()
 {
        char *p;
+       static char *line = NULL;
        register char *cp, **q;
 
        if (protof == NULL && (protof = fopen(_PATH_PROTOCOLS, "r" )) == NULL)
                return (NULL);
+
+       if (line == NULL) {
+               line = malloc(BUFSIZ+1);
+               if (line == NULL)
+                       return (NULL);
+       }
 again:
        if ((p = fgets(line, BUFSIZ, protof)) == NULL)
                return (NULL);
index 49551e1163a0eb2e28fefdb645b9e524398bc2ba..0e4b7f351712126b0dd6f2de0a5f74798227adf0 100644 (file)
@@ -71,7 +71,7 @@ getprotobyname(name)
        register char **cp;
 
        setprotoent(_proto_stayopen);
-       while (p = getprotoent()) {
+       while ((p = getprotoent())) {
                if (strcmp(p->p_name, name) == 0)
                        break;
                for (cp = p->p_aliases; *cp != 0; cp++)
index 45766e362c7791b7f3dd56217c8679b618818e6a..6139e9e804d23d5acd4b2c9603d287943679b4e4 100644 (file)
@@ -71,7 +71,7 @@ getservbyname(name, proto)
        register char **cp;
 
        setservent(_serv_stayopen);
-       while (p = getservent()) {
+       while ((p = getservent())) {
                if (strcmp(name, p->s_name) == 0)
                        goto gotname;
                for (cp = p->s_aliases; *cp; cp++)
index af3eeb0fd5b1900b08e9565d4c26329d39169e1e..4af1e107573dabbdee492cf321b8ba5b231a27db 100644 (file)
@@ -71,7 +71,7 @@ getservbyport(port, proto)
        register struct servent *p;
 
        setservent(_serv_stayopen);
-       while (p = getservent()) {
+       while ((p = getservent())) {
                if (p->s_port != port)
                        continue;
                if (proto == 0 || strcmp(p->s_proto, proto) == 0)
diff --git a/gen.subproj/getservent.3 b/gen.subproj/getservent.3
new file mode 100644 (file)
index 0000000..bcf5c23
--- /dev/null
@@ -0,0 +1,158 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     From: @(#)getservent.3 8.3 (Berkeley) 1/12/94
+.\" $FreeBSD: src/lib/libc/net/getservent.3,v 1.7.2.4 2001/08/17 15:42:38 ru Exp $
+.\"
+.Dd July 9, 1995
+.Dt GETSERVENT 3
+.Os
+.Sh NAME
+.Nm getservent ,
+.Nm getservbyport ,
+.Nm getservbyname ,
+.Nm setservent ,
+.Nm endservent
+.Nd get service entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.Fd #include <netdb.h>
+.Ft struct servent *
+.Fn getservent
+.Ft struct servent *
+.Fn getservbyname "const char *name" "const char *proto"
+.Ft struct servent *
+.Fn getservbyport "int port" "const char *proto"
+.Ft void
+.Fn setservent "int stayopen"
+.Ft void
+.Fn endservent void
+.Sh DESCRIPTION
+The
+.Fn getservent ,
+.Fn getservbyname ,
+and
+.Fn getservbyport
+functions
+each return a pointer to an object with the
+following structure
+containing the broken-out
+fields of a line in the network services data base,
+.Pa /etc/services .
+.Bd -literal -offset indent
+struct servent {
+       char    *s_name;        /* official name of service */
+       char    **s_aliases;    /* alias list */
+       int     s_port;         /* port service resides at */
+       char    *s_proto;       /* protocol to use */
+};
+.Ed
+.Pp
+The members of this structure are:
+.Bl -tag -width s_aliases
+.It Fa s_name
+The official name of the service.
+.It Fa s_aliases
+A zero terminated list of alternate names for the service.
+.It Fa s_port
+The port number at which the service resides.
+Port numbers are returned in network byte order.
+.It Fa s_proto
+The name of the protocol to use when contacting the
+service.
+.El
+.Pp
+The
+.Fn getservent
+function
+reads the next line of the file, opening the file if necessary.
+.Pp
+The
+.Fn setservent
+function
+opens and rewinds the file.  If the
+.Fa stayopen
+flag is non-zero,
+the net data base will not be closed after each call to
+.Fn getservbyname
+or
+.Fn getservbyport .
+.Pp
+The
+.Fn endservent
+function
+closes the file.
+.Pp
+The
+.Fn getservbyname
+and
+.Fn getservbyport
+functions
+sequentially search from the beginning
+of the file until a matching
+protocol name or
+port number (which must be specified in
+network byte order) is found,
+or until
+.Dv EOF
+is encountered.
+If a protocol name is also supplied (non-
+.Dv NULL ) ,
+searches must also match the protocol.
+.Sh FILES
+.Bl -tag -width /etc/services -compact
+.It Pa /etc/services
+.El
+.Sh DIAGNOSTICS
+Null pointer
+(0) returned on
+.Dv EOF
+or error.
+.Sh SEE ALSO
+.Xr getprotoent 3 ,
+.Xr services 5
+.Sh HISTORY
+The
+.Fn getservent ,
+.Fn getservbyport ,
+.Fn getservbyname ,
+.Fn setservent ,
+and
+.Fn endservent
+functions appeared in
+.Bx 4.2 .
+.Sh BUGS
+These functions use static data storage;
+if the data is needed for future use, it should be
+copied before any subsequent calls overwrite it.
+Expecting port numbers to fit in a 32 bit
+quantity is probably naive.
index 16d5cd983dda517a417aae750b17842d084b8701..134fb710fc6f5cba264cde756655327cb57c5759 100644 (file)
@@ -68,7 +68,6 @@ static char sccsid[] = "@(#)getservent.c      8.1 (Berkeley) 6/4/93";
 #define        MAXALIASES      35
 
 static FILE *servf = NULL;
-static char line[BUFSIZ+1];
 static struct servent serv;
 static char *serv_aliases[MAXALIASES];
 int _serv_stayopen;
@@ -98,10 +97,17 @@ struct servent *
 getservent()
 {
        char *p;
+       static char *line = NULL;
        register char *cp, **q;
 
        if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL)
                return (NULL);
+
+       if (line == NULL) {
+               line = malloc(BUFSIZ+1);
+               if (line == NULL)
+                       return (NULL);
+       }
 again:
        if ((p = fgets(line, BUFSIZ, servf)) == NULL)
                return (NULL);
diff --git a/gen.subproj/if_indextoname.3 b/gen.subproj/if_indextoname.3
new file mode 100644 (file)
index 0000000..9327c12
--- /dev/null
@@ -0,0 +1,142 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     From: @(#)rcmd.3       8.1 (Berkeley) 6/4/93
+.\"    $FreeBSD: src/lib/libc/net/if_indextoname.3,v 1.2.2.4 2001/08/17 15:42:38 ru Exp $
+.\"
+.Dd May 21, 1998
+.Dt IF_NAMETOINDEX 3
+.Os
+.Sh NAME
+.Nm if_nametoindex ,
+.Nm if_indextoname ,
+.Nm if_nameindex ,
+.Nm if_freenameindex
+.Nd convert interface index to name, and vice versa
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/socket.h>
+.Fd #include <net/if.h>
+.Ft "unsigned int"
+.Fn if_nametoindex "const char *ifname"
+.Ft "char *"
+.Fn if_indextoname "unsigned int ifindex" "char *ifname"
+.Ft "struct if_nameindex *"
+.Fn if_nameindex "void"
+.Ft "void"
+.Fn if_freenameindex "struct if_nameindex *ptr"
+.Sh DESCRIPTION
+The functions map interface index to readable interface name
+(such as
+.Dq Li lo0 ) ,
+and vice versa.
+.Pp
+.Fn if_nametoindex
+converts readable interface name to interface index
+.Pp positive integer value .
+If the specified interface does not exist, 0 will be returned.
+.Pp
+.Fn if_indextoname
+converts interface index to readable interface name.
+The
+.Fa ifname
+argument must point to a buffer of at least
+.Dv IF_NAMESIZE
+bytes into which the interface name corresponding to the specified index is
+returned.
+.Dv ( IF_NAMESIZE
+is also defined in
+.Aq Pa net/if.h
+and its value includes a terminating null byte at the end of the
+interface name.)
+This pointer is also the return value of the function.
+If there is no interface corresponding to the specified index,
+.Dv NULL
+is returned.
+.Pp
+.Fn if_nameindex
+returns an array of
+.Fa if_nameindex
+structures.
+.Fa if_nametoindex
+is also defined in
+.Aq Pa net/if.h ,
+and is as follows:
+.Bd -literal -offset
+struct if_nameindex {
+    unsigned int   if_index;  /* 1, 2, ... */
+    char          *if_name;   /* null terminated name: "le0", ... */
+};
+.Ed
+.Pp
+The end of the array of structures is indicated by a structure with
+an
+.Fa if_index
+of 0 and an
+.Fa if_name
+of
+.Dv NULL .
+The function returns a
+.Dv NULL
+pointer upon an error.
+The memory used for this array of structures along with the interface
+names pointed to by the
+.Fa if_name
+members is obtained dynamically.
+This memory is freed by the
+.Fn if_freenameindex
+function.
+.Pp
+.Fn if_freenameindex
+takes a pointer that was returned by
+.Fn if_nameindex
+as argument
+.Pq Fa ptr ,
+and it reclaims the region allocated.
+.Sh DIAGNOSTICS
+.Fn if_nametoindex
+returns 0 on error, positive integer on success.
+.Fn if_indextoname
+and
+.Fn if_nameindex
+return
+.Dv NULL
+on errors.
+.Sh SEE ALSO
+R. Gilligan, S.  Thomson, J. Bound, and W. Stevens,
+``Basic Socket Interface Extensions for IPv6,'' RFC2553, March 1999.
+.Sh HISTORY
+The implementation first appeared in WIDE Hydrangea IPv6 protocol stack kit.
+.Sh STANDARDS
+These functions are defined in ``Basic Socket Interface Extensions for IPv6''
+(RFC2533).
diff --git a/gen.subproj/if_indextoname.c b/gen.subproj/if_indextoname.c
new file mode 100644 (file)
index 0000000..e0e75a3
--- /dev/null
@@ -0,0 +1,85 @@
+/*     $KAME: if_indextoname.c,v 1.7 2000/11/08 03:09:30 itojun Exp $  */
+
+/*-
+ * Copyright (c) 1997, 2000
+ *     Berkeley Software Design, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     BSDI Id: if_indextoname.c,v 2.3 2000/04/17 22:38:05 dab Exp
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if_dl.h>
+#include <net/if.h>
+#include <ifaddrs.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+/*
+ * From RFC 2533:
+ *
+ * The second function maps an interface index into its corresponding
+ * name.
+ *
+ *    #include <net/if.h>
+ *
+ *    char  *if_indextoname(unsigned int ifindex, char *ifname);
+ *
+ * The ifname argument must point to a buffer of at least IF_NAMESIZE
+ * bytes into which the interface name corresponding to the specified
+ * index is returned.  (IF_NAMESIZE is also defined in <net/if.h> and
+ * its value includes a terminating null byte at the end of the
+ * interface name.) This pointer is also the return value of the
+ * function.  If there is no interface corresponding to the specified
+ * index, NULL is returned, and errno is set to ENXIO, if there was a
+ * system error (such as running out of memory), if_indextoname returns
+ * NULL and errno would be set to the proper value (e.g., ENOMEM).
+ */
+
+char *
+if_indextoname(unsigned int ifindex, char *ifname)
+{
+       struct ifaddrs *ifaddrs, *ifa;
+       int error = 0;
+
+       if (getifaddrs(&ifaddrs) < 0)
+               return(NULL);   /* getifaddrs properly set errno */
+
+       for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+               if (ifa->ifa_addr &&
+                   ifa->ifa_addr->sa_family == AF_LINK &&
+                   ifindex == ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index)
+                       break;
+       }
+
+       if (ifa == NULL) {
+               error = ENXIO;
+               ifname = NULL;
+       }
+       else
+               strncpy(ifname, ifa->ifa_name, IFNAMSIZ);
+
+       freeifaddrs(ifaddrs);
+
+       errno = error;
+       return(ifname);
+}
diff --git a/gen.subproj/if_nameindex.c b/gen.subproj/if_nameindex.c
new file mode 100644 (file)
index 0000000..eb91584
--- /dev/null
@@ -0,0 +1,146 @@
+/*     $KAME: if_nameindex.c,v 1.8 2000/11/24 08:20:01 itojun Exp $    */
+
+/*-
+ * Copyright (c) 1997, 2000
+ *     Berkeley Software Design, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     BSDI Id: if_nameindex.c,v 2.3 2000/04/17 22:38:05 dab Exp
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if_dl.h>
+#include <net/if.h>
+#include <ifaddrs.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * From RFC 2553:
+ *
+ * 4.3 Return All Interface Names and Indexes
+ *
+ *    The if_nameindex structure holds the information about a single
+ *    interface and is defined as a result of including the <net/if.h>
+ *    header.
+ *
+ *       struct if_nameindex {
+ *         unsigned int   if_index;
+ *         char          *if_name;
+ *       };
+ *
+ *    The final function returns an array of if_nameindex structures, one
+ *    structure per interface.
+ *
+ *       struct if_nameindex  *if_nameindex(void);
+ *
+ *    The end of the array of structures is indicated by a structure with
+ *    an if_index of 0 and an if_name of NULL.  The function returns a NULL
+ *    pointer upon an error, and would set errno to the appropriate value.
+ *
+ *    The memory used for this array of structures along with the interface
+ *    names pointed to by the if_name members is obtained dynamically.
+ *    This memory is freed by the next function.
+ *
+ * 4.4.  Free Memory
+ *
+ *    The following function frees the dynamic memory that was allocated by
+ *    if_nameindex().
+ *
+ *        #include <net/if.h>
+ *
+ *        void  if_freenameindex(struct if_nameindex *ptr);
+ *
+ *    The argument to this function must be a pointer that was returned by
+ *    if_nameindex().
+ */
+
+struct if_nameindex *
+if_nameindex(void)
+{
+       struct ifaddrs *ifaddrs, *ifa;
+       unsigned int ni;
+       int nbytes;
+       struct if_nameindex *ifni, *ifni2;
+       char *cp;
+
+       if (getifaddrs(&ifaddrs) < 0)
+               return(NULL);
+
+       /*
+        * First, find out how many interfaces there are, and how
+        * much space we need for the string names.
+        */
+       ni = 0;
+       nbytes = 0;
+       for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+               if (ifa->ifa_addr &&
+                   ifa->ifa_addr->sa_family == AF_LINK) {
+                       nbytes += strlen(ifa->ifa_name) + 1;
+                       ni++;
+               }
+       }
+
+       /*
+        * Next, allocate a chunk of memory, use the first part
+        * for the array of structures, and the last part for
+        * the strings.
+        */
+       cp = malloc((ni + 1) * sizeof(struct if_nameindex) + nbytes);
+       ifni = (struct if_nameindex *)cp;
+       if (ifni == NULL)
+               goto out;
+       cp += (ni + 1) * sizeof(struct if_nameindex);
+
+       /*
+        * Now just loop through the list of interfaces again,
+        * filling in the if_nameindex array and making copies
+        * of all the strings.
+        */
+       ifni2 = ifni;
+       for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+               if (ifa->ifa_addr &&
+                   ifa->ifa_addr->sa_family == AF_LINK) {
+                       ifni2->if_index =
+                           ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index;
+                       ifni2->if_name = cp;
+                       strcpy(cp, ifa->ifa_name);
+                       ifni2++;
+                       cp += strlen(cp) + 1;
+               }
+       }
+       /*
+        * Finally, don't forget to terminate the array.
+        */
+       ifni2->if_index = 0;
+       ifni2->if_name = NULL;
+out:
+       freeifaddrs(ifaddrs);
+       return(ifni);
+}
+
+#ifndef __OpenBSD__
+void
+if_freenameindex(struct if_nameindex *ptr)
+{
+       free(ptr);
+}
+#endif
diff --git a/gen.subproj/if_nametoindex.c b/gen.subproj/if_nametoindex.c
new file mode 100644 (file)
index 0000000..e1af130
--- /dev/null
@@ -0,0 +1,80 @@
+/*     $KAME: if_nametoindex.c,v 1.6 2000/11/24 08:18:54 itojun Exp $  */
+
+/*-
+ * Copyright (c) 1997, 2000
+ *     Berkeley Software Design, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     BSDI Id: if_nametoindex.c,v 2.3 2000/04/17 22:38:05 dab Exp
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <ifaddrs.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+/*
+ * From RFC 2553:
+ *
+ * 4.1 Name-to-Index
+ *
+ *
+ *    The first function maps an interface name into its corresponding
+ *    index.
+ *
+ *       #include <net/if.h>
+ *
+ *       unsigned int  if_nametoindex(const char *ifname);
+ *
+ *    If the specified interface name does not exist, the return value is
+ *    0, and errno is set to ENXIO.  If there was a system error (such as
+ *    running out of memory), the return value is 0 and errno is set to the
+ *    proper value (e.g., ENOMEM).
+ */
+
+unsigned int
+if_nametoindex(const char *ifname)
+{
+       struct ifaddrs *ifaddrs, *ifa;
+       unsigned int ni;
+
+       if (getifaddrs(&ifaddrs) < 0)
+               return(0);
+
+       ni = 0;
+
+       for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+               if (ifa->ifa_addr &&
+                   ifa->ifa_addr->sa_family == AF_LINK &&
+                   strcmp(ifa->ifa_name, ifname) == 0) {
+                       ni = ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index;
+                       break;
+               }
+       }
+
+       freeifaddrs(ifaddrs);
+       if (!ni)
+               errno = ENXIO;
+       return(ni);
+}
diff --git a/gen.subproj/ifaddrs.h b/gen.subproj/ifaddrs.h
new file mode 100644 (file)
index 0000000..cf32dae
--- /dev/null
@@ -0,0 +1,56 @@
+/*     $KAME: ifaddrs.h,v 1.3 2001/01/26 08:14:55 itojun Exp $ */
+
+/*
+ * Copyright (c) 1995, 1999
+ *     Berkeley Software Design, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp
+ */
+
+#ifndef        _IFADDRS_H_
+#define        _IFADDRS_H_
+
+struct ifaddrs {
+       struct ifaddrs  *ifa_next;
+       char            *ifa_name;
+       u_int            ifa_flags;
+       struct sockaddr *ifa_addr;
+       struct sockaddr *ifa_netmask;
+       struct sockaddr *ifa_dstaddr;
+       void            *ifa_data;
+};
+
+/*
+ * This may have been defined in <net/if.h>.  Note that if <net/if.h> is
+ * to be included it must be included before this header file.
+ */
+#ifndef        ifa_broadaddr
+#define        ifa_broadaddr   ifa_dstaddr     /* broadcast address interface */
+#endif
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+extern int getifaddrs __P((struct ifaddrs **));
+extern void freeifaddrs __P((struct ifaddrs *));
+__END_DECLS
+
+#endif
diff --git a/gen.subproj/inet6_option_space.3 b/gen.subproj/inet6_option_space.3
new file mode 100644 (file)
index 0000000..c5b6cc9
--- /dev/null
@@ -0,0 +1,445 @@
+.\" Copyright (c) 1983, 1987, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     $Id: inet6_option_space.3,v 1.2 2002/03/19 17:20:07 majka Exp $
+.\" $FreeBSD: src/lib/libc/net/inet6_option_space.3,v 1.1.2.5 2001/08/17 15:42:38 ru Exp $
+.\"
+.Dd December 10, 1999
+.Dt INET6_OPTION_SPACE 3
+.Os
+.\"
+.Sh NAME
+.Nm inet6_option_space ,
+.Nm inet6_option_init ,
+.Nm inet6_option_append ,
+.Nm inet6_option_alloc ,
+.Nm inet6_option_next ,
+.Nm inet6_option_find
+.Nd IPv6 Hop-by-Hop and Destination Options manipulation
+.\"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <netinet/in.h>
+.Ft "int"
+.Fn inet6_option_space "int nbytes"
+.Ft "int"
+.Fn inet6_option_init "void *bp" "struct cmsghdr **cmsgp" "int type"
+.Ft "int"
+.Fn inet6_option_append "struct cmsghdr *cmsg" "const u_int8_t *typep" "int multx" "int plusy"
+.Ft "u_int8_t *"
+.Fn inet6_option_alloc "struct cmsghdr *cmsg" "int datalen" "int multx" "int plusy"
+.Ft "int"
+.Fn inet6_option_next "const struct cmsghdr *cmsg" "u_int8_t **tptrp"
+.Ft "int"
+.Fn inet6_option_find "const struct cmsghdr *cmsg" "u_int8_t **tptrp" "int type"
+.\"
+.Sh DESCRIPTION
+.\"
+Building and parsing the Hop-by-Hop and Destination options is
+complicated due to alignment constranints, padding and
+ancillary data manipulation.
+RFC2292 defines a set of functions to help the application.
+The function prototypes for
+these functions are all in the
+.Aq Li netinet/in.h
+header.
+.\"
+.Ss inet6_option_space
+.Fn inet6_option_space
+returns the number of bytes required to hold an option when it is stored as
+ancillary data, including the
+.Li cmsghdr
+structure at the beginning,
+and any padding at the end
+(to make its size a multiple of 8 bytes).
+The argument is the size of the structure defining the option,
+which must include any pad bytes at the beginning
+(the value
+.Li y
+in the alignment term
+.Dq Li "xn + y" ) ,
+the type byte, the length byte, and the option data.
+.Pp
+Note: If multiple options are stored in a single ancillary data
+object, which is the recommended technique, this function
+overestimates the amount of space required by the size of
+.Li N-1
+.Li cmsghdr
+structures,
+where
+.Li N
+is the number of options to be stored in the object.
+This is of little consequence, since it is assumed that most
+Hop-by-Hop option headers and Destination option headers carry only
+one option
+(appendix B of [RFC-2460]).
+.\"
+.Ss inet6_option_init
+.Fn inet6_option_init
+is called once per ancillary data object that will
+contain either Hop-by-Hop or Destination options.
+It returns
+.Li 0
+on success or
+.Li -1
+on an error.
+.Pp
+.Fa bp
+is a pointer to previously allocated space that will contain the
+ancillary data object.
+It must be large enough to contain all the
+individual options to be added by later calls to
+.Fn inet6_option_append
+and
+.Fn inet6_option_alloc .
+.Pp
+.Fa cmsgp
+is a pointer to a pointer to a
+.Li cmsghdr
+structure.
+.Fa *cmsgp
+is initialized by this function to point to the
+.Li cmsghdr
+structure constructed by this function in the buffer pointed to by
+.Fa bp .
+.Pp
+.Fa type
+is either
+.Dv IPV6_HOPOPTS
+or
+.Dv IPV6_DSTOPTS .
+This
+.Fa type
+is stored in the
+.Li cmsg_type
+member of the
+.Li cmsghdr
+structure pointed to by
+.Fa *cmsgp .
+.\"
+.Ss inet6_option_append
+This function appends a Hop-by-Hop option or a Destination option
+into an ancillary data object that has been initialized by
+.Fn inet6_option_init .
+This function returns
+.Li 0
+if it succeeds or
+.Li -1
+on an error.
+.Pp
+.Fa cmsg
+is a pointer to the
+.Li cmsghdr
+structure that must have been
+initialized by
+.Fn inet6_option_init .
+.Pp
+.Fa typep
+is a pointer to the 8-bit option type.
+It is assumed that this
+field is immediately followed by the 8-bit option data length field,
+which is then followed immediately by the option data.
+The caller
+initializes these three fields
+(the type-length-value, or TLV)
+before calling this function.
+.Pp
+The option type must have a value from
+.Li 2
+to
+.Li 255 ,
+inclusive.
+.Li ( 0
+and
+.Li 1
+are reserved for the
+.Li Pad1
+and
+.Li PadN
+options, respectively.)
+.Pp
+The option data length must have a value between
+.Li 0
+and
+.Li 255 ,
+inclusive, and is the length of the option data that follows.
+.Pp
+.Fa multx
+is the value
+.Li x
+in the alignment term
+.Dq Li xn + y .
+It must have a value of
+.Li 1 ,
+.Li 2 ,
+.Li 4 ,
+or
+.Li 8 .
+.Pp
+.Fa plusy
+is the value
+.Li y
+in the alignment term
+.Dq Li xn + y .
+It must have a value between
+.Li 0
+and
+.Li 7 ,
+inclusive.
+.\"
+.Ss inet6_option_alloc
+This function appends a Hop-by-Hop option or a Destination option
+into an ancillary data object that has been initialized by
+.Fn inet6_option_init .
+This function returns a pointer to the 8-bit
+option type field that starts the option on success, or
+.Dv NULL
+on an error.
+.Pp
+The difference between this function and
+.Fn inet6_option_append
+is that the latter copies the contents of a previously built option into
+the ancillary data object while the current function returns a
+pointer to the space in the data object where the option's TLV must
+then be built by the caller.
+.Pp
+.Fa cmsg
+is a pointer to the
+.Li cmsghdr
+structure that must have been
+initialized by
+.Fn inet6_option_init .
+.Pp
+.Fa datalen
+is the value of the option data length byte for this option.
+This value is required as an argument to allow the function to
+determine if padding must be appended at the end of the option.
+(The
+.Fn inet6_option_append
+function does not need a data length argument
+since the option data length must already be stored by the caller.)
+.Pp
+.Fa multx
+is the value
+.Li x
+in the alignment term
+.Dq Li xn + y .
+It must have a value of
+.Li 1 ,
+.Li 2 ,
+.Li 4 ,
+or
+.Li 8 .
+.Pp
+.Fa plusy
+is the value
+.Li y
+in the alignment term
+.Dq Li xn + y .
+It must have a value between
+.Li 0
+and
+.Li 7 ,
+inclusive.
+.\"
+.Ss inet6_option_next
+This function processes the next Hop-by-Hop option or Destination
+option in an ancillary data object.
+If another option remains to be
+processed, the return value of the function is
+.Li 0
+and
+.Fa *tptrp
+points to
+the 8-bit option type field
+(which is followed by the 8-bit option
+data length, followed by the option data).
+If no more options remain
+to be processed, the return value is
+.Li -1
+and
+.Fa *tptrp
+is
+.Dv NULL .
+If an error occurs, the return value is
+.Li -1
+and
+.Fa *tptrp
+is not
+.Dv NULL .
+.Pp
+.Fa cmsg
+is a pointer to
+.Li cmsghdr
+structure of which
+.Li cmsg_level
+equals
+.Dv IPPROTO_IPV6
+and
+.Li cmsg_type
+equals either
+.Dv IPV6_HOPOPTS
+or
+.Dv IPV6_DSTOPTS .
+.Pp
+.Fa tptrp
+is a pointer to a pointer to an 8-bit byte and
+.Fa *tptrp
+is used
+by the function to remember its place in the ancillary data object
+each time the function is called.
+The first time this function is
+called for a given ancillary data object,
+.Fa *tptrp
+must be set to
+.Dv NULL .
+.Pp
+Each time this function returns success,
+.Fa *tptrp
+points to the 8-bit
+option type field for the next option to be processed.
+.\"
+.Ss inet6_option_find
+This function is similar to the previously described
+.Fn inet6_option_next
+function, except this function lets the caller
+specify the option type to be searched for, instead of always
+returning the next option in the ancillary data object.
+.Fa cmsg
+is a
+pointer to
+.Li cmsghdr
+structure of which
+.Li cmsg_level
+equals
+.Dv IPPROTO_IPV6
+and
+.Li cmsg_type
+equals either
+.Dv IPV6_HOPOPTS
+or
+.Dv IPV6_DSTOPTS .
+.Pp
+.Fa tptrp
+is a pointer to a pointer to an 8-bit byte and
+.Fa *tptrp
+is used
+by the function to remember its place in the ancillary data object
+each time the function is called.
+The first time this function is
+called for a given ancillary data object,
+.Fa *tptrp
+must be set to
+.Dv NULL .
+.Pa
+This function starts searching for an option of the specified type
+beginning after the value of
+.Fa *tptrp .
+If an option of the specified
+type is located, this function returns
+.Li 0
+and
+.Fa *tptrp
+points to the 8-
+bit option type field for the option of the specified type.
+If an
+option of the specified type is not located, the return value is
+.Li -1
+and
+.Fa *tptrp
+is
+.Dv NULL .
+If an error occurs, the return value is
+.Li -1
+and
+.Fa *tptrp
+is not
+.Dv NULL .
+.\"
+.Sh DIAGNOSTICS
+.Fn inet6_option_init
+and
+.Fn inet6_option_append
+return
+.Li 0
+on success or
+.Li -1
+on an error.
+.Pp
+.Fn inet6_option_alloc
+returns
+.Dv NULL
+on an error.
+.Pp
+On errors,
+.Fn inet6_option_next
+and
+.Fn inet6_option_find
+return
+.Li -1
+setting
+.Fa *tptrp
+to non
+.Dv NULL
+value.
+.\"
+.Sh EXAMPLES
+RFC2292 gives comprehensive examples in chapter 6.
+.\"
+.Sh SEE ALSO
+.Rs
+.%A W. Stevens
+.%A M. Thomas
+.%T "Advanced Sockets API for IPv6"
+.%N RFC2292
+.%D February 1998
+.Re
+.Rs
+.%A S. Deering
+.%A R. Hinden
+.%T "Internet Protocol, Version 6 (IPv6) Specification"
+.%N RFC2460
+.%D December 1998
+.Re
+.\"
+.Sh HISTORY
+The implementation first appeared in KAME advanced networking kit.
+.\"
+.Sh STANDARDS
+The functions
+are documented in
+.Dq Advanced Sockets API for IPv6
+(RFC2292).
+.\"
+.Sh BUGS
+The text was shamelessly copied from RFC2292.
diff --git a/gen.subproj/inet6_rthdr_space.3 b/gen.subproj/inet6_rthdr_space.3
new file mode 100644 (file)
index 0000000..3ca3581
--- /dev/null
@@ -0,0 +1,323 @@
+.\" Copyright (c) 1983, 1987, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     $Id: inet6_rthdr_space.3,v 1.2 2002/03/19 17:20:07 majka Exp $
+.\" $FreeBSD: src/lib/libc/net/inet6_rthdr_space.3,v 1.1.2.5 2001/08/17 15:42:38 ru Exp $
+.\"
+.Dd December 10, 1999
+.Dt INET6_RTHDR_SPACE 3
+.Os
+.\"
+.Sh NAME
+.Nm inet6_rthdr_space ,
+.Nm inet6_rthdr_init ,
+.Nm inet6_rthdr_add ,
+.Nm inet6_rthdr_lasthop ,
+.Nm inet6_rthdr_reverse ,
+.Nm inet6_rthdr_segments ,
+.Nm inet6_rthdr_getaddr ,
+.Nm inet6_rthdr_getflags
+.Nd IPv6 Routing Header Options manipulation
+.\"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <netinet/in.h>
+.Ft size_t
+.Fn inet6_rthdr_space "int type" "int segments"
+.Ft "struct cmsghdr *"
+.Fn inet6_rthdr_init "void *bp" "int type"
+.Ft int
+.Fn inet6_rthdr_add "struct cmsghdr *cmsg" "const struct in6_addr *addr" "unsigned int flags"
+.Ft int
+.Fn inet6_rthdr_lasthop "struct cmsghdr *cmsg" "unsigned int flags"
+.Ft int
+.Fn inet6_rthdr_reverse "const struct cmsghdr *in" "struct cmsghdr *out"
+.Ft int
+.Fn inet6_rthdr_segments "const struct cmsghdr *cmsg"
+.Ft "struct in6_addr *"
+.Fn inet6_rthdr_getaddr "struct cmsghdr *cmsg" "int index"
+.Ft int
+.Fn inet6_rthdr_getflags "const struct cmsghdr *cmsg" "int index"
+.\"
+.Sh DESCRIPTION
+RFC2292 IPv6 advanced API defines eight
+functions that the application calls to build and examine a Routing
+header.  Four functions build a Routing header:
+.Bl -hang
+.It Fn inet6_rthdr_space
+return #bytes required for ancillary data
+.It Fn inet6_rthdr_init
+initialize ancillary data for Routing header
+.It Fn inet6_rthdr_add
+add IPv6 address & flags to Routing header
+.It Fn inet6_rthdr_lasthop
+specify the flags for the final hop
+.El
+.Pp
+Four functions deal with a returned Routing header:
+.Bl -hang
+.It Fn inet6_rthdr_reverse
+reverse a Routing header
+.It Fn inet6_rthdr_segments
+return #segments in a Routing header
+.It Fn inet6_rthdr_getaddr
+fetch one address from a Routing header
+.It Fn inet6_rthdr_getflags
+fetch one flag from a Routing header
+.El
+.Pp
+The function prototypes for these functions are all in the
+.Aq Li netinet/in.h
+header.
+.\"
+.Ss inet6_rthdr_space
+This function returns the number of bytes required to hold a Routing
+header of the specified
+.Fa type
+containing the specified number of
+.Fa segments
+(addresses).
+For an IPv6 Type 0 Routing header, the number
+of segments must be between 1 and 23, inclusive.  The return value
+includes the size of the cmsghdr structure that precedes the Routing
+header, and any required padding.
+.Pp
+If the return value is 0, then either the type of the Routing header
+is not supported by this implementation or the number of segments is
+invalid for this type of Routing header.
+.Pp
+Note: This function returns the size but does not allocate the space
+required for the ancillary data.
+This allows an application to
+allocate a larger buffer, if other ancillary data objects are
+desired, since all the ancillary data objects must be specified to
+.Xr sendmsg 2
+as a single
+.Li msg_control
+buffer.
+.\"
+.Ss inet6_rthdr_init
+This function initializes the buffer pointed to by
+.Fa bp
+to contain a
+.Li cmsghdr
+structure followed by a Routing header of the specified
+.Fa type .
+The
+.Li cmsg_len
+member of the
+.Li cmsghdr
+structure is initialized to the
+size of the structure plus the amount of space required by the
+Routing header.
+The
+.Li cmsg_level
+and
+.Li cmsg_type
+members are also initialized as required.
+.Pp
+The caller must allocate the buffer and its size can be determined by
+calling
+.Fn inet6_rthdr_space .
+.Pp
+Upon success the return value is the pointer to the
+.Li cmsghdr
+structure, and this is then used as the first argument to the next
+two functions.
+Upon an error the return value is
+.Dv NULL .
+.\"
+.Ss inet6_rthdr_add
+This function adds the address pointed to by
+.Fa addr
+to the end of the
+Routing header being constructed and sets the type of this hop to the
+value of
+.Fa flags .
+For an IPv6 Type 0 Routing header,
+.Fa flags
+must be
+either
+.Dv IPV6_RTHDR_LOOSE
+or
+.Dv IPV6_RTHDR_STRICT .
+.Pp
+If successful, the
+.Li cmsg_len
+member of the
+.Li cmsghdr
+structure is
+updated to account for the new address in the Routing header and the
+return value of the function is 0.
+Upon an error the return value of
+the function is -1.
+.\"
+.Ss inet6_rthdr_lasthop
+This function specifies the Strict/Loose flag for the final hop of a
+Routing header.
+For an IPv6 Type 0 Routing header,
+.Fa flags
+must be either
+.Dv IPV6_RTHDR_LOOSE
+or
+.Dv IPV6_RTHDR_STRICT .
+.Pp
+The return value of the function is 0 upon success, or -1 upon an error.
+.Pp
+Notice that a Routing header specifying
+.Li N
+intermediate nodes requires
+.Li N+1
+Strict/Loose flags.
+This requires
+.Li N
+calls to
+.Fn inet6_rthdr_add
+followed by one call to
+.Fn inet6_rthdr_lasthop .
+.\"
+.Ss inet6_rthdr_reverse
+This function is not yet implemented.
+When implemented, this should behave as follows.
+.Pp
+This function takes a Routing header that was received as ancillary
+data
+(pointed to by the first argument,
+.Fa in )
+and writes a new Routing
+header that sends datagrams along the reverse of that route.
+Both
+arguments are allowed to point to the same buffer
+(that is, the reversal can occur in place).
+.Pp
+The return value of the function is 0 on success, or -1 upon an
+error.
+.\"
+.Ss inet6_rthdr_segments
+This function returns the number of segments
+(addresses)
+contained in
+the Routing header described by
+.Fa cmsg .
+On success the return value is
+between 1 and 23, inclusive.
+The return value of the function is -1 upon an error.
+.\"
+.Ss inet6_rthdr_getaddr
+This function returns a pointer to the IPv6 address specified by
+.Fa index
+(which must have a value between 1 and the value returned by
+.Fn inet6_rthdr_segments )
+in the Routing header described by
+.Fa cmsg .
+An
+application should first call
+.Fn inet6_rthdr_segments
+to obtain the number of segments in the Routing header.
+.Pp
+Upon an error the return value of the function is
+.Dv NULL .
+.\"
+.Ss inet6_rthdr_getflags
+This function returns the flags value specified by
+.Fa index
+(which must
+have a value between 0 and the value returned by
+.Fn inet6_rthdr_segments )
+in the Routing header described by
+.Fa cmsg .
+For an IPv6 Type 0 Routing header the return value will be either
+.Dv IPV6_RTHDR_LOOSE
+or
+.Dv IPV6_RTHDR_STRICT .
+.Pp
+Upon an error the return value of the function is -1.
+.Pp
+Note: Addresses are indexed starting at 1, and flags starting at 0,
+to maintain consistency with the terminology and figures in RFC2460.
+.\"
+.Sh DIAGNOSTICS
+.Fn inet6_rthdr_space
+returns 0 on errors.
+.Pp
+.Fn inet6_rthdr_add ,
+.Fn inet6_rthdr_lasthop
+and
+.Fn inet6_rthdr_reverse
+return 0 on success, and returns -1 on error.
+.Pp
+.Fn inet6_rthdr_init
+and
+.Fn inet6_rthdr_getaddr
+return
+.Dv NULL
+on error.
+.Pp
+.Fn inet6_rthdr_segments
+and
+.Fn inet6_rthdr_getflags
+return -1 on error.
+.\"
+.Sh EXAMPLES
+RFC2292 gives comprehensive examples in chapter 8.
+.\"
+.Sh SEE ALSO
+.Rs
+.%A W. Stevens
+.%A M. Thomas
+.%T "Advanced Sockets API for IPv6"
+.%N RFC2292
+.%D February 1998
+.Re
+.Rs
+.%A S. Deering
+.%A R. Hinden
+.%T "Internet Protocol, Version 6 (IPv6) Specification"
+.%N RFC2460
+.%D December 1998
+.Re
+.\"
+.Sh HISTORY
+The implementation first appeared in KAME advanced networking kit.
+.\"
+.Sh STANDARDS
+The functions
+are documented in
+.Dq Advanced Sockets API for IPv6
+(RFC2292).
+.\"
+.Sh BUGS
+The text was shamelessly copied from RFC2292.
+.Pp
+.Fn inet6_rthdr_reverse
+is not implemented yet.
diff --git a/gen.subproj/inet_ntop.c b/gen.subproj/inet_ntop.c
new file mode 100644 (file)
index 0000000..99bc6c7
--- /dev/null
@@ -0,0 +1,82 @@
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+
+void __res_close()
+{
+}
+
+const char *inet_ntop6(const struct in6_addr *addr,char *buf,size_t len)
+{
+       const u_int16_t *ap=addr->__u6_addr.__u6_addr16;
+       int colon=2;
+       int i;
+       char *bp=buf;
+       
+       for(i=0;i<8;i++,ap++)
+       {
+               if(bp>=buf+len-1)
+               {
+                       buf[len-1]=0;
+                       return buf;
+               }
+               if(*ap || colon==-1)
+               {
+                       if(colon==2)
+                               colon=0;
+                       if(colon)
+                               colon=-1;
+                       sprintf(bp,"%x",*ap);
+                       bp+=strlen(bp);
+                       if(i!=7)
+                               *bp++=':';
+               }
+               else
+               {
+                       if(colon==2)
+                       {
+                               *bp++=':';
+                               *bp++=':';
+                       }
+                       else if(!colon && i!=7)
+                               *bp++=':';
+                       colon=1;
+               }
+       }
+       *bp=0;
+       return buf;
+}
+
+const char *inet_ntop4(const struct in_addr *addr,char *buf,size_t len)
+{
+       const u_int8_t *ap=(u_int8_t*)&addr->s_addr;
+       int i;
+       char *bp=buf;
+       
+       for(i=0;i<4;i++,ap++)
+       {
+               if(bp>=buf+len-1)
+               {
+                       buf[len-1]=0;
+                       return buf;
+               }
+               sprintf(bp,"%d",*ap);
+               bp+=strlen(bp);
+               if(i!=3)
+                       *bp++='.';
+       }
+       *bp=0;
+       return buf;
+}
+
+const char *inet_ntop(int af,const void *addr,char *buf,size_t len)
+{
+       if(af==AF_INET6)
+               return inet_ntop6(addr,buf,len);
+       if(af==AF_INET)
+               return inet_ntop4(addr,buf,len);
+       return NULL;
+}
diff --git a/gen.subproj/inet_pton.c b/gen.subproj/inet_pton.c
new file mode 100644 (file)
index 0000000..7858ba8
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$Id: inet_pton.c,v 1.2 2002/01/17 22:22:25 majka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif 
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <string.h>
+#include <errno.h>
+
+#define IN6ADDRSZ              16
+
+#if 0
+#ifndef HAVE_PORTABLE_PROTOTYPE
+#include "cdecl_ext.h"
+#endif 
+
+#ifndef HAVE_U_INT16_T
+#include "bittypes.h"
+#endif 
+#if !(defined(HAVE_INADDRSZ) && defined(HAVE_IN6ADDRSZ))
+#include "addrsize.h"
+#endif 
+#endif
+#ifndef NS_INADDRSZ
+#define NS_INADDRSZ    INADDRSZ
+#endif
+#ifndef NS_IN6ADDRSZ
+#define NS_IN6ADDRSZ   IN6ADDRSZ
+#endif
+#ifndef NS_INT16SZ
+#define NS_INT16SZ     sizeof(u_int16_t)
+#endif
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static int     inet_pton4 __P((const char *src, u_char *dst));
+#ifdef INET6
+static int     inet_pton6 __P((const char *src, u_char *dst));
+#endif
+
+/* int
+ * inet_pton(af, src, dst)
+ *     convert from presentation format (which usually means ASCII printable)
+ *     to network format (which is usually some kind of binary format).
+ * return:
+ *     1 if the address was valid for the specified address family
+ *     0 if the address wasn't valid (`dst' is untouched in this case)
+ *     -1 if some other error occurred (`dst' is untouched in this case, too)
+ * author:
+ *     Paul Vixie, 1996.
+ */
+int
+inet_pton(af, src, dst)
+       int af;
+       const char *src;
+       void *dst;
+{
+       switch (af) {
+       case AF_INET:
+               return (inet_pton4(src, dst));
+#ifdef INET6
+       case AF_INET6:
+               return (inet_pton6(src, dst));
+#endif 
+       default:
+               errno = EAFNOSUPPORT;
+               return (-1);
+       }
+       /* NOTREACHED */
+}
+
+/* int
+ * inet_pton4(src, dst)
+ *     like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ *     1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ *     does not touch `dst' unless it's returning 1.
+ * author:
+ *     Paul Vixie, 1996.
+ */
+static int
+inet_pton4(src, dst)
+       const char *src;
+       u_char *dst;
+{
+       static const char digits[] = "0123456789";
+       int saw_digit, octets, ch;
+       u_char tmp[NS_INADDRSZ], *tp;
+
+       saw_digit = 0;
+       octets = 0;
+       *(tp = tmp) = 0;
+       while ((ch = *src++) != '\0') {
+               const char *pch;
+
+               if ((pch = strchr(digits, ch)) != NULL) {
+                       u_int new = *tp * 10 + (pch - digits);
+
+                       if (new > 255)
+                               return (0);
+                       *tp = new;
+                       if (! saw_digit) {
+                               if (++octets > 4)
+                                       return (0);
+                               saw_digit = 1;
+                       }
+               } else if (ch == '.' && saw_digit) {
+                       if (octets == 4)
+                               return (0);
+                       *++tp = 0;
+                       saw_digit = 0;
+               } else
+                       return (0);
+       }
+       if (octets < 4)
+               return (0);
+       memcpy(dst, tmp, NS_INADDRSZ);
+       return (1);
+}
+
+#ifdef INET6
+/* int
+ * inet_pton6(src, dst)
+ *     convert presentation level address to network order binary form.
+ * return:
+ *     1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ *     (1) does not touch `dst' unless it's returning 1.
+ *     (2) :: in a full address is silently ignored.
+ * credit:
+ *     inspired by Mark Andrews.
+ * author:
+ *     Paul Vixie, 1996.
+ */
+static int
+inet_pton6(src, dst)
+       const char *src;
+       u_char *dst;
+{
+       static const char xdigits_l[] = "0123456789abcdef",
+                         xdigits_u[] = "0123456789ABCDEF";
+       u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+       const char *xdigits, *curtok;
+       int ch, saw_xdigit;
+       u_int val;
+
+       memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+       endp = tp + NS_IN6ADDRSZ;
+       colonp = NULL;
+       /* Leading :: requires some special handling. */
+       if (*src == ':')
+               if (*++src != ':')
+                       return (0);
+       curtok = src;
+       saw_xdigit = 0;
+       val = 0;
+       while ((ch = *src++) != '\0') {
+               const char *pch;
+
+               if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+                       pch = strchr((xdigits = xdigits_u), ch);
+               if (pch != NULL) {
+                       val <<= 4;
+                       val |= (pch - xdigits);
+                       if (val > 0xffff)
+                               return (0);
+                       saw_xdigit = 1;
+                       continue;
+               }
+               if (ch == ':') {
+                       curtok = src;
+                       if (!saw_xdigit) {
+                               if (colonp)
+                                       return (0);
+                               colonp = tp;
+                               continue;
+                       } else if (*src == '\0') {
+                               return (0);
+                       }
+                       if (tp + NS_INT16SZ > endp)
+                               return (0);
+                       *tp++ = (u_char) (val >> 8) & 0xff;
+                       *tp++ = (u_char) val & 0xff;
+                       saw_xdigit = 0;
+                       val = 0;
+                       continue;
+               }
+               if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+                   inet_pton4(curtok, tp) > 0) {
+                       tp += NS_INADDRSZ;
+                       saw_xdigit = 0;
+                       break;  /* '\0' was seen by inet_pton4(). */
+               }
+               return (0);
+       }
+       if (saw_xdigit) {
+               if (tp + NS_INT16SZ > endp)
+                       return (0);
+               *tp++ = (u_char) (val >> 8) & 0xff;
+               *tp++ = (u_char) val & 0xff;
+       }
+       if (colonp != NULL) {
+               /*
+                * Since some memmove()'s erroneously fail to handle
+                * overlapping regions, we'll do the shift by hand.
+                */
+               const int n = tp - colonp;
+               int i;
+
+               if (tp == endp)
+                       return (0);
+               for (i = 1; i <= n; i++) {
+                       endp[- i] = colonp[n - i];
+                       colonp[n - i] = 0;
+               }
+               tp = endp;
+       }
+       if (tp != endp)
+               return (0);
+       memcpy(dst, tmp, NS_IN6ADDRSZ);
+       return (1);
+}
+#endif /*INET6*/
index 455c363c2124261a99a5baadfd7c88076cb5ad33..cf7fabfbc9d57886d436561e3dc2d4fdda2247e3 100644 (file)
@@ -61,6 +61,8 @@ static char sccsid[] = "@(#)initgroups.c      8.1 (Berkeley) 6/4/93";
 #include <sys/param.h>
 
 #include <stdio.h>
+#include <unistd.h>
+#include <err.h>
 
 int
 initgroups(uname, agroup)
diff --git a/gen.subproj/ip6opt.c b/gen.subproj/ip6opt.c
new file mode 100644 (file)
index 0000000..c8805d1
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libc/net/ip6opt.c,v 1.1 1999/12/16 18:32:01 shin Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+
+#include <string.h>
+#include <stdio.h>
+
+static int ip6optlen(u_int8_t *opt, u_int8_t *lim);
+static void inet6_insert_padopt(u_char *p, int len);
+
+/*
+ * This function returns the number of bytes required to hold an option
+ * when it is stored as ancillary data, including the cmsghdr structure
+ * at the beginning, and any padding at the end (to make its size a
+ * multiple of 8 bytes).  The argument is the size of the structure
+ * defining the option, which must include any pad bytes at the
+ * beginning (the value y in the alignment term "xn + y"), the type
+ * byte, the length byte, and the option data.
+ */
+int
+inet6_option_space(nbytes)
+       int nbytes;
+{
+       nbytes += 2;    /* we need space for nxt-hdr and length fields */
+       return(CMSG_SPACE((nbytes + 7) & ~7));
+}
+
+/*
+ * This function is called once per ancillary data object that will
+ * contain either Hop-by-Hop or Destination options.  It returns 0 on
+ * success or -1 on an error.
+ */
+int
+inet6_option_init(bp, cmsgp, type)
+       void *bp;
+       struct cmsghdr **cmsgp;
+       int type;
+{
+       register struct cmsghdr *ch = (struct cmsghdr *)bp;
+
+       /* argument validation */
+       if (type != IPV6_HOPOPTS && type != IPV6_DSTOPTS)
+               return(-1);
+       
+       ch->cmsg_level = IPPROTO_IPV6;
+       ch->cmsg_type = type;
+       ch->cmsg_len = CMSG_LEN(0);
+
+       *cmsgp = ch;
+       return(0);
+}
+
+/*
+ * This function appends a Hop-by-Hop option or a Destination option
+ * into an ancillary data object that has been initialized by
+ * inet6_option_init().  This function returns 0 if it succeeds or -1 on
+ * an error.
+ * multx is the value x in the alignment term "xn + y" described
+ * earlier.  It must have a value of 1, 2, 4, or 8.
+ * plusy is the value y in the alignment term "xn + y" described
+ * earlier.  It must have a value between 0 and 7, inclusive.
+ */
+int
+inet6_option_append(cmsg, typep, multx, plusy)
+       struct cmsghdr *cmsg;
+       const u_int8_t *typep;
+       int multx;
+       int plusy;
+{
+       int padlen, optlen, off;
+       register u_char *bp = (u_char *)cmsg + cmsg->cmsg_len;
+       struct ip6_ext *eh = (struct ip6_ext *)CMSG_DATA(cmsg);
+
+       /* argument validation */
+       if (multx != 1 && multx != 2 && multx != 4 && multx != 8)
+               return(-1);
+       if (plusy < 0 || plusy > 7)
+               return(-1);
+       if (typep[0] > 255)
+               return(-1);
+
+       /*
+        * If this is the first option, allocate space for the
+        * first 2 bytes(for next header and length fields) of
+        * the option header.
+        */
+       if (bp == (u_char *)eh) {
+               bp += 2;
+               cmsg->cmsg_len += 2;
+       }
+
+       /* calculate pad length before the option. */
+       off = bp - (u_char *)eh;
+       padlen = (((off % multx) + (multx - 1)) & ~(multx - 1)) -
+               (off % multx);
+       padlen += plusy;
+       /* insert padding */
+       inet6_insert_padopt(bp, padlen);
+       cmsg->cmsg_len += padlen;
+       bp += padlen;
+
+       /* copy the option */
+       if (typep[0] == IP6OPT_PAD1)
+               optlen = 1;
+       else
+               optlen = typep[1] + 2;
+       memcpy(bp, typep, optlen);
+       bp += optlen;
+       cmsg->cmsg_len += optlen;
+
+       /* calculate pad length after the option and insert the padding */
+       off = bp - (u_char *)eh;
+       padlen = ((off + 7) & ~7) - off;
+       inet6_insert_padopt(bp, padlen);
+       bp += padlen;
+       cmsg->cmsg_len += padlen;
+
+       /* update the length field of the ip6 option header */
+       eh->ip6e_len = ((bp - (u_char *)eh) >> 3) - 1;
+
+       return(0);
+}
+
+/*
+ * This function appends a Hop-by-Hop option or a Destination option
+ * into an ancillary data object that has been initialized by
+ * inet6_option_init().  This function returns a pointer to the 8-bit
+ * option type field that starts the option on success, or NULL on an
+ * error.
+ * The difference between this function and inet6_option_append() is
+ * that the latter copies the contents of a previously built option into
+ * the ancillary data object while the current function returns a
+ * pointer to the space in the data object where the option's TLV must
+ * then be built by the caller.
+ * 
+ */
+u_int8_t *
+inet6_option_alloc(cmsg, datalen, multx, plusy)
+       struct cmsghdr *cmsg;
+       int datalen;
+       int multx;
+       int plusy;
+{
+       int padlen, off;
+       register u_int8_t *bp = (u_char *)cmsg + cmsg->cmsg_len;
+       u_int8_t *retval;
+       struct ip6_ext *eh = (struct ip6_ext *)CMSG_DATA(cmsg);
+
+       /* argument validation */
+       if (multx != 1 && multx != 2 && multx != 4 && multx != 8)
+               return(NULL);
+       if (plusy < 0 || plusy > 7)
+               return(NULL);
+
+       /*
+        * If this is the first option, allocate space for the
+        * first 2 bytes(for next header and length fields) of
+        * the option header.
+        */
+       if (bp == (u_char *)eh) {
+               bp += 2;
+               cmsg->cmsg_len += 2;
+       }
+
+       /* calculate pad length before the option. */
+       off = bp - (u_char *)eh;
+       padlen = (((off % multx) + (multx - 1)) & ~(multx - 1)) -
+               (off % multx);
+       padlen += plusy;
+       /* insert padding */
+       inet6_insert_padopt(bp, padlen);
+       cmsg->cmsg_len += padlen;
+       bp += padlen;
+
+       /* keep space to store specified length of data */
+       retval = bp;
+       bp += datalen;
+       cmsg->cmsg_len += datalen;
+
+       /* calculate pad length after the option and insert the padding */
+       off = bp - (u_char *)eh;
+       padlen = ((off + 7) & ~7) - off;
+       inet6_insert_padopt(bp, padlen);
+       bp += padlen;
+       cmsg->cmsg_len += padlen;
+
+       /* update the length field of the ip6 option header */
+       eh->ip6e_len = ((bp - (u_char *)eh) >> 3) - 1;
+
+       return(retval);
+}
+
+/*
+ * This function processes the next Hop-by-Hop option or Destination
+ * option in an ancillary data object.  If another option remains to be
+ * processed, the return value of the function is 0 and *tptrp points to
+ * the 8-bit option type field (which is followed by the 8-bit option
+ * data length, followed by the option data).  If no more options remain
+ * to be processed, the return value is -1 and *tptrp is NULL.  If an
+ * error occurs, the return value is -1 and *tptrp is not NULL.
+ * (RFC 2292, 6.3.5)
+ */
+int
+inet6_option_next(cmsg, tptrp)
+       const struct cmsghdr *cmsg;
+       u_int8_t **tptrp;
+{
+       struct ip6_ext *ip6e;
+       int hdrlen, optlen;
+       u_int8_t *lim;
+
+       if (cmsg->cmsg_level != IPPROTO_IPV6 ||
+           (cmsg->cmsg_type != IPV6_HOPOPTS &&
+            cmsg->cmsg_type != IPV6_DSTOPTS))
+               return(-1);
+
+       /* message length validation */
+       if (cmsg->cmsg_len < CMSG_SPACE(sizeof(struct ip6_ext)))
+               return(-1);
+       ip6e = (struct ip6_ext *)CMSG_DATA(cmsg);
+       hdrlen = (ip6e->ip6e_len + 1) << 3;
+       if (cmsg->cmsg_len < CMSG_SPACE(hdrlen))
+               return(-1);
+
+       /*
+        * If the caller does not specify the starting point,
+        * simply return the 1st option.
+        * Otherwise, search the option list for the next option.
+        */
+       lim = (u_int8_t *)ip6e + hdrlen;
+       if (*tptrp == NULL)
+               *tptrp = (u_int8_t *)(ip6e + 1);
+       else {
+               if ((optlen = ip6optlen(*tptrp, lim)) == 0)
+                       return(-1);
+
+               *tptrp = *tptrp + optlen;
+       }
+       if (*tptrp >= lim) {    /* there is no option */
+               *tptrp = NULL;
+               return(-1);
+       }
+       /*
+        * Finally, checks if the next option is safely stored in the
+        * cmsg data.
+        */
+       if (ip6optlen(*tptrp, lim) == 0)
+               return(-1);
+       else
+               return(0);
+}
+
+/*
+ * This function is similar to the inet6_option_next() function,
+ * except this function lets the caller specify the option type to be
+ * searched for, instead of always returning the next option in the
+ * ancillary data object.
+ * Note: RFC 2292 says the type of tptrp is u_int8_t *, but we think
+ *       it's a typo. The variable should be type of u_int8_t **.
+ */
+int
+inet6_option_find(cmsg, tptrp, type)
+       const struct cmsghdr *cmsg;
+       u_int8_t **tptrp;
+       int type;
+{
+       struct ip6_ext *ip6e;
+       int hdrlen, optlen;
+       u_int8_t *optp, *lim;
+
+       if (cmsg->cmsg_level != IPPROTO_IPV6 ||
+           (cmsg->cmsg_type != IPV6_HOPOPTS &&
+            cmsg->cmsg_type != IPV6_DSTOPTS))
+               return(-1);
+
+       /* message length validation */
+       if (cmsg->cmsg_len < CMSG_SPACE(sizeof(struct ip6_ext)))
+               return(-1);
+       ip6e = (struct ip6_ext *)CMSG_DATA(cmsg);
+       hdrlen = (ip6e->ip6e_len + 1) << 3;
+       if (cmsg->cmsg_len < CMSG_SPACE(hdrlen))
+               return(-1);     
+
+       /*
+        * If the caller does not specify the starting point,
+        * search from the beginning of the option list.
+        * Otherwise, search from *the next option* of the specified point.
+        */
+       lim = (u_int8_t *)ip6e + hdrlen;
+       if (*tptrp == NULL)
+               *tptrp = (u_int8_t *)(ip6e + 1);
+       else {
+               if ((optlen = ip6optlen(*tptrp, lim)) == 0)
+                       return(-1);
+
+               *tptrp = *tptrp + optlen;
+       }
+       for (optp = *tptrp; optp < lim; optp += optlen) {
+               if (*optp == type) {
+                       *tptrp = optp;
+                       return(0);
+               }
+               if ((optlen = ip6optlen(optp, lim)) == 0)
+                       return(-1);
+       }
+
+       /* search failed */
+       *tptrp = NULL;
+       return(-1);
+}
+
+/*
+ * Calculate the length of a given IPv6 option. Also checks
+ * if the option is safely stored in user's buffer according to the
+ * calculated length and the limitation of the buffer.
+ */
+static int
+ip6optlen(opt, lim)
+       u_int8_t *opt, *lim;
+{
+       int optlen;
+
+       if (*opt == IP6OPT_PAD1)
+               optlen = 1;
+       else {
+               /* is there enough space to store type and len? */
+               if (opt + 2 > lim)
+                       return(0);
+               optlen = *(opt + 1) + 2;
+       }
+       if (opt + optlen <= lim)
+               return(optlen);
+
+       return(0);
+}
+
+static void
+inet6_insert_padopt(u_char *p, int len)
+{
+       switch(len) {
+        case 0:
+                return;
+        case 1:
+                p[0] = IP6OPT_PAD1;
+                return;
+        default:
+                p[0] = IP6OPT_PADN;
+                p[1] = len - 2; 
+                memset(&p[2], 0, len - 2);
+                return;
+       }
+}
diff --git a/gen.subproj/linkaddr.3 b/gen.subproj/linkaddr.3
new file mode 100644 (file)
index 0000000..4c74a84
--- /dev/null
@@ -0,0 +1,140 @@
+.\" Copyright (c) 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Donn Seeley at BSDI.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     From: @(#)linkaddr.3   8.1 (Berkeley) 7/28/93
+.\" $FreeBSD: src/lib/libc/net/linkaddr.3,v 1.8.2.3 2001/08/17 15:42:38 ru Exp $
+.\"
+.Dd June 17, 1996
+.Dt LINK_ADDR 3
+.Os
+.Sh NAME
+.Nm link_addr ,
+.Nm link_ntoa
+.Nd elementary address specification routines for link level access
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/socket.h>
+.Fd #include <net/if_dl.h>
+.Ft void
+.Fn link_addr "const char *addr" "struct sockaddr_dl *sdl"
+.Ft char *
+.Fn link_ntoa "const struct sockaddr_dl *sdl"
+.Sh DESCRIPTION
+The routine
+.Fn link_addr
+interprets character strings representing
+link-level addresses, returning binary information suitable
+for use in system calls.
+The routine
+.Fn link_ntoa
+takes
+a link-level
+address and returns an
+.Tn ASCII
+string representing some of the information present,
+including the link level address itself, and the interface name
+or number, if present.
+This facility is experimental and is
+still subject to change.
+.Pp
+For
+.Fn link_addr ,
+the string
+.Fa addr
+may contain
+an optional network interface identifier of the form
+.Dq "name unit-number" ,
+suitable for the first argument to
+.Xr ifconfig 8 ,
+followed in all cases by a colon and
+an interface address in the form of
+groups of hexadecimal digits
+separated by periods.
+Each group represents a byte of address;
+address bytes are filled left to right from
+low order bytes through high order bytes.
+.Pp
+.\" A regular expression may make this format clearer:
+.\" .Bd -literal -offset indent
+.\" ([a-z]+[0-9]+:)?[0-9a-f]+(\e.[0-9a-f]+)*
+.\" .Ed
+.\" .Pp
+Thus
+.Li le0:8.0.9.13.d.30
+represents an ethernet address
+to be transmitted on the first Lance ethernet interface.
+.Pp
+The direct use of these functions is deprecated in favor of the
+.Xr addr2ascii 3
+interface; however, portable programs cannot rely on the latter as it is
+not yet widely implemented.
+.Sh RETURN VALUES
+.Fn link_ntoa
+always returns a null terminated string.
+.Fn link_addr
+has no return value.
+(See
+.Sx BUGS . )
+.Sh SEE ALSO
+.Xr addr2ascii 3
+.\" .Xr iso 4
+.Sh HISTORY
+The
+.Fn link_addr
+and
+.Fn link_ntoa
+functions appeared in
+.Bx 4.3 Reno  .
+.Sh BUGS
+The returned values for link_ntoa
+reside in a static memory area.
+.Pp
+The function
+.Fn link_addr
+should diagnose improperly formed input, and there should be an unambiguous
+way to recognize this.
+.Pp
+If the
+.Va sdl_len
+field of the link socket address
+.Fa sdl
+is 0,
+.Fn link_ntoa
+will not insert a colon before the interface address bytes.
+If this translated address is given to
+.Fn link_addr
+without inserting an initial colon,
+the latter will not interpret it correctly.
diff --git a/gen.subproj/map_v4v6.c b/gen.subproj/map_v4v6.c
new file mode 100644 (file)
index 0000000..2ed171c
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * ++Copyright++ 1985, 1988, 1993
+ * -
+ * Copyright (c) 1985, 1988, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ * 
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostnamadr.c    8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$FreeBSD: src/lib/libc/net/map_v4v6.c,v 1.5.2.1 2001/03/05 10:47:08 obrien Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <ctype.h>
+#include <syslog.h>
+
+#define   IN6ADDRSZ       16
+typedef union {
+       int32_t al;
+       char ac;
+} align;
+
+void
+_map_v4v6_address(src, dst)
+       const char *src;
+       char *dst;
+{
+       u_char *p = (u_char *)dst;
+       char tmp[INADDRSZ];
+       int i;
+
+       /* Stash a temporary copy so our caller can update in place. */
+       bcopy(src, tmp, INADDRSZ);
+       /* Mark this ipv6 addr as a mapped ipv4. */
+       for (i = 0; i < 10; i++)
+               *p++ = 0x00;
+       *p++ = 0xff;
+       *p++ = 0xff;
+       /* Retrieve the saved copy and we're done. */
+       bcopy(tmp, (void*)p, INADDRSZ);
+}
+
+void
+_map_v4v6_hostent(hp, bpp, lenp)
+       struct hostent *hp;
+       char **bpp;
+       int *lenp;
+{
+       char **ap;
+
+       if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
+               return;
+       hp->h_addrtype = AF_INET6;
+       hp->h_length = IN6ADDRSZ;
+       for (ap = hp->h_addr_list; *ap; ap++) {
+               int i = sizeof(align) - ((u_long)*bpp % sizeof(align));
+
+               if (*lenp < (i + IN6ADDRSZ)) {
+                       /* Out of memory.  Truncate address list here.  XXX */
+                       *ap = NULL;
+                       return;
+               }
+               *bpp += i;
+               *lenp -= i;
+               _map_v4v6_address(*ap, *bpp);
+               *ap = *bpp;
+               *bpp += IN6ADDRSZ;
+               *lenp -= IN6ADDRSZ;
+       }
+}
index 2d77bdf5eac33ca965f685280a97dc7776a63032..c1ec9fea1f5a4d4b7f86743be0cc9f9e2866c89d 100644 (file)
@@ -32,7 +32,7 @@
 #define strdup(x)  strcpy(malloc(strlen(x) + 1), x)
 
 extern size_t strlen(const char *);
-extern char *index(char *, char);
+extern char *index(const char *, int);
 extern char *strcpy(char *, const char *);
 extern int strcmp(const char *, const char*);
 extern void *bcopy(void *, void *, unsigned);
@@ -221,7 +221,7 @@ _old_prdb_getbyname(
        if (pf == NULL) {
                return (NULL);
        }
-       while (ent = _old_prdb_get()) {
+       while ((ent = _old_prdb_get())) {
                if (prmatch(ent, prname)) {
                        break;
                }
diff --git a/gen.subproj/rthdr.c b/gen.subproj/rthdr.c
new file mode 100644 (file)
index 0000000..4f2385e
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libc/net/rthdr.c,v 1.2 2000/03/03 11:12:59 shin Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+
+#include <string.h>
+#include <stdio.h>
+
+size_t
+inet6_rthdr_space(type, seg)
+    int type, seg;
+{
+    switch(type) {
+     case IPV6_RTHDR_TYPE_0:
+        if (seg < 1 || seg > 23)
+            return(0);
+        return(CMSG_SPACE(sizeof(struct in6_addr) * (seg - 1)
+                          + sizeof(struct ip6_rthdr0)));
+     default:
+#ifdef DEBUG
+        fprintf(stderr, "inet6_rthdr_space: unknown type(%d)\n", type);
+#endif 
+        return(0);
+    }
+}
+
+struct cmsghdr *
+inet6_rthdr_init(bp, type)
+    void *bp;
+    int type;
+{
+    register struct cmsghdr *ch = (struct cmsghdr *)bp;
+    register struct ip6_rthdr *rthdr;
+
+    rthdr = (struct ip6_rthdr *)CMSG_DATA(ch);
+
+    ch->cmsg_level = IPPROTO_IPV6;
+    ch->cmsg_type = IPV6_RTHDR;
+
+    switch(type) {
+     case IPV6_RTHDR_TYPE_0:
+        ch->cmsg_len = CMSG_LEN(sizeof(struct ip6_rthdr0) - sizeof(struct in6_addr));
+        bzero(rthdr, sizeof(struct ip6_rthdr0));
+        rthdr->ip6r_type = IPV6_RTHDR_TYPE_0;
+        return(ch);
+     default:
+#ifdef DEBUG
+        fprintf(stderr, "inet6_rthdr_init: unknown type(%d)\n", type);
+#endif 
+        return(NULL);
+    }
+}
+
+int
+inet6_rthdr_add(cmsg, addr, flags)
+    struct cmsghdr *cmsg;
+    const struct in6_addr *addr;
+    u_int flags;
+{
+    register struct ip6_rthdr *rthdr;
+
+    rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
+
+    switch(rthdr->ip6r_type) {
+     case IPV6_RTHDR_TYPE_0:
+     {
+        struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
+        if (flags != IPV6_RTHDR_LOOSE && flags != IPV6_RTHDR_STRICT) {
+#ifdef DEBUG
+            fprintf(stderr, "inet6_rthdr_add: unsupported flag(%d)\n", flags);
+#endif 
+            return(-1);
+        }
+        if (rt0->ip6r0_segleft == 23) {
+#ifdef DEBUG
+            fprintf(stderr, "inet6_rthdr_add: segment overflow\n");
+#endif 
+            return(-1);
+        }
+        if (flags == IPV6_RTHDR_STRICT) {
+            int c, b;
+            c = rt0->ip6r0_segleft / 8;
+            b = rt0->ip6r0_segleft % 8;
+            rt0->ip6r0_slmap[c] |= (1 << (7 - b));
+        }
+        rt0->ip6r0_segleft++;
+        bcopy(addr, (caddr_t)rt0 + ((rt0->ip6r0_len + 1) << 3),
+              sizeof(struct in6_addr));
+        rt0->ip6r0_len += sizeof(struct in6_addr) >> 3;
+        cmsg->cmsg_len = CMSG_LEN((rt0->ip6r0_len + 1) << 3);
+        break;
+     }
+     default:
+#ifdef DEBUG
+        fprintf(stderr, "inet6_rthdr_add: unknown type(%d)\n",
+                rthdr->ip6r_type);
+#endif 
+        return(-1);
+    }
+
+    return(0);
+}
+
+int
+inet6_rthdr_lasthop(cmsg, flags)
+    struct cmsghdr *cmsg;
+    unsigned int flags;
+{
+    register struct ip6_rthdr *rthdr;
+
+    rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
+
+    switch(rthdr->ip6r_type) {
+     case IPV6_RTHDR_TYPE_0:
+     {
+        struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
+        if (flags != IPV6_RTHDR_LOOSE && flags != IPV6_RTHDR_STRICT) {
+#ifdef DEBUG
+            fprintf(stderr, "inet6_rthdr_lasthop: unsupported flag(%d)\n", flags);
+#endif 
+            return(-1);
+        }
+        if (rt0->ip6r0_segleft > 23) {
+#ifdef DEBUG
+            fprintf(stderr, "inet6_rthdr_add: segment overflow\n");
+#endif 
+            return(-1);
+        }
+        if (flags == IPV6_RTHDR_STRICT) {
+            int c, b;
+            c = rt0->ip6r0_segleft / 8;
+            b = rt0->ip6r0_segleft % 8;
+            rt0->ip6r0_slmap[c] |= (1 << (7 - b));
+        }
+        break;
+     }
+     default:
+#ifdef DEBUG
+        fprintf(stderr, "inet6_rthdr_lasthop: unknown type(%d)\n",
+                rthdr->ip6r_type);
+#endif 
+        return(-1);
+    }
+
+    return(0);
+}
+
+#if 0
+int
+inet6_rthdr_reverse(in, out)
+    const struct cmsghdr *in;
+    struct cmsghdr *out;
+{
+#ifdef DEBUG
+    fprintf(stderr, "inet6_rthdr_reverse: not implemented yet\n");
+#endif 
+    return -1;
+}
+#endif
+
+int
+inet6_rthdr_segments(cmsg)
+    const struct cmsghdr *cmsg;
+{
+    register struct ip6_rthdr *rthdr;
+
+    rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
+
+    switch(rthdr->ip6r_type) {
+    case IPV6_RTHDR_TYPE_0:
+      {
+       struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
+
+       if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len) {
+#ifdef DEBUG
+           fprintf(stderr, "inet6_rthdr_segments: invalid size(%d)\n",
+               rt0->ip6r0_len);
+#endif 
+           return -1;
+       }
+
+       return (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
+      }
+
+    default:
+#ifdef DEBUG
+       fprintf(stderr, "inet6_rthdr_segments: unknown type(%d)\n",
+           rthdr->ip6r_type);
+#endif 
+       return -1;
+    }
+}
+
+struct in6_addr *
+inet6_rthdr_getaddr(cmsg, index)
+    struct cmsghdr *cmsg;
+    int index;
+{
+    register struct ip6_rthdr *rthdr;
+
+    rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
+
+    switch(rthdr->ip6r_type) {
+    case IPV6_RTHDR_TYPE_0:
+      {
+       struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
+       int naddr;
+
+       if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len) {
+#ifdef DEBUG
+           fprintf(stderr, "inet6_rthdr_getaddr: invalid size(%d)\n",
+               rt0->ip6r0_len);
+#endif 
+           return NULL;
+       }
+       naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
+       if (index <= 0 || naddr < index) {
+#ifdef DEBUG
+           fprintf(stderr, "inet6_rthdr_getaddr: invalid index(%d)\n", index);
+#endif 
+           return NULL;
+       }
+       return &rt0->ip6r0_addr[index - 1];
+      }
+
+    default:
+#ifdef DEBUG
+       fprintf(stderr, "inet6_rthdr_getaddr: unknown type(%d)\n",
+           rthdr->ip6r_type);
+#endif 
+       return NULL;
+    }
+}
+
+int
+inet6_rthdr_getflags(cmsg, index)
+    const struct cmsghdr *cmsg;
+    int index;
+{
+    register struct ip6_rthdr *rthdr;
+
+    rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
+
+    switch(rthdr->ip6r_type) {
+    case IPV6_RTHDR_TYPE_0:
+      {
+       struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
+       int naddr;
+
+       if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len) {
+#ifdef DEBUG
+           fprintf(stderr, "inet6_rthdr_getflags: invalid size(%d)\n",
+               rt0->ip6r0_len);
+#endif 
+           return -1;
+       }
+       naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
+       if (index < 0 || naddr < index) {
+#ifdef DEBUG
+           fprintf(stderr, "inet6_rthdr_getflags: invalid index(%d)\n", index);
+#endif 
+           return -1;
+       }
+       if (rt0->ip6r0_slmap[index / 8] & (0x80 >> (index % 8)))
+           return IPV6_RTHDR_STRICT;
+       else
+           return IPV6_RTHDR_LOOSE;
+      }
+
+    default:
+#ifdef DEBUG
+       fprintf(stderr, "inet6_rthdr_getflags: unknown type(%d)\n",
+           rthdr->ip6r_type);
+#endif 
+       return -1;
+    }
+}
diff --git a/gen.subproj/vars.c b/gen.subproj/vars.c
new file mode 100644 (file)
index 0000000..27e9a45
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libc/net/vars.c,v 1.1 1999/12/16 18:32:01 shin Exp $
+ */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+/*
+ * Definitions of some costant IPv6 addresses.
+ */
+const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
+const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
+const struct in6_addr in6addr_nodelocal_allnodes = IN6ADDR_NODELOCAL_ALLNODES_INIT;
+const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
+const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
+
index 2122bc1134fb1c0747c98c5312b46aa33e111e22..7148858d09996f4c39faa559fd1b7490d02e0708 100644 (file)
@@ -13,10 +13,10 @@ PROJECTVERSION = 2.8
 PROJECT_TYPE = Component
 
 HFILES = aliasdb.h bootparams.h lookup_types.h lu_overrides.h\
-         lu_utils.h netgr.h printerdb.h
+         lu_host.h lu_utils.h netdb_async.h netgr.h printerdb.h
 
 CFILES = lu_alias.c lu_bootp.c lu_bootparam.c lu_fstab.c lu_group.c\
-         lu_host.c lu_netgroup.c lu_network.c lu_printer.c\
+         lu_host.c lu_host_async.c lu_netgroup.c lu_network.c lu_printer.c\
          lu_protocol.c lu_rpc.c lu_service.c lu_user.c lu_utils.c
 
 OTHERSRCS = Makefile.preamble Makefile Makefile.postamble lookup.defs\
index cf760874758e674c187827fda53acac9db1d0927..447fe32dbf44923282c55ef14e4e4f7b8915fddd 100644 (file)
@@ -1,6 +1,12 @@
 %_xdr.c: %.x
        $(RPCGEN) $(ALL_RPCFLAGS) -c -o $(SYM_DIR)/$*_xdr.c $*.x
 
+async_hdrs: $(DSTROOT)$(PRIVATE_HDR_INSTALLDIR)$(ASYNC_HEADER_DIR_SUFFIX)
+       $(SILENT) $(FASTCP) $(ASYNC_HDRS) $(DSTROOT)$(PRIVATE_HDR_INSTALLDIR)$(ASYNC_HEADER_DIR_SUFFIX)
+
+$(DSTROOT)$(PRIVATE_HDR_INSTALLDIR)$(ASYNC_HEADER_DIR_SUFFIX):
+       $(MKDIRS) $@
+
 netinfo_hdrs: $(DSTROOT)$(PUBLIC_HDR_INSTALLDIR)$(NETINFO_HEADER_DIR_SUFFIX)
        $(SILENT) $(FASTCP) $(NETINFO_HDRS) $(DSTROOT)$(PUBLIC_HDR_INSTALLDIR)$(NETINFO_HEADER_DIR_SUFFIX)
 
index 9a094c2430ee291e27d5f6ecde08f21ef88a088a..83a0b9c43dc0ef0602b174c19a0d9c61e9e68c08 100644 (file)
@@ -1,8 +1,11 @@
 RPCFILES = _lu_types.x
 OTHER_OFILES = lookupUser.o _lu_types_xdr.o
 AFTER_PREBUILD = _lu_types.h lookupUser.c 
+ASYNC_HDRS = netdb_async.h
 NETINFO_HDRS = lookup.h _lu_types.h lookup_types.h lookup.defs _lu_types.x
-BEFORE_INSTALLHDRS += $(SFILE_DIR) $(NETINFO_HDRS)
-AFTER_INSTALLHDRS += netinfo_hdrs
+BEFORE_INSTALLHDRS += $(SFILE_DIR) $(ASYNC_HDRS) $(NETINFO_HDRS)
+AFTER_INSTALLHDRS += async_hdrs netinfo_hdrs
 PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR = /usr/local/include
+ASYNC_HEADER_DIR_SUFFIX = /
 NETINFO_HEADER_DIR_SUFFIX = /netinfo
index 8270f85b2841fe686ac248a2c0580e75496de25a..e3a62e04e22a3b97dc21e69965f53f082f8c4fb7 100644 (file)
@@ -6,7 +6,9 @@
             bootparams.h, 
             lookup_types.h, 
             lu_overrides.h, 
+            lu_host.h, 
             lu_utils.h, 
+            netdb_async.h, 
             netgr.h, 
             printerdb.h
         ); 
@@ -17,6 +19,7 @@
             lu_fstab.c, 
             lu_group.c, 
             lu_host.c, 
+            lu_host_async.c, 
             lu_netgroup.c, 
             lu_network.c, 
             lu_printer.c, 
index 167d6096ce8e553462b413116474f3e512babd3b..430e2b404da08937c24f5e6eb2b6508eb6099506 100644 (file)
@@ -35,9 +35,9 @@ serverprefix _;
 
 import <netinfo/lookup_types.h>;
 
+#include <mach/std_types.defs>
+#include <mach/mach_types.defs>
 
-type int = MACH_MSG_TYPE_INTEGER_32;
-type mach_port_t = MACH_MSG_TYPE_COPY_SEND;
 type lookup_name = array [256] of MACH_MSG_TYPE_CHAR;
 type unit = array [4] of MACH_MSG_TYPE_CHAR;
 
@@ -48,24 +48,37 @@ type unit = array [4] of MACH_MSG_TYPE_CHAR;
 type inline_data = array [ * : 4096 ] of unit; 
 type ooline_data = ^ array [] of unit;
 
+routine _lookup_link_secure
+(
+       server : mach_port_t;
+       name : lookup_name;
+       out procno : int;
+       UserSecToken token : security_token_t
+);
 
-routine _lookup_link(  server : mach_port_t;
-                       name : lookup_name;
-               out     procno: int);
+routine _lookup_all_secure
+(
+       server : mach_port_t;
+       proc : int;
+       indata : inline_data;
+       out outdata  : ooline_data;
+       UserSecToken token : security_token_t
+);
 
-routine _lookup_all(   server : mach_port_t;
-                       proc : int;
-                       indata : inline_data;
-               out     outdata  : ooline_data);
-
-routine _lookup_one(   server : mach_port_t;
-                       proc : int;
-                       indata : inline_data;
-               out     outdata  : inline_data);
-
-
-routine _lookup_ooall( server : mach_port_t;
-                       proc : int;
-                       indata : ooline_data;
-               out     outdata  : ooline_data);
+routine _lookup_one_secure
+(
+       server : mach_port_t;
+       proc : int;
+       indata : inline_data;
+       out outdata  : inline_data;
+       UserSecToken token : security_token_t
+);
 
+routine _lookup_ooall_secure
+(
+       server : mach_port_t;
+       proc : int;
+       indata : ooline_data;
+       out outdata  : ooline_data;
+       UserSecToken token : security_token_t
+);
index f215067c7913f05f2ecbb8448a8f177874ad6b6c..7d22d9196d01a361aa31d48a4d6d615e8f095d47 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <rpc/types.h>
 #include <rpc/xdr.h>
 #include <aliasdb.h>
+#include <pthread.h>
 
-#include "lookup.h"
 #include "_lu_types.h"
+#include "lookup.h"
 #include "lu_utils.h"
 #include "lu_overrides.h"
 
-static lookup_state alias_state = LOOKUP_CACHE;
-static struct aliasent global_aliasent;
-static int global_free = 1;
-static char *alias_data = NULL;
-static unsigned alias_datalen;
-static int alias_nentries = 0;
-static int alias_start = 1;
-static XDR alias_xdr;
+static pthread_mutex_t _alias_lock = PTHREAD_MUTEX_INITIALIZER;
 
 static void 
-freeold(void)
+free_alias_data(struct aliasent *a)
 {
-       int i, len;
+       int i;
 
-       if (global_free == 1) return;
+       if (a == NULL) return;
+
+       if (a->alias_name != NULL) free(a->alias_name);
+       for (i = 0; i < a->alias_members_len; i++) free(a->alias_members[i]);
+       if (a->alias_members != NULL) free(a->alias_members);
+}
 
-       free(global_aliasent.alias_name);
+static void 
+free_alias(struct aliasent *a)
+{
+       if (a == NULL) return;
+       free_alias_data(a);
+       free(a);
+}
 
-       len = global_aliasent.alias_members_len;
-       for (i = 0; i < len; i++)
-               free(global_aliasent.alias_members[i]);
+static void
+free_lu_thread_info_alias(void *x)
+{
+       struct lu_thread_info *tdata;
+
+       if (x == NULL) return;
+
+       tdata = (struct lu_thread_info *)x;
+       
+       if (tdata->lu_entry != NULL)
+       {
+               free_alias((struct aliasent *)tdata->lu_entry);
+               tdata->lu_entry = NULL;
+       }
 
-       free(global_aliasent.alias_members);
+       _lu_data_free_vm_xdr(tdata);
 
-       global_free = 1;
+       free(tdata);
 }
 
-static void
-convert_aliasent(_lu_aliasent *lu_aliasent)
+static struct aliasent *
+extract_alias(XDR *xdr)
+{
+       int i, j, nkeys, nvals, status;
+       char *key, **vals;
+       struct aliasent *a;
+
+       if (xdr == NULL) return NULL;
+
+       if (!xdr_int(xdr, &nkeys)) return NULL;
+
+       a = (struct aliasent *)calloc(1, sizeof(struct aliasent));
+
+       for (i = 0; i < nkeys; i++)
+       {
+               key = NULL;
+               vals = NULL;
+               nvals = 0;
+
+               status = _lu_xdr_attribute(xdr, &key, &vals, &nvals);
+               if (status < 0)
+               {
+                       free_alias(a);
+                       return NULL;
+               }
+
+               if (nvals == 0)
+               {
+                       free(key);
+                       continue;
+               }
+
+               j = 0;
+
+               if ((a->alias_name == NULL) && (!strcmp("name", key)))
+               {
+                       a->alias_name = vals[0];
+                       j = 1;
+               }
+               else if (!strcmp("alias_local", key))
+               {
+                       a->alias_local = atoi(vals[0]);
+               }
+               else if ((a->alias_members == NULL) && (!strcmp("members", key)))
+               {
+                       a->alias_members_len = nvals;
+                       a->alias_members = vals;
+                       j = nvals;
+                       vals = NULL;
+               }
+
+               free(key);
+               if (vals != NULL)
+               {
+                       for (; j < nvals; j++) free(vals[j]);
+                       free(vals);
+               }
+       }
+
+       if (a->alias_name == NULL) a->alias_name = strdup("");
+       if (a->alias_members == NULL) a->alias_members = (char **)calloc(1, sizeof(char *));
+
+       return a;
+}
+
+static struct aliasent *
+copy_alias(struct aliasent *in)
 {
-       int i, len;
+       int i;
+       struct aliasent *a;
+
+       if (in == NULL) return NULL;
+
+       a = (struct aliasent *)calloc(1, sizeof(struct aliasent));
+
+       a->alias_name = LU_COPY_STRING(in->alias_name);
+
+       a->alias_members_len = in->alias_members_len;
+
+       if (a->alias_members_len == 0)
+       {
+               a->alias_members = (char **)calloc(1, sizeof(char *));
+       }
+       else
+       {
+               a->alias_members = (char **)calloc(a->alias_members_len, sizeof(char *));
+       }
 
-       freeold();
+       for (i = 0; i < a->alias_members_len; i++)
+       {
+               a->alias_members[i] = strdup(in->alias_members[i]);
+       }
 
-       global_aliasent.alias_name = strdup(lu_aliasent->alias_name);
+       a->alias_local = in->alias_local;
 
-       len = lu_aliasent->alias_members.alias_members_len;
-       global_aliasent.alias_members_len = len;
-       global_aliasent.alias_members = (char **)malloc(len * sizeof(char *));
+       return a;
+}
 
-       for (i = 0; i < len; i++)
+static void
+recycle_alias(struct lu_thread_info *tdata, struct aliasent *in)
+{
+       struct aliasent *a;
+
+       if (tdata == NULL) return;
+       a = (struct aliasent *)tdata->lu_entry;
+
+       if (in == NULL)
+       {
+               free_alias(a);
+               tdata->lu_entry = NULL;
+       }
+
+       if (tdata->lu_entry == NULL)
        {
-               global_aliasent.alias_members[i] =
-                       strdup(lu_aliasent->alias_members.alias_members_val[i]);
+               tdata->lu_entry = in;
+               return;
        }
 
-       global_aliasent.alias_local = lu_aliasent->alias_local;
+       free_alias_data(a);
+
+       a->alias_name = in->alias_name;
+       a->alias_members_len = in->alias_members_len;
+       a->alias_members = in->alias_members;
+       a->alias_local = in->alias_local;
 
-       global_free = 0;
+       free(in);
 }
 
 static struct aliasent *
 lu_alias_getbyname(const char *name)
 {
-       unsigned datalen;
+       struct aliasent *a;
+       unsigned int datalen;
        char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT];
-       unit lookup_buf[MAX_INLINE_UNITS];
+       char *lookup_buf;
        XDR outxdr;
        XDR inxdr;
-       _lu_aliasent_ptr lu_aliasent;
        static int proc = -1;
+       int count;
 
        if (proc < 0)
        {
                if (_lookup_link(_lu_port, "alias_getbyname", &proc) != KERN_SUCCESS)
                {
-                       return (NULL);
+                       return NULL;
                }
        }
 
        xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE);
-       if (!xdr__lu_string(&outxdr, &name))
+       if (!xdr__lu_string(&outxdr, (_lu_string *)&name))
        {
                xdr_destroy(&outxdr);
-               return (NULL);
+               return NULL;
        }
        
-       datalen = MAX_INLINE_UNITS;
-       if (_lookup_one(_lu_port, proc, (unit *)namebuf,
-               xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, lookup_buf, &datalen)
+       datalen = 0;
+       lookup_buf = NULL;
+       
+       if (_lookup_all(_lu_port, proc, (unit *)namebuf,
+               xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, &lookup_buf, &datalen)
                != KERN_SUCCESS)
        {
                xdr_destroy(&outxdr);
-               return (NULL);
+               return NULL;
        }
 
        xdr_destroy(&outxdr);
 
        datalen *= BYTES_PER_XDR_UNIT;
-       xdrmem_create(&inxdr, lookup_buf, datalen,
-               XDR_DECODE);
-       lu_aliasent = NULL;
-       if (!xdr__lu_aliasent_ptr(&inxdr, &lu_aliasent) || (lu_aliasent == NULL))
+       if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
+
+       xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
+
+       count = 0;
+       if (!xdr_int(&inxdr, &count))
+       {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
+       }
+
+       if (count == 0)
        {
                xdr_destroy(&inxdr);
-               return (NULL);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
        }
 
+       a = extract_alias(&inxdr);
        xdr_destroy(&inxdr);
+       vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
 
-       convert_aliasent(lu_aliasent);
-       xdr_free(xdr__lu_aliasent_ptr, &lu_aliasent);
-       return (&global_aliasent);
+       return a;
 }
 
 static void
 lu_alias_endent(void)
 {
-       alias_nentries = 0;
-       if (alias_data != NULL)
-       {
-               freeold();
-               vm_deallocate(mach_task_self(), (vm_address_t)alias_data, alias_datalen);
-               alias_data = NULL;
-       }
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_alias, free_lu_thread_info_alias);
+       _lu_data_free_vm_xdr(tdata);
 }
 
 static void
 lu_alias_setent(void)
 {
        lu_alias_endent();
-       alias_start = 1;
 }
 
 static struct aliasent *
 lu_alias_getent(void)
 {
        static int proc = -1;
-       _lu_aliasent lu_aliasent;
+       struct lu_thread_info *tdata;
+       struct aliasent *a;
 
-       if (alias_start == 1)
+       tdata = _lu_data_create_key(_lu_data_key_alias, free_lu_thread_info_alias);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_alias, tdata);
+       }
+\r
+       if (tdata->lu_vm == NULL)
        {
-               alias_start = 0;
-
                if (proc < 0)
                {
                        if (_lookup_link(_lu_port, "alias_getent", &proc) != KERN_SUCCESS)
                        {
                                lu_alias_endent();
-                               return (NULL);
+                               return NULL;
                        }
                }
 
-               if (_lookup_all(_lu_port, proc, NULL, 0, &alias_data, &alias_datalen)
-                       != KERN_SUCCESS)
+               if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS)
                {
                        lu_alias_endent();
-                       return (NULL);
+                       return NULL;
                }
 
-#ifdef NOTDEF
-/* NOTDEF because OOL buffers are counted in bytes with untyped IPC */
-               alias_datalen *= BYTES_PER_XDR_UNIT;
-#endif
-               xdrmem_create(&alias_xdr, alias_data,
-                       alias_datalen, XDR_DECODE);
-               if (!xdr_int(&alias_xdr, &alias_nentries))
+               /* mig stubs measure size in words (4 bytes) */
+               tdata->lu_vm_length *= 4;
+
+               if (tdata->lu_xdr != NULL)
+               {
+                       xdr_destroy(tdata->lu_xdr);
+                       free(tdata->lu_xdr);
+               }
+               tdata->lu_xdr = (XDR *)calloc(1, sizeof(XDR));
+
+               xdrmem_create(tdata->lu_xdr, tdata->lu_vm, tdata->lu_vm_length, XDR_DECODE);
+               if (!xdr_int(tdata->lu_xdr, &tdata->lu_vm_cursor))
                {
-                       xdr_destroy(&alias_xdr);
                        lu_alias_endent();
-                       return (NULL);
+                       return NULL;
                }
        }
 
-       if (alias_nentries == 0)
+       if (tdata->lu_vm_cursor == 0)
        {
-               xdr_destroy(&alias_xdr);
                lu_alias_endent();
-               return (NULL);
+               return NULL;
        }
 
-       bzero(&lu_aliasent, sizeof(lu_aliasent));
-       if (!xdr__lu_aliasent(&alias_xdr, &lu_aliasent))
+
+       a = extract_alias(tdata->lu_xdr);
+       if (a == NULL)
        {
-               xdr_destroy(&alias_xdr);
                lu_alias_endent();
-               return (NULL);
+               return NULL;
        }
 
-       alias_nentries--;
-       convert_aliasent(&lu_aliasent);
-       xdr_free(xdr__lu_aliasent, &lu_aliasent);
-       return (&global_aliasent);
+       tdata->lu_vm_cursor--;
+       
+       return a;
 }
 
 struct aliasent *
 alias_getbyname(const char *name)
 {
-       LOOKUP1(lu_alias_getbyname, _old_alias_getbyname, name, struct aliasent);
+       struct aliasent *res = NULL;
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_alias, free_lu_thread_info_alias);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_alias, tdata);
+       }
+
+       if (_lu_running())
+       {
+               res = lu_alias_getbyname(name);
+       }
+       else
+       {
+               pthread_mutex_lock(&_alias_lock);
+               res = copy_alias(_old_alias_getbyname(name));
+               pthread_mutex_unlock(&_alias_lock);
+       }
+
+       recycle_alias(tdata, res);
+       return (struct aliasent *)tdata->lu_entry;
+
 }
 
 struct aliasent *
 alias_getent(void)
 {
-       GETENT(lu_alias_getent, _old_alias_getent, &alias_state, struct aliasent);
+       struct aliasent *res = NULL;
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_alias, free_lu_thread_info_alias);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_alias, tdata);
+       }
+
+       if (_lu_running())
+       {
+               res = lu_alias_getent();
+       }
+       else
+       {
+               pthread_mutex_lock(&_alias_lock);
+               res = copy_alias(_old_alias_getent());
+               pthread_mutex_unlock(&_alias_lock);
+       }
+
+       recycle_alias(tdata, res);
+       return (struct aliasent *)tdata->lu_entry;
+
 }
 
 void
 alias_setent(void)
 {
-       SETSTATEVOID(lu_alias_setent, _old_alias_setent, &alias_state);
+       if (_lu_running()) lu_alias_setent();
+       else _old_alias_setent();
 }
 
 void
 alias_endent(void)
 {
-       UNSETSTATE(lu_alias_endent, _old_alias_endent, &alias_state);
+       if (_lu_running()) lu_alias_endent();
+       else _old_alias_endent();
 }
index ca85dbe6258b28913f6ea192647d09d5d4ca6b02..d3a9aa9b43b6d15060e51f69f98d1cf82937d6c8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  */
 #include <mach/mach.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
-#include "lookup.h"
 #include <rpc/types.h>
 #include <rpc/xdr.h>
-#include "_lu_types.h"
-#include "lu_utils.h"
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <net/if.h>
 #include <netinet/if_ether.h>
+#include <pthread.h>
+
+#include "_lu_types.h"
+#include "lookup.h"
+#include "lu_utils.h"
+
+extern struct ether_addr *ether_aton(char *);
+
+static pthread_mutex_t _bootp_lock = PTHREAD_MUTEX_INITIALIZER;
+
+struct bootpent
+{
+       char *b_name;
+       struct ether_addr b_enaddr;
+       struct in_addr b_ipaddr;
+       char *b_bootfile;
+};
+
+static void
+free_bootp(struct bootpent *b)
+{
+       if (b == NULL) return;
+
+       if (b->b_name != NULL) free(b->b_name);
+       if (b->b_bootfile != NULL) free(b->b_bootfile);
+
+       free(b);
+}
+
+static struct bootpent *
+extract_bootp(XDR *xdr)
+{
+       struct bootpent *b;
+       struct ether_addr *e;
+       int i, j, nvals, nkeys, status;
+       char *key, **vals;
+
+       if (xdr == NULL) return NULL;
+
+       if (!xdr_int(xdr, &nkeys)) return NULL;
+
+       b = (struct bootpent *)calloc(1, sizeof(struct bootpent));
+
+       for (i = 0; i < nkeys; i++)
+       {
+               key = NULL;
+               vals = NULL;
+               nvals = 0;
+
+               status = _lu_xdr_attribute(xdr, &key, &vals, &nvals);
+               if (status < 0)
+               {
+                       free_bootp(b);
+                       return NULL;
+               }
+
+               if (nvals == 0)
+               {
+                       free(key);
+                       continue;
+               }
+
+               j = 0;
+
+               if ((b->b_name == NULL) && (!strcmp("name", key)))
+               {
+                       b->b_name = vals[0];
+                       j = 1;
+               }
+               if ((b->b_name == NULL) && (!strcmp("bootfile", key)))
+               {
+                       b->b_bootfile = vals[0];
+                       j = 1;
+               }
+               else if (!strcmp("ip_address", key))
+               {
+                       b->b_ipaddr.s_addr = inet_addr(vals[0]);
+               }
+               else if (!strcmp("en_address", key))
+               {
+                       pthread_mutex_lock(&_bootp_lock);
+                       e = ether_aton(vals[0]);
+                       if (e != NULL) memcpy(&(b->b_enaddr), e, sizeof(struct ether_addr));
+                       pthread_mutex_unlock(&_bootp_lock);
+                       j = 1;
+               }
+
+               free(key);
+               if (vals != NULL)
+               {
+                       for (; j < nvals; j++) free(vals[j]);
+                       free(vals);
+               }
+       }
+
+       if (b->b_name == NULL) b->b_name = strdup("");
+       if (b->b_bootfile == NULL) b->b_bootfile = strdup("");
+
+       return b;
+}
 
 static int 
 lu_bootp_getbyether(struct ether_addr *enaddr, char **name,
        struct in_addr *ipaddr, char **bootfile)
 {
        unsigned datalen;
-       XDR xdr;
-       static _lu_bootp_ent_ptr bp;
+       XDR inxdr;
+       struct bootpent *b;
        static int proc = -1;
-       unit lookup_buf[MAX_INLINE_UNITS];
-       
+       char *lookup_buf;
+       int count;
+
        if (proc < 0)
        {
                if (_lookup_link(_lu_port, "bootp_getbyether", &proc) != KERN_SUCCESS)
                {
-                       return (0);
+                       return 0;
                }
        }
 
-       datalen = MAX_INLINE_UNITS;
-       if (_lookup_one(_lu_port, proc, (unit *)enaddr, 
-               ((sizeof(*enaddr) + sizeof(unit) - 1) / sizeof(unit)), lookup_buf, 
-               &datalen) != KERN_SUCCESS)
+       datalen = 0;
+       lookup_buf = NULL;
+
+       if (_lookup_all(_lu_port, proc, (unit *)enaddr, ((sizeof(*enaddr) + sizeof(unit) - 1) / sizeof(unit)), &lookup_buf, &datalen) != KERN_SUCCESS)
        {
-               return (0);
+               return 0;
        }
 
        datalen *= BYTES_PER_XDR_UNIT;
-       xdrmem_create(&xdr, lookup_buf, datalen, XDR_DECODE);
-       xdr_free(xdr__lu_bootp_ent_ptr, &bp);
-       if (!xdr__lu_bootp_ent_ptr(&xdr, &bp) || (bp == NULL))
+       if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
+
+       xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
+
+       count = 0;
+       if (!xdr_int(&inxdr, &count))
        {
-               xdr_destroy(&xdr);
-               return (0);
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return 0;
        }
 
-       xdr_destroy(&xdr);
+       if (count == 0)
+       {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return 0;
+       }
 
-       *name = bp->bootp_name;
-       *bootfile = bp->bootp_bootfile;
-       ipaddr->s_addr = bp->bootp_ipaddr;
-       return (1);
+       b = extract_bootp(&inxdr);
+       xdr_destroy(&inxdr);
+
+       *name = b->b_name;
+       *bootfile = b->b_bootfile;
+       ipaddr->s_addr = b->b_ipaddr.s_addr;
+
+       free(b);
+       vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+
+       return 1;
 }
 
 static int 
@@ -87,59 +202,78 @@ lu_bootp_getbyip(struct ether_addr *enaddr, char **name,
        struct in_addr *ipaddr, char **bootfile)
 {
        unsigned datalen;
-       XDR xdr;
-       static _lu_bootp_ent_ptr bp;
+       XDR inxdr;
+       struct bootpent *b;
        static int proc = -1;
-       unit lookup_buf[MAX_INLINE_UNITS];
+       char *lookup_buf;
+       int count;
        
        if (proc < 0)
        {
                if (_lookup_link(_lu_port, "bootp_getbyip", &proc) != KERN_SUCCESS)
                {
-                       return (0);
+                       return 0;
                }
        }
 
-       datalen = MAX_INLINE_UNITS;
-       if (_lookup_one(_lu_port, proc, (unit *)ipaddr, 
-               ((sizeof(*ipaddr) + sizeof(unit) - 1) / sizeof(unit)), lookup_buf, 
-               &datalen) != KERN_SUCCESS)
+       datalen = 0;
+       lookup_buf = NULL;
+
+       if (_lookup_all(_lu_port, proc, (unit *)ipaddr, ((sizeof(*ipaddr) + sizeof(unit) - 1) / sizeof(unit)), &lookup_buf, &datalen) != KERN_SUCCESS)
        {
-               return (0);
+               return 0;
        }
 
        datalen *= BYTES_PER_XDR_UNIT;
-       xdrmem_create(&xdr, lookup_buf, datalen, XDR_DECODE);
-       xdr_free(xdr__lu_bootp_ent_ptr, &bp);
-       if (!xdr__lu_bootp_ent_ptr(&xdr, &bp) || (bp == NULL))
+       if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
+
+       xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
+
+       count = 0;
+       if (!xdr_int(&inxdr, &count))
+       {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return 0;
+       }
+
+       if (count == 0)
        {
-               xdr_destroy(&xdr);
-               return (0);
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return 0;
        }
 
-       xdr_destroy(&xdr);
+       b = extract_bootp(&inxdr);
+       xdr_destroy(&inxdr);
 
-       *name = bp->bootp_name;
-       *bootfile = bp->bootp_bootfile;
-       bcopy(bp->bootp_enaddr, enaddr, sizeof(*enaddr));
-       return (1);
+       *name = b->b_name;
+       *bootfile = b->b_bootfile;
+       memcpy(enaddr, &(b->b_enaddr), sizeof(struct ether_addr));
+
+       free(b);
+       vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+
+       return 1;
 }
 
 int
-bootp_getbyether(struct ether_addr *enaddr, char **name,
-       struct in_addr *ipaddr, char **bootfile)
+bootp_getbyether(struct ether_addr *enaddr, char **name,struct in_addr *ipaddr, char **bootfile)
 {
        if (_lu_running())
+       {
                return (lu_bootp_getbyether(enaddr, name, ipaddr, bootfile));
-       return (0);
+       }
+       return 0;
 }
 
 int
-bootp_getbyip(struct ether_addr *enaddr, char **name,
-       struct in_addr *ipaddr, char **bootfile)
+bootp_getbyip(struct ether_addr *enaddr, char **name, struct in_addr *ipaddr, char **bootfile)
 {
        if (_lu_running())
+       {
                return (lu_bootp_getbyip(enaddr, name, ipaddr, bootfile));
-       return (0);
+       }
+       return 0;
 }
 
index 9386e98c9627dd06ed157976d966ce76db307a78..9594b7421829647d04b173c02f8ef7896886a9d1 100644 (file)
 #include "_lu_types.h"
 #include "lu_utils.h"
 
-static lookup_state bp_state = LOOKUP_CACHE;
-static struct bootparamsent global_bp;
-static int global_free = 1;
-static char *bp_data = NULL;
-static unsigned bp_datalen;
-static int bp_nentries;
-static int bp_start = 1;
-static XDR bp_xdr;
-
 static void 
-freeold(void)
+free_bootparams_data(struct bootparamsent *b)
 {
-       int i;
-       if (global_free == 1) return;
+       char **param;
 
-       free(global_bp.bp_name);
+       if (b == NULL) return;
 
-       for (i = 0; global_bp.bp_bootparams[i] != NULL; i++)
-               free(global_bp.bp_bootparams[i]);
+       if (b->bp_name != NULL) free(b->bp_name);
 
-       global_free = 1;
+       param = b->bp_bootparams;
+       if (param != NULL)
+       {
+               while (*param != NULL) free(*param++);
+               free(b->bp_bootparams);
+       }
+}
+
+static void 
+free_bootparams(struct bootparamsent *b)
+{
+       if (b == NULL) return;
+       free_bootparams_data(b);
+       free(b);
 }
 
 static void
-convert_bootparamsent(_lu_bootparams_ent *lu_bpent)
+free_lu_thread_info_bootparams(void *x)
+{
+       struct lu_thread_info *tdata;
+
+       if (x == NULL) return;
+
+       tdata = (struct lu_thread_info *)x;
+       
+       if (tdata->lu_entry != NULL)
+       {
+               free_bootparams((struct bootparamsent *)tdata->lu_entry);
+               tdata->lu_entry = NULL;
+       }
+
+       _lu_data_free_vm_xdr(tdata);
+
+       free(tdata);
+}
+
+static struct bootparamsent *
+extract_bootparams(XDR *xdr)
 {
-       int i, len;
+       int i, j, nkeys, nvals, status;
+       char *key, **vals;
+       struct bootparamsent *b;
 
-       freeold();
+       if (xdr == NULL) return NULL;
 
-       global_bp.bp_name = strdup(lu_bpent->bootparams_name);
+       if (!xdr_int(xdr, &nkeys)) return NULL;
 
-       len = lu_bpent->bootparams_keyvalues.bootparams_keyvalues_len;
-       global_bp.bp_bootparams = (char **)malloc((len + 1) * sizeof(char *));
+       b = (struct bootparamsent *)calloc(1, sizeof(struct bootparamsent));
 
-       for (i = 0; i < len; i++)
+       for (i = 0; i < nkeys; i++)
        {
-               global_bp.bp_bootparams[i] =
-                       strdup(lu_bpent->bootparams_keyvalues.bootparams_keyvalues_val[i]);
+               key = NULL;
+               vals = NULL;
+               nvals = 0;
+
+               status = _lu_xdr_attribute(xdr, &key, &vals, &nvals);
+               if (status < 0)
+               {
+                       free_bootparams(b);
+                       return NULL;
+               }
+
+               if (nvals == 0)
+               {
+                       free(key);
+                       continue;
+               }
+
+               j = 0;
+       
+               if ((b->bp_name == NULL) && (!strcmp("name", key)))
+               {
+                       b->bp_name = vals[0];
+                       j = 1;
+               }
+               else if ((b->bp_bootparams == NULL) && (!strcmp("bootparams", key)))
+               {
+                       b->bp_bootparams = vals;
+                       j = nvals;
+                       vals = NULL;
+               }
+
+               free(key);
+               if (vals != NULL)
+               {
+                       for (; j < nvals; j++) free(vals[j]);
+                       free(vals);
+               }
        }
 
-       global_bp.bp_bootparams[len] = NULL;
+       if (b->bp_name == NULL) b->bp_name = strdup("");
+       if (b->bp_bootparams == NULL) b->bp_bootparams = (char **)calloc(1, sizeof(char *));
 
-       global_free = 0;
+       return b;
+}
+
+static void 
+recycle_bootparams(struct lu_thread_info *tdata, struct bootparamsent *in)
+{
+       struct bootparamsent *b;
+
+       if (tdata == NULL) return;
+       b = (struct bootparamsent *)tdata->lu_entry;
+
+       if (in == NULL)
+       {
+               free_bootparams(b);
+               tdata->lu_entry = NULL;
+       }
+
+       if (tdata->lu_entry == NULL)
+       {
+               tdata->lu_entry = in;
+               return;
+       }
+
+       free_bootparams_data(b);
+
+       b->bp_name = in->bp_name;
+       b->bp_bootparams = in->bp_bootparams;
+
+       free(in);
 }
 
 static struct bootparamsent *
 lu_bootparams_getbyname(const char *name)
 {
+       struct bootparamsent *b;
        unsigned datalen;
        char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT];
-       unit lookup_buf[MAX_INLINE_UNITS];
+       char *lookup_buf;
        XDR outxdr;
        XDR inxdr;
        int size;
-       _lu_bootparams_ent_ptr lu_bpent;
        static int proc = -1;
-       
+       int count;
+
        if (proc < 0)
        {
                if (_lookup_link(_lu_port, "bootparams_getbyname", &proc)
@@ -105,7 +193,7 @@ lu_bootparams_getbyname(const char *name)
        }
 
        xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE);
-       if (!xdr__lu_string(&outxdr, &name))
+       if (!xdr__lu_string(&outxdr, (_lu_string *)&name))
        {
                xdr_destroy(&outxdr);
                return (NULL);
@@ -114,123 +202,168 @@ lu_bootparams_getbyname(const char *name)
        size = xdr_getpos(&outxdr);
        xdr_destroy(&outxdr);
 
-       datalen = MAX_INLINE_UNITS;
-       if (_lookup_one(_lu_port, proc, (unit *)namebuf, size, lookup_buf, 
+       datalen = 0;
+       lookup_buf = NULL;
+
+       if (_lookup_all(_lu_port, proc, (unit *)namebuf, size, &lookup_buf, 
                &datalen) != KERN_SUCCESS)
        {
                return (NULL);
        }
 
        datalen *= BYTES_PER_XDR_UNIT;
-       xdrmem_create(&inxdr, lookup_buf, datalen,
-               XDR_DECODE);
-       lu_bpent = NULL;
-       if (!xdr__lu_bootparams_ent_ptr(&inxdr, &lu_bpent) || (lu_bpent == NULL))
+       if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
+
+       xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
+
+       count = 0;
+       if (!xdr_int(&inxdr, &count))
        {
                xdr_destroy(&inxdr);
-               return (NULL);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
+       }
+
+       if (count == 0)
+       {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
        }
 
+       b = extract_bootparams(&inxdr);
        xdr_destroy(&inxdr);
+       vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
 
-       convert_bootparamsent(lu_bpent);
-       xdr_free(xdr__lu_bootparams_ent_ptr, &lu_bpent);
-       return (&global_bp);
+       return b;
 }
 
 static void
 lu_bootparams_endent(void)
 {
-       bp_nentries = 0;
-       if (bp_data != NULL)
-       {
-               freeold();
-               vm_deallocate(mach_task_self(), (vm_address_t)bp_data, bp_datalen);
-               bp_data = NULL;
-       }
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_bootparams, free_lu_thread_info_bootparams);
+       _lu_data_free_vm_xdr(tdata);
 }
 
 static void
 lu_bootparams_setent(void)
 {
        lu_bootparams_endent();
-       bp_start = 1;
 }
 
 static struct bootparamsent *
 lu_bootparams_getent(void)
 {
+       struct bootparamsent *b;
        static int proc = -1;
-       _lu_bootparams_ent lu_bpent;
+       struct lu_thread_info *tdata;
 
-       if (bp_start == 1)
+       tdata = _lu_data_create_key(_lu_data_key_bootparams, free_lu_thread_info_bootparams);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_bootparams, tdata);
+       }
+\r
+       if (tdata->lu_vm == NULL)
        {
-               bp_start = 0;
-
                if (proc < 0)
                {
-                       if (_lookup_link(_lu_port, "bootparams_getent", &proc)
-                               != KERN_SUCCESS)
+                       if (_lookup_link(_lu_port, "bootparams_getent", &proc) != KERN_SUCCESS)
                        {
                                lu_bootparams_endent();
-                               return (NULL);
+                               return NULL;
                        }
                }
 
-               if (_lookup_all(_lu_port, proc, NULL, 0, &bp_data, &bp_datalen)
-                       != KERN_SUCCESS)
+               if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS)
                {
                        lu_bootparams_endent();
-                       return (NULL);
+                       return NULL;
                }
 
-#ifdef NOTDEF
-/* NOTDEF because OOL buffers are counted in bytes with untyped IPC */
-               bp_datalen *= BYTES_PER_XDR_UNIT;
-#endif
-               xdrmem_create(&bp_xdr, bp_data, bp_datalen,
-                       XDR_DECODE);
-               if (!xdr_int(&bp_xdr, &bp_nentries))
+               /* mig stubs measure size in words (4 bytes) */
+               tdata->lu_vm_length *= 4;
+
+               if (tdata->lu_xdr != NULL)
+               {
+                       xdr_destroy(tdata->lu_xdr);
+                       free(tdata->lu_xdr);
+               }
+               tdata->lu_xdr = (XDR *)calloc(1, sizeof(XDR));
+
+               xdrmem_create(tdata->lu_xdr, tdata->lu_vm, tdata->lu_vm_length, XDR_DECODE);
+               if (!xdr_int(tdata->lu_xdr, &tdata->lu_vm_cursor))
                {
-                       xdr_destroy(&bp_xdr);
                        lu_bootparams_endent();
-                       return (NULL);
+                       return NULL;
                }
        }
 
-       if (bp_nentries == 0)
+       if (tdata->lu_vm_cursor == 0)
        {
-               xdr_destroy(&bp_xdr);
                lu_bootparams_endent();
-               return (NULL);
+               return NULL;
        }
 
-       bzero(&lu_bpent, sizeof(lu_bpent));
-       if (!xdr__lu_bootparams_ent(&bp_xdr, &lu_bpent))
+       b = extract_bootparams(tdata->lu_xdr);
+       if (b == NULL)
        {
-               xdr_destroy(&bp_xdr);
                lu_bootparams_endent();
-               return (NULL);
+               return NULL;
        }
 
-       bp_nentries--;
-       convert_bootparamsent(&lu_bpent);
-       xdr_free(xdr__lu_bootparams_ent, &lu_bpent);
-       return (&global_bp);
+       tdata->lu_vm_cursor--;
+
+       return b;       
 }
 
 struct bootparamsent *
 bootparams_getbyname(const char *name)
 {
-       if (_lu_running()) return (lu_bootparams_getbyname(name));
-       return (NULL);
+       struct bootparamsent *res;
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_bootparams, free_lu_thread_info_bootparams);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_bootparams, tdata);
+       }
+
+       if (_lu_running())
+       {
+               res = lu_bootparams_getbyname(name);
+               recycle_bootparams(tdata, res);
+               return (struct bootparamsent *)tdata->lu_entry;
+       }
+
+       return NULL;
 }
 
 struct bootparamsent *
 bootparams_getent(void)
 {
-       if (_lu_running()) return (lu_bootparams_getent());
-       return (NULL);
+       struct bootparamsent *res;
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_bootparams, free_lu_thread_info_bootparams);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_bootparams, tdata);
+       }
+
+       if (_lu_running())
+       {
+               res = lu_bootparams_getent();
+               recycle_bootparams(tdata, res);
+               return (struct bootparamsent *)tdata->lu_entry;
+       }
+
+       return NULL;
 }
 
 void
index b206a8a0f1ff225b2c12481f43cccf21aabfdc05..be1d53220295b6cbdb9a2eaf246034d57e66ac6c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <rpc/types.h>
 #include <rpc/xdr.h>
 #include <fstab.h>
+#include <pthread.h>
 
 #include "lookup.h"
 #include "_lu_types.h"
 #include "lu_utils.h"
 #include "lu_overrides.h"
 
-static struct fstab global_fs;
-static int global_free = 1;
-static char *fs_data = NULL;
-static unsigned fs_datalen = 0;
-static int fs_nentries = 0;
-static int fs_start = 1;
-static XDR fs_xdr = { 0 };
+static pthread_mutex_t _fstab_lock = PTHREAD_MUTEX_INITIALIZER;
+
+#define FS_GET_SPEC 1
+#define FS_GET_FILE 2
+#define FS_GET_ENT 3
 
 static void
-freeold(void)
+free_fstab_data(struct fstab *f)
 {
-       if (global_free == 1) return;
+       if (f == NULL) return;
 
-       free(global_fs.fs_spec);
-       free(global_fs.fs_file);
-       free(global_fs.fs_type);
-       free(global_fs.fs_vfstype);
-       free(global_fs.fs_mntops);
+       if (f->fs_spec != NULL) free(f->fs_spec);
+       if (f->fs_file != NULL) free(f->fs_file);
+       if (f->fs_vfstype != NULL) free(f->fs_vfstype);
+       if (f->fs_mntops != NULL) free(f->fs_mntops);
+       if (f->fs_type != NULL) free(f->fs_type);
+}
 
-       global_free = 1;
+static void
+free_fstab(struct fstab *f)
+{
+       if (f == NULL) return;
+       free_fstab_data(f);
+       free(f);
 }
 
 static void
-convert_fs(_lu_fsent *lu_fs)
+free_lu_thread_info_fstab(void *x)
+{
+       struct lu_thread_info *tdata;
+
+       if (x == NULL) return;
+
+       tdata = (struct lu_thread_info *)x;
+       
+       if (tdata->lu_entry != NULL)
+       {
+               free_fstab((struct fstab *)tdata->lu_entry);
+               tdata->lu_entry = NULL;
+       }
+
+       _lu_data_free_vm_xdr(tdata);
+
+       free(tdata);
+}
+
+static struct fstab *
+extract_fstab(XDR *xdr)
 {
-       freeold();
+       int i, j, nkeys, nvals, status;
+       char *key, **vals;
+       struct fstab *f;
+
+       if (xdr == NULL) return NULL;
+
+       if (!xdr_int(xdr, &nkeys)) return NULL;
 
-       global_fs.fs_spec = strdup(lu_fs->fs_spec);
-       global_fs.fs_file = strdup(lu_fs->fs_file);
+       f = (struct fstab *)calloc(1, sizeof(struct fstab));
 
-       /*
-        * Special case - if vfstype is unknown and spec is
-        * of the form foo:bar, then assume nfs.
-        */
-       if (lu_fs->fs_vfstype[0] == '\0')
+       for (i = 0; i < nkeys; i++)
        {
-               if (strchr(lu_fs->fs_spec, ':') != NULL)
+               key = NULL;
+               vals = NULL;
+               nvals = 0;
+
+               status = _lu_xdr_attribute(xdr, &key, &vals, &nvals);
+               if (status < 0)
+               {
+                       free_fstab(f);
+                       return NULL;
+               }
+
+               if (nvals == 0)
+               {
+                       free(key);
+                       continue;
+               }
+
+               j = 0;
+
+               if ((f->fs_spec == NULL) && (!strcmp("name", key)))
+               {
+                       f->fs_spec = vals[0];
+                       j = 1;
+               }
+               else if ((f->fs_file == NULL) && (!strcmp("dir", key)))
+               {
+                       f->fs_file = vals[0];
+                       j = 1;
+               }
+               else if ((f->fs_vfstype == NULL) && (!strcmp("vfstype", key)))
+               {
+                       f->fs_vfstype = vals[0];
+                       j = 1;
+               }
+               else if ((f->fs_mntops == NULL) && (!strcmp("opts", key)))
+               {
+                       f->fs_mntops = vals[0];
+                       j = 1;
+               }
+               else if ((f->fs_type == NULL) && (!strcmp("type", key)))
                {
-                       global_fs.fs_vfstype = malloc(4);
-                       strcpy(global_fs.fs_vfstype, "nfs");
+                       f->fs_type = vals[0];
+                       j = 1;
+               }
+               else if (!strcmp("freq", key))
+               {
+                       f->fs_freq = atoi(vals[0]);
+               }
+               else if (!strcmp("passno", key))
+               {
+                       f->fs_passno = atoi(vals[0]);
+               }
+
+               free(key);
+               if (vals != NULL)
+               {
+                       for (; j < nvals; j++) free(vals[j]);
+                       free(vals);
                }
-               else global_fs.fs_vfstype = strdup(lu_fs->fs_vfstype);
        }
-       else
+
+       if (f->fs_spec == NULL) f->fs_spec = strdup("");
+       if (f->fs_file == NULL) f->fs_file = strdup("");
+       if (f->fs_vfstype == NULL) f->fs_vfstype = strdup("");
+       if (f->fs_mntops == NULL) f->fs_mntops = strdup("");
+       if (f->fs_type == NULL) f->fs_type = strdup("");
+
+       return f;
+}
+
+static struct fstab *
+copy_fstab(struct fstab *in)
+{
+       struct fstab *f;
+
+       if (in == NULL) return NULL;
+
+       f = (struct fstab *)calloc(1, sizeof(struct fstab));
+
+       f->fs_spec = LU_COPY_STRING(in->fs_spec);
+       f->fs_file = LU_COPY_STRING(in->fs_file);
+       f->fs_vfstype = LU_COPY_STRING(in->fs_vfstype);
+       f->fs_mntops = LU_COPY_STRING(in->fs_mntops);
+       f->fs_type = LU_COPY_STRING(in->fs_type);
+
+       f->fs_freq = in->fs_freq;
+       f->fs_passno = in->fs_passno;
+
+       return f;
+}
+
+static void
+recycle_fstab(struct lu_thread_info *tdata, struct fstab *in)
+{
+       struct fstab *f;
+
+       if (tdata == NULL) return;
+       f = (struct fstab *)tdata->lu_entry;
+
+       if (in == NULL)
+       {
+               free_fstab(f);
+               tdata->lu_entry = NULL;
+       }
+
+       if (tdata->lu_entry == NULL)
        {
-               global_fs.fs_vfstype = strdup(lu_fs->fs_vfstype);
+               tdata->lu_entry = in;
+               return;
        }
 
-       global_fs.fs_mntops = strdup(lu_fs->fs_mntops);
-       global_fs.fs_type = strdup(lu_fs->fs_type);
-       global_fs.fs_freq = lu_fs->fs_freq;
-       global_fs.fs_passno = lu_fs->fs_passno;
+       free_fstab_data(f);
 
-       global_free = 0;
+       f->fs_spec = in->fs_spec;
+       f->fs_file = in->fs_file;
+       f->fs_vfstype = in->fs_vfstype;
+       f->fs_mntops = in->fs_mntops;
+       f->fs_type = in->fs_type;
+       f->fs_freq = in->fs_freq;
+       f->fs_passno = in->fs_passno;
+
+       free(in);
 }
 
 static struct fstab *
-lu_getfsbyname(const char *name)
+lu_getfsspec(const char *name)
 {
+       struct fstab *f;
        unsigned datalen;
        char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT];
        XDR outxdr;
        XDR inxdr;
-       _lu_fsent_ptr lu_fs;
        static int proc = -1;
-       unit lookup_buf[MAX_INLINE_UNITS];
+       char *lookup_buf;
+       int count;
 
        if (proc < 0)
        {
                if (_lookup_link(_lu_port, "getfsbyname", &proc) != KERN_SUCCESS)
                {
-                       return (NULL);
+                       return NULL;
                }
        }
 
        xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE);
-       if (!xdr__lu_string(&outxdr, &name))
+       if (!xdr__lu_string(&outxdr, (_lu_string *)&name))
        {
                xdr_destroy(&outxdr);
-               return (NULL);
+               return NULL;
        }
 
-       datalen = MAX_INLINE_UNITS;
-       if (_lookup_one(_lu_port, proc, (unit *)namebuf,
-               xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, lookup_buf, &datalen)
+       datalen = 0;
+       lookup_buf = NULL;
+
+       if (_lookup_all(_lu_port, proc, (unit *)namebuf, xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, &lookup_buf, &datalen)
                != KERN_SUCCESS)
        {
                xdr_destroy(&outxdr);
-               return (NULL);
+               return NULL;
        }
 
        xdr_destroy(&outxdr);
 
        datalen *= BYTES_PER_XDR_UNIT;
-       xdrmem_create(&inxdr, lookup_buf, datalen,
-               XDR_DECODE);
-       lu_fs = NULL;
-       if (!xdr__lu_fsent_ptr(&inxdr, &lu_fs) || (lu_fs == NULL))
+       if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
+
+       xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
+
+       count = 0;
+       if (!xdr_int(&inxdr, &count))
+       {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
+       }
+
+       if (count == 0)
        {
                xdr_destroy(&inxdr);
-               return (NULL);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
        }
 
+       f = extract_fstab(&inxdr);
        xdr_destroy(&inxdr);
+       vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
 
-       convert_fs(lu_fs);
-       xdr_free(xdr__lu_fsent_ptr, &lu_fs);
-       return (&global_fs);
+       return f;
 }
 
 static void
 lu_endfsent(void)
 {
-       fs_nentries = 0;
-       if (fs_data != NULL)
-       {
-               freeold();
-               vm_deallocate(mach_task_self(), (vm_address_t)fs_data, fs_datalen);
-               fs_data = NULL;
-       }
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_fstab, free_lu_thread_info_fstab);
+       _lu_data_free_vm_xdr(tdata);\r
 }
 
 static int
 lu_setfsent(void)
 {
        lu_endfsent();
-       fs_start = 1;
-       return (1);
+       return 1;
 }
 
 static struct fstab *
 lu_getfsent()
 {
        static int proc = -1;
-       _lu_fsent lu_fs;
+       struct lu_thread_info *tdata;
+       struct fstab *f;
 
-       if (fs_start == 1)
+       tdata = _lu_data_create_key(_lu_data_key_fstab, free_lu_thread_info_fstab);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_fstab, tdata);
+       }
+\r
+       if (tdata->lu_vm == NULL)
        {
-               fs_start = 0;
-
                if (proc < 0)
                {
-                       if (_lookup_link(_lu_port, "getfsent", &proc) !=
-                               KERN_SUCCESS)
+                       if (_lookup_link(_lu_port, "getfsent", &proc) != KERN_SUCCESS)
                        {
                                lu_endfsent();
-                               return (NULL);
+                               return NULL;
                        }
                }
 
-               if (_lookup_all(_lu_port, proc, NULL, 0, &fs_data, &fs_datalen)
-                       != KERN_SUCCESS)
+               if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS)
                {
                        lu_endfsent();
-                       return (NULL);
+                       return NULL;
+               }
+
+               /* mig stubs measure size in words (4 bytes) */
+               tdata->lu_vm_length *= 4;
+
+               if (tdata->lu_xdr != NULL)
+               {
+                       xdr_destroy(tdata->lu_xdr);
+                       free(tdata->lu_xdr);
                }
+               tdata->lu_xdr = (XDR *)calloc(1, sizeof(XDR));
 
-#ifdef NOTDEF
-/* NOTDEF because OOL buffers are counted in bytes with untyped IPC */
-               fs_datalen *= BYTES_PER_XDR_UNIT;
-#endif
-               xdrmem_create(&fs_xdr, fs_data,
-                       fs_datalen, XDR_DECODE);
-               if (!xdr_int(&fs_xdr, &fs_nentries))
+               xdrmem_create(tdata->lu_xdr, tdata->lu_vm, tdata->lu_vm_length, XDR_DECODE);
+               if (!xdr_int(tdata->lu_xdr, &tdata->lu_vm_cursor))
                {
-                       xdr_destroy(&fs_xdr);
                        lu_endfsent();
-                       return (NULL);
+                       return NULL;
                }
        }
 
-       if (fs_nentries == 0)
+       if (tdata->lu_vm_cursor == 0)
        {
-               xdr_destroy(&fs_xdr);
                lu_endfsent();
-               return (NULL);
+               return NULL;
        }
 
-       bzero(&lu_fs, sizeof(lu_fs));
-       if (!xdr__lu_fsent(&fs_xdr, &lu_fs))
+       f = extract_fstab(tdata->lu_xdr);
+       if (f == NULL)
        {
-               xdr_destroy(&fs_xdr);
                lu_endfsent();
-               return (NULL);
+               return NULL;
        }
 
-       fs_nentries--;
-       convert_fs(&lu_fs);
-       xdr_free(xdr__lu_fsent, &lu_fs);
-       return (&global_fs);
+       tdata->lu_vm_cursor--;
+       
+       return f;
 }
 
-struct fstab *
-lu_getfsspec(const char *name)
-{
-       if (name == NULL) return (struct fstab *)NULL;
-       return lu_getfsbyname(name);
-}
-
-struct fstab *
+static struct fstab *
 lu_getfsfile(const char *name)
 {
        struct fstab *fs;
@@ -253,18 +389,81 @@ lu_getfsfile(const char *name)
        return (struct fstab *)NULL;
 }
 
+static struct fstab *
+getfs(const char *spec, const char *file, int source)
+{
+       struct fstab *res = NULL;
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_fstab, free_lu_thread_info_fstab);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_fstab, tdata);
+       }
+
+       if (_lu_running())
+       {
+               switch (source)
+               {
+                       case FS_GET_SPEC:
+                               res = lu_getfsspec(spec);
+                               break;
+                       case FS_GET_FILE:
+                               res = lu_getfsfile(file);
+                               break;
+                       case FS_GET_ENT:
+                               res = lu_getfsent();
+                               break;
+                       default: res = NULL;
+               }
+       }
+       else
+       {
+               pthread_mutex_lock(&_fstab_lock);
+               switch (source)
+               {
+                       case FS_GET_SPEC:
+                               res = copy_fstab(_old_getfsspec(spec));
+                               break;
+                       case FS_GET_FILE:
+                               res = copy_fstab(_old_getfsfile(file));
+                               break;
+                       case FS_GET_ENT:
+                               res = copy_fstab(_old_getfsent());
+                               break;
+                       default: res = NULL;
+               }
+               pthread_mutex_unlock(&_fstab_lock);
+       }
+
+       recycle_fstab(tdata, res);
+       return (struct fstab *)tdata->lu_entry;
+}
+
+
 struct fstab *
 getfsbyname(const char *name)
 {
-       if (_lu_running()) return (lu_getfsbyname(name));
-       return (NULL);
+       return getfs(name, NULL, FS_GET_SPEC);
+}
+
+struct fstab *
+getfsspec(const char *name)
+{
+       return getfs(name, NULL, FS_GET_SPEC);
+}
+
+struct fstab *
+getfsfile(const char *name)
+{
+       return getfs(NULL, name, FS_GET_FILE);
 }
 
 struct fstab *
 getfsent(void)
 {
-       if (_lu_running()) return (lu_getfsent());
-       return (_old_getfsent());
+       return getfs(NULL, NULL, FS_GET_ENT);
 }
 
 int
@@ -281,16 +480,3 @@ endfsent(void)
        else _old_endfsent();
 }
 
-struct fstab *
-getfsspec(const char *name)
-{
-       if (_lu_running()) return (lu_getfsspec(name));
-       return (_old_getfsspec(name));
-}
-
-struct fstab *
-getfsfile(const char *name)
-{
-       if (_lu_running()) return (lu_getfsfile(name));
-       return (_old_getfsfile(name));
-}
index 2ec8e031d3c3ec6070b46887ebceaddc23b126ee..3a8233befc1a9f3afbe450963ce9b40a5cb39805 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <netinet/in.h>
 #include <sys/param.h>
 #include <unistd.h>
+#include <pthread.h>
 
 #include "_lu_types.h"
 #include "lookup.h"
 #include "lu_utils.h"
 #include "lu_overrides.h"
 
-#define GROUP_SENTINEL -99
+static pthread_mutex_t _group_lock = PTHREAD_MUTEX_INITIALIZER;
 
-static lookup_state gr_state = LOOKUP_CACHE;
-static struct group global_gr;
-static int global_free = 1;
-static char *gr_data;
-static unsigned gr_datalen = 0;
-static int gr_nentries = 0;
-static int gr_start = 1;
-static XDR gr_xdr;
+#define GR_GET_NAME 1
+#define GR_GET_GID 2
+#define GR_GET_ENT 3
 
 static void 
-freeold(void)
+free_group_data(struct group *g)
 {
        char **mem;
 
-       if (global_free == 1) return;
+       if (g == NULL) return;
 
-       free(global_gr.gr_name);
-       global_gr.gr_name = NULL;
+       if (g->gr_name != NULL) free(g->gr_name);
+       if (g->gr_passwd != NULL) free(g->gr_passwd);
 
-       free(global_gr.gr_passwd);
-       global_gr.gr_passwd = NULL;
-
-       mem = global_gr.gr_mem;
+       mem = g->gr_mem;
        if (mem != NULL)
        {
                while (*mem != NULL) free(*mem++);
-               free(global_gr.gr_mem);
-               global_gr.gr_mem = NULL;
+               free(g->gr_mem);
        }
-       global_free = 1;
 }
 
+static void 
+free_group(struct group *g)
+{
+       if (g == NULL) return;
+       free_group_data(g);
+       free(g);
+ }
+
 static void
-convert_gr(_lu_group *lu_gr)
+free_lu_thread_info_group(void *x)
+{
+       struct lu_thread_info *tdata;
+
+       if (x == NULL) return;
+
+       tdata = (struct lu_thread_info *)x;
+       
+       if (tdata->lu_entry != NULL)
+       {
+               free_group((struct group *)tdata->lu_entry);
+               tdata->lu_entry = NULL;
+       }
+
+       _lu_data_free_vm_xdr(tdata);
+
+       free(tdata);
+}
+
+static struct group *
+extract_group(XDR *xdr)
 {
+       int i, j, nkeys, nvals, status;
+       char *key, **vals;
+       struct group *g;
+
+       if (xdr == NULL) return NULL;
+
+       if (!xdr_int(xdr, &nkeys)) return NULL;
+
+       g = (struct group *)calloc(1, sizeof(struct group));
+       g->gr_gid = -2;
+
+       for (i = 0; i < nkeys; i++)
+       {
+               key = NULL;
+               vals = NULL;
+               nvals = 0;
+
+               status = _lu_xdr_attribute(xdr, &key, &vals, &nvals);
+               if (status < 0)
+               {
+                       free_group(g);
+                       return NULL;
+               }
+
+               if (nvals == 0)
+               {
+                       free(key);
+                       continue;
+               }
+
+               j = 0;
+
+               if ((g->gr_name == NULL) && (!strcmp("name", key)))
+               {
+                       g->gr_name = vals[0];
+                       j = 1;
+               }
+               else if ((g->gr_passwd == NULL) && (!strcmp("passwd", key)))
+               {
+                       g->gr_passwd = vals[0];
+                       j = 1;
+               }
+               else if ((g->gr_gid == -2) && (!strcmp("gid", key)))
+               {
+                       g->gr_gid = atoi(vals[0]);
+               }
+               else if ((g->gr_mem == NULL) && (!strcmp("users", key)))
+               {
+                       g->gr_mem = vals;
+                       j = nvals;
+                       vals = NULL;
+               }
+
+               free(key);
+               if (vals != NULL)
+               {
+                       for (; j < nvals; j++) free(vals[j]);
+                       free(vals);
+               }
+       }
+
+       if (g->gr_name == NULL) g->gr_name = strdup("");
+       if (g->gr_passwd == NULL) g->gr_passwd = strdup("");
+       if (g->gr_mem == NULL) g->gr_mem = (char **)calloc(1, sizeof(char *));
+
+       return g;
+}
+
+static struct group *
+copy_group(struct group *in)
+{
+       struct group *g;
        int i, len;
 
-       freeold();
+       if (in == NULL) return NULL;
+
+       g = (struct group *)calloc(1, sizeof(struct group));
 
-       global_gr.gr_name = strdup(lu_gr->gr_name);
-       global_gr.gr_passwd = strdup(lu_gr->gr_passwd);
-       global_gr.gr_gid = lu_gr->gr_gid;
+       g->gr_name = LU_COPY_STRING(in->gr_name);
+       g->gr_passwd = LU_COPY_STRING(in->gr_passwd);
+       g->gr_gid = in->gr_gid;
 
-       len = lu_gr->gr_mem.gr_mem_len;
-       global_gr.gr_mem = (char **)malloc((len + 1) * sizeof(char *));
+       len = 0;
+       if (in->gr_mem != NULL)
+       {
+               for (len = 0; in->gr_mem[len] != NULL; len++);
+       }
 
+       g->gr_mem = (char **)calloc(len + 1, sizeof(char *));
        for (i = 0; i < len; i++)
        {
-               global_gr.gr_mem[i] = strdup(lu_gr->gr_mem.gr_mem_val[i]);
+               g->gr_mem[i] = strdup(in->gr_mem[i]);
+       }
+
+       return g;
+}
+
+static int
+copy_group_r(struct group *in, struct group *out, char *buffer, int buflen)
+{
+       int i, len, hsize;
+       unsigned long addr;
+       char *bp, *ap;
+
+       if (in == NULL) return -1;
+       if (out == NULL) return -1;
+
+       if (buffer == NULL) buflen = 0;
+
+       /* Calculate size of input */
+       hsize = 0;
+       if (in->gr_name != NULL) hsize += strlen(in->gr_name);
+       if (in->gr_passwd != NULL) hsize += strlen(in->gr_passwd);
+
+       /* NULL pointer at end of list */
+       hsize += sizeof(char *);
+
+       len = 0;
+       if (in->gr_mem != NULL)
+       {
+               for (len = 0; in->gr_mem[len] != NULL; len++)
+               {
+                       hsize += sizeof(char *);
+                       hsize += strlen(in->gr_mem[len]);
+               }
+       }
+
+       /* Check buffer space */
+       if (hsize > buflen) return -1;
+
+       /* Copy result into caller's struct group, using buffer for memory */
+       bp = buffer;
+
+       out->gr_name = NULL;
+       if (in->gr_name != NULL)
+       {
+               out->gr_name = bp;
+               hsize = strlen(in->gr_name) + 1;
+               memmove(bp, in->gr_name, hsize);
+               bp += hsize;
+       }
+
+       out->gr_passwd = NULL;
+       if (in->gr_passwd != NULL)
+       {
+               out->gr_passwd = bp;
+               hsize = strlen(in->gr_passwd) + 1;
+               memmove(bp, in->gr_passwd, hsize);
+               bp += hsize;
        }
 
-       global_gr.gr_mem[len] = NULL;
+       out->gr_gid = in->gr_gid;
 
-       global_free = 0;
+       out->gr_mem = NULL;
+       ap = bp + ((len + 1) * sizeof(char *));
+
+       if (in->gr_mem != NULL)
+       {
+               out->gr_mem = (char **)bp;
+               for (i = 0; i < len; i++)
+               {
+                       addr = (unsigned long)ap;
+                       memmove(bp, &addr, sizeof(unsigned long));
+                       bp += sizeof(unsigned long);
+
+                       hsize = strlen(in->gr_mem[i]) + 1;
+                       memmove(ap, in->gr_mem[i], hsize);
+                       ap += hsize;
+               }
+       }
+       
+       memset(bp, 0, sizeof(unsigned long));
+       bp = ap;
+
+       return 0;
+}
+
+static void
+recycle_group(struct lu_thread_info *tdata, struct group *in)
+{
+       struct group *g;
+
+       if (tdata == NULL) return;
+       g = (struct group *)tdata->lu_entry;
+
+       if (in == NULL)
+       {
+               free_group(g);
+               tdata->lu_entry = NULL;
+       }
+
+       if (tdata->lu_entry == NULL)
+       {
+               tdata->lu_entry = in;
+               return;
+       }
+
+       free_group_data(g);
+
+       g->gr_name = in->gr_name;
+       g->gr_passwd = in->gr_passwd;
+       g->gr_gid = in->gr_gid;
+       g->gr_mem = in->gr_mem;
+
+       free(in);
 }
 
 static struct group *
 lu_getgrgid(int gid)
 {
-       unsigned datalen;
-       _lu_group_ptr lu_gr;
-       XDR xdr;
+       struct group *g;
+       unsigned int datalen;
+       XDR inxdr;
        static int proc = -1;
-       unit lookup_buf[MAX_INLINE_UNITS];
+       int count;
+       char *lookup_buf;
        
        if (proc < 0)
        {
                if (_lookup_link(_lu_port, "getgrgid", &proc) != KERN_SUCCESS)
                {
-                       return (NULL);
+                       return NULL;
                }
        }
 
        gid = htonl(gid);
-       datalen = MAX_INLINE_UNITS;
+       datalen = 0;
+       lookup_buf = NULL;
 
-       if (_lookup_one(_lu_port, proc, (unit *)&gid, 1, lookup_buf, &datalen)
-               != KERN_SUCCESS)
+       if (_lookup_all(_lu_port, proc, (unit *)&gid, 1, &lookup_buf, &datalen) != KERN_SUCCESS)
        {
-               return (NULL);
+               return NULL;
        }
 
        datalen *= BYTES_PER_XDR_UNIT;
-       xdrmem_create(&xdr, lookup_buf, datalen, XDR_DECODE);
-       lu_gr = NULL;
+       if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
+
+       xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
+
+       count = 0;
+       if (!xdr_int(&inxdr, &count))
+       {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
+       }
 
-       if (!xdr__lu_group_ptr(&xdr, &lu_gr) || lu_gr == NULL)
+       if (count == 0)
        {
-               xdr_destroy(&xdr);
-               return (NULL);
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
        }
 
-       xdr_destroy(&xdr);
+       g = extract_group(&inxdr);
+       xdr_destroy(&inxdr);
+       vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
 
-       convert_gr(lu_gr);
-       xdr_free(xdr__lu_group_ptr, &lu_gr);
-       return (&global_gr);
+       return g;
 }
 
 static struct group *
 lu_getgrnam(const char *name)
 {
-       unsigned datalen;
+       struct group *g;
+       unsigned int datalen;
        char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT];
        XDR outxdr;
        XDR inxdr;
-       _lu_group_ptr lu_gr;
        static int proc = -1;
-       unit lookup_buf[MAX_INLINE_UNITS];
+       int count;
+       char *lookup_buf;
 
        if (proc < 0)
        {
                if (_lookup_link(_lu_port, "getgrnam", &proc) != KERN_SUCCESS)
                {
-                       return (NULL);
+                       return NULL;
                }
        }
 
        xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE);
 
-       if (!xdr__lu_string(&outxdr, &name))
+       if (!xdr__lu_string(&outxdr, (_lu_string *)&name))
        {
                xdr_destroy(&outxdr);
-               return (NULL);
+               return NULL;
        }
 
-       datalen = MAX_INLINE_UNITS;
+       datalen = 0;
+       lookup_buf = NULL;
 
-       if (_lookup_one(_lu_port, proc, (unit *)namebuf,
-               xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, lookup_buf, &datalen)
-               != KERN_SUCCESS)
+       if (_lookup_all(_lu_port, proc, (unit *)namebuf, xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, &lookup_buf, &datalen) != KERN_SUCCESS)
        {
-               return (NULL);
+               return NULL;
        }
 
        xdr_destroy(&outxdr);
 
        datalen *= BYTES_PER_XDR_UNIT;
-       xdrmem_create(&inxdr, lookup_buf, datalen,
-               XDR_DECODE);
-       lu_gr = NULL;
+       if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
+
+       xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
 
-       if (!xdr__lu_group_ptr(&inxdr, &lu_gr) || (lu_gr == NULL))
+       count = 0;
+       if (!xdr_int(&inxdr, &count))
        {
                xdr_destroy(&inxdr);
-               return (NULL);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
        }
 
+       if (count == 0)
+       {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
+       }
+
+       g = extract_group(&inxdr);
        xdr_destroy(&inxdr);
+       vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
 
-       convert_gr(lu_gr);
-       xdr_free(xdr__lu_group_ptr, &lu_gr);
-       return (&global_gr);
+       return g;
 }
 
-
 static int
 lu_initgroups(const char *name, int basegid)
 {
-       unsigned datalen;
+       unsigned int datalen;
        XDR outxdr;
        XDR inxdr;
        static int proc = -1;
-       unit lookup_buf[MAX_INLINE_UNITS];
+       char *lookup_buf;
        char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT];
        int groups[NGROUPS];
-       int ngroups = 1;
+       int ngroups;
        int a_group;
-       int count;
+       int i, j, count;
 
        groups[0] = basegid;
        
@@ -227,15 +450,17 @@ lu_initgroups(const char *name, int basegid)
        }
 
        xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE);
-       if (!xdr__lu_string(&outxdr, &name))
+       if (!xdr__lu_string(&outxdr, (_lu_string *)&name))
        {
                xdr_destroy(&outxdr);
                return -1;
        }
 
-       datalen = MAX_INLINE_UNITS;
-       if (_lookup_one(_lu_port, proc, (unit *)namebuf,
-               xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, lookup_buf, &datalen)
+       datalen = 0;
+       lookup_buf = NULL;
+
+       if (_lookup_all(_lu_port, proc, (unit *)namebuf,
+               xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, &lookup_buf, &datalen)
                != KERN_SUCCESS)
        {
                xdr_destroy(&outxdr);
@@ -245,116 +470,206 @@ lu_initgroups(const char *name, int basegid)
        xdr_destroy(&outxdr);
 
        datalen *= BYTES_PER_XDR_UNIT;
-       xdrmem_create(&inxdr, lookup_buf, datalen,
-               XDR_DECODE);
+       if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
+
+       xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
 
-       while (xdr_int(&inxdr, &a_group))
+       if (!xdr_int(&inxdr, &count))
        {
-               if (a_group == GROUP_SENTINEL) break;
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return -1;
+       }
+
+       if (count > NGROUPS) count = NGROUPS;
 
-               for (count = 0; count < ngroups; count++)
+       ngroups = 0;
+
+       for (i = 0; i < count; i++)
+       {
+               if (!xdr_int(&inxdr, &a_group)) break;
+
+               for (j = 0; j < ngroups; j++)
                {
-                       if (groups[count] == a_group) break;
+                       if (groups[j] == a_group) break;
                }
-
-               if (count >= ngroups) groups[ngroups++] = a_group;
+               if (j >= ngroups) groups[ngroups++] = a_group;
+               
        }
        xdr_destroy(&inxdr);
-       
+       vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+
        return setgroups(ngroups, groups);
 }
 
 static void
 lu_endgrent(void)
 {
-       gr_nentries = 0;
-       if (gr_data != NULL)
-       {
-               freeold();
-               vm_deallocate(mach_task_self(), (vm_address_t)gr_data, gr_datalen);
-               gr_data = NULL;
-       }
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_group, free_lu_thread_info_group);
+       _lu_data_free_vm_xdr(tdata);
 }
 
 static int
 lu_setgrent(void)
 {
        lu_endgrent();
-       gr_start = 1;
-       return (1);
+       return 1;
 }
 
 static struct group *
 lu_getgrent()
 {
+       struct group *g;
        static int proc = -1;
-       _lu_group lu_gr;
+       struct lu_thread_info *tdata;
 
-       if (gr_start == 1)
+       tdata = _lu_data_create_key(_lu_data_key_group, free_lu_thread_info_group);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_group, tdata);
+       }
+\r
+       if (tdata->lu_vm == NULL)
        {
-               gr_start = 0;
-
                if (proc < 0)
                {
                        if (_lookup_link(_lu_port, "getgrent", &proc) != KERN_SUCCESS)
                        {
                                lu_endgrent();
-                               return (NULL);
+                               return NULL;
                        }
                }
 
-               if (_lookup_all(_lu_port, proc, NULL, 0, &gr_data, &gr_datalen)
-                       != KERN_SUCCESS)
+               if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS)
                {
                        lu_endgrent();
-                       return (NULL);
+                       return NULL;
                }
 
-#ifdef NOTDEF
-/* NOTDEF because OOL buffers are counted in bytes with untyped IPC */
-               gr_datalen *= BYTES_PER_XDR_UNIT;
-#endif
-               xdrmem_create(&gr_xdr, gr_data, gr_datalen,
-                       XDR_DECODE);
-               if (!xdr_int(&gr_xdr, &gr_nentries))
+               /* mig stubs measure size in words (4 bytes) */
+               tdata->lu_vm_length *= 4;
+
+               if (tdata->lu_xdr != NULL)
+               {
+                       xdr_destroy(tdata->lu_xdr);
+                       free(tdata->lu_xdr);
+               }
+               tdata->lu_xdr = (XDR *)calloc(1, sizeof(XDR));
+
+               xdrmem_create(tdata->lu_xdr, tdata->lu_vm, tdata->lu_vm_length, XDR_DECODE);
+               if (!xdr_int(tdata->lu_xdr, &tdata->lu_vm_cursor))
                {
-                       xdr_destroy(&gr_xdr);
                        lu_endgrent();
-                       return (NULL);
+                       return NULL;
                }
        }
 
-       if (gr_nentries == 0)
+       if (tdata->lu_vm_cursor == 0)
        {
-               xdr_destroy(&gr_xdr);
                lu_endgrent();
-               return (NULL);
+               return NULL;
        }
 
-       bzero(&lu_gr, sizeof(lu_gr));
-       if (!xdr__lu_group(&gr_xdr, &lu_gr))
+       g = extract_group(tdata->lu_xdr);
+       if (g == NULL)
        {
-               xdr_destroy(&gr_xdr);
                lu_endgrent();
-               return (NULL);
+               return NULL;
        }
 
-       gr_nentries--;
-       convert_gr(&lu_gr);
-       xdr_free(xdr__lu_group, &lu_gr);
-       return (&global_gr);
+       tdata->lu_vm_cursor--;
+       
+       return g;
 }
 
-struct group *
-getgrgid(gid_t gid)
+static struct group *
+getgr_internal(const char *name, gid_t gid, int source)
+{
+       struct group *res = NULL;
+
+       if (_lu_running())
+       {
+               switch (source)
+               {
+                       case GR_GET_NAME:
+                               res = lu_getgrnam(name);
+                               break;
+                       case GR_GET_GID:
+                               res = lu_getgrgid(gid);
+                               break;
+                       case GR_GET_ENT:
+                               res = lu_getgrent();
+                               break;
+                       default: res = NULL;
+               }
+       }
+       else
+       {
+               pthread_mutex_lock(&_group_lock);
+               switch (source)
+               {
+                       case GR_GET_NAME:
+                               res = copy_group(_old_getgrnam(name));
+                               break;
+                       case GR_GET_GID:
+                               res = copy_group(_old_getgrgid(gid));
+                               break;
+                       case GR_GET_ENT:
+                               res = copy_group(_old_getgrent());
+                               break;
+                       default: res = NULL;
+               }
+               pthread_mutex_unlock(&_group_lock);
+       }
+
+       return res;
+}
+
+static struct group *
+getgr(const char *name, gid_t gid, int source)
 {
-       LOOKUP1(lu_getgrgid, _old_getgrgid, gid, struct group);
+       struct group *res = NULL;
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_group, free_lu_thread_info_group);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_group, tdata);
+       }
+
+       res = getgr_internal(name, gid, source);
+
+       recycle_group(tdata, res);
+       return (struct group *)tdata->lu_entry;
 }
 
-struct group *
-getgrnam(const char *name)
+static int
+getgr_r(const char *name, gid_t gid, int source, struct group *grp, char *buffer, size_t bufsize, struct group **result)
 {
-       LOOKUP1(lu_getgrnam, _old_getgrnam, name, struct group);
+       struct group *res = NULL;
+       int status;
+
+       *result = NULL;
+       errno = 0;
+
+       res = getgr_internal(name, gid, source);
+       if (res == NULL) return -1;
+
+       status = copy_group_r(res, grp, buffer, bufsize);
+       free_group(res);
+
+       if (status != 0)
+       {
+               errno = ERANGE;
+               return -1;
+       }
+
+       *result = grp;
+       return 0;
 }
 
 int
@@ -379,20 +694,47 @@ initgroups(const char *name, int basegid)
        return (res);
 }
 
+struct group *
+getgrnam(const char *name)
+{
+       return getgr(name, -2, GR_GET_NAME);
+}
+
+struct group *
+getgrgid(gid_t gid)
+{
+       return getgr(NULL, gid, GR_GET_GID);
+}
+
 struct group *
 getgrent(void)
 {
-       GETENT(lu_getgrent, _old_getgrent, &gr_state, struct group);
+       return getgr(NULL, -2, GR_GET_ENT);
 }
 
 int
 setgrent(void)
 {
-       INTSETSTATEVOID(lu_setgrent, _old_setgrent, &gr_state);
+       if (_lu_running()) lu_setgrent();
+       else _old_setgrent();
+       return 1;
 }
 
 void
 endgrent(void)
 {
-       UNSETSTATE(lu_endgrent, _old_endgrent, &gr_state);
+       if (_lu_running()) lu_endgrent();
+       else _old_endgrent();
+}
+
+int
+getgrnam_r(const char *name, struct group *grp, char *buffer, size_t bufsize, struct group **result)
+{
+       return getgr_r(name, -2, GR_GET_NAME, grp, buffer, bufsize, result);
+}
+
+int
+getgrgid_r(gid_t gid, struct group *grp, char *buffer, size_t bufsize, struct group **result)
+{
+       return getgr_r(NULL, gid, GR_GET_GID, grp, buffer, bufsize, result);
 }
index ca56659ed86c8ee5d1a32312e3d4c0d775f678b2..d34da5b1b82d3a633a1cab7c63625662074c8a63 100644 (file)
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
-/*
- * host lookup
- * Copyright (C) 1989 by NeXT, Inc.
- */
+
 #include <stdlib.h>
 #include <mach/mach.h>
 #include <stdio.h>
 #include <string.h>
-#include "lookup.h"
 #include <rpc/types.h>
 #include <rpc/xdr.h>
-#include "_lu_types.h"
 #include <netdb.h>
-#include "lu_utils.h"
 #include <sys/socket.h>
-#import <netinet/in.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <pthread.h>
+#include <ifaddrs.h>
+
+#include "_lu_types.h"
+#include "lookup.h"
+#include "lu_host.h"
+#include "lu_utils.h"
+
+static pthread_mutex_t _host_lock = PTHREAD_MUTEX_INITIALIZER;
 
 extern struct hostent *_res_gethostbyaddr();
 extern struct hostent *_res_gethostbyname();
@@ -47,332 +52,1059 @@ extern void _old_sethostent();
 extern void _old_endhostent();
 extern void _old_sethostfile();
 
+extern mach_port_t _lu_port;
+extern int _lu_running(void);
+
 extern int h_errno;
 
-static lookup_state h_state = LOOKUP_CACHE;
-/*
- * The static return value from get*ent functions
- */
-static struct hostent global_h;
-static int global_free = 1;
-static char *h_data = NULL;
-static unsigned h_datalen;
-static int h_nentries;
-static int h_start = 1;
-static XDR h_xdr;
+#define IPV6_ADDR_LEN 16
+#define IPV4_ADDR_LEN 4
 
-static void
-freeold(void)
+__private_extern__ void
+free_host_data(struct hostent *h)
 {
        char **aliases;
        int i;
 
-       if (global_free == 1) return;
+       if (h == NULL) return;
 
-       free(global_h.h_name);
-       aliases = global_h.h_aliases;
+       if (h->h_name != NULL) free(h->h_name);
+
+       aliases = h->h_aliases;
        if (aliases != NULL)
        {
                while (*aliases != NULL) free(*aliases++);
-               free(global_h.h_aliases);
+               free(h->h_aliases);
        }
 
-       for (i = 0; global_h.h_addr_list[i] != NULL; i++)
-               free(global_h.h_addr_list[i]);
-
-       free(global_h.h_addr_list);
+       if (h->h_addr_list != NULL)
+       {
+               for (i = 0; h->h_addr_list[i] != NULL; i++) free(h->h_addr_list[i]);
+               free(h->h_addr_list);
+       }
+}
 
-       global_free = 1;
+void
+freehostent(struct hostent *h)
+{
+       if (h == NULL) return;
+       free_host_data(h);
+       free(h);
 }
 
 static void
-convert_h(_lu_hostent *lu_h)
+free_lu_thread_info_host(void *x)
+{
+       struct lu_thread_info *tdata;
+
+       if (x == NULL) return;
+
+       tdata = (struct lu_thread_info *)x;
+       
+       if (tdata->lu_entry != NULL)
+       {
+               freehostent((struct hostent *)tdata->lu_entry);
+               tdata->lu_entry = NULL;
+       }
+
+       _lu_data_free_vm_xdr(tdata);
+
+       free(tdata);
+}
+
+__private_extern__ struct hostent *
+extract_host(XDR *xdr, int want, int *err)
+{
+       struct hostent *h;
+       int i, j, nvals, nkeys, status, addr_len;
+       int family, addr_count, map_count;
+       struct in_addr addr;
+       struct in6_addr addr6;
+       char *key, **vals, **mapvals;
+
+       mapvals = NULL;
+       map_count = 0;
+       addr_count = 0;
+       addr_len = sizeof(u_long *);
+
+       if (xdr == NULL)
+       {
+               *err = NO_RECOVERY;
+               return NULL;
+       }
+
+       if (!xdr_int(xdr, &nkeys))
+       {
+               *err = NO_RECOVERY;
+               return NULL;
+       }
+
+       h = (struct hostent *)calloc(1, sizeof(struct hostent));
+
+       family = AF_INET;
+       h->h_length = IPV4_ADDR_LEN;
+
+       if (want > WANT_A4_ONLY)
+       {
+               family = AF_INET6;
+               h->h_length = IPV6_ADDR_LEN;
+       }
+
+       h->h_addrtype = family; 
+
+       for (i = 0; i < nkeys; i++)
+       {
+               key = NULL;
+               vals = NULL;
+               nvals = 0;
+
+               status = _lu_xdr_attribute(xdr, &key, &vals, &nvals);
+               if (status < 0)
+               {
+                       freehostent(h);
+                       *err = NO_RECOVERY;
+                       return NULL;
+               }
+
+               if (nvals == 0)
+               {
+                       free(key);
+                       continue;
+               }
+
+               j = 0;
+
+               if ((h->h_name == NULL) && (!strcmp("name", key)))
+               {
+                       h->h_name = vals[0];
+                       if (nvals > 1)
+                       {
+                               h->h_aliases = (char **)calloc(nvals, sizeof(char *));
+                               for (j = 1; j < nvals; j++) h->h_aliases[j-1] = vals[j];
+                       }
+                       j = nvals;
+               }
+               else if ((family == AF_INET) && (h->h_addr_list == NULL) && (!strcmp("ip_address", key)))
+               {
+                       addr_count = nvals;
+                       h->h_addr_list = (char **)calloc(nvals + 1, addr_len);
+
+                       for (j = 0; j < nvals; j++)
+                       {
+                               addr.s_addr = 0;
+                               inet_aton(vals[j], &addr);
+                               h->h_addr_list[j] = (char *)calloc(1, IPV4_ADDR_LEN);
+                               memmove(h->h_addr_list[j], &(addr.s_addr), IPV4_ADDR_LEN);
+                       }
+
+                       h->h_addr_list[nvals] = NULL;
+                       j = 0;
+               }
+               else if ((family == AF_INET6) && (h->h_addr_list == NULL) && (!strcmp("ipv6_address", key)))
+               {
+                       addr_count = nvals;
+                       h->h_addr_list = (char **)calloc(nvals + 1, addr_len);
+
+                       for (j = 0; j < nvals; j++)
+                       {
+                               memset(&addr6, 0, sizeof(struct in6_addr));
+                               inet_pton(family, vals[j], &addr6);
+                               h->h_addr_list[j] = (char *)calloc(1, IPV6_ADDR_LEN);
+                               memmove(h->h_addr_list[j], &(addr6.__u6_addr.__u6_addr32[0]), IPV6_ADDR_LEN);
+                       }
+
+                       h->h_addr_list[nvals] = NULL;
+                       j = 0;
+               }
+               else if ((family == AF_INET6) && (mapvals == NULL) && (!strcmp("ip_address", key)))
+               {
+                       map_count = nvals;
+                       mapvals = vals;
+                       vals = NULL;
+               }
+
+               free(key);
+               if (vals != NULL)
+               {
+                       for (; j < nvals; j++) free(vals[j]);
+                       free(vals);
+               }
+       }
+
+       if ((mapvals != NULL) && (want > WANT_A6_ONLY))
+       {
+               addr6.__u6_addr.__u6_addr32[0] = 0x00000000;
+               addr6.__u6_addr.__u6_addr32[1] = 0x00000000;
+               addr6.__u6_addr.__u6_addr32[2] = htonl(0x0000ffff);
+
+               if (addr_count == 0)
+               {
+                       h->h_addr_list = (char **)calloc(map_count + 1, addr_len);
+               }
+               else
+               {
+                       h->h_addr_list = (char **)realloc(h->h_addr_list, (addr_count + map_count + 1) * addr_len);
+               }
+
+               for (i = 0; i < map_count; i++)
+               {
+                       addr.s_addr = 0;
+                       inet_aton(mapvals[i], &addr);
+                       h->h_addr_list[addr_count] = (char *)calloc(1, IPV6_ADDR_LEN);
+                       memmove(&(addr6.__u6_addr.__u6_addr32[3]), &(addr.s_addr), IPV4_ADDR_LEN);
+                       memcpy(h->h_addr_list[addr_count++], &(addr6.__u6_addr.__u6_addr32[0]), IPV6_ADDR_LEN);
+               }
+
+               h->h_addr_list[addr_count] = NULL;
+       }
+
+       if (mapvals != NULL)
+       {
+               for (i = 0; i < map_count; i++) free(mapvals[i]);
+               free(mapvals);
+       }
+
+       if (h->h_name == NULL) h->h_name = strdup("");
+       if (h->h_aliases == NULL) h->h_aliases = (char **)calloc(1, sizeof(char *));
+       if (h->h_addr_list == NULL) h->h_addr_list = (char **)calloc(1, sizeof(char *));
+
+       return h;
+}
+
+static struct hostent *
+copy_host(struct hostent *in)
 {
        int i, len, addr_len;
+       struct hostent *h;
+
+       if (in == NULL) return NULL;
 
-       freeold();
+       h = (struct hostent *)calloc(1, sizeof(struct hostent));
 
-       global_h.h_name = strdup(lu_h->h_names.h_names_val[0]);
+       h->h_name = LU_COPY_STRING(in->h_name);
 
-       len = lu_h->h_names.h_names_len - 1;
-       global_h.h_aliases = (char **)malloc((len + 1) * sizeof(char *));
+       len = 0;
+       if (in->h_aliases != NULL)
+       {
+               for (len = 0; in->h_aliases[len] != NULL; len++);
+       }
 
+       h->h_aliases = (char **)calloc(len + 1, sizeof(char *));
        for (i = 0; i < len; i++)
        {
-               global_h.h_aliases[i] = strdup(lu_h->h_names.h_names_val[i + 1]);
+               h->h_aliases[i] = strdup(in->h_aliases[i]);
        }
 
-       global_h.h_aliases[len] = NULL;
+       h->h_addrtype = in->h_addrtype;
+       h->h_length = in->h_length;
 
-       global_h.h_addrtype = AF_INET;
-       global_h.h_length = sizeof(long);
+       len = 0;
+       if (in->h_addr_list != NULL)
+       {
+               for (len = 0; in->h_addr_list[len] != NULL; len++);
+       }
 
-       len = lu_h->h_addrs.h_addrs_len;
        addr_len = sizeof(u_long *);
+       h->h_addr_list = (char **)calloc(len + 1, addr_len);
+       for (i = 0; i < len; i++)
+       {
+               h->h_addr_list[i] = (char *)malloc(h->h_length);
+               memmove(h->h_addr_list[i], in->h_addr_list[i], h->h_length);
+       }
 
-       global_h.h_addr_list = (char **)malloc((len + 1) * addr_len);
+       return h;
+}
 
-       for (i = 0; i < len; i++)
+static void
+recycle_host(struct lu_thread_info *tdata, struct hostent *in)
+{
+       struct hostent *h;
+
+       if (tdata == NULL) return;
+       h = (struct hostent *)tdata->lu_entry;
+
+       if (in == NULL)
+       {
+               freehostent(h);
+               tdata->lu_entry = NULL;
+       }
+
+       if (tdata->lu_entry == NULL)
        {
-               global_h.h_addr_list[i] = (char *)malloc(sizeof(long));
-               bcopy((const void *)&(lu_h->h_addrs.h_addrs_val[i]),
-                       (void *)global_h.h_addr_list[i], sizeof(long));
+               tdata->lu_entry = in;
+               return;
        }
 
-       global_h.h_addr_list[len] = NULL;
+       free_host_data(h);
+
+       h->h_name = in->h_name;
+       h->h_aliases = in->h_aliases;
+       h->h_addrtype = in->h_addrtype;
+       h->h_length = in->h_length;
+       h->h_addr_list = in->h_addr_list;
+
+       free(in);
+}
+
+__private_extern__ struct hostent *
+fake_hostent(const char *name, struct in_addr addr)
+{
+       int addr_len;
+       struct hostent *h;
+
+       if (name == NULL) return NULL;
+
+       h = (struct hostent *)calloc(1, sizeof(struct hostent));
+
+       h->h_name = strdup(name);
+
+       h->h_aliases = (char **)calloc(1, sizeof(char *));
+
+       h->h_addrtype = AF_INET;
+       h->h_length = sizeof(long);
+
+       addr_len = sizeof(u_long *);
+       h->h_addr_list = (char **)calloc(2, addr_len);
+
+       h->h_addr_list[0] = (char *)malloc(h->h_length);
+       memmove(h->h_addr_list[0], &(addr.s_addr), h->h_length);
+
+       return h;
+}
+
+__private_extern__ struct hostent *
+fake_hostent6(const char *name, struct in6_addr addr)
+{
+       int addr_len;
+       struct hostent *h;
+
+       if (name == NULL) return NULL;
+
+       h = (struct hostent *)calloc(1, sizeof(struct hostent));
+
+       h->h_name = strdup(name);
+
+       h->h_aliases = (char **)calloc(1, sizeof(char *));
+
+       h->h_addrtype = AF_INET6;
+       h->h_length = 16;
 
-       global_free = 0;
+       addr_len = sizeof(u_long *);
+       h->h_addr_list = (char **)calloc(2, addr_len);
+
+       h->h_addr_list[0] = (char *)malloc(h->h_length);
+       memmove(h->h_addr_list[0], &(addr.__u6_addr.__u6_addr32[0]), h->h_length);
+
+       return h;
 }
 
 static struct hostent *
-lu_gethostbyaddr(const char *addr, int len, int type)
+lu_gethostbyaddr(const char *addr, int want, int *err)
 {
-       unsigned datalen;
-       _lu_hostent_ptr lu_h;
-       XDR xdr;
-       long address;
-       static int proc = -1;
-       unit lookup_buf[MAX_INLINE_UNITS];
-       
-       if (len != sizeof(long) || (type != AF_INET)) 
+       struct hostent *h;
+       unsigned int datalen;
+       XDR inxdr;
+       static int proc4 = -1;
+       static int proc6 = -1;
+       char *lookup_buf, *address;
+       int proc, count, len, family;
+       struct in_addr addr4;
+       struct in6_addr addr6;
+
+       family = AF_INET;
+       len = IPV4_ADDR_LEN;
+       if (want > WANT_A4_ONLY)
        {
-               h_errno = HOST_NOT_FOUND;
-               return (NULL);
+               family = AF_INET6;
+               len = IPV6_ADDR_LEN;
        }
 
-       if (proc < 0)
+       if ((family == AF_INET) && (proc4 < 0))
+       {
+               if (_lookup_link(_lu_port, "gethostbyaddr", &proc4) != KERN_SUCCESS)
+               {
+                       *err = NO_RECOVERY;
+                       return NULL;
+               }
+       }
+       else if ((family == AF_INET6) && (proc6 < 0))
        {
-               if (_lookup_link(_lu_port, "gethostbyaddr", &proc) != KERN_SUCCESS)
+               if (_lookup_link(_lu_port, "getipv6nodebyaddr", &proc6) != KERN_SUCCESS)
                {
-                       h_errno = HOST_NOT_FOUND;
-                       return (NULL);
+                       *err = NO_RECOVERY;
+                       return NULL;
                }
        }
 
-       bcopy(addr, &address, sizeof(address));
-       address = htonl(address);
-       datalen = MAX_INLINE_UNITS;
-       if (_lookup_one(_lu_port, proc, (unit *)&address, 1, lookup_buf, &datalen)
-               != KERN_SUCCESS)
+       address = NULL;
+
+       if (family == AF_INET)
        {
-               h_errno = HOST_NOT_FOUND;
-               return (NULL);
+               memmove(&(addr4.s_addr), addr, IPV4_ADDR_LEN);
+               addr4.s_addr = htonl(addr4.s_addr);
+               address = (char *)&(addr4.s_addr);
+               proc = proc4;
+       }
+       else
+       {
+               memmove(&(addr6.__u6_addr.__u6_addr32[0]), addr, IPV6_ADDR_LEN);
+               addr6.__u6_addr.__u6_addr32[0] = htonl(addr6.__u6_addr.__u6_addr32[0]);
+               addr6.__u6_addr.__u6_addr32[1] = htonl(addr6.__u6_addr.__u6_addr32[1]);
+               addr6.__u6_addr.__u6_addr32[2] = htonl(addr6.__u6_addr.__u6_addr32[2]);
+               addr6.__u6_addr.__u6_addr32[3] = htonl(addr6.__u6_addr.__u6_addr32[3]);
+               address = (char *)&(addr6.__u6_addr.__u6_addr32[0]);
+               proc = proc6;
+       }
+               
+       datalen = 0;
+       lookup_buf = NULL;
+
+       if (_lookup_all(_lu_port, proc, (unit *)address, len / BYTES_PER_XDR_UNIT, &lookup_buf, &datalen) != KERN_SUCCESS)
+       {
+               *err = NO_RECOVERY;
+               return NULL;
        }
 
        datalen *= BYTES_PER_XDR_UNIT;
-       xdrmem_create(&xdr, lookup_buf, datalen, XDR_DECODE);
-       lu_h = NULL;
-       h_errno = HOST_NOT_FOUND;
-       if (!xdr__lu_hostent_ptr(&xdr, &lu_h) || 
-           !xdr_int(&xdr, &h_errno) || (lu_h == NULL))
+       if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
+
+       xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
+
+       count = 0;
+       if (!xdr_int(&inxdr, &count))
+       {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               *err = NO_RECOVERY;
+               return NULL;
+       }
+
+       if (count == 0)
        {
-               xdr_destroy(&xdr);
-               return (NULL);
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               *err = HOST_NOT_FOUND;
+               return NULL;
        }
 
-       xdr_destroy(&xdr);
+       *err = 0;
+
+       h = extract_host(&inxdr, want, err);
+       xdr_destroy(&inxdr);
+       vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
 
-       convert_h(lu_h);
-       xdr_free(xdr__lu_hostent_ptr, &lu_h);
-       return (&global_h);
+       return h;
 }
 
 static struct hostent *
-lu_gethostbyname(const char *name)
+lu_gethostbyname(const char *name, int want, int *err)
 {
-       unsigned datalen;
+       struct hostent *h;
+       unsigned int datalen;
        char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT];
        XDR outxdr;
        XDR inxdr;
-       _lu_hostent_ptr lu_h;
-       static int proc = -1;
-       unit lookup_buf[MAX_INLINE_UNITS];
+       static int proc4 = -1;
+       static int proc6 = -1;
+       char *lookup_buf;
+       int proc, count, family;
+
+       family = AF_INET;
+       if (want > WANT_A4_ONLY) family = AF_INET6;
 
-       if (proc < 0)
+       if (((want == WANT_MAPPED_A4_ONLY) || (family == AF_INET)) && (proc4 < 0))
        {
-               if (_lookup_link(_lu_port, "gethostbyname", &proc) != KERN_SUCCESS)
+               if (_lookup_link(_lu_port, "gethostbyname", &proc4) != KERN_SUCCESS)
                {
-                       h_errno = HOST_NOT_FOUND;
-                       return (NULL);
+                       *err = NO_RECOVERY;
+                       return NULL;
                }
        }
+       else if ((family == AF_INET6) && (proc6 < 0))
+       {
+               if (_lookup_link(_lu_port, "getipv6nodebyname", &proc6) != KERN_SUCCESS)
+               {
+                       *err = NO_RECOVERY;
+                       return NULL;
+               }
+       }
+
+       proc = proc4;
+       if ((family == AF_INET6) && (want != WANT_MAPPED_A4_ONLY)) proc = proc6;
 
        xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE);
-       if (!xdr__lu_string(&outxdr, &name))
+       if (!xdr__lu_string(&outxdr, (_lu_string *)&name))
        {
                xdr_destroy(&outxdr);
-               h_errno = HOST_NOT_FOUND;
-               return (NULL);
+               *err = NO_RECOVERY;
+               return NULL;
        }
 
-       datalen = MAX_INLINE_UNITS;
-       if (_lookup_one(_lu_port, proc, (unit *)namebuf,
-               xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, lookup_buf, &datalen)
-               != KERN_SUCCESS)
+       datalen = 0;
+       lookup_buf = NULL;
+
+       if (_lookup_all(_lu_port, proc, (unit *)namebuf, xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, &lookup_buf, &datalen) != KERN_SUCCESS)
        {
                xdr_destroy(&outxdr);
-               h_errno = HOST_NOT_FOUND;
-               return (NULL);
+               *err = NO_RECOVERY;
+               return NULL;
        }
 
        xdr_destroy(&outxdr);
 
        datalen *= BYTES_PER_XDR_UNIT;
-       xdrmem_create(&inxdr, lookup_buf, datalen,
-               XDR_DECODE);
-       lu_h = NULL;
-       h_errno = HOST_NOT_FOUND;
-       if (!xdr__lu_hostent_ptr(&inxdr, &lu_h) || 
-           !xdr_int(&inxdr, &h_errno) || (lu_h == NULL))
+       if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
+
+       xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
+
+       count = 0;
+       if (!xdr_int(&inxdr, &count))
+       {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               *err = NO_RECOVERY;
+               return NULL;
+       }
+
+       if (count == 0)
        {
                xdr_destroy(&inxdr);
-               return (NULL);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               *err = HOST_NOT_FOUND;
+               return NULL;
        }
 
+       *err = 0;
+
+       h = extract_host(&inxdr, want, err);
        xdr_destroy(&inxdr);
+       vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
 
-       convert_h(lu_h);
-       xdr_free(xdr__lu_hostent_ptr, &lu_h);
-       return (&global_h);
+       return h;
 }
 
 static void
 lu_endhostent()
 {
-       h_nentries = 0;
-       if (h_data != NULL)
-       {
-               freeold();
-               vm_deallocate(mach_task_self(), (vm_address_t)h_data, h_datalen);
-               h_data = NULL;
-       }
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_host, free_lu_thread_info_host);
+       _lu_data_free_vm_xdr(tdata);\r
 }
 
 static void
 lu_sethostent()
 {
        lu_endhostent();
-       h_start = 1;
 }
 
 static struct hostent *
-lu_gethostent()
+lu_gethostent(int want, int *err)
 {
        static int proc = -1;
-       _lu_hostent lu_h;
+       struct lu_thread_info *tdata;
+       struct hostent *h;
 
-       if (h_start == 1)
+       tdata = _lu_data_create_key(_lu_data_key_host, free_lu_thread_info_host);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_host, tdata);
+       }
+\r
+       if (tdata->lu_vm == NULL)
        {
-               h_start = 0;
-
                if (proc < 0)
                {
                        if (_lookup_link(_lu_port, "gethostent", &proc) != KERN_SUCCESS)
                        {
                                lu_endhostent();
-                               return (NULL);
+                               *err = NO_RECOVERY;
+                               return NULL;
                        }
                }
 
-               if (_lookup_all(_lu_port, proc, NULL, 0, &h_data, &h_datalen)
-                       != KERN_SUCCESS)
+               if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS)
                {
                        lu_endhostent();
-                       return (NULL);
+                       *err = NO_RECOVERY;
+                       return NULL;
+               }
+
+               /* mig stubs measure size in words (4 bytes) */
+               tdata->lu_vm_length *= 4;
+
+               if (tdata->lu_xdr != NULL)
+               {
+                       xdr_destroy(tdata->lu_xdr);
+                       free(tdata->lu_xdr);
                }
+               tdata->lu_xdr = (XDR *)calloc(1, sizeof(XDR));
 
-#ifdef NOTDEF
-/* NOTDEF because OOL buffers are counted in bytes with untyped IPC */
-               h_datalen *= BYTES_PER_XDR_UNIT;
-#endif
-               xdrmem_create(&h_xdr, h_data, h_datalen,
-                       XDR_DECODE);
-               if (!xdr_int(&h_xdr, &h_nentries))
+               xdrmem_create(tdata->lu_xdr, tdata->lu_vm, tdata->lu_vm_length, XDR_DECODE);
+               if (!xdr_int(tdata->lu_xdr, &tdata->lu_vm_cursor))
                {
-                       xdr_destroy(&h_xdr);
                        lu_endhostent();
-                       return (NULL);
+                       *err = NO_RECOVERY;
+                       return NULL;
                }
        }
 
-       if (h_nentries == 0)
+       if (tdata->lu_vm_cursor == 0)
        {
-               xdr_destroy(&h_xdr);
                lu_endhostent();
-               return (NULL);
+               *err = HOST_NOT_FOUND;
+               return NULL;
        }
 
-       bzero(&lu_h, sizeof(lu_h));
-       if (!xdr__lu_hostent(&h_xdr, &lu_h))
+       h = extract_host(tdata->lu_xdr, want, err);
+       if (h == NULL)
        {
-               xdr_destroy(&h_xdr);
                lu_endhostent();
-               return (NULL);
+               *err = HOST_NOT_FOUND;
+               return NULL;
        }
 
-       h_nentries--;
-       convert_h(&lu_h);
-       xdr_free(xdr__lu_hostent, &lu_h);
-       return (&global_h);
+       *err = 0;
+       tdata->lu_vm_cursor--;
+       
+       return h;
 }
 
-struct hostent *
-gethostbyaddr(const char *addr, int len, int type)
+static struct hostent *
+gethostbyaddrerrno(const char *addr, int len, int type, int *err)
 {
-       struct hostent *res;
+       struct hostent *res = NULL;
+       int want;
+
+       *err = 0;
+
+       want = WANT_A4_ONLY;
+       if (type == AF_INET6) want = WANT_A6_ONLY;
 
        if (_lu_running())
        {
-           res = lu_gethostbyaddr(addr, len, type);
+               res = lu_gethostbyaddr(addr, want, err);
        }
        else
        {
-           res = _res_gethostbyaddr(addr, len, type);
-           if (res == NULL) res = _old_gethostbyaddr(addr, len, type);
+               pthread_mutex_lock(&_host_lock);
+               res = copy_host(_res_gethostbyaddr(addr, len, type));
+               if (res == NULL) res = copy_host(_old_gethostbyaddr(addr, len, type));
+               *err = h_errno;
+               pthread_mutex_unlock(&_host_lock);
        }
 
-       return (res);
+       return res;
 }
 
 struct hostent *
-gethostbyname(const char *name)
+gethostbyaddr(const char *addr, int len, int type)
 {
-    struct hostent *res;
+       struct hostent *res;
+       struct lu_thread_info *tdata;
+
+       res = gethostbyaddrerrno(addr, len, type, &h_errno);
+       if (res == NULL)
+       {
+               return NULL;
+       }
+
+       tdata = _lu_data_create_key(_lu_data_key_host, free_lu_thread_info_host);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_host, tdata);
+       }
+
+       recycle_host(tdata, res);
+       return (struct hostent *)tdata->lu_entry;
+}
+       
+struct hostent *
+gethostbynameerrno(const char *name, int *err)
+{
+       struct hostent *res = NULL;
        struct in_addr addr;
+       int i, is_addr;
 
-       if (_lu_running())
+       *err = 0;
+
+       /* 
+        * If name is all dots and digits without a trailing dot, 
+        * call inet_aton.  If it's OK, return a fake entry.
+        * Otherwise, return an error.
+        *
+        * If name has alpha or ends with a dot, proceed as usual...
+        */
+       if (name == NULL)
+       {
+               *err = HOST_NOT_FOUND;
+               return NULL;
+       }
+
+       if (name[0] == '\0')
+       {
+               *err = HOST_NOT_FOUND;
+               return NULL;
+       }
+
+       is_addr = 1;
+       for (i = 0; name[i] != '\0'; i++)
        {
-               res = lu_gethostbyname(name);
-    }
+               if (name[i] == '.') continue;
+               if ((name[i] >= '0') && (name[i] <= '9')) continue;
+               is_addr = 0;
+               break;
+       }
+
+       if ((is_addr == 1) && (name[i-1] == '.')) is_addr = 0;
+
+       if (is_addr == 1)
+       {
+               if (inet_aton(name, &addr) == 0)
+               {
+                       *err = HOST_NOT_FOUND;
+                       return NULL;
+               }
+               res = fake_hostent(name, addr);
+       }
+       else if (_lu_running())
+       {
+               res = lu_gethostbyname(name, WANT_A4_ONLY, err);
+       }
        else
        {
-               res = _res_gethostbyname(name);
-               if (res == NULL) res = _old_gethostbyname(name);
+               pthread_mutex_lock(&_host_lock);
+               res = copy_host(_res_gethostbyname(name));
+               if (res == NULL) res = copy_host(_old_gethostbyname(name));
+               *err = h_errno;
+               pthread_mutex_unlock(&_host_lock);
        }
 
        if (res == NULL)
        {
-               if (inet_aton(name, &addr) == 0) return NULL;
-               return gethostbyaddr((char *)&addr, sizeof(addr), AF_INET);
+               if (inet_aton(name, &addr) == 0)
+               {
+                       *err = HOST_NOT_FOUND;
+                       return NULL;
+               }
+
+               res = gethostbyaddrerrno((char *)&addr, sizeof(addr), AF_INET, err);
+               if (res == NULL) {
+                       res = fake_hostent(name, addr);
+               }
        }
 
-    return res;
+       return res;
+}
+
+struct hostent *
+gethostbyname(const char *name)
+{
+       struct hostent *res;
+       struct lu_thread_info *tdata;
+
+       res = gethostbynameerrno(name, &h_errno);
+       if (res == NULL)
+       {
+               return NULL;
+       }
+
+       tdata = _lu_data_create_key(_lu_data_key_host, free_lu_thread_info_host);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_host, tdata);
+       }
+
+       recycle_host(tdata, res);
+       return (struct hostent *)tdata->lu_entry;
 }
 
 struct hostent *
 gethostent(void)
 {
-       GETENT(lu_gethostent, _old_gethostent, &h_state, struct hostent);
+       struct hostent *res = NULL;
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_host, free_lu_thread_info_host);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_host, tdata);
+       }
+
+       if (_lu_running()) 
+       {
+               res = lu_gethostent(WANT_A4_ONLY, &h_errno);
+       }
+       else
+       {
+               pthread_mutex_lock(&_host_lock);
+               res = copy_host(_old_gethostent());
+               pthread_mutex_unlock(&_host_lock);
+       }
+
+       recycle_host(tdata, res);
+       return (struct hostent *)tdata->lu_entry;
 }
 
 void
 sethostent(int stayopen)
 {
-       SETSTATE(lu_sethostent, _old_sethostent, &h_state, stayopen);
+       if (_lu_running()) lu_sethostent();
+       else _old_sethostent(stayopen);
 }
 
 void
 endhostent(void)
 {
-       UNSETSTATE(lu_endhostent, _old_endhostent, &h_state);
+       if (_lu_running()) lu_endhostent();
+       else _old_endhostent();
+}
+
+__private_extern__ int
+is_a4_mapped(const char *s)
+{
+       int i;
+       u_int8_t c;
+
+       if (s == NULL) return 0;
+
+       for (i = 0; i < 10; i++)
+       {
+               c = s[i];
+               if (c != 0x0) return 0;
+       }
+
+       for (i = 10; i < 12; i++)
+       {
+               c = s[i];
+               if (c != 0xff) return 0;
+       }
+
+       return 1;
+}
+       
+__private_extern__ int
+is_a4_compat(const char *s)
+{
+       int i;
+       u_int8_t c;
+
+       if (s == NULL) return 0;
+
+       for (i = 0; i < 12; i++)
+       {
+               c = s[i];
+               if (c != 0x0) return 0;
+       }
+
+       /* Check for :: and ::1 */
+       for (i = 13; i < 15; i++)
+       {
+               /* anything non-zero in these 3 bytes means it's a V4 address */
+               c = s[i];
+               if (c != 0x0) return 1;
+       }
+
+       /* Leading 15 bytes are all zero */
+       c = s[15];
+       if (c == 0x0) return 0;
+       if (c == 0x1) return 0;
+
+       return 1;
+}
+
+struct hostent *
+getipnodebyaddr(const void *src, size_t len, int af, int *err)
+{
+       struct hostent *res;
+
+       *err = 0;
+
+       if ((af == AF_INET6) && (len == 16) && (is_a4_mapped((const char *)src) || is_a4_compat((const char *)src)))
+       {
+               src += 12;
+               len = 4;
+               af = AF_INET;
+       }
+
+       res = gethostbyaddrerrno((const char *)src, len, af, err);
+       if (res == NULL) {
+               return NULL;
+       }
+
+       if (res->h_name == NULL) {
+               freehostent(res);
+               return NULL;
+       }
+
+       return res;
+}
+
+struct hostent *
+getipnodebyname(const char *name, int af, int flags, int *err)
+{
+       int status, want, really_want, if4, if6;
+       struct hostent *res;
+       struct ifaddrs *ifa, *ifap;
+       struct in_addr addr4;
+       struct in6_addr addr6;
+
+       memset(&addr4, 0, sizeof(struct in_addr));
+       memset(&addr6, 0, sizeof(struct in6_addr));
+
+       *err = 0;
+
+       if (af == AF_INET)
+       {
+               status = inet_aton(name, &addr4);
+               if (status == 1)
+               {
+                       /* return a fake hostent */
+                       res = fake_hostent(name, addr4);
+                       return res;
+               }
+       }
+       else if (af == AF_INET6)
+       {
+               status = inet_pton(af, name, &addr6);
+               if (status == 1)
+               {
+                       /* return a fake hostent */
+                       res = fake_hostent6(name, addr6);
+                       return res;
+               }
+               status = inet_aton(name, &addr4);
+               if (status == 1)
+               {
+                       if (!(flags & (AI_V4MAPPED|AI_V4MAPPED_CFG)))
+                       {
+                               *err = HOST_NOT_FOUND;
+                               return NULL;
+                       }
+
+                       addr6.__u6_addr.__u6_addr32[0] = 0x00000000;
+                       addr6.__u6_addr.__u6_addr32[1] = 0x00000000;
+                       addr6.__u6_addr.__u6_addr32[2] = htonl(0x0000ffff);
+                       memmove(&(addr6.__u6_addr.__u6_addr32[3]), &(addr4.s_addr), IPV4_ADDR_LEN);
+
+                       /* return a fake hostent */
+                       res = fake_hostent6(name, addr6);
+                       return res;
+               }
+       }
+       else
+       {
+               *err = NO_RECOVERY;
+               return NULL;
+       }
+
+       /*
+        * IF AI_ADDRCONFIG is set, we need to know what interface flavors we really have.
+        */
+
+       if4 = 0;
+       if6 = 0;
+
+       if (flags & AI_ADDRCONFIG)
+       {
+               if (getifaddrs(&ifa) < 0)
+               {
+                       *err = NO_RECOVERY;
+                       return NULL;
+               }
+
+               for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next)
+               {
+                       if (ifap->ifa_addr == NULL) continue;
+                       if ((ifap->ifa_flags & IFF_UP) == 0) continue;
+                       if (ifap->ifa_addr->sa_family == AF_INET) if4++;
+                       else if (ifap->ifa_addr->sa_family == AF_INET6) if6++;
+               }
+
+               freeifaddrs(ifa);
+
+               /* Bail out if there are no interfaces */
+               if ((if4 == 0) && (if6 == 0))
+               {
+                       *err = NO_ADDRESS;
+                       return NULL;
+               }
+       }
+
+       /*
+        * Figure out what we want.
+        * If user asked for AF_INET, we only want V4 addresses.
+        */
+       want = WANT_A4_ONLY;
+       really_want = want;
+
+       if (af == AF_INET)
+       {
+               want = WANT_A4_ONLY;
+               if ((flags & AI_ADDRCONFIG) && (if4 == 0))
+               {
+                       *err = NO_ADDRESS;
+                       return NULL;
+               }
+       }
+       else
+       {
+               /* af == AF_INET6 */
+               want = WANT_A6_ONLY;
+               really_want = want;
+               if (flags & (AI_V4MAPPED|AI_V4MAPPED_CFG))
+               {
+                       if (flags & AI_ALL)
+                       {
+                               want = WANT_A6_PLUS_MAPPED_A4;
+                               really_want = want;
+                       }
+                       else
+                       {
+                               want = WANT_A6_ONLY;
+                               really_want = WANT_A6_OR_MAPPED_A4_IF_NO_A6;
+                       }
+               }
+               else
+               {
+                       if ((flags & AI_ADDRCONFIG) && (if6 == 0)) 
+                       {
+                               *err = NO_ADDRESS;
+                               return NULL;
+                       }
+               }
+       }
+
+       res = NULL;
+
+       if (_lu_running())
+       {
+               res = lu_gethostbyname(name, want, err);
+               if ((res == NULL) && 
+                   ((really_want == WANT_A6_OR_MAPPED_A4_IF_NO_A6) ||
+                    (really_want == WANT_A6_PLUS_MAPPED_A4       )))
+               {
+                       res = lu_gethostbyname(name, WANT_MAPPED_A4_ONLY, err);
+               }
+       }
+       else
+       {
+               pthread_mutex_lock(&_host_lock);
+               res = copy_host(_res_gethostbyname(name));
+               if (res == NULL) res = copy_host(_old_gethostbyname(name));
+               *err = h_errno;
+               pthread_mutex_unlock(&_host_lock);
+       }
+
+       if (res == NULL)
+       {
+               *err = HOST_NOT_FOUND;
+               return NULL;
+       }
+
+       return res;
 }
diff --git a/lookup.subproj/lu_host.h b/lookup.subproj/lu_host.h
new file mode 100644 (file)
index 0000000..130bc4d
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * Portions Copyright (c) 2002 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.1 (the "License").  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef _LU_HOST_H_
+#define _LU_HOST_H_
+
+#include <sys/cdefs.h>
+
+
+#define WANT_A4_ONLY 0
+#define WANT_A6_ONLY 1
+#define WANT_A6_PLUS_MAPPED_A4 2
+#define WANT_MAPPED_A4_ONLY 3
+
+/* ONLY TO BE USED BY getipv6nodebyaddr */
+#define WANT_A6_OR_MAPPED_A4_IF_NO_A6 -1
+
+
+__BEGIN_DECLS
+
+void free_host_data(struct hostent *h);
+struct hostent * extract_host(XDR *xdr, int want, int *err);
+struct hostent * fake_hostent(const char *name, struct in_addr addr);
+struct hostent * fake_hostent6(const char *name, struct in6_addr addr);
+int is_a4_mapped(const char *s);
+int is_a4_compat(const char *s);
+
+__END_DECLS
+
+#endif /* ! _LU_HOST_H_ */
diff --git a/lookup.subproj/lu_host_async.c b/lookup.subproj/lu_host_async.c
new file mode 100644 (file)
index 0000000..2874719
--- /dev/null
@@ -0,0 +1,1054 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * Portions Copyright (c) 2002 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.1 (the "License").  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <netdb.h>
+#include <netdb_async.h>       /* async gethostbyXXX function prototypes */
+#include <pthread.h>
+#include <stdlib.h>
+#include <mach/mach.h>
+#include <netinfo/_lu_types.h>
+#include <netinfo/lookup.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ifaddrs.h>
+#include <net/if.h>
+
+#include "lu_host.h"
+#include "lu_utils.h"
+
+extern mach_port_t _lu_port;
+extern int _lu_running(void);
+
+extern int h_errno;
+
+
+#define msgh_request_port       msgh_remote_port
+#define msgh_reply_port         msgh_local_port
+
+
+typedef union {
+       gethostbyaddr_async_callback    hostAddr;
+       gethostbyname_async_callback    hostName;
+       getipnodebyaddr_async_callback  nodeAddr;
+       getipnodebyname_async_callback  nodeName;
+} a_request_callout_t;
+
+typedef struct a_requests {
+       struct a_requests                       *next;
+       int                                     retry;
+       struct {
+               int                             proc;
+               ooline_data                     data;
+               unsigned int                    dataLen;
+               int                             want;
+       } request;
+       mach_port_t                             replyPort;
+       a_request_callout_t                     callout;
+       void                                    *context;
+       struct hostent                          *hent;          /* if reply known in XXX_start() */
+} a_requests_t;
+
+static a_requests_t            *a_requests     = NULL;
+static pthread_mutex_t         a_requests_lock = PTHREAD_MUTEX_INITIALIZER;
+
+#define MAX_LOOKUP_ATTEMPTS 10
+
+
+static kern_return_t
+_lookup_all_tx
+(
+       mach_port_t             server,
+       int                     proc,
+       ooline_data             indata,
+       mach_msg_type_number_t  indataCnt,
+       mach_port_t             *replyPort
+)
+{
+       typedef struct {
+               mach_msg_header_t       Head;
+               NDR_record_t            NDR;
+               int                     proc;
+               mach_msg_type_number_t  indataCnt;
+               unit                    indata[4096];
+       } Request;
+
+       Request                 In;
+       register Request        *InP = &In;
+       mach_msg_return_t       mr;
+       unsigned int            msgh_size;
+
+       if (indataCnt > 4096) {
+               return MIG_ARRAY_TOO_LARGE;
+       }
+
+       if (*replyPort == MACH_PORT_NULL) {
+               mr = mach_port_allocate(mach_task_self(),
+                                       MACH_PORT_RIGHT_RECEIVE,
+                                       replyPort);
+               if (mr != KERN_SUCCESS) {
+                       return mr;
+               }
+       }
+
+       msgh_size = (sizeof(Request) - 16384) + ((4 * indataCnt));
+       InP->Head.msgh_bits             = MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
+/*     InP->Head.msgh_size             = msgh_size;    /* msgh_size passed as argument */
+       InP->Head.msgh_request_port     = server;
+       InP->Head.msgh_reply_port       = *replyPort;
+       InP->Head.msgh_id               = 4241776;
+       InP->NDR                        = NDR_record;
+       InP->proc                       = proc;
+       InP->indataCnt                  = indataCnt;
+       (void)memcpy((char *)InP->indata, (const char *)indata, 4 * indataCnt);
+
+       mr = mach_msg(&InP->Head,               /* msg */
+                     MACH_SEND_MSG,            /* options */
+                     msgh_size,                /* send_size */
+                     0,                        /* rcv_size */
+                     MACH_PORT_NULL,           /* rcv_name */
+                     MACH_MSG_TIMEOUT_NONE,    /* timeout */
+                     MACH_PORT_NULL);          /* notify */
+       switch (mr) {
+               case MACH_MSG_SUCCESS :
+                       mr = KERN_SUCCESS;
+                       break;
+               case MACH_SEND_INVALID_REPLY :
+                       (void)mach_port_destroy(mach_task_self(), *replyPort);
+                       break;
+               default:
+                       break;
+       }
+
+       return mr;
+}
+
+
+static kern_return_t
+_lookup_all_rx
+(
+       void                    *msg,
+       ooline_data             *outdata,
+       mach_msg_type_number_t  *outdataCnt,
+       security_token_t        *token
+)
+{
+       typedef struct {
+               mach_msg_header_t               Head;
+               mach_msg_body_t                 msgh_body;
+               mach_msg_ool_descriptor_t       outdata;
+               NDR_record_t                    NDR;
+               mach_msg_type_number_t          outdataCnt;
+               mach_msg_format_0_trailer_t     trailer;
+       } Reply;
+
+       /*
+        * typedef struct {
+        *      mach_msg_header_t       Head;
+        *      NDR_record_t            NDR;
+        *      kern_return_t           RetCode;
+        * } mig_reply_error_t;
+        */
+
+       register Reply                  *OutP           = msg;
+       mach_msg_format_0_trailer_t     *TrailerP;
+       boolean_t                       msgh_simple;
+
+       if (OutP->Head.msgh_id != (4241776 + 100)) {
+           if (OutP->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)
+               return MIG_SERVER_DIED;
+           else
+               return MIG_REPLY_MISMATCH;
+       }
+
+       msgh_simple = !(OutP->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX);
+
+       TrailerP = (mach_msg_format_0_trailer_t *)((vm_offset_t)OutP +
+               round_msg(OutP->Head.msgh_size));
+       if (TrailerP->msgh_trailer_type != MACH_MSG_TRAILER_FORMAT_0)
+               return MIG_TRAILER_ERROR;
+
+       if (msgh_simple && ((mig_reply_error_t *)OutP)->RetCode != KERN_SUCCESS)
+               return ((mig_reply_error_t *)OutP)->RetCode;
+
+       *outdata    = (ooline_data)(OutP->outdata.address);
+       *outdataCnt = OutP->outdataCnt;
+
+       *token = TrailerP->msgh_sender;
+
+       return KERN_SUCCESS;
+}
+
+
+static a_requests_t *
+request_extract(mach_port_t port)
+{
+       a_requests_t    *request0, *request;
+
+       pthread_mutex_lock(&a_requests_lock);
+       request0 = NULL;
+       request  = a_requests;
+       while (request) {
+              if (port == request->replyPort) {
+                       /* request found, remove from list */
+                       if (request0) {
+                               request0->next = request->next;
+                       } else {
+                               a_requests = request->next;
+                       }
+                       break;
+               } else {
+                       /* not this request, skip to next */
+                       request0 = request;
+                       request  = request->next;
+               }
+       }
+       pthread_mutex_unlock(&a_requests_lock);
+
+       return request;
+}
+
+
+static void
+request_queue(a_requests_t *request)
+{
+       pthread_mutex_lock(&a_requests_lock);
+       request->next = a_requests;
+       a_requests = request;
+       pthread_mutex_unlock(&a_requests_lock);
+
+       return;
+}
+
+
+static boolean_t
+sendCannedReply(a_requests_t *request, int *error)
+{
+       /*
+        * typedef struct {
+        *      mach_msg_header_t       Head;
+        *      NDR_record_t            NDR;
+        *      kern_return_t           RetCode;
+        * } mig_reply_error_t;
+        */
+
+       mig_reply_error_t               Out;
+       register mig_reply_error_t      *OutP = &Out;
+
+       kern_return_t                   kr;
+       mach_msg_return_t               mr;
+       unsigned int                    msgh_size;
+
+       /*
+        * allocate reply port
+        */
+       kr = mach_port_allocate(mach_task_self(),
+                               MACH_PORT_RIGHT_RECEIVE,
+                               &request->replyPort);
+       if (kr != KERN_SUCCESS) {
+               *error = NO_RECOVERY;
+               return FALSE;
+       }
+
+       kr = mach_port_insert_right(mach_task_self(),
+                                   request->replyPort,
+                                   request->replyPort,
+                                   MACH_MSG_TYPE_MAKE_SEND);
+       if (kr != KERN_SUCCESS) {
+               (void) mach_port_destroy(mach_task_self(), request->replyPort);
+               *error = NO_RECOVERY;
+               return FALSE;
+       }
+
+       /*
+        * queue reply message
+        */
+       msgh_size = sizeof(Out);
+       OutP->Head.msgh_bits            = MACH_MSGH_BITS(19, 0);
+/*     OutP->Head.msgh_size            = msgh_size;    /* msgh_size passed as argument */
+       OutP->Head.msgh_request_port    = request->replyPort;
+       OutP->Head.msgh_reply_port      = MACH_PORT_NULL;
+       OutP->Head.msgh_id              = 4241776 + 100;
+       OutP->RetCode                   = MIG_REMOTE_ERROR;
+       OutP->NDR                       = NDR_record;
+
+       mr = mach_msg(&OutP->Head,              /* msg */
+                     MACH_SEND_MSG,            /* options */
+                     msgh_size,                /* send_size */
+                     0,                        /* rcv_size */
+                     MACH_PORT_NULL,           /* rcv_name */
+                     MACH_MSG_TIMEOUT_NONE,    /* timeout */
+                     MACH_PORT_NULL);          /* notify */
+       if (mr != MACH_MSG_SUCCESS) {
+               if (mr == MACH_SEND_INVALID_REPLY) {
+                       (void)mach_port_destroy(mach_task_self(), request->replyPort);
+               }
+               *error = NO_RECOVERY;
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+
+mach_port_t
+_gethostbyaddr_async_start(const char          *addr,
+                          int                  len,
+                          int                  type,
+                          a_request_callout_t  callout,
+                          void                 *context,
+                          int                  *error)
+{
+       void            *address;
+       int             proc;
+       a_requests_t    *request;
+       int             want;
+
+       switch (type) {
+           case AF_INET :
+               {
+                       static int      proc4   = -1;
+                       struct in_addr  *v4addr;
+
+                       if (proc4 < 0) {
+                               if (_lookup_link(_lu_port, "gethostbyaddr", &proc4) != KERN_SUCCESS) {
+                                       *error = NO_RECOVERY;
+                                       return MACH_PORT_NULL;
+                               }
+                       }
+
+                       if (len != sizeof(struct in_addr)) {
+                               *error = NO_RECOVERY;
+                               return NULL;
+                       }
+
+                       v4addr = malloc(len);
+                       memmove(v4addr, addr, len);
+                       v4addr->s_addr = htonl(v4addr->s_addr);
+
+                       address = (void *)v4addr;
+                       proc    = proc4;
+                       want    = WANT_A4_ONLY;
+                       break;
+               }
+
+           case AF_INET6 :
+               {
+                       static int      proc6   = -1;
+                       struct in6_addr *v6addr;
+
+                       if (proc6 < 0) {
+                               if (_lookup_link(_lu_port, "getipv6nodebyaddr", &proc6) != KERN_SUCCESS) {
+                                       *error = NO_RECOVERY;
+                                       return MACH_PORT_NULL;
+                               }
+                       }
+
+                       if (len != sizeof(struct in6_addr)) {
+                               *error = NO_RECOVERY;
+                               return NULL;
+                       }
+
+                       v6addr = malloc(len);
+                       memmove(v6addr, addr, len);
+                       v6addr->__u6_addr.__u6_addr32[0] = htonl(v6addr->__u6_addr.__u6_addr32[0]);
+                       v6addr->__u6_addr.__u6_addr32[1] = htonl(v6addr->__u6_addr.__u6_addr32[1]);
+                       v6addr->__u6_addr.__u6_addr32[2] = htonl(v6addr->__u6_addr.__u6_addr32[2]);
+                       v6addr->__u6_addr.__u6_addr32[3] = htonl(v6addr->__u6_addr.__u6_addr32[3]);
+
+                       address = (void *)v6addr;
+                       proc    = proc6;
+                       want    = WANT_A6_ONLY;
+                       break;
+               }
+
+           default:
+               *error = NO_RECOVERY;
+               return MACH_PORT_NULL;
+       }
+
+       request = malloc(sizeof(a_requests_t));
+       request->next            = NULL;
+       request->retry           = MAX_LOOKUP_ATTEMPTS;
+       request->request.proc    = proc;
+       request->request.data    = (ooline_data)address;
+       request->request.dataLen = len / BYTES_PER_XDR_UNIT;
+       request->request.want    = want;
+       request->replyPort       = MACH_PORT_NULL;
+       request->callout         = callout;
+       request->context         = context;
+       request->hent            = NULL;
+
+       /*
+        * allocate reply port, send query to lookupd
+        */
+       if (_lookup_all_tx(_lu_port,
+                          request->request.proc,
+                          request->request.data,
+                          request->request.dataLen,
+                          &request->replyPort) == KERN_SUCCESS) {
+               request_queue(request);
+       } else {
+               if (request->request.data) free(request->request.data);
+               free(request);
+               *error = NO_RECOVERY;
+               return MACH_PORT_NULL;
+       }
+
+       return request->replyPort;
+}
+
+
+boolean_t
+_gethostbyaddr_async_handleReply(void          *replyMsg,
+                                a_requests_t   **requestP,
+                                struct hostent **he,
+                                int            *error)
+{
+       int                     count;
+       ooline_data             data;
+       unsigned int            datalen;
+       XDR                     inxdr;
+       mach_msg_header_t       *msg    = (mach_msg_header_t *)replyMsg;
+       a_requests_t            *request;
+       kern_return_t           status;
+       security_token_t        token;
+
+       request = request_extract(msg->msgh_local_port);
+       if (!request) {
+               /* excuse me, what happenned to the request info? */
+               return FALSE;
+       }
+
+       *requestP = request;
+       *he       = NULL;
+       *error    = 0;
+
+       /* unpack the reply */
+       status = _lookup_all_rx(replyMsg, &data, &datalen, &token);
+       switch (status) {
+               case KERN_SUCCESS :
+                       break;
+
+               case MIG_SERVER_DIED :
+                       if (--request->retry > 0) {
+                               /* retry the request */
+                               if (_lookup_all_tx(_lu_port,
+                                                  request->request.proc,
+                                                  request->request.data,
+                                                  request->request.dataLen,
+                                                  &request->replyPort) == KERN_SUCCESS) {
+                                       request_queue(request);
+                                       return FALSE;
+                               }
+                       }
+                       /* fall through */
+
+               default :
+                       *error = HOST_NOT_FOUND;
+                       return TRUE;
+       }
+
+       datalen *= BYTES_PER_XDR_UNIT;
+
+       if (token.val[0] != 0) {
+               vm_deallocate(mach_task_self(), (vm_address_t)data, datalen);
+               *error = NO_RECOVERY;
+               return TRUE;
+       }
+
+       xdrmem_create(&inxdr, data, datalen, XDR_DECODE);
+
+       count = 0;
+       if (!xdr_int(&inxdr, &count)) {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)data, datalen);
+               *error = NO_RECOVERY;
+               return TRUE;
+       }
+
+       if (count == 0) {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)data, datalen);
+               *error = HOST_NOT_FOUND;
+               *he    = NULL;
+               return TRUE;
+       }
+
+       *he = extract_host(&inxdr, request->request.want, error);
+       xdr_destroy(&inxdr);
+       vm_deallocate(mach_task_self(), (vm_address_t)data, datalen);
+       return TRUE;
+}
+
+
+mach_port_t
+gethostbyaddr_async_start(const char                   *addr,
+                         int                           len,
+                         int                           type,
+                         gethostbyaddr_async_callback  callout,
+                         void                          *context)
+{
+       a_request_callout_t     cb;
+       mach_port_t             mp;
+
+       if (!_lu_running()) {
+               h_errno = NO_RECOVERY;
+               return MACH_PORT_NULL;
+       }
+
+       cb.hostAddr = callout;
+       mp = _gethostbyaddr_async_start(addr, len, type, cb, context, &h_errno);
+       return mp;
+}
+
+
+void
+gethostbyaddr_async_handleReply(void *replyMsg)
+{
+       int             error           = 0;
+       struct hostent  *he             = NULL;
+       a_requests_t    *request        = NULL;
+
+       if (_gethostbyaddr_async_handleReply(replyMsg, &request, &he, &error)) {
+               /* if we have an answer to provide */
+               h_errno = error;
+               (request->callout.hostAddr)(he, request->context);
+
+               (void)mach_port_destroy(mach_task_self(), request->replyPort);
+               if (request->request.data) free(request->request.data);
+               free(request);
+               if (he) freehostent(he);
+       }
+
+       return;
+}
+
+
+mach_port_t
+getipnodebyaddr_async_start(const void                         *addr,
+                           size_t                              len,
+                           int                                 af,
+                           int                                 *error,
+                           getipnodebyaddr_async_callback      callout,
+                           void                                *context)
+{
+       a_request_callout_t     cb;
+       mach_port_t             mp;
+
+       if (!_lu_running()) {
+               *error = NO_RECOVERY;
+               return MACH_PORT_NULL;
+       }
+
+       if ((af == AF_INET6) &&
+           (len == sizeof(struct in6_addr)) &&
+           (is_a4_mapped((const char *)addr) || is_a4_compat((const char *)addr))) {
+               /*
+                * this is really a v4 address
+                */
+               addr += sizeof(struct in6_addr) - sizeof(struct in_addr);
+               len  =  sizeof(struct in_addr);
+               af   = AF_INET;
+       }
+
+       cb.nodeAddr = callout;
+       mp = _gethostbyaddr_async_start(addr, len, af, cb, context, error);
+       return mp;
+}
+
+
+void
+getipnodebyaddr_async_handleReply(void *replyMsg)
+{
+       int             error           = 0;
+       struct hostent  *he             = NULL;
+       a_requests_t    *request        = NULL;
+
+       if (_gethostbyaddr_async_handleReply(replyMsg, &request, &he, &error)) {
+               /* if we have an answer to provide */
+               (request->callout.nodeAddr)(he, error, request->context);
+
+               (void)mach_port_destroy(mach_task_self(), request->replyPort);
+               if (request->request.data) free(request->request.data);
+               free(request);
+               /*
+                * Note: it is up to the callback function to call
+                *       freehostent().
+                */
+       }
+
+       return;
+}
+
+
+mach_port_t
+_gethostbyname_async_start(const char                  *name,
+                          int                          want,
+                          int                          *error,
+                          a_request_callout_t          callout,
+                          void                         *context)
+{
+       int             af;
+       boolean_t       is_addr         = FALSE;
+       mach_port_t     mp              = MACH_PORT_NULL;
+       XDR             outxdr;
+       static int      proc;
+       a_requests_t    *request;
+
+       if ((name == NULL) || (name[0] == '\0')) {
+               *error = NO_DATA;
+               return MACH_PORT_NULL;
+       }
+
+       af = (want == WANT_A4_ONLY) ? AF_INET : AF_INET6;
+
+       if ((af == AF_INET) || (want == WANT_MAPPED_A4_ONLY)) {
+               static int      proc4   = -1;
+
+               if (proc4 < 0) {
+                       if (_lookup_link(_lu_port, "gethostbyname", &proc4) != KERN_SUCCESS) {
+                               *error = NO_RECOVERY;
+                               return MACH_PORT_NULL;
+                       }
+               }
+               proc = proc4;
+       } else /* if (af == AF_INET6) */ {
+               static int      proc6   = -1;
+
+               if (proc6 < 0) {
+                       if (_lookup_link(_lu_port, "getipv6nodebyname", &proc6) != KERN_SUCCESS)
+                       {
+                               *error = NO_RECOVERY;
+                               return MACH_PORT_NULL;
+                       }
+               }
+               proc = proc6;
+       }
+
+       request = malloc(sizeof(a_requests_t));
+       request->next            = NULL;
+       request->retry           = MAX_LOOKUP_ATTEMPTS;
+       request->request.proc    = proc;
+       request->request.data    = NULL;
+       request->request.dataLen = 0;
+       request->request.want    = want;
+       request->replyPort       = MACH_PORT_NULL;
+       request->callout         = callout;
+       request->context         = context;
+       request->hent            = NULL;
+
+       switch (af) {
+           case AF_INET :
+               {
+                       struct in_addr  v4addr;
+
+                       memset(&v4addr, 0, sizeof(struct in_addr));
+                       if (inet_aton(name, &v4addr) == 1) {
+                               /* return a fake hostent */
+                               request->hent = fake_hostent(name, v4addr);
+                               is_addr = TRUE;
+                       }
+                       break;
+               }
+
+           case AF_INET6 :
+               {
+                       struct in_addr  v4addr;
+                       struct in6_addr v6addr;
+
+                       memset(&v6addr, 0, sizeof(struct in6_addr));
+                       if (inet_pton(af, name, &v6addr) == 1) {
+                               /* return a fake hostent */
+                               request->hent = fake_hostent6(name, v6addr);
+                               is_addr = TRUE;
+                               break;
+                       } 
+
+                       memset(&v4addr, 0, sizeof(struct in_addr));
+                       if (inet_aton(name, &v4addr) == 1) {
+                               if (want == WANT_A4_ONLY) {
+                                       free(request);
+                                       *error = HOST_NOT_FOUND;
+                                       return MACH_PORT_NULL;
+                               }
+
+                               v6addr.__u6_addr.__u6_addr32[0] = 0x00000000;
+                               v6addr.__u6_addr.__u6_addr32[1] = 0x00000000;
+                               v6addr.__u6_addr.__u6_addr32[2] = htonl(0x0000ffff);
+                               memmove(&(v6addr.__u6_addr.__u6_addr32[3]), &(v4addr.s_addr), sizeof(struct in_addr));
+
+                               /* return a fake hostent */
+                               request->hent = fake_hostent6(name, v6addr);
+                               is_addr = TRUE;
+                       }
+                       break;
+               }
+
+           default:
+               free(request);
+               *error = NO_RECOVERY;
+               return MACH_PORT_NULL;
+       }
+
+       if (is_addr) {
+               /*
+                * queue reply message
+                */
+               if (sendCannedReply(request, error)) {
+                       request_queue(request);
+                       return request->replyPort;
+               } else {
+                       freehostent(request->hent);
+                       free(request);
+                       return MACH_PORT_NULL;
+               }
+       }
+
+       request->request.dataLen = _LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT;
+       request->request.data    = malloc(request->request.dataLen);
+
+       xdrmem_create(&outxdr, request->request.data, request->request.dataLen, XDR_ENCODE);
+       if (!xdr__lu_string(&outxdr, (_lu_string *)&name)) {
+               xdr_destroy(&outxdr);
+               free(request->request.data);
+               free(request);
+               *error = NO_RECOVERY;
+               return MACH_PORT_NULL;
+       }
+
+       request->request.dataLen = xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT;
+
+       /*
+        * allocate reply port, send query to lookupd
+        */
+       if (_lookup_all_tx(_lu_port,
+                          request->request.proc,
+                          request->request.data,
+                          request->request.dataLen,
+                          &request->replyPort) == KERN_SUCCESS) {
+               request_queue(request);
+               mp = request->replyPort;
+       } else {
+               free(request->request.data);
+               free(request);
+               *error = NO_RECOVERY;
+               mp = NULL;
+       }
+
+       xdr_destroy(&outxdr);
+       return mp;
+}
+
+
+boolean_t
+_gethostbyname_async_handleReply(void          *replyMsg,
+                                a_requests_t   **requestP,
+                                struct hostent **he,
+                                int            *error)
+{
+
+       int                     count;
+       unsigned int            datalen;
+       XDR                     inxdr;
+       ooline_data             data;
+       mach_msg_header_t       *msg    = (mach_msg_header_t *)replyMsg;
+       a_requests_t            *request;
+       kern_return_t           status;
+       security_token_t        token;
+       int                     want;
+
+       request = request_extract(msg->msgh_local_port);
+       if (!request) {
+               /* excuse me, what happenned to the request info? */
+               return FALSE;
+       }
+
+       *requestP = request;
+       *he       = NULL;
+       *error    = 0;
+
+       if (request->hent) {
+               /*
+                * if the reply was already available when the
+                * request was made
+                */
+               *he = request->hent;
+               return TRUE;
+       }
+
+       /* unpack the reply */
+       status = _lookup_all_rx(replyMsg, &data, &datalen, &token);
+       switch (status) {
+               case KERN_SUCCESS :
+                       break;
+
+               case MIG_SERVER_DIED :
+                       if (--request->retry > 0) {
+                               /*
+                                * retry the request
+                                */
+                               if (_lookup_all_tx(_lu_port,
+                                                  request->request.proc,
+                                                  request->request.data,
+                                                  request->request.dataLen,
+                                                  &request->replyPort) == KERN_SUCCESS) {
+                                       request_queue(request);
+                                       return FALSE;
+                               }
+                       }
+                       /* fall through */
+
+               default :
+                       *error = HOST_NOT_FOUND;
+                       return TRUE;
+       }
+
+       datalen *= BYTES_PER_XDR_UNIT;
+
+       if (token.val[0] != 0) {
+               vm_deallocate(mach_task_self(), (vm_address_t)data, datalen);
+               *error = NO_RECOVERY;
+               return TRUE;
+       }
+
+       xdrmem_create(&inxdr, data, datalen, XDR_DECODE);
+
+       count = 0;
+       if (!xdr_int(&inxdr, &count)) {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)data, datalen);
+               *error = NO_RECOVERY;
+               return TRUE;
+       }
+
+       if (count == 0) {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)data, datalen);
+               *error = HOST_NOT_FOUND;
+               return TRUE;
+       }
+
+       want = request->request.want;
+       if (want == WANT_A6_OR_MAPPED_A4_IF_NO_A6) want = WANT_A6_ONLY;
+
+       *he = extract_host(&inxdr, want, error);
+       xdr_destroy(&inxdr);
+       vm_deallocate(mach_task_self(), (vm_address_t)data, datalen);
+       return TRUE;
+}
+
+
+mach_port_t
+gethostbyname_async_start(const char                   *name,
+                         gethostbyname_async_callback  callout,
+                         void                          *context)
+{
+       a_request_callout_t     cb;
+       int                     error;
+       mach_port_t             mp      = MACH_PORT_NULL;
+
+       if (!_lu_running()) {
+               h_errno = NO_RECOVERY;
+               return MACH_PORT_NULL;
+       }
+
+       cb.hostName = callout;
+       mp = _gethostbyname_async_start(name, WANT_A4_ONLY, &error, cb, context);
+       if (!mp) {
+               h_errno = error;
+       }
+       return mp;
+}
+
+
+void
+gethostbyname_async_handleReply(void *replyMsg)
+{
+       int             error;
+       struct hostent  *he;
+       a_requests_t    *request;
+
+       if (_gethostbyname_async_handleReply(replyMsg, &request, &he, &error)) {
+               /* if we have an answer to provide */
+               h_errno = error;
+               (request->callout.hostAddr)(he, request->context);
+
+               (void)mach_port_destroy(mach_task_self(), request->replyPort);
+               if (request->request.data) free(request->request.data);
+               free(request);
+               if (he) freehostent(he);
+       }
+
+       return;
+}
+
+
+mach_port_t
+getipnodebyname_async_start(const char                         *name,
+                           int                                 af,
+                           int                                 flags,
+                           int                                 *error,
+                           getipnodebyname_async_callback      callout,
+                           void                                *context)
+{
+       a_request_callout_t     cb;
+       int                     if4             = 0;
+       int                     if6             = 0;
+       mach_port_t             mp              = MACH_PORT_NULL;
+       int                     want            = WANT_A4_ONLY;
+
+       if (!_lu_running()) {
+               h_errno = NO_RECOVERY;
+               return MACH_PORT_NULL;
+       }
+
+       /*
+        * IF AI_ADDRCONFIG is set, we need to know what interface flavors we really have.
+        */
+       if (flags & AI_ADDRCONFIG) {
+               struct ifaddrs  *ifa, *ifap;
+
+               if (getifaddrs(&ifa) < 0) {
+                       *error = NO_RECOVERY;
+                       return MACH_PORT_NULL;
+               }
+
+               for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next) {
+                       if (ifap->ifa_addr == NULL)
+                               continue;
+                       if ((ifap->ifa_flags & IFF_UP) == 0)
+                               continue;
+                       if (ifap->ifa_addr->sa_family == AF_INET) {
+                               if4++;
+                       } else if (ifap->ifa_addr->sa_family == AF_INET6) {
+                               if6++;
+                       }
+               }
+
+               freeifaddrs(ifa);
+
+               /* Bail out if there are no interfaces */
+               if ((if4 == 0) && (if6 == 0)) {
+                       *error = NO_ADDRESS;
+                       return MACH_PORT_NULL;
+               }
+       }
+
+       /*
+        * Figure out what we want.
+        * If user asked for AF_INET, we only want V4 addresses.
+        */
+       switch (af) {
+           case AF_INET :
+               {
+                       want = WANT_A4_ONLY;
+                       if ((flags & AI_ADDRCONFIG) && (if4 == 0)) {
+                               *error = NO_ADDRESS;
+                               return MACH_PORT_NULL;
+                       }
+               }
+               break;
+           case AF_INET6 :
+               {
+                       want = WANT_A6_ONLY;
+                       if (flags & (AI_V4MAPPED|AI_V4MAPPED_CFG)) {
+                               if (flags & AI_ALL) {
+                                       want = WANT_A6_PLUS_MAPPED_A4;
+                               } else {
+                                       want = WANT_A6_OR_MAPPED_A4_IF_NO_A6;
+                               }
+                       } else {
+                               if ((flags & AI_ADDRCONFIG) && (if6 == 0)) {
+                                       *error = NO_ADDRESS;
+                                       return MACH_PORT_NULL;
+                               }
+                       }
+               }
+               break;
+       }
+
+       cb.nodeName = callout;
+       mp = _gethostbyname_async_start(name, want, &h_errno, cb, context);
+       return mp;
+}
+
+
+void
+getipnodebyname_async_handleReply(void *replyMsg)
+{
+       int             error           = 0;
+       struct hostent  *he             = NULL;
+       a_requests_t    *request        = NULL;
+
+       if (_gethostbyname_async_handleReply(replyMsg, &request, &he, &error)) {
+               /*
+                * we have an answer to provide
+                */
+               if ((he == NULL) &&
+                   (error == HOST_NOT_FOUND) &&
+                   ((request->request.want == WANT_A6_PLUS_MAPPED_A4) ||
+                    (request->request.want == WANT_A6_OR_MAPPED_A4_IF_NO_A6))) {
+                       /*
+                        * no host found (yet), if requested we send a
+                        * followup query to lookupd.
+                        */
+                       static int      proc4           = -1;
+
+                       if (proc4 < 0) {
+                               if (_lookup_link(_lu_port, "gethostbyname", &proc4) != KERN_SUCCESS) {
+                                       error = NO_RECOVERY;
+                                       goto answer;
+                               }
+                       }
+
+                       request->request.proc = proc4;
+                       request->request.want = WANT_MAPPED_A4_ONLY;
+                       if (_lookup_all_tx(_lu_port,
+                                          request->request.proc,
+                                          request->request.data,
+                                          request->request.dataLen,
+                                          &request->replyPort) == KERN_SUCCESS) {
+                               request_queue(request);
+                               return;
+                       } else {
+                               error = NO_RECOVERY;
+                       }
+               }
+
+           answer :
+               (request->callout.nodeName)(he, error, request->context);
+               (void)mach_port_destroy(mach_task_self(), request->replyPort);
+               if (request->request.data) free(request->request.data);
+               free(request);
+               /*
+                * Note: it is up to the callback function to call
+                *       freehostent().
+                */
+       }
+
+       return;
+}
index 8e522723547ea40ff98e582eae300e8889b45b94..5a32b0b083c62c0c192a9769ed4dacb73a76dd77 100644 (file)
 #include "lu_utils.h"
 #include "lu_overrides.h"
 
-#define FIX(x) ((x == NULL) ? NULL : &(x))
+#define FIX(x) ((x == NULL) ? NULL : (_lu_string *)&(x))
 
-static struct netgrent global_netgr;
-static int global_free = 1;
-static char *netgr_data = NULL;
-static unsigned netgr_datalen;
-static int netgr_nentries = 0;
-static int netgr_start = 1;
-static XDR netgr_xdr;
+static void 
+free_netgroup_data(struct netgrent *ng)
+{
+       if (ng == NULL) return;
+
+       if (ng->ng_host != NULL) free(ng->ng_host);
+       if (ng->ng_user != NULL) free(ng->ng_user);
+       if (ng->ng_domain != NULL) free(ng->ng_domain);
+}
+
+static void 
+free_netgroup(struct netgrent *ng)
+{
+       if (ng == NULL) return;
+       free_netgroup_data(ng);
+       free(ng);
+ }
 
 static void
-freeold(void)
+free_lu_thread_info_netgroup(void *x)
+{
+       struct lu_thread_info *tdata;
+
+       if (x == NULL) return;
+
+       tdata = (struct lu_thread_info *)x;
+       
+       if (tdata->lu_entry != NULL)
+       {
+               free_netgroup((struct netgrent *)tdata->lu_entry);
+               tdata->lu_entry = NULL;
+       }
+
+       _lu_data_free_vm_xdr(tdata);
+
+       free(tdata);
+}
+
+static struct netgrent *
+extract_netgroup(XDR *xdr)
 {
-       if (global_free == 1) return;
+       char *h, *u, *d;
+       struct netgrent *ng;
+
+       if (xdr == NULL) return NULL;
+
+       h = NULL;
+       u = NULL;
+       d = NULL;
+
+       if (!xdr_string(xdr, &h, LU_LONG_STRING_LENGTH))
+       {
+               return NULL;
+       }
+
+       if (!xdr_string(xdr, &u, LU_LONG_STRING_LENGTH))
+       {
+               free(h);
+               return NULL;
+       }
+
+       if (!xdr_string(xdr, &d, LU_LONG_STRING_LENGTH))
+       {
+               free(h);
+               free(u);
+               return NULL;
+       }
+
+       ng = (struct netgrent *)calloc(1, sizeof(struct netgrent));
+
+       ng->ng_host = h;
+       ng->ng_user = u;
+       ng->ng_domain = d;
+
+       return ng;
+}
+
+#ifdef NOTDEF
+static struct netgrent *
+copy_netgroup(struct netgrent *in)
+{
+       struct netgrent *ng;
+
+       if (in == NULL) return NULL;
+
+       ng = (struct group *)calloc(1, sizeof(struct netgrent));
 
-       free(global_netgr.ng_host);
-       free(global_netgr.ng_user);
-       free(global_netgr.ng_domain);
+       ng->ng_host = LU_COPY_STRING(in->ng_host);
+       ng->ng_user = LU_COPY_STRING(in->ng_user);
+       ng->ng_domain = LU_COPY_STRING(in->ng_domain);
 
-       global_free = 1;
+       return ng;
 }
+#endif
 
 static void
-convert_netgr(_lu_netgrent *lu_netgr)
+recycle_netgroup(struct lu_thread_info *tdata, struct netgrent *in)
 {
-       freeold();
+       struct netgrent *ng;
+
+       if (tdata == NULL) return;
+       ng = (struct netgrent *)tdata->lu_entry;
+
+       if (in == NULL)
+       {
+               free_netgroup(ng);
+               tdata->lu_entry = NULL;
+       }
+
+       if (tdata->lu_entry == NULL)
+       {
+               tdata->lu_entry = in;
+               return;
+       }
 
-       global_netgr.ng_host = strdup(lu_netgr->ng_host);
-       global_netgr.ng_user = strdup(lu_netgr->ng_user);
-       global_netgr.ng_domain = strdup(lu_netgr->ng_domain);
+       free_netgroup_data(ng);
 
-       global_free = 0;
+       ng->ng_host = in->ng_host;
+       ng->ng_user = in->ng_user;
+       ng->ng_domain = in->ng_domain;
+
+       free(in);
 }
 
 
@@ -84,13 +176,13 @@ lu_innetgr(const char *group, const char *host, const char *user,
        int size;
        int res;
        _lu_innetgr_args args;
-       unit lookup_buf[MAX_INLINE_UNITS];
+       char *lookup_buf;
 
        if (proc < 0)
        {
                if (_lookup_link(_lu_port, "innetgr", &proc) != KERN_SUCCESS)
                {
-                       return (0);
+                       return 0;
                }
        }
 
@@ -103,56 +195,68 @@ lu_innetgr(const char *group, const char *host, const char *user,
        if (!xdr__lu_innetgr_args(&xdr, &args))
        {
                xdr_destroy(&xdr);
-               return (0);
+               return 0;
        }
 
        size = xdr_getpos(&xdr) / BYTES_PER_XDR_UNIT;
        xdr_destroy(&xdr);
 
-       datalen = MAX_INLINE_UNITS;
-       if (_lookup_one(_lu_port, proc, (unit *)namebuf, size, lookup_buf, 
-               &datalen) != KERN_SUCCESS)
+       datalen = 0;
+       lookup_buf = NULL;
+
+       if (_lookup_all(_lu_port, proc, (unit *)namebuf, size, &lookup_buf, &datalen) != KERN_SUCCESS)
        {
-               return (0);
+               return 0;
        }
 
        datalen *= BYTES_PER_XDR_UNIT;
+       if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
+
        xdrmem_create(&xdr, lookup_buf, datalen, XDR_DECODE);
        if (!xdr_int(&xdr, &res))
        {
                xdr_destroy(&xdr);
-               return (0);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return 0;
        }
 
        xdr_destroy(&xdr);
-       return (res);
+       vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+
+       return res;
 }
 
 static void
 lu_endnetgrent(void)
 {
-       netgr_nentries = 0;
-       if (netgr_data != NULL)
-       {
-               freeold();
-               vm_deallocate(mach_task_self(), (vm_address_t)netgr_data, netgr_datalen);
-               netgr_data = NULL;
-       }
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_netgroup, free_lu_thread_info_netgroup);
+       _lu_data_free_vm_xdr(tdata);
 }
 
+
 /* 
  * This is different than the other setXXXent routines
  * since this is really more like getnetgrbyname() than
  * getnetgrent().
  */ 
 static void
-lu_setnetgrent(const char *group)
+lu_setnetgrent(const char *name)
 {
        unsigned datalen;
        char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT];
        XDR outxdr;
        static int proc = -1;
+       struct lu_thread_info *tdata;
 
+       tdata = _lu_data_create_key(_lu_data_key_netgroup, free_lu_thread_info_netgroup);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_netgroup, tdata);
+       }
+\r
        lu_endnetgrent();
 
        if (proc < 0)
@@ -165,64 +269,61 @@ lu_setnetgrent(const char *group)
        }
 
        xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE);
-       if (!xdr__lu_string(&outxdr, &group))
+       if (!xdr__lu_string(&outxdr, (_lu_string *)&name))
        {
                xdr_destroy(&outxdr);
                lu_endnetgrent();
                return;
        }
        
-       datalen = MAX_INLINE_UNITS;
-       if (_lookup_all(_lu_port, proc, (unit *)namebuf,
-               xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT,
-               &netgr_data, &netgr_datalen) != KERN_SUCCESS)
+       datalen = xdr_getpos(&outxdr);
+       xdr_destroy(&outxdr);
+       if (_lookup_all(_lu_port, proc, (unit *)namebuf, datalen / BYTES_PER_XDR_UNIT, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS)
        {
-               xdr_destroy(&outxdr);
                lu_endnetgrent();
                return;
        }
 
-       xdr_destroy(&outxdr);
+       /* mig stubs measure size in words (4 bytes) */
+       tdata->lu_vm_length *= 4;
 
-#ifdef NOTDEF
-/* NOTDEF because OOL buffers are counted in bytes with untyped IPC */
-       netgr_datalen *= BYTES_PER_XDR_UNIT;
-#endif
-
-       xdrmem_create(&netgr_xdr, netgr_data, 
-               netgr_datalen, XDR_DECODE);
-       if (!xdr_int(&netgr_xdr, &netgr_nentries))
-       {
-               xdr_destroy(&netgr_xdr);
-               lu_endnetgrent();
+       if (tdata->lu_xdr != NULL)
+       {       
+               xdr_destroy(tdata->lu_xdr);
+               free(tdata->lu_xdr);
        }
+       tdata->lu_xdr = (XDR *)calloc(1, sizeof(XDR));
+
+       xdrmem_create(tdata->lu_xdr, tdata->lu_vm, tdata->lu_vm_length, XDR_DECODE);
+       if (!xdr_int(tdata->lu_xdr, &tdata->lu_vm_cursor)) lu_endnetgrent();
 }
 
 
 struct netgrent *
 lu_getnetgrent(void)
 {
-       _lu_netgrent lu_netgr;
+       struct netgrent *ng;
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_netgroup, free_lu_thread_info_netgroup);
+       if (tdata == NULL) return NULL;
 
-       if (netgr_nentries == 0)
+       if (tdata->lu_vm_cursor == 0)
        {
-               xdr_destroy(&netgr_xdr);
                lu_endnetgrent();
-               return (NULL);
+               return NULL;
        }
 
-       bzero(&lu_netgr, sizeof(lu_netgr));
-       if (!xdr__lu_netgrent(&netgr_xdr, &lu_netgr))
+       ng = extract_netgroup(tdata->lu_xdr);
+       if (ng == NULL)
        {
-               xdr_destroy(&netgr_xdr);
                lu_endnetgrent();
-               return (NULL);
+               return NULL;
        }
 
-       netgr_nentries--;
-       convert_netgr(&lu_netgr);
-       xdr_free(xdr__lu_netgrent, &lu_netgr);
-       return (&global_netgr);
+       tdata->lu_vm_cursor--;
+       
+       return ng;
 }
 
 int 
@@ -230,28 +331,37 @@ innetgr(const char *group, const char *host, const char *user,
        const char *domain)
 {
        if (_lu_running()) return (lu_innetgr(group, host, user, domain));
-//     return (_old_innetgr(group, host, user, domain));
-       return (0);
+       return 0;
 }
 
 struct netgrent *
 getnetgrent(void)
 {
-       if (_lu_running()) return (lu_getnetgrent());
-//     return (_old_getnetgrent());
-       return (NULL);
+       struct netgrent *res = NULL;
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_netgroup, free_lu_thread_info_netgroup);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_netgroup, tdata);
+       }
+
+       res = NULL;
+       if (_lu_running()) res = lu_getnetgrent();
+
+       recycle_netgroup(tdata, res);
+       return (struct netgrent *)tdata->lu_entry;
 }
 
 void
-setnetgrent(const char *group)
+setnetgrent(const char *name)
 {
-       if (_lu_running()) lu_setnetgrent(group);
-//     else _old_setnetgrent(group);
+       if (_lu_running()) lu_setnetgrent(name);
 }
 
 void
 endnetgrent(void)
 {
        if (_lu_running()) lu_endnetgrent();
-//     else _old_endnetgrent();
 }
index 78533f9b9dec039752fedf38b82ebe1f0376f370..e603b9bd207fa876a91931fc7f9adabf74695fa1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <mach/mach.h>
 #include <stdio.h>
 #include <string.h>
-#include "lookup.h"
 #include <rpc/types.h>
 #include <rpc/xdr.h>
-#include "_lu_types.h"
 #include <netdb.h>
-#include "lu_utils.h"
 #include <sys/socket.h>
-#import <netinet/in.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <pthread.h>
+
+#include "_lu_types.h"
+#include "lookup.h"
+#include "lu_utils.h"
+
+static pthread_mutex_t _network_lock = PTHREAD_MUTEX_INITIALIZER;
+
+#define N_GET_NAME 1
+#define N_GET_ADDR 2
+#define N_GET_ENT 3
 
 extern struct netent *_res_getnetbyaddr();
 extern struct netent *_res_getnetbyname();
@@ -46,289 +55,464 @@ extern struct netent *_old_getnetent();
 extern void _old_setnetent();
 extern void _old_endnetent();
 
-static lookup_state n_state = LOOKUP_CACHE;
-static struct netent global_n;
-static int global_free = 1;
-static char *n_data = NULL;
-static unsigned n_datalen;
-static int n_nentries;
-static int n_start = 1;
-static XDR n_xdr;
+extern mach_port_t _lu_port;
+extern int _lu_running(void);
 
 static void
-freeold(void)
+free_network_data(struct netent *n)
 {
        char **aliases;
 
-       if (global_free == 1) return;
+       if (n == NULL) return;
 
-       free(global_n.n_name);
+       free(n->n_name);
 
-       aliases = global_n.n_aliases;
+       aliases = n->n_aliases;
        if (aliases != NULL)
        {
                while (*aliases != NULL) free(*aliases++);
-               free(global_n.n_aliases);
+               free(n->n_aliases);
        }
+}
 
-       global_free = 1;
+static void
+free_network(struct netent *n)
+{
+       if (n == NULL) return;
+       free_network_data(n);
+       free(n);
 }
 
 static void
-convert_n(_lu_netent *lu_n)
+free_lu_thread_info_network(void *x)
+{
+       struct lu_thread_info *tdata;
+
+       if (x == NULL) return;
+
+       tdata = (struct lu_thread_info *)x;
+       
+       if (tdata->lu_entry != NULL)
+       {
+               free_network((struct netent *)tdata->lu_entry);
+               tdata->lu_entry = NULL;
+       }
+
+       _lu_data_free_vm_xdr(tdata);
+
+       free(tdata);
+}
+
+static struct netent *
+extract_network(XDR *xdr)
+{
+       struct netent *n;
+       int i, j, nvals, nkeys, status;
+       char *key, **vals;
+
+       if (xdr == NULL) return NULL;
+
+       if (!xdr_int(xdr, &nkeys)) return NULL;
+
+       n = (struct netent *)calloc(1, sizeof(struct netent));
+
+       n->n_addrtype = AF_INET;
+
+       for (i = 0; i < nkeys; i++)
+       {
+               key = NULL;
+               vals = NULL;
+               nvals = 0;
+
+               status = _lu_xdr_attribute(xdr, &key, &vals, &nvals);
+               if (status < 0)
+               {
+                       free_network(n);
+                       return NULL;
+               }
+
+               if (nvals == 0)
+               {
+                       free(key);
+                       continue;
+               }
+
+               j = 0;
+
+               if ((n->n_name == NULL) && (!strcmp("name", key)))
+               {
+                       n->n_name = vals[0];
+                       if (nvals > 1)
+                       {
+                               n->n_aliases = (char **)calloc(nvals, sizeof(char *));
+                               for  (j = 1; j < nvals; j++) n->n_aliases[j-1] = vals[j];
+                       }
+                       j = nvals;
+               }
+               else if (!strcmp("address", key))
+               {
+                       n->n_net = inet_network(vals[0]);
+               }
+       
+               free(key);
+               if (vals != NULL)
+               {
+                       for (; j < nvals; j++) free(vals[j]);
+                       free(vals);
+               }
+       }
+
+       if (n->n_name == NULL) n->n_name = strdup("");
+       if (n->n_aliases == NULL) n->n_aliases = (char **)calloc(1, sizeof(char *));
+
+       return n;
+}
+
+static struct netent *
+copy_network(struct netent *in)
 {
        int i, len;
+       struct netent *n;
 
-       freeold();
+       if (in == NULL) return NULL;
 
-       global_n.n_name = strdup(lu_n->n_names.n_names_val[0]);
+       n = (struct netent *)calloc(1, sizeof(struct netent));
 
-       len = lu_n->n_names.n_names_len - 1;
-       global_n.n_aliases = malloc((len + 1) * sizeof(char *));
+       n->n_name = LU_COPY_STRING(in->n_name);
 
+       len = 0;
+       if (in->n_aliases != NULL)
+       {
+               for (len = 0; in->n_aliases[len] != NULL; len++);
+       }
+
+       n->n_aliases = (char **)calloc(len + 1, sizeof(char *));
        for (i = 0; i < len; i++)
        {
-               global_n.n_aliases[i] = strdup(lu_n->n_names.n_names_val[i + 1]);
+               n->n_aliases[i] = strdup(in->n_aliases[i]);
+       }
+
+       n->n_addrtype = in->n_addrtype;
+       n->n_net = in->n_net;
+
+       return n;
+}
+
+static void
+recycle_network(struct lu_thread_info *tdata, struct netent *in)
+{
+       struct netent *n;
+
+       if (tdata == NULL) return;
+       n = (struct netent *)tdata->lu_entry;
+
+       if (in == NULL)
+       {
+               free_network(n);
+               tdata->lu_entry = NULL;
        }
 
-       global_n.n_aliases[len] = NULL;
+       if (tdata->lu_entry == NULL)
+       {
+               tdata->lu_entry = in;
+               return;
+       }
 
-       global_n.n_addrtype = AF_INET;
-       global_n.n_net = lu_n->n_net;
+       free_network_data(n);
 
-       global_free = 0;
+       n->n_name = in->n_name;
+       n->n_aliases = in->n_aliases;
+       n->n_addrtype = in->n_addrtype;
+       n->n_net = in->n_net;
+
+       free(in);
 }
 
 static struct netent *
 lu_getnetbyaddr(long addr, int type)
 {
+       struct netent *n;
        unsigned datalen;
-       _lu_netent_ptr lu_n;
-       XDR xdr;
+       XDR inxdr;
        static int proc = -1;
-       unit lookup_buf[MAX_INLINE_UNITS];
-       
-       if (type != AF_INET)
-       {
-               return (NULL);
-       }
+       char *lookup_buf;
+       int count;
+
+       if (type != AF_INET) return NULL;
 
        if (proc < 0)
        {
                if (_lookup_link(_lu_port, "getnetbyaddr", &proc) != KERN_SUCCESS)
                {
-                       return (NULL);
+                       return NULL;
                }
        }
 
        addr = htonl(addr);
-       datalen = MAX_INLINE_UNITS;
-       if (_lookup_one(_lu_port, proc, (unit *)&addr, 1, lookup_buf, &datalen)
-               != KERN_SUCCESS)
+       datalen = 0;
+       lookup_buf = NULL;
+
+       if (_lookup_all(_lu_port, proc, (unit *)&addr, 1, &lookup_buf, &datalen) != KERN_SUCCESS)
        {
-               return (NULL);
+               return NULL;
        }
 
        datalen *= BYTES_PER_XDR_UNIT;
-       xdrmem_create(&xdr, lookup_buf, datalen, XDR_DECODE);
-       lu_n = NULL;
-       if (!xdr__lu_netent_ptr(&xdr, &lu_n) || (lu_n == NULL))
+       if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
+
+       xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
+
+       count = 0;
+       if (!xdr_int(&inxdr, &count))
        {
-               xdr_destroy(&xdr);
-               return (NULL);
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
+       }
+
+       if (count == 0)
+       {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
        }
 
-       xdr_destroy(&xdr);
+       n = extract_network(&inxdr);
+       xdr_destroy(&inxdr);
+       vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
 
-       convert_n(lu_n);
-       xdr_free(xdr__lu_netent_ptr, &lu_n);
-       return (&global_n);
+       return n;
 }
 
 static struct netent *
 lu_getnetbyname(const char *name)
 {
+       struct netent *n;
        unsigned datalen;
        char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT];
        XDR outxdr;
        XDR inxdr;
-       _lu_netent_ptr lu_n;
        static int proc = -1;
-       unit lookup_buf[MAX_INLINE_UNITS];
+       char *lookup_buf;
+       int count;
 
        if (proc < 0)
        {
                if (_lookup_link(_lu_port, "getnetbyname", &proc) != KERN_SUCCESS)
                {
-                       return (NULL);
+                       return NULL;
                }
        }
 
        xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE);
-       if (!xdr__lu_string(&outxdr, &name))
+       if (!xdr__lu_string(&outxdr, (_lu_string *)&name))
        {
                xdr_destroy(&outxdr);
-               return (NULL);
+               return NULL;
        }
 
-       datalen = MAX_INLINE_UNITS;
-       if (_lookup_one(_lu_port, proc, (unit *)namebuf,
-               xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, lookup_buf, &datalen)
+       datalen = 0;
+       lookup_buf = NULL;
+
+       if (_lookup_all(_lu_port, proc, (unit *)namebuf,
+               xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, &lookup_buf, &datalen)
                != KERN_SUCCESS)
        {
                xdr_destroy(&outxdr);
-               return (NULL);
+               return NULL;
        }
 
        xdr_destroy(&outxdr);
 
        datalen *= BYTES_PER_XDR_UNIT;
-       xdrmem_create(&inxdr, lookup_buf, datalen,
-               XDR_DECODE);
-       lu_n = NULL;
-       if (!xdr__lu_netent_ptr(&inxdr, &lu_n) || (lu_n == NULL))
+       if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
+
+       xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
+
+       count = 0;
+       if (!xdr_int(&inxdr, &count))
        {
                xdr_destroy(&inxdr);
-               return (NULL);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
        }
 
+       if (count == 0)
+       {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
+       }
+
+       n = extract_network(&inxdr);
        xdr_destroy(&inxdr);
+       vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
 
-       convert_n(lu_n);
-       xdr_free(xdr__lu_netent_ptr, &lu_n);
-       return (&global_n);
+       return n;
 }
 
 static void
 lu_endnetent()
 {
-       n_nentries = 0;
-       if (n_data != NULL)
-       {
-               freeold();
-               vm_deallocate(mach_task_self(), (vm_address_t)n_data, n_datalen);
-               n_data = NULL;
-       }
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_network, free_lu_thread_info_network);
+       _lu_data_free_vm_xdr(tdata);\r
 }
 
 static void
 lu_setnetent()
 {
        lu_endnetent();
-       n_start = 1;
 }
 
 static struct netent *
 lu_getnetent()
 {
        static int proc = -1;
-       _lu_netent lu_n;
+       struct lu_thread_info *tdata;
+       struct netent *n;
 
-       if (n_start == 1)
+       tdata = _lu_data_create_key(_lu_data_key_network, free_lu_thread_info_network);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_network, tdata);
+       }
+\r
+       if (tdata->lu_vm == NULL)
        {
-               n_start = 0;
-
                if (proc < 0)
                {
                        if (_lookup_link(_lu_port, "getnetent", &proc) != KERN_SUCCESS)
                        {
                                lu_endnetent();
-                               return (NULL);
+                               return NULL;
                        }
                }
 
-               if (_lookup_all(_lu_port, proc, NULL, 0, &n_data, &n_datalen)
-                       != KERN_SUCCESS)
+               if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS)
                {
                        lu_endnetent();
-                       return (NULL);
+                       return NULL;
+               }
+
+               /* mig stubs measure size in words (4 bytes) */
+               tdata->lu_vm_length *= 4;
+
+               if (tdata->lu_xdr != NULL)
+               {
+                       xdr_destroy(tdata->lu_xdr);
+                       free(tdata->lu_xdr);
                }
+               tdata->lu_xdr = (XDR *)calloc(1, sizeof(XDR));
 
-#ifdef NOTDEF
-/* NOTDEF because OOL buffers are counted in bytes with untyped IPC */
-               n_datalen *= BYTES_PER_XDR_UNIT;
-#endif
-               xdrmem_create(&n_xdr, n_data, n_datalen,
-                       XDR_DECODE);
-               if (!xdr_int(&n_xdr, &n_nentries))
+               xdrmem_create(tdata->lu_xdr, tdata->lu_vm, tdata->lu_vm_length, XDR_DECODE);
+               if (!xdr_int(tdata->lu_xdr, &tdata->lu_vm_cursor))
                {
-                       xdr_destroy(&n_xdr);
                        lu_endnetent();
-                       return (NULL);
+                       return NULL;
                }
        }
 
-       if (n_nentries == 0)
+       if (tdata->lu_vm_cursor == 0)
        {
-               xdr_destroy(&n_xdr);
                lu_endnetent();
-               return (NULL);
+               return NULL;
        }
 
-       bzero(&lu_n, sizeof(lu_n));
-       if (!xdr__lu_netent(&n_xdr, &lu_n))
+       n = extract_network(tdata->lu_xdr);
+       if (n == NULL)
        {
-               xdr_destroy(&n_xdr);
                lu_endnetent();
-               return (NULL);
+               return NULL;
        }
 
-       n_nentries--;
-       convert_n(&lu_n);
-       xdr_free(xdr__lu_netent, &lu_n);
-       return (&global_n);
+       tdata->lu_vm_cursor--;
+       
+       return n;
 }
 
-struct netent *
-getnetbyaddr(long addr, int type)
+static struct netent *
+getnet(const char *name, long addr, int type, int source)
 {
-    struct netent *res;
+       struct netent *res = NULL;
+       struct lu_thread_info *tdata;
 
-    if (_lu_running())
+       tdata = _lu_data_create_key(_lu_data_key_network, free_lu_thread_info_network);
+       if (tdata == NULL)
        {
-               res = lu_getnetbyaddr(addr, type);
-    }
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_network, tdata);
+       }
+
+       if (_lu_running())
+       {
+               switch (source)
+               {
+                       case N_GET_NAME:
+                               res = lu_getnetbyname(name);
+                               break;
+                       case N_GET_ADDR:
+                               res = lu_getnetbyaddr(addr, type);
+                               break;
+                       case N_GET_ENT:
+                               res = lu_getnetent();
+                               break;
+                       default: res = NULL;
+               }
+       }
        else
        {
-               res = _res_getnetbyaddr(addr, type);
-               if (res == NULL) res = _old_getnetbyaddr(addr, type);
-    }
+               pthread_mutex_lock(&_network_lock);
+               switch (source)
+               {
+                       case N_GET_NAME:
+                               res = copy_network(_old_getnetbyname(name));
+                               break;
+                       case N_GET_ADDR:
+                               res = copy_network(_old_getnetbyaddr(addr, type));
+                               break;
+                       case N_GET_ENT:
+                               res = copy_network(_old_getnetent());
+                               break;
+                       default: res = NULL;
+               }
+               pthread_mutex_unlock(&_network_lock);
+       }
 
-    return res;
+       recycle_network(tdata, res);
+       return (struct netent *)tdata->lu_entry;
 }
 
 struct netent *
-getnetbyname(const char *name)
+getnetbyaddr(long addr, int type)
 {
-    struct netent *res;
-
-    if (_lu_running())
-       {
-               res = lu_getnetbyname(name);
-    }
-       else
-       {
-               res = _res_getnetbyname(name);
-               if (res == NULL) res = _old_getnetbyname(name);
-    }
+       return getnet(NULL, addr, type, N_GET_ADDR);
+}
 
-    return res;
+struct netent *
+getnetbyname(const char *name)
+{
+       return getnet(name, 0, 0, N_GET_NAME);
 }
 
 struct netent *
 getnetent(void)
 {
-       GETENT(lu_getnetent, _old_getnetent, &n_state, struct netent);
+       return getnet(NULL, 0, 0, N_GET_ENT);
 }
 
 void
 setnetent(int stayopen)
 {
-       SETSTATE(lu_setnetent, _old_setnetent, &n_state, stayopen);
+       if (_lu_running()) lu_setnetent();
+       else _old_setnetent(stayopen);
 }
 
 void
 endnetent(void)
 {
-       UNSETSTATE(lu_endnetent, _old_endnetent, &n_state);
+       if (_lu_running()) lu_endnetent();
+       else _old_endnetent();
 }
index 0290e105966ab1a56c679d523ae676dc167668ff..86fd0b7d2a2f94943af8e076850a31a247847902 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <mach/mach.h>
 #include <stdio.h>
 #include <string.h>
-#include "lookup.h"
 #include <rpc/types.h>
 #include <rpc/xdr.h>
+#include <pthread.h>
+
 #include "_lu_types.h"
+#include "lookup.h"
 #include "printerdb.h"
 #include "lu_utils.h"
 
-extern struct prdb_ent *_old_prdb_get();
-extern struct prdb_ent *_old_prdb_getbyname();
+static pthread_mutex_t _printer_lock = PTHREAD_MUTEX_INITIALIZER;
+
+#define P_GET_NAME 1
+#define P_GET_ENT 2
+
+extern prdb_ent *_old_prdb_get();
+extern prdb_ent *_old_prdb_getbyname();
 extern void _old_prdb_set();
 extern void _old_prdb_end();
 
-static lookup_state prdb_state = LOOKUP_CACHE;
-static struct prdb_ent global_prdb;
-static int global_free = 1;
-static char *prdb_data = NULL;
-static unsigned prdb_datalen = 0;
-static int prdb_nentries;
-static int prdb_start = 1;
-static XDR prdb_xdr = { 0 };
-
 static void 
-freeold(void)
+free_printer_data(prdb_ent *p)
 {
        char **names;
        int i;
 
-       if (global_free == 1) return;
+       if (p == NULL) return;
 
-       names = global_prdb.pe_name;
+       names = p->pe_name;
        if (names != NULL)
        {
                while (*names) free(*names++);
-               free(global_prdb.pe_name);
+               free(p->pe_name);
        }
 
-       for (i = 0; i < global_prdb.pe_nprops; i++)
+       for (i = 0; i < p->pe_nprops; i++)
        {
-               free(global_prdb.pe_prop[i].pp_key);
-               free(global_prdb.pe_prop[i].pp_value);
+               free(p->pe_prop[i].pp_key);
+               free(p->pe_prop[i].pp_value);
        }
 
-       free(global_prdb.pe_prop);
-
-       global_free = 1;
+       free(p->pe_prop);
 }
 
+static void 
+free_printer(prdb_ent *p)
+{
+       if (p == NULL) return;
+       free_printer_data(p);
+       free(p);
+}
 
 static void
-convert_prdb(_lu_prdb_ent *lu_prdb)
+free_lu_thread_info_printer(void *x)
 {
-       int i, len;
+       struct lu_thread_info *tdata;
 
-       freeold();
+       if (x == NULL) return;
 
-       len = lu_prdb->pe_names.pe_names_len;
-       global_prdb.pe_name = (char **)malloc((len + 1) * sizeof(char *));
-       for (i = 0; i < len; i++)
+       tdata = (struct lu_thread_info *)x;
+       
+       if (tdata->lu_entry != NULL)
        {
-               global_prdb.pe_name[i] = strdup(lu_prdb->pe_names.pe_names_val[i]);
+               free_printer((prdb_ent *)tdata->lu_entry);
+               tdata->lu_entry = NULL;
        }
 
-       global_prdb.pe_name[len] = NULL;
+       _lu_data_free_vm_xdr(tdata);
+
+       free(tdata);
+}
+
+static prdb_ent *
+extract_printer(XDR *xdr)
+{
+       prdb_ent *p;
+       int i, j, nvals, nkeys, status;
+       char *key, **vals;
+
+       if (xdr == NULL) return NULL;
+
+       if (!xdr_int(xdr, &nkeys)) return NULL;
 
-       len = lu_prdb->pe_props.pe_props_len;
-       global_prdb.pe_prop = (prdb_property *)malloc(len * sizeof(prdb_property));
-       for (i = 0; i < len; i++)
+       p = (prdb_ent *)calloc(1, sizeof(prdb_ent));
+
+       for (i = 0; i < nkeys; i++)
        {
-               global_prdb.pe_prop[i].pp_key =
-                       strdup(lu_prdb->pe_props.pe_props_val[i].pp_key);
+               key = NULL;
+               vals = NULL;
+               nvals = 0;
+
+               status = _lu_xdr_attribute(xdr, &key, &vals, &nvals);
+               if (status < 0)
+               {
+                       free_printer(p);
+                       return NULL;
+               }
+
+               j = 0;
 
-               global_prdb.pe_prop[i].pp_value =
-                       strdup(lu_prdb->pe_props.pe_props_val[i].pp_value);
+               if ((p->pe_name == NULL) && (!strcmp("name", key)))
+               {
+                       free(key);
+                       p->pe_name = vals;
+                       j = nvals;
+                       vals = NULL;
+               }
+               else
+               {
+                       if (p->pe_nprops == 0)
+                       {
+                               p->pe_prop = (prdb_property *)calloc(1, sizeof(prdb_property));
+                       }
+                       else
+                       {
+                               p->pe_prop = (prdb_property *)realloc(p->pe_prop, (p->pe_nprops + 1) * sizeof(prdb_property));
+                       }
+                       p->pe_prop[p->pe_nprops].pp_key = key;
+                       p->pe_prop[p->pe_nprops].pp_value = NULL;
+                       if (nvals > 0)
+                       {
+                               p->pe_prop[p->pe_nprops].pp_value = vals[0];
+                               j = 1;
+                       }
+                       else
+                       {
+                               p->pe_prop[p->pe_nprops].pp_value = strdup("");
+                       }
+                       p->pe_nprops++;
+               }
+       
+               if (vals != NULL)
+               {
+                       for (; j < nvals; j++) free(vals[j]);
+                       free(vals);
+               }
        }
 
-       global_prdb.pe_nprops = lu_prdb->pe_props.pe_props_len;
+       if (p->pe_name == NULL) p->pe_name = (char **)calloc(1, sizeof(char *));
+       if (p->pe_prop == NULL) p->pe_prop = (prdb_property *)calloc(1, sizeof(prdb_property));
 
-       global_free = 0;
+       return p;
 }
 
-static void
-lu_prdb_end()
+static prdb_ent *
+copy_printer(prdb_ent *in)
 {
-       prdb_nentries = 0;
-       if (prdb_data != NULL)
+       int i;
+       prdb_ent *p;
+
+       if (in == NULL) return NULL;
+
+       p = (prdb_ent *)calloc(1, sizeof(prdb_ent));
+
+       if (in->pe_name != NULL)
+       {
+               for (i = 0; in->pe_name[i] != NULL; i++);       
+               p->pe_name = (char **)calloc(i, sizeof(char *));
+               for (i = 0; p->pe_name[i] != NULL; i++) p->pe_name[i] = strdup(in->pe_name[i]);
+       }
+       else
+       {
+               p->pe_name = (char **)calloc(1, sizeof(char *));
+       }
+
+       if (in->pe_nprops > 0)
        {
-               freeold();
-               vm_deallocate(mach_task_self(), (vm_address_t)prdb_data, prdb_datalen);
-               prdb_data = NULL;
+               p->pe_prop = (struct prdb_property *)calloc(in->pe_nprops, sizeof(struct prdb_property));
+               
+               for (i = 0; in->pe_nprops; i++)
+               {
+                       p->pe_prop[i].pp_key = strdup(in->pe_prop[i].pp_key);
+                       p->pe_prop[i].pp_value = NULL;
+                       if (in->pe_prop[i].pp_value != NULL) p->pe_prop[i].pp_value = strdup(in->pe_prop[i].pp_value);
+               }
        }
+       else
+       {
+               p->pe_prop = (prdb_property *)calloc(1, sizeof(prdb_property));
+       }
+
+       return p;
 }
 
 static void
-lu_prdb_set()
+recycle_printer(struct lu_thread_info *tdata, struct prdb_ent *in)
 {
-       lu_prdb_end();
-       prdb_start = 1;
+       struct prdb_ent *p;
+
+       if (tdata == NULL) return;
+       p = (struct prdb_ent *)tdata->lu_entry;
+
+       if (in == NULL)
+       {
+               free_printer(p);
+               tdata->lu_entry = NULL;
+       }
+
+       if (tdata->lu_entry == NULL)
+       {
+               tdata->lu_entry = in;
+               return;
+       }
+
+       free_printer_data(p);
+
+       p->pe_name = in->pe_name;
+       p->pe_nprops = in->pe_nprops;
+       p->pe_prop = in->pe_prop;
+
+       free(in);
 }
 
-static struct prdb_ent *
+static prdb_ent *
 lu_prdb_getbyname(const char *name)
 {
+       prdb_ent *p;
        unsigned datalen;
        char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT];
        XDR outxdr;
        XDR inxdr;
-       _lu_prdb_ent_ptr lu_prdb;
        static int proc = -1;
-       unit lookup_buf[MAX_INLINE_UNITS];
+       char *lookup_buf;
+       int count;
 
        if (proc < 0)
        {
                if (_lookup_link(_lu_port, "prdb_getbyname", &proc) != KERN_SUCCESS)
                {
-                       return (NULL);
+                       return NULL;
                }
        }
 
        xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE);
-       if (!xdr__lu_string(&outxdr, &name))
+       if (!xdr__lu_string(&outxdr, (_lu_string *)&name))
        {
                xdr_destroy(&outxdr);
-               return (NULL);
+               return NULL;
        }
        
-       datalen = MAX_INLINE_UNITS;
-       if (_lookup_one(_lu_port, proc, (unit *)namebuf,
-               xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, lookup_buf, &datalen)
-               != KERN_SUCCESS)
+       datalen = 0;
+       lookup_buf = NULL;
+
+       if (_lookup_all(_lu_port, proc, (unit *)namebuf, xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, &lookup_buf, &datalen) != KERN_SUCCESS)
        {
                xdr_destroy(&outxdr);
-               return (NULL);
+               return NULL;
        }
 
        xdr_destroy(&outxdr);
 
        datalen *= BYTES_PER_XDR_UNIT;
-       xdrmem_create(&inxdr, lookup_buf, datalen,
-               XDR_DECODE);
-       lu_prdb = NULL;
-       if (!xdr__lu_prdb_ent_ptr(&inxdr, &lu_prdb) || (lu_prdb == NULL))
+       if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
+
+       xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
+
+       count = 0;
+       if (!xdr_int(&inxdr, &count))
        {
                xdr_destroy(&inxdr);
-               return (NULL);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
        }
 
+       if (count == 0)
+       {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
+       }
+
+       p = extract_printer(&inxdr);
        xdr_destroy(&inxdr);
+       vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+
+       return p;
+}
 
-       convert_prdb(lu_prdb);
-       xdr_free(xdr__lu_prdb_ent_ptr, &lu_prdb);
-       return (&global_prdb);
+static void
+lu_prdb_end()
+{
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_printer, free_lu_thread_info_printer);
+       _lu_data_free_vm_xdr(tdata);
+}
+
+static void
+lu_prdb_set()
+{
+       lu_prdb_end();
 }
 
 static prdb_ent *
 lu_prdb_get()
 {
+       prdb_ent *p;
        static int proc = -1;
-       _lu_prdb_ent lu_prdb;
+       struct lu_thread_info *tdata;
 
-       if (prdb_start == 1)
+       tdata = _lu_data_create_key(_lu_data_key_printer, free_lu_thread_info_printer);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_printer, tdata);
+       }
+\r
+       if (tdata->lu_vm == NULL)
        {
-               prdb_start = 0;
-
                if (proc < 0)
                {
                        if (_lookup_link(_lu_port, "prdb_get", &proc) != KERN_SUCCESS)
                        {
                                lu_prdb_end();
-                               return (NULL);
+                               return NULL;
                        }
                }
-               if (_lookup_all(_lu_port, proc, NULL, 0, &prdb_data, &prdb_datalen)
-                       != KERN_SUCCESS)
+
+               if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS)
                {
                        lu_prdb_end();
-                       return (NULL);
+                       return NULL;
                }
 
-#ifdef NOTDEF
-/* NOTDEF because OOL buffers are counted in bytes with untyped IPC */
-               prdb_datalen *= BYTES_PER_XDR_UNIT;
-#endif
+               /* mig stubs measure size in words (4 bytes) */
+               tdata->lu_vm_length *= 4;
 
-               xdrmem_create(&prdb_xdr, prdb_data, prdb_datalen,
-                       XDR_DECODE);
-               if (!xdr_int(&prdb_xdr, &prdb_nentries))
+               if (tdata->lu_xdr != NULL)
+               {
+                       xdr_destroy(tdata->lu_xdr);
+                       free(tdata->lu_xdr);
+               }
+               tdata->lu_xdr = (XDR *)calloc(1, sizeof(XDR));
+
+               xdrmem_create(tdata->lu_xdr, tdata->lu_vm, tdata->lu_vm_length, XDR_DECODE);
+               if (!xdr_int(tdata->lu_xdr, &tdata->lu_vm_cursor))
                {
-                       xdr_destroy(&prdb_xdr);
                        lu_prdb_end();
-                       return (NULL);
+                       return NULL;
                }
        }
 
-       if (prdb_nentries == 0)
+       if (tdata->lu_vm_cursor == 0)
        {
-               xdr_destroy(&prdb_xdr);
                lu_prdb_end();
-               return (NULL);
+               return NULL;
        }
 
-       bzero(&lu_prdb, sizeof(lu_prdb));
-       if (!xdr__lu_prdb_ent(&prdb_xdr, &lu_prdb))
+       p = extract_printer(tdata->lu_xdr);
+       if (p == NULL)
        {
-               xdr_destroy(&prdb_xdr);
                lu_prdb_end();
-               return (NULL);
+               return NULL;
+       }
+
+       tdata->lu_vm_cursor--;
+       
+       return p;
+}
+
+static prdb_ent *
+getprinter(const char *name, int source)
+{
+       prdb_ent *res = NULL;
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_printer, free_lu_thread_info_printer);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_printer, tdata);
+       }
+
+       if (_lu_running())
+       {
+               switch (source)
+               {
+                       case P_GET_NAME:
+                               res = lu_prdb_getbyname(name);
+                               break;
+                       case P_GET_ENT:
+                               res = lu_prdb_get();
+                               break;
+                       default: res = NULL;
+               }
+       }
+       else
+       {
+               pthread_mutex_lock(&_printer_lock);
+               switch (source)
+               {
+                       case P_GET_NAME:
+                               res = copy_printer(_old_prdb_getbyname(name));
+                               break;
+                       case P_GET_ENT:
+                               res = copy_printer(_old_prdb_get());
+                               break;
+                       default: res = NULL;
+               }
+               pthread_mutex_unlock(&_printer_lock);
        }
 
-       prdb_nentries--;
-       convert_prdb(&lu_prdb);
-       xdr_free(xdr__lu_prdb_ent, &lu_prdb);
-       return (&global_prdb);
+       recycle_printer(tdata, res);
+       return (prdb_ent *)tdata->lu_entry;
 }
 
 const prdb_ent *
 prdb_getbyname(const char *name)
 {
-       LOOKUP1(lu_prdb_getbyname, _old_prdb_getbyname, name, prdb_ent);
+       return (const prdb_ent *)getprinter(name, P_GET_NAME);
 }
 
 const prdb_ent *
 prdb_get(void)
 {
-       GETENT(lu_prdb_get, _old_prdb_get, &prdb_state, prdb_ent);
+       return (const prdb_ent *)getprinter(NULL, P_GET_ENT);
 }
 
 void
 prdb_set(const char *name)
 {
-       SETSTATE(lu_prdb_set, _old_prdb_set, &prdb_state, name);
+       if (_lu_running()) lu_prdb_set();
+       else _old_prdb_set();
 }
 
 void
 prdb_end(void)
 {
-       UNSETSTATE(lu_prdb_end, _old_prdb_end, &prdb_state);
+       if (_lu_running()) lu_prdb_end();
+       else _old_prdb_end();
 }
index f2c346fbc029a007a89c9902de2804f846a531c8..e511863b5361c68c8b054c0deaf1b60ed7027ea8 100644 (file)
 #include <mach/mach.h>
 #include <stdio.h>
 #include <string.h>
-#include "lookup.h"
 #include <rpc/types.h>
 #include <rpc/xdr.h>
-#include "_lu_types.h"
 #include <netdb.h>
+#include <netinet/in.h>
+
+#include "_lu_types.h"
+#include "lookup.h"
 #include "lu_utils.h"
-#import <netinet/in.h>
 
 extern struct protoent *_old_getprotobynumber();
 extern struct protoent *_old_getprotobyname();
@@ -43,260 +44,457 @@ extern struct protoent *_old_getprotoent();
 extern void _old_setprotoent();
 extern void _old_endprotoent();
 
-static lookup_state p_state = LOOKUP_CACHE;
-static struct protoent global_p;
-static int global_free = 1;
-static char *p_data = NULL;
-static unsigned p_datalen;
-static int p_nentries;
-static int p_start;
-static XDR p_xdr;
+#define PROTO_GET_NAME 1
+#define PROTO_GET_NUM 2
+#define PROTO_GET_ENT 3
 
 static void
-freeold(void)
+free_protocol_data(struct protoent *p)
 {
        char **aliases;
 
-       if (global_free == 1) return;
+       if (p == NULL) return;
 
-       free(global_p.p_name);
-       aliases = global_p.p_aliases;
+       if (p->p_name != NULL) free(p->p_name);
+       aliases = p->p_aliases;
        if (aliases != NULL)
        {
                while (*aliases != NULL) free(*aliases++);
-               free(global_p.p_aliases);
+               free(p->p_aliases);
        }
+}
 
-       global_free = 1;
+static void
+free_protocol(struct protoent *p)
+{
+       if (p == NULL) return;
+       free_protocol_data(p);
+       free(p);
 }
 
 static void
-convert_p(_lu_protoent *lu_p)
+free_lu_thread_info_protocol(void *x)
+{
+       struct lu_thread_info *tdata;
+
+       if (x == NULL) return;
+
+       tdata = (struct lu_thread_info *)x;
+       
+       if (tdata->lu_entry != NULL)
+       {
+               free_protocol((struct protoent *)tdata->lu_entry);
+               tdata->lu_entry = NULL;
+       }
+
+       _lu_data_free_vm_xdr(tdata);
+
+       free(tdata);
+}
+
+static struct protoent *
+extract_protocol(XDR *xdr)
+{
+       struct protoent *p;
+       int i, j, nvals, nkeys, status;
+       char *key, **vals;
+
+       if (xdr == NULL) return NULL;
+
+       if (!xdr_int(xdr, &nkeys)) return NULL;
+
+       p = (struct protoent *)calloc(1, sizeof(struct protoent));
+
+       for (i = 0; i < nkeys; i++)
+       {
+               key = NULL;
+               vals = NULL;
+               nvals = 0;
+
+               status = _lu_xdr_attribute(xdr, &key, &vals, &nvals);
+               if (status < 0)
+               {
+                       free_protocol(p);
+                       return NULL;
+               }
+
+               if (nvals == 0)
+               {
+                       free(key);
+                       continue;
+               }
+
+               j = 0;
+
+               if ((p->p_name == NULL) && (!strcmp("name", key)))
+               {
+                       p->p_name = vals[0];
+                       if (nvals > 1)
+                       {
+                               p->p_aliases = (char **)calloc(nvals, sizeof(char *));
+                               for (j = 1; j < nvals; j++) p->p_aliases[j-1] = vals[j];
+                       }
+                       j = nvals;
+               }
+               else if (!strcmp("number", key))
+               {
+                       p->p_proto = atoi(vals[0]);
+               }
+
+               free(key);
+               if (vals != NULL)
+               {
+                       for (; j < nvals; j++) free(vals[j]);
+                       free(vals);
+               }
+       }
+
+       if (p->p_name == NULL) p->p_name = strdup("");
+       if (p->p_aliases == NULL) p->p_aliases = (char **)calloc(1, sizeof(char *));
+
+       return p;
+}
+
+static struct protoent *
+copy_protocol(struct protoent *in)
 {
        int i, len;
+       struct protoent *p;
 
-       freeold();
+       if (in == NULL) return NULL;
 
-       global_p.p_name = strdup(lu_p->p_names.p_names_val[0]);
+       p = (struct protoent *)calloc(1, sizeof(struct protoent));
 
-       len = lu_p->p_names.p_names_len - 1;
-       global_p.p_aliases = (char **)malloc((len + 1) * sizeof(char *));
+       p->p_proto = in->p_proto;
+       p->p_name = LU_COPY_STRING(in->p_name);
+
+       len = 0;
+       if (in->p_aliases != NULL)
+       {
+               for (len = 0; in->p_aliases[len] != NULL; len++);
+       }
 
+       p->p_aliases = (char **)calloc(len + 1, sizeof(char *));
        for (i = 0; i < len; i++)
        {
-               global_p.p_aliases[i] = strdup(lu_p->p_names.p_names_val[i+1]);
+               p->p_aliases[i] = strdup(in->p_aliases[i]);
        }
 
-       global_p.p_aliases[len] = NULL;
+       return p;
+}
+
+static void
+recycle_protocol(struct lu_thread_info *tdata, struct protoent *in)
+{
+       struct protoent *p;
 
-       global_p.p_proto = lu_p->p_proto;
+       if (tdata == NULL) return;
+       p = (struct protoent *)tdata->lu_entry;
+
+       if (in == NULL)
+       {
+               free_protocol(p);
+               tdata->lu_entry = NULL;
+       }
 
-       global_free = 0;
+       if (tdata->lu_entry == NULL)
+       {
+               tdata->lu_entry = in;
+               return;
+       }
+
+       free_protocol_data(p);
+
+       p->p_proto = in->p_proto;
+       p->p_name = in->p_name;
+       p->p_aliases = in->p_aliases;
+
+       free(in);
 }
 
 static struct protoent *
 lu_getprotobynumber(long number)
 {
-       unsigned datalen;
-       _lu_protoent_ptr lu_p;
-       XDR xdr;
+       struct protoent *p;
+       unsigned int datalen;
+       XDR inxdr;
        static int proc = -1;
-       unit lookup_buf[MAX_INLINE_UNITS];
-       
+       char *lookup_buf;
+       int count;
+
        if (proc < 0)
        {
                if (_lookup_link(_lu_port, "getprotobynumber", &proc) != KERN_SUCCESS)
                {
-                       return (NULL);
+                       return NULL;
                }
        }
 
        number = htonl(number);
-       datalen = MAX_INLINE_UNITS;
-       if (_lookup_one(_lu_port, proc, (unit *)&number, 1, lookup_buf, &datalen)
+       datalen = 0;
+       lookup_buf = NULL;
+
+       if (_lookup_all(_lu_port, proc, (unit *)&number, 1, &lookup_buf, &datalen)
                != KERN_SUCCESS)
        {
-               return (NULL);
+               return NULL;
        }
 
        datalen *= BYTES_PER_XDR_UNIT;
-       xdrmem_create(&xdr, lookup_buf, datalen,
-                     XDR_DECODE);
-       lu_p = NULL;
-       if (!xdr__lu_protoent_ptr(&xdr, &lu_p) || (lu_p == NULL))
+       if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
+
+       xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
+
+       count = 0;
+       if (!xdr_int(&inxdr, &count))
        {
-               xdr_destroy(&xdr);
-               return (NULL);
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
        }
 
-       xdr_destroy(&xdr);
+       if (count == 0)
+       {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
+       }
 
-       convert_p(lu_p);
-       xdr_free(xdr__lu_protoent_ptr, &lu_p);
-       return (&global_p);
+       p = extract_protocol(&inxdr);
+       xdr_destroy(&inxdr);
+       vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+
+       return p;
 }
 
 static struct protoent *
 lu_getprotobyname(const char *name)
 {
-       unsigned datalen;
+       struct protoent *p;
+       unsigned int datalen;
        char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT];
        XDR outxdr;
        XDR inxdr;
-       _lu_protoent_ptr lu_p;
        static int proc = -1;
-       unit lookup_buf[MAX_INLINE_UNITS];
+       char *lookup_buf;
+       int count;
 
        if (proc < 0)
        {
                if (_lookup_link(_lu_port, "getprotobyname", &proc) != KERN_SUCCESS)
                {
-                       return (NULL);
+                       return NULL;
                }
        }
 
        xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE);
-       if (!xdr__lu_string(&outxdr, &name))
+       if (!xdr__lu_string(&outxdr, (_lu_string *)&name))
        {
                xdr_destroy(&outxdr);
-               return (NULL);
+               return NULL;
        }
 
-       datalen = MAX_INLINE_UNITS;
-       if (_lookup_one(_lu_port, proc, (unit *)namebuf,
-               xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, lookup_buf, &datalen)
+       datalen = 0;
+       lookup_buf = NULL;
+
+       if (_lookup_all(_lu_port, proc, (unit *)namebuf,
+               xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, &lookup_buf, &datalen)
                != KERN_SUCCESS)
        {
                xdr_destroy(&outxdr);
-               return (NULL);
+               return NULL;
        }
 
        xdr_destroy(&outxdr);
 
        datalen *= BYTES_PER_XDR_UNIT;
-       xdrmem_create(&inxdr, lookup_buf, datalen,
-               XDR_DECODE);
-       lu_p = NULL;
-       if (!xdr__lu_protoent_ptr(&inxdr, &lu_p) || (lu_p == NULL))
+       if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
+
+       xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
+
+       count = 0;
+       if (!xdr_int(&inxdr, &count))
+       {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
+       }
+
+       if (count == 0)
        {
                xdr_destroy(&inxdr);
-               return (NULL);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
        }
 
+       p = extract_protocol(&inxdr);
        xdr_destroy(&inxdr);
+       vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
 
-       convert_p(lu_p);
-       xdr_free(xdr__lu_protoent_ptr, &lu_p);
-       return (&global_p);
+       return p;
 }
 
 static void
 lu_endprotoent()
 {
-       p_nentries = 0;
-       if (p_data != NULL)
-       {
-               freeold();
-               vm_deallocate(mach_task_self(), (vm_address_t)p_data, p_datalen);
-               p_data = NULL;
-       }
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_service, free_lu_thread_info_protocol);
+       _lu_data_free_vm_xdr(tdata);
 }
 
 static void
 lu_setprotoent()
 {
        lu_endprotoent();
-       p_start = 1;
 }
 
+
 static struct protoent *
 lu_getprotoent()
 {
+       struct protoent *p;
        static int proc = -1;
-       _lu_protoent lu_p;
+       struct lu_thread_info *tdata;
 
-       if (p_start == 1)
+       tdata = _lu_data_create_key(_lu_data_key_protocol, free_lu_thread_info_protocol);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_protocol, tdata);
+       }
+\r
+       if (tdata->lu_vm == NULL)
        {
-               p_start = 0;
-
                if (proc < 0)
                {
                        if (_lookup_link(_lu_port, "getprotoent", &proc) != KERN_SUCCESS)
                        {
                                lu_endprotoent();
-                               return (NULL);
+                               return NULL;
                        }
                }
 
-               if (_lookup_all(_lu_port, proc, NULL, 0, &p_data, &p_datalen)
-                       != KERN_SUCCESS)
+               if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS)
                {
                        lu_endprotoent();
-                       return (NULL);
+                       return NULL;
                }
 
-#ifdef NOTDEF 
-/* NOTDEF because OOL buffers are counted in bytes with untyped IPC */  
-               p_datalen *= BYTES_PER_XDR_UNIT;
-#endif
-               xdrmem_create(&p_xdr, p_data, p_datalen,
-                       XDR_DECODE);
-               if (!xdr_int(&p_xdr, &p_nentries))
+               /* mig stubs measure size in words (4 bytes) */
+               tdata->lu_vm_length *= 4;
+
+               if (tdata->lu_xdr != NULL)
+               {
+                       xdr_destroy(tdata->lu_xdr);
+                       free(tdata->lu_xdr);
+               }
+               tdata->lu_xdr = (XDR *)calloc(1, sizeof(XDR));
+
+               xdrmem_create(tdata->lu_xdr, tdata->lu_vm, tdata->lu_vm_length, XDR_DECODE);
+               if (!xdr_int(tdata->lu_xdr, &tdata->lu_vm_cursor))
                {
-                       xdr_destroy(&p_xdr);
                        lu_endprotoent();
-                       return (NULL);
+                       return NULL;
                }
        }
 
-       if (p_nentries == 0)
+       if (tdata->lu_vm_cursor == 0)
        {
-               xdr_destroy(&p_xdr);
                lu_endprotoent();
-               return (NULL);
+               return NULL;
        }
 
-       bzero(&lu_p, sizeof(lu_p));
-       if (!xdr__lu_protoent(&p_xdr, &lu_p))
+       p = extract_protocol(tdata->lu_xdr);
+       if (p == NULL)
        {
-               xdr_destroy(&p_xdr);
                lu_endprotoent();
-               return (NULL);
+               return NULL;
        }
 
-       p_nentries--;
-       convert_p(&lu_p);
-       xdr_free(xdr__lu_protoent, &lu_p);
-       return (&global_p);
+       tdata->lu_vm_cursor--;
+       
+       return p;
 }
 
-struct protoent *
-getprotobynumber(int number)
+static struct protoent *
+getproto(const char *name, int number, int source)
 {
-       LOOKUP1(lu_getprotobynumber, _old_getprotobynumber, number,
-               struct protoent);
+       struct protoent *res = NULL;
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_protocol, free_lu_thread_info_protocol);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_protocol, tdata);
+       }
+
+       if (_lu_running())
+       {
+               switch (source)
+               {
+                       case PROTO_GET_NAME:
+                               res = lu_getprotobyname(name);
+                               break;
+                       case PROTO_GET_NUM:
+                               res = lu_getprotobynumber(number);
+                               break;
+                       case PROTO_GET_ENT:
+                               res = lu_getprotoent();
+                               break;
+                       default: res = NULL;
+               }
+       }
+       else
+       {
+               switch (source)
+               {
+                       case PROTO_GET_NAME:
+                               res = copy_protocol(_old_getprotobyname(name));
+                               break;
+                       case PROTO_GET_NUM:
+                               res = copy_protocol(_old_getprotobynumber(number));
+                               break;
+                       case PROTO_GET_ENT:
+                               res = copy_protocol(_old_getprotoent());
+                               break;
+                       default: res = NULL;
+               }
+       }
+
+       recycle_protocol(tdata, res);
+       return (struct protoent *)tdata->lu_entry;
 }
 
 struct protoent *
 getprotobyname(const char *name)
 {
-       LOOKUP1(lu_getprotobyname, _old_getprotobyname,  name, struct protoent);
+       return getproto(name, -2, PROTO_GET_NAME);
+}
+
+struct protoent *
+getprotobynumber(int number)
+{
+       return getproto(NULL, number, PROTO_GET_NUM);
 }
 
 struct protoent *
 getprotoent(void)
 {
-       GETENT(lu_getprotoent, _old_getprotoent, &p_state, struct protoent);
+       return getproto(NULL, -2, PROTO_GET_ENT);
 }
 
 void
 setprotoent(int stayopen)
 {
-       SETSTATE(lu_setprotoent, _old_setprotoent, &p_state, stayopen);
+       if (_lu_running()) lu_setprotoent();
+       else _old_setprotoent(stayopen);
 }
 
 void
 endprotoent(void)
 {
-       UNSETSTATE(lu_endprotoent, _old_endprotoent, &p_state);
+       if (_lu_running()) lu_endprotoent();
+       else _old_endprotoent();
 }
index 3bd94605366b57e86cfb24cf43037a1e2a87698a..368908768b24ae557def536ed1787c5ec525ecde 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <stdio.h>
 #include <string.h>
 #include <netinet/in.h>
+#include <pthread.h>
 
 #include "_lu_types.h"
 #include "lookup.h"
 #include "lu_utils.h"
 #include "lu_overrides.h"
 
-static lookup_state r_state = LOOKUP_CACHE;
-static struct rpcent global_r;
-static int global_free = 1;
-static char *r_data = NULL;
-static unsigned r_datalen;
-static int r_nentries;
-static int r_start = 1;
-static XDR r_xdr;
+static pthread_mutex_t _rpc_lock = PTHREAD_MUTEX_INITIALIZER;
+
+#define RPC_GET_NAME 1
+#define RPC_GET_NUM 2
+#define RPC_GET_ENT 3
 
 static void
-freeold(void)
+free_rpc_data(struct rpcent *r)
 {
        char **aliases;
 
-       if (global_free == 1) return;
+       if (r == NULL) return;
 
-       free(global_r.r_name);
+       if (r->r_name != NULL) free(r->r_name);
 
-       aliases = global_r.r_aliases;
+       aliases = r->r_aliases;
        if (aliases != NULL)
        {
                while (*aliases != NULL) free(*aliases++);
-               free(global_r.r_aliases);
+               free(r->r_aliases);
        }
+}
 
-       global_free = 1;
+static void
+free_rpc(struct rpcent *r)
+{
+       if (r == NULL) return;
+       free_rpc_data(r);
+       free(r);
 }
 
 static void
-convert_r(_lu_rpcent *lu_r)
+free_lu_thread_info_rpc(void *x)
+{
+       struct lu_thread_info *tdata;
+
+       if (x == NULL) return;
+
+       tdata = (struct lu_thread_info *)x;
+       
+       if (tdata->lu_entry != NULL)
+       {
+               free_rpc((struct rpcent *)tdata->lu_entry);
+               tdata->lu_entry = NULL;
+       }
+
+       _lu_data_free_vm_xdr(tdata);
+
+       free(tdata);
+}
+
+static struct rpcent *
+extract_rpc(XDR *xdr)
+{
+       struct rpcent *r;
+       int i, j, nvals, nkeys, status;
+       char *key, **vals;
+
+       if (xdr == NULL) return NULL;
+
+       if (!xdr_int(xdr, &nkeys)) return NULL;
+
+       r = (struct rpcent *)calloc(1, sizeof(struct rpcent));
+
+       for (i = 0; i < nkeys; i++)
+       {
+               key = NULL;
+               vals = NULL;
+               nvals = 0;
+
+               status = _lu_xdr_attribute(xdr, &key, &vals, &nvals);
+               if (status < 0)
+               {
+                       free_rpc(r);
+                       return NULL;
+               }
+
+               if (nvals == 0)
+               {
+                       free(key);
+                       continue;
+               }
+
+               j = 0;
+
+               if ((r->r_name == NULL) && (!strcmp("name", key)))
+               {
+                       r->r_name = vals[0];
+                       if (nvals > 1)
+                       {
+                               r->r_aliases = (char **)calloc(nvals, sizeof(char *));
+                               for (j = 1; j < nvals; j++) r->r_aliases[j-1] = vals[j];
+                       }
+                       j = nvals;
+               }               
+               else if (!strcmp("number", key))
+               {
+                       r->r_number= atoi(vals[0]);
+               }
+
+               free(key);
+               if (vals != NULL)
+               {
+                       for (; j < nvals; j++) free(vals[j]);
+                       free(vals);
+               }
+       }
+
+       if (r->r_name == NULL) r->r_name = strdup("");
+       if (r->r_aliases == NULL) r->r_aliases = (char **)calloc(1, sizeof(char *));
+
+       return r;
+}
+
+static struct rpcent *
+copy_rpc(struct rpcent *in)
 {
        int i, len;
+       struct rpcent *r;
 
-       freeold();
+       if (in == NULL) return NULL;
 
-       global_r.r_name = strdup(lu_r->r_names.r_names_val[0]);
+       r = (struct rpcent *)calloc(1, sizeof(struct rpcent));
 
-       len = lu_r->r_names.r_names_len - 1;
-       global_r.r_aliases = (char **)malloc((len + 1) * sizeof(char *));
+       r->r_name = LU_COPY_STRING(in->r_name);
 
-       for (i = 0; i < len; i++)
+       len = 0;
+       if (in->r_aliases != NULL)
        {
-               global_r.r_aliases[i] = strdup(lu_r->r_names.r_names_val[i+1]);
+               for (len = 0; in->r_aliases[len] != NULL; len++);
        }
 
-       global_r.r_aliases[len] = NULL;
+       r->r_aliases = (char **)calloc(len + 1, sizeof(char *));
+       for (i = 0; i < len; i++)
+       {
+               r->r_aliases[i] = strdup(in->r_aliases[i]);
+       }
 
-       global_r.r_number = lu_r->r_number;
+       r->r_number = in->r_number;
 
-       global_free = 0;
+       return r;
 }
 
+static void
+recycle_rpc(struct lu_thread_info *tdata, struct rpcent *in)
+{
+       struct rpcent *r;
+
+       if (tdata == NULL) return;
+       r = (struct rpcent *)tdata->lu_entry;
+
+       if (in == NULL)
+       {
+               free_rpc(r);
+               tdata->lu_entry = NULL;
+       }
+
+       if (tdata->lu_entry == NULL)
+       {
+               tdata->lu_entry = in;
+               return;
+       }
 
+       free_rpc_data(r);
+
+       r->r_name = in->r_name;
+       r->r_aliases = in->r_aliases;
+       r->r_number = in->r_number;
+
+       free(in);
+}
 
 static struct rpcent *
 lu_getrpcbynumber(long number)
 {
+       struct rpcent *r;
        unsigned datalen;
-       _lu_rpcent_ptr lu_r;
-       XDR xdr;
+       XDR inxdr;
        static int proc = -1;
-       unit lookup_buf[MAX_INLINE_UNITS];
-       
+       char *lookup_buf;
+       int count;
+
        if (proc < 0)
        {
                if (_lookup_link(_lu_port, "getrpcbynumber", &proc) != KERN_SUCCESS)
                {
-                       return (NULL);
+                       return NULL;
                }
        }
 
        number = htonl(number);
-       datalen = MAX_INLINE_UNITS;
-       if (_lookup_one(_lu_port, proc, (unit *)&number, 1, lookup_buf, &datalen)
+       datalen = 0;
+       lookup_buf = NULL;
+
+       if (_lookup_all(_lu_port, proc, (unit *)&number, 1, &lookup_buf, &datalen)
                != KERN_SUCCESS)
        {
-               return (NULL);
+               return NULL;
        }
 
        datalen *= BYTES_PER_XDR_UNIT;
-       xdrmem_create(&xdr, lookup_buf, datalen, XDR_DECODE);
-       lu_r = NULL;
-       if (!xdr__lu_rpcent_ptr(&xdr, &lu_r) || lu_r == NULL)
+       if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
+
+       xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
+
+       count = 0;
+       if (!xdr_int(&inxdr, &count))
        {
-               xdr_destroy(&xdr);
-               return (NULL);
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
+       }
+
+       if (count == 0)
+       {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
        }
 
-       xdr_destroy(&xdr);
+       r = extract_rpc(&inxdr);
+       xdr_destroy(&inxdr);
+       vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
 
-       convert_r(lu_r);
-       xdr_free(xdr__lu_rpcent_ptr, &lu_r);
-       return (&global_r);
+       return r;
 }
 
 static struct rpcent *
 lu_getrpcbyname(const char *name)
 {
+       struct rpcent *r;
        unsigned datalen;
        char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT];
-       XDR outxdr;
-       XDR inxdr;
-       _lu_rpcent_ptr lu_r;
+       XDR outxdr, inxdr;
        static int proc = -1;
-       unit lookup_buf[MAX_INLINE_UNITS];
+       char *lookup_buf;
+       int count;
 
        if (proc < 0)
        {
                if (_lookup_link(_lu_port, "getrpcbyname", &proc) != KERN_SUCCESS)
                {
-                       return (NULL);
+                       return NULL;
                }
        }
 
        xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE);
-       if (!xdr__lu_string(&outxdr, &name))
+       if (!xdr__lu_string(&outxdr, (_lu_string *)&name))
        {
                xdr_destroy(&outxdr);
-               return (NULL);
+               return NULL;
        }
 
-       datalen = MAX_INLINE_UNITS;
-       if (_lookup_one(_lu_port, proc, (unit *)namebuf,
-               xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, lookup_buf, &datalen)
+       datalen = 0;
+       lookup_buf = NULL;
+
+       if (_lookup_all(_lu_port, proc, (unit *)namebuf,
+               xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, &lookup_buf, &datalen)
                != KERN_SUCCESS)
        {
                xdr_destroy(&outxdr);
-               return (NULL);
+               return NULL;
        }
 
        xdr_destroy(&outxdr);
 
        datalen *= BYTES_PER_XDR_UNIT;
-       xdrmem_create(&inxdr, lookup_buf, datalen, 
-               XDR_DECODE);
-       lu_r = NULL;
-       if (!xdr__lu_rpcent_ptr(&inxdr, &lu_r) || (lu_r == NULL))
+       if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
+
+       xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
+
+       count = 0;
+       if (!xdr_int(&inxdr, &count))
+       {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
+       }
+
+       if (count == 0)
        {
                xdr_destroy(&inxdr);
-               return (NULL);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
        }
 
+       r = extract_rpc(&inxdr);
        xdr_destroy(&inxdr);
+       vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
 
-       convert_r(lu_r);
-       xdr_free(xdr__lu_rpcent_ptr, &lu_r);
-       return (&global_r);
+       return r;
 }
 
 static void
 lu_endrpcent(void)
 {
-       r_nentries = 0;
-       if (r_data != NULL)
-       {
-               freeold();
-               vm_deallocate(mach_task_self(), (vm_address_t)r_data, r_datalen);
-               r_data = NULL;
-       }
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_rpc, free_lu_thread_info_rpc);
+       _lu_data_free_vm_xdr(tdata);
 }
 
-static int
-lu_setrpcent(int stayopen)
+static void
+lu_setrpcent()
 {
        lu_endrpcent();
-       r_start = 1;
-       return (1);
 }
 
 static struct rpcent *
 lu_getrpcent()
 {
+       struct rpcent *r;
        static int proc = -1;
-       _lu_rpcent lu_r;
+       struct lu_thread_info *tdata;
 
-       if (r_start == 1)
+       tdata = _lu_data_create_key(_lu_data_key_rpc, free_lu_thread_info_rpc);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_rpc, tdata);
+       }
+\r
+       if (tdata->lu_vm == NULL)
        {
-               r_start = 0;
-
                if (proc < 0)
                {
                        if (_lookup_link(_lu_port, "getrpcent", &proc) != KERN_SUCCESS)
                        {
                                lu_endrpcent();
-                               return (NULL);
+                               return NULL;
                        }
                }
 
-               if (_lookup_all(_lu_port, proc, NULL, 0, &r_data, &r_datalen)
-                       != KERN_SUCCESS)
+               if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS)
                {
                        lu_endrpcent();
-                       return (NULL);
+                       return NULL;
                }
 
-#ifdef NOTDEF
-/* NOTDEF because OOL buffers are counted in bytes with untyped IPC */
-               r_datalen *= BYTES_PER_XDR_UNIT;
-#endif
+               /* mig stubs measure size in words (4 bytes) */
+               tdata->lu_vm_length *= 4;
 
-               xdrmem_create(&r_xdr, r_data, r_datalen,
-                       XDR_DECODE);
-               if (!xdr_int(&r_xdr, &r_nentries))
+               if (tdata->lu_xdr != NULL)
+               {
+                       xdr_destroy(tdata->lu_xdr);
+                       free(tdata->lu_xdr);
+               }
+               tdata->lu_xdr = (XDR *)calloc(1, sizeof(XDR));
+
+               xdrmem_create(tdata->lu_xdr, tdata->lu_vm, tdata->lu_vm_length, XDR_DECODE);
+               if (!xdr_int(tdata->lu_xdr, &tdata->lu_vm_cursor))
                {
-                       xdr_destroy(&r_xdr);
                        lu_endrpcent();
-                       return (NULL);
+                       return NULL;
                }
        }
 
-       if (r_nentries == 0)
+       if (tdata->lu_vm_cursor == 0)
        {
-               xdr_destroy(&r_xdr);
                lu_endrpcent();
-               return (NULL);
+               return NULL;
        }
 
-       bzero(&lu_r, sizeof(lu_r));
-       if (!xdr__lu_rpcent(&r_xdr, &lu_r))
+       r = extract_rpc(tdata->lu_xdr);
+       if (r == NULL)
        {
-               xdr_destroy(&r_xdr);
                lu_endrpcent();
-               return (NULL);
+               return NULL;
        }
 
-       r_nentries--;
-       convert_r(&lu_r);
-       xdr_free(xdr__lu_rpcent, &lu_r);
-       return (&global_r);
+       tdata->lu_vm_cursor--;
+       
+       return r;
 }
 
-struct rpcent *
-getrpcbynumber(long number)
+static struct rpcent *
+getrpc(const char *name, long number, int source)
 {
-       LOOKUP1(lu_getrpcbynumber, _old_getrpcbynumber, number, struct rpcent);
+       struct rpcent *res = NULL;
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_rpc, free_lu_thread_info_rpc);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_rpc, tdata);
+       }
+
+       if (_lu_running())
+       {
+               switch (source)
+               {
+                       case RPC_GET_NAME:
+                               res = lu_getrpcbyname(name);
+                               break;
+                       case RPC_GET_NUM:
+                               res = lu_getrpcbynumber(number);
+                               break;
+                       case RPC_GET_ENT:
+                               res = lu_getrpcent();
+                               break;
+                       default: res = NULL;
+               }
+       }
+       else
+       {
+               pthread_mutex_lock(&_rpc_lock);
+               switch (source)
+               {
+                       case RPC_GET_NAME:
+                               res = copy_rpc(_old_getrpcbyname(name));
+                               break;
+                       case RPC_GET_NUM:
+                               res = copy_rpc(_old_getrpcbynumber(number));
+                               break;
+                       case RPC_GET_ENT:
+                               res = copy_rpc(_old_getrpcent());
+                               break;
+                       default: res = NULL;
+               }
+               pthread_mutex_unlock(&_rpc_lock);
+       }
+
+       recycle_rpc(tdata, res);
+       return (struct rpcent *)tdata->lu_entry;
 }
 
 struct rpcent *
 getrpcbyname(const char *name)
 {
-       LOOKUP1(lu_getrpcbyname, _old_getrpcbyname, name, struct rpcent);
+       return getrpc(name, -2, RPC_GET_NAME);
+}
+
+struct rpcent *
+getrpcbynumber(long number)
+{
+       return getrpc(NULL, number, RPC_GET_NUM);
 }
 
 struct rpcent *
 getrpcent(void)
 {
-       GETENT(lu_getrpcent, _old_getrpcent, &r_state, struct rpcent);
+       return getrpc(NULL, -2, RPC_GET_ENT);
 }
 
 void
 setrpcent(int stayopen)
 {
-       SETSTATE(lu_setrpcent, _old_setrpcent, &r_state, stayopen);
+       if (_lu_running()) lu_setrpcent();
+       else _old_setrpcent(stayopen);
 }
 
 void
 endrpcent(void)
 {
-       UNSETSTATE(lu_endrpcent, _old_endrpcent, &r_state);
+       if (_lu_running()) lu_endrpcent();
+       else _old_endrpcent();
 }
index 4dc60e59dbafe0d3f5e35cb13f09f8085685219e..7d7367790d9c86b1afd0177e7e47c7f5dd6bf06b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <mach/mach.h>
 #include <stdio.h>
 #include <string.h>
-#include "lookup.h"
 #include <rpc/types.h>
 #include <rpc/xdr.h>
-#include "_lu_types.h"
 #include <netdb.h>
+#include <netinet/in.h>
+#include <pthread.h>
+
+#include "_lu_types.h"
+#include "lookup.h"
 #include "lu_utils.h"
-#import <netinet/in.h>
+
+static pthread_mutex_t _service_lock = PTHREAD_MUTEX_INITIALIZER;
+
+#define S_GET_NAME 1
+#define S_GET_PORT 2
+#define S_GET_ENT 3
 
 extern struct servent *_old_getservbyport();
 extern struct servent *_old_getservbyname();
@@ -44,285 +52,503 @@ extern void _old_setservent();
 extern void _old_endservent();
 extern void _old_setservfile();
 
-static lookup_state s_state = LOOKUP_CACHE;
-static struct servent global_s;
-static int global_free = 1;
-static char *s_data = NULL;
-static unsigned s_datalen;
-static int s_nentries;
-static int s_start = 1;
-static XDR s_xdr;
-
 static void
-freeold(void)
+free_service_data(struct servent *s)
 {
        char **aliases;
 
-       if (global_free == 1) return;
+       if (s == NULL) return;
 
-       if (global_s.s_name != NULL) free(global_s.s_name);
-       global_s.s_name = NULL;
+       if (s->s_name != NULL) free(s->s_name);
+       if (s->s_proto != NULL) free(s->s_proto);
 
-       if (global_s.s_proto != NULL) free(global_s.s_proto);
-       global_s.s_proto = NULL;
-
-       aliases = global_s.s_aliases;
+       aliases = s->s_aliases;
        if (aliases != NULL)
        {
                while (*aliases != NULL) free(*aliases++);
-               free(global_s.s_aliases);
-               global_s.s_aliases = NULL;
+               free(s->s_aliases);
        }
+}
 
-       global_free = 1;
+static void
+free_service(struct servent *s)
+{
+       if (s == NULL) return;
+       free_service_data(s);
+       free(s);
 }
 
 static void
-convert_s(_lu_servent *lu_s)
+free_lu_thread_info_service(void *x)
+{
+       struct lu_thread_info *tdata;
+
+       if (x == NULL) return;
+
+       tdata = (struct lu_thread_info *)x;
+       
+       if (tdata->lu_entry != NULL)
+       {
+               free_service((struct servent *)tdata->lu_entry);
+               tdata->lu_entry = NULL;
+       }
+
+       _lu_data_free_vm_xdr(tdata);
+
+       free(tdata);
+}
+
+static struct servent *
+extract_service(XDR *xdr, const char *proto)
+{
+       struct servent *s;
+       int i, j, nvals, nkeys, status;
+       char *key, **vals;
+
+       if (xdr == NULL) return NULL;
+
+       if (!xdr_int(xdr, &nkeys)) return NULL;
+
+       s = (struct servent *)calloc(1, sizeof(struct servent));
+
+       for (i = 0; i < nkeys; i++)
+       {
+               key = NULL;
+               vals = NULL;
+               nvals = 0;
+
+               status = _lu_xdr_attribute(xdr, &key, &vals, &nvals);
+               if (status < 0)
+               {
+                       free_service(s);
+                       return NULL;
+               }
+
+               if (nvals == 0)
+               {
+                       free(key);
+                       continue;
+               }
+
+               j = 0;
+
+               if ((s->s_name == NULL) && (!strcmp("name", key)))
+               {
+                       s->s_name = vals[0];
+                       if (nvals > 1)
+                       {
+                               s->s_aliases = (char **)calloc(nvals, sizeof(char *));
+                               for (j = 1; j < nvals; j++) s->s_aliases[j-1] = vals[j];
+                       }
+                       j = nvals;
+               }               
+               else if ((s->s_proto == NULL) && (!strcmp("protocol", key)))
+               {
+                       if ((proto == NULL) || (proto[0] == '\0'))
+                       {
+                               s->s_proto = vals[0];
+                               j = 1;
+                       }
+                       else
+                       {
+                               s->s_proto = strdup(proto);
+                       }
+               }
+               else if ((s->s_port == 0) && (!strcmp("port", key)))
+               {
+                       s->s_port = htons(atoi(vals[0]));
+               }
+               
+               free(key);
+               if (vals != NULL)
+               {
+                       for (; j < nvals; j++) free(vals[j]);
+                       free(vals);
+               }
+       }
+
+       if (s->s_name == NULL) s->s_name = strdup("");
+       if (s->s_proto == NULL) s->s_proto = strdup("");
+       if (s->s_aliases == NULL) s->s_aliases = (char **)calloc(1, sizeof(char *));
+
+       return s;
+}
+
+static struct servent *
+copy_service(struct servent *in)
 {
        int i, len;
+       struct servent *s;
 
-       freeold();
+       if (in == NULL) return NULL;
 
-       global_s.s_name = strdup(lu_s->s_names.s_names_val[0]);
+       s = (struct servent *)calloc(1, sizeof(struct servent));
 
-       len = lu_s->s_names.s_names_len - 1;
-       global_s.s_aliases = (char **)malloc((len + 1) * sizeof(char *));
+       s->s_name = LU_COPY_STRING(in->s_name);
 
+       len = 0;
+       if (in->s_aliases != NULL)
+       {
+               for (len = 0; in->s_aliases[len] != NULL; len++);
+       }
+
+       s->s_aliases = (char **)calloc(len + 1, sizeof(char *));
        for (i = 0; i < len; i++)
        {
-               global_s.s_aliases[i] = strdup(lu_s->s_names.s_names_val[i+1]);
+               s->s_aliases[i] = strdup(in->s_aliases[i]);
+       }
+
+       s->s_proto = LU_COPY_STRING(in->s_proto);
+       s->s_port = in->s_port;
+
+       return s;
+}
+
+static void
+recycle_service(struct lu_thread_info *tdata, struct servent *in)
+{
+       struct servent *s;
+
+       if (tdata == NULL) return;
+       s = (struct servent *)tdata->lu_entry;
+
+       if (in == NULL)
+       {
+               free_service(s);
+               tdata->lu_entry = NULL;
+       }
+
+       if (tdata->lu_entry == NULL)
+       {
+               tdata->lu_entry = in;
+               return;
        }
 
-       global_s.s_aliases[len] = NULL;
+       free_service_data(s);
 
-       if (lu_s->s_proto != NULL) global_s.s_proto = strdup(lu_s->s_proto);
-       global_s.s_port = lu_s->s_port;
+       s->s_name = in->s_name;
+       s->s_aliases = in->s_aliases;
+       s->s_proto = in->s_proto;
+       s->s_port = in->s_port;
 
-       global_free = 0;
+       free(in);
 }
 
 static struct servent *
 lu_getservbyport(int port, const char *proto)
 {
-       unsigned datalen;
-       _lu_servent_ptr lu_s;
-       XDR xdr;
+       struct servent *s;
+       unsigned int datalen;
+       XDR outxdr, inxdr;
        static int proc = -1;
        char output_buf[_LU_MAXLUSTRLEN + 3 * BYTES_PER_XDR_UNIT];
-       unit lookup_buf[MAX_INLINE_UNITS];
-       XDR outxdr;
+       char *lookup_buf;
+       int count;
 
        if (proc < 0)
        {
                if (_lookup_link(_lu_port, "getservbyport", &proc) != KERN_SUCCESS)
                {
-                       return (NULL);
+                       return NULL;
                }
        }
 
        /* Encode NULL for xmission to lookupd. */
-       if (!proto) proto = ""; 
+       if (proto == NULL) proto = "";  
 
        xdrmem_create(&outxdr, output_buf, sizeof(output_buf), XDR_ENCODE);
-       if (!xdr_int(&outxdr, &port) || !xdr__lu_string(&outxdr, &proto))
+       if (!xdr_int(&outxdr, &port) || !xdr__lu_string(&outxdr, (_lu_string *)&proto))
        {
                xdr_destroy(&outxdr);
-               return (NULL);
+               return NULL;
        }
 
-       datalen = MAX_INLINE_UNITS;
-       if (_lookup_one(_lu_port, proc, (unit *)output_buf, 
-               xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT,  lookup_buf, &datalen)
+       datalen = 0;
+       lookup_buf = NULL;
+
+       if (_lookup_all(_lu_port, proc, (unit *)output_buf, 
+               xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, &lookup_buf, &datalen)
                != KERN_SUCCESS)
        {
                xdr_destroy(&outxdr);
-               return (NULL);
+               return NULL;
        }
 
        xdr_destroy(&outxdr);
 
        datalen *= BYTES_PER_XDR_UNIT;
-       xdrmem_create(&xdr, lookup_buf, datalen, XDR_DECODE);
-       lu_s = NULL;
-       if (!xdr__lu_servent_ptr(&xdr, &lu_s) || (lu_s == NULL))
+       if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
+
+       xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
+
+       count = 0;
+       if (!xdr_int(&inxdr, &count))
+       {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
+       }
+
+       if (count == 0)
        {
-               xdr_destroy(&xdr);
-               return (NULL);
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
        }
 
-       xdr_destroy(&xdr);
+       /*
+        * lookupd will only send back a reply for a service with the protocol specified
+        * if it finds a match.  We pass the protocol name to extract_service, which
+        * copies the requested protocol name into the returned servent.  This is a
+        * bit of a kludge, but since NetInfo / lookupd treat services as single entities
+        * with multiple protocols, we are forced to do some special-case handling. 
+        */
+       s = extract_service(&inxdr, proto);
+       xdr_destroy(&inxdr);
+       vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
 
-       convert_s(lu_s);
-       xdr_free(xdr__lu_servent_ptr, &lu_s);
-       return (&global_s);
+       return s;
 }
 
 static struct servent *
 lu_getservbyname(const char *name, const char *proto)
 {
-       unsigned datalen;
-       unit lookup_buf[MAX_INLINE_UNITS];
+       struct servent *s;
+       unsigned int datalen;
+       char *lookup_buf;
        char output_buf[2 * (_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT)];
-       XDR outxdr;
-       XDR inxdr;
-       _lu_servent_ptr lu_s;
+       XDR outxdr, inxdr;
        static int proc = -1;
+       int count;
 
        if (proc < 0)
        {
                if (_lookup_link(_lu_port, "getservbyname", &proc) != KERN_SUCCESS)
                {
-                   return (NULL);
+                   return NULL;
                }
        }
 
        /* Encode NULL for xmission to lookupd. */
-       if (!proto) proto = "";
+       if (proto == NULL) proto = "";
 
        xdrmem_create(&outxdr, output_buf, sizeof(output_buf), XDR_ENCODE);
-       if (!xdr__lu_string(&outxdr, &name) || !xdr__lu_string(&outxdr, &proto))
+       if (!xdr__lu_string(&outxdr, (_lu_string *)&name) ||
+           !xdr__lu_string(&outxdr, (_lu_string *)&proto))
        {
                xdr_destroy(&outxdr);
-               return (NULL);
+               return NULL;
        }
 
-       datalen = MAX_INLINE_UNITS;
-       if (_lookup_one(_lu_port, proc, (unit *)output_buf,
-               xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, lookup_buf, &datalen)
+       datalen = 0;
+       lookup_buf = NULL;
+
+       if (_lookup_all(_lu_port, proc, (unit *)output_buf,
+               xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, &lookup_buf, &datalen)
                != KERN_SUCCESS)
        {
                xdr_destroy(&outxdr);
-               return (NULL);
+               return NULL;
        }
 
        xdr_destroy(&outxdr);
 
        datalen *= BYTES_PER_XDR_UNIT;
-       xdrmem_create(&inxdr, lookup_buf, datalen,
-               XDR_DECODE);
-       lu_s = NULL;
-       if (!xdr__lu_servent_ptr(&inxdr, &lu_s) || (lu_s == NULL))
+       if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
+
+       xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
+
+       count = 0;
+       if (!xdr_int(&inxdr, &count))
+       {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
+       }
+
+       if (count == 0)
        {
                xdr_destroy(&inxdr);
-               return (NULL);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
        }
 
+       /*
+        * lookupd will only send back a reply for a service with the protocol specified
+        * if it finds a match.  We pass the protocol name to extract_service, which
+        * copies the requested protocol name into the returned servent.  This is a
+        * bit of a kludge, but since NetInfo / lookupd treat services as single entities
+        * with multiple protocols, we are forced to do some special-case handling. 
+        */
+       s = extract_service(&inxdr, proto);
        xdr_destroy(&inxdr);
+       vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
 
-       convert_s(lu_s);
-       xdr_free(xdr__lu_servent_ptr, &lu_s);
-       return (&global_s);
+       return s;
 }
 
 static void
 lu_endservent()
 {
-       s_nentries = 0;
-       if (s_data != NULL)
-       {
-               freeold();
-               vm_deallocate(mach_task_self(), (vm_address_t)s_data, s_datalen);
-               s_data = NULL;
-       }
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_service, free_lu_thread_info_service);
+       _lu_data_free_vm_xdr(tdata);
 }
 
 static void
 lu_setservent()
 {
        lu_endservent();
-       s_start = 1;
 }
 
 static struct servent *
 lu_getservent()
 {
+       struct servent *s;
        static int proc = -1;
-       _lu_servent lu_s;
+       struct lu_thread_info *tdata;
 
-       if (s_start == 1)
+       tdata = _lu_data_create_key(_lu_data_key_service, free_lu_thread_info_service);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_service, tdata);
+       }
+\r
+       if (tdata->lu_vm == NULL)
        {
-               s_start = 0;
-
                if (proc < 0)
                {
                        if (_lookup_link(_lu_port, "getservent", &proc) != KERN_SUCCESS)
                        {
                                lu_endservent();
-                               return (NULL);
+                               return NULL;
                        }
                }
 
-               if (_lookup_all(_lu_port, proc, NULL, 0, &s_data, &s_datalen)
-                       != KERN_SUCCESS)
+               if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS)
                {
                        lu_endservent();
-                       return (NULL);
+                       return NULL;
                }
 
-#ifdef NOTDEF
-/* NOTDEF because OOL buffers are counted in bytes with untyped IPC */
-               s_datalen *= BYTES_PER_XDR_UNIT;
-#endif
+               /* mig stubs measure size in words (4 bytes) */
+               tdata->lu_vm_length *= 4;
+
+               if (tdata->lu_xdr != NULL)
+               {
+                       xdr_destroy(tdata->lu_xdr);
+                       free(tdata->lu_xdr);
+               }
+               tdata->lu_xdr = (XDR *)calloc(1, sizeof(XDR));
 
-               xdrmem_create(&s_xdr, s_data, s_datalen,
-                       XDR_DECODE);
-               if (!xdr_int(&s_xdr, &s_nentries))
+               xdrmem_create(tdata->lu_xdr, tdata->lu_vm, tdata->lu_vm_length, XDR_DECODE);
+               if (!xdr_int(tdata->lu_xdr, &tdata->lu_vm_cursor))
                {
-                       xdr_destroy(&s_xdr);
                        lu_endservent();
-                       return (NULL);
+                       return NULL;
                }
        }
 
-       if (s_nentries == 0)
+       if (tdata->lu_vm_cursor == 0)
        {
-               xdr_destroy(&s_xdr);
                lu_endservent();
-               return (NULL);
+               return NULL;
        }
 
-       bzero(&lu_s, sizeof(lu_s));
-       if (!xdr__lu_servent(&s_xdr, &lu_s))
+       s = extract_service(tdata->lu_xdr, NULL);
+       if (s == NULL)
        {
-               xdr_destroy(&s_xdr);
                lu_endservent();
-               return (NULL);
+               return NULL;
+       }
+
+       tdata->lu_vm_cursor--;
+       
+       return s;
+}
+
+static struct servent *
+getserv(const char *name, const char *proto, int port, int source)
+{
+       struct servent *res = NULL;
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_service, free_lu_thread_info_service);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_service, tdata);
+       }
+
+       if (_lu_running())
+       {
+               switch (source)
+               {
+                       case S_GET_NAME:
+                               res = lu_getservbyname(name, proto);
+                               break;
+                       case S_GET_PORT:
+                               res = lu_getservbyport(port, proto);
+                               break;
+                       case S_GET_ENT:
+                               res = lu_getservent();
+                               break;
+                       default: res = NULL;
+               }
+       }
+       else
+       {
+               pthread_mutex_lock(&_service_lock);
+               switch (source)
+               {
+                       case S_GET_NAME:
+                               res = copy_service(_old_getservbyname(name, proto));
+                               break;
+                       case S_GET_PORT:
+                               res = copy_service(_old_getservbyport(port, proto));
+                               break;
+                       case S_GET_ENT:
+                               res = copy_service(_old_getservent());
+                               break;
+                       default: res = NULL;
+               }
+               pthread_mutex_unlock(&_service_lock);
        }
 
-       s_nentries--;
-       convert_s(&lu_s);
-       xdr_free(xdr__lu_servent, &lu_s);
-       return (&global_s);
+       recycle_service(tdata, res);
+       return (struct servent *)tdata->lu_entry;
 }
 
 struct servent *
 getservbyport(int port, const char *proto)
 {
-       LOOKUP2(lu_getservbyport, _old_getservbyport, port, proto, struct servent);
+       return getserv(NULL, proto, port, S_GET_PORT);
 }
 
 struct servent *
 getservbyname(const char *name, const char *proto)
 {
-       LOOKUP2(lu_getservbyname, _old_getservbyname, name, proto,
-               struct servent);
+       return getserv(name, proto, 0, S_GET_NAME);
 }
 
 struct servent *
 getservent(void)
 {
-       GETENT(lu_getservent, _old_getservent, &s_state, struct servent);
+       return getserv(NULL, NULL, 0, S_GET_ENT);
 }
 
 void
 setservent(int stayopen)
 {
-       SETSTATE(lu_setservent, _old_setservent, &s_state, stayopen);
+       if (_lu_running()) lu_setservent();
+       else _old_setservent();
 }
 
 void
 endservent(void)
 {
-       UNSETSTATE(lu_endservent, _old_endservent, &s_state);
+       if (_lu_running()) lu_endservent();
+       else _old_endservent();
 }
index ecf36f6a44c9c11e42081a926ddcac06d4bca92d..c9276705d05d96aa5e3817d9232e56f31a397bfb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <rpc/xdr.h>
 #include <pwd.h>
 #include <netinet/in.h>
+#include <pthread.h>
+#include <unistd.h>
 
 #include "_lu_types.h"
 #include "lookup.h"
 #include "lu_utils.h"
 #include "lu_overrides.h"
 
-static lookup_state pw_state = LOOKUP_CACHE;
-static struct passwd global_pw;
-static int global_free = 1;
-static char *pw_data = NULL;
-static unsigned pw_datalen;
-static int pw_nentries;
-static int pw_start = 1;
-static XDR pw_xdr;
+static pthread_mutex_t _user_lock = PTHREAD_MUTEX_INITIALIZER;
+
+#define PW_GET_NAME 1
+#define PW_GET_UID 2
+#define PW_GET_ENT 3
 
 static void
-freeold(void)
+free_user_data(struct passwd *p)
 {
-       if (global_free == 1) return;
-
-       free(global_pw.pw_name);
-       free(global_pw.pw_passwd);
-       free(global_pw.pw_class);
-       free(global_pw.pw_gecos);
-       free(global_pw.pw_dir);
-       free(global_pw.pw_shell);
+       if (p == NULL) return;
+
+       if (p->pw_name != NULL) free(p->pw_name);
+       if (p->pw_passwd != NULL) free(p->pw_passwd);
+       if (p->pw_class != NULL) free(p->pw_class);
+       if (p->pw_gecos != NULL) free(p->pw_gecos);
+       if (p->pw_dir != NULL) free(p->pw_dir);
+       if (p->pw_shell != NULL) free(p->pw_shell);
+}
 
-       global_free = 1;
+static void
+free_user(struct passwd *p)
+{
+       if (p == NULL) return;
+       free_user_data(p);
+       free(p);
 }
 
 static void
-convert_pw(_lu_passwd *lu_pw)
+free_lu_thread_info_user(void *x)
 {
-       freeold();
-
-       global_pw.pw_name = strdup(lu_pw->pw_name);
-       global_pw.pw_passwd = strdup(lu_pw->pw_passwd);
-       global_pw.pw_uid = lu_pw->pw_uid;
-       global_pw.pw_gid = lu_pw->pw_gid;
-       global_pw.pw_change = lu_pw->pw_change;
-       global_pw.pw_class = strdup(lu_pw->pw_class);
-       global_pw.pw_gecos = strdup(lu_pw->pw_gecos);
-       global_pw.pw_dir = strdup(lu_pw->pw_dir);
-       global_pw.pw_shell = strdup(lu_pw->pw_shell);
-       global_pw.pw_expire = lu_pw->pw_expire;
-
-       global_free = 0;
+       struct lu_thread_info *tdata;
+
+       if (x == NULL) return;
+
+       tdata = (struct lu_thread_info *)x;
+       
+       if (tdata->lu_entry != NULL)
+       {
+               free_user((struct passwd *)tdata->lu_entry);
+               tdata->lu_entry = NULL;
+       }
+
+       _lu_data_free_vm_xdr(tdata);
+
+       free(tdata);
 }
 
 static struct passwd *
-lu_getpwuid(int uid)
+extract_user(XDR *xdr)
 {
-       unsigned datalen;
-       _lu_passwd_ptr lu_pw;
-       XDR xdr;
-       static int proc = -1;
-       unit lookup_buf[MAX_INLINE_UNITS];
-       
-       if (proc < 0)
+       int i, j, nvals, nkeys, status;
+       char *key, **vals;
+       struct passwd *p;
+
+       if (xdr == NULL) return NULL;
+
+       if (!xdr_int(xdr, &nkeys)) return NULL;
+
+       p = (struct passwd *)calloc(1, sizeof(struct passwd));
+
+       p->pw_uid = -2;
+       p->pw_gid = -2;
+
+       for (i = 0; i < nkeys; i++)
        {
-               if (_lookup_link(_lu_port, "getpwuid_A", &proc) != KERN_SUCCESS)
+               key = NULL;
+               vals = NULL;
+               nvals = 0;
+
+               status = _lu_xdr_attribute(xdr, &key, &vals, &nvals);
+               if (status < 0)
+               {
+                       free_user(p);
+                       return NULL;
+               }
+
+               if (nvals == 0)
+               {
+                       free(key);
+                       continue;
+               }
+
+               j = 0;
+
+               if ((p->pw_name == NULL) && (!strcmp("name", key)))
+               {
+                       p->pw_name = vals[0];
+                       j = 1;
+               }
+               else if ((p->pw_passwd == NULL) && (!strcmp("passwd", key)))
+               {
+                       p->pw_passwd = vals[0];
+                       j = 1;
+               }
+               else if ((p->pw_class == NULL) && (!strcmp("class", key)))
                {
-                       return (NULL);
+                       p->pw_class = vals[0];
+                       j = 1;
+               }
+               else if ((p->pw_gecos == NULL) && (!strcmp("realname", key)))
+               {
+                       p->pw_gecos = vals[0];
+                       j = 1;
+               }
+               else if ((p->pw_dir == NULL) && (!strcmp("home", key)))
+               {
+                       p->pw_dir = vals[0];
+                       j = 1;
+               }
+               else if ((p->pw_shell == NULL) && (!strcmp("shell", key)))
+               {
+                       p->pw_shell = vals[0];
+                       j = 1;
+               }
+               else if ((p->pw_uid == -2) && (!strcmp("uid", key)))
+               {
+                       p->pw_uid = atoi(vals[0]);
+               }
+               else if ((p->pw_gid == -2) && (!strcmp("gid", key)))
+               {
+                       p->pw_gid = atoi(vals[0]);
+               }
+               else if (!strcmp("change", key))
+               {
+                       p->pw_change = atoi(vals[0]);
+               }               
+               else if (!strcmp("expire", key))
+               {
+                       p->pw_expire = atoi(vals[0]);
+               }
+
+               free(key);
+               if (vals != NULL)
+               {
+                       for (; j < nvals; j++) free(vals[j]);
+                       free(vals);
                }
        }
 
-       uid = htonl(uid);
-       datalen = MAX_INLINE_UNITS;
-       if (_lookup_one(_lu_port, proc, (unit *)&uid, 1, lookup_buf, &datalen)
-               != KERN_SUCCESS)
+       if (p->pw_name == NULL) p->pw_name = strdup("");
+       if (p->pw_passwd == NULL) p->pw_passwd = strdup("");
+       if (p->pw_class == NULL) p->pw_class = strdup("");
+       if (p->pw_gecos == NULL) p->pw_gecos = strdup("");
+       if (p->pw_dir == NULL) p->pw_dir = strdup("");
+       if (p->pw_shell == NULL) p->pw_shell = strdup("");
+
+       return p;
+}
+
+static struct passwd *
+copy_user(struct passwd *in)
+{
+       struct passwd *p;
+
+       if (in == NULL) return NULL;
+
+       p = (struct passwd *)calloc(1, sizeof(struct passwd));
+
+       p->pw_name = LU_COPY_STRING(in->pw_name);
+       p->pw_passwd = LU_COPY_STRING(in->pw_passwd);
+       p->pw_uid = in->pw_uid;
+       p->pw_gid = in->pw_gid;
+       p->pw_change = in->pw_change;
+       p->pw_class = LU_COPY_STRING(in->pw_class);
+       p->pw_gecos = LU_COPY_STRING(in->pw_gecos);
+       p->pw_dir = LU_COPY_STRING(in->pw_dir);
+       p->pw_shell = LU_COPY_STRING(in->pw_shell);
+       p->pw_expire = in->pw_expire;
+
+       return p;
+}
+
+static int
+copy_user_r(struct passwd *in, struct passwd *out, char *buffer, int buflen)
+{
+       int hsize;
+       char *bp;
+
+       if (in == NULL) return -1;
+       if (out == NULL) return -1;
+
+       if (buffer == NULL) buflen = 0;
+
+       /* Calculate size of input */
+       hsize = 0;
+       if (in->pw_name != NULL) hsize += strlen(in->pw_name);
+       if (in->pw_passwd != NULL) hsize += strlen(in->pw_passwd);
+       if (in->pw_class != NULL) hsize += strlen(in->pw_class);
+       if (in->pw_gecos != NULL) hsize += strlen(in->pw_gecos);
+       if (in->pw_dir != NULL) hsize += strlen(in->pw_dir);
+       if (in->pw_shell != NULL) hsize += strlen(in->pw_shell);
+
+       /* Check buffer space */
+       if (hsize > buflen) return -1;
+
+       /* Copy result into caller's struct passwd, using buffer for memory */
+       bp = buffer;
+
+       out->pw_name = NULL;
+       if (in->pw_name != NULL)
        {
-               return (NULL);
+               out->pw_name = bp;
+               hsize = strlen(in->pw_name) + 1;
+               memmove(bp, in->pw_name, hsize);
+               bp += hsize;
        }
 
-       datalen *= BYTES_PER_XDR_UNIT;
-       xdrmem_create(&xdr, lookup_buf, datalen, XDR_DECODE);
-       lu_pw = NULL;
-       if (!xdr__lu_passwd_ptr(&xdr, &lu_pw) || (lu_pw == NULL))
+       out->pw_passwd = NULL;
+       if (in->pw_passwd != NULL)
        {
-               xdr_destroy(&xdr);
-               return (NULL);
+               out->pw_passwd = bp;
+               hsize = strlen(in->pw_passwd) + 1;
+               memmove(bp, in->pw_passwd, hsize);
+               bp += hsize;
        }
 
-       xdr_destroy(&xdr);
+       out->pw_uid = in->pw_uid;
 
-       convert_pw(lu_pw);
-       xdr_free(xdr__lu_passwd_ptr, &lu_pw);
-       return (&global_pw);
+       out->pw_gid = in->pw_gid;
+
+       out->pw_change = in->pw_change;
+
+       out->pw_class = NULL;
+       if (in->pw_class != NULL)
+       {
+               out->pw_class = bp;
+               hsize = strlen(in->pw_class) + 1;
+               memmove(bp, in->pw_class, hsize);
+               bp += hsize;
+       }
+
+       out->pw_gecos = NULL;
+       if (in->pw_gecos != NULL)
+       {
+               out->pw_gecos = bp;
+               hsize = strlen(in->pw_gecos) + 1;
+               memmove(bp, in->pw_gecos, hsize);
+               bp += hsize;
+       }
+
+       out->pw_dir = NULL;
+       if (in->pw_dir != NULL)
+       {
+               out->pw_dir = bp;
+               hsize = strlen(in->pw_dir) + 1;
+               memmove(bp, in->pw_dir, hsize);
+               bp += hsize;
+       }
+
+       out->pw_shell = NULL;
+       if (in->pw_shell != NULL)
+       {
+               out->pw_shell = bp;
+               hsize = strlen(in->pw_shell) + 1;
+               memmove(bp, in->pw_shell, hsize);
+               bp += hsize;
+       }
+
+       out->pw_expire = in->pw_expire;
+
+       return 0;
+}
+
+static void
+recycle_user(struct lu_thread_info *tdata, struct passwd *in)
+{
+       struct passwd *p;
+
+       if (tdata == NULL) return;
+       p = (struct passwd *)tdata->lu_entry;
+
+       if (in == NULL)
+       {
+               free_user(p);
+               tdata->lu_entry = NULL;
+       }
+
+       if (tdata->lu_entry == NULL)
+       {
+               tdata->lu_entry = in;
+               return;
+       }
+
+       free_user_data(p);
+
+       p->pw_name = in->pw_name;
+       p->pw_passwd = in->pw_passwd;
+       p->pw_uid = in->pw_uid;
+       p->pw_gid = in->pw_gid;
+       p->pw_change = in->pw_change;
+       p->pw_class = in->pw_class;
+       p->pw_gecos = in->pw_gecos;
+       p->pw_dir = in->pw_dir;
+       p->pw_shell = in->pw_shell;
+       p->pw_expire = in->pw_expire;
+
+       free(in);
 }
 
 static struct passwd *
-lu_getpwnam(const char *name)
+lu_getpwuid(int uid)
 {
-       unsigned datalen;
-       char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT];
-       XDR outxdr;
+       struct passwd *p;
+       unsigned int datalen;
        XDR inxdr;
-       _lu_passwd_ptr lu_pw;
        static int proc = -1;
-       unit lookup_buf[MAX_INLINE_UNITS];
+       int count;
+       char *lookup_buf;
 
        if (proc < 0)
        {
-               if (_lookup_link(_lu_port, "getpwnam_A", &proc) != KERN_SUCCESS)
+               if (_lookup_link(_lu_port, "getpwuid_A", &proc) != KERN_SUCCESS)
                {
-                       return (NULL);
+                       return NULL;
                }
        }
 
-       xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE);
-       if (!xdr__lu_string(&outxdr, &name))
-       {
-               xdr_destroy(&outxdr);
-               return (NULL);
-       }
-       
-       datalen = MAX_INLINE_UNITS;
-       if (_lookup_one(_lu_port, proc, (unit *)namebuf,
-               xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, lookup_buf, &datalen)
+       uid = htonl(uid);
+       datalen = 0;
+       lookup_buf = NULL;
+
+       if (_lookup_all(_lu_port, proc, (unit *)&uid, 1, &lookup_buf, &datalen)
                != KERN_SUCCESS)
        {
-               xdr_destroy(&outxdr);
-               return (NULL);
+               return NULL;
        }
 
-       xdr_destroy(&outxdr);
-
        datalen *= BYTES_PER_XDR_UNIT;
-       xdrmem_create(&inxdr, lookup_buf, datalen, 
-               XDR_DECODE);
-       lu_pw = NULL;
-       if (!xdr__lu_passwd_ptr(&inxdr, &lu_pw) || (lu_pw == NULL))
+       if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
+
+       xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
+
+       count = 0;
+       if (!xdr_int(&inxdr, &count))
        {
                xdr_destroy(&inxdr);
-               return (NULL);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
        }
 
+       if (count == 0)
+       {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
+       }
+
+       p = extract_user(&inxdr);
        xdr_destroy(&inxdr);
+       vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
 
-       convert_pw(lu_pw);
-       xdr_free(xdr__lu_passwd_ptr, &lu_pw);
-       return (&global_pw);
+       return p;
 }
 
-#ifdef notdef
-static int
-lu_putpwpasswd(char *login, char *old_passwd, char *new_passwd)
+static struct passwd *
+lu_getpwnam(const char *name)
 {
-       unsigned datalen;
-       int changed;
-       XDR xdr;
-       static int proc = -1;
-       char output_buf[3 * (_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT)];
-       unit lookup_buf[MAX_INLINE_UNITS];
+       struct passwd *p;
+       unsigned int datalen;
+       char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT];
        XDR outxdr;
-       
+       XDR inxdr;
+       static int proc = -1;
+       int count;
+       char *lookup_buf;
+
        if (proc < 0)
        {
-               if (_lookup_link(_lu_port, "putpwpasswd", &proc) != KERN_SUCCESS)
+               if (_lookup_link(_lu_port, "getpwnam_A", &proc) != KERN_SUCCESS)
                {
-                       return (0);
+                       return NULL;
                }
        }
 
-       xdrmem_create(&outxdr, output_buf, sizeof(output_buf), XDR_ENCODE);
-       if (!xdr__lu_string(&outxdr, &login) ||
-           !xdr__lu_string(&outxdr, &old_passwd) ||
-           !xdr__lu_string(&outxdr, &new_passwd))
+       xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE);
+       if (!xdr__lu_string(&outxdr, (_lu_string *)&name))
        {
                xdr_destroy(&outxdr);
-               return (0);
+               return NULL;
        }
+       
+       datalen = 0;
+       lookup_buf = NULL;
 
-       datalen = MAX_INLINE_UNITS;
-       if (_lookup_one(_lu_port, proc, output_buf,
-               xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, lookup_buf, &datalen)
+       if (_lookup_all(_lu_port, proc, (unit *)namebuf,
+               xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, &lookup_buf, &datalen)
                != KERN_SUCCESS)
        {
                xdr_destroy(&outxdr);
-               return (0);
+               return NULL;
        }
 
        xdr_destroy(&outxdr);
 
        datalen *= BYTES_PER_XDR_UNIT;
-       xdrmem_create(&xdr, lookup_buf, datalen, XDR_DECODE);
-       if (!xdr_int(&xdr, &changed))
+       if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
+
+       xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
+
+       count = 0;
+       if (!xdr_int(&inxdr, &count))
        {
-               xdr_destroy(&xdr);
-               return (0);
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
        }
 
-       xdr_destroy(&xdr);
+       if (count == 0)
+       {
+               xdr_destroy(&inxdr);
+               vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+               return NULL;
+       }
 
-       return (changed);
+       p = extract_user(&inxdr);
+       xdr_destroy(&inxdr);
+       vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
+
+
+       return p;
 }
-#endif
 
 static void
 lu_endpwent(void)
 {
-       pw_nentries = 0;
-       if (pw_data != NULL)
-       {
-               freeold();
-               vm_deallocate(mach_task_self(), (vm_address_t)pw_data, pw_datalen);
-               pw_data = NULL;
-       }
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_user, free_lu_thread_info_user);
+       _lu_data_free_vm_xdr(tdata);
 }
 
 static int
 lu_setpwent(void)
 {
        lu_endpwent();
-       pw_start = 1;
-       return (1);
+       return 1;
 }
 
 static struct passwd *
 lu_getpwent()
 {
+       struct passwd *p;
        static int proc = -1;
-       _lu_passwd lu_pw;
+       struct lu_thread_info *tdata;
 
-       if (pw_start == 1)
+       tdata = _lu_data_create_key(_lu_data_key_user, free_lu_thread_info_user);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_user, tdata);
+       }
+\r
+       if (tdata->lu_vm == NULL)
        {
-               pw_start = 0;
-
                if (proc < 0)
                {
                        if (_lookup_link(_lu_port, "getpwent_A", &proc) != KERN_SUCCESS)
                        {
                                lu_endpwent();
-                               return (NULL);
+                               return NULL;
                        }
                }
 
-               if (_lookup_all(_lu_port, proc, NULL, 0, &pw_data, &pw_datalen)
-                       != KERN_SUCCESS)
+               if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS)
                {
                        lu_endpwent();
-                       return (NULL);
+                       return NULL;
                }
 
-#ifdef NOTDEF
-/* NOTDEF because OOL buffers are counted in bytes with untyped IPC */
-               pw_datalen *= BYTES_PER_XDR_UNIT;
-#endif
+               /* mig stubs measure size in words (4 bytes) */
+               tdata->lu_vm_length *= 4;
 
-               xdrmem_create(&pw_xdr, pw_data, pw_datalen,
-                       XDR_DECODE);
-               if (!xdr_int(&pw_xdr, &pw_nentries))
+               if (tdata->lu_xdr != NULL)
+               {
+                       xdr_destroy(tdata->lu_xdr);
+                       free(tdata->lu_xdr);
+               }
+               tdata->lu_xdr = (XDR *)calloc(1, sizeof(XDR));
+
+               xdrmem_create(tdata->lu_xdr, tdata->lu_vm, tdata->lu_vm_length, XDR_DECODE);
+               if (!xdr_int(tdata->lu_xdr, &tdata->lu_vm_cursor))
                {
-                       xdr_destroy(&pw_xdr);
                        lu_endpwent();
-                       return (NULL);
+                       return NULL;
                }
        }
 
-       if (pw_nentries == 0)
+       if (tdata->lu_vm_cursor == 0)
        {
-               xdr_destroy(&pw_xdr);
                lu_endpwent();
-               return (NULL);
+               return NULL;
        }
 
-       bzero(&lu_pw, sizeof(lu_pw));
-       if (!xdr__lu_passwd(&pw_xdr, &lu_pw))
+       p = extract_user(tdata->lu_xdr);
+       if (p == NULL)
        {
-               xdr_destroy(&pw_xdr);
                lu_endpwent();
-               return (NULL);
+               return NULL;
        }
 
-       pw_nentries--;
-       convert_pw(&lu_pw);
-       xdr_free(xdr__lu_passwd, &lu_pw);
-       return (&global_pw);
+       tdata->lu_vm_cursor--;
+       
+       return p;
 }
 
-static char *loginName = NULL;
-static uid_t loginUid = -1;
+static struct passwd *
+getpw_internal(const char *name, uid_t uid, int source)
+{
+       struct passwd *res = NULL;
+       static char             *loginName = NULL;
+       static struct passwd    *loginEnt  = NULL;
 
-extern char *getlogin(void);
+       if (loginName == NULL)
+       {
+               char    *l = getlogin();
 
-struct passwd *
-getpwuid(uid_t uid)
+               pthread_mutex_lock(&_user_lock);
+               if ((loginEnt == NULL) && (l != NULL) && (*l != '\0'))
+               {
+                       if (_lu_running())
+                       {
+                               loginEnt = lu_getpwnam(l);
+                       }
+                       else
+                       {
+                               loginEnt = copy_user(_old_getpwnam(l));
+                       }
+       
+                       loginName = l;
+               }
+               pthread_mutex_unlock(&_user_lock);
+       }
+
+       if (loginEnt != NULL)
+       {
+               switch (source)
+               {
+                       case PW_GET_NAME:
+                               if (strcmp(name, loginEnt->pw_name) == 0)
+                               {
+                                       name = loginName;
+                               }
+                               if (strcmp(name, loginEnt->pw_gecos) == 0)
+                               {
+                                       name = loginName;
+                               }
+                               break;
+                       case PW_GET_UID:
+                               if (uid == loginEnt->pw_uid)
+                               {
+                                       source = PW_GET_NAME;
+                                       name = loginName;
+                               }
+                               break;
+                       default:
+                               break;
+               }
+       }
+
+       if (_lu_running())
+       {
+               switch (source)
+               {
+                       case PW_GET_NAME:
+                               res = lu_getpwnam(name);
+                               break;
+                       case PW_GET_UID:
+                               res = lu_getpwuid(uid);
+                               break;
+                       case PW_GET_ENT:
+                               res = lu_getpwent();
+                               break;
+                       default: res = NULL;
+               }
+       }
+       else
+       {
+               pthread_mutex_lock(&_user_lock);
+               switch (source)
+               {
+                       case PW_GET_NAME:
+                               res = copy_user(_old_getpwnam(name));
+                               break;
+                       case PW_GET_UID:
+                               res = copy_user(_old_getpwuid(uid));
+                               break;
+                       case PW_GET_ENT:
+                               res = copy_user(_old_getpwent());
+                               break;
+                       default: res = NULL;
+               }
+               pthread_mutex_unlock(&_user_lock);
+       }
+
+       return res;
+}
+
+static struct passwd *
+getpw(const char *name, uid_t uid, int source)
 {
-    if (uid != 0) {
-        if (loginName == NULL) {
-            char *l = getlogin();
-            if (l != NULL) {
-                struct passwd *p = getpwnam(l);
-                if (p != NULL) {
-                    loginUid = p->pw_uid;
-                    loginName = l;
-                }
-            }
-        }
-        if (uid == loginUid) {
-            LOOKUP1(lu_getpwnam, _old_getpwnam,  loginName, struct passwd);
-        }
-    }
-    LOOKUP1(lu_getpwuid, _old_getpwuid,  uid, struct passwd);
+       struct passwd *res = NULL;
+       struct lu_thread_info *tdata;
+
+       tdata = _lu_data_create_key(_lu_data_key_user, free_lu_thread_info_user);
+       if (tdata == NULL)
+       {
+               tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
+               _lu_data_set_key(_lu_data_key_user, tdata);
+       }
+
+       res = getpw_internal(name, uid, source);
+
+       recycle_user(tdata, res);
+
+       return (struct passwd *)tdata->lu_entry;
+}
+
+static int
+getpw_r(const char *name, uid_t uid, int source, struct passwd *pwd, char *buffer, size_t bufsize, struct passwd **result)
+{
+       struct passwd *res = NULL;
+       int status;
+
+       *result = NULL;
+       errno = 0;
+
+       res = getpw_internal(name, uid, source);
+       if (res == NULL) return -1;
+
+       status = copy_user_r(res, pwd, buffer, bufsize);
+       free_user(res);
+
+       if (status != 0)
+       {
+               errno = ERANGE;
+               return -1;
+       }
+
+       *result = pwd;
+       return 0;
 }
 
 struct passwd *
 getpwnam(const char *name)
 {
-       LOOKUP1(lu_getpwnam, _old_getpwnam,  name, struct passwd);
+       return getpw(name, -2, PW_GET_NAME);
 }
 
-#ifdef notdef
-/*
- * putpwpasswd() is not supported with anything other than netinfo
- * right now.
- * old_passwd is clear text.
- * new_passwd is encrypted.
- */
-#define _old_passwd(name, oldpass, newpass) 0
-int
-putpwpasswd(char *login, char *old_passwd, char *new_passwd)
+struct passwd *
+getpwuid(uid_t uid)
 {
-       if (_lu_running()) return (lu_putpwpasswd(login, old_passwd, new_passwd));
-       return (old_passwd(login, old_passwd, new_passwd));
+       return getpw(NULL, uid, PW_GET_UID);
 }
-#endif
 
 struct passwd *
 getpwent(void)
 {
-       GETENT(lu_getpwent, _old_getpwent, &pw_state, struct passwd);
+       return getpw(NULL, -2, PW_GET_ENT);
 }
 
 int
 setpwent(void)
 {
-       INTSETSTATEVOID(lu_setpwent, _old_setpwent, &pw_state);
+       if (_lu_running()) lu_setpwent();
+       else _old_setpwent();
+       return 1;
 }
 
 void
 endpwent(void)
 {
-       UNSETSTATE(lu_endpwent, _old_endpwent, &pw_state);
+       if (_lu_running()) lu_endpwent();
+       else _old_endpwent();
+}
+\rint
+getpwnam_r(const char *name, struct passwd *pwd, char *buffer, size_t bufsize, struct passwd **result)
+{
+       return getpw_r(name, -2, PW_GET_NAME, pwd, buffer, bufsize, result);
+}
+
+int
+getpwuid_r(uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, struct passwd **result)
+{
+       return getpw_r(NULL, uid, PW_GET_UID, pwd, buffer, bufsize, result);
 }
index b458b74107d71656207b23e7242125e8c9b5ba7b..5e258641ec929a832367ca217f61ee6b09f231d1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <stdlib.h>
 #include <string.h>
 #include <mach/mach.h>
-
+#include <pthread.h>
+#ifdef DEBUG
+#include <syslog.h>
+#endif
 #include "_lu_types.h"
 #include "lookup.h"
 #include "lu_utils.h"
 
-#define LONG_STRING_LENGTH 8192
+#define MAX_LOOKUP_ATTEMPTS 10
+
+static pthread_key_t  _info_key             = NULL;
+static pthread_once_t _info_key_initialized = PTHREAD_ONCE_INIT;
+
+struct _lu_data_s
+{
+       unsigned int icount;
+       unsigned int *ikey;
+       void **idata;
+       void (**idata_destructor)(void *);
+};
+
 #define _LU_MAXLUSTRLEN 256
 
-static ni_proplist *
-lookupd_process_dictionary(XDR *inxdr)
+ni_proplist *
+_lookupd_xdr_dictionary(XDR *inxdr)
 {
        int i, nkeys, j, nvals;
        char *key, *val;
@@ -50,15 +65,13 @@ lookupd_process_dictionary(XDR *inxdr)
        if (nkeys > 0)
        {
                i = nkeys * sizeof(ni_property);
-               l->ni_proplist_val = (ni_property *)malloc(i);
-               memset(l->ni_proplist_val, 0, i);
+               l->ni_proplist_val = (ni_property *)calloc(1, i);
        }
 
        for (i = 0; i < nkeys; i++)
        {
                key = NULL;
-
-               if (!xdr_string(inxdr, &key, LONG_STRING_LENGTH))
+               if (!xdr_string(inxdr, &key, -1))
                {
                        ni_proplist_free(l);
                        return NULL;
@@ -76,14 +89,13 @@ lookupd_process_dictionary(XDR *inxdr)
                if (nvals > 0)
                {
                        j = nvals * sizeof(ni_name);
-                       l->ni_proplist_val[i].nip_val.ni_namelist_val = (ni_name *)malloc(j);
-                       memset(l->ni_proplist_val[i].nip_val.ni_namelist_val, 0 , j);
+                       l->ni_proplist_val[i].nip_val.ni_namelist_val = (ni_name *)calloc(1, j);
                }
                
                for (j = 0; j < nvals; j++)
                {
                        val = NULL;
-                       if (!xdr_string(inxdr, &val, LONG_STRING_LENGTH))
+                       if (!xdr_string(inxdr, &val, -1))
                        {
                                ni_proplist_free(l);
                                return NULL;
@@ -103,7 +115,7 @@ lookupd_query(ni_proplist *l, ni_proplist ***out)
        XDR outxdr;
        XDR inxdr;
        int proc;
-       char *listbuf;
+       char *listbuf, *s;
        char databuf[_LU_MAXLUSTRLEN * BYTES_PER_XDR_UNIT];
        int n, i, j, na;
        kern_return_t status;
@@ -131,11 +143,13 @@ lookupd_query(ni_proplist *l, ni_proplist ***out)
        for (i = 0; i < l->ni_proplist_len; i++)
        {
                p = &(l->ni_proplist_val[i]);
-               if (!xdr_string(&outxdr, &(p->nip_name), _LU_MAXLUSTRLEN))
+               s = NULL;
+               if (!xdr_string(&outxdr, &s, _LU_MAXLUSTRLEN))
                {
                        xdr_destroy(&outxdr);
                        return 0;
                }
+               p->nip_name = s;
 
                if (!xdr_int(&outxdr, &(p->nip_val.ni_namelist_len)))
                {
@@ -145,11 +159,13 @@ lookupd_query(ni_proplist *l, ni_proplist ***out)
 
                for (j = 0; j < p->nip_val.ni_namelist_len; j++)
                {
-                       if (!xdr_string(&outxdr, &(p->nip_val.ni_namelist_val[j]), _LU_MAXLUSTRLEN))
+                       s = NULL;
+                       if (!xdr_string(&outxdr, &s, _LU_MAXLUSTRLEN))
                        {
                                xdr_destroy(&outxdr);
                                return 0;
                        }
+                       p->nip_val.ni_namelist_val[j] = s;
                }
        }
 
@@ -189,7 +205,7 @@ lookupd_query(ni_proplist *l, ni_proplist ***out)
 
        for (i = 0; i < n; i++)
        {
-               (*out)[i] = lookupd_process_dictionary(&inxdr);
+               (*out)[i] = _lookupd_xdr_dictionary(&inxdr);
        }
 
        xdr_destroy(&inxdr);
@@ -330,3 +346,366 @@ ni_proplist_merge(ni_proplist *a, ni_proplist *b)
        }
 }
 
+static void
+_lu_data_free(void *x)
+{
+       struct _lu_data_s *t;
+       int i;
+
+       if (x == NULL) return;
+
+       t = (struct _lu_data_s *)x;
+
+       for (i = 0; i < t->icount; i++)
+       {               
+               if ((t->idata[i] != NULL) && (t->idata_destructor[i] != NULL))
+               {
+                       (*(t->idata_destructor[i]))(t->idata[i]);
+               }
+
+               t->idata[i] = NULL;
+               t->idata_destructor[i] = NULL;
+       }
+
+       if (t->ikey != NULL) free(t->ikey);
+       t->ikey = NULL;
+
+       if (t->idata != NULL) free(t->idata);
+       t->idata = NULL;
+
+       if (t->idata_destructor != NULL) free(t->idata_destructor);
+       t->idata_destructor = NULL;
+
+       free(t);
+}
+
+static void
+_lu_data_init()
+{
+       pthread_key_create(&_info_key, _lu_data_free);
+       return;
+}
+
+static struct _lu_data_s *
+_lu_data_get()
+{
+       struct _lu_data_s *libinfo_data;
+
+       /*
+        * Only one thread should create the _info_key
+        */
+       pthread_once(&_info_key_initialized, _lu_data_init);
+
+       /* Check if this thread already created libinfo_data */
+       libinfo_data = pthread_getspecific(_info_key);
+       if (libinfo_data != NULL) return libinfo_data;
+
+       libinfo_data = (struct _lu_data_s *)calloc(1, sizeof(struct _lu_data_s));
+
+       pthread_setspecific(_info_key, libinfo_data);
+       return libinfo_data;
+}
+
+void *
+_lu_data_create_key(unsigned int key, void (*destructor)(void *))
+{
+       struct _lu_data_s *libinfo_data;
+       unsigned int i, n;
+
+       libinfo_data = _lu_data_get();
+
+       for (i = 0; i < libinfo_data->icount; i++)
+       {
+               if (libinfo_data->ikey[i] == key) return libinfo_data->idata[i];
+       }
+
+       i = libinfo_data->icount;
+       n = i + 1;
+
+       if (i == 0)
+       {
+               libinfo_data->ikey = (unsigned int *)malloc(sizeof(unsigned int));
+               libinfo_data->idata = (void **)malloc(sizeof(void *));
+               libinfo_data->idata_destructor = (void (**)(void *))malloc(sizeof(void (*)(void *)));
+       }
+       else
+       {
+               libinfo_data->ikey = (unsigned int *)realloc(libinfo_data->ikey, n * sizeof(unsigned int));
+               libinfo_data->idata = (void **)realloc(libinfo_data->idata, n * sizeof(void *));
+               libinfo_data->idata_destructor = (void (**)(void *))realloc(libinfo_data->idata_destructor, n * sizeof(void (*)(void *)));
+       }
+
+       libinfo_data->ikey[i] = key;
+       libinfo_data->idata[i] = NULL;
+       libinfo_data->idata_destructor[i] = destructor;
+       libinfo_data->icount++;
+
+       return NULL;
+}
+
+static unsigned int
+_lu_data_index(unsigned int key, struct _lu_data_s *libinfo_data)
+{
+       unsigned int i;
+
+       if (libinfo_data == NULL) return (unsigned int)-1;
+
+       for (i = 0; i < libinfo_data->icount; i++)
+       {
+               if (libinfo_data->ikey[i] == key) return i;
+       }
+
+       return (unsigned int)-1;
+}
+
+void
+_lu_data_set_key(unsigned int key, void *data)
+{
+       struct _lu_data_s *libinfo_data;
+       unsigned int i;
+
+       libinfo_data = _lu_data_get();
+
+       i = _lu_data_index(key, libinfo_data);
+       if (i == (unsigned int)-1) return;
+
+       libinfo_data->idata[i] = data;
+}
+
+void *
+_lu_data_get_key(unsigned int key)
+{
+       struct _lu_data_s *libinfo_data;
+       unsigned int i;
+
+       libinfo_data = _lu_data_get();
+
+       i = _lu_data_index(key, libinfo_data);
+       if (i == (unsigned int)-1) return NULL;
+
+       return libinfo_data->idata[i];
+}
+
+void
+_lu_data_free_vm_xdr(struct lu_thread_info *tdata)
+{
+       if (tdata == NULL) return;
+
+       if (tdata->lu_vm != NULL)
+       {
+               vm_deallocate(mach_task_self(), (vm_address_t)tdata->lu_vm, tdata->lu_vm_length);
+               tdata->lu_vm = NULL;
+       }
+       tdata->lu_vm_length = 0;
+       tdata->lu_vm_cursor = 0;
+
+       if (tdata->lu_xdr != NULL)
+       {
+               xdr_destroy(tdata->lu_xdr);
+               free(tdata->lu_xdr);
+               tdata->lu_xdr = NULL;
+       }
+}
+
+int
+_lu_xdr_attribute(XDR *xdr, char **key, char ***val, unsigned int *count)
+{
+       unsigned int i, j, len;
+       char **x, *s;
+
+       if (xdr == NULL) return -1;
+       if (key == NULL) return -1;
+       if (val == NULL) return -1;
+       if (count == NULL) return -1;
+
+       *key = NULL;
+       *val = NULL;
+       *count = 0;
+
+       if (!xdr_string(xdr, key, -1)) return -1;
+
+       if (!xdr_int(xdr, &len))
+       {
+               free(*key);
+               *key = NULL;
+               return -1;
+       }
+
+       if (len == 0) return 0;
+       *count = len;
+
+       x = (char **)calloc(len + 1, sizeof(char *));
+       *val = x;
+
+       for (i = 0; i < len; i++)
+       {
+               s = NULL;
+               if (!xdr_string(xdr, &s, -1))
+               {
+                       for (j = 0; j < i; j++) free(x[j]);
+                       free(x);
+                       *val = NULL;
+                       free(*key);
+                       *key = NULL;
+                       *count = 0;
+                       return -1;
+               }
+               x[i] = s;
+       }
+
+       x[len] = NULL;
+
+       return 0;
+}
+
+kern_return_t 
+_lookup_link(mach_port_t server, lookup_name name, int *procno)
+{
+       kern_return_t status;
+       security_token_t token;
+       unsigned int n;
+
+       token.val[0] = -1;
+       token.val[1] = -1;
+
+       status = MIG_SERVER_DIED;
+       for (n = 0; (status == MIG_SERVER_DIED) && (n < MAX_LOOKUP_ATTEMPTS); n++)
+       {
+               status = _lookup_link_secure(server, name, procno, &token);
+       }
+
+       if (status != KERN_SUCCESS)
+       {
+#ifdef DEBUG
+               syslog(LOG_DEBUG, "pid %u _lookup_link %s status %u", getpid(), name, status);
+#endif
+               return status;
+       }
+
+       if (token.val[0] != 0)
+       {
+#ifdef DEBUG
+               syslog(LOG_DEBUG, "pid %u _lookup_link %s auth failure uid=%d", getpid(), name, token.val[0]);
+#endif
+               return KERN_FAILURE;
+       }
+
+#ifdef DEBUG
+       syslog(LOG_DEBUG, "pid %u _lookup_link %s = %d", getpid(), name, *procno);
+#endif
+       return status;
+}
+
+kern_return_t 
+_lookup_one(mach_port_t server, int proc, inline_data indata, mach_msg_type_number_t indataCnt, inline_data outdata, mach_msg_type_number_t *outdataCnt)
+{
+       kern_return_t status;
+       security_token_t token;
+       unsigned int n;
+
+       token.val[0] = -1;
+       token.val[1] = -1;
+
+       status = MIG_SERVER_DIED;
+       for (n = 0; (status == MIG_SERVER_DIED) && (n < MAX_LOOKUP_ATTEMPTS); n++)
+       {
+               status = _lookup_one_secure(server, proc, indata, indataCnt, outdata, outdataCnt, &token);
+       }
+
+       if (status != KERN_SUCCESS)
+       {
+#ifdef DEBUG
+               syslog(LOG_DEBUG, "pid %u _lookup_one %d status %u", getpid(), proc, status);
+#endif
+               return status;
+       }
+
+       if (token.val[0] != 0)
+       {
+#ifdef DEBUG
+               syslog(LOG_DEBUG, "pid %u _lookup_one %d auth failure uid=%d", getpid(), proc, token.val[0]);
+#endif
+               return KERN_FAILURE;
+       }
+
+#ifdef DEBUG
+       syslog(LOG_DEBUG, "pid %u _lookup_one %d", getpid(), proc);
+#endif
+       return status;
+}
+
+kern_return_t 
+_lookup_all(mach_port_t server, int proc, inline_data indata, mach_msg_type_number_t indataCnt, ooline_data *outdata, mach_msg_type_number_t *outdataCnt)
+{
+       kern_return_t status;
+       security_token_t token;
+       unsigned int n;
+
+       token.val[0] = -1;
+       token.val[1] = -1;
+
+       status = MIG_SERVER_DIED;
+       for (n = 0; (status == MIG_SERVER_DIED) && (n < MAX_LOOKUP_ATTEMPTS); n++)
+       {
+               status = _lookup_all_secure(server, proc, indata, indataCnt, outdata, outdataCnt, &token);
+       }
+
+       if (status != KERN_SUCCESS)
+       {
+#ifdef DEBUG
+               syslog(LOG_DEBUG, "pid %u _lookup_all %d status %u", getpid(), proc, status);
+#endif
+               return status;
+       }
+
+       if (token.val[0] != 0)
+       {
+#ifdef DEBUG
+               syslog(LOG_DEBUG, "pid %u _lookup_all %d auth failure uid=%d", getpid(), proc, token.val[0]);
+#endif
+               return KERN_FAILURE;
+       }
+
+#ifdef DEBUG
+       syslog(LOG_DEBUG, "pid %u _lookup_all %d", getpid(), proc);
+#endif
+       return status;
+}
+
+kern_return_t 
+_lookup_ooall(mach_port_t server, int proc, ooline_data indata, mach_msg_type_number_t indataCnt, ooline_data *outdata, mach_msg_type_number_t *outdataCnt)
+{
+       kern_return_t status;
+       security_token_t token;
+       unsigned int n;
+
+       token.val[0] = -1;
+       token.val[1] = -1;
+
+       status = MIG_SERVER_DIED;
+       for (n = 0; (status == MIG_SERVER_DIED) && (n < MAX_LOOKUP_ATTEMPTS); n++)
+       {
+               status = _lookup_ooall_secure(server, proc, indata, indataCnt, outdata, outdataCnt, &token);
+       }
+
+       if (status != KERN_SUCCESS)
+       {
+#ifdef DEBUG
+               syslog(LOG_DEBUG, "pid %u _lookup_ooall %d status %u", getpid(), proc, status);
+#endif
+               return status;
+       }
+
+       if (token.val[0] != 0)
+       {
+#ifdef DEBUG
+               syslog(LOG_DEBUG, "pid %u _lookup_ooall %d auth failure uid=%d", getpid(), proc, token.val[0]);
+#endif
+               return KERN_FAILURE;
+       }
+
+#ifdef DEBUG
+       syslog(LOG_DEBUG, "pid %u _lookup_ooall %d", getpid(), proc);
+#endif
+       return status;
+}
index d1a268cfbafe2bf8f680f82d2b976eee426f94ba..ae987c057522dd55fbd1c1602c0dca2d198a6f9f 100644 (file)
  * Copyright (C) 1989 by NeXT, Inc.
  */
 
+#ifndef _LU_UTILS_H_
+#define _LU_UTILS_H_
+
 #import <netinfo/lookup_types.h>
 #include <netinfo/ni.h>
 #include <stdarg.h>
 
+#define LU_COPY_STRING(x) strdup(((x) == NULL) ? "" : x)
+
+#define LU_LONG_STRING_LENGTH 8192
+
+#define _lu_data_key_alias       10010
+#define _lu_data_key_bootp       10020
+#define _lu_data_key_bootparams  10030
+#define _lu_data_key_fstab       10040
+#define _lu_data_key_group       10050
+#define _lu_data_key_host        10060
+#define _lu_data_key_netgroup    10070
+#define _lu_data_key_network     10080
+#define _lu_data_key_printer     10090
+#define _lu_data_key_protocol    10100
+#define _lu_data_key_rpc         10110
+#define _lu_data_key_service     10120
+#define _lu_data_key_user        10130
+
+struct lu_thread_info
+{
+       void *lu_entry;
+       XDR *lu_xdr;
+       char *lu_vm;
+       unsigned int lu_vm_length;
+       unsigned int lu_vm_cursor;
+};
+
 extern mach_port_t _lu_port;
 extern unit *_lookup_buf;
 extern int _lu_running(void);
 
+void *_lu_data_create_key(unsigned int key, void (*destructor)(void *));
+void _lu_data_set_key(unsigned int key, void *data);
+void *_lu_data_get_key(unsigned int key);
+void _lu_data_free_vm_xdr(struct lu_thread_info *tdata);
+
+int _lu_xdr_attribute(XDR *xdr, char **key, char ***val, unsigned int *count);
+
+ni_proplist *_lookupd_xdr_dictionary(XDR *inxdr);
 int lookupd_query(ni_proplist *l, ni_proplist ***out);
 ni_proplist *lookupd_make_query(char *cat, char *fmt, ...);
 void ni_property_merge(ni_property *a, ni_property *b);
 void ni_proplist_merge(ni_proplist *a, ni_proplist *b);
 
-typedef enum lookup_state {
-       LOOKUP_CACHE,
-       LOOKUP_FILE,
-} lookup_state;
-
-#define SETSTATE(_lu_set, _old_set, state, stayopen) \
-{ \
-       if (_lu_running()) { \
-               _lu_set(stayopen); \
-               *state = LOOKUP_CACHE; \
-       } else { \
-               _old_set(stayopen); \
-               *state = LOOKUP_FILE; \
-       } \
-} 
-
-#define SETSTATEVOID(_lu_set, _old_set, state) \
-{ \
-       if (_lu_running()) { \
-               _lu_set(); \
-               *state = LOOKUP_CACHE; \
-       } else { \
-               _old_set(); \
-               *state = LOOKUP_FILE; \
-       } \
-} 
-
-#define INTSETSTATEVOID(_lu_set, _old_set, state) \
-{ \
-       int result; \
-       if (_lu_running()) { \
-               result = _lu_set(); \
-               *state = LOOKUP_CACHE; \
-       } else { \
-               result = _old_set(); \
-               *state = LOOKUP_FILE; \
-       } \
-       return result; \
-} 
-
-#define UNSETSTATE(_lu_unset, _old_unset, state) \
-{ \
-       if (_lu_running()) { \
-               _lu_unset(); \
-       } else { \
-               _old_unset(); \
-       } \
-       *state = LOOKUP_CACHE; \
-}
-
-#define GETENT(_lu_get, _old_get, state, res_type) \
-{ \
-       res_type *res; \
-\
-       if (_lu_running()) { \
-               if (*state == LOOKUP_CACHE) { \
-                       res = _lu_get(); \
-               } else { \
-                       res = _old_get(); \
-               } \
-       } else { \
-               res = _old_get(); \
-       } \
-       return (res); \
-}
-
-#define LOOKUP1(_lu_lookup, _old_lookup, arg, res_type) \
-{ \
-       res_type *res; \
- \
-       if (_lu_running()) { \
-               res = _lu_lookup(arg); \
-       } else { \
-               res = _old_lookup(arg); \
-       } \
-       return (res); \
-}
+kern_return_t _lookup_link(mach_port_t server, lookup_name name, int *procno);
+kern_return_t _lookup_one(mach_port_t server, int proc, inline_data indata, mach_msg_type_number_t indataCnt, inline_data outdata, mach_msg_type_number_t *outdataCnt);
+kern_return_t _lookup_all(mach_port_t server, int proc, inline_data indata, mach_msg_type_number_t indataCnt, ooline_data *outdata, mach_msg_type_number_t *outdataCnt);
+kern_return_t _lookup_ooall(mach_port_t server, int proc, ooline_data indata, mach_msg_type_number_t indataCnt, ooline_data *outdata, mach_msg_type_number_t *outdataCnt);
 
-#define LOOKUP2(_lu_lookup, _old_lookup, arg1, arg2, res_type) \
-{ \
-       res_type *res; \
- \
-       if (_lu_running()) { \
-               res = _lu_lookup(arg1, arg2); \
-       } else { \
-               res = _old_lookup(arg1, arg2); \
-       } \
-       return (res); \
-}
+#endif /* ! _LU_UTILS_H_ */
diff --git a/lookup.subproj/netdb_async.h b/lookup.subproj/netdb_async.h
new file mode 100644 (file)
index 0000000..561bb5f
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * Portions Copyright (c) 2002 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.1 (the "License").  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef _NETDB_ASYNC_H_
+#define _NETDB_ASYNC_H_
+
+#include <sys/cdefs.h>
+#include <mach/mach.h>
+#include <netdb.h>
+
+__BEGIN_DECLS
+
+/*
+       @typedef gethostbyaddr_async_callback
+       @discussion Type of the callback function used when a
+               gethostbyaddr_async_start() request is delivered.
+       @param hent The resolved host entry.
+       @param context The context provided when the request
+               was initiated.
+ */
+typedef void (*gethostbyaddr_async_callback)   (
+                                               struct hostent  *hent,
+                                               void            *context
+                                               );
+
+/*!
+       @function gethostbyaddr_async_start
+       @description Asynchronously resolves an Internet address
+       @param addr The address to be resolved.
+       @param len The length, in bytes, of the address.
+       @param type
+       @param callout The function to be called when the specified
+               address has been resolved.
+       @param context A user specified context which will be passed
+               to the callout function.
+       @result A mach reply port which will be sent a message when
+               the addr resolution has completed.  This message
+               should be passed to the gethostbyaddr_async_handleReply
+               function.  A NULL value indicates that no address
+               was specified or some other error occurred which
+               prevented the resolution from being started.
+ */
+mach_port_t
+gethostbyaddr_async_start                      (
+                                               const char                      *addr,
+                                               int                             len,
+                                               int                             type,
+                                               gethostbyaddr_async_callback    callout,
+                                               void                            *context
+                                               );
+
+
+/*!
+       @function gethostbyaddr_async_handleReply
+       @description This function should be called with the Mach message sent
+               to the port returned by the call to gethostbyaddr_async_start.
+               The reply message will be interpreted and will result in a
+               call to the specified callout function.
+       @param replyMsg The Mach message.
+ */
+void
+gethostbyaddr_async_handleReply                        (
+                                               void *replyMsg
+                                               );
+
+
+/*
+       @typedef gethostbyname_async_callback
+       @discussion Type of the callback function used when a
+               gethostbyname_async_start() request is delivered.
+       @param hent The resolved host entry.
+       @param context The context provided when the request
+               was initiated.
+ */
+typedef void (*gethostbyname_async_callback)   (
+                                               struct hostent  *hent,
+                                               void            *context
+                                               );
+
+/*!
+       @function gethostbyname_async_start
+       @description Asynchronously resolves a hostname
+       @param name The hostname to be resolved.
+       @param callout The function to be called when the specified
+               hostname has been resolved.
+       @param context A user specified context which will be passed
+               to the callout function.
+       @result A mach reply port which will be sent a message when
+               the name resolution has completed.  This message
+               should be passed to the gethostbyname_async_handleReply
+               function.  A NULL value indicates that no hostname
+               was specified or some other error occurred which
+               prevented the resolution from being started.
+ */
+mach_port_t
+gethostbyname_async_start                      (
+                                               const char                      *name,
+                                               gethostbyname_async_callback    callout,
+                                               void                            *context
+                                               );
+
+
+/*!
+       @function gethostbyname_async_handleReply
+       @description This function should be called with the Mach message sent
+               to the port returned by the call to gethostbyname_async_start.
+               The reply message will be interpreted and will result in a
+               call to the specified callout function.
+       @param replyMsg The Mach message.
+ */
+void
+gethostbyname_async_handleReply                        (
+                                               void *replyMsg
+                                               );
+
+
+/*
+       @typedef getipnodebyaddr_async_callback
+       @discussion Type of the callback function used when a
+               getipnodebyaddr_async_start() request is delivered.
+       @param hent The resolved host entry.  If not NULL, the caller
+               must call freehostent() on the host entry.
+       @param error If error code if the resolved host entry is NULL
+       @param context The context provided when the request
+               was initiated.
+ */
+typedef void (*getipnodebyaddr_async_callback) (
+                                               struct hostent  *hent,
+                                               int             error,
+                                               void            *context
+                                               );
+
+/*!
+       @function getipnodebyaddr_async_start
+       @description Asynchronously resolves an Internet address
+       @param addr The address to be resolved.
+       @param len The length, in bytes, of the address.
+       @param af The address family
+       @param error
+       @param callout The function to be called when the specified
+               address has been resolved.
+       @param context A user specified context which will be passed
+               to the callout function.
+       @result A mach reply port which will be sent a message when
+               the addr resolution has completed.  This message
+               should be passed to the getipnodebyaddr_async_handleReply
+               function.  A NULL value indicates that no address
+               was specified or some other error occurred which
+               prevented the resolution from being started.
+ */
+mach_port_t
+getipnodebyaddr_async_start                    (
+                                               const void                      *addr,
+                                               size_t                          len,
+                                               int                             af,
+                                               int                             *error,
+                                               getipnodebyaddr_async_callback  callout,
+                                               void                            *context
+                                               );
+
+
+/*!
+       @function getipnodebyaddr_async_handleReply
+       @description This function should be called with the Mach message sent
+               to the port returned by the call to getipnodebyaddr_async_start.
+               The reply message will be interpreted and will result in a
+               call to the specified callout function.
+       @param replyMsg The Mach message.
+ */
+void
+getipnodebyaddr_async_handleReply              (
+                                               void    *replyMsg
+                                               );
+
+
+/*
+       @typedef getipnodebyname_async_callback
+       @discussion Type of the callback function used when a
+               getipnodebyname_async_start() request is delivered.
+       @param hent The resolved host entry.  If not NULL, the caller
+               must call freehostent() on the host entry.
+       @param error If error code if the resolved host entry is NULL
+       @param context The context provided when the request
+               was initiated.
+ */
+typedef void (*getipnodebyname_async_callback) (
+                                               struct hostent  *hent,
+                                               int             error,
+                                               void            *context
+                                               );
+
+/*!
+       @function getipnodebyname_async_start
+       @description Asynchronously resolves a hostname
+       @param name The hostname to be resolved.
+       @param af
+       @param flags
+       @param error
+       @param callout The function to be called when the specified
+               hostname has been resolved.
+       @param context A user specified context which will be passed
+               to the callout function.
+       @result A mach reply port which will be sent a message when
+               the name resolution has completed.  This message
+               should be passed to the getipnodebyname_async_handleReply
+               function.  A NULL value indicates that no hostname
+               was specified or some other error occurred which
+               prevented the resolution from being started.
+ */
+mach_port_t
+getipnodebyname_async_start                    (
+                                               const char                      *name,
+                                               int                             af,
+                                               int                             flags,
+                                               int                             *error,
+                                               getipnodebyname_async_callback  callout,
+                                               void                            *context
+                                               );
+
+
+/*!
+       @function getipnodebyname_async_handleReply
+       @description This function should be called with the Mach message sent
+               to the port returned by the call to getipnodebyname_async_start.
+               The reply message will be interpreted and will result in a
+               call to the specified callout function.
+       @param replyMsg The Mach message.
+ */
+void
+getipnodebyname_async_handleReply              (
+                                               void    *replyMsg
+                                               );
+
+__END_DECLS
+
+#endif /* !_NETDB_ASYNC_H_ */
diff --git a/mdns.subproj/DNSServiceDiscovery.c b/mdns.subproj/DNSServiceDiscovery.c
new file mode 100644 (file)
index 0000000..0d01e46
--- /dev/null
@@ -0,0 +1,658 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License").  You may not use this file except in compliance with the
+ * License.  Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
+ *
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "DNSServiceDiscovery.h"
+#include "DNSServiceDiscoveryDefines.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <servers/bootstrap.h>
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+#include <pthread.h>
+
+#include <netinet/in.h>
+
+extern struct rpc_subsystem internal_DNSServiceDiscoveryReply_subsystem;
+
+extern boolean_t DNSServiceDiscoveryReply_server(
+        mach_msg_header_t *InHeadP,
+        mach_msg_header_t *OutHeadP);
+
+extern
+kern_return_t DNSServiceBrowserCreate_rpc
+(
+    mach_port_t server,
+    mach_port_t client,
+    DNSCString regtype,
+    DNSCString domain
+);
+
+extern
+kern_return_t DNSServiceDomainEnumerationCreate_rpc
+(
+    mach_port_t server,
+    mach_port_t client,
+    int registrationDomains
+);
+
+extern
+kern_return_t DNSServiceRegistrationCreate_rpc
+(
+    mach_port_t server,
+    mach_port_t client,
+    DNSCString name,
+    DNSCString regtype,
+    DNSCString domain,
+    int port,
+    DNSCString txtRecord
+);
+
+extern
+kern_return_t DNSServiceResolverResolve_rpc
+(
+    mach_port_t server,
+    mach_port_t client,
+    DNSCString name,
+    DNSCString regtype,
+    DNSCString domain
+);
+
+extern
+kern_return_t DNSServiceRegistrationAddRecord_rpc
+(
+    mach_port_t server,
+    mach_port_t client,
+    int type,
+    record_data_t data,
+    mach_msg_type_number_t record_dataCnt,
+    uint32_t ttl,
+    natural_t *reference
+);
+
+extern
+int DNSServiceRegistrationUpdateRecord_rpc
+(
+    mach_port_t server,
+    mach_port_t client,
+    natural_t reference,
+    record_data_t data,
+    mach_msg_type_number_t record_dataCnt,
+    uint32_t ttl
+);
+
+extern
+kern_return_t DNSServiceRegistrationRemoveRecord_rpc
+(
+    mach_port_t server,
+    mach_port_t client,
+    natural_t reference
+);
+
+struct a_requests {
+    struct a_requests          *next;
+    mach_port_t                                client_port;
+    union {
+        DNSServiceBrowserReply                                 browserCallback;
+        DNSServiceDomainEnumerationReply       enumCallback;
+        DNSServiceRegistrationReply            regCallback;
+        DNSServiceResolverReply                        resolveCallback;
+    } callout;
+    void                                       *context;
+};
+
+static struct a_requests       *a_requests     = NULL;
+static pthread_mutex_t         a_requests_lock = PTHREAD_MUTEX_INITIALIZER;
+
+typedef struct _dns_service_discovery_t {
+    mach_port_t        port;
+} dns_service_discovery_t;
+
+mach_port_t DNSServiceDiscoveryLookupServer(void)
+{
+    static mach_port_t sndPort         = MACH_PORT_NULL;
+    kern_return_t   result;
+
+    if (sndPort != MACH_PORT_NULL) {
+        return sndPort;
+    }
+
+    result = bootstrap_look_up(bootstrap_port, DNS_SERVICE_DISCOVERY_SERVER, &sndPort);
+    if (result != KERN_SUCCESS) {
+        printf("%s(): {%s:%d} bootstrap_look_up() failed: $%x\n", __FUNCTION__, __FILE__, __LINE__, (int) result);
+        sndPort = MACH_PORT_NULL;
+    }
+
+
+    return sndPort;
+}
+
+void _increaseQueueLengthOnPort(mach_port_t port)
+{
+    mach_port_limits_t qlimits;
+    kern_return_t result;
+    
+    qlimits.mpl_qlimit = 16;
+    result = mach_port_set_attributes(mach_task_self(), port, MACH_PORT_LIMITS_INFO, (mach_port_info_t)&qlimits, MACH_PORT_LIMITS_INFO_COUNT);
+
+    if (result != KERN_SUCCESS) {
+        printf("%s(): {%s:%d} mach_port_set_attributes() failed: $%x %s\n", __FUNCTION__, __FILE__, __LINE__, (int) result, mach_error_string(result));
+    }
+}
+
+dns_service_discovery_ref DNSServiceBrowserCreate (const char *regtype, const char *domain, DNSServiceBrowserReply callBack,void *context)
+{
+    mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
+    mach_port_t clientPort;
+    kern_return_t result;
+    dns_service_discovery_ref return_t;
+    struct a_requests  *request;
+    
+    if (!serverPort) {
+        return NULL;
+    }
+
+    result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &clientPort);
+    if (result != KERN_SUCCESS) {
+        printf("Mach port receive creation failed, %s\n", mach_error_string(result));
+        return NULL;
+    }
+    result = mach_port_insert_right(mach_task_self(), clientPort, clientPort, MACH_MSG_TYPE_MAKE_SEND);
+    if (result != KERN_SUCCESS) {
+        printf("Mach port send creation failed, %s\n", mach_error_string(result));
+        mach_port_destroy(mach_task_self(), clientPort);
+        return NULL;
+    }
+    _increaseQueueLengthOnPort(clientPort);
+
+    return_t = malloc(sizeof(dns_service_discovery_t));
+    return_t->port = clientPort;
+
+    request = malloc(sizeof(struct a_requests));
+    request->client_port = clientPort;
+    request->context = context;
+    request->callout.browserCallback = callBack;
+
+    result = DNSServiceBrowserCreate_rpc(serverPort, clientPort, (char *)regtype, (char *)domain);
+
+    if (result != KERN_SUCCESS) {
+        printf("There was an error creating a browser, %s\n", mach_error_string(result));
+        free(request);
+        return NULL;
+    }
+
+    pthread_mutex_lock(&a_requests_lock);
+    request->next = a_requests;
+    a_requests = request;
+    pthread_mutex_unlock(&a_requests_lock);
+    
+    return return_t;
+}
+
+/* Service Enumeration */
+
+dns_service_discovery_ref DNSServiceDomainEnumerationCreate (int registrationDomains, DNSServiceDomainEnumerationReply callBack, void *context)
+{
+    mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
+    mach_port_t clientPort;
+    kern_return_t result;
+    dns_service_discovery_ref return_t;
+    struct a_requests  *request;
+
+    if (!serverPort) {
+        return NULL;
+    }
+
+    result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &clientPort);
+    if (result != KERN_SUCCESS) {
+        printf("Mach port receive creation failed, %s\n", mach_error_string(result));
+        return NULL;
+    }
+    result = mach_port_insert_right(mach_task_self(), clientPort, clientPort, MACH_MSG_TYPE_MAKE_SEND);
+    if (result != KERN_SUCCESS) {
+        printf("Mach port send creation failed, %s\n", mach_error_string(result));
+        mach_port_destroy(mach_task_self(), clientPort);
+        return NULL;
+    }
+    _increaseQueueLengthOnPort(clientPort);
+
+    return_t = malloc(sizeof(dns_service_discovery_t));
+    return_t->port = clientPort;
+
+    request = malloc(sizeof(struct a_requests));
+    request->client_port = clientPort;
+    request->context = context;
+    request->callout.enumCallback = callBack;
+
+    result = DNSServiceDomainEnumerationCreate_rpc(serverPort, clientPort, registrationDomains);
+
+    if (result != KERN_SUCCESS) {
+        printf("There was an error creating an enumerator, %s\n", mach_error_string(result));
+        free(request);
+        return NULL;
+    }
+    
+    pthread_mutex_lock(&a_requests_lock);
+    request->next = a_requests;
+    a_requests = request;
+    pthread_mutex_unlock(&a_requests_lock);
+
+    return return_t;
+}
+
+
+/* Service Registration */
+
+dns_service_discovery_ref DNSServiceRegistrationCreate
+(const char *name, const char *regtype, const char *domain, uint16_t port, const char *txtRecord, DNSServiceRegistrationReply callBack, void *context)
+{
+    mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
+    mach_port_t clientPort;
+    kern_return_t              result;
+    dns_service_discovery_ref return_t;
+    struct a_requests  *request;
+    
+    if (!serverPort) {
+        return NULL;
+    }
+
+    result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &clientPort);
+    if (result != KERN_SUCCESS) {
+        printf("Mach port receive creation failed, %s\n", mach_error_string(result));
+        return NULL;
+    }
+    result = mach_port_insert_right(mach_task_self(), clientPort, clientPort, MACH_MSG_TYPE_MAKE_SEND);
+    if (result != KERN_SUCCESS) {
+        printf("Mach port send creation failed, %s\n", mach_error_string(result));
+        mach_port_destroy(mach_task_self(), clientPort);
+        return NULL;
+    }
+    _increaseQueueLengthOnPort(clientPort);
+
+    return_t = malloc(sizeof(dns_service_discovery_t));
+    return_t->port = clientPort;
+
+    request = malloc(sizeof(struct a_requests));
+    request->client_port = clientPort;
+    request->context = context;
+    request->callout.regCallback = callBack;
+
+    result = DNSServiceRegistrationCreate_rpc(serverPort, clientPort, (char *)name, (char *)regtype, (char *)domain, port, (char *)txtRecord);
+
+    if (result != KERN_SUCCESS) {
+        printf("There was an error creating a resolve, %s\n", mach_error_string(result));
+        free(request);
+        return NULL;
+    }
+
+    pthread_mutex_lock(&a_requests_lock);
+    request->next = a_requests;
+    a_requests = request;
+    pthread_mutex_unlock(&a_requests_lock);
+
+    return return_t;
+}
+
+/* Resolver requests */
+
+dns_service_discovery_ref DNSServiceResolverResolve(const char *name, const char *regtype, const char *domain, DNSServiceResolverReply callBack, void *context)
+{
+    mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
+    mach_port_t clientPort;
+    kern_return_t              result;
+    dns_service_discovery_ref return_t;
+    struct a_requests  *request;
+
+    if (!serverPort) {
+        return NULL;
+    }
+
+    result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &clientPort);
+    if (result != KERN_SUCCESS) {
+        printf("Mach port receive creation failed, %s\n", mach_error_string(result));
+        return NULL;
+    }
+    result = mach_port_insert_right(mach_task_self(), clientPort, clientPort, MACH_MSG_TYPE_MAKE_SEND);
+    if (result != KERN_SUCCESS) {
+        printf("Mach port send creation failed, %s\n", mach_error_string(result));
+        mach_port_destroy(mach_task_self(), clientPort);
+        return NULL;
+    }
+    _increaseQueueLengthOnPort(clientPort);
+
+    return_t = malloc(sizeof(dns_service_discovery_t));
+    return_t->port = clientPort;
+
+    request = malloc(sizeof(struct a_requests));
+    request->client_port = clientPort;
+    request->context = context;
+    request->callout.resolveCallback = callBack;
+
+    DNSServiceResolverResolve_rpc(serverPort, clientPort, (char *)name, (char *)regtype, (char *)domain);
+
+    pthread_mutex_lock(&a_requests_lock);
+    request->next = a_requests;
+    a_requests = request;
+    pthread_mutex_unlock(&a_requests_lock);
+
+    return return_t;
+}
+
+DNSRecordReference DNSServiceRegistrationAddRecord(dns_service_discovery_ref ref, uint16_t rrtype, uint16_t rdlen, const char *rdata, uint32_t ttl)
+{
+    mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
+    mach_port_t clientPort;
+    natural_t reference = 0;
+    kern_return_t result = KERN_SUCCESS;
+
+    if (!serverPort) {
+        return kDNSServiceDiscoveryUnknownErr;
+    }
+
+    clientPort = DNSServiceDiscoveryMachPort(ref);
+
+    if (!clientPort) {
+        return kDNSServiceDiscoveryUnknownErr;
+    }
+
+    result = DNSServiceRegistrationAddRecord_rpc(serverPort, clientPort, rrtype, (record_data_t)rdata, rdlen, ttl, &reference);
+
+    if (result != KERN_SUCCESS) {
+        printf("The result of the registration was not successful.  Error %d, result %s\n", result, mach_error_string(result));
+    }
+    
+    return reference;
+}
+
+DNSServiceRegistrationReplyErrorType DNSServiceRegistrationUpdateRecord(dns_service_discovery_ref ref, DNSRecordReference reference, uint16_t rdlen, const char *rdata, uint32_t ttl)
+{
+    mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
+    mach_port_t clientPort;
+    kern_return_t result = KERN_SUCCESS;
+
+    if (!serverPort) {
+        return kDNSServiceDiscoveryUnknownErr;
+    }
+
+    clientPort = DNSServiceDiscoveryMachPort(ref);
+
+    if (!clientPort) {
+        return kDNSServiceDiscoveryUnknownErr;
+    }
+
+    result = DNSServiceRegistrationUpdateRecord_rpc(serverPort, clientPort, (natural_t)reference, (record_data_t)rdata, rdlen, ttl);
+    if (result != KERN_SUCCESS) {
+        printf("The result of the registration was not successful.  Error %d, result %s\n", result, mach_error_string(result));
+        return result;
+    }
+
+    return kDNSServiceDiscoveryNoError;
+}
+
+
+DNSServiceRegistrationReplyErrorType DNSServiceRegistrationRemoveRecord(dns_service_discovery_ref ref, DNSRecordReference reference)
+{
+    mach_port_t serverPort = DNSServiceDiscoveryLookupServer();
+    mach_port_t clientPort;
+    kern_return_t result = KERN_SUCCESS;
+
+    if (!serverPort) {
+        return kDNSServiceDiscoveryUnknownErr;
+    }
+
+    clientPort = DNSServiceDiscoveryMachPort(ref);
+
+    if (!clientPort) {
+        return kDNSServiceDiscoveryUnknownErr;
+    }
+
+    result = DNSServiceRegistrationRemoveRecord_rpc(serverPort, clientPort, (natural_t)reference);
+
+    if (result != KERN_SUCCESS) {
+        printf("The result of the registration was not successful.  Error %d, result %s\n", result, mach_error_string(result));
+        return result;
+    }
+
+    return kDNSServiceDiscoveryNoError;
+}
+
+void DNSServiceDiscovery_handleReply(void *replyMsg)
+{
+    unsigned long                      result = 0xFFFFFFFF;
+    mach_msg_header_t *        msgSendBufPtr;
+    mach_msg_header_t *     receivedMessage;
+    unsigned                   msgSendBufLength;
+
+    msgSendBufLength = internal_DNSServiceDiscoveryReply_subsystem.maxsize;
+    msgSendBufPtr = (mach_msg_header_t *) malloc(msgSendBufLength);
+
+
+    receivedMessage = ( mach_msg_header_t * ) replyMsg;
+
+    // Call DNSServiceDiscoveryReply_server to change mig-generated message into a
+    // genuine mach message. It will then cause the callback to get called.
+    result = DNSServiceDiscoveryReply_server ( receivedMessage, msgSendBufPtr );
+    ( void ) mach_msg_send ( msgSendBufPtr );
+    free(msgSendBufPtr);
+}
+
+mach_port_t DNSServiceDiscoveryMachPort(dns_service_discovery_ref dnsServiceDiscovery)
+{
+    return dnsServiceDiscovery->port;
+}
+
+void DNSServiceDiscoveryDeallocate(dns_service_discovery_ref dnsServiceDiscovery)
+{
+    struct a_requests  *request0, *request;
+    mach_port_t reply = dnsServiceDiscovery->port;
+
+    if (dnsServiceDiscovery->port) {
+        pthread_mutex_lock(&a_requests_lock);
+        request0 = NULL;
+        request  = a_requests;
+        while (request) {
+            if (request->client_port == reply) {
+                /* request info found, remove from list */
+                if (request0) {
+                    request0->next = request->next;
+                } else {
+                    a_requests = request->next;
+                }
+                break;
+            } else {
+                /* not info for this request, skip to next */
+                request0 = request;
+                request  = request->next;
+            }
+
+        }
+        pthread_mutex_unlock(&a_requests_lock);
+
+        free(request);
+        
+        mach_port_destroy(mach_task_self(), dnsServiceDiscovery->port);
+
+        free(dnsServiceDiscovery);
+    }
+    return;
+}
+
+// reply functions, calls the users setup callbacks with function pointers
+
+kern_return_t internal_DNSServiceDomainEnumerationReply_rpc
+(
+    mach_port_t reply,
+    int resultType,
+    DNSCString replyDomain,
+    DNSServiceDiscoveryReplyFlags flags
+)
+{
+    struct a_requests  *request;
+    void *requestContext = NULL;
+    DNSServiceDomainEnumerationReply callback = NULL;
+
+    pthread_mutex_lock(&a_requests_lock);
+    request  = a_requests;
+    while (request) {
+        if (request->client_port == reply) {
+            break;
+        }
+        request = request->next;
+    }
+
+    if (request != NULL) {
+        callback = (*request->callout.enumCallback);
+        requestContext = request->context;
+    }
+    pthread_mutex_unlock(&a_requests_lock);
+
+    if (request != NULL) {
+        (callback)(resultType, replyDomain, flags, requestContext);
+    }
+    
+    return KERN_SUCCESS;
+
+}
+
+kern_return_t internal_DNSServiceBrowserReply_rpc
+(
+    mach_port_t reply,
+    int resultType,
+    DNSCString replyName,
+    DNSCString replyType,
+    DNSCString replyDomain,
+    DNSServiceDiscoveryReplyFlags flags
+)
+{
+    struct a_requests  *request;
+    void *requestContext = NULL;
+    DNSServiceBrowserReply callback = NULL;
+
+    pthread_mutex_lock(&a_requests_lock);
+    request  = a_requests;
+    while (request) {
+        if (request->client_port == reply) {
+            break;
+        }
+        request = request->next;
+    }
+    if (request != NULL) {
+        callback = (*request->callout.browserCallback);
+        requestContext = request->context;
+    }
+
+    pthread_mutex_unlock(&a_requests_lock);
+
+    if (request != NULL) {
+        (callback)(resultType, replyName, replyType, replyDomain, flags, requestContext);
+    }
+
+    return KERN_SUCCESS;
+}
+
+
+kern_return_t internal_DNSServiceRegistrationReply_rpc
+(
+    mach_port_t reply,
+    int resultType
+)
+{
+    struct a_requests  *request;
+    void *requestContext = NULL;
+    DNSServiceRegistrationReply callback = NULL;
+
+    pthread_mutex_lock(&a_requests_lock);
+    request  = a_requests;
+    while (request) {
+        if (request->client_port == reply) {
+            break;
+        }
+        request = request->next;
+    }
+    if (request != NULL) {
+        callback = (*request->callout.regCallback);
+        requestContext = request->context;
+    }
+
+    pthread_mutex_unlock(&a_requests_lock);
+    if (request != NULL) {
+        (callback)(resultType, requestContext);
+    }
+    return KERN_SUCCESS;
+}
+
+
+kern_return_t internal_DNSServiceResolverReply_rpc
+(
+    mach_port_t reply,
+    sockaddr_t interface,
+    sockaddr_t address,
+    DNSCString txtRecord,
+    DNSServiceDiscoveryReplyFlags flags
+)
+{
+    struct sockaddr  *interface_storage = NULL;
+    struct sockaddr  *address_storage = NULL;
+    struct a_requests  *request;
+    void *requestContext = NULL;
+    DNSServiceResolverReply callback = NULL;
+
+    if (interface) {
+        int len = ((struct sockaddr *)interface)->sa_len;
+        interface_storage = (struct sockaddr *)malloc(len);
+        bcopy(interface, interface_storage,len);
+    }
+
+    if (address) {
+        int len = ((struct sockaddr *)address)->sa_len;
+        address_storage = (struct sockaddr *)malloc(len);
+        bcopy(address, address_storage, len);
+    }
+
+    pthread_mutex_lock(&a_requests_lock);
+    request  = a_requests;
+    while (request) {
+        if (request->client_port == reply) {
+            break;
+        }
+        request = request->next;
+    }
+
+    if (request != NULL) {
+        callback = (*request->callout.resolveCallback);
+        requestContext = request->context;
+    }
+    pthread_mutex_unlock(&a_requests_lock);
+
+    if (request != NULL) {
+        (callback)(interface_storage, address_storage, txtRecord, flags, requestContext);
+    }
+
+    if (interface) {
+        free(interface_storage);
+    }
+    if (address) {
+        free(address_storage);
+    }
+    
+    return KERN_SUCCESS;
+}
diff --git a/mdns.subproj/DNSServiceDiscovery.h b/mdns.subproj/DNSServiceDiscovery.h
new file mode 100644 (file)
index 0000000..3cd32f1
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+* "License").  You may not use this file except in compliance with the
+ * License.  Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
+ *
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef __DNS_SERVICE_DISCOVERY_H
+#define __DNS_SERVICE_DISCOVERY_H
+
+#include <mach/mach_types.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/cdefs.h>
+
+#include <netinet/in.h>
+
+__BEGIN_DECLS
+
+/* Opaque internal data type */
+typedef struct _dns_service_discovery_t * dns_service_discovery_ref;
+
+/* possible reply flags values */
+
+enum {
+    kDNSServiceDiscoveryNoFlags                        = 0,
+    kDNSServiceDiscoveryMoreRepliesImmediately = 1 << 0,
+};
+
+
+/* possible error code values */
+typedef enum
+{
+    kDNSServiceDiscoveryWaiting     = 1,
+    kDNSServiceDiscoveryNoError     = 0,
+      // mDNS Error codes are in the range
+      // FFFE FF00 (-65792) to FFFE FFFF (-65537)
+    kDNSServiceDiscoveryUnknownErr        = -65537,       // 0xFFFE FFFF
+    kDNSServiceDiscoveryNoSuchNameErr     = -65538,
+    kDNSServiceDiscoveryNoMemoryErr       = -65539,
+    kDNSServiceDiscoveryBadParamErr       = -65540,
+    kDNSServiceDiscoveryBadReferenceErr   = -65541,
+    kDNSServiceDiscoveryBadStateErr       = -65542,
+    kDNSServiceDiscoveryBadFlagsErr       = -65543,
+    kDNSServiceDiscoveryUnsupportedErr    = -65544,
+    kDNSServiceDiscoveryNotInitializedErr = -65545,
+    kDNSServiceDiscoveryNoCache           = -65546,
+    kDNSServiceDiscoveryAlreadyRegistered = -65547,
+    kDNSServiceDiscoveryNameConflict      = -65548,
+    kDNSServiceDiscoveryInvalid           = -65549,
+    kDNSServiceDiscoveryMemFree           = -65792        // 0xFFFE FF00
+} DNSServiceRegistrationReplyErrorType;
+
+typedef uint32_t DNSRecordReference;
+
+
+/*!
+@function DNSServiceResolver_handleReply
+ @description This function should be called with the Mach message sent
+ to the port returned by the call to DNSServiceResolverResolve.
+ The reply message will be interpreted and will result in a
+ call to the specified callout function.
+ @param replyMsg The Mach message.
+ */
+void DNSServiceDiscovery_handleReply(void *replyMsg);
+
+/* Service Registration */
+
+typedef void (*DNSServiceRegistrationReply) (
+    DNSServiceRegistrationReplyErrorType               errorCode,
+    void                                                                               *context
+);
+
+/*!
+@function DNSServiceRegistrationCreate
+    @description Register a named service with DNS Service Discovery
+    @param name The name of this service instance (e.g. "Steve's Printer")
+    @param regtype The service type (e.g. "_printer._tcp." -- see
+        RFC 2782 (DNS SRV) and <http://www.iana.org/assignments/port-numbers>)
+    @param domain The domain in which to register the service (e.g. "apple.com.")
+    @param port The local port on which this service is being offered (in network byte order)
+    @param txtRecord Optional protocol-specific additional information
+    @param callBack The DNSServiceRegistrationReply function to be called
+    @param context A user specified context which will be passed to the callout function.
+    @result A dns_registration_t
+*/
+dns_service_discovery_ref DNSServiceRegistrationCreate
+(
+    const char                 *name,
+    const char                 *regtype,
+    const char                 *domain,
+    uint16_t           port,
+    const char                 *txtRecord,
+    DNSServiceRegistrationReply callBack,
+    void               *context
+);
+
+/***************************************************************************/
+/*   DNS Domain Enumeration   */
+
+typedef enum
+{
+    DNSServiceDomainEnumerationReplyAddDomain,                 // Domain found
+    DNSServiceDomainEnumerationReplyAddDomainDefault,          // Domain found (and should be selected by default)
+    DNSServiceDomainEnumerationReplyRemoveDomain,                      // Domain has been removed from network
+} DNSServiceDomainEnumerationReplyResultType;
+
+typedef enum
+{
+    DNSServiceDiscoverReplyFlagsFinished,
+    DNSServiceDiscoverReplyFlagsMoreComing,
+} DNSServiceDiscoveryReplyFlags;
+
+typedef void (*DNSServiceDomainEnumerationReply) (
+    DNSServiceDomainEnumerationReplyResultType                         resultType,             // One of DNSServiceDomainEnumerationReplyResultType
+    const char                                                 *replyDomain,
+    DNSServiceDiscoveryReplyFlags              flags,                  // DNS Service Discovery reply flags information
+    void                                                               *context                
+);
+
+/*!
+    @function DNSServiceDomainEnumerationCreate
+    @description Asynchronously create a DNS Domain Enumerator
+    @param registrationDomains A boolean indicating whether you are looking
+        for recommended registration domains
+        (e.g. equivalent to the AppleTalk zone list in the AppleTalk Control Panel)
+        or recommended browsing domains
+        (e.g. equivalent to the AppleTalk zone list in the Chooser).
+    @param callBack The function to be called when domains are found or removed
+    @param context A user specified context which will be passed to the callout function.
+    @result A dns_registration_t
+*/
+dns_service_discovery_ref DNSServiceDomainEnumerationCreate
+(
+    int                registrationDomains,
+    DNSServiceDomainEnumerationReply   callBack,
+    void               *context
+);
+
+/***************************************************************************/
+/*   DNS Service Browser   */
+
+typedef enum
+{
+    DNSServiceBrowserReplyAddInstance, // Instance of service found
+    DNSServiceBrowserReplyRemoveInstance       // Instance has been removed from network
+} DNSServiceBrowserReplyResultType;
+
+typedef void (*DNSServiceBrowserReply) (
+    DNSServiceBrowserReplyResultType                   resultType,             // One of DNSServiceBrowserReplyResultType
+    const char         *replyName,
+    const char         *replyType,
+    const char         *replyDomain,
+    DNSServiceDiscoveryReplyFlags                              flags,                  // DNS Service Discovery reply flags information
+    void                       *context
+);
+
+/*!
+    @function DNSServiceBrowserCreate
+    @description Asynchronously create a DNS Service browser
+    @param regtype The type of service
+    @param domain The domain in which to find the service
+    @param callBack The function to be called when service instances are found or removed
+    @param context A user specified context which will be passed to the callout function.
+    @result A dns_registration_t
+*/
+dns_service_discovery_ref DNSServiceBrowserCreate
+(
+    const char                 *regtype,
+    const char                 *domain,
+    DNSServiceBrowserReply     callBack,
+    void               *context
+);
+
+/***************************************************************************/
+/* Resolver requests */
+
+typedef void (*DNSServiceResolverReply) (
+    struct sockaddr    *interface,             // Needed for scoped addresses like link-local
+    struct sockaddr    *address,
+    const char                         *txtRecord,
+    DNSServiceDiscoveryReplyFlags                              flags,                  // DNS Service Discovery reply flags information
+    void                               *context
+);
+
+/*!
+@function DNSServiceResolverResolve
+    @description Resolved a named instance of a service to its address, port, and
+        (optionally) other demultiplexing information contained in the TXT record.
+    @param name The name of the service instance
+    @param regtype The type of service
+    @param domain The domain in which to find the service
+    @param callBack The DNSServiceResolverReply function to be called when the specified
+        address has been resolved.
+    @param context A user specified context which will be passed to the callout function.
+    @result A dns_registration_t
+*/
+
+dns_service_discovery_ref DNSServiceResolverResolve
+(
+    const char                 *name,
+    const char                 *regtype,
+    const char                 *domain,
+    DNSServiceResolverReply callBack,
+    void               *context
+);
+
+/***************************************************************************/
+/* Mach port accessor and deallocation */
+
+/*!
+    @function DNSServiceDiscoveryMachPort
+    @description Returns the mach port for a dns_service_discovery_ref
+    @param registration A dns_service_discovery_ref as returned from DNSServiceRegistrationCreate
+    @result A mach reply port which will be sent messages as appropriate.
+        These messages should be passed to the DNSServiceDiscovery_handleReply
+        function.  A NULL value indicates that no address was
+        specified or some other error occurred which prevented the
+        resolution from being started.
+*/
+mach_port_t DNSServiceDiscoveryMachPort(dns_service_discovery_ref dnsServiceDiscovery);
+
+/*!
+    @function DNSServiceDiscoveryDeallocate
+    @description Deallocates the DNS Service Discovery type / closes the connection to the server
+    @param dnsServiceDiscovery A dns_service_discovery_ref as returned from a creation or enumeration call
+    @result void
+*/
+void DNSServiceDiscoveryDeallocate(dns_service_discovery_ref dnsServiceDiscovery);
+
+/***************************************************************************/
+/* Registration updating */
+
+
+/*!
+    @function DNSServiceRegistrationAddRecord
+    @description Request that the mDNS Responder add the DNS Record of a specific type
+    @param dnsServiceDiscovery A dns_service_discovery_ref as returned from a DNSServiceRegistrationCreate call
+    @param rrtype A standard DNS Resource Record Type, from http://www.iana.org/assignments/dns-parameters
+    @param rdlen Length of the data
+    @param rdata Opaque binary Resource Record data, up to 64 kB.
+    @param ttl time to live for the added record.
+    @result DNSRecordReference An opaque reference that can be passed to the update and remove record calls.  If an error occurs, this value will be zero or negative
+*/
+DNSRecordReference DNSServiceRegistrationAddRecord(dns_service_discovery_ref dnsServiceDiscovery, uint16_t rrtype, uint16_t rdlen, const char *rdata, uint32_t ttl);
+
+/*!
+    @function DNSServiceRegistrationUpdateRecord
+    @description Request that the mDNS Responder add the DNS Record of a specific type
+    @param dnsServiceDiscovery A dns_service_discovery_ref as returned from a DNSServiceRegistrationCreate call
+    @param dnsRecordReference A dnsRecordReference as returned from a DNSServiceRegistrationAddRecord call
+    @param rdlen Length of the data
+    @param rdata Opaque binary Resource Record data, up to 64 kB.
+    @param ttl time to live for the updated record.
+    @result DNSServiceRegistrationReplyErrorType If an error occurs, this value will be non zero
+*/
+DNSServiceRegistrationReplyErrorType DNSServiceRegistrationUpdateRecord(dns_service_discovery_ref ref, DNSRecordReference reference, uint16_t rdlen, const char *rdata, uint32_t ttl);
+
+/*!
+    @function DNSServiceRegistrationRemoveRecord
+    @description Request that the mDNS Responder remove the DNS Record(s) of a specific type
+    @param dnsServiceDiscovery A dns_service_discovery_ref as returned from a DNSServiceRegistrationCreate call
+    @param dnsRecordReference A dnsRecordReference as returned from a DNSServiceRegistrationAddRecord call
+    @result DNSServiceRegistrationReplyErrorType If an error occurs, this value will be non zero
+*/
+DNSServiceRegistrationReplyErrorType DNSServiceRegistrationRemoveRecord(dns_service_discovery_ref ref, DNSRecordReference reference);
+
+
+__END_DECLS
+
+#endif /* __DNS_SERVICE_DISCOVERY_H */
diff --git a/mdns.subproj/DNSServiceDiscoveryDefines.h b/mdns.subproj/DNSServiceDiscoveryDefines.h
new file mode 100644 (file)
index 0000000..51dffe7
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2001 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+                                                               * "License").  You may not use this file except in compliance with the
+ * License.  Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
+ *
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef __DNS_SERVICE_DISCOVERY_DEFINES_H
+#define __DNS_SERVICE_DISCOVERY_DEFINES_H
+
+#include <mach/mach_types.h>
+
+#define DNS_SERVICE_DISCOVERY_SERVER "DNSServiceDiscoveryServer"
+
+typedef char    DNSCString[1024];
+typedef char    sockaddr_t[128];
+
+typedef const char * record_data_t;
+
+#endif /* __DNS_SERVICE_DISCOVERY_DEFINES_H */
+
diff --git a/mdns.subproj/DNSServiceDiscoveryReply.defs b/mdns.subproj/DNSServiceDiscoveryReply.defs
new file mode 100644 (file)
index 0000000..d26c20b
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2001 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License").  You may not use this file except in compliance with the
+ * License.  Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
+ *
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+subsystem
+       DNSServiceDiscoveryReply 7250;
+
+ServerPrefix internal_;
+
+#include <mach/std_types.defs>
+#include <mach/mach_types.defs>
+
+import "DNSServiceDiscoveryDefines.h";
+
+type DNSCString = c_string[*:1024];
+type sockaddr_t = array[128] of char;
+
+simpleroutine DNSServiceDomainEnumerationReply_rpc(
+                               reply: mach_port_t;
+                        in     resultType: int;
+                        in     replyDomain: DNSCString;
+                        in     flags: int;
+                               SendTime        to: natural_t);
+
+simpleroutine DNSServiceBrowserReply_rpc(
+                               reply: mach_port_t;
+                        in     resultType: int;
+                        in     replyName: DNSCString;
+                        in     replyType: DNSCString;
+                        in     replyDomain: DNSCString;
+                        in     flags: int;
+                               SendTime        to: natural_t);
+
+                        
+simpleroutine DNSServiceRegistrationReply_rpc(
+                               reply: mach_port_t;
+                        in     resultType: int;
+                               SendTime        to: natural_t);
+
+
+simpleroutine DNSServiceResolverReply_rpc(
+                               reply: mach_port_t;
+                        in     interface: sockaddr_t;
+                        in     address: sockaddr_t;
+                        in     txtRecord: DNSCString;
+                        in     flags: int;
+                               SendTime        to: natural_t);
+
diff --git a/mdns.subproj/DNSServiceDiscoveryRequest.defs b/mdns.subproj/DNSServiceDiscoveryRequest.defs
new file mode 100644 (file)
index 0000000..29495f8
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License").  You may not use this file except in compliance with the
+ * License.  Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
+ *
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+subsystem
+       DNSServiceDiscoveryRequest 7200;
+
+ServerPrefix provide_;
+
+#include <mach/std_types.defs>
+#include <mach/mach_types.defs>
+
+import "DNSServiceDiscoveryDefines.h";
+
+type DNSCString = c_string[*:1024];
+type record_data = ^ array [] of MACH_MSG_TYPE_BYTE
+                               ctype: record_data_t;
+
+simpleroutine DNSServiceBrowserCreate_rpc(
+                               server: mach_port_t;
+                        in     client: mach_port_t;
+                                               in      regtype: DNSCString;
+                                               in      domain: DNSCString);
+                                                
+
+simpleroutine DNSServiceDomainEnumerationCreate_rpc(
+                               server: mach_port_t;
+                        in     client: mach_port_t;
+                                               in      registrationDomains: int);
+
+simpleroutine DNSServiceRegistrationCreate_rpc(
+                               server: mach_port_t;
+                        in     client: mach_port_t;
+                        in     name: DNSCString;
+                        in     regtype: DNSCString;
+                        in     domain: DNSCString;
+                        in     port: int;
+                        in     txtRecord: DNSCString);
+
+                        
+simpleroutine DNSServiceResolverResolve_rpc(
+                               server: mach_port_t;
+                        in     client: mach_port_t;
+                        in     name: DNSCString;
+                        in     regtype: DNSCString;
+                        in     domain: DNSCString);
+
+routine DNSServiceRegistrationAddRecord_rpc(
+                               server: mach_port_t;
+                                               in client: mach_port_t;
+                                               in record_type: int;
+                                               in record_data: record_data;
+                                               in ttl: uint32_t;
+                                               out record_reference: natural_t);
+
+simpleroutine DNSServiceRegistrationUpdateRecord_rpc(
+                               server: mach_port_t;
+                                               in client: mach_port_t;
+                                                in record_reference: natural_t;
+                                               in record_data: record_data;
+                                               in ttl: uint32_t);
+
+simpleroutine DNSServiceRegistrationRemoveRecord_rpc(
+                               server: mach_port_t;
+                                               in client: mach_port_t;
+                                               in record_reference: natural_t);
+                        
diff --git a/mdns.subproj/Makefile b/mdns.subproj/Makefile
new file mode 100644 (file)
index 0000000..6b2d9b7
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# Generated by the Apple Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = mdns
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Component
+
+HFILES = DNSServiceDiscoveryDefines.h DNSServiceDiscovery.h
+
+CFILES = DNSServiceDiscovery.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble\
+            DNSServiceDiscoveryReply.defs DNSServiceDiscoveryRequest.defs
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = subproj.make
+NEXTSTEP_INSTALLDIR = /usr/local/lib/system
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_PUBLIC_HEADERS_DIR = /usr/include
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/mdns.subproj/Makefile.postamble b/mdns.subproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..b00b2ab
--- /dev/null
@@ -0,0 +1,106 @@
+###############################################################################
+#  Makefile.postamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile, which is imported after all other makefiles, to
+#  override attributes for a project's Makefile environment. This allows you  
+#  to take advantage of the environment set up by the other Makefiles. 
+#  You can also define custom rules at the end of this file.
+#
+###############################################################################
+# 
+# These variables are exported by the standard makefiles and can be 
+# used in any customizations you make.  They are *outputs* of
+# the Makefiles and should be used, not set.
+# 
+#  PRODUCTS: products to install.  All of these products will be placed in
+#       the directory $(DSTROOT)$(INSTALLDIR)
+#  GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
+#  LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
+#  OFILE_DIR: Directory into which .o object files are generated.
+#  DERIVED_SRC_DIR: Directory used for all other derived files
+#
+#  ALL_CFLAGS:  flags to pass when compiling .c files
+#  ALL_MFLAGS:  flags to pass when compiling .m files
+#  ALL_CCFLAGS:  flags to pass when compiling .cc, .cxx, and .C files
+#  ALL_MMFLAGS:  flags to pass when compiling .mm, .mxx, and .M files
+#  ALL_PRECOMPFLAGS:  flags to pass when precompiling .h files
+#  ALL_LDFLAGS:  flags to pass when linking object files
+#  ALL_LIBTOOL_FLAGS:  flags to pass when libtooling object files
+#  ALL_PSWFLAGS:  flags to pass when processing .psw and .pswm (pswrap) files
+#  ALL_RPCFLAGS:  flags to pass when processing .rpc (rpcgen) files
+#  ALL_YFLAGS:  flags to pass when processing .y (yacc) files
+#  ALL_LFLAGS:  flags to pass when processing .l (lex) files
+#
+#  NAME: name of application, bundle, subproject, palette, etc.
+#  LANGUAGES: langages in which the project is written (default "English")
+#  English_RESOURCES: localized resources (e.g. nib's, images) of project
+#  GLOBAL_RESOURCES: non-localized resources of project
+#
+#  SRCROOT:  base directory in which to place the new source files
+#  SRCPATH:  relative path from SRCROOT to present subdirectory
+#
+#  INSTALLDIR: Directory the product will be installed into by 'install' target
+#  PUBLIC_HDR_INSTALLDIR: where to install public headers.  Don't forget
+#        to prefix this with DSTROOT when you use it.
+#  PRIVATE_HDR_INSTALLDIR: where to install private headers.  Don't forget
+#       to prefix this with DSTROOT when you use it.
+#
+#  EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
+#
+###############################################################################
+
+# Some compiler flags can be overridden here for certain build situations.
+#
+#    WARNING_CFLAGS:  flag used to set warning level (defaults to -Wmost)
+#    DEBUG_SYMBOLS_CFLAGS:  debug-symbol flag passed to all builds (defaults
+#      to -g)
+#    DEBUG_BUILD_CFLAGS:  flags passed during debug builds (defaults to -DDEBUG)
+#    OPTIMIZE_BUILD_CFLAGS:  flags passed during optimized builds (defaults
+#      to -O)
+#    PROFILE_BUILD_CFLAGS:  flags passed during profile builds (defaults
+#      to -pg -DPROFILE)
+#    LOCAL_DIR_INCLUDE_DIRECTIVE:  flag used to add current directory to
+#      the include path (defaults to -I.)
+#    DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
+#      passed to ld/libtool (defaults to nothing)
+
+
+# Library and Framework projects only:
+#    INSTALL_NAME_DIRECTIVE:  This directive ensures that executables linked
+#      against the framework will run against the correct version even if
+#      the current version of the framework changes.  You may override this
+#      to "" as an alternative to using the DYLD_LIBRARY_PATH during your
+#      development cycle, but be sure to restore it before installing.
+
+
+# Ownership and permissions of files installed by 'install' target
+
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =
+        # If set, 'install' chmod's executable to this
+
+
+# Options to strip.  Note: -S strips debugging symbols (executables can be stripped
+# down further with -x or, if they load no bundles, with no options at all).
+
+#STRIPFLAGS = -S
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Include them in
+# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
+#
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
+
+mdns_hdrs: $(DSTROOT)$(PRIVATE_HDR_INSTALLDIR)$(MDNS_HEADER_DIR_SUFFIX)
+       $(SILENT) $(FASTCP) $(MDNS_HDRS) $(DSTROOT)$(PRIVATE_HDR_INSTALLDIR)$(MDNS_HEADER_DIR_SUFFIX)
+
+$(DSTROOT)$(PRIVATE_HDR_INSTALLDIR)$(MDNS_HEADER_DIR_SUFFIX):
+       $(MKDIRS) $@
diff --git a/mdns.subproj/Makefile.preamble b/mdns.subproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..2a9ecd4
--- /dev/null
@@ -0,0 +1,153 @@
+###############################################################################
+#  Makefile.preamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile for configuring the standard application makefiles 
+#  associated with ProjectBuilder. It is included before the main makefile.
+#  In Makefile.preamble you set attributes for a project, so they are available
+#  to the project's makefiles.  In contrast, you typically write additional rules or 
+#  override built-in behavior in the Makefile.postamble.
+#  
+#  Each directory in a project tree (main project plus subprojects) should 
+#  have its own Makefile.preamble and Makefile.postamble.
+###############################################################################
+#
+# Before the main makefile is included for this project, you may set:
+#
+#    MAKEFILEDIR: Directory in which to find $(MAKEFILE)
+#    MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
+
+# Compiler/linker flags added to the defaults:  The OTHER_* variables will be 
+# inherited by all nested sub-projects, but the LOCAL_ versions of the same
+# variables will not.  Put your -I, -D, -U, and -L flags in ProjectBuilder's
+# Build Attributes inspector if at all possible.  To override the default flags
+# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble.  The
+# variables below are *inputs* to the build process and distinct from the override
+# settings done (less often) in the Makefile.postamble.
+#
+#    OTHER_CFLAGS, LOCAL_CFLAGS:  additional flags to pass to the compiler
+#      Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
+#      .cc, .cxx, .C, and .M files.  There is no need to respecify the
+#      flags in OTHER_MFLAGS, etc.
+#    OTHER_MFLAGS, LOCAL_MFLAGS:  additional flags for .m files
+#    OTHER_CCFLAGS, LOCAL_CCFLAGS:  additional flags for .cc, .cxx, and ...C files
+#    OTHER_MMFLAGS, LOCAL_MMFLAGS:  additional flags for .mm and .M files
+#    OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS:  additional flags used when
+#      precompiling header files
+#    OTHER_LDFLAGS, LOCAL_LDFLAGS:  additional flags passed to ld and libtool
+#    OTHER_PSWFLAGS, LOCAL_PSWFLAGS:  additional flags passed to pswrap
+#    OTHER_RPCFLAGS, LOCAL_RPCFLAGS:  additional flags passed to rpcgen
+#    OTHER_YFLAGS, LOCAL_YFLAGS:  additional flags passed to yacc
+#    OTHER_LFLAGS, LOCAL_LFLAGS:  additional flags passed to lex
+
+# These variables provide hooks enabling you to add behavior at almost every 
+# stage of the make:
+#
+#    BEFORE_PREBUILD: targets to build before installing headers for a subproject
+#    AFTER_PREBUILD: targets to build after installing headers for a subproject
+#    BEFORE_BUILD_RECURSION: targets to make before building subprojects
+#    BEFORE_BUILD: targets to make before a build, but after subprojects
+#    AFTER_BUILD: targets to make after a build
+#
+#    BEFORE_INSTALL: targets to build before installing the product
+#    AFTER_INSTALL: targets to build after installing the product
+#    BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
+#    AFTER_POSTINSTALL: targts to build after postinstalling every subproject
+#
+#    BEFORE_INSTALLHDRS: targets to build before installing headers for a 
+#         subproject
+#    AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
+#    BEFORE_INSTALLSRC: targets to build before installing source for a subproject
+#    AFTER_INSTALLSRC: targets to build after installing source for a subproject
+#
+#    BEFORE_DEPEND: targets to build before building dependencies for a
+#        subproject
+#    AFTER_DEPEND: targets to build after building dependencies for a
+#        subproject
+#
+#    AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
+#        updated every time the project is built.  If NO, the dependency
+#        file is only built when the depend target is invoked.
+
+# Framework-related variables:
+#    FRAMEWORK_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the framework's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+
+# Library-related variables:
+#    PUBLIC_HEADER_DIR:  Determines where public exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.  For library projects you should
+#       set this to something like /Developer/Headers/$(NAME).  Do not set
+#       this variable for framework projects unless you do not want the
+#       header files included in the framework.
+#    PRIVATE_HEADER_DIR:  Determines where private exported header files
+#      should be installed.  Do not include $(DSTROOT) in this value --
+#      it is prefixed automatically.
+#    LIBRARY_STYLE:  This may be either STATIC or DYNAMIC, and determines
+#      whether the libraries produced are statically linked when they
+#      are used or if they are dynamically loadable. This defaults to
+#       DYNAMIC.
+#    LIBRARY_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
+#      where to put the library's DLL.  This variable defaults to 
+#      $(INSTALLDIR)/../Executables
+#
+#    INSTALL_AS_USER: owner of the intalled products (default root)
+#    INSTALL_AS_GROUP: group of the installed products (default wheel)
+#    INSTALL_PERMISSIONS: permissions of the installed product (default o+rX)
+#
+#    OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
+#      passed on the command line to recursive invocations of make.  Note that
+#      the values in OTHER_*FLAGS are inherited by subprojects automatically --
+#      you do not have to (and shouldn't) add OTHER_*FLAGS to 
+#      OTHER_RECURSIVE_VARIABLES. 
+
+# Additional headers to export beyond those in the PB.project:
+#    OTHER_PUBLIC_HEADERS
+#    OTHER_PROJECT_HEADERS
+#    OTHER_PRIVATE_HEADERS
+
+# Additional files for the project's product: <<path relative to proj?>>
+#    OTHER_RESOURCES: (non-localized) resources for this project
+#    OTHER_OFILES: relocatables to be linked into this project
+#    OTHER_LIBS: more libraries to link against
+#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
+#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
+#    OTHER_GARBAGE: additional files to be removed by `make clean'
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+#    BUILD_OFILES_LIST_ONLY
+
+# To include a version string, project source must exist in a directory named 
+# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
+# OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Uncomment to suppress generation of a KeyValueCoding index when installing 
+# frameworks (This index is used by WOB and IB to determine keys available
+# for an object).  Set to YES by default.
+# PREINDEX_FRAMEWORK = NO
+
+# Change this definition to install projects somewhere other than the
+# standard locations.  NEXT_ROOT defaults to "C:/Apple" on Windows systems
+# and "" on other systems.
+DSTROOT = $(HOME)
+
+# Additional flags (MiG generated files)
+OTHER_OFILES = DNSServiceDiscoveryRequestUser.o DNSServiceDiscoveryReplyServer.o
+
+#private headers
+MDNS_HDRS = DNSServiceDiscoveryRequest.defs DNSServiceDiscoveryRequest.h \
+                        DNSServiceDiscoveryReply.defs DNSServiceDiscoveryReply.h DNSServiceDiscoveryDefines.h
+
+BEFORE_INSTALLHDRS += $(SFILE_DIR) $(MDNS_HDRS)
+AFTER_INSTALLHDRS += mdns_hdrs
+PRIVATE_HEADER_DIR = /AppleInternal/Developer/Headers
+MDNS_HEADER_DIR_SUFFIX = /DNSServiceDiscovery
+
+# public headers
+OTHER_PUBLIC_HEADERS = DNSServiceDiscovery.h
+PUBLIC_HEADER_DIR_SUFFIX = /DNSServiceDiscovery
diff --git a/mdns.subproj/PB.project b/mdns.subproj/PB.project
new file mode 100644 (file)
index 0000000..eec7d5c
--- /dev/null
@@ -0,0 +1,34 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    English_RESOURCES = {}; 
+    FILESTABLE = {
+        H_FILES = (DNSServiceDiscoveryDefines.h, DNSServiceDiscovery.h); 
+        OTHER_LINKED = (DNSServiceDiscovery.c); 
+        OTHER_RESOURCES = (); 
+        OTHER_SOURCES = (
+            Makefile.preamble, 
+            Makefile, 
+            Makefile.postamble, 
+            DNSServiceDiscoveryReply.defs, 
+            DNSServiceDiscoveryRequest.defs
+        ); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDTOOL = /usr/bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/local/lib/system; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    NEXTSTEP_PUBLICHEADERSDIR = /usr/include; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = mdns; 
+    PROJECTTYPE = Component; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
index ea95aa2b068e9f8f31e9a286b2654df74a0da19f..4861159687ce2fe46aba55f565ae3477678d0425 100644 (file)
@@ -18,7 +18,7 @@ CFILES = multi_call.c ni_error.c ni_glue.c ni_pwdomain.c ni_useful.c\
          ni_util.c sys_interfaces.c
 
 OTHERSRCS = Makefile.preamble Makefile Makefile.postamble nibind_prot.x\
-            ni_prot.x
+            ni_prot.x netinfo.3 netinfo.5
 
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
index 8361d56afb6b2f9ff024f87661c29c1b15588d81..d8a74f51722d680ef2395a08c2d1c5f48fe641a4 100644 (file)
@@ -1,3 +1,12 @@
+MAN3DIR=/usr/share/man/man3
+MAN5DIR=/usr/share/man/man5
+
+install-netinfo-man:
+       install -m 755 -o root -g wheel -d $(DSTROOT)$(MAN3DIR)
+       install -m 644 -o root -g wheel -c netinfo.3 "$(DSTROOT)$(MAN3DIR)"
+       install -m 755 -o root -g wheel -d $(DSTROOT)$(MAN5DIR)
+       install -m 644 -o root -g wheel -c netinfo.5 "$(DSTROOT)$(MAN5DIR)"
+
 %_clnt.c: %.x
        $(RPCGEN) $(ALL_RPCFLAGS) -l -o $(SYM_DIR)/$*_clnt.c $*.x
 
index 77e442be658fd2102b97fafa5869fdf3eaf35786..680d1b6ba5153d8bbbd94b60e1d778c8669bfe82 100644 (file)
@@ -1,6 +1,7 @@
 OTHER_OFILES = nibind_prot_clnt.o ni_prot_clnt.o nibind_prot_xdr.o ni_prot_xdr.o
 NETINFO_HEADERS = nibind_prot.h ni_prot.h
 AFTER_PREBUILD = $(NETINFO_HEADERS)
+AFTER_POSTINSTALL += install-netinfo-man
 OTHER_PUBLIC_HEADERS = $(NETINFO_HEADERS)
 BEFORE_INSTALLHEADERS += $(NETINFO_HEADERS)
 PUBLIC_HEADER_DIR_SUFFIX = /netinfo
index 789dee70ae71e00f3c533a4f18c9d4639fdab38c..3635900f0b98daffb85155b2fe47d8a16b6394d1 100644 (file)
@@ -3,7 +3,15 @@
     FILESTABLE = {
         H_FILES = (clib.h, mm.h, ni.h, ni_util.h, sys_interfaces.h); 
         OTHER_LINKED = (multi_call.c, ni_error.c, ni_glue.c, ni_pwdomain.c, ni_useful.c, ni_util.c, sys_interfaces.c); 
-        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, nibind_prot.x, ni_prot.x); 
+        OTHER_SOURCES = (
+            Makefile.preamble, 
+            Makefile, 
+            Makefile.postamble, 
+            nibind_prot.x, 
+            ni_prot.x, 
+            netinfo.3, 
+            netinfo.5
+        ); 
         PUBLIC_HEADERS = (ni.h, ni_util.h); 
     }; 
     LANGUAGE = English; 
diff --git a/netinfo.subproj/netinfo.3 b/netinfo.subproj/netinfo.3
new file mode 100644 (file)
index 0000000..50486b7
--- /dev/null
@@ -0,0 +1,425 @@
+.TH NETINFO 3 "August 29, 1989" "Apple Computer, Inc."
+.SH NAME
+netinfo \- library routines for NetInfo calls
+.SH SYNOPSIS
+\fB#include <netinfo/ni.h>\fR
+.SH DESCRIPTION
+These calls are the programming interface to NetInfo.  Typically, 
+a handle (of type "void *") is allocated through a call to
+.I ni_new,
+.I ni_open,
+or
+.I ni_connect.
+This handle opens a connection to the given NetInfo domain.  Read calls
+may go to either the master or the clone servers, while writes will
+always go to the master server.  If the master is unavailable,
+no writes can be performed.
+The handle is then passed to one of several NetInfo routines for database
+operations and then freed using
+.I ni_free.
+Several utility routines are also supplied which operate on NetInfo data
+structures.  These routines don't require NetInfo handles.
+.LP
+.SH MACROS
+.PP
+.B NI_INDEX_NULL
+.IP
+A constant which evaluates to the highest unsigned integer.  It is useful
+for indicating something which should go at the end of a list, as opposed
+to a smaller value which indicates the precise position at which the insert
+should occur.
+.PP
+\fBNI_INIT\fR(\fIptr\fR)
+.IP
+Initializes a NetInfo data structure.  It effectively zeros out the structure
+referred to by
+.I ptr.
+This macro is useful for indicating an empty list or NULL value with one
+of the many NetInfo data structures.
+.SH "DATATYPES AND ASSOCIATED UTILITY ROUTINES"
+.PP
+.B ni_status
+.IP
+The result code of most NetInfo routines.
+.PP
+const char *\fBni_error\fR(ni_status \fIstatus\fR)
+.IP
+Returns the error string associated with the given NetInfo status.
+.PP
+.B ni_index
+.IP
+An index into a NetInfo list.
+.PP
+.B ni_id
+.IP
+NetInfo directories are identified through the
+.I ni_id
+data structure.  It records the ID of the directory in the
+.I nii_object
+field and the instance of the directory in the
+.I nii_instance
+field.  The instance indicates which version of the directory is being
+operated on and is only relevant for writes.  Each time a write is
+performed, the instance is incremented to reflect the new version.  If
+the instance given does not match the current instance of the directory,
+the error NI_STALE is returned, indicating a stale ID.  All NetInfo
+routines which operate on directories will return the latest value of
+the instance.
+.PP
+.B ni_name
+.IP
+A NetInfo name.  It is equivalent to a C string.
+.PP 
+ni_name \fBni_name_dup\fR(const ni_name \fIname\fR)
+.IP
+Returns a mallocated copy of a NetInfo name.
+.PP
+void \fBni_name_free\fR(ni_name *\fInamep\fR)
+.IP
+Frees a NetInfo name.  The pointer is converted to NULL.  A NULL pointer
+will not be freed.
+.PP
+int \fBni_name_match\fR(const ni_name \fIname1\fR, const ni_name \fIname2\fR)
+.IP
+Compares two NetInfo names for equality.  Returns non-zero for success,
+zero for failure.
+.PP
+.B ni_namelist
+.IP
+A list of NetInfo names.
+.PP
+ni_namelist \fBni_namelist_dup\fR(const ni_namelist \fInl\fR)
+.IP
+Returns a mallocated duplicate of a NetInfo namelist.
+.PP
+void \fBni_namelist_free\fR(ni_namelist *\fInl\fR)
+.IP
+Frees a NetInfo namelist.  The namelist structure is zeroed.  Zeroed
+namelists will not be freed.
+.PP
+void \fBni_namelist_insert\fR(ni_namelist *\fInl\fR, const ni_name \fIname\fR, ni_index \fIwhere\fR)
+.IP
+Duplicates and inserts the given name at the given location into the namelist.
+.PP
+void \fBni_namelist_delete\fR(ni_namelist *\fInl\fR, ni_index \fIwhere\fR)
+.IP
+Deletes and frees the name at the given location in the namelist.
+.PP
+ni_index \fBni_namelist_match\fR(const ni_namelist \fInl\fR, const ni_name \fIname\fR)
+.IP
+If the name is in the given namelist, the first index of its occurrence
+is returned.  Otherwise, NI_INDEX_NULL is returned indicating failure.
+.PP
+.B ni_property
+.IP
+A NetInfo property.  It contains a name and a namelist of associated values.
+.PP 
+ni_property \fBni_prop_dup\fR(const ni_property \fIprop\fR)
+.IP
+Returns a mallocated duplicate of the given NetInfo property.
+.PP
+void \fBni_prop_free\fR(ni_property *\fIprop\fR)
+.IP
+Frees and zeros the NetInfo property.  Zeroed properties will not be freed
+again.
+.PP
+.B ni_proplist
+.IP
+A list of NetInfo properties.
+.PP
+void \fBni_proplist_insert\fR(ni_proplist *\fIpl\fR, const ni_property \fIprop\fR, ni_index \fIwhere\fR)
+.IP
+Duplicates and inserts the given property at the given location into the given property
+list.
+.PP
+void \fBni_proplist_delete\fR(ni_proplist *\fIpl\fR, ni_index \fIwhere\fR)
+.IP
+Frees and deletes the property at the given location in the property list.
+.PP
+ni_index \fBni_proplist_match\fR(const ni_proplist \fIpl\fR, const ni_name \fIname\fR, const ni_name \fIval\fR)
+.IP
+Returns the location in the property list of the first property with a name
+of 
+.I name
+and having value
+.I val.
+NI_INDEX_NULL is returned on failure.
+If NULL is the \fIvalue\fR argument,
+\fBni_proplist_match\fR will match on only the \fIname\fR argument.
+.PP
+ni_proplist \fBni_proplist_dup\fR(const ni_proplist \fIpl\fR)
+.IP
+Returns a mallocated duplicate property list.
+.PP
+void \fBni_proplist_free\fR(ni_proplist *\fIpl\fR)
+.IP
+Frees and zeroes the property list.  A zeroed property will not be freed again.
+.PP
+.B ni_idlist
+.IP
+A list of NetInfo indices (usually directory ID's).
+.PP
+void \fBni_idlist_free\fR(ni_idlist *\fIidl\fR)
+.IP
+Frees and zeroes the given ID list.  A zeroed ID list will not be freed again.
+.PP
+.B ni_entry
+.IP
+An entry in a NetInfo directory.  It contains the ID of the directory and
+a list of values assocated with whatever property was requested in the
+.I ni_list
+routine.  The list may be NULL, indicating that there is not associated
+property for this directory.
+.PP
+.B ni_entrylist
+.IP
+A list of NetInfo entries.
+.PP
+void \fBni_entrylist_free\fR(ni_entrylist *\fIentries\fR)
+.IP
+Frees and zeros the given entry list.  A zeroed entry list will not be
+freed again.
+.LP
+.SH "ROUTINES"
+.PP
+ni_status \fBni_addrtag\fR(void *\fIhandle\fR, struct sockaddr_in *\fIaddr\fR, ni_name *\fItag\fR)
+.IP
+Returns the address and domain tag associated with the connected
+NetInfo handle.
+.PP
+ni_status \fBni_children\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_idlist *\fIidlist\fR)
+.IP
+Lists the children ID's (subdirectories) of the given directory.
+.PP
+void *\fBni_connect\fR(struct sockaddr_in *\fIaddr\fR, ni_name \fItag\fR)
+.IP
+Returns a NetInfo handle to the NetInfo domain at the given address
+and domain tag.  Returns NULL on failure.
+.PP
+ni_status \fBni_create\fR(void *\fIhandle\fR, ni_id *\fIparent\fR, ni_proplist \fIprops\fR, ni_id *\fIchild\fR, ni_index \fIwhere\fR)
+.IP
+Creates a new directory at the given index initialized with the given 
+properties.
+.PP
+ni_status \fBni_createname\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_index \fIprop_index\fR, ni_name \fIname\fR, ni_index \fIval_index\fR)
+.IP
+Inserts the name into the value list of the given directory at the property
+indexed by prop_index and value list location val_index.
+.PP
+ni_status \fBni_createprop\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_property \fIprop\fR, ni_index \fIwhere\fR)
+.IP
+Creates a new property at the given index in the given directory.
+.PP
+ni_status \fBni_destroy\fR(void *\fIhandle\fR, ni_id *\fIparent\fR, ni_id \fIchild\fR)
+.IP
+Destroys the directory child in the given parent directory.  Both instance
+must be the latest values or the error NI_STALE is returned.
+.PP
+ni_status \fBni_destroyname\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_index \fIprop_index\fR, ni_index \fIval_index\fR)
+.IP
+Destroys a property value in the given directory at the given prop_index and
+value-list val_index.
+.PP
+ni_status \fBni_destroyprop\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_index \fIwhere\fR)
+.IP
+Destroys the property at property index
+.I where
+in the given directory.
+.PP
+ni_status \fBni_fancyopen\fR(void *\fIhandle\fR, ni_name \fIdomain\fR, void **\fIrethandle\fR, ni_fancyopenargs *\fIargs\fR)
+.PP
+.nf
+typedef struct ni_fancyopenargs {
+       int rtimeout; 
+       int wtimeout; 
+       int abort;    
+       int needwrite;
+} ni_fancyopenargs;
+.fi
+.IP
+A fancier version of ni_open which allows one to set
+various attributes on the the returned handle. See 
+.I ni_setreadtimeout(), 
+.I ni_setwritetimeout(), 
+.I ni_setabort()
+and 
+.I ni_needwrite()
+for descriptions of the fields 
+in the ni_fancyopenargs structure. A 0 in the 
+rtimeout or wtimeout field indicates the 
+default timeout should be used.
+.PP
+void \fBni_free\fR(void *\fIhandle\fR)
+.IP
+Frees a NetInfo handle and closes any associated connections.
+.PP
+ni_status \fBni_list\fR(void *\fIhandle\fR, ni_id *\fIdir\fR , ni_name \fIname\fR, ni_entrylist *\fIentries\fR)
+.IP
+Lists all the subdirectories of the given directory along with any associated
+values they may have for the property 
+.I name.
+If a subdirectory doesn't have the property \fIname\fR,
+the entry is still returned but with a NULL property list.
+.PP
+ni_status \fBni_listprops\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_namelist *\fInl\fR)
+.IP
+Returns the list of property names associated with the given directory.
+.PP
+ni_status \fBni_lookup\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_name \fIname\fR, ni_name \fIval\fR, ni_idlist *\fIfound\fR)
+.IP
+Returns a list of subdirectories which satisfy the relation 
+.I name
+equals
+.I val.
+.PP
+ni_status \fBni_lookupprop\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_name \fIname\fR, ni_namelist *\fIval\fR)
+.IP
+Returns the values associated with the property named 
+.I name
+in the given directory.
+.PP
+ni_status \fBni_lookupread\fR(void *\fIhandle\fR, ni_id *\fIdirid\fR, ni_name \fIpropname\fR, ni_name \fIpropval\fR, ni_proplist *\fIprops\fR)
+.IP
+Looks up the subdirectory given the 
+.I (propname, propval\) 
+pair
+and returns the subdirectory's properties. This call is equivalent to 
+an 
+.I ni_lookup() 
+followed by an 
+.I ni_read().
+.PP
+void \fBni_needwrite\fR(void *\fIhandle\fR, int \fIneedwrite\fR)
+.IP
+Indicates whether subsequent calls will need to write to a 
+netinfo server. By default, the flag is off and the netinfo 
+library will automatically switch to a server capable of 
+writing whenever a write call occurs. However, since writes
+may take some time to reach the clone server, one could read
+stale information from a clone server and then attempt to 
+write the master based upon the stale information. Setting 
+.I needwrite
+will lock the handle onto the master netinfo server even for 
+reads to prevent this from happening.
+.PP
+ni_status \fBni_open\fR(void *\fIrelativeto\fR, ni_name \fIdomain\fR, void **\fIresult\fR)
+.IP
+Opens a connection to the NetInfo domain 
+.I domain.
+The returned handle is opened relative to the domain specified in the
+.I relativeto.
+This handle may be passed as NULL, indicating relative to the local
+NetInfo domain.  The path may contain "/"s to indicate a multilevel 
+search and may also be "." or ".." to indicate the current domain or
+parent domain, respectively.
+.PP
+ni_status \fBni_parent\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_index *\fIparent_id\fR)
+.IP
+Returns the parent ID of the given directory.
+.PP
+ni_status \fBni_pathsearch\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_name \fIpath\fR)
+.IP
+Does a multilevel lookup on a directory, relative to the given directory
+ID.  The path may contain "/"s to separative directory components.  "="s
+are used to specify relations and both may be escaped using "\\"s.  For
+example, to find the directory associated with the superuser, you may
+specify (relative to the root directory) "/name=users/uid=0".  Note that
+the equal signs are not mandatory and will default to "name=" if none
+are specified.  In the previous example, "/users/uid=0" would accomplish
+the same result.
+.PP
+ni_status \fBni_read\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_proplist *\fIprops\fR)
+.IP
+Reads all of the properties of the given directory.
+.PP
+ni_status \fBni_readname\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_index \fIprop_index\fR, ni_index \fIval_index\fR, ni_name *\fIvalue\fR)
+.IP
+Reads a value from a property in the given directory.  The value is indexed
+by property index 
+.I prop_index
+and value index
+.I val_index.
+.PP
+ni_status \fBni_readprop\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_index \fIprop_index\fr, ni_namelist *\fInl\fR)
+.IP
+Reads the value-list associated with the given property, indexed by
+.I prop_index.
+.PP
+ni_status \fBni_renameprop\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_index \fIprop_index\fR, ni_name \fInewname\fR)
+.IP
+Renames the property indexed by
+.I prop_index
+to the new name
+.I newname.
+.PP
+ni_status \fBni_resync\fR(void *\fIhandle\fR)
+.IP
+Attempts to resynchronize the clone servers with the master copy of
+the database.
+.PP
+ni_status \fBni_root\fR(void *\fIhandle\fR, ni_id *\fIdir\fR)
+.IP
+Returns the directory ID of the root of the directory tree.
+.PP
+ni_status \fBni_self\fR(void *\fIhandle\fR, ni_id *\fIdir\fR)
+.IP
+Returns the directory ID of the given directory.  Simply refreshes the
+instance field to the latest value.
+.PP
+void \fBni_setabort\fR(void *\fIhandle\fR, int \fIshouldabort\fR)
+.IP
+By default, netinfo calls will try forever until an answer 
+is returned from a server. 
+.I ni_setabort
+ allows one to have 
+netinfo return failure upon the first timeout or other failure.
+.PP
+ni_status \fBni_setpassword\fR(void *\fIhandle\fR, ni_name \fIpassword\fR)
+.IP
+Sets the password for the session to
+.I password.  
+By default, no password is sent.
+.PP
+void \fBni_setreadtimeout\fR(void *\fIhandle\fR, int \fIseconds\fR)
+.IP
+Sets the timeout associated with reads on netinfo. The timeout
+is only a hint and the effective timeout may be longer. Note
+that calls will not abort even if a timeout is set unless the
+abort flag has been set (see 
+.I ni_setabort()).
+.PP
+ni_status \fBni_setuser\fr(void *\fIhandle\fR, ni_name \fIusername\fR)
+.IP
+Changes the username associated with the session.  By default, the username
+is the one associated with the user-ID that was used during the UNIX login
+process.
+.PP
+void \fBni_setwritetimeout\fR(void *\fIhandle\fR, int \fIseconds\fR)
+.IP
+Sets the timeout associated with writes on netinfo. The timeout
+is only a hint and the effective timeout may be a longer. Note
+that calls will not abort even if a timeout is set unless the
+abort flag has been set (see 
+.I ni_setabort()).
+.PP
+ni_status \fBni_statistics\fR(void *\fIhandle\fR, ni_proplist *\fIstatistics\fR)
+.IP
+Returns various statistics from the server.
+.PP
+ni_status \fBni_write\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_proplist \fIprops\fR)
+.IP
+Writes a new property list to the directory.
+.PP
+ni_status \fBni_writename\fr(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_index \fIprop_index\fr, ni_index \fIname_index\fR, ni_name \fIval\fR)
+.IP
+Writes a new property value to the property indexed by
+.I prop_index
+and value indexed by
+.I val_index.
+.PP
+ni_status \fBni_writeprop\fr(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_index \fIprop_index\fR, ni_namelist \fIvalues\fR) 
+.IP
+Writes a new value list to the property indexed by
+.I prop_index.
+It is allowable to have more than one property with the same name.
+.IP
diff --git a/netinfo.subproj/netinfo.5 b/netinfo.subproj/netinfo.5
new file mode 100644 (file)
index 0000000..aea5803
--- /dev/null
@@ -0,0 +1,278 @@
+.TH NETINFO 5 "October 8, 1990" "Apple Computer, Inc."
+.SH NAME
+netinfo \- network administrative information
+.SH DESCRIPTION
+NetInfo stores its administration information in a hierarchical database.
+The hierarchy is composed of nodes called NetInfo
+.I directories.
+Each directory may have zero or more NetInfo
+.I properties
+associated with it.
+Each property has a 
+.I name
+and zero or more
+.I values.
+.PP
+This man page describes those directories and properties which have
+meaning in the system distributed by Apple. Users and 3rd-parties may
+create other directories and properties, which of course cannot be
+described here.
+.PP
+.I Search Policy
+.PP
+Virtually everything that utilizes NetInfo for lookups adheres to the
+following convention. Search the local domain first. If found, return
+the answer. Otherwise, try the next level up and so on until the top
+of the domain hierarchy is reached. For compatibility with Yellow Pages
+and BIND, see 
+.I lookupd(8).
+.PP
+.I Database Format
+.PP
+At the top level, the root directory contains a single property called
+.I master.
+This properties indicates who is the master of this database, i.e., which
+server contains the master copy of the database. The singular value of master
+contains two fields, a hostname and a domain tag separated by a '/' which 
+uniquely identifies the machine and process serving as master of this data.
+For example, the entry 
+.I clothier/network
+says that the 
+.I netinfod(8) 
+process serving domain tag
+.I network
+on the machine 
+.I clothier 
+controls the master copy of the database.
+.PP
+For added security, a second property can be installed in the root directory
+to limit who can connect to the domain. By default, anybody can connect to
+the domain, which would allow them to read anything that is there (writes are
+protected however). If this default is undesirable, a property called
+.I trusted_networks
+should be enabled in the root directory. Its values should be the network 
+(or subnet) addresses which are assumed to contain trusted machines which
+are allowed to connect to the domain. Any other clients are assumed to be
+untrustworthy. A name may be used instead of an address. If a name is given,
+then that name should be listed as a subdirectory of "/networks" within the
+same domain and resolve to the appropriate network address. 
+.PP
+At the second level, the following directories exist which have the
+following names (property named "name" has these values):
+.PP
+.RS
+.I aliases
+.LP
+.I groups
+.LP
+.I machines
+.LP
+.I mounts
+.LP
+.I networks
+.LP
+.I printers
+.LP
+.I protocols
+.LP
+.I rpcs
+.LP
+.I services
+.LP
+.I users
+.RE
+.PP
+These directories contain, for the most part, only the single property
+named "name". The exception is the "machines" directory which  contains
+other properties having to do with automatic host installation. These 
+properties are the following:
+.PP
+.RS
+"promiscuous" - if it exists, the bootpd(8) daemon is 
+promiscuous. Has no value.
+.LP
+"assignable_ipaddr" - a range of IP addresses to automatically assigned,
+specified with two values as endpoints.
+.LP
+"configuration_ipaddr" - the temporary IP address given to unknown machines in the process of booting.
+.LP
+"default_bootfile" - the default bootfile to assign to a new machine.
+.LP
+"net_passwd" - optional property. If it exists, it's the encrypted password
+for protecting automatic host installations.
+.RE
+.PP
+The directory "/aliases" contains directories which refer to individual
+mailing aliases. The relevant properties are:
+.PP
+.RS
+"name" - the name of the alias
+.LP
+"members" - a list of values, each of which is a member of this alias.
+.RE
+.PP
+The directory "/groups" contains directories which refer to individual
+system groups. The relevant properties are:
+.PP
+.RS
+"name" - the name of the system group
+.LP
+"passwd" - the associated password
+.LP
+"gid" - the associated group id
+.LP
+"users" - a list of values, each of which is a user who is a member
+of this system group.
+.RE
+.PP
+The directory "/machines" contains directories which refer to individual
+machines. The relevant properties are:
+.PP
+.RS
+"name" - the name of this machine. This property can have multiple values 
+if the machine name has aliases.
+.LP
+"ip_address" - the Internet Protocol address of the machine. This property
+can have multiple values if the machine has multiple IP addresses. Note
+that the address MUST be stored in decimal-dot notation with no leading
+zeroes.
+.LP
+"en_address" - the Ethernet address of the machine. Note that the address
+MUST be stored in standard 6 field hex Ethernet notation, with no leading
+zeros. For example, "0:0:f:0:7:5a" is a valid Ethernet address, 
+"00:00:0f:00:07:5a" is not.
+.LP
+"serves" - a list of values, each of which is information about which
+NetInfo domains this machine serves. Each value has the format
+.I domain-name/domain-tag.
+The domain name is the external name of the domain served by this machine as 
+seen from this level of hierarchy. The domain tag is the internal
+name associated with the actual process on the machine that serves this
+information.
+.LP
+"bootfile" - the name of the kernel that this machine will use by 
+default when NetBooting.
+.LP
+"bootparams" - a list of values, each of which is a Bootparams protocol
+key-value pair. For example, "root=parrish:/" has the Bootparams key
+"root" and Bootparams value "parrish:/".
+.LP
+"netgroups" - a list of values, each of which is the name of a netgroup
+of which this machine is a member.
+.RE
+.PP
+The directory "/mounts" contains directories which refer to filesystems.
+The relevant properties are:
+.PP
+.RS
+"name" - the name of the filesytem. For example, "/dev/od0a" or
+"papazian:/".
+.LP
+"dir" - the directory upon which this filesystem is mounted.
+.LP
+"type" - the filesystem type of the mount
+.LP
+"opts" - a list of values, each of which is a
+.I mount(8)
+option associated with the mounting of this filesystem.
+.LP
+"passno" - pass number on parallel 
+.I fsck(8)
+.LP
+"freq" - dump frequency, in days.
+.RE
+.PP
+The directory "/networks" contains directories which refer to Internet
+networks. The relevant properties are:
+.PP
+.RS
+"name" - the name of the network. If the network has aliases, there
+may be more than one value for this property.
+.LP
+"address" - the network number of this network. The value MUST be
+in decimal-dot notation with no leading zeroes.
+.RE
+.PP
+The directory "/printers" contains directories which refer to
+printer entries. The relevant properties are:
+.PP
+.RS
+"name" - the name of the printer. If the printer has alias, this
+property will have multiple values.
+.LP
+"lp", "sd", etc. - the names of 
+.I printcap(5)
+properties associated with this printer. If the value associated with
+the property name is numeric, the number has a leading "#" prepended
+to it.
+.RE
+.PP
+The directory "/protocols" contains directories which refer to 
+transport protocols. The relevant properties are:
+.PP
+.RS
+"name" - the name of the protocol. If the protocol has aliases, the
+property will have multiple values.
+.LP
+"number" - the associated protocol number.
+.RE
+.PP
+The directory "/services" contains directories which refer to
+ARPA services. The relevant properties are:
+.PP
+.RS
+"name" - the name of the service. If the service has aliases, the
+property will have multiple values.
+.LP
+"protocol" - the name of the protocol upon which the service runs.
+If the service runs on multiple protocols, this property will have
+multiple values.
+.LP
+"port" - the associated port number of the service.
+.RE
+.PP
+The directory "/users" contains information which refer to users.
+The relevant properties are:
+.PP
+.RS
+"name" - the login name of the user.
+.LP
+"passwd" - the encrypted password of the user.
+.LP
+"uid" - the user id of the user.
+.LP
+"gid" - the default group id of the user.
+.LP
+"realname" - the real name of the user.
+.LP
+"home" - the home directory of the user.
+.LP
+"shell" - the login shell of the user.
+.SH "SEE ALSO"
+.I aliases(5)
+.LP
+.I bootparams(5)
+.LP
+.I bootptab(5)
+.LP
+.I fstab(5)
+.LP
+.I group(5)
+.LP
+.I hosts(5)
+.LP
+.I lookupd(8)
+.LP
+.I netinfod(8)
+.LP
+.I netgroup(5)
+.LP
+.I networks(5)
+.LP
+.I passwd(5)
+.LP
+.I printcap(5)
+.LP
+.I protocols(5)
+.LP
+.I services(5)
index b6129bc42e61b88b3092fdb63e0605b85ac4c887..7ec53c910170a24c8119387ded1e522ac5574c7c 100644 (file)
@@ -26,6 +26,7 @@
  * Copyright (C) 1989 by NeXT, Inc.
  */
 #include <libc.h>
+#include <string.h>
 #include <syslog.h>
 #include <netinfo/ni.h>
 #include <rpc/pmap_clnt.h>
@@ -85,6 +86,8 @@ static const ni_name NAME_MASTER = "master";
 static const ni_name NAME_USERS = "users";
 static const ni_name NAME_UID = "uid";
 
+static const ni_name NAME_DOMAIN_SERVERS = "domain_servers";
+
 typedef struct getreg_stuff {
        nibind_getregister_res res;
        ni_private *ni;
@@ -682,9 +685,12 @@ confirm_tcp(
                 * Somebody closed our socket. Do not close it, it could
                 * be owned by somebody else now.
                 */
-               auth_destroy(ni->tc->cl_auth);
-               clnt_destroy(ni->tc);
-               ni->tc = NULL;
+               if (ni->tc != NULL)
+               {
+                       if (ni->tc->cl_auth != NULL) auth_destroy(ni->tc->cl_auth);
+                       clnt_destroy(ni->tc);
+                       ni->tc = NULL;
+               }
        }
        if (!needwrite && !rebind(ni) && ni->abort) {
                return (0);
@@ -837,9 +843,10 @@ callit(
                                }
                                return (resp);
                        }
-                       clnt_geterr(ni->tc, &err);
-                       if (err.re_status != RPC_CANTRECV) {
-                               break;
+                       if (ni->tc != NULL)
+                       {
+                               clnt_geterr(ni->tc, &err);
+                               if (err.re_status != RPC_CANTRECV) break;
                        }
                        if (i + 1 < NI_MAXCONNTRIES) {
                                /*
@@ -1016,13 +1023,47 @@ match(
 }
 
 
+static void
+add_addr_tag(ni_private *ni, ni_name addrtag)
+{
+       struct in_addr addr;
+       ni_name tag;
+       char *slash;
+
+       slash = strchr(addrtag, '/');
+       if (slash == NULL) return;
+
+       tag = slash + 1;
+       if (tag[0] == '\0') return;
+
+       *slash = '\0';
+
+       if (inet_aton(addrtag, &addr) == 0) return;
+
+       if (ni->naddrs == 0)
+       {
+               ni->addrs = (struct in_addr *)calloc(1, sizeof(struct in_addr));
+               if (ni->addrs == NULL) return;
+
+               ni->tags = (ni_name *)calloc(1, sizeof(ni_name));
+               if (ni->tags == NULL) return;
+       }
+       else
+       {
+               ni->addrs = (struct in_addr *)realloc(ni->addrs, ((ni->naddrs + 1) * sizeof(struct in_addr)));
+               if (ni->addrs == NULL) return;
+
+               ni->tags = (ni_name *)realloc(ni->tags, ((ni->naddrs + 1) * sizeof(ni_name)));
+               if (ni->tags == NULL) return;
+       }
+
+       ni->addrs[ni->naddrs] = addr;
+       ni->tags[ni->naddrs] = ni_name_dup(tag);
+       ni->naddrs++;
+}
+
 static int
-addaddr(
-       void *ni,
-       ni_index ido,
-       ni_name tag,
-       ni_private *target_ni
-       )
+addaddr(void *ni, ni_index ido, ni_name tag, ni_private *target_ni)
 {
        ni_id id;
        ni_namelist nl;
@@ -1031,172 +1072,141 @@ addaddr(
 
        id.nii_object = ido;
        NI_INIT(&nl);
-       if (ni_lookupprop(ni, &id, NAME_IP_ADDRESS, &nl) != NI_OK) {
-               return (0);
-       }
-       if (nl.ninl_len == 0) {
-               return(0);
-       }
+       if (ni_lookupprop(ni, &id, NAME_IP_ADDRESS, &nl) != NI_OK) return 0;
 
-       if (target_ni->naddrs == 0) {
-               target_ni->addrs =
-                       (struct in_addr *)malloc(nl.ninl_len * sizeof(struct in_addr));
-               target_ni->tags =
-                       (ni_name *)malloc(nl.ninl_len * sizeof(ni_name));
-       } else {
-               target_ni->addrs =
-                       (struct in_addr *)realloc(target_ni->addrs,
-                                               ((target_ni->naddrs + nl.ninl_len) * sizeof(struct in_addr)));
-               target_ni->tags =
-                       (ni_name *)realloc(target_ni->tags,
-                                               ((target_ni->naddrs + nl.ninl_len) * sizeof(ni_name)));
+       if (nl.ni_namelist_len == 0) return 0;
+
+       if (target_ni->naddrs == 0) 
+       {
+               target_ni->addrs = (struct in_addr *)malloc(nl.ni_namelist_len * sizeof(struct in_addr));
+               target_ni->tags = (ni_name *)malloc(nl.ni_namelist_len * sizeof(ni_name));
+       }
+       else
+       {
+               target_ni->addrs = (struct in_addr *)realloc(target_ni->addrs, ((target_ni->naddrs + nl.ni_namelist_len) * sizeof(struct in_addr)));
+               target_ni->tags = (ni_name *)realloc(target_ni->tags, ((target_ni->naddrs + nl.ni_namelist_len) * sizeof(ni_name)));
        }
 
-       for (i=0; i<nl.ninl_len; i++) {
-               addr.s_addr = inet_addr(nl.ninl_val[i]);
+       for (i = 0; i < nl.ni_namelist_len; i++)
+       {
+               addr.s_addr = inet_addr(nl.ni_namelist_val[i]);
                target_ni->addrs[target_ni->naddrs] = addr;
                target_ni->tags[target_ni->naddrs] = ni_name_dup(tag);
                target_ni->naddrs++;
        }
 
        ni_namelist_free(&nl);
-       return (1);
+       return 1;
 }
 
-
 static int
-get_daddr(
-         ni_private *ni,
-         ni_name dom,
-         ni_private *target_ni
-       )
+get_daddr(ni_private *ni, ni_name dom, ni_private *target_ni)
 {
-       ni_id id;
+       ni_id nid;
        ni_idlist ids;
-       ni_namelist nl;
        ni_entrylist entries;
+       ni_proplist pl;
        ni_index i;
        ni_index j;
        ni_name tag;
 
-       if (ni_root(ni, &id) != NI_OK) {
-               return(0);
+       if (dom == NULL) return 0;
+
+       if (!strcmp(dom, "."))
+       {
+               /* check for server list */
+               NI_INIT(&pl);
+               if (ni_statistics(ni, &pl) == NI_OK)
+               {
+                       i = ni_proplist_match(pl, NAME_DOMAIN_SERVERS, NULL);
+                       if (i != NI_INDEX_NULL)
+                       {
+                               if (pl.ni_proplist_val[i].nip_val.ni_namelist_len > 0)
+                               {
+                                       for (j = 0; j < pl.ni_proplist_val[i].nip_val.ni_namelist_len; j++)
+                                       {
+                                               add_addr_tag(target_ni, pl.ni_proplist_val[i].nip_val.ni_namelist_val[j]);
+                                       }
+                                       ni_proplist_free(&pl);
+                                       return 1;
+                               }
+                       }
+                       ni_proplist_free(&pl);
+               }
        }
 
+       if (ni_root(ni, &nid) != NI_OK) return 0;
        NI_INIT(&ids);
-       if (ni_lookup(ni, &id, NAME_NAME, NAME_MACHINES, &ids) != NI_OK) {
-               return (0);
-       }
+       if (ni_lookup(ni, &nid, NAME_NAME, NAME_MACHINES, &ids) != NI_OK) return 0;
 
-       id.nii_object = ids.niil_val[0];
+       nid.nii_object = ids.niil_val[0];
        ni_idlist_free(&ids);
 
        NI_INIT(&entries);
-       if (ni_list(ni, &id, NAME_SERVES, &entries) != NI_OK) {
-               return (0);
-       }
+       if (ni_list(ni, &nid, NAME_SERVES, &entries) != NI_OK) return 0;
 
-       for (i = 0; i < entries.niel_len; i++) {
-               if (entries.niel_val[i].names != NULL) {
-                       nl = *entries.niel_val[i].names;
-                       for (j = 0; j < nl.ninl_len; j++) {
-                               if (match(dom, nl.ninl_val[j], &tag)) {
-                                       if (addaddr(ni,
-                                                   entries.niel_val[i].id,
-                                                   tag,
-                                                   target_ni)) {
-                                               ni_name_free(&tag);
-                                               break;
-                                       }
-                                       ni_name_free(&tag);
-                               }
+       for (i = 0; i < entries.niel_len; i++)
+       {
+               if (entries.niel_val[i].names == NULL) continue;
+
+               for (j = 0; j < entries.niel_val[i].names->ni_namelist_len; j++)
+               {
+                       if (match(dom, entries.niel_val[i].names->ni_namelist_val[j], &tag))
+                       {
+                               addaddr(ni, entries.niel_val[i].id, tag, target_ni);
+                               ni_name_free(&tag);
                        }
                }
-
        }
+
        ni_entrylist_free(&entries);
        return (target_ni->naddrs > 0);
 }
 
-
-#ifdef notdef
-static int
-get_haddr(
-         ni_private *ni,
-         ni_name hname,
-         ni_name tag,
-         ni_private *target_ni
-       )
-{
-       ni_id id;
-       ni_idlist ids;
-
-       if (ni_root(ni, &id) != NI_OK) {
-               return(0);
-       }
-       NI_INIT(&ids);
-       if (ni_lookup(ni, &id, NAME_NAME, NAME_MACHINES, &ids) != NI_OK) {
-               return (0);
-       }
-       id.nii_object = ids.niil_val[0];
-       ni_idlist_free(&ids);
-
-       NI_INIT(&ids);
-       if (ni_lookup(ni, &id, NAME_NAME, hname, &ids) != NI_OK) {
-               return (0);
-       }
-       id.nii_object = ids.niil_val[0];
-       ni_idlist_free(&ids);
-       if (!addaddr(ni, id.nii_object, tag, target_ni)) {
-               return (0);
-       }
-       return (1);
-}
-#endif
-
-
 static ni_status
 getparent(ni_private *oldni, ni_private **newni)
 {
        ni_rparent_res *resp;
-       ni_private *ni;
+       ni_private *ni = NULL;
        ni_private *dupni;
-       int found;
+       int found = 0;
        ni_index i;
        struct in_addr raddr;
        int printed = 0;
        int inlist = 0;
 
-       found = 0;
-       while (!found) {
+       while (found == 0)
+       {
                /*
                 * First, find our parent, any parent
                 */
-               for (;;) {
+               for (;;)
+               {
                        resp = RCALLIT(oldni, _ni_rparent_2, NULL);
-                       if (resp == NULL) {
-                               return (NI_FAILED);
-                       }
-                       if (resp->status != NI_NORESPONSE) {
-                               break;
-                       }
-                       if (!printed) {
+                       if (resp == NULL) return NI_FAILED;
+                       if (resp->status != NI_NORESPONSE) break;
+
+                       if (!printed)
+                       {
                                syslog(LOG_ERR, "NetInfo timeout finding server for parent of %s/%s, sleeping",
                                        inet_ntoa(oldni->addrs[0]), oldni->tags[0]);
                                printed++;
                        }
+
                        sleep(NI_SLEEPTIME);
                }
-               if (printed) {
+
+               if (printed)
+               {
                        raddr.s_addr = htonl(resp->ni_rparent_res_u.binding.addr);
                        
                        syslog(LOG_ERR, "NetInfo %s/%s found parent %s/%s",
                                        inet_ntoa(oldni->addrs[0]), oldni->tags[0],
                                        inet_ntoa(raddr), resp->ni_rparent_res_u.binding.tag);
                }
-               if (resp->status != NI_OK) {
-                       return (resp->status);
-               }
+
+               if (resp->status != NI_OK) return (resp->status);
+
                ni = ni_alloc();
                *ni = *oldni;
                ni_clear(ni);
@@ -1212,15 +1222,19 @@ getparent(ni_private *oldni, ni_private **newni)
                ni = ni_alloc();
                *ni = *dupni;
                ni_clear(ni);
-               if (get_daddr(dupni, ".", ni)) {
-
+               if (get_daddr(dupni, ".", ni) == 0) 
+               {
+                       if (oldni->abort == 1) break;
+               }
+               else
+               {
                        /*
-                        * Now make sure returned parent is head of
-                        * list
+                        * Make sure returned parent is head of list
                         */
-                       for (i = 0; i < ni->naddrs; i++) {
-                               if (ni->addrs[i].s_addr ==
-                                   dupni->addrs[0].s_addr) {
+                       for (i = 0; i < ni->naddrs; i++)
+                       {
+                               if (ni->addrs[i].s_addr == dupni->addrs[0].s_addr)
+                               {
                                        ni_switch(ni, i);
                                        inlist++;
                                        break;
@@ -1236,13 +1250,14 @@ getparent(ni_private *oldni, ni_private **newni)
                        dupni->tsock = -1;
                        dupni->tport = -1;
                        dupni->tc = NULL;
-                       found++;
+                       found = 1;
 
                        /*
                         * If returned parent wasn't in list, it's a rogue.
                         * Log an error and drop the connection.
                         */
-                       if (inlist == 0) {
+                       if (inlist == 0)
+                       {
                                syslog(LOG_ERR, "Rogue NetInfo server detected: %s/%s",
                                        inet_ntoa(dupni->addrs[0]), dupni->tags[0]);
                                reinit(ni);
@@ -1251,13 +1266,15 @@ getparent(ni_private *oldni, ni_private **newni)
                }
                ni_free(dupni);
        }
-       if (found) {
+
+       if (found)
+       {
                *newni = ni;
-               return (NI_OK);
-       } else {
-               ni_free(ni);
-               return (NI_FAILED);
+               return NI_OK;
        }
+
+       if (ni != NULL) ni_free(ni);
+       return NI_FAILED;
 }
 
 
index 1f881e97a7d7b52bf6faa98301aa3e23f6e18146..e99f78ce21f0374e892d061ac8b5914b902a0af5 100644 (file)
@@ -436,22 +436,26 @@ ni_find(void **dom, ni_id *nid, ni_name dirname, unsigned int timeout)
        void *d, *p;
        ni_id n;
        ni_status status;
+       struct sockaddr_in addr;
 
        *dom = NULL;
        nid->nii_object = NI_INDEX_NULL;
        nid->nii_instance = NI_INDEX_NULL;
        
-       status = ni_open(NULL, ".", &d);
-       if (status != NI_OK) return status;
+       memset(&addr, 0, sizeof(struct sockaddr_in));
+       addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
 
-       if (timeout > 0)
-       {
-               ni_setreadtimeout(d, timeout);
-               ni_setabort(d, 1);
-       }
+       d = ni_connect(&addr, "local");
+       if (d == NULL) return NI_FAILED;
 
        while (d != NULL)
        {
+               if (timeout > 0)
+               {
+                       ni_setreadtimeout(d, timeout);
+                       ni_setabort(d, 1);
+               }
+
                status = ni_pathsearch(d, &n, dirname);
                if (status == NI_OK)
                {
@@ -478,11 +482,7 @@ ni_search(void *handle, ni_id *dir, ni_name name, ni_name expr, int flags, ni_en
        ni_namelist *nl;
        ni_status status;
 
-       /* get subdirectory list */
-       NI_INIT(&el);
-       status = ni_list(handle, dir, name, &el);
-       if (status != NI_OK) return status;
-
+       /* compile the regular expression */
        cexp = (regex_t *)malloc(sizeof(regex_t));
        memset(cexp, 0, sizeof(regex_t));
        i = regcomp(cexp, expr, flags);
@@ -492,6 +492,16 @@ ni_search(void *handle, ni_id *dir, ni_name name, ni_name expr, int flags, ni_en
                return NI_FAILED;
        }
 
+       /* get subdirectory list */
+       NI_INIT(&el);
+       status = ni_list(handle, dir, name, &el);
+       if (status != NI_OK)
+       {
+               regfree(cexp);
+               free(cexp);
+               return status;
+       }
+
        for (i = 0; i < el.ni_entrylist_len; i++)
        {
                if (el.ni_entrylist_val[i].names == NULL) continue;
index d04f3e080681a339e669da1bbd3893ecaed92b4d..682da1a0d1c5dd575c8c349bca23299d5c49808f 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <ifaddrs.h>
 #include "sys_interfaces.h"
 
 __private_extern__ interface_list_t *
 sys_interfaces(void)
 {
-       struct ifconf ifc;
-       struct ifreq *ifr;
-       char buf[1024]; /* XXX */
-       int offset, addrlen, extra, delta;
-       int sock;
+       interface_list_t *my_interfaces = NULL;
        interface_t *iface;
-       interface_list_t *my_interfaces;
+       struct ifaddrs *ifa, *p;
 
-       sock = socket(AF_INET, SOCK_DGRAM, 0);
-
-       if (sock < 0) return NULL;
-
-       ifc.ifc_len = sizeof(buf);
-       ifc.ifc_buf = buf;
-
-       if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0)
-       {
-               close(sock);
-               return NULL;
-       }
+       if (getifaddrs(&ifa) < 0) return NULL;
 
        my_interfaces = (interface_list_t *)malloc(sizeof(interface_list_t));
        my_interfaces->count = 0;
        my_interfaces->interface = NULL;
 
-       delta = sizeof(struct ifreq);
-       addrlen = delta - IFNAMSIZ;
-       extra = 0;
-
-       offset = 0;
-
-       while (offset <= ifc.ifc_len)
+       for (p = ifa; p != NULL; p = p->ifa_next)
        {
-               ifr = (struct ifreq *)(ifc.ifc_buf + offset);
-
-#ifndef _NO_SOCKADDR_LENGTH_
-               extra = ifr->ifr_addr.sa_len - addrlen;
-               if (extra < 0) extra = 0;
-#endif
-
-               offset = offset + delta + extra;
-
-               if (ifr->ifr_addr.sa_family != AF_INET) continue;
-               if (ioctl(sock, SIOCGIFFLAGS, (char *)ifr) < 0) continue;
+               if (p->ifa_addr == NULL) continue;
+               if ((p->ifa_flags & IFF_UP) == 0) continue;
+               if (p->ifa_addr->sa_family != AF_INET) continue;
 
                my_interfaces->count++;
                if (my_interfaces->count == 1)
@@ -87,26 +59,32 @@ sys_interfaces(void)
 
                iface = &(my_interfaces->interface[my_interfaces->count - 1]);
                memset(iface, 0, sizeof(interface_t));
-
-               memmove(iface->name, ifr->ifr_name, IFNAMSIZ);
-               iface->flags = ifr->ifr_ifru.ifru_flags;
-               iface->addr.s_addr = ((struct sockaddr_in *)&(ifr->ifr_addr))->sin_addr.s_addr;
-               ioctl(sock, SIOCGIFNETMASK, (char *)ifr);
-               iface->mask.s_addr = ((struct sockaddr_in *)&(ifr->ifr_addr))->sin_addr.s_addr;
+               iface->name = strdup(p->ifa_name);
+               iface->flags = p->ifa_flags;
+               iface->addr.s_addr = ((struct sockaddr_in *)(p->ifa_addr))->sin_addr.s_addr;
+               iface->mask.s_addr = ((struct sockaddr_in *)(p->ifa_netmask))->sin_addr.s_addr;
                iface->netaddr.s_addr = iface->addr.s_addr & iface->mask.s_addr;
                iface->bcast.s_addr = iface->netaddr.s_addr | (~iface->mask.s_addr);
        }
 
-       close(sock);
+       freeifaddrs(ifa);
+
        return my_interfaces;
 }
 
 __private_extern__  void
 sys_interfaces_release(interface_list_t *l)
 {
+       int i;
+
        if (l == NULL) return;
 
-       if (l->interface != NULL) free(l->interface);
+       for (i = 0; i < l->count; i++)
+       {
+               if (l->interface[i].name != NULL) free(l->interface[i].name);
+       }
+
+       free(l->interface);
        free(l);
 }
 
index 154ac5ba41f71e65dc17ca304dab8cc7f7eab63e..03d4d5254055221d1132f5120fd32abc4ead9bcf 100644 (file)
 #define __SYS_INTERFACES__
 
 #include <sys/types.h>
+#include <netinet/in.h>
 #include <sys/socket.h>
-#include <sys/ioctl.h>
 #include <net/if.h>
-#include <netinet/in.h>
 
 typedef struct
 {
-       char name[IFNAMSIZ];
+       char *name;
        short flags;
        struct in_addr addr;
        struct in_addr mask;
@@ -47,7 +46,7 @@ typedef struct
        interface_t *interface;
 } interface_list_t;
 
-interface_list_t * sys_interfaces(void);
+interface_list_t *sys_interfaces(void);
 void sys_interfaces_release(interface_list_t *l);
 int sys_is_my_address(interface_list_t *l, struct in_addr *a);
 int sys_is_my_network(interface_list_t *l, struct in_addr *a);
index fd7babbd24c8d4886069a04cbe93d42ef47ebdf8..05745d445f1e3d532d4422ab6851c82fd2eff166 100644 (file)
@@ -25,7 +25,10 @@ CFILES = getdomainname.c getnetgrent.c innetgr.c setdomainname.c\
          yp_all.c yp_bind.c yp_first.c yp_get_default_domain.c\
          yp_maplist.c yp_master.c yp_order.c
 
-OTHERSRCS = Makefile.preamble Makefile
+OTHERSRCS = Makefile.preamble Makefile yp_all.3 yp_bind.3 yp_first.3\
+            yp_get_default_domain.3 yp_master.3 yp_match.3 yp_next.3\
+            yp_order.3 yp_unbind.3 ypclnt.3 yperr_string.3 ypprot_err.3\
+            ypserv.acl.5
 
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
index eb861200297f1d631850ca5792f59074f8f408bd..5001fae165e4448bfe062fd6b44eb2999596f2a4 100644 (file)
@@ -1 +1,2 @@
+AFTER_POSTINSTALL += install-nis-man
 PUBLIC_HEADER_DIR_SUFFIX = /rpcsvc
index 6d2b72e9b614a9382e97c2d32eae1f507d7182c3..ecec27f6504f67656c40d834058455b6b9d8ccd8 100644 (file)
             yp_master.c, 
             yp_order.c
         ); 
-        OTHER_SOURCES = (Makefile.preamble, Makefile); 
+        OTHER_SOURCES = (
+            Makefile.preamble, 
+            Makefile, 
+            yp_all.3, 
+            yp_bind.3, 
+            yp_first.3, 
+            yp_get_default_domain.3, 
+            yp_master.3, 
+            yp_match.3, 
+            yp_next.3, 
+            yp_order.3, 
+            yp_unbind.3, 
+            ypclnt.3, 
+            yperr_string.3, 
+            ypprot_err.3, 
+            ypserv.acl.5
+        ); 
         PUBLIC_HEADERS = (ypclnt.h, yp_prot.h); 
     }; 
     LANGUAGE = English; 
index d146233c0f2286c042a7b37399fd9d7d46a0e318..6553520c4828dd81acec5a90bca617d400140135 100644 (file)
@@ -329,9 +329,9 @@ makekey(key,name,domain)
        register char *name;
        register char *domain;
 {
-       while (*key++ = *name++)
+       while ((*key++ = *name++))
                ;
        *(key-1) = '.';
-       while (*key++ = *domain++)
+       while ((*key++ = *domain++))
                ;
 }      
diff --git a/nis.subproj/yp_all.3 b/nis.subproj/yp_all.3
new file mode 100644 (file)
index 0000000..ee71c09
--- /dev/null
@@ -0,0 +1 @@
+.so man3/ypclnt.3
diff --git a/nis.subproj/yp_bind.3 b/nis.subproj/yp_bind.3
new file mode 100644 (file)
index 0000000..ee71c09
--- /dev/null
@@ -0,0 +1 @@
+.so man3/ypclnt.3
diff --git a/nis.subproj/yp_first.3 b/nis.subproj/yp_first.3
new file mode 100644 (file)
index 0000000..ee71c09
--- /dev/null
@@ -0,0 +1 @@
+.so man3/ypclnt.3
diff --git a/nis.subproj/yp_get_default_domain.3 b/nis.subproj/yp_get_default_domain.3
new file mode 100644 (file)
index 0000000..ee71c09
--- /dev/null
@@ -0,0 +1 @@
+.so man3/ypclnt.3
diff --git a/nis.subproj/yp_master.3 b/nis.subproj/yp_master.3
new file mode 100644 (file)
index 0000000..ee71c09
--- /dev/null
@@ -0,0 +1 @@
+.so man3/ypclnt.3
diff --git a/nis.subproj/yp_match.3 b/nis.subproj/yp_match.3
new file mode 100644 (file)
index 0000000..ee71c09
--- /dev/null
@@ -0,0 +1 @@
+.so man3/ypclnt.3
diff --git a/nis.subproj/yp_next.3 b/nis.subproj/yp_next.3
new file mode 100644 (file)
index 0000000..ee71c09
--- /dev/null
@@ -0,0 +1 @@
+.so man3/ypclnt.3
diff --git a/nis.subproj/yp_order.3 b/nis.subproj/yp_order.3
new file mode 100644 (file)
index 0000000..ee71c09
--- /dev/null
@@ -0,0 +1 @@
+.so man3/ypclnt.3
diff --git a/nis.subproj/yp_unbind.3 b/nis.subproj/yp_unbind.3
new file mode 100644 (file)
index 0000000..ee71c09
--- /dev/null
@@ -0,0 +1 @@
+.so man3/ypclnt.3
diff --git a/nis.subproj/ypclnt.3 b/nis.subproj/ypclnt.3
new file mode 100644 (file)
index 0000000..6f1651f
--- /dev/null
@@ -0,0 +1,342 @@
+.\"    $OpenBSD: ypclnt.3,v 1.5 1996/12/28 09:06:29 downsj Exp $
+.\"
+.\" Copyright (c) 1996 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Jason R. Thorpe.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"        This product includes software developed by the NetBSD
+.\"        Foundation, Inc. and its contributors.
+.\" 4. Neither the name of The NetBSD Foundation nor the names of its
+.\"    contributors may be used to endorse or promote products derived
+.\"    from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd October 26, 1994
+.Dt YPCLNT 3
+.Os
+.Sh NAME
+.Nm yp_all ,
+.Nm yp_bind ,
+.Nm yp_first ,
+.Nm yp_get_default_domain ,
+.Nm yp_master ,
+.Nm yp_match ,
+.Nm yp_next ,
+.Nm yp_order ,
+.Nm yp_unbind ,
+.Nm yperr_string ,
+.Nm ypprot_err
+.Nd Interface to the YP subsystem
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <rpcsvc/ypclnt.h>
+.Fd #include <rpcsvc/yp_prot.h>
+.Ft int
+.Fn yp_all "char *indomain" "char *inmap" "struct ypall_callback *incallback"
+.Ft int
+.Fn yp_bind "char *dom"
+.Ft int
+.Fn yp_first "char *indomain" "char *inmap" "char **outkey" "int *outkeylen" "char **outval" "int *outvallen"
+.Ft int
+.Fn yp_get_default_domain "char **domp"
+.Ft int
+.Fn yp_master "char *indomain" "char *inmap" "char **outname"
+.Ft int
+.Fn yp_match "char *indomain" "char *inmap" "const char *inkey" "int inkeylen" "char **outval" "int *outvallen"
+.Ft int
+.Fn yp_next "char *indomain" "char *inmap" "char *inkey" "int inkeylen" "char **outkey" "int *outkeylen" "char **outval" "int *outvallen"
+.Ft int
+.Fn yp_order "char *indomain" "char *inmap" "char *outorder"
+.Ft void
+.Fn yp_unbind "char *dom"
+.Ft char *
+.Fn yperr_string "int incode"
+.Ft int
+.Fn ypprot_err "unsigned int incode"
+.Sh DESCRIPTION
+The
+.Nm ypclnt
+suite provides an interface to the YP subsystem.  For a general description
+of the YP subsystem, see
+.Xr yp 8 .
+.Pp
+For all functions, input values begin with
+.Pa in
+and output values begin with
+.Pa out .
+Any output values of type
+.Em char **
+should be the addresses of uninitialized character pointers.  Memory will be
+allocated by the YP client routines using
+.Fn malloc .
+This memory can later be freed by the user if there is no additional need for
+the data stored there.  For
+.Pa outkey
+and
+.Pa outval ,
+two extra bytes of memory are allocated for a
+.Ql \en
+and
+.Ql \e0 ,
+which are not
+reflected in the values of
+.Pa outkeylen
+or
+.Pa outvallen .
+All occurrences of
+.Pa indomain
+and
+.Pa inmap
+must be non-null, null-terminated strings.  All input strings which also have
+a corresponding length parameter cannot be null unless the corresponding
+length value is zero.  Such strings need not be null-terminated.
+.Pp
+All YP lookup calls (the functions
+.Fn yp_all ,
+.Fn yp_first ,
+.Fn yp_master ,
+.Fn yp_match ,
+.Fn yp_next ,
+.Fn yp_order )
+require a YP domain name and a YP map name.  The default domain name may be 
+obtained by calling
+.Fn yp_get_default_domain ,
+and should thus be used before all other YP calls in a client program.
+The value it places
+.Pa outdomain
+is suitable for use as the
+.Pa indomain
+parameter to all subsequent YP calls.
+.Pp
+In order for YP lookup calls to succeed, the client process must be bound
+to a YP server process.  The client process need not explicitly bind to
+the server, as it happens automatically whenever a lookup occurs.
+The function
+.Fn yp_bind
+is provided for a backup strategy, e.g. a local file, when a YP server process
+is not available.  Each binding uses one socket descriptor on the client
+process, which may be explicitly freed using
+.Fn yp_unbind ,
+which frees all per-process and per-node resources to bind the domain and
+marks the domain unbound.
+.Pp
+If, during a YP lookup, an RPC failure occurs, the domain used in the lookup
+is automatically marked unbound and the
+.Nm ypclnt
+layer retries the lookup as long as
+.Xr ypbind 8
+is running and either the client process cannot bind to a server for the domain
+specified in the lookup, or RPC requests to the YP server process fail.
+If an error is not RPC-related, one of the YP error codes described below
+is returned and control given back to the user code.
+.Pp
+The
+.Nm ypclnt
+suite provides the following functionality:
+.Bl -tag -width Fn yp_match
+.It Fn yp_match
+Provides the value associated with the given key.
+.It Fn yp_first
+Provides the first key-value pair from the given map in the named domain.
+.It Fn yp_next
+Provides the next key-value pair in the given map.  To obtain the second pair,
+the
+.Pa inkey
+value should be the
+.Pa outkey
+value provided by the initial call to
+.Fn yp_first .
+In the general case, the next key-value pair may be obtained by using the
+.Pa outkey
+value from the previous call to
+.Fn yp_next
+as the value for
+.Pa inkey .
+.Pp
+Of course, the notions of ``first'' and ``next'' are particular to the
+type of YP map being accessed, and thus there is no guarantee of lexical
+order.  The only guarantees provided with
+.Fn yp_first
+and
+.Fn yp_next ,
+providing that the same map on the same server is polled repeatedly
+until
+.Fn yp_next
+returns YPERR_NOMORE, are that all key-value pairs in that map will be accessed
+exactly once, and if the entire procedure is repeated, the order will be
+the same.
+.Pp
+If the server is heaviliy loaded or the server fails for some reason, the
+domain being used may become unbound.  If this happens, and the client process
+re-binds, the retrieval rules will break: some entries may be seen twice, and
+others not at all.  For this reason, the function
+.Fn yp_all
+provides a better solution for reading all of the entries in a particular
+map.
+.It Fn yp_all
+This function provides a way to transfer an entire map from
+the server to the client process with a single request.  This transfer
+uses TCP, unlike all other functions in the
+.Nm ypclnt
+suite, which use UDP.  The entire transaction occurs in a single RPC
+request-response.  The third argument to this function provides a way
+to supply the name of a function to process each key-value pair in the
+map.
+.Fn Yp_all
+returns after the entire transaction is complete, or the
+.Pa foreach
+function decides that it does not want any more key-value pairs.  The third
+argument to
+.Fn yp_all
+is:
+.Bd -literal -offset indent
+struct ypall_callback *incallback {
+       int (*foreach)();
+       char *data;
+};
+.Ed
+.Pp
+The
+.Em char *data
+argument is an opaque pointer for use by the callback function.  The
+.Pa foreach
+function should return non-zero when it no longer wishes to process
+key-value pairs, at which time
+.Fn yp_all
+returns a value of 0, and is called with the following arguments:
+.Pp
+.Bd -literal -offset indent
+int foreach (
+       int instatus,
+       char *inkey,
+       int inkeylen,
+       char *inval,
+       int invallen,
+       char *indata
+);
+.Ed
+.Pp
+Where:
+.Bl -tag -width "inkey, inval"
+.It Fa instatus
+Holds one of the return status values described in
+.Nm <rpcsvc/yp_prot.h> :
+see
+.Fn ypprot_err
+below for a function that will translate YP protocol errors into a
+.Nm ypclnt
+layer error code as described in
+.Nm <rpcsvc/ypclnt.h> .
+.It Fa inkey, inval
+The key and value arguments are somewhat different here than described
+above.  In this case, the memory pointed to by
+.Fa inkey
+and
+.Fa inval
+is private to
+.Fn yp_all ,
+and is overwritten with each subsequent key-value pair, thus the
+.Pa foreach
+function should do something useful with the contents of that memory during
+each iteration.  If the key-value pairs are not terminated with either
+.Ql \en
+or
+.Ql \e0
+in the map, then they will not be terminated as such when given to the
+.Pa foreach
+function, either.
+.It Fa indata
+This is the contents of the
+.Pa incallback->data
+element of the callback structure.  It is provided as a means to share
+state between the
+.Pa foreach
+function and the user code.  Its use is completely optional: cast it to
+something useful or simply ignore it.
+.El
+.It Fn yp_order
+Returns the order number for a map.
+.It Fn yp_master
+Returns the hostname for the machine on which the master YP server process for
+a map is running.
+.It Fn yperr_string
+Returns a pointer to a null-terminated error string that does not contain a
+.Ql \&.
+or
+.Ql \en .
+.It Fn ypprot_err
+Converts a YP protocol error code to a
+.Nm ypclnt
+error code suitable for
+.Fn yperr_string .
+.El
+.Sh RETURN VALUES
+All functions in the
+.Nm ypclnt
+suite which are of type
+.Em int
+return 0 upon success or one of the following error codes upon failure:
+.Bl -tag -width "YPERR_BADARGS   "
+.It Bq Er YPERR_BADARGS
+The passed arguments to the function are invalid
+.It Bq Er YPERR_BADDB
+The YP map that was polled is defective.
+.It Bq Er YPERR_DOMAIN
+Client process cannot bind to server on this YP domain.
+.It Bq Er YPERR_KEY
+The key passed does not exist.
+.It Bq Er YPERR_MAP
+There is no such map in the server's domain.
+.It Bq Er YPERR_DOM
+The local YP domain is not set.
+.It Bq Er YPERR_NOMORE
+There are no more records in the queried map.
+.It Bq Er YPERR_PMAP
+Cannot communicate with portmap.
+.It Bq Er YPERR_RESRC
+A resource allocation failure occurred.
+.It Bq Er YPERR_RPC
+An RPC failure has occurred.  The domain has been marked unbound.
+.It Bq Er YPERR_VERS
+Client/server version mismatch.  If the server is running version 1
+of the YP protocol,
+.Fn yp_all
+functionality does not exist.
+.It Bq Er YPERR_BIND
+Cannot communicate with
+.Xr ypbind 8 .
+.It Bq Er YPERR_YPERR
+An internal server or client error has occurred.
+.It Bq Er YPERR_YPSERV
+The client cannot communicate with the YP server process.
+.El
+.Sh SEE ALSO
+.Xr malloc 3 ,
+.Xr yp 8 ,
+.Xr ypbind 8 ,
+.Xr ypserv 8
+.Sh AUTHOR
+Theo De Raadt
diff --git a/nis.subproj/yperr_string.3 b/nis.subproj/yperr_string.3
new file mode 100644 (file)
index 0000000..ee71c09
--- /dev/null
@@ -0,0 +1 @@
+.so man3/ypclnt.3
index d285182ff463222e48176821e2988a9f9c318612..2d3fe2f6eaee43459dda301fa5cfd343f2655da4 100644 (file)
@@ -54,7 +54,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef LINT
+#if defined(LIBC_SCCS) && !defined(lint)
 static char rcsid[] = "$OpenBSD: yppasswdd_xdr.c,v 1.4 1997/08/19 07:00:52 niklas Exp $";
 #endif
 
diff --git a/nis.subproj/ypprot_err.3 b/nis.subproj/ypprot_err.3
new file mode 100644 (file)
index 0000000..ee71c09
--- /dev/null
@@ -0,0 +1 @@
+.so man3/ypclnt.3
diff --git a/nis.subproj/ypserv.acl.5 b/nis.subproj/ypserv.acl.5
new file mode 100644 (file)
index 0000000..000824a
--- /dev/null
@@ -0,0 +1,177 @@
+.\"    $OpenBSD: ypserv.acl.5,v 1.5 1996/07/04 21:17:15 deraadt Exp $
+.\" Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by Mats O Jansson
+.\" 4. The name of the author may not be used to endorse or promote products
+.\"    derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd July 2, 1994
+.Dt YPSERV.ACL 5
+.Os
+.Sh NAME
+.Nm ypserv.acl
+.Nd 
+.Xr ypserv 8
+configuration file
+.Sh DESCRIPTION
+The 
+.Nm ypserv.acl
+file controls which hosts can connect to the
+.Nm YP
+server.
+.Pp
+The format is more complex than the format for
+.Xr securenet 5 .
+The first two verbs on each line controls if the line will
+.Nm allow
+or
+.Nm deny
+access for a
+.Nm host ,
+network
+.Nm (net)
+or
+.Nm all
+hosts.
+.Pp
+The
+.Nm YP
+server reads the configuration file and build a list in memory. This list
+is processed from the beginning for every incomming request. As soon a
+match is found in the list the search terminates and it returns success
+or failure depending on 
+.Nm allow
+or 
+.Nm deny .
+If no match was found in the list success is returned.
+.Pp
+If access is denied every call will cause a 
+.Nm no such domain
+error for the caller.
+.Pp
+There is no default name for this file. Start 
+.Nm ypserv
+with a
+.Ar -a filename
+to read a file with this format.
+.Pp
+The following different syntax can be used:
+.Pp
+<
+.Nm allow|deny
+>
+.Nm host
+<
+.Nm hostname|ip-address
+>
+.Pp
+If 
+.Nm hostname
+has more than one ip address then all will be added to the list.
+.Pp
+<
+.Nm allow|deny
+>
+.Nm net
+<
+.Nm netname|netnumber
+>
+.Op Nm netmask <netname|netnumber>
+.Pp
+If
+.Nm netmask
+part of the command isn't given then the netmask will be assumed to be a
+class A, B or C net depending on the net number.
+.Pp
+<
+.Nm allow|deny 
+>
+.Nm all
+.Pp
+A line containing one of these commands will always match any host.
+.Sh EXAMPLES
+.Pp
+A configuration file might appear as follows:
+.Bd -literal
+# This is an example of an access control file to be used by ypserv.
+#
+# This file is parsed line by line. First match will terminate the check
+# of the caller.
+#
+
+###########################################################################
+# This is the commands that will match a single host
+#
+#      allow host <hostname|ip-address>
+#      deny host <hostname|ip-address>
+#
+# To process hostname gethostbyname is called. If the hostname has
+# multiple ip-addresses all will be added (I hope). ip-address
+# processed by inet_aton.
+deny host jodie
+
+###########################################################################
+# This is the commands that will match a network
+#
+#      allow net <netname|netnumber> [netmask <netname|netnumber>]
+#      deny net <netname|netnumber> [netmask <netname|netnumber>]
+#
+# To process netname getnetbyname is called, and inet_aton is used for
+# netnumber. inet_aton both access numbers as 255.255.255.0 and 0xffffff00.
+#
+# If netmask isn't given the parser will assume netmask from the first bits
+# of the network number. So if the network is subneted the you have to add
+# the netmask. In my case I've got the network 139.58.253.0 at home so too
+# allow any of my computers to talk with the server I need the following
+# line
+#
+allow net mojathome netmask 255.255.255.0
+
+###########################################################################
+# At last we have a command that will match any caller:
+#
+#      allow all 
+#      deny all
+#
+
+# reject all connections
+deny all
+
+.Ed
+.Sh FILES
+.Bl -tag -width /var/yp/ypserv.acl -compact
+.It Pa /var/yp/ypserv.acl
+A
+.Xr ypserv 8
+configuration file.
+.El
+.Sh SEE ALSO
+.Xr yp 8 ,
+.Xr ypserv 8 ,
+.Xr securenet 5
+.Sh AUTHOR
+Mats O Jansson <moj@stacken.kth.se>
+
index 220a8ca66d9a91d761db7109ae00e3961d154d93..e2901a0e79ad8bfff1cc211306d2acd185e6803a 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)auth_none.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)auth_none.c 2.1 88/07/29 4.0 RPCSRC";*/
-static char *rcsid = "$Id: auth_none.c,v 1.2 1999/10/14 21:56:52 wsanchez Exp $";
+static char *rcsid = "$Id: auth_none.c,v 1.3 2002/02/19 20:36:22 epeyton Exp $";
 #endif
 
 /*
@@ -64,11 +64,16 @@ static char *rcsid = "$Id: auth_none.c,v 1.2 1999/10/14 21:56:52 wsanchez Exp $"
  * Copyright (C) 1984, Sun Microsystems, Inc. 
  */
 
+#include <stdlib.h>
+#include <sys/types.h>
+#include <netinet/in.h>
 #include <rpc/types.h>
 #include <rpc/xdr.h>
 #include <rpc/auth.h>
 #define MAX_MARSHEL_SIZE 20
 
+extern bool_t  xdr_opaque_auth();
+
 /*
  * Authenticator operations routines
  */
index 448654d4b2ae2779eb8fd252cbe6c1e952aa5d27..f2902c1f7757a6a801263a4b817ccf0cfd576e33 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)auth_unix.c 2.2 88/08/01 4.0 RPCSRC";*/
-static char *rcsid = "$Id: auth_unix.c,v 1.3 2001/01/17 19:05:42 majka Exp $";
+static char *rcsid = "$Id: auth_unix.c,v 1.4 2002/02/19 20:36:22 epeyton Exp $";
 #endif
 
 /*
@@ -70,13 +70,19 @@ static char *rcsid = "$Id: auth_unix.c,v 1.3 2001/01/17 19:05:42 majka Exp $";
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
 #include <sys/param.h>
+#include <sys/types.h>
+#include <netinet/in.h>
 
 #include <rpc/types.h>
 #include <rpc/xdr.h>
 #include <rpc/auth.h>
 #include <rpc/auth_unix.h>
 
+extern bool_t  xdr_opaque_auth();
+
 /*
  * Unix authenticator operations vector
  */
@@ -106,7 +112,7 @@ struct audata {
 };
 #define        AUTH_PRIVATE(auth)      ((struct audata *)auth->ah_private)
 
-static bool_t marshal_new_auth();
+static void marshal_new_auth();
 
 
 /*
@@ -193,8 +199,9 @@ authunix_create(machname, uid, gid, len, aup_gids)
 * the maximum size of the group list that will be sent.
 */
 
-static maxgrplist = NGROUPS;
+static int maxgrplist = NGROUPS;
 
+void
 set_rpc_maxgrouplist(num)
        int num;
 {
@@ -345,7 +352,7 @@ authunix_destroy(auth)
  * Marshals (pre-serializes) an auth struct.
  * sets private data, au_marshed and au_mpos
  */
-static bool_t
+static void
 marshal_new_auth(auth)
        register AUTH *auth;
 {
index dce59b38ef85ff39b409f2fd5e314ca0ff0d38df..38864f24661b36aefbca1e661f046b50eed88369 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)authunix_prot.c 1.15 87/08/11 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)authunix_prot.c     2.1 88/07/29 4.0 RPCSRC";*/
-static char *rcsid = "$Id: authunix_prot.c,v 1.3 2001/01/17 19:05:42 majka Exp $";
+static char *rcsid = "$Id: authunix_prot.c,v 1.4 2002/02/19 20:36:22 epeyton Exp $";
 #endif
 
 /*
@@ -64,6 +64,8 @@ static char *rcsid = "$Id: authunix_prot.c,v 1.3 2001/01/17 19:05:42 majka Exp $
  */
 
 
+#include <sys/types.h>
+#include <netinet/in.h>
 #include <rpc/types.h>
 #include <rpc/xdr.h>
 #include <rpc/auth.h>
index 14261d16b03234926d5b99d293e3d1f51e85de38..ae903aeb5984c1d20807c1f29b7bc99eb6ae9ba5 100644 (file)
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)bindresvport.c 1.8 88/02/08 SMI";*/
 /*static char *sccsid = "from: @(#)bindresvport.c      2.2 88/07/29 4.0 RPCSRC";*/
-static char *rcsid = "$Id: bindresvport.c,v 1.2 1999/10/14 21:56:52 wsanchez Exp $";
+/*from: OpenBSD: bindresvport.c,v 1.7 1996/07/30 16:25:47 downsj Exp */
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/bindresvport.c,v 1.12 2000/01/26 09:02:42 shin Exp $";
 #endif
 
 /*
  * Copyright (c) 1987 by Sun Microsystems, Inc.
+ *
+ * Portions Copyright(C) 1996, Jason Downs.  All rights reserved.
  */
 
+#include <string.h>
+#include <unistd.h>
 #include <sys/types.h>
 #include <sys/errno.h>
 #include <sys/socket.h>
@@ -68,40 +73,94 @@ static char *rcsid = "$Id: bindresvport.c,v 1.2 1999/10/14 21:56:52 wsanchez Exp
 /*
  * Bind a socket to a privileged IP port
  */
+int
 bindresvport(sd, sin)
        int sd;
        struct sockaddr_in *sin;
 {
-       int res;
-       static short port;
-       struct sockaddr_in myaddr;
-       extern int errno;
-       int i;
-
-#define STARTPORT 600
-#define ENDPORT (IPPORT_RESERVED - 1)
-#define NPORTS (ENDPORT - STARTPORT + 1)
-
-       if (sin == (struct sockaddr_in *)0) {
-               sin = &myaddr;
-               bzero(sin, sizeof (*sin));
-               sin->sin_family = AF_INET;
-       } else if (sin->sin_family != AF_INET) {
+       return bindresvport_sa(sd, (struct sockaddr *)sin);
+}
+
+/*
+ * Bind a socket to a privileged port for whatever protocol.
+ */
+int
+bindresvport_sa(sd, sa)
+       int sd;
+       struct sockaddr *sa;
+{
+       int old, error, af;
+       struct sockaddr_storage myaddr;
+       struct sockaddr_in *sin;
+       struct sockaddr_in6 *sin6;
+       int proto, portrange, portlow;
+       u_int16_t port;
+       int salen;
+
+       if (sa == NULL) {
+               salen = sizeof(myaddr);
+               sa = (struct sockaddr *)&myaddr;
+
+               if (getsockname(sd, sa, &salen) == -1)
+                       return -1;      /* errno is correctly set */
+
+               af = sa->sa_family;
+               memset(&myaddr, 0, salen);
+       } else
+               af = sa->sa_family;
+
+       if (af == AF_INET) {
+               proto = IPPROTO_IP;
+               portrange = IP_PORTRANGE;
+               portlow = IP_PORTRANGE_LOW;
+               sin = (struct sockaddr_in *)sa;
+               salen = sizeof(struct sockaddr_in);
+               port = sin->sin_port;
+       } else if (af == AF_INET6) {
+               proto = IPPROTO_IPV6;
+               portrange = IPV6_PORTRANGE;
+               portlow = IPV6_PORTRANGE_LOW;
+               sin6 = (struct sockaddr_in6 *)sa;
+               salen = sizeof(struct sockaddr_in6);
+               port = sin6->sin6_port;
+       } else {
                errno = EPFNOSUPPORT;
                return (-1);
        }
+       sa->sa_family = af;
+       sa->sa_len = salen;
+
        if (port == 0) {
-               port = (getpid() % NPORTS) + STARTPORT;
+               int oldlen = sizeof(old);
+
+               error = getsockopt(sd, proto, portrange, &old, &oldlen);
+               if (error < 0)
+                       return (error);
+
+               error = setsockopt(sd, proto, portrange, &portlow,
+                   sizeof(portlow));
+               if (error < 0)
+                       return (error);
        }
-       res = -1;
-       errno = EADDRINUSE;
-       for (i = 0; i < NPORTS && res < 0 && errno == EADDRINUSE; i++) {
-               sin->sin_port = htons(port++);
-               if (port > ENDPORT) {
-                       port = STARTPORT;
+
+       error = bind(sd, sa, salen);
+
+       if (port == 0) {
+               int saved_errno = errno;
+
+               if (error) {
+                       if (setsockopt(sd, proto, portrange, &old,
+                           sizeof(old)) < 0)
+                               errno = saved_errno;
+                       return (error);
+               }
+
+               if (sa != (struct sockaddr *)&myaddr) {
+                       /* Hmm, what did the kernel assign... */
+                       if (getsockname(sd, sa, &salen) < 0)
+                               errno = saved_errno;
+                       return (error);
                }
-               res = bind(sd,
-                   (struct sockaddr *)sin, sizeof(struct sockaddr_in));
        }
-       return (res);
+       return (error);
 }
index cd966ef62e8cdc0eb1eb6219ed66223e0623ab2e..3901b6037301116592f85ca533736537aa5d4c6a 100644 (file)
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)clnt_generic.c 1.4 87/08/11 (C) 1987 SMI";*/
 /*static char *sccsid = "from: @(#)clnt_generic.c      2.2 88/08/01 4.0 RPCSRC";*/
-static char *rcsid = "$Id: clnt_generic.c,v 1.2 1999/10/14 21:56:52 wsanchez Exp $";
+static char *rcsid = "$Id: clnt_generic.c,v 1.3 2002/02/19 20:36:22 epeyton Exp $";
 #endif
 
 /*
  * Copyright (C) 1987, Sun Microsystems, Inc.
  */
+#include <string.h>
 #include <rpc/rpc.h>
 #include <sys/socket.h>
 #include <sys/errno.h>
index 7ad8e75a7bedc038a777b279e9a4ef62458307a0..1e3ce14e1a0ac32204ecadea580a0a55cb5a912a 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)clnt_perror.c 1.15 87/10/07 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)clnt_perror.c       2.1 88/07/29 4.0 RPCSRC";*/
-static char *rcsid = "$Id: clnt_perror.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp $";
+static char *rcsid = "$Id: clnt_perror.c,v 1.3 2002/02/19 20:36:22 epeyton Exp $";
 #endif
 
 /*
@@ -63,6 +63,7 @@ static char *rcsid = "$Id: clnt_perror.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp
  *
  */
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <rpc/rpc.h>
 #include <rpc/types.h>
@@ -251,7 +252,6 @@ char *
 clnt_spcreateerror(s)
        char *s;
 {
-       extern int sys_nerr;
        char *str = _buf();
 
        if (str == 0)
index 100b8707def511324083e6d0a4b9ee76070f7642..0fccf080cbc0431d6a052c0829fa264e7f75e04b 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)clnt_raw.c  2.2 88/08/01 4.0 RPCSRC";*/
-static char *rcsid = "$Id: clnt_raw.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp $";
+static char *rcsid = "$Id: clnt_raw.c,v 1.3 2002/02/19 20:36:22 epeyton Exp $";
 #endif
 
 /*
@@ -67,8 +67,12 @@ static char *rcsid = "$Id: clnt_raw.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp $";
  * any interference from the kernal.
  */
 
+#include <stdio.h>
+#include <stdlib.h>
 #include <rpc/rpc.h>
 
+extern bool_t  xdr_opaque_auth();
+
 #define MCALL_MSG_SIZE 24
 
 /*
index ec99490c1a31aa63c89d3e3f7b53cd56485ad708..0ba26d05fc232675c209bb6f0a86f1904fe1681b 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)clnt_simple.c 1.35 87/08/11 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)clnt_simple.c       2.2 88/08/01 4.0 RPCSRC";*/
-static char *rcsid = "$Id: clnt_simple.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp $";
+static char *rcsid = "$Id: clnt_simple.c,v 1.3 2002/02/19 20:36:23 epeyton Exp $";
 #endif
 
 /* 
@@ -66,6 +66,7 @@ static char *rcsid = "$Id: clnt_simple.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 #include <rpc/rpc.h>
 #include <sys/socket.h>
 #include <netdb.h>
@@ -77,6 +78,7 @@ static struct callrpc_private {
        char    *oldhost;
 } *callrpc_private;
 
+int
 callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
        char *host;
        xdrproc_t inproc, outproc;
index 22f66161ad9158c0a959210edce64ad77f9efb72..71afd9d16fe09e0645a3f5fbf28e23cbf6f49043 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)clnt_tcp.c  2.2 88/08/01 4.0 RPCSRC";*/
-static char *rcsid = "$Id: clnt_tcp.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp $";
+static char *rcsid = "$Id: clnt_tcp.c,v 1.4 2002/03/15 22:07:48 majka Exp $";
 #endif
  
 /*
@@ -76,8 +76,12 @@ static char *rcsid = "$Id: clnt_tcp.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp $";
  */
 
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
 #include <rpc/rpc.h>
 #include <sys/socket.h>
+#include <sys/fcntl.h>
 #include <netdb.h>
 #include <errno.h>
 #include <rpc/pmap_clnt.h>
@@ -86,6 +90,9 @@ static char *rcsid = "$Id: clnt_tcp.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp $";
 
 extern int errno;
 
+extern int     bindresvport();
+extern bool_t  xdr_opaque_auth();
+
 static int     readtcp();
 static int     writetcp();
 
@@ -141,9 +148,10 @@ clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
        u_int recvsz;
 {
        CLIENT *h;
-       register struct ct_data *ct;
+       register struct ct_data *ct = NULL;
        struct timeval now;
        struct rpc_msg call_msg;
+       int rfd;
 
        h  = (CLIENT *)mem_alloc(sizeof(*h));
        if (h == NULL) {
@@ -203,8 +211,14 @@ clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
        /*
         * Initialize call message
         */
-       (void)gettimeofday(&now, (struct timezone *)0);
-       call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
+       rfd = open("/dev/random", O_RDONLY, 0);
+       if ((rfd < 0) || (read(rfd, &call_msg.rm_xid, sizeof(call_msg.rm_xid)) != sizeof(call_msg.rm_xid)))
+       {
+               gettimeofday(&now, (struct timezone *)0);
+               call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
+       }
+       if (rfd > 0) close(rfd);
+
        call_msg.rm_direction = CALL;
        call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
        call_msg.rm_call.cb_prog = prog;
@@ -431,7 +445,7 @@ readtcp(ct, buf, len)
        FD_SET(ct->ct_sock, &mask);
        while (TRUE) {
                readfds = mask;
-               switch (select(ct->ct_sock+1, &readfds, (int*)NULL, (int*)NULL,
+               switch (select(ct->ct_sock+1, &readfds, NULL, NULL,
                               &(ct->ct_wait))) {
                case 0:
                        ct->ct_error.re_status = RPC_TIMEDOUT;
index 38a03fe77988b26b8c2ba73a4a3cc1047ff7d83f..446603a9dfba002415dfd3f5c64aae9dccf5064f 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)clnt_udp.c  2.2 88/08/01 4.0 RPCSRC";*/
-static char *rcsid = "$Id: clnt_udp.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp $";
+static char *rcsid = "$Id: clnt_udp.c,v 1.4 2002/03/15 22:07:49 majka Exp $";
 #endif
 
 /*
@@ -63,13 +63,20 @@ static char *rcsid = "$Id: clnt_udp.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp $";
  */
 
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
 #include <rpc/rpc.h>
 #include <sys/socket.h>
+#include <sys/fcntl.h>
 #include <sys/ioctl.h>
 #include <netdb.h>
 #include <errno.h>
 #include <rpc/pmap_clnt.h>
 
+extern int     bindresvport();
+extern bool_t  xdr_opaque_auth();
+
 extern int errno;
 
 /*
@@ -137,9 +144,10 @@ clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
        u_int recvsz;
 {
        CLIENT *cl;
-       register struct cu_data *cu;
+       register struct cu_data *cu = NULL;
        struct timeval now;
        struct rpc_msg call_msg;
+       int rfd;
 
        cl = (CLIENT *)mem_alloc(sizeof(CLIENT));
        if (cl == NULL) {
@@ -159,7 +167,6 @@ clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
        }
        cu->cu_outbuf = &cu->cu_inbuf[recvsz];
 
-       (void)gettimeofday(&now, (struct timezone *)0);
        if (raddr->sin_port == 0) {
                u_short port;
                if ((port =
@@ -177,7 +184,15 @@ clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
        cu->cu_total.tv_usec = -1;
        cu->cu_sendsz = sendsz;
        cu->cu_recvsz = recvsz;
-       call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
+       
+       rfd = open("/dev/random", O_RDONLY, 0);
+       if ((rfd < 0) || (read(rfd, &call_msg.rm_xid, sizeof(call_msg.rm_xid)) != sizeof(call_msg.rm_xid)))
+       {
+               gettimeofday(&now, (struct timezone *)0);
+               call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
+       }
+       if (rfd > 0) close(rfd);
+
        call_msg.rm_direction = CALL;
        call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
        call_msg.rm_call.cb_prog = program;
@@ -302,8 +317,8 @@ send_again:
        FD_SET(cu->cu_sock, &mask);
        for (;;) {
                readfds = mask;
-               switch (select(cu->cu_sock+1, &readfds, (int *)NULL, 
-                              (int *)NULL, &(cu->cu_wait))) {
+               switch (select(cu->cu_sock+1, &readfds, NULL, 
+                              NULL, &(cu->cu_wait))) {
 
                case 0:
                        time_waited.tv_sec += cu->cu_wait.tv_sec;
index 944a0e8af5646018654bd778c1c51b4c84d7ea52..00cd6729e95ecdc1687a8352b3561a45be4ea401 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)get_myaddress.c 1.4 87/08/11 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)get_myaddress.c     2.1 88/07/29 4.0 RPCSRC";*/
-static char *rcsid = "$Id: get_myaddress.c,v 1.3 2000/08/03 20:25:14 ajn Exp $";
+static char *rcsid = "$Id: get_myaddress.c,v 1.4 2002/02/19 20:36:23 epeyton Exp $";
 #endif
 
 /*
@@ -70,6 +70,7 @@ static char *rcsid = "$Id: get_myaddress.c,v 1.3 2000/08/03 20:25:14 ajn Exp $";
 #include <rpc/pmap_prot.h>
 #include <sys/socket.h>
 #include <stdio.h>
+#include <string.h>
 #include <unistd.h>
 #include <net/if.h>
 #include <sys/ioctl.h>
index 1b57d994368e9abaebd878edd3533bbd2427cebc..1a8fe445f2497588ece5096cc14b200798d467f7 100644 (file)
@@ -53,7 +53,7 @@
 
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)getrpcent.c 1.14 91/03/11 Copyr 1984 Sun Micro";*/
-static char *rcsid = "$Id: getrpcent.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp $";
+static char *rcsid = "$Id: getrpcent.c,v 1.3 2002/02/19 20:36:23 epeyton Exp $";
 #endif
 
 /*
@@ -61,6 +61,7 @@ static char *rcsid = "$Id: getrpcent.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp $"
  */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <sys/types.h>
 #include <string.h>
 #include <rpc/rpc.h>
@@ -105,7 +106,7 @@ getrpcbynumber(number)
        if (d == 0)
                return (0);
        setrpcent(0);
-       while (p = getrpcent()) {
+       while ((p = getrpcent())) {
                if (p->r_number == number)
                        break;
        }
@@ -125,7 +126,7 @@ getrpcbyname(name)
        char **rp;
 
        setrpcent(0);
-       while (rpc = getrpcent()) {
+       while ((rpc = getrpcent())) {
                if (strcmp(rpc->r_name, name) == 0)
                        return (rpc);
                for (rp = rpc->r_aliases; *rp != NULL; rp++) {
@@ -168,8 +169,6 @@ endrpcent()
 struct rpcent *
 getrpcent()
 {
-       struct rpcent *hp;
-       int reason;
        register struct rpcdata *d = _rpcdata();
 
        if (d == 0)
index af368dd52317fd91183ffd25814342a9fb3cd6c4..f7c51af2d159d7dab3f67b09bebf3d4f40ee9d9d 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)getrpcport.c 1.3 87/08/11 SMI";*/
 /*static char *sccsid = "from: @(#)getrpcport.c        2.1 88/07/29 4.0 RPCSRC";*/
-static char *rcsid = "$Id: getrpcport.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp $";
+static char *rcsid = "$Id: getrpcport.c,v 1.3 2002/02/19 20:36:23 epeyton Exp $";
 #endif
 
 /*
@@ -61,10 +61,13 @@ static char *rcsid = "$Id: getrpcport.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp $
  */
 
 #include <stdio.h>
+#include <string.h>
 #include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
 #include <netdb.h>
 #include <sys/socket.h>
 
+int
 getrpcport(host, prognum, versnum, proto)
        char *host;
 {
index cdd3261556c8502a97610f5b8ac665bcd6a7a2dd..087e4a8b8dbfb91f33923412bf64eec0a01b2a40 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)pmap_clnt.c 1.37 87/08/11 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)pmap_clnt.c 2.2 88/08/01 4.0 RPCSRC";*/
-static char *rcsid = "$Id: pmap_clnt.c,v 1.3 2000/08/03 20:25:14 ajn Exp $";
+static char *rcsid = "$Id: pmap_clnt.c,v 1.4 2002/02/19 20:36:23 epeyton Exp $";
 #endif
 
 /*
@@ -63,6 +63,7 @@ static char *rcsid = "$Id: pmap_clnt.c,v 1.3 2000/08/03 20:25:14 ajn Exp $";
  * Copyright (C) 1984, Sun Microsystems, Inc.
  */
 
+#include <string.h>
 #include <rpc/rpc.h>
 #include <rpc/pmap_prot.h>
 #include <rpc/pmap_clnt.h>
index 7946572942b92b3c05c60e1c34a6cb3b8d60f653..2d8b3415a2b1ec42c3a8372f285c99bb0a7ffec5 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)pmap_getmaps.c 1.10 87/08/11 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)pmap_getmaps.c      2.2 88/08/01 4.0 RPCSRC";*/
-static char *rcsid = "$Id: pmap_getmaps.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp $";
+static char *rcsid = "$Id: pmap_getmaps.c,v 1.3 2002/02/19 20:36:24 epeyton Exp $";
 #endif
 
 /*
@@ -64,6 +64,7 @@ static char *rcsid = "$Id: pmap_getmaps.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp
  * Copyright (C) 1984, Sun Microsystems, Inc.
  */
 
+#include <unistd.h>
 #include <rpc/rpc.h>
 #include <rpc/pmap_prot.h>
 #include <rpc/pmap_clnt.h>
index b4b6eb5cd7b9993c067bb7455124e4c671db6eb7..2e78d396f33c02929688ca3aa223fa702d3af70f 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)pmap_getport.c 1.9 87/08/11 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)pmap_getport.c      2.2 88/08/01 4.0 RPCSRC";*/
-static char *rcsid = "$Id: pmap_getport.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp $";
+static char *rcsid = "$Id: pmap_getport.c,v 1.3 2002/02/19 20:36:24 epeyton Exp $";
 #endif
 
 /*
@@ -63,6 +63,7 @@ static char *rcsid = "$Id: pmap_getport.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp
  * Copyright (C) 1984, Sun Microsystems, Inc.
  */
 
+#include <unistd.h>
 #include <rpc/rpc.h>
 #include <rpc/pmap_prot.h>
 #include <rpc/pmap_clnt.h>
index 986c2c8bcfef9ad27ce630970c97c79e66564df6..a5bd77d0a464bd9404afbecc5e72e6c660a821b9 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)pmap_prot2.c        2.1 88/07/29 4.0 RPCSRC";*/
-static char *rcsid = "$Id: pmap_prot2.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp $";
+static char *rcsid = "$Id: pmap_prot2.c,v 1.3 2002/02/19 20:36:24 epeyton Exp $";
 #endif
 
 /*
@@ -118,7 +118,7 @@ xdr_pmaplist(xdrs, rp)
         */
        bool_t more_elements;
        register int freeing = (xdrs->x_op == XDR_FREE);
-       register struct pmaplist **next;
+       register struct pmaplist **next = NULL;
 
        while (TRUE) {
                more_elements = (bool_t)(*rp != NULL);
index cbfffa69d632dfd1fc3e972450279d7c75b37d02..7474d9f29394e83b23b67dfd97ef6ef005addc03 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)pmap_rmt.c  2.2 88/08/01 4.0 RPCSRC";*/
-static char *rcsid = "$Id: pmap_rmt.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp $";
+static char *rcsid = "$Id: pmap_rmt.c,v 1.4 2002/03/15 22:07:50 majka Exp $";
 #endif
 
 /*
@@ -64,11 +64,14 @@ static char *rcsid = "$Id: pmap_rmt.c,v 1.2 1999/10/14 21:56:53 wsanchez Exp $";
  * Copyright (C) 1984, Sun Microsystems, Inc.
  */
 
+#include <string.h>
+#include <unistd.h>
 #include <rpc/rpc.h>
 #include <rpc/pmap_prot.h>
 #include <rpc/pmap_clnt.h>
 #include <rpc/pmap_rmt.h>
 #include <sys/socket.h>
+#include <sys/fcntl.h>
 #include <stdio.h>
 #include <errno.h>
 #include <net/if.h>
@@ -193,7 +196,7 @@ getbroadcastnets(addrs, sock, buf)
         struct ifreq ifreq, *ifr;
        struct sockaddr_in *sin;
         char *cp, *cplim;
-        int n, i = 0;
+        int i = 0;
 
         ifc.ifc_len = UDPMSGSIZE;
         ifc.ifc_buf = buf;
@@ -268,6 +271,7 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
        struct rpc_msg msg;
        struct timeval t; 
        char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE];
+       int rfd;
 
        /*
         * initialization: create a socket, a broadcast address, and
@@ -293,8 +297,15 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
        baddr.sin_port = htons(PMAPPORT);
        baddr.sin_addr.s_addr = htonl(INADDR_ANY);
 /*     baddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); */
-       (void)gettimeofday(&t, (struct timezone *)0);
-       msg.rm_xid = xid = getpid() ^ t.tv_sec ^ t.tv_usec;
+
+       rfd = open("/dev/random", O_RDONLY, 0);
+       if ((rfd < 0) || (read(rfd, &msg.rm_xid, sizeof(msg.rm_xid)) != sizeof(msg.rm_xid)))
+       {
+               gettimeofday(&t, (struct timezone *)0);
+               msg.rm_xid = getpid() ^ t.tv_sec ^ t.tv_usec;
+       }
+       if (rfd > 0) close(rfd);
+
        t.tv_usec = 0;
        msg.rm_direction = CALL;
        msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
@@ -342,8 +353,7 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
                msg.acpted_rply.ar_results.where = (caddr_t)&r;
                 msg.acpted_rply.ar_results.proc = xdr_rmtcallres;
                readfds = mask;
-               switch (select(sock+1, &readfds, (int *)NULL, 
-                              (int *)NULL, &t)) {
+               switch (select(sock+1, &readfds, NULL, NULL, &t)) {
 
                case 0:  /* timed out */
                        stat = RPC_TIMEDOUT;
index 45014db8c92e27f09825151452e369082f3753bd..713be6d6a0cc34bb9edd33a61cde72a9f929a48f 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)rpc_callmsg.c       2.1 88/07/29 4.0 RPCSRC";*/
-static char *rcsid = "$Id: rpc_callmsg.c,v 1.2 1999/10/14 21:56:54 wsanchez Exp $";
+static char *rcsid = "$Id: rpc_callmsg.c,v 1.3 2002/02/19 20:36:24 epeyton Exp $";
 #endif
 
 /*
@@ -63,10 +63,14 @@ static char *rcsid = "$Id: rpc_callmsg.c,v 1.2 1999/10/14 21:56:54 wsanchez Exp
  *
  */
 
+#include <stdlib.h>
+#include <string.h>
 #include <sys/param.h>
 
 #include <rpc/rpc.h>
 
+extern bool_t          xdr_opaque_auth();
+
 /*
  * XDR a call message
  */
index c12c2651897c73afbe7cf2fb8c5332fafa804f58..a3a122cde827b5682b3b4c515a8d42584db77cf7 100644 (file)
@@ -52,7 +52,7 @@
 
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)rpc_commondata.c    2.1 88/07/29 4.0 RPCSRC";*/
-static char *rcsid = "$Id: rpc_commondata.c,v 1.2 1999/10/14 21:56:54 wsanchez Exp $";
+static char *rcsid = "$Id: rpc_commondata.c,v 1.3 2002/02/19 20:36:24 epeyton Exp $";
 #endif
 
 #include <rpc/rpc.h>
@@ -62,7 +62,7 @@ static char *rcsid = "$Id: rpc_commondata.c,v 1.2 1999/10/14 21:56:54 wsanchez E
  */
 #if defined(__APPLE__)
 struct opaque_auth _null_auth = {0};
-fd_set svc_fdset = {0};
+fd_set svc_fdset = {{0}};
 int svc_maxfd = -1;
 struct rpc_createerr rpc_createerr = {0};
 #else
index bfdd00bebb9ad17687450ae57ab3ef0ae4e186b6..39a313a52c9b1eef4f58f77dc6f0d3c43e920a23 100644 (file)
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)rpc_dtablesize.c 1.2 87/08/11 Copyr 1987 Sun Micro";*/
 /*static char *sccsid = "from: @(#)rpc_dtablesize.c    2.1 88/07/29 4.0 RPCSRC";*/
-static char *rcsid = "$Id: rpc_dtablesize.c,v 1.2 1999/10/14 21:56:54 wsanchez Exp $";
+static char *rcsid = "$Id: rpc_dtablesize.c,v 1.3 2002/02/19 20:36:24 epeyton Exp $";
 #endif
 
+#include <unistd.h>
 #include <sys/types.h>
 
 /*
  * Cache the result of getdtablesize(), so we don't have to do an
  * expensive system call every time.
  */
+int
 _rpc_dtablesize()
 {
        static int size;
index a559c034dab81a7904b7cdeb71f75c05795f3f20..b0a6a9ae6969277cc086c5434c7bf1d4250ed94a 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint) 
 /*static char *sccsid = "from: @(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)svc.c       2.4 88/08/11 4.0 RPCSRC";*/
-static char *rcsid = "$Id: svc.c,v 1.3 2001/08/23 01:25:01 ajn Exp $";
+static char *rcsid = "$Id: svc.c,v 1.4 2002/02/19 20:36:24 epeyton Exp $";
 #endif
 
 /*
@@ -66,6 +66,8 @@ static char *rcsid = "$Id: svc.c,v 1.3 2001/08/23 01:25:01 ajn Exp $";
  * Copyright (C) 1984, Sun Microsystems, Inc.
  */
 
+#include <stdlib.h>
+#include <string.h>
 #include <sys/errno.h>
 #include <rpc/rpc.h>
 #include <rpc/pmap_clnt.h>
@@ -412,7 +414,7 @@ svc_getreqset(readfds)
 
        maskp = (u_long *)readfds->fds_bits;
        for (sock = 0; sock <= svc_maxfd; sock += NFDBITS) {
-           for (mask = *maskp++; bit = ffs(mask); mask ^= (1 << (bit - 1))) {
+           for (mask = *maskp++; (bit = ffs(mask)); mask ^= (1 << (bit - 1))) {
                if ((sock + bit) > (svc_maxfd + 1))
                        /* if we're past our sockets */
                        return;
index 6586c984577c94d7f6deff9c1c8c54b3d02221df..0d8db838c9cfa0ecd9ade3aa9a12bed3f0c55f33 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)svc_auth.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)svc_auth.c  2.1 88/08/07 4.0 RPCSRC";*/
-static char *rcsid = "$Id: svc_auth.c,v 1.2 1999/10/14 21:56:54 wsanchez Exp $";
+static char *rcsid = "$Id: svc_auth.c,v 1.3 2002/02/19 20:36:25 epeyton Exp $";
 #endif
 
 /*
@@ -87,9 +87,9 @@ enum auth_stat _svcauth_short();      /* short hand unix style */
 static struct {
        enum auth_stat (*authenticator)();
 } svcauthsw[] = {
-       _svcauth_null,                  /* AUTH_NULL */
-       _svcauth_unix,                  /* AUTH_UNIX */
-       _svcauth_short,                 /* AUTH_SHORT */
+       { _svcauth_null },              /* AUTH_NULL */
+       { _svcauth_unix },              /* AUTH_UNIX */
+       { _svcauth_short },             /* AUTH_SHORT */
 };
 #define        AUTH_MAX        2               /* HIGHEST AUTH NUMBER */
 
index 2f30dd7dd6c7a8d9bfafe80e72004f24f9f8edf4..95f6ca8a9a9a835a44eb21bd6bfd3b6b08eebc68 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)svc_auth_unix.c 1.28 88/02/08 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)svc_auth_unix.c     2.3 88/08/01 4.0 RPCSRC";*/
-static char *rcsid = "$Id: svc_auth_unix.c,v 1.3 2001/01/17 19:05:42 majka Exp $";
+static char *rcsid = "$Id: svc_auth_unix.c,v 1.4 2002/02/19 20:36:25 epeyton Exp $";
 #endif
 
 /*
@@ -68,6 +68,7 @@ static char *rcsid = "$Id: svc_auth_unix.c,v 1.3 2001/01/17 19:05:42 majka Exp $
  */
 
 #include <stdio.h>
+#include <string.h>
 #include <sys/param.h>
 #include <rpc/rpc.h>
 
index 6729e4dbcf637b0556ed970cc4562866490e39df..54e6f62573d09c3a2c28c951f1584991158a5322 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)svc_raw.c 1.15 87/08/11 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)svc_raw.c   2.1 88/07/29 4.0 RPCSRC";*/
-static char *rcsid = "$Id: svc_raw.c,v 1.2 1999/10/14 21:56:54 wsanchez Exp $";
+static char *rcsid = "$Id: svc_raw.c,v 1.3 2002/02/19 20:36:25 epeyton Exp $";
 #endif
 
 /*
@@ -65,6 +65,7 @@ static char *rcsid = "$Id: svc_raw.c,v 1.2 1999/10/14 21:56:54 wsanchez Exp $";
  * Copyright (C) 1984, Sun Microsystems, Inc.
  */
 
+#include <stdlib.h>
 #include <rpc/rpc.h>
 
 
index 47b467afe7b4b2a71220458c1c964c818cca3289..451591d3ba2f0c8ffb4a9a780d3e66213a0a7c9a 100644 (file)
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)svc_run.c   2.1 88/07/29 4.0 RPCSRC";*/
-static char *rcsid = "$Id: svc_run.c,v 1.2 1999/10/14 21:56:54 wsanchez Exp $";
+static char *rcsid = "$Id: svc_run.c,v 1.3 2002/02/19 20:36:25 epeyton Exp $";
 #endif
 
 /*
  * This is the rpc server side idle loop
  * Wait for input, call server program.
  */
+#include <stdio.h>
+#include <unistd.h>
 #include <rpc/rpc.h>
 #include <sys/errno.h>
 
@@ -73,7 +75,7 @@ svc_run()
 
        for (;;) {
                readfds = svc_fdset;
-               switch (select(svc_maxfd+1, &readfds, (int *)0, (int *)0,
+               switch (select(svc_maxfd+1, &readfds, NULL, NULL,
                               (struct timeval *)0)) {
                case -1:
                        if (errno == EINTR) {
index 6174d0435cfac9be01d9f7db672c8ef2d0d9d4da..22687327ddc149c4163fed9b2efc1e1670ff99bf 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)svc_simple.c 1.18 87/08/11 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)svc_simple.c        2.2 88/08/01 4.0 RPCSRC";*/
-static char *rcsid = "$Id: svc_simple.c,v 1.2 1999/10/14 21:56:54 wsanchez Exp $";
+static char *rcsid = "$Id: svc_simple.c,v 1.3 2002/02/19 20:36:25 epeyton Exp $";
 #endif
 
 /* 
@@ -64,7 +64,10 @@ static char *rcsid = "$Id: svc_simple.c,v 1.2 1999/10/14 21:56:54 wsanchez Exp $
  */
 
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
 #include <sys/socket.h>
 #include <netdb.h>
 
@@ -79,6 +82,7 @@ static void universal();
 static SVCXPRT *transp;
 struct proglst *pl;
 
+int
 registerrpc(prognum, versnum, procnum, progname, inproc, outproc)
        char *(*progname)();
        xdrproc_t inproc, outproc;
@@ -86,7 +90,7 @@ registerrpc(prognum, versnum, procnum, progname, inproc, outproc)
        
        if (procnum == NULLPROC) {
                (void) fprintf(stderr,
-                   "can't reassign procedure number %d\n", NULLPROC);
+                   "can't reassign procedure number %ld\n", NULLPROC);
                return (-1);
        }
        if (transp == 0) {
index 8828b639327b2c67a739c57bd04e7a9c0bef881f..077861fa8483298d486fed04dfb7351662cede5d 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)svc_tcp.c   2.2 88/08/01 4.0 RPCSRC";*/
-static char *rcsid = "$Id: svc_tcp.c,v 1.2 1999/10/14 21:56:54 wsanchez Exp $";
+static char *rcsid = "$Id: svc_tcp.c,v 1.3 2002/02/19 20:36:25 epeyton Exp $";
 #endif
 
 /*
@@ -67,11 +67,14 @@ static char *rcsid = "$Id: svc_tcp.c,v 1.2 1999/10/14 21:56:54 wsanchez Exp $";
  */
 
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
 #include <rpc/rpc.h>
 #include <sys/socket.h>
 #include <errno.h>
-extern bool_t abort();
-extern errno;
+
+extern int             bindresvport();
 
 /*
  * Ops vector for TCP/IP based rpc service handle
@@ -95,15 +98,16 @@ static struct xp_ops svctcp_op = {
 /*
  * Ops vector for TCP/IP rendezvous handler
  */
+static bool_t          rendezvous_abort();
 static bool_t          rendezvous_request();
 static enum xprt_stat  rendezvous_stat();
 
 static struct xp_ops svctcp_rendezvous_op = {
        rendezvous_request,
        rendezvous_stat,
-       abort,
-       abort,
-       abort,
+       rendezvous_abort,
+       rendezvous_abort,
+       rendezvous_abort,
        svctcp_destroy
 };
 
@@ -246,6 +250,13 @@ makefd_xprt(fd, sendsize, recvsize)
        return (xprt);
 }
 
+static bool_t
+rendezvous_abort()
+{       
+       abort();
+       return (FALSE);
+}
+
 static bool_t
 rendezvous_request(xprt)
        register SVCXPRT *xprt;
@@ -324,7 +335,7 @@ readtcp(xprt, buf, len)
        FD_SET(sock, &mask);
        do {
                readfds = mask;
-               if (select(sock+1, &readfds, (int*)NULL, (int*)NULL, 
+               if (select(sock+1, &readfds, NULL, NULL, 
                           &wait_per_try) <= 0) {
                        if (errno == EINTR) {
                                continue;
index 5af3045bac0d7a31b1033839d2b3322ae6023058..5d799b8e620a72a8b1e9f2a690fbd720d763d4f8 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)svc_udp.c 1.24 87/08/11 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)svc_udp.c   2.2 88/07/29 4.0 RPCSRC";*/
-static char *rcsid = "$Id: svc_udp.c,v 1.2 1999/10/14 21:56:54 wsanchez Exp $";
+static char *rcsid = "$Id: svc_udp.c,v 1.3 2002/02/19 20:36:25 epeyton Exp $";
 #endif
 
 /*
@@ -66,13 +66,15 @@ static char *rcsid = "$Id: svc_udp.c,v 1.2 1999/10/14 21:56:54 wsanchez Exp $";
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
 #include <rpc/rpc.h>
 #include <sys/socket.h>
 #include <errno.h>
 
+extern int             bindresvport();
 
 #define rpc_buffer(xprt) ((xprt)->xp_p1)
-#define MAX(a, b)     ((a > b) ? a : b)
 
 static bool_t          svcudp_recv();
 static bool_t          svcudp_reply();
@@ -361,6 +363,7 @@ struct udp_cache {
  * Enable use of the cache. 
  * Note: there is no disable.
  */
+int
 svcudp_enablecache(transp, size)
        SVCXPRT *transp;
        u_long size;
@@ -464,7 +467,7 @@ cache_set(xprt, replylen)
  * Try to get an entry from the cache
  * return 1 if found, 0 if not found
  */
-static
+static int
 cache_get(xprt, msg, replyp, replylenp)
        SVCXPRT *xprt;
        struct rpc_msg *msg;
index b9cd3cf9d02809043857cb172f36ee7584df8a3e..79f7ede0a0a1fbf69d407b511b24dc613ecc1b3c 100644 (file)
@@ -51,7 +51,7 @@
  *
  *     from: @(#)types.h 1.18 87/07/24 SMI
  *     from: @(#)types.h       2.3 88/08/15 4.0 RPCSRC
- *     $Id: types.h,v 1.2 1999/10/14 21:56:54 wsanchez Exp $
+ *     $Id: types.h,v 1.3 2002/07/27 18:24:28 majka Exp $
  */
 
 /*
@@ -74,7 +74,7 @@
 #      define NULL     0
 #endif
 
-#define mem_alloc(bsize)       malloc(bsize)
+#define mem_alloc(bsize)       calloc(1, bsize)
 #define mem_free(ptr, bsize)   free(ptr)
 
 #ifndef makedev /* ie, we haven't already included it */
index b523fee675b66a8deb495e764d876980018ffa9b..227f601e8172c98679d6283f906618e1f2fa9b26 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)xdr.c 1.35 87/08/12";*/
 /*static char *sccsid = "from: @(#)xdr.c       2.1 88/07/29 4.0 RPCSRC";*/
-static char *rcsid = "$Id: xdr.c,v 1.2 1999/10/14 21:56:54 wsanchez Exp $";
+static char *rcsid = "$Id: xdr.c,v 1.3 2002/02/19 20:36:26 epeyton Exp $";
 #endif
 
 /*
@@ -67,6 +67,8 @@ static char *rcsid = "$Id: xdr.c,v 1.2 1999/10/14 21:56:54 wsanchez Exp $";
  */
 
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 
 #include <rpc/types.h>
 #include <rpc/xdr.h>
@@ -360,7 +362,7 @@ xdr_opaque(xdrs, cp, cnt)
        register u_int cnt;
 {
        register u_int rndup;
-       static crud[BYTES_PER_XDR_UNIT];
+       static char crud[BYTES_PER_XDR_UNIT];
 
        /*
         * if no data we are done
index 356b79553beaa3c51b2498088ab34c57b5b70937..7d684748794ba721877fd9ca7a21514470b2d012 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)xdr_array.c 2.1 88/07/29 4.0 RPCSRC";*/
-static char *rcsid = "$Id: xdr_array.c,v 1.2 1999/10/14 21:56:55 wsanchez Exp $";
+static char *rcsid = "$Id: xdr_array.c,v 1.3 2002/02/19 20:36:26 epeyton Exp $";
 #endif
 
 /*
@@ -67,6 +67,7 @@ static char *rcsid = "$Id: xdr_array.c,v 1.2 1999/10/14 21:56:55 wsanchez Exp $"
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <rpc/types.h>
 #include <rpc/xdr.h>
 
index 3bec281554c356904c4964a2314a5eb114c9fdc1..88848e3cd0b1f21931700479fbedb7d1f86529a1 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint)
 /*static char *sccsid = "from: @(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)xdr_mem.c   2.1 88/07/29 4.0 RPCSRC";*/
-static char *rcsid = "$Id: xdr_mem.c,v 1.2 1999/10/14 21:56:55 wsanchez Exp $";
+static char *rcsid = "$Id: xdr_mem.c,v 1.3 2002/02/19 20:36:26 epeyton Exp $";
 #endif
 
 /*
@@ -68,6 +68,7 @@ static char *rcsid = "$Id: xdr_mem.c,v 1.2 1999/10/14 21:56:55 wsanchez Exp $";
  */
 
 
+#include <string.h>
 #include <rpc/types.h>
 #include <rpc/xdr.h>
 #include <netinet/in.h>
index 912dbfb0f5bd8916d123385b732c475557aba147..27228961dafedec02f84e5000d42395cb8398dd8 100644 (file)
@@ -52,7 +52,7 @@
 #if defined(LIBC_SCCS) && !defined(lint) 
 /*static char *sccsid = "from: @(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/
 /*static char *sccsid = "from: @(#)xdr_rec.c   2.2 88/08/01 4.0 RPCSRC";*/
-static char *rcsid = "$Id: xdr_rec.c,v 1.2 1999/10/14 21:56:55 wsanchez Exp $";
+static char *rcsid = "$Id: xdr_rec.c,v 1.3 2002/02/19 20:36:26 epeyton Exp $";
 #endif
 
 /*
@@ -74,6 +74,8 @@ static char *rcsid = "$Id: xdr_rec.c,v 1.2 1999/10/14 21:56:55 wsanchez Exp $";
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
 #include <rpc/types.h>
 #include <rpc/xdr.h>
 #include <netinet/in.h>
index bfc82e116bc9be2f39837d446323b69683f1a28b..acdd540b1d694c6fc4f4b0cb89dc7ef414bfdb10 100644 (file)
@@ -53,7 +53,7 @@
 #if defined(LIBC_SCCS) && !defined(lint) 
 /*static char *sccsid = "from: @(#)xdr_reference.c 1.11 87/08/11 SMI";*/
 /*static char *sccsid = "from: @(#)xdr_reference.c     2.1 88/07/29 4.0 RPCSRC";*/
-static char *rcsid = "$Id: xdr_reference.c,v 1.2 1999/10/14 21:56:55 wsanchez Exp $";
+static char *rcsid = "$Id: xdr_reference.c,v 1.3 2002/02/19 20:36:26 epeyton Exp $";
 #endif
 
 /*
@@ -66,6 +66,8 @@ static char *rcsid = "$Id: xdr_reference.c,v 1.2 1999/10/14 21:56:55 wsanchez Ex
  */
 
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <rpc/types.h>
 #include <rpc/xdr.h>
 
index aede900dc206d6cc2faba7e5d154c06af6da990f..499e7e61c9008f93227c342fa0a856a0665c3e40 100644 (file)
@@ -15,7 +15,7 @@ PROJECT_TYPE = Component
 CFILES = getgrouplist.c glob.c hton.c putpwpasswd.c pwcache.c rcmd.c\
          rcmdsh.c
 
-OTHERSRCS = Makefile
+OTHERSRCS = Makefile Makefile.preamble Makefile.postamble rcmd.3
 
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
diff --git a/util.subproj/Makefile.postamble b/util.subproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..b2a9e16
--- /dev/null
@@ -0,0 +1,119 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES    # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+#COMPATIBILITY_PROJECT_VERSION = 1
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wall
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User/group ownership 
+#INSTALL_AS_GROUP = wheel      # (probably want to set both of these) 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S   # for .a archives
+#DYNAMIC_STRIP_OPTS = -S   # for bundles and shared libraries
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
+install-man-page:
+       mkdir -p "$(DSTROOT)/usr/share/man/man3"
+       install -c -m 644 rcmd.3 "$(DSTROOT)/usr/share/man/man3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/rcmd.3" "$(DSTROOT)/usr/share/man/man3/iruserok.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/rcmd.3" "$(DSTROOT)/usr/share/man/man3/iruserok_sa.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/rcmd.3" "$(DSTROOT)/usr/share/man/man3/rcmd_af.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/rcmd.3" "$(DSTROOT)/usr/share/man/man3/rresvport.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/rcmd.3" "$(DSTROOT)/usr/share/man/man3/rresvport_af.3"
+       $(LN) -f "$(DSTROOT)/usr/share/man/man3/rcmd.3" "$(DSTROOT)/usr/share/man/man3/ruserok.3"
diff --git a/util.subproj/Makefile.preamble b/util.subproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..9b478c6
--- /dev/null
@@ -0,0 +1,3 @@
+AFTER_POSTINSTALL += install-man-page
+OTHER_CFLAGS = \
+       -DINET6=1 \
index eab47ff4306b02de77dc6fba009140dfb4171b04..2c20a90c81ef73a1354239e783480160883900cd 100644 (file)
@@ -2,7 +2,7 @@
     DYNAMIC_CODE_GEN = YES; 
     FILESTABLE = {
         OTHER_LINKED = (getgrouplist.c, glob.c, hton.c, putpwpasswd.c, pwcache.c, rcmd.c, rcmdsh.c); 
-        OTHER_SOURCES = (Makefile); 
+        OTHER_SOURCES = (Makefile, Makefile.preamble, Makefile.postamble, rcmd.3); 
     }; 
     LANGUAGE = English; 
     MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
index 305f1b8e7d2877f392d4bc4744f50b4224a6416c..b342f6042e6624ad5e6a027eab9915f21e5097c5 100644 (file)
@@ -73,7 +73,6 @@ getgrouplist(uname, agroup, groups, grpcnt)
        int *grpcnt;
 {
        register struct group *grp;
-       register struct passwd *pw;
        register int i, ngroups;
        int ret, maxgroups;
 
@@ -92,7 +91,7 @@ getgrouplist(uname, agroup, groups, grpcnt)
         * Scan the group file to find additional groups.
         */
        setgrent();
-       while (grp = getgrent()) {
+       while ((grp = getgrent())) {
                if (grp->gr_gid == agroup)
                        continue;
                for (i = 0; grp->gr_mem[i]; i++) {
index f0a4eec5071c5e286e5a36faee181b2d0403b361..3f2b72b7fd592f9a63f4085c404905ef16e246a0 100644 (file)
 #include <grp.h>
 #include <pwd.h>
 #include <stdio.h>
+#include <string.h>
 #include <utmp.h>
 
 #define        NCACHE  64                      /* power of 2 */
-#define        MASK    NCACHE - 1              /* bits to store with */
+#define        MASK    (NCACHE - 1)            /* bits to store with */
 
 char *
 user_from_uid(uid, nouser)
@@ -52,29 +53,35 @@ user_from_uid(uid, nouser)
        static struct ncache {
                uid_t   uid;
                char    name[UT_NAMESIZE + 1];
-       } c_uid[NCACHE];
+       } *c_uid[NCACHE];
        static int pwopen;
        static char nbuf[15];           /* 32 bits == 10 digits */
        register struct passwd *pw;
-       register struct ncache *cp;
+       register struct ncache **cp;
 
-       cp = c_uid + (uid & MASK);
-       if (cp->uid != uid || !*cp->name) {
+       cp = &c_uid[uid & MASK];
+       if (*cp == NULL || (*cp)->uid != uid || !*(*cp)->name) {
                if (pwopen == 0) {
                        setpassent(1);
                        pwopen = 1;
                }
                if ((pw = getpwuid(uid)) == NULL) {
+err:
                        if (nouser)
                                return (NULL);
                        (void)snprintf(nbuf, sizeof(nbuf), "%u", uid);
                        return (nbuf);
                }
-               cp->uid = uid;
-               (void)strncpy(cp->name, pw->pw_name, UT_NAMESIZE);
-               cp->name[UT_NAMESIZE] = '\0';
+               if (*cp == NULL) {
+                       *cp = malloc(sizeof(struct ncache));
+                       if (*cp == NULL)
+                               goto err;
+               }
+               (*cp)->uid = uid;
+               (void)strncpy((*cp)->name, pw->pw_name, UT_NAMESIZE);
+               (*cp)->name[UT_NAMESIZE] = '\0';
        }
-       return (cp->name);
+       return ((*cp)->name);
 }
 
 char *
@@ -85,27 +92,33 @@ group_from_gid(gid, nogroup)
        static struct ncache {
                gid_t   gid;
                char    name[UT_NAMESIZE + 1];
-       } c_gid[NCACHE];
+       } *c_gid[NCACHE];
        static int gropen;
        static char nbuf[15];           /* 32 bits == 10 digits */
        struct group *gr;
-       struct ncache *cp;
+       struct ncache **cp = NULL;
 
-       cp = c_gid + (gid & MASK);
-       if (cp->gid != gid || !*cp->name) {
+       cp = &c_gid[gid & MASK];
+       if (*cp == NULL || (*cp)->gid != gid || !*(*cp)->name) {
                if (gropen == 0) {
                        setgroupent(1);
                        gropen = 1;
                }
                if ((gr = getgrgid(gid)) == NULL) {
+err:
                        if (nogroup)
                                return (NULL);
                        (void)snprintf(nbuf, sizeof(nbuf), "%u", gid);
                        return (nbuf);
                }
-               cp->gid = gid;
-               (void)strncpy(cp->name, gr->gr_name, UT_NAMESIZE);
-               cp->name[UT_NAMESIZE] = '\0';
+               if (*cp == NULL) {
+                       *cp = malloc(sizeof(struct ncache));
+                       if (*cp == NULL)
+                               goto err;
+               }
+               (*cp)->gid = gid;
+               (void)strncpy((*cp)->name, gr->gr_name, UT_NAMESIZE);
+               (*cp)->name[UT_NAMESIZE] = '\0';
        }
-       return (cp->name);
+       return ((*cp)->name);
 }
diff --git a/util.subproj/rcmd.3 b/util.subproj/rcmd.3
new file mode 100644 (file)
index 0000000..2fe71d0
--- /dev/null
@@ -0,0 +1,298 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     From: @(#)rcmd.3       8.1 (Berkeley) 6/4/93
+.\" $FreeBSD: src/lib/libc/net/rcmd.3,v 1.12.2.7 2001/08/17 15:42:38 ru Exp $
+.\"
+.Dd March 3, 2000
+.Dt RCMD 3
+.Os
+.Sh NAME
+.Nm rcmd ,
+.Nm rresvport ,
+.Nm iruserok ,
+.Nm ruserok ,
+.Nm rcmd_af ,
+.Nm rresvport_af ,
+.Nm iruserok_sa
+.Nd routines for returning a stream to a remote command
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.Fd #include <unistd.h>
+.Ft int
+.Fn rcmd "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "int *fd2p"
+.Ft int
+.Fn rresvport "int *port"
+.Ft int
+.Fn iruserok "u_long raddr" "int superuser" "const char *ruser" "const char *luser"
+.Ft int
+.Fn ruserok "const char *rhost" "int superuser" "const char *ruser" "const char *luser"
+.Ft int
+.Fn rcmd_af "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "int *fd2p" "int af"
+.Ft int
+.Fn rresvport_af "int *port" "int af"
+.Ft int
+.Fn iruserok_sa "const void *addr" "int addrlen" "int superuser" "const char *ruser" "const char *luser"
+.Sh DESCRIPTION
+The
+.Fn rcmd
+function
+is used by the super-user to execute a command on
+a remote machine using an authentication scheme based
+on reserved port numbers.
+The
+.Fn rresvport
+function
+returns a descriptor to a socket
+with an address in the privileged port space.
+The
+.Fn ruserok
+function
+is used by servers
+to authenticate clients requesting service with
+.Fn rcmd .
+All three functions are present in the same file and are used
+by the
+.Xr rshd 8
+server (among others).
+.Pp
+The
+.Fn rcmd
+function
+looks up the host
+.Fa *ahost
+using
+.Xr gethostbyname 3 ,
+returning -1 if the host does not exist.
+Otherwise
+.Fa *ahost
+is set to the standard name of the host
+and a connection is established to a server
+residing at the well-known Internet port
+.Fa inport .
+.Pp
+If the connection succeeds,
+a socket in the Internet domain of type
+.Dv SOCK_STREAM
+is returned to the caller, and given to the remote
+command as
+.Em stdin
+and
+.Em stdout .
+If
+.Fa fd2p
+is non-zero, then an auxiliary channel to a control
+process will be set up, and a descriptor for it will be placed
+in
+.Fa *fd2p .
+The control process will return diagnostic
+output from the command (unit 2) on this channel, and will also
+accept bytes on this channel as being
+.Tn UNIX
+signal numbers, to be
+forwarded to the process group of the command.
+If
+.Fa fd2p
+is 0, then the
+.Em stderr
+(unit 2 of the remote
+command) will be made the same as the
+.Em stdout
+and no
+provision is made for sending arbitrary signals to the remote process,
+although you may be able to get its attention by using out-of-band data.
+.Pp
+The protocol is described in detail in
+.Xr rshd 8 .
+.Pp
+The
+.Fn rresvport
+function is used to obtain a socket to which an address with a Privileged
+Internet port is bound.
+This socket is suitable for use by
+.Fn rcmd
+and several other functions.
+Privileged Internet ports are those in the range 0 to 1023.
+Only the super-user is allowed to bind an address of this sort
+to a socket.
+.Pp
+The
+.Fn iruserok
+and
+.Fn ruserok
+functions take a remote host's IP address or name, as returned by the
+.Xr gethostbyname 3
+routines, two user names and a flag indicating whether the local user's
+name is that of the super-user.
+Then, if the user is
+.Em NOT
+the super-user, it checks the
+.Pa /etc/hosts.equiv
+file.
+If that lookup is not done, or is unsuccessful, the
+.Pa .rhosts
+in the local user's home directory is checked to see if the request for
+service is allowed.
+.Pp
+If this file does not exist, is not a regular file, is owned by anyone
+other than the user or the super-user, or is writable by anyone other
+than the owner, the check automatically fails.
+Zero is returned if the machine name is listed in the
+.Dq Pa hosts.equiv
+file, or the host and remote user name are found in the
+.Dq Pa .rhosts
+file; otherwise
+.Fn iruserok
+and
+.Fn ruserok
+return -1.
+If the local domain (as obtained from
+.Xr gethostname 3 )
+is the same as the remote domain, only the machine name need be specified.
+.Pp
+The
+.Fn iruserok
+function is strongly preferred for security reasons.
+It requires trusting the local DNS at most, while the
+.Fn ruserok
+function requires trusting the entire DNS, which can be spoofed.
+.Pp
+The functions with an
+.Dq Li _af
+or
+.Dq Li _sa
+suffix, i.e.,
+.Fn rcmd_af ,
+.Fn rresvport_af
+and
+.Fn iruserok_sa ,
+work the same as the corresponding functions without a
+suffix, except that they are capable of handling both IPv6 and IPv4 ports.
+.Pp
+The
+.Dq Li _af
+suffix means that the function has an additional
+.Fa af
+argument which is used to specify the address family,
+(see below).
+The
+.Fa af
+argument extension is implemented for functions
+that have no binary address argument.
+Instead, the
+.Fa af
+argument specifies which address family is desired.
+.Pp
+The
+.Dq Li _sa
+suffix means that the function has general socket address and
+length arguments.
+As the socket address is a protocol independent data structure,
+IPv4 and IPv6 socket address can be passed as desired.
+The
+.Fa sa
+argument extension is implemented for functions
+that pass a protocol dependent binary address argument.
+The argument needs to be replaced with a more general address structure
+to support multiple address families in a general way.
+.Pp
+The functions with neither an
+.Dq Li _af
+suffix nor an
+.Dq Li _sa
+suffix work for IPv4 only, except for
+.Fn ruserok
+which can handle both IPv6 and IPv4.
+To switch the address family, the
+.Fa af
+argument must be filled with
+.Dv AF_INET ,
+or
+.Dv AF_INET6 .
+For
+.Fn rcmd_af ,
+.Dv PF_UNSPEC
+is also allowed.
+.Sh DIAGNOSTICS
+The
+.Fn rcmd
+function
+returns a valid socket descriptor on success.
+It returns -1 on error and prints a diagnostic message
+on the standard error.
+.Pp
+The
+.Fn rresvport
+function
+returns a valid, bound socket descriptor on success.
+It returns -1 on error with the global value
+.Va errno
+set according to the reason for failure.
+The error code
+.Er EAGAIN
+is overloaded to mean ``All network ports in use.''
+.Sh SEE ALSO
+.Xr rlogin 1 ,
+.Xr rsh 1 ,
+.Xr intro 2 ,
+.Xr rexec 3 ,
+.Xr rexecd 8 ,
+.Xr rlogind 8 ,
+.Xr rshd 8
+.Pp
+.Rs
+.%A W. Stevens
+.%A M. Thomas
+.%T "Advanced Socket API for IPv6"
+.%O RFC2292
+.Re
+.Rs
+.%A W. Stevens
+.%A M. Thomas
+.%A E. Nordmark
+.%T "Advanced Socket API for IPv6"
+.%O draft-ietf-ipngwg-rfc2292bis-01.txt
+.Re
+.Sh HISTORY
+Most of these
+functions appeared in
+.Bx 4.2 .
+.Fn rresvport_af
+appeared in RFC2292, and was implemented by the WIDE project
+for the Hydrangea IPv6 protocol stack kit.
+.Fn rcmd_af
+appeared in draft-ietf-ipngwg-rfc2292bis-01.txt,
+and was implemented in the WIDE/KAME IPv6 protocol stack kit.
+.Fn iruserok_sa
+appeared in discussion on the IETF ipngwg mailing list,
+and was implemented in
+.Fx 4.0 .
index 611b94d866d642bd12a7fa76d4fca5dd4ea90b15..4345fb7b55698f06b9c9e78aa80fc49b6655e394 100644 (file)
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libc/net/rcmd.c,v 1.23.2.5 2001/03/05 10:47:11 obrien Exp $
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char *rcsid = "$OpenBSD: rcmd.c,v 1.30 1998/02/12 02:21:19 deraadt Exp $";
+static char sccsid[] = "@(#)rcmd.c     8.3 (Berkeley) 3/26/94";
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/param.h>
@@ -77,19 +79,34 @@ static char *rcsid = "$OpenBSD: rcmd.c,v 1.30 1998/02/12 02:21:19 deraadt Exp $"
 #include <stdio.h>
 #include <ctype.h>
 #include <string.h>
-#include <syslog.h>
-#include <stdlib.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+#include <arpa/nameser.h>
+
+/* wrapper for KAME-special getnameinfo() */
+#ifndef NI_WITHSCOPEID
+#define NI_WITHSCOPEID 0
+#endif
+
+#ifndef socklen_t
+#define socklen_t int
+#endif
 
-typedef u_int32_t       in_addr_t;      /* base type for internet address */
-typedef u_int16_t       in_port_t;      /* IP port type */
+extern int innetgr __P(( const char *, const char *, const char *, const char * ));
 
-extern int bindresvport(int sd, struct sockaddr_in *sin);
-extern int getdomainname(char *val, size_t len);
-extern int rcmdsh(char **ahost, int rport, const char *locuser, const char *remuser, const char *cmd, char *rshprog);
+#define max(a, b)      ((a > b) ? a : b)
+
+int    __ivaliduser __P((FILE *, u_int32_t, const char *, const char *));
+int __ivaliduser_af __P((FILE *,const void *, const char *, const char *,
+       int, int));
+int __ivaliduser_sa __P((FILE *, const struct sockaddr *, socklen_t,
+       const char *,const char *));
+static int __icheckhost __P((const struct sockaddr *, socklen_t,
+       const char *));
 
-int    __ivaliduser __P((FILE *, in_addr_t, const char *, const char *));
-static int __icheckhost __P((u_int32_t, const char *));
-static char *__gethostloop __P((u_int32_t));
 
 int
 rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
@@ -98,87 +115,121 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
        const char *locuser, *remuser, *cmd;
        int *fd2p;
 {
-       struct hostent *hp;
-       struct sockaddr_in sin, from;
-       fd_set *readsp = NULL;
-       int oldmask;
-       pid_t pid;
-       int s, lport, timo;
-       char c, *p;
-
-       /* call rcmdsh() with specified remote shell if appropriate. */
-       if ((getuid() == geteuid()) && (p = getenv("RSH"))) {
-               struct servent *sp = getservbyname("shell", "tcp");
-
-               if (sp && sp->s_port == rport)
-                       return (rcmdsh(ahost, rport, locuser, remuser,
-                           cmd, p));
-       }
-
-       /* use rsh(1) if non-root and remote port is shell. */
-       if (geteuid()) {
-               struct servent *sp = getservbyname("shell", "tcp");
+       return rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, AF_INET);
+}
 
-               if (sp && sp->s_port == rport)
-                       return (rcmdsh(ahost, rport, locuser, remuser,
-                           cmd, NULL));
-       }
+int
+rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af)
+       char **ahost;
+       u_short rport;
+       const char *locuser, *remuser, *cmd;
+       int *fd2p;
+       int af;
+{
+       struct addrinfo hints, *res, *ai;
+       struct sockaddr_storage from;
+       fd_set reads;
+       long oldmask;
+       pid_t pid;
+       int s, aport, lport, timo, error;
+       char c;
+       int refused, nres;
+       char num[8], paddr[NI_MAXHOST];
+       static char canonnamebuf[MAXDNAME];     /* is it proper here? */
 
        pid = getpid();
-       hp = gethostbyname(*ahost);
-       if (hp == NULL) {
-               herror(*ahost);
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_flags = AI_CANONNAME;
+       hints.ai_family = af;
+       hints.ai_socktype = SOCK_STREAM;
+       hints.ai_protocol = 0;
+       (void)snprintf(num, sizeof(num), "%d", ntohs(rport));
+       error = getaddrinfo(*ahost, num, &hints, &res);
+       if (error) {
+               fprintf(stderr, "rcmd: getaddrinfo: %s\n",
+                       gai_strerror(error));
+               if (error == EAI_SYSTEM)
+                       fprintf(stderr, "rcmd: getaddrinfo: %s\n",
+                               strerror(errno));
                return (-1);
        }
-       *ahost = hp->h_name;
 
+       if (res->ai_canonname
+        && strlen(res->ai_canonname) + 1 < sizeof(canonnamebuf)) {
+               strncpy(canonnamebuf, res->ai_canonname, sizeof(canonnamebuf));
+               *ahost = canonnamebuf;
+       }
+       nres = 0;
+       for (ai = res; ai; ai = ai->ai_next)
+               nres++;
+       ai = res;
+       refused = 0;
        oldmask = sigblock(sigmask(SIGURG));
        for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
-               s = rresvport(&lport);
+               s = rresvport_af(&lport, ai->ai_family);
                if (s < 0) {
+                       if (errno != EAGAIN && ai->ai_next) {
+                               ai = ai->ai_next;
+                               continue;
+                       }
                        if (errno == EAGAIN)
                                (void)fprintf(stderr,
                                    "rcmd: socket: All ports in use\n");
                        else
                                (void)fprintf(stderr, "rcmd: socket: %s\n",
                                    strerror(errno));
+                       freeaddrinfo(res);
                        sigsetmask(oldmask);
                        return (-1);
                }
                fcntl(s, F_SETOWN, pid);
-               bzero(&sin, sizeof sin);
-               sin.sin_len = sizeof(struct sockaddr_in);
-               sin.sin_family = hp->h_addrtype;
-               sin.sin_port = rport;
-               bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length);
-               if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
+               if (connect(s, ai->ai_addr, ai->ai_addrlen) >= 0)
                        break;
                (void)close(s);
                if (errno == EADDRINUSE) {
                        lport--;
                        continue;
                }
-               if (errno == ECONNREFUSED && timo <= 16) {
-                       (void)sleep(timo);
-                       timo *= 2;
-                       continue;
+               if (errno == ECONNREFUSED)
+                       refused = 1;
+               if (ai->ai_next == NULL && (!refused || timo > 16)) {
+                       (void)fprintf(stderr, "%s: %s\n",
+                                     *ahost, strerror(errno));
+                       freeaddrinfo(res);
+                       sigsetmask(oldmask);
+                       return (-1);
                }
-               if (hp->h_addr_list[1] != NULL) {
+               if (nres > 1) {
                        int oerrno = errno;
 
+                       getnameinfo(ai->ai_addr, ai->ai_addrlen,
+                                   paddr, sizeof(paddr),
+                                   NULL, 0,
+                                   NI_NUMERICHOST|NI_WITHSCOPEID);
                        (void)fprintf(stderr, "connect to address %s: ",
-                           inet_ntoa(sin.sin_addr));
+                                     paddr);
                        errno = oerrno;
                        perror(0);
-                       hp->h_addr_list++;
-                       bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length);
-                       (void)fprintf(stderr, "Trying %s...\n",
-                           inet_ntoa(sin.sin_addr));
-                       continue;
                }
-               (void)fprintf(stderr, "%s: %s\n", hp->h_name, strerror(errno));
-               sigsetmask(oldmask);
-               return (-1);
+               if ((ai = ai->ai_next) == NULL) {
+                       /* refused && timo <= 16 */
+                       struct timespec time_to_sleep, time_remaining;
+
+                       time_to_sleep.tv_sec = timo;
+                       time_to_sleep.tv_nsec = 0;
+                       (void)nanosleep(&time_to_sleep, &time_remaining);
+                       timo *= 2;
+                       ai = res;
+                       refused = 0;
+               }
+               if (nres > 1) {
+                       getnameinfo(ai->ai_addr, ai->ai_addrlen,
+                                   paddr, sizeof(paddr),
+                                   NULL, 0,
+                                   NI_NUMERICHOST|NI_WITHSCOPEID);
+                       fprintf(stderr, "Trying %s...\n", paddr);
+               }
        }
 #if 0
        /*
@@ -192,15 +243,12 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
                lport = 0;
        } else {
                char num[8];
-               int s2 = rresvport(&lport), s3;
-               int len = sizeof(from);
-               int fdssize = howmany(MAX(s, s2)+1, NFDBITS) * sizeof(fd_mask);
+               int s2 = rresvport_af(&lport, ai->ai_family), s3;
+               int len = ai->ai_addrlen;
+               int nfds;
 
                if (s2 < 0)
                        goto bad;
-               readsp = (fd_set *)malloc(fdssize);
-               if (readsp == NULL)
-                       goto bad;
                listen(s2, 1);
                (void)snprintf(num, sizeof(num), "%d", lport);
                if (write(s, num, strlen(num)+1) != strlen(num)+1) {
@@ -210,13 +258,18 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
                        (void)close(s2);
                        goto bad;
                }
+               nfds = max(s, s2)+1;
+               if(nfds > FD_SETSIZE) {
+                       fprintf(stderr, "rcmd: too many files\n");
+                       (void)close(s2);
+                       goto bad;
+               }
 again:
-               bzero(readsp, fdssize);
-               FD_SET(s, readsp);
-               FD_SET(s2, readsp);
+               FD_ZERO(&reads);
+               FD_SET(s, &reads);
+               FD_SET(s2, &reads);
                errno = 0;
-               if (select(MAX(s, s2) + 1, readsp, 0, 0, 0) < 1 ||
-                   !FD_ISSET(s2, readsp)) {
+               if (select(nfds, &reads, 0, 0, 0) < 1 || !FD_ISSET(s2, &reads)){
                        if (errno != 0)
                                (void)fprintf(stderr,
                                    "rcmd: select (setting up stderr): %s\n",
@@ -228,11 +281,24 @@ again:
                        goto bad;
                }
                s3 = accept(s2, (struct sockaddr *)&from, &len);
+               switch (from.ss_family) {
+               case AF_INET:
+                       aport = ntohs(((struct sockaddr_in *)&from)->sin_port);
+                       break;
+#ifdef INET6
+               case AF_INET6:
+                       aport = ntohs(((struct sockaddr_in6 *)&from)->sin6_port);
+                       break;
+#endif
+               default:
+                       aport = 0;      /* error */
+                       break;
+               }
                /*
                 * XXX careful for ftp bounce attacks. If discovered, shut them
                 * down and check for the real auxiliary channel to connect.
                 */
-               if (from.sin_family == AF_INET && from.sin_port == htons(20)) {
+               if (aport == 20) {
                        close(s3);
                        goto again;
                }
@@ -244,10 +310,7 @@ again:
                        goto bad;
                }
                *fd2p = s3;
-               from.sin_port = ntohs(from.sin_port);
-               if (from.sin_family != AF_INET ||
-                   from.sin_port >= IPPORT_RESERVED ||
-                   from.sin_port < IPPORT_RESERVED / 2) {
+               if (aport >= IPPORT_RESERVED || aport < IPPORT_RESERVED / 2) {
                        (void)fprintf(stderr,
                            "socket: protocol failure in circuit setup.\n");
                        goto bad2;
@@ -270,48 +333,71 @@ again:
                goto bad2;
        }
        sigsetmask(oldmask);
-       free(readsp);
+       freeaddrinfo(res);
        return (s);
 bad2:
        if (lport)
                (void)close(*fd2p);
 bad:
-       if (readsp)
-               free(readsp);
        (void)close(s);
        sigsetmask(oldmask);
+       freeaddrinfo(res);
        return (-1);
 }
 
 int
-rresvport(alport)
-       int *alport;
+rresvport(port)
+       int *port;
+{
+       return rresvport_af(port, AF_INET);
+}
+
+int
+rresvport_af(alport, family)
+       int *alport, family;
 {
-       struct sockaddr_in sin;
        int s;
+       struct sockaddr_storage ss;
+       u_short *sport;
+
+       memset(&ss, 0, sizeof(ss));
+       ss.ss_family = family;
+       switch (family) {
+       case AF_INET:
+               ((struct sockaddr *)&ss)->sa_len = sizeof(struct sockaddr_in);
+               sport = &((struct sockaddr_in *)&ss)->sin_port;
+               ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
+               break;
+#ifdef INET6
+       case AF_INET6:
+               ((struct sockaddr *)&ss)->sa_len = sizeof(struct sockaddr_in6);
+               sport = &((struct sockaddr_in6 *)&ss)->sin6_port;
+               ((struct sockaddr_in6 *)&ss)->sin6_addr = in6addr_any;
+               break;
+#endif
+       default:
+               errno = EAFNOSUPPORT;
+               return -1;
+       }
 
-       bzero(&sin, sizeof sin);
-       sin.sin_len = sizeof(struct sockaddr_in);
-       sin.sin_family = AF_INET;
-       sin.sin_addr.s_addr = INADDR_ANY;
-       s = socket(AF_INET, SOCK_STREAM, 0);
+       s = socket(ss.ss_family, SOCK_STREAM, 0);
        if (s < 0)
                return (-1);
-       sin.sin_port = htons((in_port_t)*alport);
-       if (*alport < IPPORT_RESERVED - 1) {
-               if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
-                       return (s);
-               if (errno != EADDRINUSE) {
-                       (void)close(s);
-                       return (-1);
-               }
+#if 0 /* compat_exact_traditional_rresvport_semantics */
+       sin.sin_port = htons((u_short)*alport);
+       if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
+               return (s);
+       if (errno != EADDRINUSE) {
+               (void)close(s);
+               return (-1);
        }
-       sin.sin_port = 0;
-       if (bindresvport(s, &sin) == -1) {
+#endif
+       *sport = 0;
+       if (bindresvport_sa(s, (struct sockaddr *)&ss) == -1) {
                (void)close(s);
                return (-1);
        }
-       *alport = (int)ntohs(sin.sin_port);
+       *alport = (int)ntohs(*sport);
        return (s);
 }
 
@@ -323,21 +409,24 @@ ruserok(rhost, superuser, ruser, luser)
        const char *rhost, *ruser, *luser;
        int superuser;
 {
-       struct hostent *hp;
-       char **ap;
-       int i;
-#define MAXADDRS       35
-       u_int32_t addrs[MAXADDRS + 1];
-
-       if ((hp = gethostbyname(rhost)) == NULL)
+       struct addrinfo hints, *res, *r;
+       int error;
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = PF_UNSPEC;
+       hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+       error = getaddrinfo(rhost, "0", &hints, &res);
+       if (error)
                return (-1);
-       for (i = 0, ap = hp->h_addr_list; *ap && i < MAXADDRS; ++ap, ++i)
-               bcopy(*ap, &addrs[i], sizeof(addrs[i]));
-       addrs[i] = 0;
 
-       for (i = 0; i < MAXADDRS && addrs[i]; i++)
-               if (iruserok((in_addr_t)addrs[i], superuser, ruser, luser) == 0)
+       for (r = res; r; r = r->ai_next) {
+               if (iruserok_sa(r->ai_addr, r->ai_addrlen, superuser, ruser,
+                   luser) == 0) {
+                       freeaddrinfo(res);
                        return (0);
+               }
+       }
+       freeaddrinfo(res);
        return (-1);
 }
 
@@ -355,6 +444,28 @@ iruserok(raddr, superuser, ruser, luser)
        unsigned long raddr;
        int superuser;
        const char *ruser, *luser;
+{
+       struct sockaddr_in sin;
+
+       memset(&sin, 0, sizeof(sin));
+       sin.sin_family = AF_INET;
+       sin.sin_len = sizeof(struct sockaddr_in);
+       memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr));
+       return iruserok_sa((struct sockaddr *)&sin, sin.sin_len, superuser,
+               ruser, luser);
+}
+
+/*
+ * AF independent extension of iruserok.
+ *
+ * Returns 0 if ok, -1 if not ok.
+ */
+int
+iruserok_sa(ra, rlen, superuser, ruser, luser)
+       const void *ra;
+       int rlen;
+       int superuser;
+       const char *ruser, *luser;
 {
        register char *cp;
        struct stat sbuf;
@@ -363,12 +474,20 @@ iruserok(raddr, superuser, ruser, luser)
        uid_t uid;
        int first;
        char pbuf[MAXPATHLEN];
+       const struct sockaddr *raddr;
+       struct sockaddr_storage ss;
+
+       /* avoid alignment issue */
+       if (rlen > sizeof(ss)) 
+               return(-1);
+       memcpy(&ss, ra, rlen);
+       raddr = (struct sockaddr *)&ss;
 
        first = 1;
        hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
 again:
        if (hostf) {
-               if (__ivaliduser(hostf, raddr, luser, ruser) == 0) {
+               if (__ivaliduser_sa(hostf, raddr, rlen, luser, ruser) == 0) {
                        (void)fclose(hostf);
                        return (0);
                }
@@ -426,212 +545,249 @@ again:
  * Returns 0 if ok, -1 if not ok.
  */
 int
-__ivaliduser(hostf, raddrl, luser, ruser)
+__ivaliduser(hostf, raddr, luser, ruser)
        FILE *hostf;
-       in_addr_t raddrl;
+       u_int32_t raddr;
        const char *luser, *ruser;
 {
-       register char *user, *p;
-       char *buf;
-       const char *auser, *ahost;
-       int hostok, userok;
-       char *rhost = (char *)-1;
-       char domain[MAXHOSTNAMELEN];
-       u_int32_t raddr = (u_int32_t)raddrl;
-       size_t buflen;
+       struct sockaddr_in sin;
+
+       memset(&sin, 0, sizeof(sin));
+       sin.sin_family = AF_INET;
+       sin.sin_len = sizeof(struct sockaddr_in);
+       memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr));
+       return __ivaliduser_sa(hostf, (struct sockaddr *)&sin, sin.sin_len,
+               luser, ruser);
+}
+
+/*
+ * Returns 0 if ok, -1 if not ok.
+ *
+ * XXX obsolete API.
+ */
+int
+__ivaliduser_af(hostf, raddr, luser, ruser, af, len)
+       FILE *hostf;
+       const void *raddr;
+       const char *luser, *ruser;
+       int af, len;
+{
+       struct sockaddr *sa = NULL;
+       struct sockaddr_in *sin = NULL;
+#ifdef INET6
+       struct sockaddr_in6 *sin6 = NULL;
+#endif
+       struct sockaddr_storage ss;
+
+       memset(&ss, 0, sizeof(ss));
+       switch (af) {
+       case AF_INET:
+               if (len != sizeof(sin->sin_addr))
+                       return -1;
+               sin = (struct sockaddr_in *)&ss;
+               sin->sin_family = AF_INET;
+               sin->sin_len = sizeof(struct sockaddr_in);
+               memcpy(&sin->sin_addr, raddr, sizeof(sin->sin_addr));
+               break;
+#ifdef INET6
+       case AF_INET6:
+               if (len != sizeof(sin6->sin6_addr))
+                       return -1;
+               /* you will lose scope info */
+               sin6 = (struct sockaddr_in6 *)&ss;
+               sin6->sin6_family = AF_INET6;
+               sin6->sin6_len = sizeof(struct sockaddr_in6);
+               memcpy(&sin6->sin6_addr, raddr, sizeof(sin6->sin6_addr));
+               break;
+#endif
+       default:
+               return -1;
+       }
 
-       getdomainname(domain, sizeof(domain));
+       sa = (struct sockaddr *)&ss;
+       return __ivaliduser_sa(hostf, sa, sa->sa_len, luser, ruser);
+}
+
+/*
+ * Returns 0 if ok, -1 if not ok.
+ */
+int
+__ivaliduser_sa(hostf, raddr, salen, luser, ruser)
+       FILE *hostf;
+       const struct sockaddr *raddr;
+       socklen_t salen;
+       const char *luser, *ruser;
+{
+       register char *user, *p;
+       int ch;
+       char buf[MAXHOSTNAMELEN + 128];         /* host + login */
+       char hname[MAXHOSTNAMELEN];
+       /* Presumed guilty until proven innocent. */
+       int userok = 0, hostok = 0;
+#ifdef YP
+       char *ypdomain;
+
+       if (yp_get_default_domain(&ypdomain))
+               ypdomain = NULL;
+#else
+#define        ypdomain NULL
+#endif
+       /* We need to get the damn hostname back for netgroup matching. */
+       if (getnameinfo(raddr, salen, hname, sizeof(hname), NULL, 0,
+                       NI_NAMEREQD) != 0)
+               return (-1);
 
-       while ((buf = fgetln(hostf, &buflen))) {
+       while (fgets(buf, sizeof(buf), hostf)) {
                p = buf;
-               if (*p == '#')
+               /* Skip lines that are too long. */
+               if (strchr(p, '\n') == NULL) {
+                       while ((ch = getc(hostf)) != '\n' && ch != EOF);
                        continue;
-               while (*p != '\n' && *p != ' ' && *p != '\t' && p < buf + buflen) {
-                       if (!isprint(*p))
-                               goto bail;
-                       *p = isupper(*p) ? tolower(*p) : *p;
-                       p++;
                }
-               if (p >= buf + buflen)
+               if (*p == '\n' || *p == '#') {
+                       /* comment... */
                        continue;
+               }
+               while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
+                       *p = isupper((unsigned char)*p) ? tolower((unsigned char)*p) : *p;
+                       p++;
+               }
                if (*p == ' ' || *p == '\t') {
                        *p++ = '\0';
-                       while (*p == ' ' || *p == '\t' && p < buf + buflen)
+                       while (*p == ' ' || *p == '\t')
                                p++;
-                       if (p >= buf + buflen)
-                               continue;
                        user = p;
                        while (*p != '\n' && *p != ' ' &&
-                           *p != '\t' && p < buf + buflen) {
-                               if (!isprint(*p))
-                                       goto bail;
+                           *p != '\t' && *p != '\0')
                                p++;
-                       }
                } else
                        user = p;
                *p = '\0';
-
-               if (p == buf)
-                       continue;
-
-               auser = *user ? user : luser;
-               ahost = buf;
-
-               if (strlen(ahost) >= MAXHOSTNAMELEN)
-                       continue;
-
                /*
-                * innetgr() must lookup a hostname (we do not attempt
-                * to change the semantics so that netgroups may have
-                * #.#.#.# addresses in the list.)
+                * Do +/- and +@/-@ checking. This looks really nasty,
+                * but it matches SunOS's behavior so far as I can tell.
                 */
-               if (ahost[0] == '+')
-                       switch (ahost[1]) {
-                       case '\0':
+               switch(buf[0]) {
+               case '+':
+                       if (!buf[1]) {     /* '+' matches all hosts */
                                hostok = 1;
                                break;
-                       case '@':
-                               if (rhost == (char *)-1)
-                                       rhost = __gethostloop(raddr);
-                               hostok = 0;
-                               if (rhost)
-                                       hostok = innetgr(&ahost[2], rhost,
-                                           NULL, domain);
-                               break;
-                       default:
-                               hostok = __icheckhost(raddr, &ahost[1]);
-                               break;
                        }
-               else if (ahost[0] == '-')
-                       switch (ahost[1]) {
-                       case '\0':
-                               hostok = -1;
-                               break;
-                       case '@':
-                               if (rhost == (char *)-1)
-                                       rhost = __gethostloop(raddr);
-                               hostok = 0;
-                               if (rhost)
-                                       hostok = -innetgr(&ahost[2], rhost,
-                                           NULL, domain);
-                               break;
-                       default:
-                               hostok = -__icheckhost(raddr, &ahost[1]);
-                               break;
+                       if (buf[1] == '@')  /* match a host by netgroup */
+                               hostok = innetgr((char *)&buf[2],
+                                       (char *)&hname, NULL, ypdomain);
+                       else            /* match a host by addr */
+                               hostok = __icheckhost(raddr, salen,
+                                                     (char *)&buf[1]);
+                       break;
+               case '-':     /* reject '-' hosts and all their users */
+                       if (buf[1] == '@') {
+                               if (innetgr((char *)&buf[2],
+                                             (char *)&hname, NULL, ypdomain))
+                                       return(-1);
+                       } else {
+                               if (__icheckhost(raddr, salen,
+                                                (char *)&buf[1]))
+                                       return(-1);
                        }
-               else
-                       hostok = __icheckhost(raddr, ahost);
-
-
-               if (auser[0] == '+')
-                       switch (auser[1]) {
-                       case '\0':
+                       break;
+               default:  /* if no '+' or '-', do a simple match */
+                       hostok = __icheckhost(raddr, salen, buf);
+                       break;
+               }
+               switch(*user) {
+               case '+':
+                       if (!*(user+1)) {      /* '+' matches all users */
                                userok = 1;
                                break;
-                       case '@':
-                               userok = innetgr(&auser[2], NULL, ruser,
-                                   domain);
-                               break;
-                       default:
-                               userok = strcmp(ruser, &auser[1]) ? 0 : 1;
-                               break;
                        }
-               else if (auser[0] == '-')
-                       switch (auser[1]) {
-                       case '\0':
-                               userok = -1;
-                               break;
-                       case '@':
-                               userok = -innetgr(&auser[2], NULL, ruser,
-                                   domain);
-                               break;
-                       default:
-                               userok = strcmp(ruser, &auser[1]) ? 0 : -1;
-                               break;
+                       if (*(user+1) == '@')  /* match a user by netgroup */
+                               userok = innetgr(user+2, NULL, ruser, ypdomain);
+                       else       /* match a user by direct specification */
+                               userok = !(strcmp(ruser, user+1));
+                       break;
+               case '-':               /* if we matched a hostname, */
+                       if (hostok) {   /* check for user field rejections */
+                               if (!*(user+1))
+                                       return(-1);
+                               if (*(user+1) == '@') {
+                                       if (innetgr(user+2, NULL,
+                                                       ruser, ypdomain))
+                                               return(-1);
+                               } else {
+                                       if (!strcmp(ruser, user+1))
+                                               return(-1);
+                               }
                        }
-               else
-                       userok = strcmp(ruser, auser) ? 0 : 1;
-
-               /* Check if one component did not match */
-               if (hostok == 0 || userok == 0)
-                       continue;
-
-               /* Check if we got a forbidden pair */
-               if (userok <= -1 || hostok <= -1)
-                       return (-1);
-
-               /* Check if we got a valid pair */
-               if (hostok >= 1 && userok >= 1)
-                       return (0);
+                       break;
+               default:        /* no rejections: try to match the user */
+                       if (hostok)
+                               userok = !(strcmp(ruser,*user ? user : luser));
+                       break;
+               }
+               if (hostok && userok)
+                       return(0);
        }
-bail:
        return (-1);
 }
 
 /*
- * Returns "true" if match, 0 if no match.  If we do not find any
- * semblance of an A->PTR->A loop, allow a simple #.#.#.# match to work.
+ * Returns "true" if match, 0 if no match.
+ *
+ * NI_WITHSCOPEID is useful for comparing sin6_scope_id portion
+ * if af == AF_INET6.
  */
 static int
-__icheckhost(raddr, lhost)
-       u_int32_t raddr;
-       const char *lhost;
+__icheckhost(raddr, salen, lhost)
+       const struct sockaddr *raddr;
+       socklen_t salen;
+        const char *lhost;
 {
-       register struct hostent *hp;
-       register char **pp;
-       struct in_addr in;
-
-       hp = gethostbyname(lhost);
-       if (hp != NULL) {
-               /* Spin through ip addresses. */
-               for (pp = hp->h_addr_list; *pp; ++pp)
-                       if (!bcmp(&raddr, *pp, sizeof(raddr)))
-                               return (1);
+       struct sockaddr_in sin;
+       struct sockaddr_in6 *sin6;
+       struct addrinfo hints, *res, *r;
+       int error;
+       char h1[NI_MAXHOST], h2[NI_MAXHOST];
+
+       if (raddr->sa_family == AF_INET6) {
+               sin6 = (struct sockaddr_in6 *)raddr;
+               if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
+                       memset(&sin, 0, sizeof(sin));
+                       sin.sin_family = AF_INET;
+                       sin.sin_len = sizeof(struct sockaddr_in);
+                       memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr[12],
+                              sizeof(sin.sin_addr));
+                       raddr = (struct sockaddr *)&sin;
+                       salen = sin.sin_len;
+               }
        }
 
-       in.s_addr = raddr;
-       if (strcmp(lhost, inet_ntoa(in)) == 0)
-               return (1);
-       return (0);
-}
-
-/*
- * Return the hostname associated with the supplied address.
- * Do a reverse lookup as well for security. If a loop cannot
- * be found, pack the result of inet_ntoa() into the string.
- */
-static char *
-__gethostloop(raddr)
-       u_int32_t raddr;
-{
-       static char remotehost[MAXHOSTNAMELEN];
-       struct hostent *hp;
-       struct in_addr in;
-
-       hp = gethostbyaddr((char *) &raddr, sizeof(raddr), AF_INET);
-       if (hp == NULL)
-               return (NULL);
-
-       /*
-        * Look up the name and check that the supplied
-        * address is in the list
-        */
-       strncpy(remotehost, hp->h_name, sizeof(remotehost) - 1);
-       remotehost[sizeof(remotehost) - 1] = '\0';
-       hp = gethostbyname(remotehost);
-       if (hp == NULL)
-               return (NULL);
-
-       for (; hp->h_addr_list[0] != NULL; hp->h_addr_list++)
-               if (!bcmp(hp->h_addr_list[0], (caddr_t)&raddr, sizeof(raddr)))
-                       return (remotehost);
+       h1[0] = '\0';
+       if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0,
+                       NI_NUMERICHOST | NI_WITHSCOPEID) != 0)
+               return (0);
+
+       /* Resolve laddr into sockaddr */
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = raddr->sa_family;
+       hints.ai_socktype = SOCK_DGRAM; /*XXX dummy*/
+       res = NULL;
+       error = getaddrinfo(lhost, "0", &hints, &res);
+       if (error)
+               return (0);
+
+       for (r = res; r ; r = r->ai_next) {
+               h2[0] = '\0';
+               if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
+                               NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID) != 0)
+                       continue;
+               if (strcmp(h1, h2) == 0) {
+                       freeaddrinfo(res);
+                       return (1);
+               }
+       }
 
-       /*
-        * either the DNS adminstrator has made a configuration
-        * mistake, or someone has attempted to spoof us
-        */
-       in.s_addr = raddr;
-       syslog(LOG_NOTICE, "rcmd: address %s not listed for host %s",
-           inet_ntoa(in), hp->h_name);
-       return (NULL);
+       /* No match. */
+       freeaddrinfo(res);
+       return (0);
 }
index 49f9eee1351039db420657c57a483cc9ae15f503..988e6142b6f96d79499f92d5133040f58f67c403 100644 (file)
@@ -140,7 +140,6 @@ rcmdsh(ahost, rport, locuser, remuser, cmd, rshprog)
                (void) close(sp[1]);
                /* Reap child. */
                (void) wait(NULL);
-               return(sp[0]);
        }
-       /* NOTREACHED */
+       return(sp[0]);
 }