From 3b7c7bd7aae68ec949fb3f4ef1d58b96033e40df Mon Sep 17 00:00:00 2001 From: Apple Date: Sat, 27 Jul 2002 18:24:28 +0000 Subject: [PATCH] Libinfo-129.tar.gz --- Makefile | 4 +- PB.project | 7 +- dns.subproj/gethnamaddr.c | 61 +- dns.subproj/getnetbyaddr.c | 4 +- dns.subproj/getnetbyname.c | 4 +- dns.subproj/getnetent.c | 11 +- dns.subproj/getnetnamadr.c | 13 +- dns.subproj/herror.c | 4 +- dns.subproj/inet.h | 5 +- dns.subproj/res_comp.c | 6 +- dns.subproj/res_debug.c | 10 +- dns.subproj/res_init.c | 10 +- gen.subproj/Makefile | 24 +- gen.subproj/Makefile.postamble | 165 +++ gen.subproj/Makefile.preamble | 2 + gen.subproj/PB.project | 40 +- gen.subproj/fstab.c | 25 +- gen.subproj/getaddrinfo.3 | 612 +++++++++++ gen.subproj/getaddrinfo.c | 289 +++-- gen.subproj/getgrent.c | 7 +- gen.subproj/gethostbyname.3 | 318 ++++++ gen.subproj/getifaddrs.3 | 164 +++ gen.subproj/getifaddrs.c | 382 +++++++ gen.subproj/getipnodebyname.3 | 460 ++++++++ gen.subproj/getnameinfo.3 | 311 ++++++ gen.subproj/getnameinfo.c | 384 +++++++ gen.subproj/getnetent.3 | 162 +++ gen.subproj/getproto.c | 2 +- gen.subproj/getprotoent.3 | 149 +++ gen.subproj/getprotoent.c | 8 +- gen.subproj/getprotoname.c | 2 +- gen.subproj/getservbyname.c | 2 +- gen.subproj/getservbyport.c | 2 +- gen.subproj/getservent.3 | 158 +++ gen.subproj/getservent.c | 8 +- gen.subproj/if_indextoname.3 | 142 +++ gen.subproj/if_indextoname.c | 85 ++ gen.subproj/if_nameindex.c | 146 +++ gen.subproj/if_nametoindex.c | 80 ++ gen.subproj/ifaddrs.h | 56 + gen.subproj/inet6_option_space.3 | 445 ++++++++ gen.subproj/inet6_rthdr_space.3 | 323 ++++++ gen.subproj/inet_ntop.c | 82 ++ gen.subproj/inet_pton.c | 252 +++++ gen.subproj/initgroups.c | 2 + gen.subproj/ip6opt.c | 386 +++++++ gen.subproj/linkaddr.3 | 140 +++ dns.subproj/inet.h => gen.subproj/map_v4v6.c | 119 ++- gen.subproj/printerdb.c | 4 +- gen.subproj/rthdr.c | 310 ++++++ gen.subproj/vars.c | 43 + lookup.subproj/Makefile | 4 +- lookup.subproj/Makefile.postamble | 6 + lookup.subproj/Makefile.preamble | 7 +- lookup.subproj/PB.project | 3 + lookup.subproj/lookup.defs | 53 +- lookup.subproj/lu_alias.c | 364 +++++-- lookup.subproj/lu_bootp.c | 232 +++- lookup.subproj/lu_bootparam.c | 299 ++++-- lookup.subproj/lu_fstab.c | 422 +++++--- lookup.subproj/lu_group.c | 608 ++++++++--- lookup.subproj/lu_host.c | 1062 ++++++++++++++++--- .../sys_interfaces.h => lookup.subproj/lu_host.h | 62 +- lookup.subproj/lu_host_async.c | 1054 +++++++++++++++++++ lookup.subproj/lu_netgroup.c | 262 +++-- lookup.subproj/lu_network.c | 444 +++++--- lookup.subproj/lu_printer.c | 395 +++++-- lookup.subproj/lu_protocol.c | 412 ++++++-- lookup.subproj/lu_rpc.c | 413 ++++++-- lookup.subproj/lu_service.c | 464 +++++--- lookup.subproj/lu_user.c | 1108 +++++++++++++------- lookup.subproj/lu_utils.c | 411 +++++++- lookup.subproj/lu_utils.h | 131 +-- lookup.subproj/netdb_async.h | 257 +++++ mdns.subproj/DNSServiceDiscovery.c | 658 ++++++++++++ mdns.subproj/DNSServiceDiscovery.h | 287 +++++ mdns.subproj/DNSServiceDiscoveryDefines.h | 36 + mdns.subproj/DNSServiceDiscoveryReply.defs | 66 ++ mdns.subproj/DNSServiceDiscoveryRequest.defs | 85 ++ {netinfo.subproj => mdns.subproj}/Makefile | 16 +- mdns.subproj/Makefile.postamble | 106 ++ mdns.subproj/Makefile.preamble | 153 +++ {gen.subproj => mdns.subproj}/PB.project | 35 +- netinfo.subproj/Makefile | 2 +- netinfo.subproj/Makefile.postamble | 9 + netinfo.subproj/Makefile.preamble | 1 + netinfo.subproj/PB.project | 10 +- netinfo.subproj/netinfo.3 | 425 ++++++++ netinfo.subproj/netinfo.5 | 278 +++++ netinfo.subproj/ni_glue.c | 281 ++--- netinfo.subproj/ni_util.c | 34 +- netinfo.subproj/sys_interfaces.c | 66 +- netinfo.subproj/sys_interfaces.h | 7 +- nis.subproj/Makefile | 5 +- nis.subproj/Makefile.preamble | 1 + nis.subproj/PB.project | 18 +- nis.subproj/innetgr.c | 4 +- nis.subproj/yp_all.3 | 1 + nis.subproj/yp_bind.3 | 1 + nis.subproj/yp_first.3 | 1 + nis.subproj/yp_get_default_domain.3 | 1 + nis.subproj/yp_master.3 | 1 + nis.subproj/yp_match.3 | 1 + nis.subproj/yp_next.3 | 1 + nis.subproj/yp_order.3 | 1 + nis.subproj/yp_unbind.3 | 1 + nis.subproj/ypclnt.3 | 342 ++++++ nis.subproj/yperr_string.3 | 1 + nis.subproj/yppasswdd_xdr.c | 2 +- nis.subproj/ypprot_err.3 | 1 + nis.subproj/ypserv.acl.5 | 177 ++++ rpc.subproj/auth_none.c | 7 +- rpc.subproj/auth_unix.c | 15 +- rpc.subproj/authunix_prot.c | 4 +- rpc.subproj/bindresvport.c | 111 +- rpc.subproj/clnt_generic.c | 3 +- rpc.subproj/clnt_perror.c | 4 +- rpc.subproj/clnt_raw.c | 6 +- rpc.subproj/clnt_simple.c | 4 +- rpc.subproj/clnt_tcp.c | 24 +- rpc.subproj/clnt_udp.c | 27 +- rpc.subproj/get_myaddress.c | 3 +- rpc.subproj/getrpcent.c | 9 +- rpc.subproj/getrpcport.c | 5 +- rpc.subproj/pmap_clnt.c | 3 +- rpc.subproj/pmap_getmaps.c | 3 +- rpc.subproj/pmap_getport.c | 3 +- rpc.subproj/pmap_prot2.c | 4 +- rpc.subproj/pmap_rmt.c | 22 +- rpc.subproj/rpc_callmsg.c | 6 +- rpc.subproj/rpc_commondata.c | 4 +- rpc.subproj/rpc_dtablesize.c | 4 +- rpc.subproj/svc.c | 6 +- rpc.subproj/svc_auth.c | 8 +- rpc.subproj/svc_auth_unix.c | 3 +- rpc.subproj/svc_raw.c | 3 +- rpc.subproj/svc_run.c | 6 +- rpc.subproj/svc_simple.c | 8 +- rpc.subproj/svc_tcp.c | 25 +- rpc.subproj/svc_udp.c | 9 +- rpc.subproj/types.h | 4 +- rpc.subproj/xdr.c | 6 +- rpc.subproj/xdr_array.c | 3 +- rpc.subproj/xdr_mem.c | 3 +- rpc.subproj/xdr_rec.c | 4 +- rpc.subproj/xdr_reference.c | 4 +- util.subproj/Makefile | 2 +- util.subproj/Makefile.postamble | 119 +++ util.subproj/Makefile.preamble | 3 + util.subproj/PB.project | 2 +- util.subproj/getgrouplist.c | 3 +- util.subproj/pwcache.c | 47 +- util.subproj/rcmd.3 | 298 ++++++ util.subproj/rcmd.c | 716 ++++++++----- util.subproj/rcmdsh.c | 3 +- 155 files changed, 16891 insertions(+), 2683 deletions(-) create mode 100644 gen.subproj/Makefile.postamble create mode 100644 gen.subproj/getaddrinfo.3 create mode 100644 gen.subproj/gethostbyname.3 create mode 100644 gen.subproj/getifaddrs.3 create mode 100644 gen.subproj/getifaddrs.c create mode 100644 gen.subproj/getipnodebyname.3 create mode 100644 gen.subproj/getnameinfo.3 create mode 100644 gen.subproj/getnameinfo.c create mode 100644 gen.subproj/getnetent.3 create mode 100644 gen.subproj/getprotoent.3 create mode 100644 gen.subproj/getservent.3 create mode 100644 gen.subproj/if_indextoname.3 create mode 100644 gen.subproj/if_indextoname.c create mode 100644 gen.subproj/if_nameindex.c create mode 100644 gen.subproj/if_nametoindex.c create mode 100644 gen.subproj/ifaddrs.h create mode 100644 gen.subproj/inet6_option_space.3 create mode 100644 gen.subproj/inet6_rthdr_space.3 create mode 100644 gen.subproj/inet_ntop.c create mode 100644 gen.subproj/inet_pton.c create mode 100644 gen.subproj/ip6opt.c create mode 100644 gen.subproj/linkaddr.3 copy dns.subproj/inet.h => gen.subproj/map_v4v6.c (60%) create mode 100644 gen.subproj/rthdr.c create mode 100644 gen.subproj/vars.c copy netinfo.subproj/sys_interfaces.h => lookup.subproj/lu_host.h (53%) create mode 100644 lookup.subproj/lu_host_async.c rewrite lookup.subproj/lu_user.c (65%) create mode 100644 lookup.subproj/netdb_async.h create mode 100644 mdns.subproj/DNSServiceDiscovery.c create mode 100644 mdns.subproj/DNSServiceDiscovery.h create mode 100644 mdns.subproj/DNSServiceDiscoveryDefines.h create mode 100644 mdns.subproj/DNSServiceDiscoveryReply.defs create mode 100644 mdns.subproj/DNSServiceDiscoveryRequest.defs copy {netinfo.subproj => mdns.subproj}/Makefile (69%) create mode 100644 mdns.subproj/Makefile.postamble create mode 100644 mdns.subproj/Makefile.preamble copy {gen.subproj => mdns.subproj}/PB.project (50%) create mode 100644 netinfo.subproj/netinfo.3 create mode 100644 netinfo.subproj/netinfo.5 create mode 100644 nis.subproj/yp_all.3 create mode 100644 nis.subproj/yp_bind.3 create mode 100644 nis.subproj/yp_first.3 create mode 100644 nis.subproj/yp_get_default_domain.3 create mode 100644 nis.subproj/yp_master.3 create mode 100644 nis.subproj/yp_match.3 create mode 100644 nis.subproj/yp_next.3 create mode 100644 nis.subproj/yp_order.3 create mode 100644 nis.subproj/yp_unbind.3 create mode 100644 nis.subproj/ypclnt.3 create mode 100644 nis.subproj/yperr_string.3 create mode 100644 nis.subproj/ypprot_err.3 create mode 100644 nis.subproj/ypserv.acl.5 create mode 100644 util.subproj/Makefile.postamble create mode 100644 util.subproj/Makefile.preamble create mode 100644 util.subproj/rcmd.3 diff --git a/Makefile b/Makefile index 5784600..cbb3bca 100644 --- 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 diff --git a/PB.project b/PB.project index 5ebc657..bda4330 100644 --- a/PB.project +++ b/PB.project @@ -13,16 +13,17 @@ 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"; diff --git a/dns.subproj/gethnamaddr.c b/dns.subproj/gethnamaddr.c index 1d6aba5..250a3c4 100644 --- a/dns.subproj/gethnamaddr.c +++ b/dns.subproj/gethnamaddr.c @@ -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 @@ -88,6 +88,7 @@ static char rcsid[] = "$Id: gethnamaddr.c,v 1.2 1999/10/14 21:56:44 wsanchez Exp #include #include +#include #include #include #include @@ -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(); diff --git a/dns.subproj/getnetbyaddr.c b/dns.subproj/getnetbyaddr.c index 415aa1b..9406809 100644 --- a/dns.subproj/getnetbyaddr.c +++ b/dns.subproj/getnetbyaddr.c @@ -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 @@ -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) diff --git a/dns.subproj/getnetbyname.c b/dns.subproj/getnetbyname.c index fe5ac4d..24cf4a6 100644 --- a/dns.subproj/getnetbyname.c +++ b/dns.subproj/getnetbyname.c @@ -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 @@ -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++) diff --git a/dns.subproj/getnetent.c b/dns.subproj/getnetent.c index 00f9d6e..9240a1b 100644 --- a/dns.subproj/getnetent.c +++ b/dns.subproj/getnetent.c @@ -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 @@ -76,6 +76,7 @@ static char rcsid[] = "$Id: getnetent.c,v 1.2 1999/10/14 21:56:44 wsanchez Exp $ #include #include +#include #include #include #include @@ -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) diff --git a/dns.subproj/getnetnamadr.c b/dns.subproj/getnetnamadr.c index f3d3265..40bc224 100644 --- a/dns.subproj/getnetnamadr.c +++ b/dns.subproj/getnetnamadr.c @@ -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 @@ -74,6 +74,7 @@ static char rcsid[] = "$Id: getnetnamadr.c,v 1.2 1999/10/14 21:56:44 wsanchez Ex #include #include +#include #include #include #include @@ -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) diff --git a/dns.subproj/herror.c b/dns.subproj/herror.c index dcfe656..580f847 100644 --- a/dns.subproj/herror.c +++ b/dns.subproj/herror.c @@ -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 @@ -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"); } diff --git a/dns.subproj/inet.h b/dns.subproj/inet.h index ae203b2..c07ca4f 100644 --- a/dns.subproj/inet.h +++ b/dns.subproj/inet.h @@ -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)); diff --git a/dns.subproj/res_comp.c b/dns.subproj/res_comp.c index 7c07818..805630d 100644 --- a/dns.subproj/res_comp.c +++ b/dns.subproj/res_comp.c @@ -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 @@ -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 */ diff --git a/dns.subproj/res_debug.c b/dns.subproj/res_debug.c index 519104a..656797d 100644 --- a/dns.subproj/res_debug.c +++ b/dns.subproj/res_debug.c @@ -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 @@ -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); diff --git a/dns.subproj/res_init.c b/dns.subproj/res_init.c index 5eb64dd..f9e8ad2 100644 --- a/dns.subproj/res_init.c +++ b/dns.subproj/res_init.c @@ -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 @@ -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 # 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; diff --git a/gen.subproj/Makefile b/gen.subproj/Makefile index 3e59457..e05996d 100644 --- a/gen.subproj/Makefile +++ b/gen.subproj/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. # @@ -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 index 0000000..cc40951 --- /dev/null +++ b/gen.subproj/Makefile.postamble @@ -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" diff --git a/gen.subproj/Makefile.preamble b/gen.subproj/Makefile.preamble index 8bcebdc..97b5bb5 100644 --- a/gen.subproj/Makefile.preamble +++ b/gen.subproj/Makefile.preamble @@ -1,4 +1,6 @@ +AFTER_POSTINSTALL += install-man-page OTHER_CFLAGS = \ + -DINET6=1 \ -Dsetservent=_old_setservent \ -Dgetservent=_old_getservent \ -Dendservent=_old_endservent \ diff --git a/gen.subproj/PB.project b/gen.subproj/PB.project index 5e70c18..19a7616 100644 --- a/gen.subproj/PB.project +++ b/gen.subproj/PB.project @@ -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, @@ -15,16 +17,46 @@ 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"; diff --git a/gen.subproj/fstab.c b/gen.subproj/fstab.c index 09a2f7b..5d8d78c 100644 --- a/gen.subproj/fstab.c +++ b/gen.subproj/fstab.c @@ -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 index 0000000..c51fcac --- /dev/null +++ b/gen.subproj/getaddrinfo.3 @@ -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 +.Fd #include +.Fd #include +.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. diff --git a/gen.subproj/getaddrinfo.c b/gen.subproj/getaddrinfo.c index 0d105ea..ab0fa14 100644 --- a/gen.subproj/getaddrinfo.c +++ b/gen.subproj/getaddrinfo.c @@ -39,15 +39,23 @@ #include #include #include +#include +#include +#include #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; } + diff --git a/gen.subproj/getgrent.c b/gen.subproj/getgrent.c index e9552d4..36a01d2 100644 --- a/gen.subproj/getgrent.c +++ b/gen.subproj/getgrent.c @@ -61,6 +61,7 @@ static char sccsid[] = "@(#)getgrent.c 8.2 (Berkeley) 3/21/94"; #include #include #include +#include #include 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 index 0000000..8f23b28 --- /dev/null +++ b/gen.subproj/gethostbyname.3 @@ -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 +.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 index 0000000..7409e90 --- /dev/null +++ b/gen.subproj/getifaddrs.3 @@ -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 +.Fd #include +.Fd #include +.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 index 0000000..9522032 --- /dev/null +++ b/gen.subproj/getifaddrs.c @@ -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 +#include +#include +#include +#ifdef NET_RT_IFLIST +#include +#include +#include +#include +#endif + +#include +#include +#include +#include + +#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 index 0000000..7d52521 --- /dev/null +++ b/gen.subproj/getipnodebyname.3 @@ -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 +.Fd #include +.Fd #include +.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 index 0000000..ce36d8a --- /dev/null +++ b/gen.subproj/getnameinfo.3 @@ -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 +.Fd #include +.Fd #include +.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 index 0000000..2f71a73 --- /dev/null +++ b/gen.subproj/getnameinfo.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + */ + 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 index 0000000..d53c5c9 --- /dev/null +++ b/gen.subproj/getnetent.3 @@ -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 +.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. diff --git a/gen.subproj/getproto.c b/gen.subproj/getproto.c index 0c3634e..1f09b7c 100644 --- a/gen.subproj/getproto.c +++ b/gen.subproj/getproto.c @@ -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 index 0000000..e0fd91c --- /dev/null +++ b/gen.subproj/getprotoent.3 @@ -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 +.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. diff --git a/gen.subproj/getprotoent.c b/gen.subproj/getprotoent.c index 0320109..ed158c9 100644 --- a/gen.subproj/getprotoent.c +++ b/gen.subproj/getprotoent.c @@ -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); diff --git a/gen.subproj/getprotoname.c b/gen.subproj/getprotoname.c index 49551e1..0e4b7f3 100644 --- a/gen.subproj/getprotoname.c +++ b/gen.subproj/getprotoname.c @@ -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++) diff --git a/gen.subproj/getservbyname.c b/gen.subproj/getservbyname.c index 45766e3..6139e9e 100644 --- a/gen.subproj/getservbyname.c +++ b/gen.subproj/getservbyname.c @@ -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++) diff --git a/gen.subproj/getservbyport.c b/gen.subproj/getservbyport.c index af3eeb0..4af1e10 100644 --- a/gen.subproj/getservbyport.c +++ b/gen.subproj/getservbyport.c @@ -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 index 0000000..bcf5c23 --- /dev/null +++ b/gen.subproj/getservent.3 @@ -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 +.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. diff --git a/gen.subproj/getservent.c b/gen.subproj/getservent.c index 16d5cd9..134fb71 100644 --- a/gen.subproj/getservent.c +++ b/gen.subproj/getservent.c @@ -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 index 0000000..9327c12 --- /dev/null +++ b/gen.subproj/if_indextoname.3 @@ -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 +.Fd #include +.Fd #include +.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 index 0000000..e0e75a3 --- /dev/null +++ b/gen.subproj/if_indextoname.c @@ -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 +#include +#include +#include +#include +#include +#include +#include + +/* + * From RFC 2533: + * + * The second function maps an interface index into its corresponding + * name. + * + * #include + * + * 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 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 index 0000000..eb91584 --- /dev/null +++ b/gen.subproj/if_nameindex.c @@ -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 +#include +#include +#include +#include +#include +#include + +/* + * 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 + * 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 + * + * 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 index 0000000..e1af130 --- /dev/null +++ b/gen.subproj/if_nametoindex.c @@ -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 +#include +#include +#include +#include +#include +#include +#include + +/* + * From RFC 2553: + * + * 4.1 Name-to-Index + * + * + * The first function maps an interface name into its corresponding + * index. + * + * #include + * + * 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 index 0000000..cf32dae --- /dev/null +++ b/gen.subproj/ifaddrs.h @@ -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 . Note that if 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 + +__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 index 0000000..c5b6cc9 --- /dev/null +++ b/gen.subproj/inet6_option_space.3 @@ -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 +.Fd #include +.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 index 0000000..3ca3581 --- /dev/null +++ b/gen.subproj/inet6_rthdr_space.3 @@ -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 +.Fd #include +.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 index 0000000..99bc6c7 --- /dev/null +++ b/gen.subproj/inet_ntop.c @@ -0,0 +1,82 @@ + +#include +#include +#include +#include +#include + +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 index 0000000..7858ba8 --- /dev/null +++ b/gen.subproj/inet_pton.c @@ -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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#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*/ diff --git a/gen.subproj/initgroups.c b/gen.subproj/initgroups.c index 455c363..cf7fabf 100644 --- a/gen.subproj/initgroups.c +++ b/gen.subproj/initgroups.c @@ -61,6 +61,8 @@ static char sccsid[] = "@(#)initgroups.c 8.1 (Berkeley) 6/4/93"; #include #include +#include +#include int initgroups(uname, agroup) diff --git a/gen.subproj/ip6opt.c b/gen.subproj/ip6opt.c new file mode 100644 index 0000000..c8805d1 --- /dev/null +++ b/gen.subproj/ip6opt.c @@ -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 +#include +#include + +#include +#include + +#include +#include + +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 index 0000000..4c74a84 --- /dev/null +++ b/gen.subproj/linkaddr.3 @@ -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 +.Fd #include +.Fd #include +.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/dns.subproj/inet.h b/gen.subproj/map_v4v6.c similarity index 60% copy from dns.subproj/inet.h copy to gen.subproj/map_v4v6.c index ae203b2..2ed171c 100644 --- a/dns.subproj/inet.h +++ b/gen.subproj/map_v4v6.c @@ -1,30 +1,7 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 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@ - */ -/* - * ++Copyright++ 1983, 1993 + * ++Copyright++ 1985, 1988, 1993 * - - * Copyright (c) 1983, 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 @@ -76,36 +53,76 @@ * --Copyright-- */ -/* - * @(#)inet.h 8.1 (Berkeley) 6/2/93 - * $Id: inet.h,v 1.2 1999/10/14 21:56:45 wsanchez Exp $ - */ +#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 */ -#ifndef _INET_H_ -#define _INET_H_ +#include +#include +#include +#include +#include +#include -/* External definitions for functions in inet(3) */ +#include +#include +#include +#include +#include +#include -#include -#if (!defined(BSD)) || (BSD < 199306) -# include -#else -# include -#endif -#include +#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; -__BEGIN_DECLS -unsigned long inet_addr __P((const char *)); -int inet_aton __P((const char *, struct in_addr *)); -unsigned long inet_lnaof __P((struct in_addr)); -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)); + /* 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); +} -u_int inet_nsap_addr __P((const char *, u_char *, int maxlen)); -char *inet_nsap_ntoa __P((int, const u_char *, char *ascii)); +void +_map_v4v6_hostent(hp, bpp, lenp) + struct hostent *hp; + char **bpp; + int *lenp; +{ + char **ap; -__END_DECLS + 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)); -#endif /* !_INET_H_ */ + 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; + } +} diff --git a/gen.subproj/printerdb.c b/gen.subproj/printerdb.c index 2d77bdf..c1ec9fe 100644 --- a/gen.subproj/printerdb.c +++ b/gen.subproj/printerdb.c @@ -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 index 0000000..4f2385e --- /dev/null +++ b/gen.subproj/rthdr.c @@ -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 +#include +#include + +#include +#include + +#include +#include + +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 index 0000000..27e9a45 --- /dev/null +++ b/gen.subproj/vars.c @@ -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 +#include + +/* + * 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; + diff --git a/lookup.subproj/Makefile b/lookup.subproj/Makefile index 2122bc1..7148858 100644 --- a/lookup.subproj/Makefile +++ b/lookup.subproj/Makefile @@ -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\ diff --git a/lookup.subproj/Makefile.postamble b/lookup.subproj/Makefile.postamble index cf76087..447fe32 100644 --- a/lookup.subproj/Makefile.postamble +++ b/lookup.subproj/Makefile.postamble @@ -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) diff --git a/lookup.subproj/Makefile.preamble b/lookup.subproj/Makefile.preamble index 9a094c2..83a0b9c 100644 --- a/lookup.subproj/Makefile.preamble +++ b/lookup.subproj/Makefile.preamble @@ -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 diff --git a/lookup.subproj/PB.project b/lookup.subproj/PB.project index 8270f85..e3a62e0 100644 --- a/lookup.subproj/PB.project +++ b/lookup.subproj/PB.project @@ -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, diff --git a/lookup.subproj/lookup.defs b/lookup.subproj/lookup.defs index 167d609..430e2b4 100644 --- a/lookup.subproj/lookup.defs +++ b/lookup.subproj/lookup.defs @@ -35,9 +35,9 @@ serverprefix _; import ; +#include +#include -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 +); diff --git a/lookup.subproj/lu_alias.c b/lookup.subproj/lu_alias.c index f215067..7d22d91 100644 --- a/lookup.subproj/lu_alias.c +++ b/lookup.subproj/lu_alias.c @@ -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@ * @@ -33,217 +33,401 @@ #include #include #include +#include -#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); + } + + 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(); } diff --git a/lookup.subproj/lu_bootp.c b/lookup.subproj/lu_bootp.c index ca85dbe..d3a9aa9 100644 --- a/lookup.subproj/lu_bootp.c +++ b/lookup.subproj/lu_bootp.c @@ -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@ * @@ -27,59 +27,174 @@ */ #include #include +#include #include -#include "lookup.h" #include #include -#include "_lu_types.h" -#include "lu_utils.h" #include #include #include #include #include +#include + +#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; } diff --git a/lookup.subproj/lu_bootparam.c b/lookup.subproj/lu_bootparam.c index 9386e98..9594b74 100644 --- a/lookup.subproj/lu_bootparam.c +++ b/lookup.subproj/lu_bootparam.c @@ -37,64 +37,152 @@ #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); + } + + 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 diff --git a/lookup.subproj/lu_fstab.c b/lookup.subproj/lu_fstab.c index b206a8a..be1d532 100644 --- a/lookup.subproj/lu_fstab.c +++ b/lookup.subproj/lu_fstab.c @@ -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@ * @@ -33,212 +33,348 @@ #include #include #include +#include #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); } 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); + } + + 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)); -} diff --git a/lookup.subproj/lu_group.c b/lookup.subproj/lu_group.c index 2ec8e03..3a8233b 100644 --- a/lookup.subproj/lu_group.c +++ b/lookup.subproj/lu_group.c @@ -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@ * @@ -37,184 +37,407 @@ #include #include #include +#include #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); + } + + 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 @@ -380,19 +695,46 @@ initgroups(const char *name, int basegid) } 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); } diff --git a/lookup.subproj/lu_host.c b/lookup.subproj/lu_host.c index ca56659..d34da5b 100644 --- a/lookup.subproj/lu_host.c +++ b/lookup.subproj/lu_host.c @@ -21,22 +21,27 @@ * * @APPLE_LICENSE_HEADER_END@ */ -/* - * host lookup - * Copyright (C) 1989 by NeXT, Inc. - */ + #include #include #include #include -#include "lookup.h" #include #include -#include "_lu_types.h" #include -#include "lu_utils.h" #include -#import +#include +#include +#include +#include +#include + +#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); } 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); + } + + 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/netinfo.subproj/sys_interfaces.h b/lookup.subproj/lu_host.h similarity index 53% copy from netinfo.subproj/sys_interfaces.h copy to lookup.subproj/lu_host.h index 154ac5b..130bc4d 100644 --- a/netinfo.subproj/sys_interfaces.h +++ b/lookup.subproj/lu_host.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * 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 @@ -22,34 +22,30 @@ * @APPLE_LICENSE_HEADER_END@ */ -#ifndef __SYS_INTERFACES__ -#define __SYS_INTERFACES__ - -#include -#include -#include -#include -#include - -typedef struct -{ - char name[IFNAMSIZ]; - short flags; - struct in_addr addr; - struct in_addr mask; - struct in_addr netaddr; - struct in_addr bcast; -} interface_t; - -typedef struct -{ - unsigned int count; - interface_t *interface; -} interface_list_t; - -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); - -#endif /* __SYS_INTERFACES__ */ +#ifndef _LU_HOST_H_ +#define _LU_HOST_H_ + +#include + + +#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 index 0000000..2874719 --- /dev/null +++ b/lookup.subproj/lu_host_async.c @@ -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 +#include /* async gethostbyXXX function prototypes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/lookup.subproj/lu_netgroup.c b/lookup.subproj/lu_netgroup.c index 8e52272..5a32b0b 100644 --- a/lookup.subproj/lu_netgroup.c +++ b/lookup.subproj/lu_netgroup.c @@ -38,38 +38,130 @@ #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); + } + 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(); } diff --git a/lookup.subproj/lu_network.c b/lookup.subproj/lu_network.c index 78533f9..e603b9b 100644 --- a/lookup.subproj/lu_network.c +++ b/lookup.subproj/lu_network.c @@ -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@ * @@ -29,14 +29,23 @@ #include #include #include -#include "lookup.h" #include #include -#include "_lu_types.h" #include -#include "lu_utils.h" #include -#import +#include +#include +#include + +#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); } 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); + } + + 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(); } diff --git a/lookup.subproj/lu_printer.c b/lookup.subproj/lu_printer.c index 0290e10..86fd0b7 100644 --- a/lookup.subproj/lu_printer.c +++ b/lookup.subproj/lu_printer.c @@ -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@ * @@ -29,240 +29,433 @@ #include #include #include -#include "lookup.h" #include #include +#include + #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); + } + + 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(); } diff --git a/lookup.subproj/lu_protocol.c b/lookup.subproj/lu_protocol.c index f2c346f..e511863 100644 --- a/lookup.subproj/lu_protocol.c +++ b/lookup.subproj/lu_protocol.c @@ -29,13 +29,14 @@ #include #include #include -#include "lookup.h" #include #include -#include "_lu_types.h" #include +#include + +#include "_lu_types.h" +#include "lookup.h" #include "lu_utils.h" -#import 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); + } + + 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(); } diff --git a/lookup.subproj/lu_rpc.c b/lookup.subproj/lu_rpc.c index 3bd9460..3689087 100644 --- a/lookup.subproj/lu_rpc.c +++ b/lookup.subproj/lu_rpc.c @@ -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@ * @@ -33,269 +33,468 @@ #include #include #include +#include #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); + } + + 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(); } diff --git a/lookup.subproj/lu_service.c b/lookup.subproj/lu_service.c index 4dc60e5..7d73677 100644 --- a/lookup.subproj/lu_service.c +++ b/lookup.subproj/lu_service.c @@ -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@ * @@ -29,13 +29,21 @@ #include #include #include -#include "lookup.h" #include #include -#include "_lu_types.h" #include +#include +#include + +#include "_lu_types.h" +#include "lookup.h" #include "lu_utils.h" -#import + +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); + } + + 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(); } diff --git a/lookup.subproj/lu_user.c b/lookup.subproj/lu_user.c dissimilarity index 65% index ecf36f6..c927670 100644 --- a/lookup.subproj/lu_user.c +++ b/lookup.subproj/lu_user.c @@ -1,380 +1,728 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 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@ - */ -/* - * user information (passwd) lookup - * Copyright (C) 1989 by NeXT, Inc. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#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 void -freeold(void) -{ - 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); - - global_free = 1; -} - -static void -convert_pw(_lu_passwd *lu_pw) -{ - 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; -} - -static struct passwd * -lu_getpwuid(int uid) -{ - unsigned datalen; - _lu_passwd_ptr lu_pw; - XDR xdr; - static int proc = -1; - unit lookup_buf[MAX_INLINE_UNITS]; - - if (proc < 0) - { - if (_lookup_link(_lu_port, "getpwuid_A", &proc) != KERN_SUCCESS) - { - return (NULL); - } - } - - uid = htonl(uid); - datalen = MAX_INLINE_UNITS; - if (_lookup_one(_lu_port, proc, (unit *)&uid, 1, lookup_buf, &datalen) - != KERN_SUCCESS) - { - return (NULL); - } - - 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)) - { - xdr_destroy(&xdr); - return (NULL); - } - - xdr_destroy(&xdr); - - convert_pw(lu_pw); - xdr_free(xdr__lu_passwd_ptr, &lu_pw); - return (&global_pw); -} - -static struct passwd * -lu_getpwnam(const char *name) -{ - unsigned datalen; - char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT]; - XDR outxdr; - XDR inxdr; - _lu_passwd_ptr lu_pw; - static int proc = -1; - unit lookup_buf[MAX_INLINE_UNITS]; - - if (proc < 0) - { - if (_lookup_link(_lu_port, "getpwnam_A", &proc) != KERN_SUCCESS) - { - 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) - != KERN_SUCCESS) - { - xdr_destroy(&outxdr); - 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)) - { - xdr_destroy(&inxdr); - return (NULL); - } - - xdr_destroy(&inxdr); - - convert_pw(lu_pw); - xdr_free(xdr__lu_passwd_ptr, &lu_pw); - return (&global_pw); -} - -#ifdef notdef -static int -lu_putpwpasswd(char *login, char *old_passwd, char *new_passwd) -{ - 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]; - XDR outxdr; - - if (proc < 0) - { - if (_lookup_link(_lu_port, "putpwpasswd", &proc) != KERN_SUCCESS) - { - return (0); - } - } - - 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)) - { - xdr_destroy(&outxdr); - return (0); - } - - datalen = MAX_INLINE_UNITS; - if (_lookup_one(_lu_port, proc, output_buf, - xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, lookup_buf, &datalen) - != KERN_SUCCESS) - { - xdr_destroy(&outxdr); - return (0); - } - - xdr_destroy(&outxdr); - - datalen *= BYTES_PER_XDR_UNIT; - xdrmem_create(&xdr, lookup_buf, datalen, XDR_DECODE); - if (!xdr_int(&xdr, &changed)) - { - xdr_destroy(&xdr); - return (0); - } - - xdr_destroy(&xdr); - - return (changed); -} -#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; - } -} - -static int -lu_setpwent(void) -{ - lu_endpwent(); - pw_start = 1; - return (1); -} - -static struct passwd * -lu_getpwent() -{ - static int proc = -1; - _lu_passwd lu_pw; - - if (pw_start == 1) - { - pw_start = 0; - - if (proc < 0) - { - if (_lookup_link(_lu_port, "getpwent_A", &proc) != KERN_SUCCESS) - { - lu_endpwent(); - return (NULL); - } - } - - if (_lookup_all(_lu_port, proc, NULL, 0, &pw_data, &pw_datalen) - != KERN_SUCCESS) - { - lu_endpwent(); - return (NULL); - } - -#ifdef NOTDEF -/* NOTDEF because OOL buffers are counted in bytes with untyped IPC */ - pw_datalen *= BYTES_PER_XDR_UNIT; -#endif - - xdrmem_create(&pw_xdr, pw_data, pw_datalen, - XDR_DECODE); - if (!xdr_int(&pw_xdr, &pw_nentries)) - { - xdr_destroy(&pw_xdr); - lu_endpwent(); - return (NULL); - } - } - - if (pw_nentries == 0) - { - xdr_destroy(&pw_xdr); - lu_endpwent(); - return (NULL); - } - - bzero(&lu_pw, sizeof(lu_pw)); - if (!xdr__lu_passwd(&pw_xdr, &lu_pw)) - { - xdr_destroy(&pw_xdr); - lu_endpwent(); - return (NULL); - } - - pw_nentries--; - convert_pw(&lu_pw); - xdr_free(xdr__lu_passwd, &lu_pw); - return (&global_pw); -} - -static char *loginName = NULL; -static uid_t loginUid = -1; - -extern char *getlogin(void); - -struct passwd * -getpwuid(uid_t uid) -{ - 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 * -getpwnam(const char *name) -{ - LOOKUP1(lu_getpwnam, _old_getpwnam, name, struct passwd); -} - -#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) -{ - if (_lu_running()) return (lu_putpwpasswd(login, old_passwd, new_passwd)); - return (old_passwd(login, old_passwd, new_passwd)); -} -#endif - -struct passwd * -getpwent(void) -{ - GETENT(lu_getpwent, _old_getpwent, &pw_state, struct passwd); -} - -int -setpwent(void) -{ - INTSETSTATEVOID(lu_setpwent, _old_setpwent, &pw_state); -} - -void -endpwent(void) -{ - UNSETSTATE(lu_endpwent, _old_endpwent, &pw_state); -} +/* + * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999 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@ + */ +/* + * user information (passwd) lookup + * Copyright (C) 1989 by NeXT, Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "_lu_types.h" +#include "lookup.h" +#include "lu_utils.h" +#include "lu_overrides.h" + +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 +free_user_data(struct passwd *p) +{ + 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); +} + +static void +free_user(struct passwd *p) +{ + if (p == NULL) return; + free_user_data(p); + free(p); +} + +static void +free_lu_thread_info_user(void *x) +{ + 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 * +extract_user(XDR *xdr) +{ + 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++) + { + 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))) + { + 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); + } + } + + 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) + { + out->pw_name = bp; + hsize = strlen(in->pw_name) + 1; + memmove(bp, in->pw_name, hsize); + bp += hsize; + } + + out->pw_passwd = NULL; + if (in->pw_passwd != NULL) + { + out->pw_passwd = bp; + hsize = strlen(in->pw_passwd) + 1; + memmove(bp, in->pw_passwd, hsize); + bp += hsize; + } + + out->pw_uid = in->pw_uid; + + 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_getpwuid(int uid) +{ + struct passwd *p; + unsigned int datalen; + XDR inxdr; + static int proc = -1; + int count; + char *lookup_buf; + + if (proc < 0) + { + if (_lookup_link(_lu_port, "getpwuid_A", &proc) != KERN_SUCCESS) + { + return NULL; + } + } + + uid = htonl(uid); + datalen = 0; + lookup_buf = NULL; + + if (_lookup_all(_lu_port, proc, (unit *)&uid, 1, &lookup_buf, &datalen) + != KERN_SUCCESS) + { + return NULL; + } + + datalen *= BYTES_PER_XDR_UNIT; + 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); + 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); + + return p; +} + +static struct passwd * +lu_getpwnam(const char *name) +{ + 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, "getpwnam_A", &proc) != KERN_SUCCESS) + { + return NULL; + } + } + + xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE); + if (!xdr__lu_string(&outxdr, (_lu_string *)&name)) + { + xdr_destroy(&outxdr); + return NULL; + } + + 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; + } + + xdr_destroy(&outxdr); + + datalen *= BYTES_PER_XDR_UNIT; + 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); + 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); + + + return p; +} + +static void +lu_endpwent(void) +{ + 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(); + return 1; +} + +static struct passwd * +lu_getpwent() +{ + struct passwd *p; + static int proc = -1; + 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); + } + + if (tdata->lu_vm == NULL) + { + if (proc < 0) + { + if (_lookup_link(_lu_port, "getpwent_A", &proc) != KERN_SUCCESS) + { + lu_endpwent(); + return NULL; + } + } + + if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS) + { + lu_endpwent(); + 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)); + + 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_endpwent(); + return NULL; + } + } + + if (tdata->lu_vm_cursor == 0) + { + lu_endpwent(); + return NULL; + } + + p = extract_user(tdata->lu_xdr); + if (p == NULL) + { + lu_endpwent(); + return NULL; + } + + tdata->lu_vm_cursor--; + + return p; +} + +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; + + if (loginName == NULL) + { + char *l = getlogin(); + + 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) +{ + 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) +{ + return getpw(name, -2, PW_GET_NAME); +} + +struct passwd * +getpwuid(uid_t uid) +{ + return getpw(NULL, uid, PW_GET_UID); +} + +struct passwd * +getpwent(void) +{ + return getpw(NULL, -2, PW_GET_ENT); +} + +int +setpwent(void) +{ + if (_lu_running()) lu_setpwent(); + else _old_setpwent(); + return 1; +} + +void +endpwent(void) +{ + if (_lu_running()) lu_endpwent(); + else _old_endpwent(); +} + int +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); +} diff --git a/lookup.subproj/lu_utils.c b/lookup.subproj/lu_utils.c index b458b74..5e25864 100644 --- a/lookup.subproj/lu_utils.c +++ b/lookup.subproj/lu_utils.c @@ -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@ * @@ -25,16 +25,31 @@ #include #include #include - +#include +#ifdef DEBUG +#include +#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; +} diff --git a/lookup.subproj/lu_utils.h b/lookup.subproj/lu_utils.h index d1a268c..ae987c0 100644 --- a/lookup.subproj/lu_utils.h +++ b/lookup.subproj/lu_utils.h @@ -26,105 +26,60 @@ * Copyright (C) 1989 by NeXT, Inc. */ +#ifndef _LU_UTILS_H_ +#define _LU_UTILS_H_ + #import #include #include +#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 index 0000000..561bb5f --- /dev/null +++ b/lookup.subproj/netdb_async.h @@ -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 +#include +#include + +__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 index 0000000..0d01e46 --- /dev/null +++ b/mdns.subproj/DNSServiceDiscovery.c @@ -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 +#include +#include +#include +#include +#include + +#include + +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 index 0000000..3cd32f1 --- /dev/null +++ b/mdns.subproj/DNSServiceDiscovery.h @@ -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 + +#include +#include +#include + +#include + +__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 ) + @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 index 0000000..51dffe7 --- /dev/null +++ b/mdns.subproj/DNSServiceDiscoveryDefines.h @@ -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 + +#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 index 0000000..d26c20b --- /dev/null +++ b/mdns.subproj/DNSServiceDiscoveryReply.defs @@ -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 +#include + +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 index 0000000..29495f8 --- /dev/null +++ b/mdns.subproj/DNSServiceDiscoveryRequest.defs @@ -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 +#include + +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/netinfo.subproj/Makefile b/mdns.subproj/Makefile similarity index 69% copy from netinfo.subproj/Makefile copy to mdns.subproj/Makefile index ea95aa2..6b2d9b7 100644 --- a/netinfo.subproj/Makefile +++ b/mdns.subproj/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. # @@ -7,31 +7,31 @@ # and Makefile.postamble (both optional), and Makefile will include them. # -NAME = netinfo +NAME = mdns PROJECTVERSION = 2.8 PROJECT_TYPE = Component -HFILES = clib.h mm.h ni.h ni_util.h sys_interfaces.h +HFILES = DNSServiceDiscoveryDefines.h DNSServiceDiscovery.h -CFILES = multi_call.c ni_error.c ni_glue.c ni_pwdomain.c ni_useful.c\ - ni_util.c sys_interfaces.c +CFILES = DNSServiceDiscovery.c -OTHERSRCS = Makefile.preamble Makefile Makefile.postamble nibind_prot.x\ - ni_prot.x +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) -PUBLIC_HEADERS = ni.h ni_util.h nibind_prot.x ni_prot.x +NEXTSTEP_PUBLIC_HEADERS_DIR = /usr/include NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc diff --git a/mdns.subproj/Makefile.postamble b/mdns.subproj/Makefile.postamble new file mode 100644 index 0000000..b00b2ab --- /dev/null +++ b/mdns.subproj/Makefile.postamble @@ -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 index 0000000..2a9ecd4 --- /dev/null +++ b/mdns.subproj/Makefile.preamble @@ -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: <> +# 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/gen.subproj/PB.project b/mdns.subproj/PB.project similarity index 50% copy from gen.subproj/PB.project copy to mdns.subproj/PB.project index 5e70c18..eec7d5c 100644 --- a/gen.subproj/PB.project +++ b/mdns.subproj/PB.project @@ -1,34 +1,31 @@ { DYNAMIC_CODE_GEN = YES; + English_RESOURCES = {}; FILESTABLE = { - H_FILES = (); - OTHER_LINKED = ( - 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 + H_FILES = (DNSServiceDiscoveryDefines.h, DNSServiceDiscovery.h); + OTHER_LINKED = (DNSServiceDiscovery.c); + OTHER_RESOURCES = (); + OTHER_SOURCES = ( + Makefile.preamble, + Makefile, + Makefile.postamble, + DNSServiceDiscoveryReply.defs, + DNSServiceDiscoveryRequest.defs ); - OTHER_SOURCES = (Makefile.preamble, Makefile); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); }; 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"; - PROJECTNAME = gen; + PROJECTNAME = mdns; PROJECTTYPE = Component; PROJECTVERSION = 2.8; WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; diff --git a/netinfo.subproj/Makefile b/netinfo.subproj/Makefile index ea95aa2..4861159 100644 --- a/netinfo.subproj/Makefile +++ b/netinfo.subproj/Makefile @@ -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 diff --git a/netinfo.subproj/Makefile.postamble b/netinfo.subproj/Makefile.postamble index 8361d56..d8a74f5 100644 --- a/netinfo.subproj/Makefile.postamble +++ b/netinfo.subproj/Makefile.postamble @@ -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 diff --git a/netinfo.subproj/Makefile.preamble b/netinfo.subproj/Makefile.preamble index 77e442b..680d1b6 100644 --- a/netinfo.subproj/Makefile.preamble +++ b/netinfo.subproj/Makefile.preamble @@ -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 diff --git a/netinfo.subproj/PB.project b/netinfo.subproj/PB.project index 789dee7..3635900 100644 --- a/netinfo.subproj/PB.project +++ b/netinfo.subproj/PB.project @@ -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 index 0000000..50486b7 --- /dev/null +++ b/netinfo.subproj/netinfo.3 @@ -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 \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 index 0000000..aea5803 --- /dev/null +++ b/netinfo.subproj/netinfo.5 @@ -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) diff --git a/netinfo.subproj/ni_glue.c b/netinfo.subproj/ni_glue.c index b6129bc..7ec53c9 100644 --- a/netinfo.subproj/ni_glue.c +++ b/netinfo.subproj/ni_glue.c @@ -26,6 +26,7 @@ * Copyright (C) 1989 by NeXT, Inc. */ #include +#include #include #include #include @@ -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; iaddrs[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; } diff --git a/netinfo.subproj/ni_util.c b/netinfo.subproj/ni_util.c index 1f881e9..e99f78c 100644 --- a/netinfo.subproj/ni_util.c +++ b/netinfo.subproj/ni_util.c @@ -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; diff --git a/netinfo.subproj/sys_interfaces.c b/netinfo.subproj/sys_interfaces.c index d04f3e0..682da1a 100644 --- a/netinfo.subproj/sys_interfaces.c +++ b/netinfo.subproj/sys_interfaces.c @@ -25,55 +25,27 @@ #include #include #include +#include #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); } diff --git a/netinfo.subproj/sys_interfaces.h b/netinfo.subproj/sys_interfaces.h index 154ac5b..03d4d52 100644 --- a/netinfo.subproj/sys_interfaces.h +++ b/netinfo.subproj/sys_interfaces.h @@ -26,14 +26,13 @@ #define __SYS_INTERFACES__ #include +#include #include -#include #include -#include 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); diff --git a/nis.subproj/Makefile b/nis.subproj/Makefile index fd7babb..05745d4 100644 --- a/nis.subproj/Makefile +++ b/nis.subproj/Makefile @@ -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 diff --git a/nis.subproj/Makefile.preamble b/nis.subproj/Makefile.preamble index eb86120..5001fae 100644 --- a/nis.subproj/Makefile.preamble +++ b/nis.subproj/Makefile.preamble @@ -1 +1,2 @@ +AFTER_POSTINSTALL += install-nis-man PUBLIC_HEADER_DIR_SUFFIX = /rpcsvc diff --git a/nis.subproj/PB.project b/nis.subproj/PB.project index 6d2b72e..ecec27f 100644 --- a/nis.subproj/PB.project +++ b/nis.subproj/PB.project @@ -38,7 +38,23 @@ 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; diff --git a/nis.subproj/innetgr.c b/nis.subproj/innetgr.c index d146233..6553520 100644 --- a/nis.subproj/innetgr.c +++ b/nis.subproj/innetgr.c @@ -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 index 0000000..ee71c09 --- /dev/null +++ b/nis.subproj/yp_all.3 @@ -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 index 0000000..ee71c09 --- /dev/null +++ b/nis.subproj/yp_bind.3 @@ -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 index 0000000..ee71c09 --- /dev/null +++ b/nis.subproj/yp_first.3 @@ -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 index 0000000..ee71c09 --- /dev/null +++ b/nis.subproj/yp_get_default_domain.3 @@ -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 index 0000000..ee71c09 --- /dev/null +++ b/nis.subproj/yp_master.3 @@ -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 index 0000000..ee71c09 --- /dev/null +++ b/nis.subproj/yp_match.3 @@ -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 index 0000000..ee71c09 --- /dev/null +++ b/nis.subproj/yp_next.3 @@ -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 index 0000000..ee71c09 --- /dev/null +++ b/nis.subproj/yp_order.3 @@ -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 index 0000000..ee71c09 --- /dev/null +++ b/nis.subproj/yp_unbind.3 @@ -0,0 +1 @@ +.so man3/ypclnt.3 diff --git a/nis.subproj/ypclnt.3 b/nis.subproj/ypclnt.3 new file mode 100644 index 0000000..6f1651f --- /dev/null +++ b/nis.subproj/ypclnt.3 @@ -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 +.Fd #include +.Fd #include +.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 : +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 . +.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 index 0000000..ee71c09 --- /dev/null +++ b/nis.subproj/yperr_string.3 @@ -0,0 +1 @@ +.so man3/ypclnt.3 diff --git a/nis.subproj/yppasswdd_xdr.c b/nis.subproj/yppasswdd_xdr.c index d285182..2d3fe2f 100644 --- a/nis.subproj/yppasswdd_xdr.c +++ b/nis.subproj/yppasswdd_xdr.c @@ -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 index 0000000..ee71c09 --- /dev/null +++ b/nis.subproj/ypprot_err.3 @@ -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 index 0000000..000824a --- /dev/null +++ b/nis.subproj/ypserv.acl.5 @@ -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 +.\" 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 +.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 +# deny host +# +# 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 [netmask ] +# deny net [netmask ] +# +# 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 + diff --git a/rpc.subproj/auth_none.c b/rpc.subproj/auth_none.c index 220a8ca..e2901a0 100644 --- a/rpc.subproj/auth_none.c +++ b/rpc.subproj/auth_none.c @@ -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 +#include +#include #include #include #include #define MAX_MARSHEL_SIZE 20 +extern bool_t xdr_opaque_auth(); + /* * Authenticator operations routines */ diff --git a/rpc.subproj/auth_unix.c b/rpc.subproj/auth_unix.c index 448654d..f2902c1 100644 --- a/rpc.subproj/auth_unix.c +++ b/rpc.subproj/auth_unix.c @@ -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 #include +#include +#include #include +#include +#include #include #include #include #include +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; { diff --git a/rpc.subproj/authunix_prot.c b/rpc.subproj/authunix_prot.c index dce59b3..38864f2 100644 --- a/rpc.subproj/authunix_prot.c +++ b/rpc.subproj/authunix_prot.c @@ -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 +#include #include #include #include diff --git a/rpc.subproj/bindresvport.c b/rpc.subproj/bindresvport.c index 14261d1..ae903ae 100644 --- a/rpc.subproj/bindresvport.c +++ b/rpc.subproj/bindresvport.c @@ -53,13 +53,18 @@ #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 +#include #include #include #include @@ -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); } diff --git a/rpc.subproj/clnt_generic.c b/rpc.subproj/clnt_generic.c index cd966ef..3901b60 100644 --- a/rpc.subproj/clnt_generic.c +++ b/rpc.subproj/clnt_generic.c @@ -53,12 +53,13 @@ #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 #include #include #include diff --git a/rpc.subproj/clnt_perror.c b/rpc.subproj/clnt_perror.c index 7ad8e75..1e3ce14 100644 --- a/rpc.subproj/clnt_perror.c +++ b/rpc.subproj/clnt_perror.c @@ -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 +#include #include #include #include @@ -251,7 +252,6 @@ char * clnt_spcreateerror(s) char *s; { - extern int sys_nerr; char *str = _buf(); if (str == 0) diff --git a/rpc.subproj/clnt_raw.c b/rpc.subproj/clnt_raw.c index 100b870..0fccf08 100644 --- a/rpc.subproj/clnt_raw.c +++ b/rpc.subproj/clnt_raw.c @@ -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 +#include #include +extern bool_t xdr_opaque_auth(); + #define MCALL_MSG_SIZE 24 /* diff --git a/rpc.subproj/clnt_simple.c b/rpc.subproj/clnt_simple.c index ec99490..0ba26d0 100644 --- a/rpc.subproj/clnt_simple.c +++ b/rpc.subproj/clnt_simple.c @@ -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 #include #include +#include #include #include #include @@ -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; diff --git a/rpc.subproj/clnt_tcp.c b/rpc.subproj/clnt_tcp.c index 22f6616..71afd9d 100644 --- a/rpc.subproj/clnt_tcp.c +++ b/rpc.subproj/clnt_tcp.c @@ -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 +#include +#include +#include #include #include +#include #include #include #include @@ -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; diff --git a/rpc.subproj/clnt_udp.c b/rpc.subproj/clnt_udp.c index 38a03fe..446603a 100644 --- a/rpc.subproj/clnt_udp.c +++ b/rpc.subproj/clnt_udp.c @@ -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 +#include +#include +#include #include #include +#include #include #include #include #include +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; diff --git a/rpc.subproj/get_myaddress.c b/rpc.subproj/get_myaddress.c index 944a0e8..00cd672 100644 --- a/rpc.subproj/get_myaddress.c +++ b/rpc.subproj/get_myaddress.c @@ -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 #include #include +#include #include #include #include diff --git a/rpc.subproj/getrpcent.c b/rpc.subproj/getrpcent.c index 1b57d99..1a8fe44 100644 --- a/rpc.subproj/getrpcent.c +++ b/rpc.subproj/getrpcent.c @@ -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 +#include #include #include #include @@ -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) diff --git a/rpc.subproj/getrpcport.c b/rpc.subproj/getrpcport.c index af368dd..f7c51af 100644 --- a/rpc.subproj/getrpcport.c +++ b/rpc.subproj/getrpcport.c @@ -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 +#include #include +#include #include #include +int getrpcport(host, prognum, versnum, proto) char *host; { diff --git a/rpc.subproj/pmap_clnt.c b/rpc.subproj/pmap_clnt.c index cdd3261..087e4a8 100644 --- a/rpc.subproj/pmap_clnt.c +++ b/rpc.subproj/pmap_clnt.c @@ -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 #include #include #include diff --git a/rpc.subproj/pmap_getmaps.c b/rpc.subproj/pmap_getmaps.c index 7946572..2d8b341 100644 --- a/rpc.subproj/pmap_getmaps.c +++ b/rpc.subproj/pmap_getmaps.c @@ -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 #include #include #include diff --git a/rpc.subproj/pmap_getport.c b/rpc.subproj/pmap_getport.c index b4b6eb5..2e78d39 100644 --- a/rpc.subproj/pmap_getport.c +++ b/rpc.subproj/pmap_getport.c @@ -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 #include #include #include diff --git a/rpc.subproj/pmap_prot2.c b/rpc.subproj/pmap_prot2.c index 986c2c8..a5bd77d 100644 --- a/rpc.subproj/pmap_prot2.c +++ b/rpc.subproj/pmap_prot2.c @@ -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); diff --git a/rpc.subproj/pmap_rmt.c b/rpc.subproj/pmap_rmt.c index cbfffa6..7474d9f 100644 --- a/rpc.subproj/pmap_rmt.c +++ b/rpc.subproj/pmap_rmt.c @@ -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 +#include #include #include #include #include #include +#include #include #include #include @@ -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; diff --git a/rpc.subproj/rpc_callmsg.c b/rpc.subproj/rpc_callmsg.c index 45014db..713be6d 100644 --- a/rpc.subproj/rpc_callmsg.c +++ b/rpc.subproj/rpc_callmsg.c @@ -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 +#include #include #include +extern bool_t xdr_opaque_auth(); + /* * XDR a call message */ diff --git a/rpc.subproj/rpc_commondata.c b/rpc.subproj/rpc_commondata.c index c12c265..a3a122c 100644 --- a/rpc.subproj/rpc_commondata.c +++ b/rpc.subproj/rpc_commondata.c @@ -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 @@ -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 diff --git a/rpc.subproj/rpc_dtablesize.c b/rpc.subproj/rpc_dtablesize.c index bfdd00b..39a313a 100644 --- a/rpc.subproj/rpc_dtablesize.c +++ b/rpc.subproj/rpc_dtablesize.c @@ -53,15 +53,17 @@ #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 #include /* * Cache the result of getdtablesize(), so we don't have to do an * expensive system call every time. */ +int _rpc_dtablesize() { static int size; diff --git a/rpc.subproj/svc.c b/rpc.subproj/svc.c index a559c03..b0a6a9a 100644 --- a/rpc.subproj/svc.c +++ b/rpc.subproj/svc.c @@ -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 +#include #include #include #include @@ -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; diff --git a/rpc.subproj/svc_auth.c b/rpc.subproj/svc_auth.c index 6586c98..0d8db83 100644 --- a/rpc.subproj/svc_auth.c +++ b/rpc.subproj/svc_auth.c @@ -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 */ diff --git a/rpc.subproj/svc_auth_unix.c b/rpc.subproj/svc_auth_unix.c index 2f30dd7..95f6ca8 100644 --- a/rpc.subproj/svc_auth_unix.c +++ b/rpc.subproj/svc_auth_unix.c @@ -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 +#include #include #include diff --git a/rpc.subproj/svc_raw.c b/rpc.subproj/svc_raw.c index 6729e4d..54e6f62 100644 --- a/rpc.subproj/svc_raw.c +++ b/rpc.subproj/svc_raw.c @@ -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 #include diff --git a/rpc.subproj/svc_run.c b/rpc.subproj/svc_run.c index 47b467a..451591d 100644 --- a/rpc.subproj/svc_run.c +++ b/rpc.subproj/svc_run.c @@ -53,13 +53,15 @@ #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 +#include #include #include @@ -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) { diff --git a/rpc.subproj/svc_simple.c b/rpc.subproj/svc_simple.c index 6174d04..2268732 100644 --- a/rpc.subproj/svc_simple.c +++ b/rpc.subproj/svc_simple.c @@ -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 +#include +#include #include +#include #include #include @@ -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) { diff --git a/rpc.subproj/svc_tcp.c b/rpc.subproj/svc_tcp.c index 8828b63..077861f 100644 --- a/rpc.subproj/svc_tcp.c +++ b/rpc.subproj/svc_tcp.c @@ -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 +#include +#include +#include #include #include #include -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 }; @@ -247,6 +251,13 @@ makefd_xprt(fd, sendsize, recvsize) } 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; diff --git a/rpc.subproj/svc_udp.c b/rpc.subproj/svc_udp.c index 5af3045..5d799b8 100644 --- a/rpc.subproj/svc_udp.c +++ b/rpc.subproj/svc_udp.c @@ -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 #include +#include +#include #include #include #include +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; diff --git a/rpc.subproj/types.h b/rpc.subproj/types.h index b9cd3cf..79f7ede 100644 --- a/rpc.subproj/types.h +++ b/rpc.subproj/types.h @@ -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 */ diff --git a/rpc.subproj/xdr.c b/rpc.subproj/xdr.c index b523fee..227f601 100644 --- a/rpc.subproj/xdr.c +++ b/rpc.subproj/xdr.c @@ -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 +#include +#include #include #include @@ -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 diff --git a/rpc.subproj/xdr_array.c b/rpc.subproj/xdr_array.c index 356b795..7d68474 100644 --- a/rpc.subproj/xdr_array.c +++ b/rpc.subproj/xdr_array.c @@ -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 #include +#include #include #include diff --git a/rpc.subproj/xdr_mem.c b/rpc.subproj/xdr_mem.c index 3bec281..88848e3 100644 --- a/rpc.subproj/xdr_mem.c +++ b/rpc.subproj/xdr_mem.c @@ -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 #include #include #include diff --git a/rpc.subproj/xdr_rec.c b/rpc.subproj/xdr_rec.c index 912dbfb..2722896 100644 --- a/rpc.subproj/xdr_rec.c +++ b/rpc.subproj/xdr_rec.c @@ -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 #include +#include +#include #include #include #include diff --git a/rpc.subproj/xdr_reference.c b/rpc.subproj/xdr_reference.c index bfc82e1..acdd540 100644 --- a/rpc.subproj/xdr_reference.c +++ b/rpc.subproj/xdr_reference.c @@ -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 +#include +#include #include #include diff --git a/util.subproj/Makefile b/util.subproj/Makefile index aede900..499e7e6 100644 --- a/util.subproj/Makefile +++ b/util.subproj/Makefile @@ -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 index 0000000..b2a9e16 --- /dev/null +++ b/util.subproj/Makefile.postamble @@ -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 index 0000000..9b478c6 --- /dev/null +++ b/util.subproj/Makefile.preamble @@ -0,0 +1,3 @@ +AFTER_POSTINSTALL += install-man-page +OTHER_CFLAGS = \ + -DINET6=1 \ diff --git a/util.subproj/PB.project b/util.subproj/PB.project index eab47ff..2c20a90 100644 --- a/util.subproj/PB.project +++ b/util.subproj/PB.project @@ -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"; diff --git a/util.subproj/getgrouplist.c b/util.subproj/getgrouplist.c index 305f1b8..b342f60 100644 --- a/util.subproj/getgrouplist.c +++ b/util.subproj/getgrouplist.c @@ -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++) { diff --git a/util.subproj/pwcache.c b/util.subproj/pwcache.c index f0a4eec..3f2b72b 100644 --- a/util.subproj/pwcache.c +++ b/util.subproj/pwcache.c @@ -39,10 +39,11 @@ #include #include #include +#include #include #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 index 0000000..2fe71d0 --- /dev/null +++ b/util.subproj/rcmd.3 @@ -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 +.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 . diff --git a/util.subproj/rcmd.c b/util.subproj/rcmd.c index 611b94d..4345fb7 100644 --- a/util.subproj/rcmd.c +++ b/util.subproj/rcmd.c @@ -54,10 +54,12 @@ * 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 @@ -77,19 +79,34 @@ static char *rcsid = "$OpenBSD: rcmd.c,v 1.30 1998/02/12 02:21:19 deraadt Exp $" #include #include #include -#include -#include +#ifdef YP +#include +#include +#include +#endif +#include + +/* 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); } @@ -356,6 +445,28 @@ iruserok(raddr, superuser, ruser, luser) 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; struct passwd *pwd; @@ -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); } diff --git a/util.subproj/rcmdsh.c b/util.subproj/rcmdsh.c index 49f9eee..988e614 100644 --- a/util.subproj/rcmdsh.c +++ b/util.subproj/rcmdsh.c @@ -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]); } -- 2.7.4