From b3dd680f589a1f02e301659e04768ef61be3b843 Mon Sep 17 00:00:00 2001 From: Apple Date: Thu, 27 Sep 2007 21:46:25 +0000 Subject: [PATCH] Libinfo-278.tar.gz --- Makefile | 3 +- PB.project | 3 +- dns.subproj/Makefile.preamble | 1 + dns.subproj/gethnamaddr.c | 7 +- dns.subproj/inet.h | 26 +- dns.subproj/nameser8_compat.h | 2 +- dns.subproj/options.h | 3 + dns.subproj/res_debug.c | 9 +- dns.subproj/res_init.c | 187 -- dns.subproj/res_send.c | 2 +- gen.subproj/Makefile | 4 +- gen.subproj/Makefile.postamble | 1 - gen.subproj/Makefile.preamble | 4 + gen.subproj/PB.project | 1 - gen.subproj/ether_addr.3 | 1 - gen.subproj/fstab.c | 8 + gen.subproj/getgrent.c | 4 +- gen.subproj/gethostbyname.3 | 63 +- gen.subproj/getifaddrs.c | 62 +- gen.subproj/getnetent.3 | 29 +- gen.subproj/getprotoent.3 | 30 +- gen.subproj/getpwent.c | 355 ++- gen.subproj/getservent.3 | 32 +- gen.subproj/if_indextoname.3 | 25 +- gen.subproj/inet_ntop.c | 123 +- gen.subproj/inet_pton.c | 55 +- gen.subproj/initgroups.c | 5 +- gen.subproj/printerdb.c | 9 +- lookup.subproj/DSlibinfoMIG.defs | 77 + lookup.subproj/DSlibinfoMIGAsyncReply.defs | 55 + lookup.subproj/DSlibinfoMIG_types.h | 52 + lookup.subproj/Makefile | 12 +- lookup.subproj/Makefile.postamble | 41 +- lookup.subproj/Makefile.preamble | 15 +- lookup.subproj/PB.project | 2 +- lookup.subproj/bootparams.5 | 39 + lookup.subproj/gai_strerror.3 | 102 + lookup.subproj/getaddrinfo.3 | 45 +- lookup.subproj/getaddrinfo.c | 1030 +++---- lookup.subproj/getfsent.3 | 153 + lookup.subproj/getgrent.3 | 260 ++ lookup.subproj/getgrouplist.3 | 96 + lookup.subproj/getnameinfo.3 | 53 +- lookup.subproj/getnetgrent.3 | 133 + lookup.subproj/getpwent.3 | 315 ++ lookup.subproj/initgroups.3 | 86 + lookup.subproj/kvbuf.h | 137 + lookup.subproj/lu_alias.c | 379 +-- lookup.subproj/lu_bootp.c | 227 -- lookup.subproj/lu_bootparam.c | 325 --- lookup.subproj/lu_fstab.c | 392 +-- lookup.subproj/lu_group.c | 894 +++--- lookup.subproj/lu_host.c | 1294 ++++---- lookup.subproj/lu_host.h | 20 +- lookup.subproj/lu_host_async.c | 1188 ++------ lookup.subproj/lu_netgroup.c | 347 +-- lookup.subproj/lu_network.c | 416 +-- lookup.subproj/lu_overrides.h | 14 - lookup.subproj/lu_printer.c | 409 +-- lookup.subproj/lu_protocol.c | 414 +-- lookup.subproj/lu_rpc.c | 434 +-- lookup.subproj/lu_service.c | 563 +--- lookup.subproj/lu_user.c | 646 +--- lookup.subproj/lu_utils.c | 2758 +++++++++++++----- lookup.subproj/lu_utils.h | 118 +- lookup.subproj/netdb.h | 68 +- lookup.subproj/netdb_async.h | 43 +- lookup.subproj/netgr.h | 41 - mdns.subproj/DNSServiceDiscovery.c | 672 ----- mdns.subproj/DNSServiceDiscovery.h | 292 -- mdns.subproj/DNSServiceDiscoveryDefines.h | 37 - mdns.subproj/DNSServiceDiscoveryReply.defs | 66 - mdns.subproj/DNSServiceDiscoveryRequest.defs | 86 - mdns.subproj/Makefile | 52 - mdns.subproj/Makefile.postamble | 110 - mdns.subproj/Makefile.preamble | 160 - mdns.subproj/PB.project | 34 - mdns.subproj/dns_sd.h | 1644 ----------- mdns.subproj/dnssd_clientlib.c | 361 --- mdns.subproj/dnssd_clientstub.c | 1176 -------- mdns.subproj/dnssd_ipc.c | 129 - mdns.subproj/dnssd_ipc.h | 225 -- membership.subproj/DSmemberdMIG.defs | 1 + membership.subproj/Makefile | 5 +- membership.subproj/Makefile.postamble | 11 + membership.subproj/Makefile.preamble | 11 +- membership.subproj/PB.project | 4 +- membership.subproj/mbr_check_membership.3 | 93 + membership.subproj/mbr_uid_to_uuid.3 | 101 + membership.subproj/mbr_uid_to_uuid_so.3 | 1 + membership.subproj/memberd.defs | 90 - membership.subproj/memberd_defines.h | 53 - membership.subproj/membership.c | 421 +-- membership.subproj/membershipPriv.h | 28 +- netinfo.subproj/Makefile | 19 +- netinfo.subproj/Makefile.postamble | 12 - netinfo.subproj/Makefile.preamble | 8 +- netinfo.subproj/PB.project | 16 +- netinfo.subproj/clib.h | 34 - netinfo.subproj/mm.h | 57 - netinfo.subproj/multi_call.c | 352 --- netinfo.subproj/netinfo.3 | 425 --- netinfo.subproj/netinfo.5 | 278 -- netinfo.subproj/ni.h | 133 - netinfo.subproj/ni_error.c | 77 - netinfo.subproj/ni_glue.c | 2325 --------------- netinfo.subproj/ni_prot.x | 502 ---- netinfo.subproj/ni_pwdomain.c | 238 -- netinfo.subproj/ni_stub.c | 171 ++ netinfo.subproj/ni_useful.c | 746 ----- netinfo.subproj/ni_util.c | 541 ---- netinfo.subproj/ni_util.h | 107 - netinfo.subproj/nibind_prot.x | 116 - netinfo.subproj/sys_interfaces.c | 119 - netinfo.subproj/sys_interfaces.h | 54 - nis.subproj/Makefile | 2 +- nis.subproj/Makefile.postamble | 4 + nis.subproj/Makefile.preamble | 2 + nis.subproj/xdr_ypmaplist.c | 2 +- nis.subproj/xdr_ypresp_maplist.c | 2 +- nis.subproj/yp.8 | 566 ++++ nis.subproj/yp_all.c | 12 +- nis.subproj/yp_bind.c | 212 +- nis.subproj/yp_first.c | 19 +- nis.subproj/yp_maplist.c | 17 +- nis.subproj/yp_master.c | 19 +- nis.subproj/yp_order.c | 21 +- nis.subproj/ypclnt.3 | 4 +- nis.subproj/ypinternal.h | 8 + nis.subproj/ypmatch_cache.c | 40 +- rpc.subproj/Makefile | 3 +- rpc.subproj/Makefile.postamble | 224 ++ rpc.subproj/Makefile.preamble | 3 + rpc.subproj/auth.h | 7 +- rpc.subproj/auth_unix.c | 4 +- rpc.subproj/auth_unix.h | 4 + rpc.subproj/authunix_prot.c | 2 +- rpc.subproj/bindresvport.3 | 27 + rpc.subproj/bindresvport.c | 4 +- rpc.subproj/clnt.h | 109 +- rpc.subproj/clnt_generic.c | 7 + rpc.subproj/clnt_perror.c | 24 +- rpc.subproj/clnt_raw.c | 22 +- rpc.subproj/clnt_tcp.c | 138 +- rpc.subproj/clnt_udp.c | 194 +- rpc.subproj/getrpcent.3 | 93 + rpc.subproj/getrpcent.c | 19 +- rpc.subproj/getrpcport.3 | 32 + rpc.subproj/pmap_clnt.c | 63 +- rpc.subproj/pmap_clnt.h | 35 +- rpc.subproj/pmap_getmaps.c | 7 +- rpc.subproj/pmap_getport.c | 71 +- rpc.subproj/pmap_prot.h | 20 + rpc.subproj/pmap_prot2.c | 3 +- rpc.subproj/pmap_rmt.c | 56 +- rpc.subproj/pmap_rmt.h | 9 + rpc.subproj/pmap_wakeup.c | 7 +- rpc.subproj/pmap_wakeup.h | 2 +- rpc.subproj/rpc.3 | 1731 +++++++++++ rpc.subproj/rpc_callmsg.c | 46 +- rpc.subproj/rpc_msg.h | 29 +- rpc.subproj/rpc_prot.c | 18 +- rpc.subproj/svc.c | 19 + rpc.subproj/svc.h | 26 +- rpc.subproj/svc_auth_unix.c | 15 +- rpc.subproj/svc_simple.c | 11 +- rpc.subproj/svc_tcp.c | 7 +- rpc.subproj/svc_udp.c | 5 +- rpc.subproj/types.h | 8 + rpc.subproj/xdr.3 | 829 ++++++ rpc.subproj/xdr.c | 148 +- rpc.subproj/xdr.h | 52 +- rpc.subproj/xdr_mem.c | 48 +- rpc.subproj/xdr_rec.c | 100 +- rpc.subproj/xdr_sizeof.c | 16 +- rpc.subproj/xdr_stdio.c | 48 +- util.subproj/Makefile.postamble | 1 + util.subproj/Makefile.preamble | 1 + util.subproj/hosts.equiv.5 | 1 - util.subproj/putpwpasswd.c | 114 +- util.subproj/pwcache.c | 21 +- util.subproj/rcmd.c | 23 +- 182 files changed, 12319 insertions(+), 20057 deletions(-) delete mode 100644 gen.subproj/ether_addr.3 create mode 100644 lookup.subproj/DSlibinfoMIG.defs create mode 100644 lookup.subproj/DSlibinfoMIGAsyncReply.defs create mode 100644 lookup.subproj/DSlibinfoMIG_types.h create mode 100644 lookup.subproj/bootparams.5 create mode 100644 lookup.subproj/gai_strerror.3 create mode 100644 lookup.subproj/getfsent.3 create mode 100644 lookup.subproj/getgrent.3 create mode 100644 lookup.subproj/getgrouplist.3 create mode 100644 lookup.subproj/getnetgrent.3 create mode 100644 lookup.subproj/getpwent.3 create mode 100644 lookup.subproj/initgroups.3 create mode 100644 lookup.subproj/kvbuf.h delete mode 100644 lookup.subproj/netgr.h delete mode 100644 mdns.subproj/DNSServiceDiscovery.c delete mode 100644 mdns.subproj/DNSServiceDiscovery.h delete mode 100644 mdns.subproj/DNSServiceDiscoveryDefines.h delete mode 100644 mdns.subproj/DNSServiceDiscoveryReply.defs delete mode 100644 mdns.subproj/DNSServiceDiscoveryRequest.defs delete mode 100644 mdns.subproj/Makefile delete mode 100644 mdns.subproj/Makefile.postamble delete mode 100644 mdns.subproj/Makefile.preamble delete mode 100644 mdns.subproj/PB.project delete mode 100644 mdns.subproj/dns_sd.h delete mode 100755 mdns.subproj/dnssd_clientlib.c delete mode 100644 mdns.subproj/dnssd_clientstub.c delete mode 100644 mdns.subproj/dnssd_ipc.c delete mode 100644 mdns.subproj/dnssd_ipc.h create mode 100644 membership.subproj/DSmemberdMIG.defs create mode 100644 membership.subproj/mbr_check_membership.3 create mode 100644 membership.subproj/mbr_uid_to_uuid.3 create mode 100644 membership.subproj/mbr_uid_to_uuid_so.3 delete mode 100644 membership.subproj/memberd.defs delete mode 100644 membership.subproj/memberd_defines.h delete mode 100644 netinfo.subproj/Makefile.postamble delete mode 100644 netinfo.subproj/clib.h delete mode 100644 netinfo.subproj/mm.h delete mode 100644 netinfo.subproj/multi_call.c delete mode 100644 netinfo.subproj/netinfo.3 delete mode 100644 netinfo.subproj/netinfo.5 delete mode 100644 netinfo.subproj/ni.h delete mode 100644 netinfo.subproj/ni_error.c delete mode 100644 netinfo.subproj/ni_glue.c delete mode 100644 netinfo.subproj/ni_prot.x delete mode 100644 netinfo.subproj/ni_pwdomain.c create mode 100644 netinfo.subproj/ni_stub.c delete mode 100644 netinfo.subproj/ni_useful.c delete mode 100644 netinfo.subproj/ni_util.c delete mode 100644 netinfo.subproj/ni_util.h delete mode 100644 netinfo.subproj/nibind_prot.x delete mode 100644 netinfo.subproj/sys_interfaces.c delete mode 100644 netinfo.subproj/sys_interfaces.h create mode 100644 nis.subproj/yp.8 create mode 100644 rpc.subproj/Makefile.postamble create mode 100644 rpc.subproj/bindresvport.3 create mode 100644 rpc.subproj/getrpcent.3 create mode 100644 rpc.subproj/getrpcport.3 create mode 100644 rpc.subproj/rpc.3 create mode 100644 rpc.subproj/xdr.3 diff --git a/Makefile b/Makefile index 6739fad..35007d3 100644 --- a/Makefile +++ b/Makefile @@ -13,8 +13,7 @@ PROJECTVERSION = 2.8 PROJECT_TYPE = Library SUBPROJECTS = dns.subproj gen.subproj lookup.subproj membership.subproj\ - netinfo.subproj nis.subproj rpc.subproj util.subproj\ - mdns.subproj + netinfo.subproj nis.subproj rpc.subproj util.subproj OTHERSRCS = Makefile.preamble Makefile Makefile.postamble diff --git a/PB.project b/PB.project index 34ca56b..314f8be 100644 --- a/PB.project +++ b/PB.project @@ -14,8 +14,7 @@ netinfo.subproj, nis.subproj, rpc.subproj, - util.subproj, - mdns.subproj + util.subproj ); }; LANGUAGE = English; diff --git a/dns.subproj/Makefile.preamble b/dns.subproj/Makefile.preamble index c775255..f88e7ff 100644 --- a/dns.subproj/Makefile.preamble +++ b/dns.subproj/Makefile.preamble @@ -1,4 +1,5 @@ OTHER_CFLAGS = \ + -D__DARWIN_NON_CANCELABLE=1 \ -Dsethostent=_res_sethostent \ -Dgethostent=_res_gethostent \ -Dendhostent=_res_endhostent \ diff --git a/dns.subproj/gethnamaddr.c b/dns.subproj/gethnamaddr.c index b95f26f..f00f3dd 100644 --- a/dns.subproj/gethnamaddr.c +++ b/dns.subproj/gethnamaddr.c @@ -118,8 +118,9 @@ static const char AskedForGot[] = "gethostby*.getanswer: asked for \"%s\", got \"%s\""; static char *h_addr_ptrs[MAXADDRS + 1]; +#ifdef NOTDEF static struct hostent *gethostbyname_ipv4 __P((const char *)); - +#endif static struct hostent host; static char *host_aliases[MAXALIASES]; static char *hostbuf = NULL; @@ -149,8 +150,6 @@ typedef union { extern int h_errno; -extern int _lu_running(void); - #ifdef DEBUG static void dprintf(msg, num) @@ -442,6 +441,7 @@ gethostbyname(name) return (gethostbyname2(name, AF_INET)); } +#ifdef NOTDEF static struct hostent * gethostbyname_ipv4(name) const char *name; @@ -524,6 +524,7 @@ gethostbyname_ipv4(name) } return (getanswer(&buf, n, name, C_IN, T_A)); } +#endif struct hostent * gethostbyaddr(vaddr, len, type) diff --git a/dns.subproj/inet.h b/dns.subproj/inet.h index 6091ed9..2d75a40 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.7 2004/10/28 21:58:13 emoy Exp $ + * $Id: inet.h,v 1.10 2006/02/01 18:09:47 majka Exp $ */ #ifndef _INET_H_ @@ -86,25 +86,19 @@ /* External definitions for functions in inet(3) */ +#include <_types.h> #include /* uint32_t uint16_t */ -#include /* htonl() and family if !_POSIX_C_SOURCE */ -#include /* htonl() and family if _POSIX_C_SOURCE */ +#include /* htonl() and family if (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ +#include /* htonl() and family if (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */ #include /* in_addr */ -#include -#if (!defined(BSD)) || (BSD < 199306) -# include -#else -# include -#endif -#include __BEGIN_DECLS in_addr_t inet_addr(const char *); char *inet_ntoa(struct in_addr); -const char *inet_ntop(int, const void *, char *, size_t); +const char *inet_ntop(int, const void *, char *, socklen_t); int inet_pton(int, const char *, void *); -#ifndef _POSIX_C_SOURCE +#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) int ascii2addr(int, const char *, void *); char *addr2ascii(int, const void *, int, char *); int inet_aton(const char *, struct in_addr *); @@ -112,12 +106,12 @@ in_addr_t inet_lnaof(struct in_addr); struct in_addr inet_makeaddr(in_addr_t, in_addr_t); in_addr_t inet_netof(struct in_addr); in_addr_t inet_network(const char *); -char *inet_net_ntop(int, const void *, int, char *, size_t); -int inet_net_pton(int, const char *, void *, size_t); -char *inet_neta(in_addr_t, char *, size_t); +char *inet_net_ntop(int, const void *, int, char *, __darwin_size_t); +int inet_net_pton(int, const char *, void *, __darwin_size_t); +char *inet_neta(in_addr_t, char *, __darwin_size_t); unsigned int inet_nsap_addr(const char *, unsigned char *, int maxlen); char *inet_nsap_ntoa(int, const unsigned char *, char *ascii); -#endif /* _POSIX_C_SOURCE */ +#endif /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */ __END_DECLS diff --git a/dns.subproj/nameser8_compat.h b/dns.subproj/nameser8_compat.h index 809ec6b..d48d59a 100644 --- a/dns.subproj/nameser8_compat.h +++ b/dns.subproj/nameser8_compat.h @@ -233,7 +233,7 @@ #define BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */ #define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long (pdp)*/ -#if defined(vax) || defined(ns32000) || defined(sun386) || defined(i386) || \ +#if defined(vax) || defined(ns32000) || defined(sun386) || defined(__i386__) || \ defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \ defined(__alpha__) || defined(__alpha) #define BYTE_ORDER LITTLE_ENDIAN diff --git a/dns.subproj/options.h b/dns.subproj/options.h index 6a79326..a632bb3 100644 --- a/dns.subproj/options.h +++ b/dns.subproj/options.h @@ -98,7 +98,10 @@ * gns = Greg Shapiro of WPI */ +#ifndef DEBUG #define DEBUG /* enable -d flag and SIGUSR[12] support (ucb) */ +#endif + /*#define ALLOW_T_UNSPEC enable the "unspec" RR type for old athena (ucb) */ /*#define INVQ enable inverse queries (nslookup) (ucb/vix) */ /*#define DSTORAGE debug malloc overruns using storage.o (ucb/vix) */ diff --git a/dns.subproj/res_debug.c b/dns.subproj/res_debug.c index ba2cfb4..bf83730 100644 --- a/dns.subproj/res_debug.c +++ b/dns.subproj/res_debug.c @@ -477,7 +477,7 @@ __p_rr(cp, msg, file) FILE *file; { int type, class, n, c; - long dlen; + int dlen; struct in_addr inaddr; const u_char *cp1, *cp2; u_int32_t tmpttl, t; @@ -704,8 +704,11 @@ __p_rr(cp, msg, file) putc('\n', file); #endif if (cp - cp1 != dlen) { - fprintf(file, ";; packet size error (found %ld, dlen was %ld)\n", - cp - cp1, dlen); +#ifdef __LP64__ + fprintf(file, ";; packet size error (found %ld, dlen was %d)\n", cp - cp1, dlen); +#else + fprintf(file, ";; packet size error (found %d, dlen was %d)\n", cp - cp1, dlen); +#endif cp = NULL; } return (cp); diff --git a/dns.subproj/res_init.c b/dns.subproj/res_init.c index d45795f..7336289 100644 --- a/dns.subproj/res_init.c +++ b/dns.subproj/res_init.c @@ -99,35 +99,6 @@ static char rcsid[] = "$Id: res_init.c,v 1.8 2003/02/18 17:29:24 majka Exp $"; # include "portability.h" #endif -/*-------------------------------------- info about "sortlist" -------------- - * Marc Majka 1994/04/16 - * Allan Nathanson 1994/10/29 (BIND 4.9.3.x) - * - * NetInfo resolver configuration directory support. - * - * Allow a NetInfo directory to be created in the hierarchy which - * contains the same information as the resolver configuration file. - * - * - The local domain name is stored as the value of the "domain" property. - * - The Internet address(es) of the name server(s) are stored as values - * of the "nameserver" property. - * - The name server addresses are stored as values of the "nameserver" - * property. - * - The search list for host-name lookup is stored as values of the - * "search" property. - * - The sortlist comprised of IP address netmask pairs are stored as - * values of the "sortlist" property. The IP address and optional netmask - * should be seperated by a slash (/) or ampersand (&) character. - * - Internal resolver variables can be set from the value of the "options" - * property. - */ -#if defined(__APPLE__) && defined(CONFIGURE_RESOLVER_FROM_NETINFO) -# include -# define NI_PATH_RESCONF "/locations/resolver" -# define NI_TIMEOUT 10 -static int netinfo_res_init __P((int *haveenv, int *havesearch)); -#endif - #if defined(USE_OPTIONS_H) # include "options.h" #endif @@ -403,9 +374,6 @@ res_init() #endif (void) fclose(fp); } -#if defined(__APPLE__) && defined(CONFIGURE_RESOLVER_FROM_NETINFO) - else netinfo_res_init(&haveenv, &havesearch); -#endif if (_res.defdname[0] == 0 && gethostname(buf, sizeof(_res.defdname) - 1) == 0 && @@ -510,161 +478,6 @@ net_mask(in) /* XXX - should really use system's version of this */ } #endif -#if defined(__APPLE__) && defined(CONFIGURE_RESOLVER_FROM_NETINFO) -static int -netinfo_res_init(haveenv, havesearch) - int *haveenv; - int *havesearch; -{ - register int n; - void *domain, *parent; - ni_id dir; - ni_status status; - ni_namelist nl; - int nserv = 0; -#ifdef RESOLVSORT - int nsort = 0; -#endif - - status = ni_open(NULL, ".", &domain); - if (status == NI_OK) { - ni_setreadtimeout(domain, NI_TIMEOUT); - ni_setabort(domain, 1); - - /* climb the NetInfo hierarchy to find a resolver directory */ - while (status == NI_OK) { - status = ni_pathsearch(domain, &dir, NI_PATH_RESCONF); - if (status == NI_OK) { - /* found a resolver directory */ - - if (*haveenv == 0) { - /* get the default domain name */ - status = ni_lookupprop(domain, &dir, "domain", &nl); - if (status == NI_OK && nl.ni_namelist_len > 0) { - (void)strncpy(_res.defdname, - nl.ni_namelist_val[0], - sizeof(_res.defdname) - 1); - _res.defdname[sizeof(_res.defdname) - 1] = '\0'; - ni_namelist_free(&nl); - *havesearch = 0; - } - - /* get search list */ - status = ni_lookupprop(domain, &dir, "search", &nl); - if (status == NI_OK && nl.ni_namelist_len > 0) { - (void)strncpy(_res.defdname, - nl.ni_namelist_val[0], - sizeof(_res.defdname) - 1); - _res.defdname[sizeof(_res.defdname) - 1] = '\0'; - /* copy */ - for (n = 0; - n < nl.ni_namelist_len && n < MAXDNSRCH; - n++) { - /* duplicate up to MAXDNSRCH servers */ - char *cp = nl.ni_namelist_val[n]; - _res.dnsrch[n] = - strcpy((char *)malloc(strlen(cp) + 1), cp); - } - ni_namelist_free(&nl); - *havesearch = 1; - } - } - - /* get list of nameservers */ - status = ni_lookupprop(domain, &dir, "nameserver", &nl); - if (status == NI_OK && nl.ni_namelist_len > 0) { - /* copy up to MAXNS servers */ - for (n = 0; - n < nl.ni_namelist_len && nserv < MAXNS; - n++) { - struct in_addr a; - - if (inet_aton(nl.ni_namelist_val[n], &a)) { - _res.nsaddr_list[nserv].sin_addr = a; - _res.nsaddr_list[nserv].sin_family = AF_INET; - _res.nsaddr_list[nserv].sin_port = - htons(NAMESERVER_PORT); - nserv++; - } - } - ni_namelist_free(&nl); - } - - if (nserv > 1) - _res.nscount = nserv; - -#ifdef RESOLVSORT - /* get sort order */ - status = ni_lookupprop(domain, &dir, "sortlist", &nl); - if (status == NI_OK && nl.ni_namelist_len > 0) { - - /* copy up to MAXRESOLVSORT address/netmask pairs */ - for (n = 0; - n < nl.ni_namelist_len && nsort < MAXRESOLVSORT; - n++) { - char ch = '\0'; - char *cp; - const char *sp; - struct in_addr a; - - cp = NULL; - for (sp = sort_mask; *sp; sp++) { - char *cp1; - cp1 = strchr(nl.ni_namelist_val[n], *sp); - if (cp && cp1) - cp = (cp < cp1)? cp : cp1; - else if (cp1) - cp = cp1; - } - if (cp != NULL) { - ch = *cp; - *cp = '\0'; - break; - } - if (inet_aton(nl.ni_namelist_val[n], &a)) { - _res.sort_list[nsort].addr = a; - if (*cp && ISSORTMASK(ch)) { - *cp++ = ch; - if (inet_aton(cp, &a)) { - _res.sort_list[nsort].mask = a.s_addr; - } else { - _res.sort_list[nsort].mask = - net_mask(_res.sort_list[nsort].addr); - } - } else { - _res.sort_list[nsort].mask = - net_mask(_res.sort_list[nsort].addr); - } - nsort++; - } - } - ni_namelist_free(&nl); - } - - _res.nsort = nsort; -#endif - - /* get resolver options */ - status = ni_lookupprop(domain, &dir, "options", &nl); - if (status == NI_OK && nl.ni_namelist_len > 0) { - res_setoptions(nl.ni_namelist_val[0], "conf"); - ni_namelist_free(&nl); - } - - ni_free(domain); - return(1); /* using DNS configuration from NetInfo */ - } - - status = ni_open(domain, "..", &parent); - ni_free(domain); - if (status == NI_OK) - domain = parent; - } - } - return(0); /* if not using DNS configuration from NetInfo */ -} -#endif /* __APPLE__ */ - u_int16_t res_randomid() { diff --git a/dns.subproj/res_send.c b/dns.subproj/res_send.c index 5e2a2fb..d6cf0f5 100644 --- a/dns.subproj/res_send.c +++ b/dns.subproj/res_send.c @@ -584,7 +584,7 @@ res_send(buf, buflen, ans, anssiz) struct timeval timeout; fd_set dsmask; struct sockaddr_in from; - int fromlen; + unsigned int fromlen; if ((s < 0) || vc) { if (vc) diff --git a/gen.subproj/Makefile b/gen.subproj/Makefile index 0c859d6..ae7b3ee 100644 --- a/gen.subproj/Makefile +++ b/gen.subproj/Makefile @@ -22,11 +22,13 @@ CFILES = aliasdb.c ether_addr.c fstab.c getgrent.c\ map_v4v6.c ip6opt.c rthdr.c vars.c OTHERSRCS = Makefile.preamble Makefile Makefile.postamble\ - ether_addr.3 getifaddrs.3 if_indextoname.3 inet6_rthdr_space.3\ + getifaddrs.3 if_indextoname.3 inet6_rthdr_space.3\ gethostbyname.3 inet6_option_space.3\ getprotoent.3 gethostbyname.3 getipnodebyname.3\ getnetent.3 getservent.3 inet6_option_space.3 +OTHERLINKEDOFILES = _version.o + MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles CODE_GEN_STYLE = DYNAMIC diff --git a/gen.subproj/Makefile.postamble b/gen.subproj/Makefile.postamble index 0db6698..3cc4f8e 100644 --- a/gen.subproj/Makefile.postamble +++ b/gen.subproj/Makefile.postamble @@ -118,7 +118,6 @@ install-man-page: $(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 ether_addr.3 "$(DSTROOT)/usr/share/man/man3" 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" diff --git a/gen.subproj/Makefile.preamble b/gen.subproj/Makefile.preamble index baa75c4..7f9c621 100644 --- a/gen.subproj/Makefile.preamble +++ b/gen.subproj/Makefile.preamble @@ -1,5 +1,6 @@ AFTER_POSTINSTALL += install-man-page OTHER_CFLAGS = \ + -D__DARWIN_NON_CANCELABLE=1 \ -DINET6=1 \ -Dsetservent=_old_setservent \ -Dgetservent=_old_getservent \ @@ -35,3 +36,6 @@ OTHER_CFLAGS = \ # for building 64-bit # Libinfo need to build with gcc-3.5 and 3-way fat NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER) + +$(OFILE_DIR)/_version.c: + /Developer/Makefiles/bin/version.pl Libinfo > $@ diff --git a/gen.subproj/PB.project b/gen.subproj/PB.project index 387e3a5..7dbd744 100644 --- a/gen.subproj/PB.project +++ b/gen.subproj/PB.project @@ -31,7 +31,6 @@ Makefile.preamble, Makefile, Makefile.postamble, - ether_addr.3, getifaddrs.3, if_indextoname.3, inet6_rthdr_space.3, diff --git a/gen.subproj/ether_addr.3 b/gen.subproj/ether_addr.3 deleted file mode 100644 index 4c50e4d..0000000 --- a/gen.subproj/ether_addr.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/ethers.3 diff --git a/gen.subproj/fstab.c b/gen.subproj/fstab.c index 5ccc4b1..8ed5824 100644 --- a/gen.subproj/fstab.c +++ b/gen.subproj/fstab.c @@ -21,6 +21,14 @@ * * @APPLE_LICENSE_HEADER_END@ */ +/* + * Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved + * + * Copyright (c) 1980, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * @(#)fstab.c 8.1 (Berkeley) 6/4/93 + */ #include #include diff --git a/gen.subproj/getgrent.c b/gen.subproj/getgrent.c index 36a01d2..b867892 100644 --- a/gen.subproj/getgrent.c +++ b/gen.subproj/getgrent.c @@ -124,10 +124,10 @@ start_gr() return((_gr_fp = fopen(_PATH_GROUP, "r")) ? 1 : 0); } -int +void setgrent() { - return(setgroupent(0)); + setgroupent(0); } int diff --git a/gen.subproj/gethostbyname.3 b/gen.subproj/gethostbyname.3 index 779383e..1789cb5 100644 --- a/gen.subproj/gethostbyname.3 +++ b/gen.subproj/gethostbyname.3 @@ -36,36 +36,55 @@ .Dt GETHOSTBYNAME 3 .Os .Sh NAME +.Nm endhostent , +.Nm gethostbyaddr , .Nm gethostbyname , .Nm gethostbyname2 , -.Nm gethostbyaddr , .Nm gethostent , -.Nm sethostent , -.Nm endhostent , .Nm herror , -.Nm hstrerror +.Nm hstrerror , +.Nm sethostent .Nd get network host entry .Sh LIBRARY .Lb libc .Sh SYNOPSIS .Fd #include .Vt extern int h_errno ; +.Ft void +.Fo endhostent +.Fa void +.Fc .Ft struct hostent * -.Fn gethostbyname "const char *name" +.Fo gethostbyaddr +.Fa "const void *addr" +.Fa "socklen_t len" +.Fa "int type" +.Fc .Ft struct hostent * -.Fn gethostbyname2 "const char *name" "int af" +.Fo gethostbyname +.Fa "const char *name" +.Fc .Ft struct hostent * -.Fn gethostbyaddr "const char *addr" "socklen_t len" "int type" +.Fo gethostbyname2 +.Fa "const char *name" +.Fa "int af" +.Fc .Ft struct hostent * -.Fn gethostent void -.Ft void -.Fn sethostent "int stayopen" -.Ft void -.Fn endhostent void +.Fo gethostent +.Fa void +.Fc .Ft void -.Fn herror "const char *string" +.Fo herror +.Fa "const char *string" +.Fc .Ft const char * -.Fn hstrerror "int err" +.Fo hstrerror +.Fa "int err" +.Fc +.Ft void +.Fo sethostent +.Fa "int stayopen" +.Fc .Sh DESCRIPTION The .Fn gethostbyname , @@ -236,6 +255,22 @@ 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 LEGACY SYNOPSIS +.Fd #include +.Pp +.Vt extern int h_errno ; +.Pp +.Ft struct hostent * +.br +.Fo gethostbyaddr +.Fa "const void *addr" +.Fa "socklen_t len" +.Fa "int type" +.Fc ; +.Pp +The type of +.Fa addr +has changed slightly. .Sh SEE ALSO .Xr getaddrinfo 3 , .Xr resolver 3 , diff --git a/gen.subproj/getifaddrs.c b/gen.subproj/getifaddrs.c index b2e286e..63c4bfc 100644 --- a/gen.subproj/getifaddrs.c +++ b/gen.subproj/getifaddrs.c @@ -39,8 +39,10 @@ #include #include +#include #include #include +#include #if !defined(AF_LINK) #define SA_LEN(sa) sizeof(struct sockaddr) @@ -50,7 +52,7 @@ #define SA_LEN(sa) (sa)->sa_len #endif -#define SALIGN (sizeof(long) - 1) +#define SALIGN (sizeof(int32_t) - 1) #define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : (SALIGN + 1)) #ifndef ALIGNBYTES @@ -81,12 +83,18 @@ #define HAVE_IFM_DATA #endif +#define MEMORY_MIN 2048 +#define MEMORY_MAX 4194304 + int getifaddrs(struct ifaddrs **pif) { int icnt = 1; int dcnt = 0; int ncnt = 0; + struct ifaddrs *ifa, *ift; + struct sockaddr_in6 *sin6; + uint16_t esid; #ifdef NET_RT_IFLIST int mib[6]; size_t needed; @@ -99,7 +107,6 @@ getifaddrs(struct ifaddrs **pif) 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]; @@ -108,7 +115,7 @@ getifaddrs(struct ifaddrs **pif) struct ifreq *ifr; struct ifreq *lifr; #endif /* NET_RT_IFLIST */ - int i; + int i, status; size_t len, alen; char *data; char *names; @@ -120,13 +127,22 @@ getifaddrs(struct ifaddrs **pif) 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) { + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) return (-1); + + if (needed < MEMORY_MIN) needed = MEMORY_MIN; + needed *= 2; + + while (needed <= MEMORY_MAX) + { + buf = malloc(needed); + if (buf == NULL) return (-1); + + status = sysctl(mib, 6, buf, &needed, NULL, 0); + if (status >= 0) break; + free(buf); - return (-1); + buf = NULL; + needed *= 2; } for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { @@ -196,12 +212,17 @@ getifaddrs(struct ifaddrs **pif) ifc.ifc_buf = buf; ifc.ifc_len = sizeof(buf); - if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + free(buf); return (-1); + } + i = ioctl(sock, SIOCGIFCONF, (char *)&ifc); close(sock); - if (i < 0) + if (i < 0) { + free(buf); return (-1); + } ifr = ifc.ifc_req; lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len]; @@ -213,7 +234,7 @@ getifaddrs(struct ifaddrs **pif) ++icnt; dcnt += SA_RLEN(sa); ncnt += sizeof(ifr->ifr_name) + 1; - + ifr = (struct ifreq *)(((char *)sa) + SA_LEN(sa)); } #endif /* NET_RT_IFLIST */ @@ -364,7 +385,7 @@ getifaddrs(struct ifaddrs **pif) 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); } @@ -376,6 +397,21 @@ getifaddrs(struct ifaddrs **pif) *pif = NULL; free(ifa); } + + for (ift = ifa; ift != NULL; ift = ift->ifa_next) + { + if (ift->ifa_addr->sa_family == AF_INET6) + { + sin6 = (struct sockaddr_in6 *)ift->ifa_addr; + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) || IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) + { + esid = ntohs(sin6->sin6_addr.__u6_addr.__u6_addr16[1]); + sin6->sin6_addr.__u6_addr.__u6_addr16[1] = 0; + if (sin6->sin6_scope_id == 0) sin6->sin6_scope_id = esid; + } + } + } + return (0); } diff --git a/gen.subproj/getnetent.3 b/gen.subproj/getnetent.3 index 18bbd70..7786ce0 100644 --- a/gen.subproj/getnetent.3 +++ b/gen.subproj/getnetent.3 @@ -36,26 +36,37 @@ .Dt GETNETENT 3 .Os .Sh NAME -.Nm getnetent , +.Nm endnetent , .Nm getnetbyaddr , .Nm getnetbyname , -.Nm setnetent , -.Nm endnetent +.Nm getnetent , +.Nm setnetent .Nd get network entry .Sh LIBRARY .Lb libc .Sh SYNOPSIS .Fd #include +.Ft void +.Fo endnetent +.Fa void +.Fc .Ft struct netent * -.Fn getnetent void +.Fo getnetbyaddr +.Fa "uint32_t net" +.Fa "int type" +.Fc .Ft struct netent * -.Fn getnetbyname "const char *name" +.Fo getnetbyname +.Fa "const char *name" +.Fc .Ft struct netent * -.Fn getnetbyaddr "uint32_t net" "int type" -.Ft void -.Fn setnetent "int stayopen" +.Fo getnetent +.Fa void +.Fc .Ft void -.Fn endnetent void +.Fo setnetent +.Fa "int stayopen" +.Fc .Sh DESCRIPTION The .Fn getnetent , diff --git a/gen.subproj/getprotoent.3 b/gen.subproj/getprotoent.3 index e0fd91c..5a22328 100644 --- a/gen.subproj/getprotoent.3 +++ b/gen.subproj/getprotoent.3 @@ -36,26 +36,36 @@ .Dt GETPROTOENT 3 .Os .Sh NAME -.Nm getprotoent , -.Nm getprotobynumber , +.Nm endprotoent , .Nm getprotobyname , -.Nm setprotoent , -.Nm endprotoent +.Nm getprotobynumber , +.Nm getprotoent , +.Nm setprotoent .Nd get protocol entry .Sh LIBRARY .Lb libc .Sh SYNOPSIS .Fd #include +.Ft void +.Fo endprotoent +.Fa void +.Fc .Ft struct protoent * -.Fn getprotoent void +.Fo getprotobyname +.Fa "const char *name" +.Fc .Ft struct protoent * -.Fn getprotobyname "const char *name" +.Fo getprotobynumber +.Fa "int proto" +.Fc .Ft struct protoent * -.Fn getprotobynumber "int proto" -.Ft void -.Fn setprotoent "int stayopen" +.Fo getprotoent +.Fa void +.Fc .Ft void -.Fn endprotoent void +.Fo setprotoent +.Fa "int stayopen" +.Fc .Sh DESCRIPTION The .Fn getprotoent , diff --git a/gen.subproj/getpwent.c b/gen.subproj/getpwent.c index 8081b71..01a9eee 100644 --- a/gen.subproj/getpwent.c +++ b/gen.subproj/getpwent.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2007 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -26,7 +26,7 @@ * * /etc/passwd file access routines. * Just read from the /etc/passwd file and skip the dbm database, since - * lookupd does all flat file lookups when the system is multi-user. + * Directory Service does all flat file lookups when the system is multi-user. * These routines are only used in single-user mode. * * 17 Apr 1997 file created - Marc Majka @@ -36,6 +36,9 @@ #include #include #include +#include +#include +#include #include #define forever for (;;) @@ -45,27 +48,19 @@ #define _PWUID_ 2 static struct passwd _pw = { 0 }; -static FILE *_pfp; -static int _pwStayOpen; +static FILE *_pfp = NULL; static int _pwFileFormat = 1; -static void -free_pw() -{ - if (_pw.pw_name != NULL) free(_pw.pw_name); - if (_pw.pw_passwd != NULL) free(_pw.pw_passwd); - if (_pw.pw_class != NULL) free(_pw.pw_class); - if (_pw.pw_gecos != NULL) free(_pw.pw_gecos); - if (_pw.pw_dir != NULL) free(_pw.pw_dir); - if (_pw.pw_shell != NULL) free(_pw.pw_shell); +#define _HENT_ 0 +#define _HNAM_ 1 +#define _HADDR_ 2 - _pw.pw_name = NULL; - _pw.pw_passwd = NULL; - _pw.pw_class = NULL; - _pw.pw_gecos = NULL; - _pw.pw_dir = NULL; - _pw.pw_shell = NULL; -} +static struct hostent _h = { 0 }; +static FILE *_hfp = NULL; + +/* Forward */ +__private_extern__ void LI_files_setpwent(); +__private_extern__ void LI_files_endhostent(); static void freeList(char **l) @@ -143,7 +138,6 @@ appendString(char *s, char **l) return insertString(s, l, (unsigned int)-1); } - static char ** tokenize(const char *data, const char *sep) { @@ -189,14 +183,14 @@ tokenize(const char *data, const char *sep) if (p[0] == sep[j] || (p[0] == '\0')) scanning = 0; } } - + /* back over trailing whitespace */ i--; if (i > -1) { /* did we actually copy anything? */ while ((buf[i] == ' ') || (buf[i] == '\t') || (buf[i] == '\n')) i--; } buf[++i] = '\0'; - + tokens = appendString(buf, tokens); /* check for end of line */ @@ -220,11 +214,49 @@ tokenize(const char *data, const char *sep) return tokens; } } + return tokens; } -struct passwd * -parseUser(char *data) +static char * +getLine(FILE *fp) +{ + char s[1024]; + char *out; + + s[0] = '\0'; + + fgets(s, 1024, fp); + if ((s == NULL) || (s[0] == '\0')) return NULL; + + if (s[0] != '#') s[strlen(s) - 1] = '\0'; + + out = copyString(s); + return out; +} + +/* USERS */ + +static void +LI_files_free_user() +{ + if (_pw.pw_name != NULL) free(_pw.pw_name); + if (_pw.pw_passwd != NULL) free(_pw.pw_passwd); + if (_pw.pw_class != NULL) free(_pw.pw_class); + if (_pw.pw_gecos != NULL) free(_pw.pw_gecos); + if (_pw.pw_dir != NULL) free(_pw.pw_dir); + if (_pw.pw_shell != NULL) free(_pw.pw_shell); + + _pw.pw_name = NULL; + _pw.pw_passwd = NULL; + _pw.pw_class = NULL; + _pw.pw_gecos = NULL; + _pw.pw_dir = NULL; + _pw.pw_shell = NULL; +} + +static struct passwd * +LI_files_parse_user(char *data) { char **tokens; int ntokens; @@ -234,13 +266,13 @@ parseUser(char *data) tokens = tokenize(data, ":"); ntokens = listLength(tokens); if (( _pwFileFormat && (ntokens != 10)) || - (!_pwFileFormat && (ntokens != 7))) + (!_pwFileFormat && (ntokens != 7))) { freeList(tokens); return NULL; } - free_pw(); + LI_files_free_user(); _pw.pw_name = tokens[0]; _pw.pw_passwd = tokens[1]; @@ -275,32 +307,79 @@ parseUser(char *data) return &_pw; } -static char * -getLine(FILE *fp) +static struct passwd * +LI_files_getpw(const char *name, uid_t uid, int which) { - char s[1024]; - char *out; + char *line; + struct passwd *pw; - s[0] = '\0'; + if (_pfp == NULL) LI_files_setpwent(); + if (_pfp == NULL) return NULL; - fgets(s, 1024, fp); - if (s == NULL || s[0] == '\0') return NULL; + if (which != _PWENT_) rewind(_pfp); - if (s[0] != '#') s[strlen(s) - 1] = '\0'; + forever + { + line = getLine(_pfp); + if (line == NULL) break; - out = copyString(s); - return out; + if (line[0] == '#') + { + free(line); + line = NULL; + continue; + } + + pw = LI_files_parse_user(line); + free(line); + line = NULL; + + if (pw == NULL) continue; + + if (which == _PWENT_) return pw; + + if (((which == _PWNAM_) && (!strcmp(name, pw->pw_name))) || ((which == _PWUID_) && (uid == pw->pw_uid))) + { + fclose(_pfp); + _pfp = NULL; + return pw; + } + } + + fclose(_pfp); + _pfp = NULL; + + return NULL; +} + +/* "Public" */ + +__private_extern__ struct passwd * +LI_files_getpwent() +{ + return LI_files_getpw(NULL, 0, _PWENT_); +} + +__private_extern__ struct passwd * +LI_files_getpwnam(const char *name) +{ + return LI_files_getpw(name, 0, _PWNAM_); +} + +__private_extern__ struct passwd * +LI_files_getpwuid(uid_t uid) +{ + return LI_files_getpw(NULL, uid, _PWUID_); } int setpassent(int stayopen) { - _pwStayOpen = stayopen; - return(1); + return 1; } -int -setpwent() +__private_extern__ void +LI_files_setpwent() { if (_pfp == NULL) { @@ -314,20 +393,14 @@ setpwent() pwFile = _PATH_PASSWD; _pwFileFormat = 0; } + _pfp = fopen(pwFile, "r"); - if (_pfp == NULL) - { - perror(pwFile); - return(0); - } } else rewind(_pfp); - _pwStayOpen = 0; - return(1); } -void -endpwent() +__private_extern__ void +LI_files_endpwent() { if (_pfp != NULL) { @@ -336,20 +409,110 @@ endpwent() } } -static struct passwd * -getpw(const char *nam, uid_t uid, int which) +/* HOSTS */ + +static void +LI_files_free_host() { - char *line; - struct passwd *pw; + int i; + + if (_h.h_name != NULL) free(_h.h_name); - if (which != 0) + if (_h.h_aliases != NULL) { - if (setpwent() == 0) return NULL; + for (i = 0; _h.h_aliases[i] != NULL; i++) free(_h.h_aliases[i]); + free(_h.h_aliases); } + 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); + } + + _h.h_name = NULL; + _h.h_aliases = NULL; + _h.h_addrtype = 0; + _h.h_length = 0; + _h.h_addr_list = NULL; +} + +static struct hostent * +LI_files_parse_host(char *data) +{ + char **tokens, *addrstr; + int i, ntokens, af; + struct in_addr a4; + struct in6_addr a6; + + if (data == NULL) return NULL; + + tokens = tokenize(data, " "); + ntokens = listLength(tokens); + if (ntokens < 2) + { + freeList(tokens); + return NULL; + } + + LI_files_free_host(); + + af = AF_UNSPEC; + if (inet_pton(AF_INET, tokens[0], &a4) == 1) af = AF_INET; + else if (inet_pton(AF_INET6, tokens[0], &a6) == 1) af = AF_INET6; + + if (af == AF_UNSPEC) + { + freeList(tokens); + return NULL; + } + + addrstr = tokens[0]; + + _h.h_addrtype = af; + if (af == AF_INET) + { + _h.h_length = sizeof(struct in_addr); + _h.h_addr_list = (char **)calloc(2, sizeof(char *)); + _h.h_addr_list[0] = (char *)calloc(1, _h.h_length); + memcpy(_h.h_addr_list[0], &a4, _h.h_length); + } + else + { + _h.h_length = sizeof(struct in6_addr); + _h.h_addr_list = (char **)calloc(2, sizeof(char *)); + _h.h_addr_list[0] = (char *)calloc(1, _h.h_length); + memcpy(_h.h_addr_list[0], &a6, _h.h_length); + } + + _h.h_name = tokens[1]; + + _h.h_aliases = (char **)calloc(ntokens - 1, sizeof(char *)); + for (i = 2; i < ntokens; i++) _h.h_aliases[i-2] = tokens[i]; + + free(addrstr); + free(tokens); + + return &_h; +} + +static struct hostent * +LI_files_get_host(const char *name, const void *addr, int af, int which) +{ + char *line; + struct hostent *h; + int i, got_host; + + if ((which == _HADDR_) && (addr == NULL)) return NULL; + + if (_hfp == NULL) _hfp = fopen(_PATH_HOSTS, "r"); + if (_hfp == NULL) return NULL; + + if (which != _HENT_) rewind(_hfp); + forever { - line = getLine(_pfp); + line = getLine(_hfp); if (line == NULL) break; if (line[0] == '#') @@ -359,42 +522,84 @@ getpw(const char *nam, uid_t uid, int which) continue; } - pw = parseUser(line); + h = LI_files_parse_host(line); free(line); line = NULL; - if ((pw == NULL) || (which == _PWENT_)) + if (h == NULL) continue; + + if (which == _HENT_) return h; + + got_host = 0; + + if ((which == _HNAM_) && (af == h->h_addrtype)) { - if (_pwStayOpen == 0) endpwent(); - return pw; + if (!strcmp(name, h->h_name)) got_host = 1; + else if (h->h_aliases != NULL) + { + for (i = 0; (h->h_aliases[i] != NULL) && (got_host == 0); i++) + if (!strcmp(name, h->h_aliases[i])) got_host = 1; + } } - if (((which == _PWNAM_) && (!strcmp(nam, pw->pw_name))) || - ((which == _PWUID_) && (uid == pw->pw_uid))) + if ((which == _HADDR_) && (h->h_addrtype == af)) { - if (_pwStayOpen == 0) endpwent(); - return pw; + for (i = 0; (h->h_addr_list[i] != NULL) && (got_host == 0); i++) + if (memcmp(addr, h->h_addr_list[i], h->h_length) == 0) got_host = 1; + } + + if (got_host == 1) + { + fclose(_hfp); + _hfp = NULL; + return h; } } - if (_pwStayOpen == 0) endpwent(); + fclose(_hfp); + _hfp = NULL; + + return NULL; +} + +/* "Public" */ + +__private_extern__ struct hostent * +LI_files_gethostbyname(const char *name) +{ + return LI_files_get_host(name, NULL, AF_INET, _HNAM_); +} + +__private_extern__ struct hostent * +LI_files_gethostbyname2(const char *name, int af) +{ + return LI_files_get_host(name, NULL, af, _HNAM_); +} + +__private_extern__ struct hostent * +LI_files_gethostbyaddr(const void *addr, socklen_t len, int type) +{ + if ((type == AF_INET) || (type == AF_INET6)) return LI_files_get_host(NULL, addr, type, _HADDR_); return NULL; } -struct passwd * -getpwent() +__private_extern__ struct hostent * +LI_files_gethostent() { - return getpw(NULL, 0, _PWENT_); + return LI_files_get_host(NULL, NULL, AF_UNSPEC, _HENT_); } -struct passwd * -getpwnam(const char *nam) +__private_extern__ void +LI_files_sethostent(int stayopen) { - return getpw(nam, 0, _PWNAM_); } -struct passwd * -getpwuid(uid_t uid) +__private_extern__ void +LI_files_endhostent() { - return getpw(NULL, uid, _PWUID_); + if (_hfp != NULL) + { + fclose(_hfp); + _hfp = NULL; + } } diff --git a/gen.subproj/getservent.3 b/gen.subproj/getservent.3 index bcf5c23..79953ff 100644 --- a/gen.subproj/getservent.3 +++ b/gen.subproj/getservent.3 @@ -36,26 +36,38 @@ .Dt GETSERVENT 3 .Os .Sh NAME -.Nm getservent , -.Nm getservbyport , +.Nm endservent , .Nm getservbyname , -.Nm setservent , -.Nm endservent +.Nm getservbyport , +.Nm getservent , +.Nm setservent .Nd get service entry .Sh LIBRARY .Lb libc .Sh SYNOPSIS .Fd #include +.Ft void +.Fo endservent +.Fa void +.Fc .Ft struct servent * -.Fn getservent +.Fo getservbyname +.Fa "const char *name" +.Fa "const char *proto" +.Fc .Ft struct servent * -.Fn getservbyname "const char *name" "const char *proto" +.Fo getservbyport +.Fa "int port" +.Fa "const char *proto" +.Fc .Ft struct servent * -.Fn getservbyport "int port" "const char *proto" -.Ft void -.Fn setservent "int stayopen" +.Fo getservent +.Fa void +.Fc .Ft void -.Fn endservent void +.Fo setservent +.Fa "int stayopen" +.Fc .Sh DESCRIPTION The .Fn getservent , diff --git a/gen.subproj/if_indextoname.3 b/gen.subproj/if_indextoname.3 index 9327c12..5d550f3 100644 --- a/gen.subproj/if_indextoname.3 +++ b/gen.subproj/if_indextoname.3 @@ -36,10 +36,10 @@ .Dt IF_NAMETOINDEX 3 .Os .Sh NAME -.Nm if_nametoindex , +.Nm if_freenameindex , .Nm if_indextoname , .Nm if_nameindex , -.Nm if_freenameindex +.Nm if_nametoindex .Nd convert interface index to name, and vice versa .Sh LIBRARY .Lb libc @@ -47,14 +47,23 @@ .Fd #include .Fd #include .Fd #include -.Ft "unsigned int" -.Fn if_nametoindex "const char *ifname" +.Ft void +.Fo if_freenameindex +.Fa "struct if_nameindex *ptr" +.Fc .Ft "char *" -.Fn if_indextoname "unsigned int ifindex" "char *ifname" +.Fo if_indextoname +.Fa "unsigned ifindex" +.Fa "char *ifname" +.Fc .Ft "struct if_nameindex *" -.Fn if_nameindex "void" -.Ft "void" -.Fn if_freenameindex "struct if_nameindex *ptr" +.Fo if_nameindex +.Fa void +.Fc +.Ft "unsigned int" +.Fo if_nametoindex +.Fa "const char *ifname" +.Fc .Sh DESCRIPTION The functions map interface index to readable interface name (such as diff --git a/gen.subproj/inet_ntop.c b/gen.subproj/inet_ntop.c index d4f08ae..51f7050 100644 --- a/gen.subproj/inet_ntop.c +++ b/gen.subproj/inet_ntop.c @@ -5,31 +5,43 @@ #include #include #include +#include #include void __res_close() { } +#define MAX_V4_ADDR_LEN 16 #define MAX_V6_ADDR_LEN 64 static const char *hexchars = "0123456789abcdef"; const char * -inet_ntop6(const struct in6_addr *addr, char *dst, size_t size) +inet_ntop6(const struct in6_addr *addr, char *dst, socklen_t size) { char hexa[8][5], tmp[MAX_V6_ADDR_LEN]; int zr[8]; - size_t len; + socklen_t len; int32_t i, j, k, skip; uint8_t x8, hx8; uint16_t x16; struct in_addr a4; - - if (addr == NULL) return NULL; - + + if (addr == NULL) + { + errno = EAFNOSUPPORT; + return NULL; + } + + if (dst == NULL) + { + errno = ENOSPC; + return NULL; + } + memset(tmp, 0, MAX_V6_ADDR_LEN); - + /* check for mapped or compat addresses */ i = IN6_IS_ADDR_V4MAPPED(addr); j = IN6_IS_ADDR_V4COMPAT(addr); @@ -38,49 +50,54 @@ inet_ntop6(const struct in6_addr *addr, char *dst, size_t size) a4.s_addr = addr->__u6_addr.__u6_addr32[3]; sprintf(tmp, "::%s%s", (i != 0) ? "ffff:" : "", inet_ntoa(a4)); len = strlen(tmp) + 1; - if (len > size) return NULL; + if (len > size) + { + errno = ENOSPC; + return NULL; + } + memcpy(dst, tmp, len); return dst; } - + k = 0; for (i = 0; i < 16; i += 2) { j = 0; skip = 1; - + memset(hexa[k], 0, 5); - + x8 = addr->__u6_addr.__u6_addr8[i]; - + hx8 = x8 >> 4; if (hx8 != 0) { skip = 0; hexa[k][j++] = hexchars[hx8]; } - + hx8 = x8 & 0x0f; if ((skip == 0) || ((skip == 1) && (hx8 != 0))) { skip = 0; hexa[k][j++] = hexchars[hx8]; } - + x8 = addr->__u6_addr.__u6_addr8[i + 1]; - + hx8 = x8 >> 4; if ((skip == 0) || ((skip == 1) && (hx8 != 0))) { hexa[k][j++] = hexchars[hx8]; } - + hx8 = x8 & 0x0f; hexa[k][j++] = hexchars[hx8]; - + k++; } - + /* find runs of zeros for :: convention */ j = 0; for (i = 7; i >= 0; i--) @@ -91,7 +108,7 @@ inet_ntop6(const struct in6_addr *addr, char *dst, size_t size) else j = 0; zr[i] = j; } - + /* find longest run of zeros */ k = -1; j = 0; @@ -103,12 +120,12 @@ inet_ntop6(const struct in6_addr *addr, char *dst, size_t size) j = zr[i]; } } - + for(i = 0; i < 8; i++) { if (i != k) zr[i] = 0; } - + len = 0; for (i = 0; i < 8; i++) { @@ -127,41 +144,67 @@ inet_ntop6(const struct in6_addr *addr, char *dst, size_t size) /* trailing NULL */ len++; - if (len > size) return NULL; + if (len > size) + { + errno = ENOSPC; + return NULL; + } + memcpy(dst, tmp, len); return dst; } const char * -inet_ntop4(const struct in_addr *addr, char *buf, size_t len) +inet_ntop4(const struct in_addr *addr, char *dst, socklen_t size) { + char tmp[MAX_V4_ADDR_LEN], *p; const u_int8_t *ap = (u_int8_t *)&addr->s_addr; - int i; - char *bp=buf; - + int i, ql, len; + + if (addr == NULL) + { + errno = EAFNOSUPPORT; + return NULL; + } + + if (dst == NULL) + { + errno = ENOSPC; + return NULL; + } + + memset(tmp, 0, MAX_V4_ADDR_LEN); + + /* 3 dots, trailing nul */ + len = 4; + + p = tmp; + for (i = 0; i < 4; i++, ap++) { - if (bp >= buf + len - 1) - { - buf[len-1] = 0; - return buf; - } + snprintf(p, 4, "%d", *ap); + ql = strlen(p); + len += ql; + p += ql; + if (i < 3) *p++ = '.'; + } - sprintf(bp, "%d", *ap); - bp += strlen(bp); - if (i != 3) *bp++='.'; + if (len > size) + { + errno = ENOSPC; + return NULL; } - *bp = 0; - return buf; + memcpy(dst, tmp, len); + return dst; } const char * -inet_ntop(int af, const void *addr, char *buf, size_t len) +inet_ntop(int af, const void *addr, char *buf, socklen_t len) { - if(af==AF_INET6) - return inet_ntop6(addr, buf, len); - if(af==AF_INET) - return inet_ntop4(addr, buf, len); + if (af == AF_INET6) return inet_ntop6(addr, buf, len); + if (af == AF_INET) return inet_ntop4(addr, buf, len); + + errno = EAFNOSUPPORT; return NULL; } diff --git a/gen.subproj/inet_pton.c b/gen.subproj/inet_pton.c index e49eae4..e46a7a1 100644 --- a/gen.subproj/inet_pton.c +++ b/gen.subproj/inet_pton.c @@ -28,6 +28,7 @@ static char rcsid[] = "$Id: inet_pton.c,v 1.3 2003/04/10 18:53:29 majka Exp $"; #include #include #include +#include #include #include #include @@ -82,16 +83,20 @@ int inet_pton(int af, const char *src, void *dst) { int status; + unsigned short ifnum; char *p, *s; switch (af) { - case AF_INET: return (inet_pton4(src, dst)); + case AF_INET: + { + return (inet_pton4(src, dst)); + } #ifdef INET6 case AF_INET6: - /* Ignore trailing %xxx (interface specification) */ - + { + ifnum = 0; p = NULL; s = (char *)src; @@ -99,19 +104,39 @@ inet_pton(int af, const char *src, void *dst) if (p != NULL) { s = strdup(src); + if (s == NULL) + { + errno = ENOMEM; + return -1; + } + s[p - src] = '\0'; } status = inet_pton6(s, dst); if (p != NULL) free(s); - return status; + if (status != 1) return status; + + if ((p != NULL) && IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)dst)) + { + ifnum = if_nametoindex(++p); + ifnum = htons(ifnum); + ((struct in6_addr *)dst)->__u6_addr.__u6_addr16[1] = ifnum; + } + + return 1; + } #endif default: + { errno = EAFNOSUPPORT; return -1; + } } + /* NOTREACHED */ + return -1; } /* int @@ -125,23 +150,21 @@ inet_pton(int af, const char *src, void *dst) * Paul Vixie, 1996. */ static int -inet_pton4(src, dst) - const char *src; - u_char *dst; +inet_pton4(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; @@ -179,17 +202,15 @@ inet_pton4(src, dst) * Paul Vixie, 1996. */ static int -inet_pton6(src, dst) - const char *src; - u_char *dst; +inet_pton6(const char *src, u_char *dst) { static const char xdigits_l[] = "0123456789abcdef", - xdigits_u[] = "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; @@ -202,7 +223,7 @@ inet_pton6(src, dst) 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) { @@ -252,7 +273,7 @@ inet_pton6(src, dst) */ const int n = tp - colonp; int i; - + if (tp == endp) return (0); for (i = 1; i <= n; i++) { diff --git a/gen.subproj/initgroups.c b/gen.subproj/initgroups.c index 0ca077a..2cce689 100644 --- a/gen.subproj/initgroups.c +++ b/gen.subproj/initgroups.c @@ -66,6 +66,9 @@ static char sccsid[] = "@(#)initgroups.c 8.1 (Berkeley) 6/4/93"; #include #include +__private_extern__ struct passwd *LI_files_getpwnam(const char *name); + +/* this is _old_initgroups */ int initgroups(uname, agroup) const char *uname; @@ -75,7 +78,7 @@ initgroups(uname, agroup) struct passwd *pw; /* get the UID for this user */ - if ((pw = getpwnam(uname)) == NULL) + if ((pw = LI_files_getpwnam(uname)) == NULL) return(-1); /* fetch the initial (advisory) group list */ diff --git a/gen.subproj/printerdb.c b/gen.subproj/printerdb.c index c1ec9fe..26bde62 100644 --- a/gen.subproj/printerdb.c +++ b/gen.subproj/printerdb.c @@ -27,16 +27,9 @@ */ #include #include +#include #include -#define strdup(x) strcpy(malloc(strlen(x) + 1), x) - -extern size_t strlen(const 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); - static FILE *pf; static char *getline(FILE *); static int emptyfield(char *); diff --git a/lookup.subproj/DSlibinfoMIG.defs b/lookup.subproj/DSlibinfoMIG.defs new file mode 100644 index 0000000..14ebc7e --- /dev/null +++ b/lookup.subproj/DSlibinfoMIG.defs @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * 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 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + * @header DSLookupMIG.defs + */ + +/* + * Warning! + * Do not re-order this file as it will cause MIG API number + * changes. Always add to the end of the file for new defs. + */ + +subsystem DSlibinfoMIG 50000; + +userprefix libinfoDSmig_; +serverprefix libinfoDSmig_do_; + +import ; + +#include +#include + +import ; + +type proc_name_t = c_string [* : 256]; +type inline_data_t = array [* : 16384] of char; + +routine GetProcedureNumber +( + server : mach_port_t; + name : proc_name_t; + out procno : int32_t; + ServerAuditToken bsmtoken : audit_token_t; + UserSecToken usertoken : security_token_t +); + +routine Query +( + server : mach_port_t; + proc : int32_t; + request : inline_data_t; + out reply : inline_data_t; + out ooreply : pointer_t, Dealloc; + ServerAuditToken bsmtoken : audit_token_t; + UserSecToken usertoken : security_token_t +); + +simpleroutine Query_async +( + server : mach_port_t; + replyToPort : mach_port_make_send_once_t; + proc : int32_t; + request : inline_data_t; + callbackAddr : mach_vm_address_t; + ServerAuditToken bsmtoken : audit_token_t +); diff --git a/lookup.subproj/DSlibinfoMIGAsyncReply.defs b/lookup.subproj/DSlibinfoMIGAsyncReply.defs new file mode 100644 index 0000000..4524a8e --- /dev/null +++ b/lookup.subproj/DSlibinfoMIGAsyncReply.defs @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * 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 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + * @header DSLookupMIGAsyncReply.defs + */ + +/* + * Warning! + * Do not re-order this file as it will cause MIG API number + * changes. Always add to the end of the file for new defs. + */ + +subsystem DSlibinfoMIGAsyncReply 50050; + +userprefix libinfoDSmig_; +serverprefix libinfoDSmig_do_; + +import ; + +#include +#include + +import ; + +type inline_data_t = array [* : 16384] of char; + +simpleroutine Response_async +( + server : mach_port_move_send_once_t; + reply : inline_data_t; + ooreply : pointer_t, Dealloc; + callbackAddr : mach_vm_address_t; + ServerSecToken servertoken : security_token_t +); diff --git a/lookup.subproj/DSlibinfoMIG_types.h b/lookup.subproj/DSlibinfoMIG_types.h new file mode 100644 index 0000000..f6e0350 --- /dev/null +++ b/lookup.subproj/DSlibinfoMIG_types.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * 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 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/*! + * @header DSlibinfoMIG_types.h + */ + +#ifndef __DSLIBINFOMIG_TYPES_H__ +#define __DSLIBINFOMIG_TYPES_H__ + +#ifndef kDSStdMachDSLookupPortName +#define kDSStdMachDSLookupPortName "com.apple.system.DirectoryService.libinfo_v1" +#endif + +#define MAX_MIG_INLINE_DATA 16384 + +typedef char *inline_data_t; +typedef char *proc_name_t; + +struct sLibinfoRequest +{ + mach_port_t fReplyPort; + int32_t fProcedure; + char *fBuffer; + int32_t fBufferLen; + mach_vm_address_t fCallbackAddr; + audit_token_t fToken; +}; + +extern boolean_t DSlibinfoMIGAsyncReply_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + +#endif /* __DSLIBINFOMIG_TYPES_H__ */ diff --git a/lookup.subproj/Makefile b/lookup.subproj/Makefile index 32f6ba8..4085a6a 100644 --- a/lookup.subproj/Makefile +++ b/lookup.subproj/Makefile @@ -12,15 +12,17 @@ NAME = lookup PROJECTVERSION = 2.8 PROJECT_TYPE = Component -HFILES = aliasdb.h bootparams.h lookup_types.h lu_overrides.h\ - lu_host.h lu_utils.h netdb.h netdb_async.h netgr.h printerdb.h +HFILES = aliasdb.h bootparams.h kvbuf.h lookup_types.h lu_overrides.h\ + lu_host.h lu_utils.h netdb.h netdb_async.h printerdb.h CFILES = getaddrinfo.c lu_alias.c lu_bootp.c lu_bootparam.c lu_fstab.c\ lu_group.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 + lu_printer.c lu_protocol.c lu_rpc.c lu_service.c lu_user.c lu_utils.c -OTHERSRCS = Makefile.preamble Makefile Makefile.postamble getaddrinfo.3\ - getnameinfo.3 lookup.defs _lu_types.x +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble\ + bootparams.5 gai_strerror.3 getaddrinfo.3 getfsent.3 getgrent.3 getgrouplist.3\ + getnameinfo.3 getnetgrent.3 getpwent.3 initgroups.3\ + DSlibinfoMIG_types.h DSlibinfoMIG.defs DSlibinfoMIGAsyncReply.defs lookup.defs _lu_types.x MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles CODE_GEN_STYLE = DYNAMIC diff --git a/lookup.subproj/Makefile.postamble b/lookup.subproj/Makefile.postamble index f4013b1..a5404b3 100644 --- a/lookup.subproj/Makefile.postamble +++ b/lookup.subproj/Makefile.postamble @@ -1,10 +1,10 @@ %_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) +private_hdrs: $(DSTROOT)$(PRIVATE_HDR_INSTALLDIR)$(PRIVATE_HEADER_DIR_SUFFIX) + $(SILENT) $(FASTCP) $(PRIVATE_HDRS) $(DSTROOT)$(PRIVATE_HDR_INSTALLDIR)$(PRIVATE_HEADER_DIR_SUFFIX) -$(DSTROOT)$(PRIVATE_HDR_INSTALLDIR)$(ASYNC_HEADER_DIR_SUFFIX): +$(DSTROOT)$(PRIVATE_HDR_INSTALLDIR)$(PRIVATE_HEADER_DIR_SUFFIX): $(MKDIRS) $@ netinfo_hdrs: $(DSTROOT)$(PRIVATE_HDR_INSTALLDIR)$(NETINFO_HEADER_DIR_SUFFIX) @@ -15,7 +15,38 @@ $(DSTROOT)$(PRIVATE_HDR_INSTALLDIR)$(NETINFO_HEADER_DIR_SUFFIX): install-man-page: mkdir -p "$(DSTROOT)/usr/share/man/man3" + install -c -m 644 gai_strerror.3 "$(DSTROOT)/usr/share/man/man3" install -c -m 644 getaddrinfo.3 "$(DSTROOT)/usr/share/man/man3" - install -c -m 644 getnameinfo.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 getfsent.3 "$(DSTROOT)/usr/share/man/man3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getfsent.3" "$(DSTROOT)/usr/share/man/man3/endfsent.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getfsent.3" "$(DSTROOT)/usr/share/man/man3/getfsfile.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getfsent.3" "$(DSTROOT)/usr/share/man/man3/getfsspec.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getfsent.3" "$(DSTROOT)/usr/share/man/man3/getfstype.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getfsent.3" "$(DSTROOT)/usr/share/man/man3/setfsent.3" + install -c -m 644 getgrent.3 "$(DSTROOT)/usr/share/man/man3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getgrent.3" "$(DSTROOT)/usr/share/man/man3/endgrent.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getgrent.3" "$(DSTROOT)/usr/share/man/man3/getgrgid.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getgrent.3" "$(DSTROOT)/usr/share/man/man3/getgrgid_r.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getgrent.3" "$(DSTROOT)/usr/share/man/man3/getgrnam.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getgrent.3" "$(DSTROOT)/usr/share/man/man3/getgrnam_r.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getgrent.3" "$(DSTROOT)/usr/share/man/man3/setgrent.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getgrent.3" "$(DSTROOT)/usr/share/man/man3/setgroupent.3" + install -c -m 644 getgrouplist.3 "$(DSTROOT)/usr/share/man/man3" + install -c -m 644 getnameinfo.3 "$(DSTROOT)/usr/share/man/man3" + install -c -m 644 getnetgrent.3 "$(DSTROOT)/usr/share/man/man3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getnetgrent.3" "$(DSTROOT)/usr/share/man/man3/endnetgrent.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getnetgrent.3" "$(DSTROOT)/usr/share/man/man3/innetgr.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getnetgrent.3" "$(DSTROOT)/usr/share/man/man3/setnetgrent.3" + install -c -m 644 getpwent.3 "$(DSTROOT)/usr/share/man/man3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getpwent.3" "$(DSTROOT)/usr/share/man/man3/endpwent.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getpwent.3" "$(DSTROOT)/usr/share/man/man3/getpwnam.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getpwent.3" "$(DSTROOT)/usr/share/man/man3/getpwnam_r.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getpwent.3" "$(DSTROOT)/usr/share/man/man3/getpwuid.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getpwent.3" "$(DSTROOT)/usr/share/man/man3/getpwuid_r.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getpwent.3" "$(DSTROOT)/usr/share/man/man3/setpassent.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getpwent.3" "$(DSTROOT)/usr/share/man/man3/setpwent.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getpwent.3" "$(DSTROOT)/usr/share/man/man3/setpwfile.3" + install -c -m 644 initgroups.3 "$(DSTROOT)/usr/share/man/man3" + mkdir -p "$(DSTROOT)/usr/share/man/man5" + install -c -m 644 bootparams.5 "$(DSTROOT)/usr/share/man/man5" diff --git a/lookup.subproj/Makefile.preamble b/lookup.subproj/Makefile.preamble index 0f382d0..0300b74 100644 --- a/lookup.subproj/Makefile.preamble +++ b/lookup.subproj/Makefile.preamble @@ -1,15 +1,16 @@ 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) $(ASYNC_HDRS) $(NETINFO_HDRS) -AFTER_INSTALLHDRS += async_hdrs netinfo_hdrs +OTHER_OFILES = DSlibinfoMIGUser.o DSlibinfoMIGAsyncReplyServer.o +AFTER_PREBUILD = _lu_types.h DSlibinfoMIGUser.c DSlibinfoMIGAsyncReplyServer.c +PRIVATE_HDRS = kvbuf.h netdb_async.h +NETINFO_HDRS = DSlibinfoMIG.h DSlibinfoMIGAsyncReply.h lookup.h _lu_types.h lookup_types.h lookup.defs _lu_types.x +BEFORE_INSTALLHDRS += $(SFILE_DIR) $(PRIVATE_HDRS) $(NETINFO_HDRS) +AFTER_INSTALLHDRS += private_hdrs netinfo_hdrs PUBLIC_HEADER_DIR_SUFFIX = PRIVATE_HEADER_DIR = /usr/local/include -ASYNC_HEADER_DIR_SUFFIX = / +PRIVATE_HEADER_DIR_SUFFIX = / NETINFO_HEADER_DIR_SUFFIX = /netinfo AFTER_POSTINSTALL += install-man-page +OTHER_CFLAGS += -D__MigTypeCheck=1 -D__DARWIN_NON_CANCELABLE=1 # for building 64-bit # Libinfo need to build with gcc-3.5 and 3-way fat diff --git a/lookup.subproj/PB.project b/lookup.subproj/PB.project index 19077d8..f54271c 100644 --- a/lookup.subproj/PB.project +++ b/lookup.subproj/PB.project @@ -4,13 +4,13 @@ H_FILES = ( aliasdb.h, bootparams.h, + kvbuf.h, lookup_types.h, lu_overrides.h, lu_host.h, lu_utils.h, netdb.h, netdb_async.h, - netgr.h, printerdb.h ); OTHER_LINKED = ( diff --git a/lookup.subproj/bootparams.5 b/lookup.subproj/bootparams.5 new file mode 100644 index 0000000..d36d7ee --- /dev/null +++ b/lookup.subproj/bootparams.5 @@ -0,0 +1,39 @@ +.\" Copyright (c) 2006 Apple Computer +.\" 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. +.\" 4. Neither the name of Apple Computer 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 APPLE COMPUTER 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 December 12, 2006 +.Dt BOOTPARAMS 5 +.Os "Mac OS X" +.Sh NAME +.Nm bootparams +.Nd boot parameter database +.Sh SYNOPSIS +.Nm /etc/bootparams +.Sh DESCRIPTION +Mac OS X no longer supports boot paramters. +The /etc/bootparams file is unused. diff --git a/lookup.subproj/gai_strerror.3 b/lookup.subproj/gai_strerror.3 new file mode 100644 index 0000000..5ed9474 --- /dev/null +++ b/lookup.subproj/gai_strerror.3 @@ -0,0 +1,102 @@ +.\" $KAME: gai_strerror.3,v 1.1 2005/01/05 03:04:47 itojun Exp $ +.\" $OpenBSD: gai_strerror.3,v 1.4 2004/12/20 23:04:53 millert Exp $ +.\" +.\" Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2000, 2001 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 ISC DISCLAIMS ALL WARRANTIES WITH +.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +.\" AND FITNESS. IN NO EVENT SHALL ISC 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. +.\" +.\" $FreeBSD: src/lib/libc/net/gai_strerror.3,v 1.3 2005/06/16 19:01:06 ru Exp $ +.\" +.Dd December 20, 2004 +.Dt GAI_STRERROR 3 +.Os +.Sh NAME +.Nm gai_strerror +.Nd get error message string from EAI_xxx error code +.Sh SYNOPSIS +.In sys/types.h +.In sys/socket.h +.In netdb.h +.Ft "const char *" +.Fo gai_strerror +.Fa "int ecode" +.Fc +.Sh DESCRIPTION +The +.Fn gai_strerror +function returns an error message string corresponding to the error code +returned by +.Xr getaddrinfo 3 +or +.Xr getnameinfo 3 . +.Pp +The following error codes and their meaning are defined in +.In netdb.h : +.Pp +.Bl -tag -width ".Dv EAI_BADFLAGS" -offset indent -compact +.It Dv EAI_AGAIN +temporary failure in name resolution +.It Dv EAI_BADFLAGS +invalid value for +.Fa ai_flags +.It Dv EAI_BADHINTS +invalid value for +.Fa hints +.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_NONAME +.Fa hostname +or +.Fa servname +not provided, or not known +.It Dv EAI_PROTOCOL +resolved protocol is unknown +.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 +.Sh RETURN VALUES +The +.Fn gai_strerror +function +returns a pointer to the error message string corresponding to +.Fa ecode . +If +.Fa ecode +is out of range, an implementation-specific error message string is returned. +.Sh LEGACY SYNOPSIS +.Fd #include +.Fd #include +.Fd #include +.Pp +The include files +.In sys/types.h +and +.In sys/socket.h +are necessary. +.Sh SEE ALSO +.Xr getaddrinfo 3 , +.Xr getnameinfo 3 diff --git a/lookup.subproj/getaddrinfo.3 b/lookup.subproj/getaddrinfo.3 index 5ab76fb..b03fa0c 100644 --- a/lookup.subproj/getaddrinfo.3 +++ b/lookup.subproj/getaddrinfo.3 @@ -21,25 +21,30 @@ .Dt GETADDRINFO 3 .Os .Sh NAME -.Nm getaddrinfo , -.Nm freeaddrinfo +.Nm freeaddrinfo , +.Nm getaddrinfo .Nd socket address structure to host and service name .Sh SYNOPSIS -.Fd #include .Fd #include .Fd #include -.Ft int -.Fn getaddrinfo "const char *hostname" "const char *servname" \ - "const struct addrinfo *hints" "struct addrinfo **res" .Ft void -.Fn freeaddrinfo "struct addrinfo *ai" +.Fo freeaddrinfo +.Fa "struct addrinfo *ai" +.Fc +.Ft int +.Fo getaddrinfo +.Fa "const char *restrict nodename" +.Fa "const char *restrict servname" +.Fa "const struct addrinfo *restrict hints" +.Fa "struct addrinfo **restrict res" +.Fc .Sh DESCRIPTION The .Fn getaddrinfo function is used to get a list of .Tn IP addresses and port numbers for host -.Fa hostname +.Fa nodename and service .Fa servname . It is a replacement for and provides more flexibility than the @@ -49,12 +54,12 @@ and functions. .Pp The -.Fa hostname +.Fa nodename and .Fa servname arguments are either pointers to NUL-terminated strings or the null pointer. An acceptable value for -.Fa hostname +.Fa nodename is either a valid host name or a numeric host address string consisting of a dotted decimal IPv4 address or an IPv6 address. The @@ -62,7 +67,7 @@ The is either a decimal port number or a service name listed in .Xr services 5 . At least one of -.Fa hostname +.Fa nodename and .Fa servname must be non-null. @@ -136,7 +141,7 @@ structure returned. If the .Dv AI_NUMERICHOST bit is set, it indicates that -.Fa hostname +.Fa nodename should be treated as a numeric string defining an IPv4 or IPv6 address and no name resolution should be attempted. .It Dv AI_PASSIVE @@ -146,7 +151,7 @@ bit is set it indicates that the returned socket address structure is intended for use in a call to .Xr bind 2 . In this case, if the -.Fa hostname +.Fa nodename argument is the null pointer, then the IP address portion of the socket address structure will be set to .Dv INADDR_ANY @@ -169,7 +174,7 @@ The .Tn IP address portion of the socket address structure will be set to the loopback address if -.Fa hostname +.Fa nodename is the null pointer and .Dv AI_PASSIVE is not set. @@ -379,6 +384,14 @@ if (nsock == 0) { } freeaddrinfo(res0); .Ed +.Sh LEGACY SYNOPSIS +.Fd #include +.Fd #include +.Fd #include +.Pp +The include file +.In sys/types.h +is necessary. .Sh SEE ALSO .Xr bind 2 , .Xr connect 2 , @@ -429,7 +442,3 @@ function is defined by the draft specification and documented in .Dv "RFC 3493" , .Dq Basic Socket Interface Extensions for IPv6 . -.Sh BUGS -The implementation of -.Fn getaddrinfo -is not thread-safe. diff --git a/lookup.subproj/getaddrinfo.c b/lookup.subproj/getaddrinfo.c index cde6136..fc9482f 100644 --- a/lookup.subproj/getaddrinfo.c +++ b/lookup.subproj/getaddrinfo.c @@ -32,8 +32,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -46,17 +46,11 @@ #define SOCK_UNSPEC 0 #define IPPROTO_UNSPEC 0 -#define LONG_STRING_LENGTH 8192 -#define _LU_MAXLUSTRLEN 256 -#define LU_QBUF_SIZE 8192 - #define MAX_LOOKUP_ATTEMPTS 10 #define INET_NTOP_AF_INET_OFFSET 4 #define INET_NTOP_AF_INET6_OFFSET 8 -extern mach_port_t _lookupd_port(); - static int gai_proc = -1; static int gni_proc = -1; @@ -220,18 +214,6 @@ append_addrinfo(struct addrinfo **l, struct addrinfo *a) } } -static int -encode_kv(XDR *x, const char *k, const char *v) -{ - int32_t n = 1; - - if (!xdr_string(x, (char **)&k, _LU_MAXLUSTRLEN)) return 1; - if (!xdr_int(x, &n)) return 1; - if (!xdr_string(x, (char **)&v, _LU_MAXLUSTRLEN)) return 1; - - return 0; -} - void freeaddrinfo(struct addrinfo *a) { @@ -248,7 +230,7 @@ freeaddrinfo(struct addrinfo *a) } static struct addrinfo * -new_addrinfo_v4(int32_t flags, int32_t sock, int32_t proto, uint16_t port, struct in_addr addr, uint32_t iface, char *cname) +new_addrinfo_v4(int32_t flags, int32_t sock, int32_t proto, uint16_t port, struct in_addr addr, uint32_t iface, const char *cname) { struct addrinfo *a; struct sockaddr_in *sa; @@ -294,11 +276,12 @@ new_addrinfo_v4(int32_t flags, int32_t sock, int32_t proto, uint16_t port, struc } static struct addrinfo * -new_addrinfo_v6(int32_t flags, int32_t sock, int32_t proto, uint16_t port, struct in6_addr addr, uint32_t scopeid, char *cname) +new_addrinfo_v6(int32_t flags, int32_t sock, int32_t proto, uint16_t port, struct in6_addr addr, uint16_t scopeid, const char *cname) { struct addrinfo *a; struct sockaddr_in6 *sa; int32_t len; + uint16_t esid; a = (struct addrinfo *)calloc(1, sizeof(struct addrinfo)); if (a == NULL) return NULL; @@ -323,9 +306,23 @@ new_addrinfo_v6(int32_t flags, int32_t sock, int32_t proto, uint16_t port, struc sa->sin6_family = PF_INET6; sa->sin6_port = htons(port); sa->sin6_addr = addr; + + /* sin6_scope_id is in host byte order */ sa->sin6_scope_id = scopeid; + a->ai_addr = (struct sockaddr *)sa; + if (IN6_IS_ADDR_LINKLOCAL(&sa->sin6_addr)) + { + /* check for embedded scopeid */ + esid = ntohs(sa->sin6_addr.__u6_addr.__u6_addr16[1]); + if (esid != 0) + { + sa->sin6_addr.__u6_addr.__u6_addr16[1] = 0; + if (scopeid == 0) sa->sin6_scope_id = esid; + } + } + if (cname != NULL) { len = strlen(cname) + 1; @@ -337,7 +334,8 @@ new_addrinfo_v6(int32_t flags, int32_t sock, int32_t proto, uint16_t port, struc } /* - * getaddrinfo support in lookupd + * getaddrinfo + * * Input dict may contain the following * * name: nodename @@ -364,13 +362,12 @@ new_addrinfo_v6(int32_t flags, int32_t sock, int32_t proto, uint16_t port, struc */ static struct addrinfo * -gai_lookupd_process_dictionary(XDR *inxdr) +gai_extract(kvarray_t *in) { - int32_t i, nkeys, nvals; - char *key, *val; - uint32_t flags, family, socktype, protocol, longport, scopeid; - uint16_t port; - char *addr, *canonname; + uint32_t d, k, kcount; + uint32_t flags, family, socktype, protocol, port32; + uint16_t port, scopeid; + const char *addr, *canonname; struct addrinfo *a; struct in_addr a4; struct in6_addr a6; @@ -384,69 +381,61 @@ gai_lookupd_process_dictionary(XDR *inxdr) addr = NULL; canonname = NULL; - if (!xdr_int(inxdr, &nkeys)) return NULL; + if (in == NULL) return NULL; - for (i = 0; i < nkeys; i++) - { - key = NULL; - val = NULL; + d = in->curr; + in->curr++; - if (!xdr_string(inxdr, &key, LONG_STRING_LENGTH)) return NULL; - if (!xdr_int(inxdr, &nvals)) - { - free(key); - return NULL; - } + if (d >= in->count) return NULL; + + kcount = in->dict[d].kcount; - if (nvals != 1) + for (k = 0; k < kcount; k++) + { + if (!strcmp(in->dict[d].key[k], "gai_flags")) { - free(key); - return NULL; + if (in->dict[d].vcount[k] == 0) continue; + flags = atoi(in->dict[d].val[k][0]); } - - if (!xdr_string(inxdr, &val, LONG_STRING_LENGTH)) + else if (!strcmp(in->dict[d].key[k], "gai_family")) { - free(key); - return NULL; + if (in->dict[d].vcount[k] == 0) continue; + family = atoi(in->dict[d].val[k][0]); } - - if (!strcmp(key, "flags")) + else if (!strcmp(in->dict[d].key[k], "gai_socktype")) { - flags = atoi(val); + if (in->dict[d].vcount[k] == 0) continue; + socktype = atoi(in->dict[d].val[k][0]); } - else if (!strcmp(key, "family")) + else if (!strcmp(in->dict[d].key[k], "gai_protocol")) { - family = atoi(val); + if (in->dict[d].vcount[k] == 0) continue; + protocol = atoi(in->dict[d].val[k][0]); } - else if (!strcmp(key, "socktype")) + else if (!strcmp(in->dict[d].key[k], "gai_port")) { - socktype = atoi(val); + if (in->dict[d].vcount[k] == 0) continue; + port32 = atoi(in->dict[d].val[k][0]); + port = port32; } - else if (!strcmp(key, "protocol")) + else if (!strcmp(in->dict[d].key[k], "gai_scopeid")) { - protocol = atoi(val); + if (in->dict[d].vcount[k] == 0) continue; + scopeid = atoi(in->dict[d].val[k][0]); } - else if (!strcmp(key, "port")) + else if (!strcmp(in->dict[d].key[k], "gai_address")) { - longport = atoi(val); - port = longport; + if (in->dict[d].vcount[k] == 0) continue; + addr = in->dict[d].val[k][0]; } - else if (!strcmp(key, "scopeid")) + else if (!strcmp(in->dict[d].key[k], "gai_canonname")) { - scopeid = atoi(val); + if (in->dict[d].vcount[k] == 0) continue; + canonname = in->dict[d].val[k][0]; } - else if (!strcmp(key, "address")) addr = strdup(val); - else if (!strcmp(key, "canonname")) canonname = strdup(val); - free(key); - free(val); } - if (family == PF_UNSPEC) - { - if (addr != NULL) free(addr); - if (canonname != NULL) free(canonname); - return NULL; - } + if (family == PF_UNSPEC) return NULL; a = NULL; if (family == PF_INET) @@ -460,43 +449,38 @@ gai_lookupd_process_dictionary(XDR *inxdr) a = new_addrinfo_v6(flags, socktype, protocol, port, a6, scopeid, canonname); } - if (addr != NULL) free(addr); - if (canonname != NULL) free(canonname); - return a; } -static int -gai_make_query(const char *nodename, const char *servname, const struct addrinfo *hints, char *buf, uint32_t *len) +static kvbuf_t * +gai_make_query(const char *nodename, const char *servname, const struct addrinfo *hints) { - int32_t numerichost, family, proto, socktype, canonname, passive, parallel; - uint32_t na; - XDR outxdr; + int32_t flags, family, proto, socktype; + kvbuf_t *request; char str[64], *cname; - numerichost = 0; + flags = 0; family = PF_UNSPEC; proto = IPPROTO_UNSPEC; socktype = SOCK_UNSPEC; - canonname = 0; - passive = 0; - parallel = 0; cname = NULL; if (hints != NULL) { family = hints->ai_family; - if (hints->ai_flags & AI_NUMERICHOST) numerichost = 1; - if (hints->ai_flags & AI_CANONNAME) canonname = 1; - if (hints->ai_flags & AI_PASSIVE) passive = 1; - if (hints->ai_flags & AI_PARALLEL) parallel = 1; + if (hints->ai_flags & AI_NUMERICHOST) flags |= AI_NUMERICHOST; + if (hints->ai_flags & AI_CANONNAME) flags |= AI_CANONNAME; + if (hints->ai_flags & AI_PASSIVE) flags |= AI_PASSIVE; + if (hints->ai_flags & AI_PARALLEL) flags |= AI_PARALLEL; proto = hints->ai_protocol; + if (hints->ai_socktype == SOCK_DGRAM) { socktype = SOCK_DGRAM; proto = IPPROTO_UDP; } + if (hints->ai_socktype == SOCK_STREAM) { socktype = SOCK_STREAM; @@ -504,125 +488,53 @@ gai_make_query(const char *nodename, const char *servname, const struct addrinfo } } - xdrmem_create(&outxdr, buf, *len, XDR_ENCODE); - - /* Attribute count */ - na = 0; - if (nodename != NULL) na++; - if (servname != NULL) na++; - if (proto != IPPROTO_UNSPEC) na++; - if (socktype != SOCK_UNSPEC) na++; - if (family != PF_UNSPEC) na++; - if (canonname != 0) na++; - if (passive != 0) na++; - if (parallel != 0) na++; - if (numerichost != 0) na++; - - if (!xdr_int(&outxdr, (int32_t *)&na)) + request = kvbuf_new(); + if (request == NULL) { - xdr_destroy(&outxdr); - errno = EIO; - return EAI_SYSTEM; + errno = ENOMEM; + return NULL; } + kvbuf_add_dict(request); + if (nodename != NULL) { - if (encode_kv(&outxdr, "name", nodename) != 0) - { - xdr_destroy(&outxdr); - errno = EIO; - return EAI_SYSTEM; - } + kvbuf_add_key(request, "name"); + kvbuf_add_val(request, nodename); } if (servname != NULL) { - if (encode_kv(&outxdr, "service", servname) != 0) - { - xdr_destroy(&outxdr); - errno = EIO; - return EAI_SYSTEM; - } + kvbuf_add_key(request, "service"); + kvbuf_add_val(request, servname); } if (proto != IPPROTO_UNSPEC) { - snprintf(str, 64, "%u", proto); - if (encode_kv(&outxdr, "protocol", str) != 0) - { - xdr_destroy(&outxdr); - errno = EIO; - return EAI_SYSTEM; - } + snprintf(str, sizeof(str), "%u", proto); + kvbuf_add_key(request, "protocol"); + kvbuf_add_val(request, str); } if (socktype != SOCK_UNSPEC) { - snprintf(str, 64, "%u", socktype); - if (encode_kv(&outxdr, "socktype", str) != 0) - { - xdr_destroy(&outxdr); - errno = EIO; - return EAI_SYSTEM; - } + snprintf(str, sizeof(str), "%u", socktype); + kvbuf_add_key(request, "socktype"); + kvbuf_add_val(request, str); } if (family != PF_UNSPEC) { - snprintf(str, 64, "%u", family); - if (encode_kv(&outxdr, "family", str) != 0) - { - xdr_destroy(&outxdr); - errno = EIO; - return EAI_SYSTEM; - } + snprintf(str, sizeof(str), "%u", family); + kvbuf_add_key(request, "family"); + kvbuf_add_val(request, str); } - if (canonname != 0) - { - if (encode_kv(&outxdr, "canonname", "1") != 0) - { - xdr_destroy(&outxdr); - errno = EIO; - return EAI_SYSTEM; - } - } + snprintf(str, sizeof(str), "%u", flags); + kvbuf_add_key(request, "ai_flags"); + kvbuf_add_val(request, str); - if (passive != 0) - { - if (encode_kv(&outxdr, "passive", "1") != 0) - { - xdr_destroy(&outxdr); - errno = EIO; - return EAI_SYSTEM; - } - } - - if (parallel != 0) - { - if (encode_kv(&outxdr, "parallel", "1") != 0) - { - xdr_destroy(&outxdr); - errno = EIO; - return EAI_SYSTEM; - } - } - - if (numerichost != 0) - { - if (encode_kv(&outxdr, "numerichost", "1") != 0) - { - xdr_destroy(&outxdr); - errno = EIO; - return EAI_SYSTEM; - } - } - - *len = xdr_getpos(&outxdr); - - xdr_destroy(&outxdr); - - return 0; + return request; } static int32_t @@ -699,7 +611,7 @@ gai_trivial(struct in_addr *in4, struct in6_addr *in6, int16_t port, const struc } else { - return EAI_NODATA; + return EAI_NONAME; } proto = IPPROTO_UNSPEC; @@ -759,10 +671,11 @@ gai_trivial(struct in_addr *in4, struct in6_addr *in6, int16_t port, const struc return 0; } -int +static int gai_files(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res) { - int32_t i, status, numericserv, numerichost, family, proto, wantv4, wantv6; + int32_t i, status, numericserv, numerichost, family, proto, wantv4, wantv6, count; + uint16_t scopeid; int16_t port; struct servent *s; struct hostent *h; @@ -771,6 +684,9 @@ gai_files(const char *nodename, const char *servname, const struct addrinfo *hin struct in6_addr a6; struct addrinfo *a; + count = 0; + scopeid = 0; + numericserv = 0; if (servname != NULL) numericserv = is_a_number(servname); @@ -821,6 +737,11 @@ gai_files(const char *nodename, const char *servname, const struct addrinfo *hin { numerichost = 1; if (family == PF_UNSPEC) family = PF_INET6; + if ((IN6_IS_ADDR_LINKLOCAL(&a6)) && (a6.__u6_addr.__u6_addr16[1] != 0)) + { + scopeid = ntohs(a6.__u6_addr.__u6_addr16[1]); + a6.__u6_addr.__u6_addr16[1] = 0; + } } } } @@ -870,18 +791,21 @@ gai_files(const char *nodename, const char *servname, const struct addrinfo *hin { a = new_addrinfo_v4(0, SOCK_DGRAM, IPPROTO_UDP, port, a4, 0, NULL); append_addrinfo(res, a); + count++; } if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_TCP)) { a = new_addrinfo_v4(0, SOCK_STREAM, IPPROTO_TCP, port, a4, 0, NULL); append_addrinfo(res, a); + count++; } if (proto == IPPROTO_ICMP) { a = new_addrinfo_v4(0, SOCK_RAW, IPPROTO_ICMP, port, a4, 0, NULL); append_addrinfo(res, a); + count++; } } @@ -889,30 +813,34 @@ gai_files(const char *nodename, const char *servname, const struct addrinfo *hin { if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_UDP)) { - a = new_addrinfo_v6(0, SOCK_DGRAM, IPPROTO_UDP, port, a6, 0, NULL); + a = new_addrinfo_v6(0, SOCK_DGRAM, IPPROTO_UDP, port, a6, scopeid, NULL); append_addrinfo(res, a); + count++; } if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_TCP)) { - a = new_addrinfo_v6(0, SOCK_STREAM, IPPROTO_TCP, port, a6, 0, NULL); + a = new_addrinfo_v6(0, SOCK_STREAM, IPPROTO_TCP, port, a6, scopeid, NULL); append_addrinfo(res, a); + count++; } if (proto == IPPROTO_ICMPV6) { - a = new_addrinfo_v6(0, SOCK_RAW, IPPROTO_ICMPV6, port, a6, 0, NULL); + a = new_addrinfo_v6(0, SOCK_RAW, IPPROTO_ICMPV6, port, a6, scopeid, NULL); append_addrinfo(res, a); + count++; } } + if (count == 0) return EAI_AGAIN; return 0; } if (wantv4 == 1) { h = gethostbyname(nodename); - if (h == NULL) return 0; + if (h == NULL) return EAI_AGAIN; for (i = 0; h->h_addr_list[i] != 0; i++) { @@ -922,42 +850,65 @@ gai_files(const char *nodename, const char *servname, const struct addrinfo *hin { a = new_addrinfo_v4(0, SOCK_DGRAM, IPPROTO_UDP, port, a4, 0, NULL); append_addrinfo(res, a); + count++; } if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_TCP)) { a = new_addrinfo_v4(0, SOCK_STREAM, IPPROTO_TCP, port, a4, 0, NULL); append_addrinfo(res, a); + count++; } } } + if (wantv6 == 1) + { + h = gethostbyname2(nodename, AF_INET6); + if (h == NULL) return EAI_AGAIN; + + for (i = 0; h->h_addr_list[i] != 0; i++) + { + memmove(&(a6.__u6_addr.__u6_addr32[0]), h->h_addr_list[i], h->h_length); + + if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_UDP)) + { + a = new_addrinfo_v6(0, SOCK_DGRAM, IPPROTO_UDP, port, a6, 0, NULL); + append_addrinfo(res, a); + count++; + } + + if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_TCP)) + { + a = new_addrinfo_v6(0, SOCK_STREAM, IPPROTO_TCP, port, a6, 0, NULL); + append_addrinfo(res, a); + count++; + } + } + } + + if (count == 0) return EAI_AGAIN; return 0; } static int -gai_lookupd(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res) +ds_getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res) { - uint32_t n, i, qlen, rlen; - XDR inxdr; - char qbuf[LU_QBUF_SIZE]; - char *rbuf; + uint32_t i; + kvbuf_t *request; + kvarray_t *reply; char *cname; - mach_port_t server_port; kern_return_t status; struct addrinfo *a; - server_port = MACH_PORT_NULL; - if (_lu_running()) server_port = _lookupd_port(0); - if (server_port == MACH_PORT_NULL) + if (_ds_running() == 0) { - /* lookupd isn't available - fall back to the flat files */ return gai_files(nodename, servname, hints, res); } if (gai_proc < 0) { - status = _lookup_link(server_port, "getaddrinfo", &gai_proc); + status = LI_DSLookupGetProcedureNumber("getaddrinfo", &gai_proc); if (status != KERN_SUCCESS) { errno = ECONNREFUSED; @@ -965,40 +916,31 @@ gai_lookupd(const char *nodename, const char *servname, const struct addrinfo *h } } - qlen = LU_QBUF_SIZE; - - /* gai_make_query sets errno if it fails */ - i = gai_make_query(nodename, servname, hints, qbuf, &qlen); - if (i != 0) return EAI_SYSTEM; - - qlen /= BYTES_PER_XDR_UNIT; + request = gai_make_query(nodename, servname, hints); + if (request == NULL) return EAI_SYSTEM; - rbuf = NULL; + reply = NULL; + status = LI_DSLookupQuery(gai_proc, request, &reply); + kvbuf_free(request); - status = _lookup_all(server_port, gai_proc, (unit *)qbuf, qlen, &rbuf, &rlen); - if (status != KERN_SUCCESS) return EAI_NODATA; - - rlen *= BYTES_PER_XDR_UNIT; - - xdrmem_create(&inxdr, rbuf, rlen, XDR_DECODE); - - if (!xdr_int(&inxdr, (int32_t *)&n)) + if (status != KERN_SUCCESS) { - xdr_destroy(&inxdr); - errno = EIO; + errno = ECONNREFUSED; return EAI_SYSTEM; } + if (reply == NULL) return EAI_NONAME; + cname = NULL; - for (i = 0; i < n; i++) + for (i = 0; i < reply->count; i++) { - a = gai_lookupd_process_dictionary(&inxdr); + a = gai_extract(reply); + if (a == NULL) continue; if ((cname == NULL) && (a->ai_canonname != NULL)) cname = a->ai_canonname; append_addrinfo(res, a); } - xdr_destroy(&inxdr); - if (rbuf != NULL) vm_deallocate(mach_task_self(), (vm_address_t)rbuf, rlen); + kvarray_free(reply); if ((cname != NULL) && (res != NULL) && (res[0] != NULL) && (res[0]->ai_canonname == NULL)) { @@ -1104,11 +1046,11 @@ getaddrinfo(const char * __restrict nodename, const char * __restrict servname, if ((numerichost == 1) && (numericserv == 1)) return gai_trivial(p4, p6, port, hints, res); if ((numerichost == 1) && (servnull == 1)) return gai_trivial(p4, p6, 0, hints, res); - if (nodenull == 1) status = gai_lookupd(NULL, servname, hints, res); - else if (servnull == 1) status = gai_lookupd(nodename, NULL, hints, res); - else status = gai_lookupd(nodename, servname, hints, res); + if (nodenull == 1) status = ds_getaddrinfo(NULL, servname, hints, res); + else if (servnull == 1) status = ds_getaddrinfo(nodename, NULL, hints, res); + else status = ds_getaddrinfo(nodename, servname, hints, res); - if ((status == 0) && (*res == NULL)) status = EAI_NODATA; + if ((status == 0) && (*res == NULL)) status = EAI_NONAME; return status; } @@ -1117,9 +1059,7 @@ int32_t getaddrinfo_async_start(mach_port_t *p, const char *nodename, const char *servname, const struct addrinfo *hints, getaddrinfo_async_callback callback, void *context) { int32_t status; - uint32_t i, qlen; - char qbuf[LU_QBUF_SIZE]; - mach_port_t server_port; + kvbuf_t *request; *p = MACH_PORT_NULL; @@ -1128,17 +1068,9 @@ getaddrinfo_async_start(mach_port_t *p, const char *nodename, const char *servna status = gai_checkhints(hints); if (status != 0) return EAI_BADHINTS; - server_port = MACH_PORT_NULL; - if (_lu_running()) server_port = _lookupd_port(0); - if (server_port == MACH_PORT_NULL) - { - errno = ECONNREFUSED; - return EAI_SYSTEM; - } - if (gai_proc < 0) { - status = _lookup_link(server_port, "getaddrinfo", &gai_proc); + status = LI_DSLookupGetProcedureNumber("getaddrinfo", &gai_proc); if (status != KERN_SUCCESS) { errno = ECONNREFUSED; @@ -1146,16 +1078,14 @@ getaddrinfo_async_start(mach_port_t *p, const char *nodename, const char *servna } } - qlen = LU_QBUF_SIZE; + request = gai_make_query(nodename, servname, hints); + if (request == NULL) return EAI_SYSTEM; - /* gai_make_query sets errno if it fails */ - i = gai_make_query(nodename, servname, hints, qbuf, &qlen); - if (i != 0) return EAI_SYSTEM; + status = LI_async_start(p, gai_proc, request, (void *)callback, context); - qlen /= BYTES_PER_XDR_UNIT; + kvbuf_free(request); - status = lu_async_start(p, gai_proc, qbuf, qlen, (void *)callback, context); - if (status != 0) + if (status != KERN_SUCCESS) { errno = ECONNREFUSED; return EAI_SYSTEM; @@ -1164,76 +1094,54 @@ getaddrinfo_async_start(mach_port_t *p, const char *nodename, const char *servna return 0; } +void +getaddrinfo_async_cancel(mach_port_t p) +{ + LI_async_call_cancel(p, NULL); +} + int32_t getaddrinfo_async_send(mach_port_t *p, const char *nodename, const char *servname, const struct addrinfo *hints) { return getaddrinfo_async_start(p, nodename, servname, hints, NULL, NULL); } -static int -gai_extract_data(char *buf, uint32_t len, struct addrinfo **res) +int32_t +getaddrinfo_async_receive(mach_port_t p, struct addrinfo **res) { - XDR xdr; - uint32_t i, n; + kern_return_t status; char *cname; + kvarray_t *reply; + uint32_t i; struct addrinfo *a; + if (res == NULL) return 0; *res = NULL; - if (buf == NULL) return EAI_NODATA; - if (len == 0) return EAI_NODATA; + reply = NULL; - xdrmem_create(&xdr, buf, len, XDR_DECODE); - - if (!xdr_int(&xdr, (int32_t *)&n)) - { - xdr_destroy(&xdr); - errno = EIO; - return EAI_SYSTEM; - } + status = LI_async_receive(p, &reply); + if (status < 0) return EAI_FAIL; + if (reply == NULL) return EAI_NONAME; cname = NULL; - for (i = 0; i < n; i++) + for (i = 0; i < reply->count; i++) { - a = gai_lookupd_process_dictionary(&xdr); - if (a == NULL) break; - + a = gai_extract(reply); + if (a == NULL) continue; if ((cname == NULL) && (a->ai_canonname != NULL)) cname = a->ai_canonname; append_addrinfo(res, a); } - xdr_destroy(&xdr); + kvarray_free(reply); if ((cname != NULL) && (res != NULL) && (res[0] != NULL) && (res[0]->ai_canonname == NULL)) { res[0]->ai_canonname = strdup(cname); } - if (*res == NULL) return EAI_NODATA; - return 0; -} -int32_t -getaddrinfo_async_receive(mach_port_t p, struct addrinfo **res) -{ - kern_return_t status; - char *buf; - uint32_t len; - - if (res == NULL) return 0; - *res = NULL; - - buf = NULL; - len = 0; - - status = lu_async_receive(p, &buf, &len); - if (status < 0) return EAI_FAIL; - - status = gai_extract_data(buf, len, res); - if (buf != NULL) vm_deallocate(mach_task_self(), (vm_address_t)buf, len); - if (status != 0) return status; - - if (*res == NULL) return EAI_NODATA; + if (*res == NULL) return EAI_NONAME; return 0; } @@ -1243,40 +1151,57 @@ getaddrinfo_async_handle_reply(void *msg) { getaddrinfo_async_callback callback; void *context; - char *buf; - uint32_t len; + char *buf, *cname; + uint32_t i, len; int status; - struct addrinfo *res; + kvarray_t *reply; + struct addrinfo *l, *a, **res; callback = (getaddrinfo_async_callback)NULL; context = NULL; buf = NULL; len = 0; - res = NULL; + reply = NULL; + l = NULL; + res = &l; - status = lu_async_handle_reply(msg, &buf, &len, (void **)&callback, &context); + status = LI_async_handle_reply(msg, &reply, (void **)&callback, &context); if (status != KERN_SUCCESS) { if (status == MIG_REPLY_MISMATCH) return 0; - if (callback != NULL) callback(EAI_NODATA, NULL, context); - return EAI_NODATA; + if (callback != NULL) callback(EAI_FAIL, NULL, context); + return EAI_FAIL; } - status = gai_extract_data(buf, len, &res); - if (buf != NULL) vm_deallocate(mach_task_self(), (vm_address_t)buf, len); - if (status != 0) + if (reply == NULL) { - if (callback != NULL) callback(status, NULL, context); - return status; + if (callback != NULL) callback(EAI_NONAME, NULL, context); + return EAI_NONAME; + } + + cname = NULL; + for (i = 0; i < reply->count; i++) + { + a = gai_extract(reply); + if (a == NULL) continue; + if ((cname == NULL) && (a->ai_canonname != NULL)) cname = a->ai_canonname; + append_addrinfo(res, a); } - if (res == NULL) + kvarray_free(reply); + + if ((cname != NULL) && (res[0] != NULL) && (res[0]->ai_canonname == NULL)) + { + res[0]->ai_canonname = strdup(cname); + } + + if (*res == NULL) { - callback(EAI_NODATA, NULL, context); - return EAI_NODATA; + callback(EAI_NONAME, NULL, context); + return EAI_NONAME; } - callback(0, res, context); + callback(0, *res, context); return 0; } @@ -1285,7 +1210,7 @@ getaddrinfo_async_handle_reply(void *msg) */ /* - * getnameinfo support in lookupd + * getnameinfo support in Directory Service * Input dict may contain the following * * ip_address: node address @@ -1305,10 +1230,11 @@ getaddrinfo_async_handle_reply(void *msg) */ static int -gni_lookupd_process_dictionary(XDR *inxdr, char **host, char **serv) +gni_extract(kvarray_t *in, const char **host, const char **serv) { - int32_t i, j, nkeys, nvals, status; - char *key, **vals; + uint32_t d, k, kcount; + + if (in == NULL) return -1; if ((host == NULL) || (serv == NULL)) { @@ -1316,75 +1242,63 @@ gni_lookupd_process_dictionary(XDR *inxdr, char **host, char **serv) return EAI_SYSTEM; } - if (!xdr_int(inxdr, &nkeys)) - { - errno = EIO; - return EAI_SYSTEM; - } - *host = NULL; *serv = NULL; - for (i = 0; i < nkeys; i++) - { - key = NULL; - vals = NULL; - nvals = 0; + d = in->curr; + in->curr++; - status = _lu_xdr_attribute(inxdr, &key, &vals, (uint32_t *)&nvals); - if (status < 0) - { - errno = EIO; - return EAI_SYSTEM; - } + if (d >= in->count) return EAI_NONAME; - if (nvals == 0) - { - free(key); - continue; - } + kcount = in->dict[d].kcount; + if (kcount == 0) return EAI_NONAME; - if ((*host == NULL) && (!strcmp("name", key))) + for (k = 0; k < kcount; k++) + { + if (!strcmp(in->dict[d].key[k], "gni_name")) { - *host = vals[0]; - for (j = 1; j < nvals; j++) free(vals[j]); - } + if (in->dict[d].vcount[k] == 0) continue; + if (*host != NULL) continue; - else if ((*serv == NULL) && (!strcmp(key, "service"))) - { - *serv = vals[0]; - for (j = 1; j < nvals; j++) free(vals[j]); + *host = in->dict[d].val[k][0]; } + else if (!strcmp(in->dict[d].key[k], "gni_service")) + { + if (in->dict[d].vcount[k] == 0) continue; + if (*serv != NULL) continue; - if (key != NULL) free(key); - free(vals); + *serv = in->dict[d].val[k][0]; + } } + if ((*host == NULL) && (*serv == NULL)) return EAI_NONAME; return 0; } -static int -gni_make_query(const struct sockaddr *sa, size_t salen, int wanthost, int wantserv, int flags, char *buf, uint32_t *len) +static kvbuf_t * +gni_make_query(const struct sockaddr *sa, size_t salen, int wanthost, int wantserv, int flags) { - XDR outxdr; - uint16_t port; - char str[_LU_MAXLUSTRLEN], *key, ifname[IF_NAMESIZE]; - uint32_t a4, ifnum, offset, na, proto, fqdn, numerichost, numericserv, name_req, isll, issl; + kvbuf_t *request; + uint16_t port, ifnum; + char str[NI_MAXHOST], ifname[IF_NAMESIZE], tmp[64]; + uint32_t a4, offset, isll; struct sockaddr_in6 *s6; - if (sa == NULL) return EAI_FAIL; - if (sa->sa_len != salen) return EAI_FAMILY; + if (sa == NULL) + { + errno = EINVAL; + return NULL; + } + + if (sa->sa_len != salen) + { + errno = EINVAL; + return NULL; + } - proto = IPPROTO_TCP; - fqdn = 1; - numerichost = 0; - numericserv = 0; - name_req = 0; isll = 0; - issl = 0; offset = INET_NTOP_AF_INET_OFFSET; - key = "ip_address"; port = 0; if (sa->sa_family == PF_INET) @@ -1394,7 +1308,7 @@ gni_make_query(const struct sockaddr *sa, size_t salen, int wanthost, int wantse a4 >>= IN_CLASSA_NSHIFT; if (a4 == 0) flags |= NI_NUMERICHOST; - port = ((struct sockaddr_in *)sa)->sin_port; + port = ntohs(((struct sockaddr_in *)sa)->sin_port); } else if (sa->sa_family == PF_INET6) { @@ -1402,6 +1316,7 @@ gni_make_query(const struct sockaddr *sa, size_t salen, int wanthost, int wantse switch (s6->sin6_addr.s6_addr[0]) { case 0x00: + { if (IN6_IS_ADDR_V4MAPPED(&s6->sin6_addr)) { } @@ -1413,27 +1328,30 @@ gni_make_query(const struct sockaddr *sa, size_t salen, int wanthost, int wantse flags |= NI_NUMERICHOST; } break; + } default: + { if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr)) { isll = 1; } - else if (IN6_IS_ADDR_SITELOCAL(&s6->sin6_addr)) - { - issl = 1; - } else if (IN6_IS_ADDR_MULTICAST(&s6->sin6_addr)) { flags |= NI_NUMERICHOST; } break; + } } - if ((isll != 0) || (issl != 0)) + if (isll != 0) { - ifnum = s6->sin6_addr.__u6_addr.__u6_addr16[1]; + ifnum = ntohs(s6->sin6_addr.__u6_addr.__u6_addr16[1]); if (ifnum == 0) ifnum = s6->sin6_scope_id; - else if ((s6->sin6_scope_id != 0) && (ifnum != s6->sin6_scope_id)) return EAI_FAIL; + else if ((s6->sin6_scope_id != 0) && (ifnum != s6->sin6_scope_id)) + { + errno = EINVAL; + return NULL; + } s6->sin6_addr.__u6_addr.__u6_addr16[1] = 0; s6->sin6_scope_id = ifnum; @@ -1441,183 +1359,105 @@ gni_make_query(const struct sockaddr *sa, size_t salen, int wanthost, int wantse } offset = INET_NTOP_AF_INET6_OFFSET; - key = "ipv6_address"; - port = s6->sin6_port; + port = ntohs(s6->sin6_port); } else { - return EAI_FAMILY; - } - - na = 0; - - if (wanthost != 0) na++; - if (wantserv != 0) na++; - - if (flags & NI_NOFQDN) - { - fqdn = 0; - na++; - } - - if (flags & NI_NUMERICHOST) - { - numerichost = 1; - na++; - } - - if (flags & NI_NUMERICSERV) - { - numericserv = 1; - na++; - } - - if (flags & NI_NAMEREQD) - { - name_req = 1; - na++; + errno = EPFNOSUPPORT; + return NULL; } - if (flags & NI_DGRAM) + request = kvbuf_new(); + if (request == NULL) { - proto = IPPROTO_UDP; - na++; + errno = ENOMEM; + return NULL; } - xdrmem_create(&outxdr, buf, *len, XDR_ENCODE); - - if (!xdr_int(&outxdr, (int32_t *)&na)) - { - xdr_destroy(&outxdr); - errno = EIO; - return EAI_SYSTEM; - } + kvbuf_add_dict(request); if (wanthost != 0) { - inet_ntop(sa->sa_family, (char *)(sa) + offset, str, _LU_MAXLUSTRLEN); + inet_ntop(sa->sa_family, (char *)(sa) + offset, str, NI_MAXHOST); - if ((flags & NI_WITHSCOPEID) && (sa->sa_family == AF_INET6)) + if (isll != 0) { ifnum = ((struct sockaddr_in6 *)sa)->sin6_scope_id; - if (if_indextoname(ifnum, ifname) != NULL) + if ((ifnum != 0) && (if_indextoname(ifnum, ifname) != NULL)) { strcat(str, "%"); strcat(str, ifname); } } - if (encode_kv(&outxdr, key, str) != 0) - { - xdr_destroy(&outxdr); - errno = EIO; - return EAI_SYSTEM; - } - } - - if (wantserv != 0) - { - snprintf(str, _LU_MAXLUSTRLEN, "%hu", port); - if (encode_kv(&outxdr, "port", str) != 0) - { - xdr_destroy(&outxdr); - errno = EIO; - return EAI_SYSTEM; - } - } + kvbuf_add_key(request, "address"); + kvbuf_add_val(request, str); - if (proto == IPPROTO_UDP) - { - if (encode_kv(&outxdr, "protocol", "udp") != 0) - { - xdr_destroy(&outxdr); - errno = EIO; - return EAI_SYSTEM; - } - } - - if (fqdn == 0) - { - if (encode_kv(&outxdr, "fqdn", "0") != 0) - { - xdr_destroy(&outxdr); - errno = EIO; - return EAI_SYSTEM; - } - } - - if (numerichost == 1) - { - if (encode_kv(&outxdr, "numerichost", "1") != 0) - { - xdr_destroy(&outxdr); - errno = EIO; - return EAI_SYSTEM; - } - } - - if (numericserv == 1) - { - if (encode_kv(&outxdr, "numericserv", "1") != 0) - { - xdr_destroy(&outxdr); - errno = EIO; - return EAI_SYSTEM; - } + kvbuf_add_key(request, "family"); + snprintf(tmp, sizeof(tmp), "%u", sa->sa_family); + kvbuf_add_val(request, tmp); } - if (name_req == 1) + if (wantserv != 0) { - if (encode_kv(&outxdr, "name_required", "1") != 0) - { - xdr_destroy(&outxdr); - errno = EIO; - return EAI_SYSTEM; - } + snprintf(tmp, sizeof(tmp), "%hu", port); + kvbuf_add_key(request, "port"); + kvbuf_add_val(request, tmp); } - *len = xdr_getpos(&outxdr); - - xdr_destroy(&outxdr); + snprintf(tmp, sizeof(tmp), "%u", flags); + kvbuf_add_key(request, "flags"); + kvbuf_add_val(request, tmp); - return 0; + return request; } int getnameinfo(const struct sockaddr * __restrict sa, socklen_t salen, char * __restrict host, socklen_t hostlen, char * __restrict serv, socklen_t servlen, int flags) { - uint32_t n, i, qlen, rlen; - uint32_t ifnum; - int wanth, wants, isll, issl; - XDR inxdr; - char qbuf[LU_QBUF_SIZE], ifname[IF_NAMESIZE]; - char *rbuf, *hval, *sval; - mach_port_t server_port; + uint32_t n, i, ifnum; + int wanth, wants, isll; + kvbuf_t *request; + kvarray_t *reply; + char ifname[IF_NAMESIZE]; + const char *hval, *sval; kern_return_t status; - struct sockaddr_in *s4; - struct sockaddr_in6 *s6; + struct sockaddr_in *s4, s4buf; + struct sockaddr_in6 *s6, s6buf; + struct in_addr *a4; + struct in6_addr *a6; /* Check input */ if (sa == NULL) return EAI_FAIL; isll = 0; - issl = 0; ifnum = 0; - if (sa->sa_family == AF_INET6) + s4 = &s4buf; + a4 = NULL; + + s6 = &s6buf; + a6 = NULL; + + if (sa->sa_family == AF_INET) { - s6 = (struct sockaddr_in6 *)sa; + memcpy(s4, sa, sizeof(struct sockaddr_in)); + a4 = &(s4->sin_addr); + } + else if (sa->sa_family == AF_INET6) + { + memcpy(s6, sa, sizeof(struct sockaddr_in6)); + a6 = &(s6->sin6_addr); if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr)) isll = 1; - if (IN6_IS_ADDR_SITELOCAL(&s6->sin6_addr)) issl = 1; /* - * Link-local and site-local IPv6 addresses may have a scope id + * Link-local IPv6 addresses may have a scope id * in s6->sin6_addr.__u6_addr.__u6_addr16[1] as well as in s6->sin6_scope_id. * If they are both non-zero, they must be equal. * We zero s6->sin6_addr.__u6_addr.__u6_addr16[1] and set s6->sin6_scope_id. */ - if ((isll != 0) || (issl != 0)) + if (isll != 0) { ifnum = ntohs(s6->sin6_addr.__u6_addr.__u6_addr16[1]); if (ifnum == 0) ifnum = s6->sin6_scope_id; @@ -1630,17 +1470,17 @@ getnameinfo(const struct sockaddr * __restrict sa, socklen_t salen, char * __res /* V4 mapped and compat addresses are converted to plain V4 */ if ((IN6_IS_ADDR_V4MAPPED(&s6->sin6_addr)) || (IN6_IS_ADDR_V4COMPAT(&s6->sin6_addr))) { - s4 = (struct sockaddr_in *)calloc(1, sizeof(struct sockaddr_in)); + memset(s4, 0, sizeof(struct sockaddr_in)); + s4->sin_len = sizeof(struct sockaddr_in); s4->sin_family = AF_INET; s4->sin_port = s6->sin6_port; memcpy(&(s4->sin_addr.s_addr), &(s6->sin6_addr.s6_addr[12]), 4); - i = getnameinfo((const struct sockaddr *)s4, s4->sin_len, host, hostlen, serv, servlen, flags); - free(s4); - return i; + return getnameinfo((const struct sockaddr *)s4, s4->sin_len, host, hostlen, serv, servlen, flags); } } + else return EAI_FAMILY; wanth = 0; if ((host != NULL) && (hostlen != 0)) wanth = 1; @@ -1655,11 +1495,16 @@ getnameinfo(const struct sockaddr * __restrict sa, socklen_t salen, char * __res */ if ((wanth == 1) && (flags & NI_NUMERICHOST)) { - i = INET_NTOP_AF_INET_OFFSET; - if (sa->sa_family == PF_INET6) i = INET_NTOP_AF_INET6_OFFSET; - if (inet_ntop(sa->sa_family, (char *)(sa) + i, host, hostlen) == NULL) return EAI_FAIL; + if (sa->sa_family == AF_INET) + { + if (inet_ntop(AF_INET, a4, host, hostlen) == NULL) return EAI_FAIL; + } + else + { + if (inet_ntop(AF_INET6, a6, host, hostlen) == NULL) return EAI_FAIL; + } - if (((isll != 0) || (issl != 0)) && (ifnum != 0)) + if ((isll != 0) && (ifnum != 0)) { /* append interface name */ if (if_indextoname(ifnum, ifname) != NULL) @@ -1676,29 +1521,21 @@ getnameinfo(const struct sockaddr * __restrict sa, socklen_t salen, char * __res { if (sa->sa_family == PF_INET) { - s4 = (struct sockaddr_in *)sa; n = snprintf(serv, servlen, "%hu", ntohs(s4->sin_port)); if (n >= servlen) return EAI_FAIL; } - else if (sa->sa_family == PF_INET6) + else { - s6 = (struct sockaddr_in6 *)sa; n = snprintf(serv, servlen, "%hu", ntohs(s6->sin6_port)); if (n >= servlen) return EAI_FAIL; } - else return EAI_FAMILY; if (wanth == 0) return 0; } if ((wanth == 1) && (flags & NI_NUMERICHOST) && (wants == 1) && (flags & NI_NUMERICSERV)) return 0; - /* - * Ask lookupd - */ - server_port = MACH_PORT_NULL; - if (_lu_running()) server_port = _lookupd_port(0); - if (server_port == MACH_PORT_NULL) + if (_ds_running() == 0) { errno = ECONNREFUSED; return EAI_SYSTEM; @@ -1706,7 +1543,7 @@ getnameinfo(const struct sockaddr * __restrict sa, socklen_t salen, char * __res if (gni_proc < 0) { - status = _lookup_link(server_port, "getnameinfo", &gni_proc); + status = LI_DSLookupGetProcedureNumber("getnameinfo", &gni_proc); if (status != KERN_SUCCESS) { errno = ECONNREFUSED; @@ -1714,87 +1551,76 @@ getnameinfo(const struct sockaddr * __restrict sa, socklen_t salen, char * __res } } - qlen = LU_QBUF_SIZE; - i = gni_make_query(sa, salen, wanth, wants, flags, qbuf, &qlen); - if (i != 0) return i; - - qlen /= BYTES_PER_XDR_UNIT; - - rbuf = NULL; - - status = _lookup_all(server_port, gni_proc, (unit *)qbuf, qlen, &rbuf, &rlen); - if (status != KERN_SUCCESS) return EAI_NONAME; - - rlen *= BYTES_PER_XDR_UNIT; + request = gni_make_query(sa, salen, wanth, wants, flags); + if (request == NULL) return EAI_SYSTEM; - xdrmem_create(&inxdr, rbuf, rlen, XDR_DECODE); + reply = NULL; + status = LI_DSLookupQuery(gni_proc, request, &reply); + kvbuf_free(request); - if (!xdr_int(&inxdr, (int32_t *)&n)) + if (status != KERN_SUCCESS) { - xdr_destroy(&inxdr); - errno = EIO; + errno = ECONNREFUSED; return EAI_SYSTEM; } - if (n != 1) - { - xdr_destroy(&inxdr); - return EAI_NONAME; - } + if (reply == NULL) return EAI_NONAME; hval = NULL; sval = NULL; - i = gni_lookupd_process_dictionary(&inxdr, &hval, &sval); - - xdr_destroy(&inxdr); - if (rbuf != NULL) vm_deallocate(mach_task_self(), (vm_address_t)rbuf, rlen); + status = gni_extract(reply, &hval, &sval); - if (i != 0) return i; + if (status != 0) + { + kvarray_free(reply); + return status; + } i = 0; if (hval != NULL) i = strlen(hval) + 1; if ((host != NULL) && (hostlen != 0) && (i != 0)) { - if (i > hostlen) return EAI_FAIL; + if (i > hostlen) + { + kvarray_free(reply); + return EAI_FAIL; + } + memcpy(host, hval, i); - free(hval); } i = 0; if (sval != NULL) i = strlen(sval) + 1; if ((serv != NULL) && (servlen != 0) && (i != 0)) { - if (i > servlen) return EAI_FAIL; + if (i > servlen) + { + kvarray_free(reply); + return EAI_FAIL; + } + memcpy(serv, sval, i); - free(sval); } + kvarray_free(reply); return 0; } int32_t getnameinfo_async_start(mach_port_t *p, const struct sockaddr *sa, size_t salen, int flags, getnameinfo_async_callback callback, void *context) { - uint32_t i, qlen; - char qbuf[LU_QBUF_SIZE]; - mach_port_t server_port; - kern_return_t status; + int32_t status; + kvbuf_t *request; + + *p = MACH_PORT_NULL; /* Check input */ if (sa == NULL) return EAI_FAIL; - server_port = MACH_PORT_NULL; - if (_lu_running()) server_port = _lookupd_port(0); - if (server_port == MACH_PORT_NULL) - { - errno = ECONNREFUSED; - return EAI_SYSTEM; - } - if (gni_proc < 0) { - status = _lookup_link(server_port, "getnameinfo", &gni_proc); + status = LI_DSLookupGetProcedureNumber("getnameinfo", &gni_proc); if (status != KERN_SUCCESS) { errno = ECONNREFUSED; @@ -1802,14 +1628,14 @@ getnameinfo_async_start(mach_port_t *p, const struct sockaddr *sa, size_t salen, } } - qlen = LU_QBUF_SIZE; - i = gni_make_query(sa, salen, 1, 1, flags, qbuf, &qlen); - if (i != 0) return i; + request = gni_make_query(sa, salen, 1, 1, flags); + if (request == NULL) return EAI_SYSTEM; - qlen /= BYTES_PER_XDR_UNIT; + status = LI_async_start(p, gni_proc, request, (void *)callback, context); - status = lu_async_start(p, gni_proc, qbuf, qlen, (void *)callback, context); - if (status != 0) + kvbuf_free(request); + + if (status != KERN_SUCCESS) { errno = ECONNREFUSED; return EAI_SYSTEM; @@ -1818,62 +1644,45 @@ getnameinfo_async_start(mach_port_t *p, const struct sockaddr *sa, size_t salen, return 0; } -int32_t -getnameinfo_async_send(mach_port_t *p, const struct sockaddr *sa, size_t salen, int flags) +void +getnameinfo_async_cancel(mach_port_t p) { - return getnameinfo_async_start(p, sa, salen, flags, NULL, NULL); + LI_async_call_cancel(p, NULL); } -static int -gni_extract_data(char *buf, uint32_t len, char **host, char **serv) +int32_t +getnameinfo_async_send(mach_port_t *p, const struct sockaddr *sa, size_t salen, int flags) { - XDR xdr; - uint32_t n; - int i; - - *host = NULL; - *serv = NULL; - - if (buf == NULL) return EAI_NODATA; - if (len == 0) return EAI_NODATA; - - xdrmem_create(&xdr, buf, len, XDR_DECODE); - - if (!xdr_int(&xdr, (int32_t *)&n)) - { - xdr_destroy(&xdr); - errno = EIO; - return EAI_SYSTEM; - } - - if (n != 1) - { - xdr_destroy(&xdr); - return EAI_NONAME; - } - - i = gni_lookupd_process_dictionary(&xdr, host, serv); - xdr_destroy(&xdr); - return i; + return getnameinfo_async_start(p, sa, salen, flags, NULL, NULL); } int32_t getnameinfo_async_receive(mach_port_t p, char **host, char **serv) { kern_return_t status; - char *buf; - uint32_t len; + const char *hval, *sval; + kvarray_t *reply; - buf = NULL; - len = 0; + reply = NULL; - status = lu_async_receive(p, &buf, &len); + status = LI_async_receive(p, &reply); if (status < 0) return EAI_FAIL; + if (reply == NULL) return EAI_NONAME; - status = gni_extract_data(buf, len, host, serv); - if (buf != NULL) vm_deallocate(mach_task_self(), (vm_address_t)buf, len); - if (status != 0) return status; + hval = NULL; + sval = NULL; + + status = gni_extract(reply, &hval, &sval); + if (status != 0) + { + kvarray_free(reply); + return status; + } + if (hval != NULL) *host = strdup(hval); + if (sval != NULL) *serv = strdup(sval); + + kvarray_free(reply); return 0; } @@ -1882,17 +1691,19 @@ getnameinfo_async_handle_reply(void *msg) { getnameinfo_async_callback callback; void *context; - char *buf, *hval, *sval; + const char *hval, *sval; + char *host, *serv; uint32_t len; int status; + kvarray_t *reply; callback = (getnameinfo_async_callback)NULL; context = NULL; - buf = NULL; + reply = NULL; len = 0; - status = lu_async_handle_reply(msg, &buf, &len, (void **)&callback, &context); - if (status != KERN_SUCCESS) + status = LI_async_handle_reply(msg, &reply, (void **)&callback, &context); + if ((status != KERN_SUCCESS) || (reply == NULL)) { if (status == MIG_REPLY_MISMATCH) return 0; if (callback != NULL) callback(EAI_NONAME, NULL, NULL, context); @@ -1902,14 +1713,21 @@ getnameinfo_async_handle_reply(void *msg) hval = NULL; sval = NULL; - status = gni_extract_data(buf, len, &hval, &sval); - if (buf != NULL) vm_deallocate(mach_task_self(), (vm_address_t)buf, len); + status = gni_extract(reply, &hval, &sval); if (status != 0) { if (callback != NULL) callback(status, NULL, NULL, context); + kvarray_free(reply); return status; } - callback(0, hval, sval, context); + host = NULL; + serv = NULL; + + if (hval != NULL) host = strdup(hval); + if (sval != NULL) serv = strdup(sval); + kvarray_free(reply); + + callback(0, host, serv, context); return 0; } diff --git a/lookup.subproj/getfsent.3 b/lookup.subproj/getfsent.3 new file mode 100644 index 0000000..a898b04 --- /dev/null +++ b/lookup.subproj/getfsent.3 @@ -0,0 +1,153 @@ +.\" 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. +.\" +.\" @(#)getfsent.3 8.1 (Berkeley) 6/4/93 +.\" $FreeBSD: src/lib/libc/gen/getfsent.3,v 1.9 2001/10/01 16:08:51 ru Exp $ +.\" +.Dd June 4, 1993 +.Dt GETFSENT 3 +.Os +.Sh NAME +.Nm getfsent , +.Nm getfsspec , +.Nm getfsfile , +.Nm setfsent , +.Nm endfsent +.Nd get file system descriptor file entry +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In fstab.h +.Ft struct fstab * +.Fn getfsent void +.Ft struct fstab * +.Fn getfsspec "const char *spec" +.Ft struct fstab * +.Fn getfsfile "const char *file" +.Ft int +.Fn setfsent void +.Ft void +.Fn endfsent void +.Sh DESCRIPTION +The +.Fn getfsent , +.Fn getfsspec , +and +.Fn getfsfile +functions +each return a pointer to an object with the following structure +containing the broken-out fields of a line in the file system +description file, +.Aq Pa fstab.h . +.Bd -literal -offset indent +struct fstab { + char *fs_spec; /* block special device name */ + char *fs_file; /* file system path prefix */ + char *fs_vfstype; /* File system type, ufs, nfs */ + char *fs_mntops; /* Mount options ala -o */ + char *fs_type; /* FSTAB_* from fs_mntops */ + int fs_freq; /* dump frequency, in days */ + int fs_passno; /* pass number on parallel fsck */ +}; +.Ed +.Pp +The fields have meanings described in +.Xr fstab 5 . +.Pp +The +.Fn setfsent +function +opens the file (closing any previously opened file) or rewinds it +if it is already open. +.Pp +The +.Fn endfsent +function +closes the file. +.Pp +The +.Fn getfsspec +and +.Fn getfsfile +functions +search the entire file (opening it if necessary) for a matching special +file name or file system file name. +.Pp +For programs wishing to read the entire database, +.Fn getfsent +reads the next entry (opening the file if necessary). +.Pp +All entries in the file with a type field equivalent to +.Dv FSTAB_XX +are ignored. +.Sh RETURN VALUES +The +.Fn getfsent , +.Fn getfsspec , +and +.Fn getfsfile +functions +return a +.Dv NULL +pointer on +.Dv EOF +or error. +The +.Fn setfsent +function +returns 0 on failure, 1 on success. +The +.Fn endfsent +function +returns nothing. +.Sh FILES +.Bl -tag -width /etc/fstab -compact +.It Pa /etc/fstab +.El +.Sh SEE ALSO +.Xr fstab 5 +.Sh HISTORY +The +.Fn getfsent +function appeared in +.Bx 4.0 ; +the +.Fn endfsent , +.Fn getfsfile , +.Fn getfsspec , +and +.Fn setfsent +functions appeared in +.Bx 4.3 . +.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. diff --git a/lookup.subproj/getgrent.3 b/lookup.subproj/getgrent.3 new file mode 100644 index 0000000..c4c212c --- /dev/null +++ b/lookup.subproj/getgrent.3 @@ -0,0 +1,260 @@ +.\" Copyright (c) 1989, 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: @(#)getgrent.3 8.2 (Berkeley) 4/19/94 +.\" $FreeBSD: src/lib/libc/gen/getgrent.3,v 1.16 2001/10/01 16:08:51 ru Exp $ +.\" +.Dd September 29, 1994 +.Dt GETGRENT 3 +.Os +.Sh NAME +.Nm endgrent , +.Nm getgrent , +.Nm getgrgid , +.Nm getgrgid_r , +.Nm getgrnam , +.Nm getgrnam_r , +.Nm setgrent , +.\" .Nm setgrfile , +.Nm setgroupent +.Nd group database operations +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In grp.h +.Ft void +.Fo endgrent +.Fa void +.Fc +.Ft struct group * +.Fo getgrent +.Fa void +.Fc +.Ft struct group * +.Fo getgrgid +.Fa "gid_t gid" +.Fc +.Ft int +.Fo getgrgid_r +.Fa "gid_t gid" +.Fa "struct group *grp" +.Fa "char *buffer" +.Fa "size_t bufsize" +.Fa "struct group **result" +.Fc +.Ft struct group * +.Fo getgrnam +.Fa "const char *name" +.Fc +.Ft int +.Fo getgrnam_r +.Fa "const char *name" +.Fa "struct group *grp" +.Fa "char *buffer" +.Fa "size_t bufsize" +.Fa "struct group **result" +.Fc +.Ft void +.Fo setgrent +.Fa void +.Fc +.\" .Ft void +.\" .Fn setgrfile "const char *name" +.Ft int +.Fo setgroupent +.Fa "int stayopen" +.Fc +.Sh DESCRIPTION +These functions operate on the group database file +.Pa /etc/group , +which is described +in +.Xr group 5 . +Each line of the database is defined by the structure +.Ar group , +found in the include +file +.Aq Pa grp.h : +.Bd -literal -offset indent +struct group { + char *gr_name; /* group name */ + char *gr_passwd; /* group password */ + int gr_gid; /* group id */ + char **gr_mem; /* group members */ +}; +.Ed +.Pp +The functions +.Fn getgrnam +and +.Fn getgrgid +search the group database for the given group name (pointed to by +.Ar name ) +or the group id (pointed to by +.Ar gid ) , +respectively, returning the first one encountered. Identical group +names or group ids may result in undefined behavior. +.Pp +All of these routines are thread-safe. +The +.Fn getgrent , +.Fn getgrgid , +and +.Fn getgrnam +routines return a pointer to a result managed by the system library in a +thread-specific data structure. +Every thread has space for a pointer to a struct group and allocates its own storage for the result. +Neither previously returned values in memory nor a previously returned pointer value should be used +by a thread after calling any one of these three routines. +Memory allocated by a thread is automatically released on subsequent calls by the same thread to any of these +three routines, and when the thread exits. +.Pp +The functions +.Fn getgrgid_r +and +.Fn getgrnam_r +take additional arguments which supply storage space for the returned result. +The +.Fa grp +parameter is a pointer to a struct group, which must be allocated by the caller. +The +.Fa buffer +parameter is a pointer to a block of memory with a size specified by +.Pa bufsize . +This buffer is used to hold the values which are pointed to by values filled in +the +.Fa grp +structure. +Zero is returned on success. +If insufficient memory is supplied, these routines return ERANGE. +.Pp +The +.Fn getgrent +function +sequentially reads the group database and is intended for programs +that wish to step through the complete list of groups. +.Pp +All three routines will open the group file for reading, if necessary. +.Pp +The +.Fn setgroupent +function +opens the file, or rewinds it if it is already open. If +.Fa stayopen +is non-zero, file descriptors are left open, significantly speeding +functions' subsequent calls. This functionality is unnecessary for +.Fn getgrent , +as it doesn't close its file descriptors by default. It should also +be noted that it is dangerous for long-running programs to use this +functionality, as the group file may be updated. +.Pp +The +.Fn setgrent +function +is identical to +.Fn setgroupent +with an argument of zero. +.Pp +The +.Fn endgrent +function +closes any open files. +.Sh RETURN VALUES +The functions +.Fn getgrent , +.Fn getgrgid , +and +.Fn getgrnam +each return a pointer to the group entry if successful; if end-of-file +is reached or an error occurs, a null pointer is returned. +The function +.Fn setgroupent +returns the value 1 if successful; +otherwise, the value 0 is returned. +The functions +.Fn endgrent , +.Fn setgrent , +and +.Fn setgrfile +have no return value. +.Sh FILES +.Bl -tag -width /etc/group -compact +.It Pa /etc/group +group database file +.El +.Sh LEGACY SYNOPSIS +.Fd #include +.Pp +.Ft int +.br +.Fo setgrent +.Fa void +.Fc ; +.Pp +The function +.Fn setgrent +returns the value 1 if successful; +otherwise, the value 0 is returned. +.Sh SEE ALSO +.Xr getpwent 3 , +.Xr yp 8 , +.Xr group 5 +.Sh HISTORY +The functions +.Fn endgrent , +.Fn getgrent , +.Fn getgrnam , +.Fn getgrgid , +and +.Fn setgrent +appeared in +.At v7 . +The functions +.Fn setgrfile +and +.Fn setgroupent +appeared in +.Bx 4.3 Reno . +.Sh COMPATIBILITY +The historic function +.Fn setgrfile , +which allowed the specification of alternate password databases, has +been deprecated and is no longer available. +.Sh BUGS +The functions +.Fn getgrent , +.Fn getgrnam , +and +.Fn getgrgid , +leave their results in internal thread-specific memory and return +a pointer to that object. +Subsequent calls to any of these three routines by the same thread will +release the object and return a new pointer value. diff --git a/lookup.subproj/getgrouplist.3 b/lookup.subproj/getgrouplist.3 new file mode 100644 index 0000000..28364eb --- /dev/null +++ b/lookup.subproj/getgrouplist.3 @@ -0,0 +1,96 @@ +.\" Copyright (c) 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. +.\" +.\" @(#)getgrouplist.3 8.1 (Berkeley) 6/9/93 +.\" $FreeBSD: src/lib/libc/gen/getgrouplist.3,v 1.7 2001/10/01 16:08:51 ru Exp $ +.\" +.Dd June 9, 1993 +.Dt GETGROUPLIST 3 +.Os +.Sh NAME +.Nm getgrouplist +.Nd calculate group access list +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In unistd.h +.Ft int +.Fn getgrouplist "const char *name" "int basegid" "int *groups" "int *ngroups" +.Sh DESCRIPTION +The +.Fn getgrouplist +function reads through the group file and calculates +the group access list for the user specified in +.Fa name . +The +.Fa basegid +is automatically included in the groups list. +Typically this value is given as +the group number from the password file. +.Pp +The resulting group list is returned in the integer array pointed to by +.Fa groups . +The caller specifies the size of the +.Fa groups +array in the integer pointed to by +.Fa ngroups ; +the actual number of groups found is returned in +.Fa ngroups . +.Sh RETURN VALUES +The +.Fn getgrouplist +function +returns \-1 if the size of the group list is too small to +hold all the user's groups. +Here, the group array will be filled with as many groups as will fit. +.Sh FILES +.Bl -tag -width /etc/group -compact +.It Pa /etc/group +group membership list +.El +.Sh SEE ALSO +.Xr setgroups 2 , +.Xr initgroups 3 +.Sh HISTORY +The +.Fn getgrouplist +function first appeared in +.Bx 4.4 . +.Sh BUGS +The +.Fn getgrouplist +function +uses the routines based on +.Xr getgrent 3 . +If the invoking program uses any of these routines, +the group structure will +be overwritten in the call to +.Fn getgrouplist . diff --git a/lookup.subproj/getnameinfo.3 b/lookup.subproj/getnameinfo.3 index 9220959..8b0e939 100644 --- a/lookup.subproj/getnameinfo.3 +++ b/lookup.subproj/getnameinfo.3 @@ -24,12 +24,18 @@ .Nm getnameinfo .Nd socket address structure to hostname and service name .Sh SYNOPSIS -.In sys/types.h .In sys/socket.h .In netdb.h .Ft int -.Fn getnameinfo "const struct sockaddr *sa" "socklen_t salen" "char *host" \ - "size_t hostlen" "char *serv" "size_t servlen" "int flags" +.Fo getnameinfo +.Fa "const struct sockaddr *restrict sa" +.Fa "socklen_t salen" +.Fa "char *restrict node" +.Fa "socklen_t nodelen" +.Fa "char *restrict service" +.Fa "socklen_t servicelen" +.Fa "int flags" +.Fc .Sh DESCRIPTION The .Fn getnameinfo @@ -59,19 +65,19 @@ bytes long. The host and service names associated with .Fa sa are stored in -.Fa host +.Fa node and -.Fa serv +.Fa service which have length parameters -.Fa hostlen +.Fa nodelen and -.Fa servlen . +.Fa servicelen . The maximum value for -.Fa hostlen +.Fa nodelen is .Dv NI_MAXHOST and the maximum value for -.Fa servlen +.Fa servicelen is .Dv NI_MAXSERV , as defined by @@ -156,6 +162,31 @@ if (getnameinfo(sa, sa-\*[Gt]sa_len, hbuf, sizeof(hbuf), NULL, 0, } printf("host=%s\en", hbuf); .Ed +.Sh LEGACY SYNOPSIS +.Fd #include +.Fd #include +.Fd #include +.Pp +The include file +.In sys/types.h +is necessary. +.Pp +.Ft int +.Fo getnameinfo +.Fa "const struct sockaddr *restrict sa" +.Fa "socklen_t salen" +.Fa "char *restrict node" +.Fa "size_t nodelen" +.Fa "char *service" +.Fa "size_t servicelen" +.Fa "int flags" +.Fc ; +.Pp +The type of +.Fa nodelen +and +.Fa servicelen +has changed. .Sh SEE ALSO .Xr gai_strerror 3 , .Xr getaddrinfo 3 , @@ -256,10 +287,6 @@ if (error == 0) { NULL, 0, NI_NUMERICHOST); } .Ed -.Sh BUGS -The implementation of -.Fn getnameinfo -is not thread-safe. .\".Pp .\".Ox .\"intentionally uses a different diff --git a/lookup.subproj/getnetgrent.3 b/lookup.subproj/getnetgrent.3 new file mode 100644 index 0000000..7124aef --- /dev/null +++ b/lookup.subproj/getnetgrent.3 @@ -0,0 +1,133 @@ +.\" Copyright (c) 1992, 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. +.\" +.\" @(#)getnetgrent.3 8.1 (Berkeley) 6/4/93 +.\" $FreeBSD: src/lib/libc/gen/getnetgrent.3,v 1.10 2001/10/01 16:08:51 ru Exp $ +.\" +.Dd June 4, 1993 +.Dt GETNETGRENT 3 +.Os +.Sh NAME +.Nm getnetgrent , +.Nm innetgr , +.Nm setnetgrent , +.Nm endnetgrent +.Nd netgroup database operations +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In netdb.h +.Ft int +.Fn getnetgrent "char **host" "char **user" "char **domain" +.Ft int +.Fn innetgr "const char *netgroup" "const char *host" "const char *user" "const char *domain" +.Ft void +.Fn setnetgrent "const char *netgroup" +.Ft void +.Fn endnetgrent void +.Sh DESCRIPTION +These functions operate on the netgroup database file +.Pa /etc/netgroup +which is described +in +.Xr netgroup 5 . +The database defines a set of netgroups, each made up of one or more triples: +.Bd -literal -offset indent +(host, user, domain) +.Ed +that defines a combination of host, user and domain. +Any of the three fields may be specified as ``wildcards'' that match any +string. +.Pp +The function +.Fn getnetgrent +sets the three pointer arguments to the strings of the next member of the +current netgroup. +If any of the string pointers are +.Sy (char *)0 +that field is considered a wildcard. +.Pp +The functions +.Fn setnetgrent +and +.Fn endnetgrent +set the current netgroup and terminate the current netgroup respectively. +If +.Fn setnetgrent +is called with a different netgroup than the previous call, an implicit +.Fn endnetgrent +is implied. +.Fn Setnetgrent +also sets the offset to the first member of the netgroup. +.Pp +The function +.Fn innetgr +searches for a match of all fields within the specified group. +If any of the +.Sy host , +.Sy user , +or +.Sy domain +arguments are +.Sy (char *)0 +those fields will match any string value in the netgroup member. +.Sh RETURN VALUES +The function +.Fn getnetgrent +returns 0 for ``no more netgroup members'' and 1 otherwise. +The function +.Fn innetgr +returns 1 for a successful match and 0 otherwise. +The functions +.Fn setnetgrent +and +.Fn endnetgrent +have no return value. +.Sh FILES +.Bl -tag -width /etc/netgroup -compact +.It Pa /etc/netgroup +netgroup database file +.El +.Sh SEE ALSO +.Xr netgroup 5 +.Sh COMPATIBILITY +The netgroup members have three string fields to maintain compatibility +with other vendor implementations, however it is not obvious what use the +.Sy domain +string has within +.Bx . +.Sh BUGS +The function +.Fn getnetgrent +returns pointers to dynamically allocated data areas that are freed when +the function +.Fn endnetgrent +is called. diff --git a/lookup.subproj/getpwent.3 b/lookup.subproj/getpwent.3 new file mode 100644 index 0000000..f60d28a --- /dev/null +++ b/lookup.subproj/getpwent.3 @@ -0,0 +1,315 @@ +.\" Copyright (c) 1988, 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: @(#)getpwent.3 8.2 (Berkeley) 12/11/93 +.\" $FreeBSD: src/lib/libc/gen/getpwent.3,v 1.18 2001/10/01 16:08:51 ru Exp $ +.\" +.Dd September 20, 1994 +.Dt GETPWENT 3 +.Os +.Sh NAME +.Nm endpwent , +.Nm getpwent , +.Nm getpwnam , +.Nm getpwnam_r , +.Nm getpwuid , +.Nm getpwuid_r , +.Nm setpassent , +.Nm setpwent +.Nd password database operations +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In pwd.h +.Ft void +.Fo endpwent +.Fa void +.Fc +.Ft struct passwd * +.Fo getpwent +.Fa void +.Fc +.Ft struct passwd * +.Fo getpwnam +.Fa "const char *login" +.Fc +.Ft int +.Fo getpwnam_r +.Fa "const char *login" +.Fa "struct passwd *pwd" +.Fa "char *buffer" +.Fa "size_t bufsize" +.Fa "struct passwd **result" +.Fc +.Ft struct passwd * +.Fo getpwuid +.Fa "uid_t uid" +.Fc +.Ft int +.Fo getuid_r +.Fa "uid_t uid" +.Fa "struct passwd *pwd" +.Fa "char *buffer" +.Fa "size_t bufsize" +.Fa "struct passwd **result" +.Fc +.Ft int +.Fo setpassent +.Fa "int stayopen" +.Fc +.Ft void +.Fo setpwent +.Fa void +.Fc +.Sh DESCRIPTION +These functions +operate on the password database file, +which is described +in +.Xr passwd 5 . +Each entry in the database is defined by the structure +.Ar passwd , +found in the include file +.Aq Pa pwd.h : +.Bd -literal -offset indent +struct passwd { + char *pw_name; /* user name */ + char *pw_passwd; /* encrypted password */ + uid_t pw_uid; /* user uid */ + gid_t pw_gid; /* user gid */ + time_t pw_change; /* password change time */ + char *pw_class; /* user access class */ + char *pw_gecos; /* Honeywell login info */ + char *pw_dir; /* home directory */ + char *pw_shell; /* default shell */ + time_t pw_expire; /* account expiration */ + int pw_fields; /* internal: fields filled in */ +}; +.Ed +.Pp +The functions +.Fn getpwnam +and +.Fn getpwuid +search the password database for the given login name or user uid, +respectively, always returning the first one encountered. +.Pp +All of these routines are thread-safe. +The +.Fn getpwent , +.Fn getpwnam , +and +.Fn getpwuid +routines return a pointer to a result managed by the system library in a +thread-specific data structure. +Every thread has space for a pointer to a struct passwd and allocates its own storage for the result. +Neither previously returned values in memory nor a previously returned pointer value should be used +by a thread after calling any one of these three routines. +Memory allocated by a thread is automatically released on subsequent calls by the same thread to any of these +three routines, and when the thread exits. +.Pp +The functions +.Fn getpwnam_r +and +.Fn getpwuid_r +take additional arguments which supply storage space for the returned result. +The +.Fa pwd +parameter is a pointer to a struct passwd, which must be allocated by the caller. +The +.Fa buffer +parameter is a pointer to a block of memory with a size specified by +.Pa bufsize . +This buffer is used to hold the values which are pointed to by values filled in +the +.Fa pwd +structure. +Zero is returned on success. +If insufficient memory is supplied, these routines return ERANGE. +.Pp +The +.Fn getpwent +function +sequentially reads the password database and is intended for programs +that wish to process the complete list of users. +.Pp +The +.Fn setpassent +function +accomplishes two purposes. +First, it causes +.Fn getpwent +to ``rewind'' to the beginning of the database. +Additionally, if +.Fa stayopen +is non-zero, file descriptors are left open, significantly speeding +up subsequent accesses for all of the routines. +(This latter functionality is unnecessary for +.Fn getpwent , +as it doesn't close its file descriptors by default.) +.Pp +It is dangerous for long-running programs to keep the file descriptors +open, as the database will become out of date if it is updated while the +program is running. +.Pp +The +.Fn setpwent +function +is identical to +.Fn setpassent +with an argument of zero, +save that it does not return a status value. +.Pp +The +.Fn endpwent +function +closes any open files. +.Pp +As of Mac OS X 10.3, there are now different per-user behaviours of +this function, based on the AuthenticationAuthority value +stored for the queried user in DirectoryServices. +.Pp +If the queried user is still a legacy crypt password user or now +has an AuthenticationAuthority value containing ``;basic;'', +these routines will behave in their standard BSD fashion. +These functions will ``shadow'' the password file, e.g.\& +allow only certain programs to have access to the encrypted password. +If the process which calls them has an effective uid of 0, the encrypted +password will be returned, otherwise, the password field of the returned +structure will point to the string +.Ql * . +.Pp +By default in Mac OS X 10.3 and later all users will have an +AuthenticationAuthority with the value ``;ShadowHash;''. +These users will have a visible password value of ``********''. +These functions +will have no access to the encrypted password whatsoever. +Setting or changing +an user password must be done entirely through the DirectoryService APIs +for this default user. +.Pp +There also exists an ``Apple Password Server'' user whose password +value is also ``********'' and with an AuthenticationAuthority that +contains the value ";ApplePasswordServer;" among other data. +There is no getpwnam access to the password for this user either +and again set/change password can be done through the DirectoryService API. +.Pp +Finally in support of local user caching there is a local cached user +whose password is also ``********'' and has an AuthenticationAuthority +value containing ``;LocalCachedUser;'' among other data. +These functions also provide no access to the password for this user +and set/change password functionality is through the DirectoryService API. +.Pp +.Sh RETURN VALUES +The functions +.Fn getpwent , +.Fn getpwnam , +and +.Fn getpwuid +return a valid pointer to a passwd structure on success +and a null pointer if end-of-file is reached or an error occurs. +The +.Fn setpassent +function returns 0 on failure and 1 on success. +The +.Fn endpwent +and +.Fn setpwent +functions have no return value. +.Sh FILES +.Bl -tag -width /etc/master.passwd -compact +.It Pa /etc/pwd.db +The insecure password database file +.It Pa /etc/spwd.db +The secure password database file +.It Pa /etc/master.passwd +The current password file +.It Pa /etc/passwd +A Version 7 format password file +.El +.Sh LEGACY SYNOPSIS +.Fd #include +.Fd #include +.Pp +The include file +.In sys/types.h +is necessary for the +.Fa getpwent , +.Fa getpwnam , +and +.Fa getpwuid +functions. +.Pp +.Ft int +.br +.Fo setpwent +.Fa void +.Fc ; +.Pp +The +.Fn setpwent +function returns 0 on failure and 1 on success. +.Sh SEE ALSO +.Xr getlogin 2 , +.Xr getgrent 3 , +.Xr yp 8 , +.Xr passwd 5 , +.Xr pwd_mkdb 8 , +.Xr vipw 8 +.Sh HISTORY +The +.Fn getpwent , +.Fn getpwnam , +.Fn getpwuid , +.Fn setpwent , +and +.Fn endpwent +functions appeared in +.At v7 . +The +.Fn setpassent +function appeared in +.Bx 4.3 Reno . +.Sh COMPATIBILITY +The historic function +.Xr setpwfile 3 , +which allowed the specification of alternate password databases, +has been deprecated and is no longer available. +.Sh BUGS +The functions +.Fn getpwent , +.Fn getpwnam , +and +.Fn getpwuid +leave their results in internal thread-specific memory and return +a pointer to that object. +Subsequent calls to any of these three routines by the same thread will +release the object and return a new pointer value. diff --git a/lookup.subproj/initgroups.3 b/lookup.subproj/initgroups.3 new file mode 100644 index 0000000..039b87f --- /dev/null +++ b/lookup.subproj/initgroups.3 @@ -0,0 +1,86 @@ +.\" 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. +.\" +.\" @(#)initgroups.3 8.1 (Berkeley) 6/4/93 +.\" $FreeBSD: src/lib/libc/gen/initgroups.3,v 1.10 2001/10/01 16:08:51 ru Exp $ +.\" +.Dd June 4, 1993 +.Dt INITGROUPS 3 +.Os +.Sh NAME +.Nm initgroups +.Nd initialize group access list +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In unistd.h +.Ft int +.Fn initgroups "const char *name" "int basegid" +.Sh DESCRIPTION +The +.Fn initgroups +function +uses the +.Xr getgrouplist 3 +function to calculate the group access list for the user +specified in +.Fa name . +This group list is then setup for the current process using +.Xr setgroups 2 . +The +.Fa basegid +is automatically included in the groups list. +Typically this value is given as +the group number from the password file. +.Sh RETURN VALUES +The +.Fn initgroups +function +returns \-1 if it was not invoked by the super-user. +.Sh SEE ALSO +.Xr setgroups 2 , +.Xr getgrouplist 3 +.Sh HISTORY +The +.Fn initgroups +function appeared in +.Bx 4.2 . +.Sh BUGS +The +.Fn getgrouplist +function called by +.Fn initgroups +uses the routines based on +.Xr getgrent 3 . +If the invoking program uses any of these routines, +the group structure will +be overwritten in the call to +.Fn initgroups . diff --git a/lookup.subproj/kvbuf.h b/lookup.subproj/kvbuf.h new file mode 100644 index 0000000..4da841f --- /dev/null +++ b/lookup.subproj/kvbuf.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2006 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@ + */ +/* + * Useful macros and other stuff for generic lookups + * Copyright (C) 1989 by NeXT, Inc. + */ + +#ifndef _KVBUF_H_ +#define _KVBUF_H_ + +#include +#include + +/* + * kvbuf_t is used to encode requests and replies. + * It encodes a list of dictionaries. + * First 4 bytes are number of dictionaries. + * All numbers and lengths are uint32_t in network byte order. + * Each dictionary is a list of (key, value list) pairs. + * First 4 bytes in a dictionary are the number of keys. + * Key is 4 bytes (length) followed by nul-terminated string. + * Following the key is a value list. + * First 4 bytes in a value list are the number of values. + * Each value is 4 bytes (length) followed by nul-terminated string. + */ +typedef struct +{ + uint32_t datalen; + char *databuf; + uint32_t _size; + uint32_t _dict; + uint32_t _key; + uint32_t _vlist; + uint32_t _val; +} kvbuf_t; + +typedef struct +{ + uint32_t kcount; + const char **key; + uint32_t *vcount; + const char ***val; +} kvdict_t; + +typedef struct +{ + uint32_t count; + uint32_t curr; + kvdict_t *dict; + kvbuf_t *kv; +} kvarray_t; + +__BEGIN_DECLS + +/* + * Utilities for creating KV buffers + */ +kvbuf_t *kvbuf_new(void); +kvbuf_t *kvbuf_init(char *buffer, uint32_t length); + +void kvbuf_add_dict(kvbuf_t *kv); +void kvbuf_add_key(kvbuf_t *kv, const char *key); +void kvbuf_add_val(kvbuf_t *kv, const char *val); +void kvbuf_add_val_len(kvbuf_t *kv, const char *val, uint32_t len); +uint32_t kvbuf_get_len(const char *p); +void kvbuf_free(kvbuf_t *kv); + +/* + * Utilities for getting data back from KV buffers + * These are ugly, but reasonably efficient. + * Libinfo routines decode the raw databuf in a single pass + * i.e. not with these routines. + */ + +kvarray_t *kvbuf_decode(kvbuf_t *kv); +void kvarray_free(kvarray_t *a); + +/* + * Utility to append a kvbuf to an existing kvbuf + */ +void kvbuf_append_kvbuf( kvbuf_t *kv, const kvbuf_t *kv2 ); + +/* + * Call this to start walking through the kvbuf. + * Returns the number of dictionaries. + */ +uint32_t kvbuf_reset(kvbuf_t *kv); + +/* + * Walk through dictionaries. + * Returns the number of keys in the dictionary. + */ +uint32_t kvbuf_next_dict(kvbuf_t *kv); + +/* + * Walk through keys in a dictionary. + * Returns the key. Don't free it! + * Sets the number of values for the key in the val_count output parameter. + */ +char *kvbuf_next_key(kvbuf_t *kv, uint32_t *val_count); + +/* + * Walk through values for a key. + * Returns the value. Don't free it! + */ +char *kvbuf_next_val(kvbuf_t *kv); + +/* + * Walk through values for a key, with a length returned + * Returns the value. Don't free it! + */ +char *kvbuf_next_val_len(kvbuf_t *kv, uint32_t *vl ); + +__END_DECLS + +#endif /* ! _KVBUF_H_ */ diff --git a/lookup.subproj/lu_alias.c b/lookup.subproj/lu_alias.c index cb62a7c..5c7d28a 100644 --- a/lookup.subproj/lu_alias.c +++ b/lookup.subproj/lu_alias.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -30,352 +30,127 @@ #include #include #include -#include -#include #include #include - -#include "_lu_types.h" -#include "lookup.h" #include "lu_utils.h" #include "lu_overrides.h" +#define ENTRY_SIZE sizeof(struct aliasent) +#define ENTRY_KEY _li_data_key_alias + static pthread_mutex_t _alias_lock = PTHREAD_MUTEX_INITIALIZER; -static void -free_alias_data(struct aliasent *a) +static struct aliasent * +copy_alias(struct aliasent *in) { - int i; - - 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); -} + if (in == NULL) return NULL; -static void -free_alias(struct aliasent *a) -{ - if (a == NULL) return; - free_alias_data(a); - free(a); + return (struct aliasent *)LI_ils_create("s4*4", in->alias_name, in->alias_members_len, in->alias_members, in->alias_local); } -static void -free_lu_thread_info_alias(void *x) +/* + * Extract the next alias entry from a kvarray. + */ +static void * +extract_alias(kvarray_t *in) { - 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; - } + struct aliasent tmp; + uint32_t d, k, kcount; + char *empty[1]; - _lu_data_free_vm_xdr(tdata); - - free(tdata); -} + if (in == NULL) return NULL; -static struct aliasent * -extract_alias(XDR *xdr) -{ - int i, j, nkeys, nvals, status; - char *key, **vals; - struct aliasent *a; + d = in->curr; + in->curr++; - if (xdr == NULL) return NULL; + if (d >= in->count) return NULL; - if (!xdr_int(xdr, &nkeys)) return NULL; + empty[0] = NULL; + memset(&tmp, 0, ENTRY_SIZE); - a = (struct aliasent *)calloc(1, sizeof(struct aliasent)); + kcount = in->dict[d].kcount; - for (i = 0; i < nkeys; i++) + for (k = 0; k < kcount; k++) { - key = NULL; - vals = NULL; - nvals = 0; - - status = _lu_xdr_attribute(xdr, &key, &vals, &nvals); - if (status < 0) + if (!strcmp(in->dict[d].key[k], "alias_name")) { - free_alias(a); - return NULL; - } + if (tmp.alias_name != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; - if (nvals == 0) - { - free(key); - continue; + tmp.alias_name = (char *)in->dict[d].val[k][0]; } - - j = 0; - - if ((a->alias_name == NULL) && (!strcmp("name", key))) - { - a->alias_name = vals[0]; - j = 1; - } - else if (!strcmp("alias_local", key)) + else if (!strcmp(in->dict[d].key[k], "alias_members")) { - 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; - } + if (tmp.alias_members != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; - free(key); - if (vals != NULL) + tmp.alias_members_len = in->dict[d].vcount[k]; + tmp.alias_members = (char **)in->dict[d].val[k]; + } + else if (!strcmp(in->dict[d].key[k], "alias_local")) { - for (; j < nvals; j++) free(vals[j]); - free(vals); + if (in->dict[d].vcount[k] == 0) continue; + tmp.alias_local = atoi(in->dict[d].val[k][0]); } } - if (a->alias_name == NULL) a->alias_name = strdup(""); - if (a->alias_members == NULL) a->alias_members = (char **)calloc(1, sizeof(char *)); + if (tmp.alias_name == NULL) tmp.alias_name = ""; + if (tmp.alias_members == NULL) tmp.alias_members = empty; - return a; + return copy_alias(&tmp); } +/* + * Send a query to the system information daemon. + */ static struct aliasent * -copy_alias(struct aliasent *in) -{ - 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 *)); - } - - for (i = 0; i < a->alias_members_len; i++) - { - a->alias_members[i] = strdup(in->alias_members[i]); - } - - a->alias_local = in->alias_local; - - return a; -} - -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) - { - tdata->lu_entry = in; - return; - } - - 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; - - free(in); -} - -static struct aliasent * -lu_alias_getbyname(const char *name) +ds_alias_getbyname(const char *name) { - struct aliasent *a; - unsigned int datalen; - char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT]; - char *lookup_buf; - XDR outxdr; - XDR inxdr; static int proc = -1; - int count; - - if (proc < 0) - { - if (_lookup_link(_lu_port, "alias_getbyname", &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; - } - - a = extract_alias(&inxdr); - xdr_destroy(&inxdr); - vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); - - return a; + return (struct aliasent *)LI_getone("alias_getbyname", &proc, extract_alias, "name", name); } +/* + * Clean up / initialize / reinitialize the kvarray used to hold a list of all rpc entries. + */ static void -lu_alias_endent(void) +ds_alias_endent(void) { - 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); + LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY)); } static void -lu_alias_setent(void) +ds_alias_setent(void) { - lu_alias_endent(); + ds_alias_endent(); } +/* + * Get an entry from the getrpcent kvarray. + * Calls the system information daemon if the list doesn't exist (first call), + * or extracts the next entry if the list has been fetched. + */ static struct aliasent * -lu_alias_getent(void) +ds_alias_getent(void) { static int proc = -1; - struct lu_thread_info *tdata; - struct aliasent *a; - - 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) - { - if (proc < 0) - { - if (_lookup_link(_lu_port, "alias_getent", &proc) != KERN_SUCCESS) - { - lu_alias_endent(); - return NULL; - } - } - - if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS) - { - lu_alias_endent(); - 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_alias_endent(); - return NULL; - } - } - - if (tdata->lu_vm_cursor == 0) - { - lu_alias_endent(); - return NULL; - } - - - a = extract_alias(tdata->lu_xdr); - if (a == NULL) - { - lu_alias_endent(); - return NULL; - } - - tdata->lu_vm_cursor--; - - return a; + return (struct aliasent *)LI_getent("alias_getent", &proc, extract_alias, ENTRY_KEY, ENTRY_SIZE); } struct aliasent * alias_getbyname(const char *name) { struct aliasent *res = NULL; - struct lu_thread_info *tdata; + struct li_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); - } + tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); + if (tdata == NULL) return NULL; - if (_lu_running()) + if (_ds_running()) { - res = lu_alias_getbyname(name); + res = ds_alias_getbyname(name); } else { @@ -384,8 +159,8 @@ alias_getbyname(const char *name) pthread_mutex_unlock(&_alias_lock); } - recycle_alias(tdata, res); - return (struct aliasent *)tdata->lu_entry; + LI_data_recycle(tdata, res, ENTRY_SIZE); + return (struct aliasent *)tdata->li_entry; } @@ -393,18 +168,14 @@ struct aliasent * alias_getent(void) { struct aliasent *res = NULL; - struct lu_thread_info *tdata; + struct li_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); - } + tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); + if (tdata == NULL) return NULL; - if (_lu_running()) + if (_ds_running()) { - res = lu_alias_getent(); + res = ds_alias_getent(); } else { @@ -413,21 +184,21 @@ alias_getent(void) pthread_mutex_unlock(&_alias_lock); } - recycle_alias(tdata, res); - return (struct aliasent *)tdata->lu_entry; + LI_data_recycle(tdata, res, ENTRY_SIZE); + return (struct aliasent *)tdata->li_entry; } void alias_setent(void) { - if (_lu_running()) lu_alias_setent(); + if (_ds_running()) ds_alias_setent(); else _old_alias_setent(); } void alias_endent(void) { - if (_lu_running()) lu_alias_endent(); + if (_ds_running()) ds_alias_endent(); else _old_alias_endent(); } diff --git a/lookup.subproj/lu_bootp.c b/lookup.subproj/lu_bootp.c index 8f96c94..90b0ac3 100644 --- a/lookup.subproj/lu_bootp.c +++ b/lookup.subproj/lu_bootp.c @@ -29,8 +29,6 @@ #include #include #include -#include -#include #include #include #include @@ -39,240 +37,15 @@ #include #include -#include "_lu_types.h" -#include "lookup.h" -#include "lu_utils.h" - -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 inxdr; - struct bootpent *b; - static int proc = -1; - char *lookup_buf; - int count; - - if (proc < 0) - { - if (_lookup_link(_lu_port, "bootp_getbyether", &proc) != KERN_SUCCESS) - { - return 0; - } - } - - 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; - } - - datalen *= BYTES_PER_XDR_UNIT; - if ((lookup_buf == NULL) || (datalen == 0)) return 0; - - 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(&inxdr); - vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); - return 0; - } - - 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 -lu_bootp_getbyip(struct ether_addr *enaddr, char **name, - struct in_addr *ipaddr, char **bootfile) -{ - unsigned datalen; - XDR inxdr; - struct bootpent *b; - static int proc = -1; - char *lookup_buf; - int count; - - if (proc < 0) - { - if (_lookup_link(_lu_port, "bootp_getbyip", &proc) != KERN_SUCCESS) - { - return 0; - } - } - - 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; - } - - datalen *= BYTES_PER_XDR_UNIT; - if ((lookup_buf == NULL) || (datalen == 0)) return 0; - - 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(&inxdr); - vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); - return 0; - } - - b = extract_bootp(&inxdr); - xdr_destroy(&inxdr); - - *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) { - if (_lu_running()) - { - return (lu_bootp_getbyether(enaddr, name, ipaddr, bootfile)); - } return 0; } int 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; } diff --git a/lookup.subproj/lu_bootparam.c b/lookup.subproj/lu_bootparam.c index 9fe1b84..ea452e1 100644 --- a/lookup.subproj/lu_bootparam.c +++ b/lookup.subproj/lu_bootparam.c @@ -29,351 +29,26 @@ #include #include #include -#include -#include #include -#include "lookup.h" -#include "_lu_types.h" -#include "lu_utils.h" - -static void -free_bootparams_data(struct bootparamsent *b) -{ - char **param; - - if (b == NULL) return; - - if (b->bp_name != NULL) free(b->bp_name); - - 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 -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, j, nkeys, nvals, status; - char *key, **vals; - struct bootparamsent *b; - - if (xdr == NULL) return NULL; - - if (!xdr_int(xdr, &nkeys)) return NULL; - - b = (struct bootparamsent *)calloc(1, sizeof(struct bootparamsent)); - - for (i = 0; i < nkeys; 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); - } - } - - if (b->bp_name == NULL) b->bp_name = strdup(""); - if (b->bp_bootparams == NULL) b->bp_bootparams = (char **)calloc(1, sizeof(char *)); - - 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]; - char *lookup_buf; - XDR outxdr; - XDR inxdr; - int size; - static int proc = -1; - int count; - - if (proc < 0) - { - if (_lookup_link(_lu_port, "bootparams_getbyname", &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); - } - - size = xdr_getpos(&outxdr); - xdr_destroy(&outxdr); - - 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; - 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; - } - - b = extract_bootparams(&inxdr); - xdr_destroy(&inxdr); - vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); - - return b; -} - -static void -lu_bootparams_endent(void) -{ - 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(); -} - -static struct bootparamsent * -lu_bootparams_getent(void) -{ - struct bootparamsent *b; - static int proc = -1; - 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 (tdata->lu_vm == NULL) - { - if (proc < 0) - { - if (_lookup_link(_lu_port, "bootparams_getent", &proc) != KERN_SUCCESS) - { - lu_bootparams_endent(); - return NULL; - } - } - - if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS) - { - lu_bootparams_endent(); - 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_bootparams_endent(); - return NULL; - } - } - - if (tdata->lu_vm_cursor == 0) - { - lu_bootparams_endent(); - return NULL; - } - - b = extract_bootparams(tdata->lu_xdr); - if (b == NULL) - { - lu_bootparams_endent(); - return NULL; - } - - tdata->lu_vm_cursor--; - - return b; -} - struct bootparamsent * bootparams_getbyname(const char *name) { - 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) { - 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 bootparams_setent(void) { - if (_lu_running()) lu_bootparams_setent(); } void bootparams_endent(void) { - if (_lu_running()) lu_bootparams_endent(); } diff --git a/lookup.subproj/lu_fstab.c b/lookup.subproj/lu_fstab.c index 725255b..05f7624 100644 --- a/lookup.subproj/lu_fstab.c +++ b/lookup.subproj/lu_fstab.c @@ -30,397 +30,183 @@ #include #include #include -#include -#include #include #include - -#include "lookup.h" -#include "_lu_types.h" #include "lu_utils.h" #include "lu_overrides.h" +#define ENTRY_SIZE sizeof(struct fstab) +#define ENTRY_KEY _li_data_key_fstab + 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 -free_fstab_data(struct fstab *f) +static struct fstab * +copy_fstab(struct fstab *in) { - if (f == NULL) return; + if (in == NULL) return NULL; - 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); + return (struct fstab *)LI_ils_create("sssss44", in->fs_spec, in->fs_file, in->fs_vfstype, in->fs_mntops, in->fs_type, in->fs_freq, in->fs_passno); } -static void -free_fstab(struct fstab *f) -{ - if (f == NULL) return; - free_fstab_data(f); - free(f); -} - -static void -free_lu_thread_info_fstab(void *x) +/* + * Extract the next fstab entry from a kvarray. + */ +static void * +extract_fstab(kvarray_t *in) { - 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; - } + struct fstab tmp; + uint32_t d, k, kcount; - _lu_data_free_vm_xdr(tdata); - - free(tdata); -} + if (in == NULL) return NULL; -static struct fstab * -extract_fstab(XDR *xdr) -{ - int i, j, nkeys, nvals, status; - char *key, **vals; - struct fstab *f; + d = in->curr; + in->curr++; - if (xdr == NULL) return NULL; + if (d >= in->count) return NULL; - if (!xdr_int(xdr, &nkeys)) return NULL; + memset(&tmp, 0, ENTRY_SIZE); - f = (struct fstab *)calloc(1, sizeof(struct fstab)); + kcount = in->dict[d].kcount; - for (i = 0; i < nkeys; i++) + for (k = 0; k < kcount; k++) { - key = NULL; - vals = NULL; - nvals = 0; - - status = _lu_xdr_attribute(xdr, &key, &vals, &nvals); - if (status < 0) + if (!strcmp(in->dict[d].key[k], "fs_spec")) { - free_fstab(f); - return NULL; - } + if (tmp.fs_spec != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; - if (nvals == 0) - { - free(key); - continue; + tmp.fs_spec = (char *)in->dict[d].val[k][0]; } - - j = 0; - - if ((f->fs_spec == NULL) && (!strcmp("name", key))) + else if (!strcmp(in->dict[d].key[k], "fs_file")) { - 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; + if (tmp.fs_file != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.fs_file = (char *)in->dict[d].val[k][0]; } - else if ((f->fs_mntops == NULL) && (!strcmp("opts", key))) + else if (!strcmp(in->dict[d].key[k], "fs_vfstype")) { - f->fs_mntops = vals[0]; - j = 1; + if (tmp.fs_vfstype != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.fs_vfstype = (char *)in->dict[d].val[k][0]; } - else if ((f->fs_type == NULL) && (!strcmp("type", key))) + else if (!strcmp(in->dict[d].key[k], "fs_mntops")) { - f->fs_type = vals[0]; - j = 1; + if (tmp.fs_mntops != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.fs_mntops = (char *)in->dict[d].val[k][0]; } - else if (!strcmp("freq", key)) + else if (!strcmp(in->dict[d].key[k], "fs_type")) { - f->fs_freq = atoi(vals[0]); + if (tmp.fs_type != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.fs_type = (char *)in->dict[d].val[k][0]; } - else if (!strcmp("passno", key)) + else if (!strcmp(in->dict[d].key[k], "fs_freq")) { - f->fs_passno = atoi(vals[0]); + if (in->dict[d].vcount[k] == 0) continue; + tmp.fs_freq = atoi(in->dict[d].val[k][0]); } - - free(key); - if (vals != NULL) + else if (!strcmp(in->dict[d].key[k], "fs_passno")) { - for (; j < nvals; j++) free(vals[j]); - free(vals); + if (in->dict[d].vcount[k] == 0) continue; + tmp.fs_passno = atoi(in->dict[d].val[k][0]); } } - 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) - { - tdata->lu_entry = in; - return; - } - - free_fstab_data(f); - - 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; + if (tmp.fs_spec == NULL) tmp.fs_spec = ""; + if (tmp.fs_file == NULL) tmp.fs_file = ""; + if (tmp.fs_vfstype == NULL) tmp.fs_vfstype = ""; + if (tmp.fs_mntops == NULL) tmp.fs_mntops = ""; + if (tmp.fs_type == NULL) tmp.fs_type = ""; - free(in); + return copy_fstab(&tmp); } static struct fstab * -lu_getfsspec(const char *name) +ds_getfsspec(const char *name) { - struct fstab *f; - unsigned datalen; - char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT]; - XDR outxdr; - XDR inxdr; static int proc = -1; - char *lookup_buf; - int count; - - if (proc < 0) - { - if (_lookup_link(_lu_port, "getfsbyname", &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; - } - - f = extract_fstab(&inxdr); - xdr_destroy(&inxdr); - vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); - - return f; + return (struct fstab *)LI_getone("getfsbyname", &proc, extract_fstab, "name", name); } static void -lu_endfsent(void) +ds_endfsent(void) { - 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); + LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY)); } static int -lu_setfsent(void) +ds_setfsent(void) { - lu_endfsent(); + ds_endfsent(); return 1; } static struct fstab * -lu_getfsent() +ds_getfsent() { static int proc = -1; - struct lu_thread_info *tdata; - struct fstab *f; - 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) - { - if (proc < 0) - { - if (_lookup_link(_lu_port, "getfsent", &proc) != KERN_SUCCESS) - { - lu_endfsent(); - return NULL; - } - } - - if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS) - { - lu_endfsent(); - 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_endfsent(); - return NULL; - } - } - - if (tdata->lu_vm_cursor == 0) - { - lu_endfsent(); - return NULL; - } - - f = extract_fstab(tdata->lu_xdr); - if (f == NULL) - { - lu_endfsent(); - return NULL; - } - - tdata->lu_vm_cursor--; - - return f; + return (struct fstab *)LI_getent("getfsent", &proc, extract_fstab, ENTRY_KEY, ENTRY_SIZE); } static struct fstab * -lu_getfsfile(const char *name) +ds_getfsfile(const char *name) { struct fstab *fs; - if (name == NULL) return (struct fstab *)NULL; + if (name == NULL) return NULL; - setfsent(); - for (fs = lu_getfsent(); fs != NULL; fs = lu_getfsent()) + ds_setfsent(); + + for (fs = ds_getfsent(); fs != NULL; fs = ds_getfsent()) + { if (!strcmp(fs->fs_file, name)) return fs; + } - endfsent(); - return (struct fstab *)NULL; + ds_endfsent(); + + return NULL; } static struct fstab * getfs(const char *spec, const char *file, int source) { struct fstab *res = NULL; - struct lu_thread_info *tdata; + struct li_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); - } + tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); + if (tdata == NULL) return NULL; - if (_lu_running()) + if (_ds_running()) { switch (source) { case FS_GET_SPEC: - res = lu_getfsspec(spec); + res = ds_getfsspec(spec); break; case FS_GET_FILE: - res = lu_getfsfile(file); + res = ds_getfsfile(file); break; case FS_GET_ENT: - res = lu_getfsent(); - break; + res = ds_getfsent(); + break; default: res = NULL; } } else { pthread_mutex_lock(&_fstab_lock); + switch (source) { case FS_GET_SPEC: @@ -434,11 +220,12 @@ getfs(const char *spec, const char *file, int source) break; default: res = NULL; } + pthread_mutex_unlock(&_fstab_lock); } - recycle_fstab(tdata, res); - return (struct fstab *)tdata->lu_entry; + LI_data_recycle(tdata, res, ENTRY_SIZE); + return (struct fstab *)tdata->li_entry; } @@ -469,14 +256,13 @@ getfsent(void) int setfsent(void) { - if (_lu_running()) return (lu_setfsent()); + if (_ds_running()) return (ds_setfsent()); return (_old_setfsent()); } void endfsent(void) { - if (_lu_running()) lu_endfsent(); + if (_ds_running()) ds_endfsent(); else _old_endfsent(); } - diff --git a/lookup.subproj/lu_group.c b/lookup.subproj/lu_group.c index 844cd3c..05d7aca 100644 --- a/lookup.subproj/lu_group.c +++ b/lookup.subproj/lu_group.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2007 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -31,9 +31,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -41,180 +38,119 @@ #include #include #include - -#include "_lu_types.h" -#include "lookup.h" +#include #include "lu_utils.h" #include "lu_overrides.h" +#define ENTRY_SIZE sizeof(struct group) +#define ENTRY_KEY _li_data_key_group #define GROUP_CACHE_SIZE 10 -#define DEFAULT_GROUP_CACHE_TTL 10 static pthread_mutex_t _group_cache_lock = PTHREAD_MUTEX_INITIALIZER; -static void *_group_cache[GROUP_CACHE_SIZE] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -static unsigned int _group_cache_best_before[GROUP_CACHE_SIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static void *_group_cache[GROUP_CACHE_SIZE] = { NULL }; static unsigned int _group_cache_index = 0; -static unsigned int _group_cache_ttl = DEFAULT_GROUP_CACHE_TTL; +static unsigned int _group_cache_init = 0; static pthread_mutex_t _group_lock = PTHREAD_MUTEX_INITIALIZER; +/* + * Note that we don't include grp.h and define struct group privately in here + * to avoid needing to produce a variant version of setgrent, which changed + * for UXIX03 conformance. + */ +struct group +{ + char *gr_name; + char *gr_passwd; + gid_t gr_gid; + char **gr_mem; +}; + +/* forward */ +int setgrent(void); +struct group *getgrent(void); +void endgrent(void); + /* * Support for memberd calls */ #define MEMBERD_NAME "com.apple.memberd" -static mach_port_t mbr_port = MACH_PORT_NULL; typedef uint32_t GIDArray[16]; -extern kern_return_t _mbr_GetGroups(mach_port_t server, uint32_t uid, uint32_t *numGroups, GIDArray gids, security_token_t *token); +extern kern_return_t memberdDSmig_GetGroups(mach_port_t server, uint32_t uid, uint32_t *numGroups, GIDArray gids, audit_token_t *token); +extern kern_return_t memberdDSmig_GetAllGroups(mach_port_t server, uint32_t uid, uint32_t *numGroups, gid_t **gids, uint32_t *gidsCnt, audit_token_t *token); +__private_extern__ uid_t audit_token_uid(audit_token_t a); #define GR_GET_NAME 1 #define GR_GET_GID 2 #define GR_GET_ENT 3 -static void -free_group_data(struct group *g) +static struct group * +copy_group(struct group *in) { - char **mem; - - if (g == NULL) return; - - if (g->gr_name != NULL) free(g->gr_name); - if (g->gr_passwd != NULL) free(g->gr_passwd); + if (in == NULL) return NULL; - mem = g->gr_mem; - if (mem != NULL) - { - while (*mem != NULL) free(*mem++); - free(g->gr_mem); - } + return (struct group *)LI_ils_create("ss4*", in->gr_name, in->gr_passwd, in->gr_gid, in->gr_mem); } -static void -free_group(struct group *g) -{ - if (g == NULL) return; - free_group_data(g); - free(g); - } - -static void -free_lu_thread_info_group(void *x) +/* + * Extract the next group entry from a kvarray. + */ +static void * +extract_group(kvarray_t *in) { - struct lu_thread_info *tdata; - - if (x == NULL) return; + struct group tmp; + uint32_t d, k, kcount; + char *empty[1]; - tdata = (struct lu_thread_info *)x; + if (in == NULL) return NULL; - if (tdata->lu_entry != NULL) - { - free_group((struct group *)tdata->lu_entry); - tdata->lu_entry = NULL; - } + d = in->curr; + in->curr++; - _lu_data_free_vm_xdr(tdata); + if (d >= in->count) return NULL; - free(tdata); -} + empty[0] = NULL; + memset(&tmp, 0, ENTRY_SIZE); -static struct group * -extract_group(XDR *xdr) -{ - int i, j, nkeys, nvals, status; - char *key, **vals; - struct group *g; - - if (xdr == NULL) return NULL; + tmp.gr_gid = -2; - if (!xdr_int(xdr, &nkeys)) return NULL; + kcount = in->dict[d].kcount; - g = (struct group *)calloc(1, sizeof(struct group)); - g->gr_gid = -2; - - for (i = 0; i < nkeys; i++) + for (k = 0; k < kcount; k++) { - key = NULL; - vals = NULL; - nvals = 0; - - status = _lu_xdr_attribute(xdr, &key, &vals, &nvals); - if (status < 0) + if (!strcmp(in->dict[d].key[k], "gr_name")) { - free_group(g); - return NULL; - } + if (tmp.gr_name != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; - if (nvals == 0) - { - free(key); - continue; + tmp.gr_name = (char *)in->dict[d].val[k][0]; } - - j = 0; - - if ((g->gr_name == NULL) && (!strcmp("name", key))) + else if (!strcmp(in->dict[d].key[k], "gr_passwd")) { - g->gr_name = vals[0]; - j = 1; - } - else if ((g->gr_passwd == NULL) && (!strcmp("passwd", key))) - { - g->gr_passwd = vals[0]; - j = 1; + if (tmp.gr_passwd != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.gr_passwd = (char *)in->dict[d].val[k][0]; } - else if ((g->gr_gid == (gid_t)-2) && (!strcmp("gid", key))) + else if (!strcmp(in->dict[d].key[k], "gr_gid")) { - g->gr_gid = atoi(vals[0]); - if ((g->gr_gid == 0) && (strcmp(vals[0], "0"))) g->gr_gid = -2; + if (in->dict[d].vcount[k] == 0) continue; + tmp.gr_gid = atoi(in->dict[d].val[k][0]); } - else if ((g->gr_mem == NULL) && (!strcmp("users", key))) + else if (!strcmp(in->dict[d].key[k], "gr_mem")) { - g->gr_mem = vals; - j = nvals; - vals = NULL; - } + if (tmp.gr_mem != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; - free(key); - if (vals != NULL) - { - for (; j < nvals; j++) free(vals[j]); - free(vals); + tmp.gr_mem = (char **)in->dict[d].val[k]; } } - 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 *)); + if (tmp.gr_name == NULL) tmp.gr_name = ""; + if (tmp.gr_passwd == NULL) tmp.gr_passwd = ""; + if (tmp.gr_mem == NULL) tmp.gr_mem = empty; - return g; -} - -static struct group * -copy_group(struct group *in) -{ - struct group *g; - int i, len; - - if (in == NULL) return NULL; - - g = (struct group *)calloc(1, sizeof(struct group)); - - 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 = 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++) - { - g->gr_mem[i] = strdup(in->gr_mem[i]); - } - - return g; + return copy_group(&tmp); } static int @@ -298,110 +234,75 @@ copy_group_r(struct group *in, struct group *out, char *buffer, int buflen) } static void -recycle_group(struct lu_thread_info *tdata, struct group *in) +cache_group(struct group *gr) { - struct group *g; + struct group *grcache; - if (tdata == NULL) return; - g = (struct group *)tdata->lu_entry; + if (gr == NULL) return; - if (in == NULL) - { - free_group(g); - tdata->lu_entry = NULL; - } + pthread_mutex_lock(&_group_cache_lock); - if (tdata->lu_entry == NULL) - { - tdata->lu_entry = in; - return; - } + grcache = copy_group(gr); - free_group_data(g); + if (_group_cache[_group_cache_index] != NULL) LI_ils_free(_group_cache[_group_cache_index], ENTRY_SIZE); - g->gr_name = in->gr_name; - g->gr_passwd = in->gr_passwd; - g->gr_gid = in->gr_gid; - g->gr_mem = in->gr_mem; + _group_cache[_group_cache_index] = grcache; + _group_cache_index = (_group_cache_index + 1) % GROUP_CACHE_SIZE; - free(in); -} + _group_cache_init = 1; -__private_extern__ unsigned int -get_group_cache_ttl() -{ - return _group_cache_ttl; + pthread_mutex_unlock(&_group_cache_lock); } -__private_extern__ void -set_group_cache_ttl(unsigned int ttl) +static int +group_cache_check() { - int i; - - pthread_mutex_lock(&_group_cache_lock); + uint32_t i, status; - _group_cache_ttl = ttl; + /* don't consult cache if it has not been initialized */ + if (_group_cache_init == 0) return 1; - if (ttl == 0) - { - for (i = 0; i < GROUP_CACHE_SIZE; i++) - { - if (_group_cache[i] == NULL) continue; + status = LI_L1_cache_check(ENTRY_KEY); - free_group((struct group *)_group_cache[i]); - _group_cache[i] = NULL; - _group_cache_best_before[i] = 0; - } - } + /* don't consult cache if it is disabled or if we can't validate */ + if ((status == LI_L1_CACHE_DISABLED) || (status == LI_L1_CACHE_FAILED)) return 1; - pthread_mutex_unlock(&_group_cache_lock); -} - -static void -cache_group(struct group *gr) -{ - struct timeval now; - struct group *grcache; - - if (_group_cache_ttl == 0) return; - if (gr == NULL) return; + /* return 0 if cache is OK */ + if (status == LI_L1_CACHE_OK) return 0; + /* flush cache */ pthread_mutex_lock(&_group_cache_lock); - grcache = copy_group(gr); - - gettimeofday(&now, NULL); + for (i = 0; i < GROUP_CACHE_SIZE; i++) + { + LI_ils_free(_group_cache[i], ENTRY_SIZE); + _group_cache[i] = NULL; + } - if (_group_cache[_group_cache_index] != NULL) - free_group((struct group *)_group_cache[_group_cache_index]); - - _group_cache[_group_cache_index] = grcache; - _group_cache_best_before[_group_cache_index] = now.tv_sec + _group_cache_ttl; - _group_cache_index = (_group_cache_index + 1) % GROUP_CACHE_SIZE; + _group_cache_index = 0; pthread_mutex_unlock(&_group_cache_lock); + + /* don't consult cache - it's now empty */ + return 1; } + static struct group * cache_getgrnam(const char *name) { int i; struct group *gr, *res; - struct timeval now; - if (_group_cache_ttl == 0) return NULL; if (name == NULL) return NULL; + if (group_cache_check() != 0) return NULL; pthread_mutex_lock(&_group_cache_lock); - gettimeofday(&now, NULL); - for (i = 0; i < GROUP_CACHE_SIZE; i++) { - if (_group_cache_best_before[i] == 0) continue; - if ((unsigned int)now.tv_sec > _group_cache_best_before[i]) continue; - gr = (struct group *)_group_cache[i]; + if (gr == NULL) continue; if (gr->gr_name == NULL) continue; @@ -422,20 +323,15 @@ cache_getgrgid(int gid) { int i; struct group *gr, *res; - struct timeval now; - if (_group_cache_ttl == 0) return NULL; + if (group_cache_check() != 0) return NULL; pthread_mutex_lock(&_group_cache_lock); - gettimeofday(&now, NULL); - for (i = 0; i < GROUP_CACHE_SIZE; i++) { - if (_group_cache_best_before[i] == 0) continue; - if ((unsigned int)now.tv_sec > _group_cache_best_before[i]) continue; - gr = (struct group *)_group_cache[i]; + if (gr == NULL) continue; if ((gid_t)gid == gr->gr_gid) { @@ -450,122 +346,21 @@ cache_getgrgid(int gid) } static struct group * -lu_getgrgid(int gid) +ds_getgrgid(int gid) { - struct group *g; - unsigned int datalen; - XDR inxdr; static int proc = -1; - int count; - char *lookup_buf; - - if (proc < 0) - { - if (_lookup_link(_lu_port, "getgrgid", &proc) != KERN_SUCCESS) - { - return NULL; - } - } - - gid = htonl(gid); - datalen = 0; - lookup_buf = NULL; - - if (_lookup_all(_lu_port, proc, (unit *)&gid, 1, &lookup_buf, &datalen) != KERN_SUCCESS) - { - return NULL; - } + char val[16]; - 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; - } - - g = extract_group(&inxdr); - xdr_destroy(&inxdr); - vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); - - return g; + snprintf(val, sizeof(val), "%d", gid); + return (struct group *)LI_getone("getgrgid", &proc, extract_group, "gid", val); } static struct group * -lu_getgrnam(const char *name) +ds_getgrnam(const char *name) { - struct group *g; - 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, "getgrnam", &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) - { - 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; - } - - g = extract_group(&inxdr); - xdr_destroy(&inxdr); - vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); - - return g; + return (struct group *)LI_getone("getgrnam", &proc, extract_group, "name", name); } /* @@ -577,50 +372,69 @@ lu_getgrnam(const char *name) * returns -1 if adding the gid would overflow the list * */ -static int -_add_group(int gid, int *list, int *listcount, int max, int dupok, int laststatus) +static void +_add_group(gid_t g, gid_t **list, uint32_t *count, int dupok) { - int i, n, addit, status; - - if (laststatus != 0) return laststatus; + uint32_t i, n, addit; - status = 0; addit = 1; - n = *listcount; + + if (list == NULL) return; + if (*list == NULL) *count = 0; + + n = *count; if (dupok == 0) { for (i = 0; (i < n) && (addit == 1); i++) { - if (list[i] == gid) addit = 0; + if ((*list)[i] == g) addit = 0; } } - if (addit == 0) return 0; - if (n >= max) return -1; + if (addit == 0) return; - list[n] = gid; - *listcount = n + 1; - return 0; + if (*list == NULL) *list = (gid_t *)calloc(1, sizeof(gid_t)); + else *list = (gid_t *)realloc(*list, (n + 1) * sizeof(gid_t)); + + if (*list == NULL) + { + *count = 0; + return; + } + + (*list)[n] = g; + *count = n + 1; } int _old_getgrouplist(const char *uname, int basegid, int *groups, int *grpcnt) { struct group *grp; - int i, status, maxgroups; + int i, status; + uint32_t maxgroups, gg_count; + gid_t *gg_list; status = 0; - maxgroups = *grpcnt; + maxgroups = (uint32_t)*grpcnt; *grpcnt = 0; + gg_list = NULL; + gg_count = 0; + /* * When installing primary group, duplicate it; * the first element of groups is the effective gid * and will be overwritten when a setgid file is executed. */ - status = _add_group(basegid, groups, grpcnt, maxgroups, 0, status); - status = _add_group(basegid, groups, grpcnt, maxgroups, 1, status); + _add_group(basegid, &gg_list, &gg_count, 0); + _add_group(basegid, &gg_list, &gg_count, 1); + + if (gg_list == NULL) + { + errno = ENOMEM; + return 0; + } /* * Scan the group file to find additional groups. @@ -634,25 +448,31 @@ _old_getgrouplist(const char *uname, int basegid, int *groups, int *grpcnt) { if (!strcmp(grp->gr_mem[i], uname)) { - status = _add_group(grp->gr_gid, groups, grpcnt, maxgroups, 0, status); + _add_group(grp->gr_gid, &gg_list, &gg_count, 0); break; } } } endgrent(); - return status; -} -static int -_mbr_running() -{ - kern_return_t status; + if (gg_list == NULL) + { + errno = ENOMEM; + return 0; + } - status = bootstrap_look_up(bootstrap_port, MEMBERD_NAME, &mbr_port); - if (status != KERN_SUCCESS) return 0; - if (mbr_port == MACH_PORT_NULL) return 0; - return 1; + /* return -1 if the user-supplied list is too short */ + status = 0; + if (gg_count > maxgroups) status = -1; + + /* copy at most maxgroups gids from gg_list to groups */ + for (i = 0; (i < maxgroups) && (i < gg_count); i++) groups[i] = gg_list[i]; + + *grpcnt = gg_count; + free(gg_list); + + return status; } /* @@ -665,243 +485,250 @@ _mbr_running() * This adds to 6533 bytes (until one of the constants changes) */ #define MAXPWBUF (MAXLOGNAME + 1 + _PASSWORD_LEN + 1 + MAXPATHLEN + 1 + MAXPATHLEN + 1 + 4098) + +/* + * This is the "old" client side routine from memberd. + * It now talks to DirectoryService, but it retains the old style where + * the caller provides an array for the output gids. It fetches the + * user's gids from DS, then copies as many as possible into the + * caller-supplied array. + */ static int mbr_getgrouplist(const char *name, int basegid, int *groups, int *grpcnt, int dupbase) { struct passwd p, *res; char buf[MAXPWBUF]; kern_return_t kstatus; - uint32_t i, count; + uint32_t i, maxgroups, count, gidptrCnt, gg_count; int pwstatus; GIDArray gids; - int status, maxgroups; - security_token_t token; + gid_t *gidptr, *gg_list; + int status, do_dealloc; + audit_token_t token; - status = 0; - - if (mbr_port == MACH_PORT_NULL) return status; - if (name == NULL) return status; - if (groups == NULL) return status; - if (grpcnt == NULL) return status; + if (_ds_port == MACH_PORT_NULL) return 0; + if (name == NULL) return 0; + if (groups == NULL) return 0; + if (grpcnt == NULL) return 0; - maxgroups = *grpcnt; + maxgroups = (uint32_t)(*grpcnt); + do_dealloc = 0; *grpcnt = 0; + gidptr = NULL; + gidptrCnt = 0; + gg_list = NULL; + gg_count = 0; + + _add_group(basegid, &gg_list, &gg_count, 0); + if (dupbase != 0) _add_group(basegid, &gg_list, &gg_count, 1); - status = _add_group(basegid, groups, grpcnt, maxgroups, 0, status); - if (dupbase != 0) status = _add_group(basegid, groups, grpcnt, maxgroups, 1, status); - - if (status != 0) return status; + if (gg_list == NULL) + { + errno = ENOMEM; + return 0; + } memset(&p, 0, sizeof(struct passwd)); memset(buf, 0, sizeof(buf)); res = NULL; pwstatus = getpwnam_r(name, &p, buf, MAXPWBUF, &res); - if (pwstatus != 0) return status; - if (res == NULL) return status; - - token.val[0] = -1; - token.val[1] = -1; + if (pwstatus != 0) return 0; + if (res == NULL) return 0; count = 0; - kstatus = _mbr_GetGroups(mbr_port, p.pw_uid, &count, gids, &token); - if (kstatus != KERN_SUCCESS) return status; - if (token.val[0] != 0) return KERN_FAILURE; + memset(&token, 0, sizeof(audit_token_t)); + + kstatus = 0; + if (maxgroups > 16) + { + kstatus = memberdDSmig_GetAllGroups(_ds_port, p.pw_uid, &count, &gidptr, &gidptrCnt, &token); + do_dealloc = 1; + } + else + { + kstatus = memberdDSmig_GetGroups(_ds_port, p.pw_uid, &count, gids, &token); + gidptr = (gid_t *)gids; + } + + if (kstatus != KERN_SUCCESS) return 0; + if (audit_token_uid(token) != 0) + { + if (gg_list != NULL) free(gg_list); + return 0; + } + + for (i = 0; i < count; i++) _add_group(gidptr[i], &gg_list, &gg_count, 0); + + if ((do_dealloc == 1) && (gidptr != NULL)) vm_deallocate(mach_task_self(), (vm_address_t)gidptr, gidptrCnt); - for (i = 0; (i < count) && (status == 0); i++) + if (gg_list == NULL) { - status = _add_group(gids[i], groups, grpcnt, maxgroups, 0, status); + errno = ENOMEM; + return 0; } + /* return -1 if the user-supplied list is too short */ + status = 0; + if (gg_count > maxgroups) status = -1; + + /* copy at most maxgroups gids from gg_list to groups */ + for (i = 0; (i < maxgroups) && (i < gg_count); i++) groups[i] = gg_list[i]; + + *grpcnt = gg_count; + free(gg_list); + return status; } -static int -lu_getgrouplist(const char *name, int basegid, int *groups, int *grpcnt, int dupbase) +/* + * This is the "modern" routine for fetching the group list for a user. + * The grplist output parameter is allocated and filled with the gids + * of the specified user's groups. Returns the number of gids in the + * list or -1 on failure. Caller must free() the returns grplist. + */ +static int32_t +ds_getgrouplist(const char *name, gid_t basegid, gid_t **grplist, int dupbase) { - unsigned int datalen; - XDR outxdr; - XDR inxdr; - static int proc = -1; - char *lookup_buf; - char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT]; - int gid; - int i, count; - int status, maxgroups; - - status = 0; + struct passwd p, *res; + char buf[MAXPWBUF]; + kern_return_t kstatus; + uint32_t i, count, gidptrCnt, out_count; + int pwstatus; + gid_t *gidptr, *out_list; + audit_token_t token; - if (name == NULL) return status; - if (groups == NULL) return status; - if (grpcnt == NULL) return status; + if (_ds_port == MACH_PORT_NULL) return -1; + if (name == NULL) return -1; + if (grplist == NULL) return -1; - maxgroups = *grpcnt; - *grpcnt = 0; + gidptr = NULL; + gidptrCnt = 0; + out_list = NULL; + out_count = 0; - status = _add_group(basegid, groups, grpcnt, maxgroups, 0, status); - if (dupbase != 0) status = _add_group(basegid, groups, grpcnt, maxgroups, 1, status); + _add_group(basegid, &out_list, &out_count, 0); + if (dupbase != 0) _add_group(basegid, &out_list, &out_count, 1); - if (status != 0) return status; + if (out_list == NULL) return -1; - if (proc < 0) + memset(&p, 0, sizeof(struct passwd)); + memset(buf, 0, sizeof(buf)); + res = NULL; + + pwstatus = getpwnam_r(name, &p, buf, MAXPWBUF, &res); + if (pwstatus != 0) return -1; + if (res == NULL) return -1; + + count = 0; + memset(&token, 0, sizeof(audit_token_t)); + + kstatus = memberdDSmig_GetAllGroups(_ds_port, p.pw_uid, &count, &gidptr, &gidptrCnt, &token); + if (kstatus != KERN_SUCCESS) { - if (_lookup_link(_lu_port, "initgroups", &proc) != KERN_SUCCESS) return status; + if (out_list != NULL) free(out_list); + return -1; } - xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE); - if (!xdr__lu_string(&outxdr, (_lu_string *)&name)) + if (audit_token_uid(token) != 0) { - xdr_destroy(&outxdr); - return status; + if (out_list != NULL) free(out_list); + if (gidptr != NULL) vm_deallocate(mach_task_self(), (vm_address_t)gidptr, gidptrCnt); + return -1; } - datalen = 0; - lookup_buf = NULL; + for (i = 0; i < count; i++) _add_group(gidptr[i], &out_list, &out_count, 0); - if (_lookup_all(_lu_port, proc, (unit *)namebuf, xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, &lookup_buf, &datalen) != KERN_SUCCESS) - { - xdr_destroy(&outxdr); - return status; - } + if (gidptr != NULL) vm_deallocate(mach_task_self(), (vm_address_t)gidptr, gidptrCnt); - xdr_destroy(&outxdr); - - datalen *= BYTES_PER_XDR_UNIT; - if ((lookup_buf == NULL) || (datalen == 0)) return 0; + *grplist = out_list; + return out_count; +} - xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE); +static int +getgrouplist_internal(const char *name, int basegid, int *groups, int *grpcnt, int dupbase) +{ + int status, in_grpcnt; - if (!xdr_int(&inxdr, &count)) - { - xdr_destroy(&inxdr); - vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); - return status; - } + /* + * The man page says that the grpcnt parameter will be set to the actual number + * of groups that were found. Unfortunately, older impementations of this API + * have always set grpcnt to the number of groups that are being returned. + * To prevent regressions in callers of this API, we respect the old and + * incorrect implementation. + */ - for (i = 0; (i < count) && (status == 0); i++) - { - if (!xdr_int(&inxdr, &gid)) break; - status = _add_group(gid, groups, grpcnt, maxgroups, 0, status); - } + in_grpcnt = *grpcnt; + status = 0; - xdr_destroy(&inxdr); - vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); + if (_ds_running()) status = mbr_getgrouplist(name, basegid, groups, grpcnt, dupbase); + else status = _old_getgrouplist(name, basegid, groups, grpcnt); + if ((status < 0) && (*grpcnt > in_grpcnt)) *grpcnt = in_grpcnt; return status; } -static int -getgrouplist_internal(const char *name, int basegid, int *groups, int *grpcnt, int dupbase) +static int32_t +getgrouplist_internal_2(const char *name, gid_t basegid, gid_t **gid_list, int dupbase) { - if (_mbr_running()) - { - return mbr_getgrouplist(name, basegid, groups, grpcnt, dupbase); - } + int status; + uint32_t gid_count; - if (_lu_running()) - { - return lu_getgrouplist(name, basegid, groups, grpcnt, dupbase); - } + if (name == NULL) return -1; + if (gid_list == NULL) return -1; - return _old_getgrouplist(name, basegid, groups, grpcnt); + *gid_list = NULL; + + if (_ds_running()) return ds_getgrouplist(name, basegid, gid_list, dupbase); + + gid_count = NGROUPS + 1; + *gid_list = (gid_t *)calloc(gid_count, sizeof(gid_t)); + if (*gid_list == NULL) return -1; + + status = _old_getgrouplist(name, basegid, (int *)gid_list, (int *)&gid_count); + if (status < 0) return -1; + return gid_count; } int getgrouplist(const char *uname, int agroup, int *groups, int *grpcnt) { - return getgrouplist_internal(uname, agroup, groups, grpcnt, 1); + return getgrouplist_internal(uname, agroup, groups, grpcnt, 0); } -static void -lu_endgrent(void) +int32_t +getgrouplist_2(const char *uname, gid_t agroup, gid_t **groups) { - struct lu_thread_info *tdata; + return getgrouplist_internal_2(uname, agroup, groups, 0); +} - tdata = _lu_data_create_key(_lu_data_key_group, free_lu_thread_info_group); - _lu_data_free_vm_xdr(tdata); +static void +ds_endgrent(void) +{ + LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY)); } -static int -lu_setgrent(void) +static void +ds_setgrent(void) { - lu_endgrent(); - return 1; + ds_endgrent(); } static struct group * -lu_getgrent() +ds_getgrent() { - struct group *g; static int proc = -1; - 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); - } - - if (tdata->lu_vm == NULL) - { - if (proc < 0) - { - if (_lookup_link(_lu_port, "getgrent", &proc) != KERN_SUCCESS) - { - lu_endgrent(); - return NULL; - } - } - - if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS) - { - lu_endgrent(); - 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_endgrent(); - return NULL; - } - } - - if (tdata->lu_vm_cursor == 0) - { - lu_endgrent(); - return NULL; - } - - g = extract_group(tdata->lu_xdr); - if (g == NULL) - { - lu_endgrent(); - return NULL; - } - - tdata->lu_vm_cursor--; - - return g; + return (struct group *)LI_getent("getgrent", &proc, extract_group, ENTRY_KEY, ENTRY_SIZE); } static struct group * getgr_internal(const char *name, gid_t gid, int source) { struct group *res = NULL; - int from_cache; + int add_to_cache; - from_cache = 0; + add_to_cache = 0; res = NULL; switch (source) @@ -917,27 +744,29 @@ getgr_internal(const char *name, gid_t gid, int source) if (res != NULL) { - from_cache = 1; } - else if (_lu_running()) + else if (_ds_running()) { switch (source) { case GR_GET_NAME: - res = lu_getgrnam(name); + res = ds_getgrnam(name); break; case GR_GET_GID: - res = lu_getgrgid(gid); + res = ds_getgrgid(gid); break; case GR_GET_ENT: - res = lu_getgrent(); + res = ds_getgrent(); break; default: res = NULL; } + + if (res != NULL) add_to_cache = 1; } else { pthread_mutex_lock(&_group_lock); + switch (source) { case GR_GET_NAME: @@ -951,10 +780,11 @@ getgr_internal(const char *name, gid_t gid, int source) break; default: res = NULL; } + pthread_mutex_unlock(&_group_lock); } - if (from_cache == 0) cache_group(res); + if (add_to_cache == 1) cache_group(res); return res; } @@ -963,19 +793,15 @@ static struct group * getgr(const char *name, gid_t gid, int source) { struct group *res = NULL; - struct lu_thread_info *tdata; + struct li_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); - } + tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); + if (tdata == NULL) return NULL; res = getgr_internal(name, gid, source); - recycle_group(tdata, res); - return (struct group *)tdata->lu_entry; + LI_data_recycle(tdata, res, ENTRY_SIZE); + return (struct group *)tdata->li_entry; } static int @@ -985,19 +811,15 @@ getgr_r(const char *name, gid_t gid, int source, struct group *grp, char *buffer int status; *result = NULL; - errno = 0; res = getgr_internal(name, gid, source); - if (res == NULL) return -1; + if (res == NULL) return 0; status = copy_group_r(res, grp, buffer, bufsize); - free_group(res); - if (status != 0) - { - errno = ERANGE; - return -1; - } + LI_ils_free(res, ENTRY_SIZE); + + if (status != 0) return ERANGE; *result = grp; return 0; @@ -1006,14 +828,28 @@ getgr_r(const char *name, gid_t gid, int source, struct group *grp, char *buffer int initgroups(const char *name, int basegid) { - int status, ngroups, groups[NGROUPS]; + int status, pwstatus, ngroups, groups[NGROUPS]; + struct passwd p, *res; + char buf[MAXPWBUF]; + + /* get the UID for this user */ + memset(&p, 0, sizeof(struct passwd)); + memset(buf, 0, sizeof(buf)); + res = NULL; + + pwstatus = getpwnam_r(name, &p, buf, MAXPWBUF, &res); + if (pwstatus != 0) return -1; + if (res == NULL) return -1; ngroups = NGROUPS; status = getgrouplist_internal(name, basegid, groups, &ngroups, 0); if (status < 0) return status; - return setgroups(ngroups, groups); + status = syscall(SYS_initgroups, ngroups, groups, p.pw_uid); + if (status < 0) return -1; + + return 0; } struct group * @@ -1037,7 +873,7 @@ getgrent(void) int setgrent(void) { - if (_lu_running()) lu_setgrent(); + if (_ds_running()) ds_setgrent(); else _old_setgrent(); return 1; } @@ -1045,7 +881,7 @@ setgrent(void) void endgrent(void) { - if (_lu_running()) lu_endgrent(); + if (_ds_running()) ds_endgrent(); else _old_endgrent(); } diff --git a/lookup.subproj/lu_host.c b/lookup.subproj/lu_host.c index d9d178e..d671afa 100644 --- a/lookup.subproj/lu_host.c +++ b/lookup.subproj/lu_host.c @@ -38,58 +38,51 @@ #include #include #include - -#include "_lu_types.h" -#include "lookup.h" #include "lu_host.h" -#include "lu_utils.h" -#define HOST_CACHE_SIZE 10 -#define DEFAULT_HOST_CACHE_TTL 10 +#define ENTRY_SIZE sizeof(struct hostent) +#define ENTRY_KEY _li_data_key_host +#define HOST_CACHE_SIZE 20 #define CACHE_BYNAME 0 #define CACHE_BYADDR 1 static pthread_mutex_t _host_cache_lock = PTHREAD_MUTEX_INITIALIZER; -static unsigned int _host_cache_ttl = DEFAULT_HOST_CACHE_TTL; -static void *_host_byname_cache[HOST_CACHE_SIZE] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -static int _host_byname_cache_flavor[HOST_CACHE_SIZE] = { WANT_NOTHING, WANT_NOTHING, WANT_NOTHING, WANT_NOTHING, WANT_NOTHING, WANT_NOTHING, WANT_NOTHING, WANT_NOTHING, WANT_NOTHING, WANT_NOTHING }; -static unsigned int _host_byname_cache_best_before[HOST_CACHE_SIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static void *_host_byname_cache[HOST_CACHE_SIZE] = { NULL }; +static int _host_byname_cache_flavor[HOST_CACHE_SIZE] = { WANT_NOTHING }; static unsigned int _host_byname_cache_index = 0; -static void *_host_byaddr_cache[HOST_CACHE_SIZE] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -static int _host_byaddr_cache_flavor[HOST_CACHE_SIZE] = { WANT_NOTHING, WANT_NOTHING, WANT_NOTHING, WANT_NOTHING, WANT_NOTHING, WANT_NOTHING, WANT_NOTHING, WANT_NOTHING, WANT_NOTHING, WANT_NOTHING }; -static unsigned int _host_byaddr_cache_best_before[HOST_CACHE_SIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static void *_host_byaddr_cache[HOST_CACHE_SIZE] = { NULL }; +static int _host_byaddr_cache_flavor[HOST_CACHE_SIZE] = { WANT_NOTHING }; static unsigned int _host_byaddr_cache_index = 0; +static unsigned int _host_cache_init = 0; + static pthread_mutex_t _host_lock = PTHREAD_MUTEX_INITIALIZER; -extern struct hostent *_old_gethostbyaddr(); -extern struct hostent *_old_gethostbyname(); -extern struct hostent *_old_gethostent(); -extern void _old_sethostent(); -extern void _old_endhostent(); -extern void _old_sethostfile(); +__private_extern__ struct hostent *LI_files_gethostbyname(const char *name); +__private_extern__ struct hostent *LI_files_gethostbyname2(const char *name, int af); +__private_extern__ struct hostent *LI_files_gethostbyaddr(const void *addr, socklen_t len, int type); +__private_extern__ struct hostent *LI_files_gethostent(); +__private_extern__ void LI_files_sethostent(int stayopen); +__private_extern__ void LI_files_endhostent(); extern int _old_ether_hostton(const char *, struct ether_addr *); extern int _old_ether_ntohost(char *, const struct ether_addr *); -extern mach_port_t _lu_port; -extern int _lu_running(void); - extern int h_errno; #define IPV6_ADDR_LEN 16 #define IPV4_ADDR_LEN 4 -__private_extern__ void -free_host_data(struct hostent *h) +void +freehostent(struct hostent *h) { char **aliases; int i; - if (h == NULL) return; + if (LI_ils_free(h, ENTRY_SIZE) == 0) return; if (h->h_name != NULL) free(h->h_name); @@ -105,431 +98,399 @@ free_host_data(struct hostent *h) for (i = 0; h->h_addr_list[i] != NULL; i++) free(h->h_addr_list[i]); free(h->h_addr_list); } + free(h); } -void -freehostent(struct hostent *h) +static struct hostent * +copy_host(struct hostent *in) { - if (h == NULL) return; - free_host_data(h); - free(h); + if (in == NULL) return NULL; + + if (in->h_addrtype == AF_INET) + return (struct hostent *)LI_ils_create("s*44a", in->h_name, in->h_aliases, in->h_addrtype, in->h_length, in->h_addr_list); + + if (in->h_addrtype == AF_INET6) + return (struct hostent *)LI_ils_create("s*44c", in->h_name, in->h_aliases, in->h_addrtype, in->h_length, in->h_addr_list); + + return NULL; } static void -free_lu_thread_info_host(void *x) +_free_addr_list(char **l) { - struct lu_thread_info *tdata; + int i; - if (x == NULL) return; + if (l == NULL) return; + for (i = 0; l[i] != NULL; i++) free(l[i]); + free(l); +} - tdata = (struct lu_thread_info *)x; - - if (tdata->lu_entry != NULL) +/* map ipv4 addresses and append to v6 list */ +static int +_map_v4(char ***v6, uint32_t n6, char **v4, uint32_t n4) +{ + struct in6_addr a6; + uint32_t i; + + a6.__u6_addr.__u6_addr32[0] = 0x00000000; + a6.__u6_addr.__u6_addr32[1] = 0x00000000; + a6.__u6_addr.__u6_addr32[2] = htonl(0x0000ffff); + + if (*v6 == NULL) + { + *v6 = (char **)calloc(n4 + 1, sizeof(char *)); + } + else { - freehostent((struct hostent *)tdata->lu_entry); - tdata->lu_entry = NULL; + *v6 = (char **)reallocf(*v6, (n6 + n4 + 1) * sizeof(char *)); } - _lu_data_free_vm_xdr(tdata); + if (*v6 == NULL) return -1; + + for (i = 0; i < n4; i++) + { + (*v6)[n6] = (char *)calloc(1, IPV6_ADDR_LEN); + if ((*v6)[n6] == NULL) return -1; - free(tdata); + memcpy(&(a6.__u6_addr.__u6_addr32[3]), v4[i], IPV4_ADDR_LEN); + memcpy((*v6)[n6], &(a6.__u6_addr.__u6_addr32[0]), IPV6_ADDR_LEN); + + n6++; + } + + return 0; } __private_extern__ struct hostent * -extract_host(XDR *xdr, int want, int *err) +extract_host(kvarray_t *in, int want) { - 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; + struct hostent tmp, *out; + uint32_t i, d, k, kcount, vcount, v4count, v6count; + int status, addr_len; + int family, addr_count; + struct in_addr a4; + struct in6_addr a6; + char **v4addrs, **v6addrs; + char *empty[1]; + + v4addrs = NULL; + v6addrs = NULL; + v4count = 0; + v6count = 0; addr_count = 0; - addr_len = sizeof(u_long *); + addr_len = sizeof(void *); - if (xdr == NULL) - { - *err = NO_RECOVERY; - return NULL; - } + if (in == NULL) return NULL; - if (!xdr_int(xdr, &nkeys)) - { - *err = NO_RECOVERY; - return NULL; - } + d = in->curr; + in->curr++; - h = (struct hostent *)calloc(1, sizeof(struct hostent)); + if (d >= in->count) return NULL; + + empty[0] = NULL; + memset(&tmp, 0, ENTRY_SIZE); family = AF_INET; - h->h_length = IPV4_ADDR_LEN; + tmp.h_length = IPV4_ADDR_LEN; - if (want > WANT_A4_ONLY) + if (want != WANT_A4_ONLY) { family = AF_INET6; - h->h_length = IPV6_ADDR_LEN; + tmp.h_length = IPV6_ADDR_LEN; } - h->h_addrtype = family; - - for (i = 0; i < nkeys; i++) - { - key = NULL; - vals = NULL; - nvals = 0; + tmp.h_addrtype = family; - status = _lu_xdr_attribute(xdr, &key, &vals, &nvals); - if (status < 0) - { - freehostent(h); - *err = NO_RECOVERY; - return NULL; - } + kcount = in->dict[d].kcount; - if (nvals == 0) + for (k = 0; k < kcount; k++) + { + if (!strcmp(in->dict[d].key[k], "h_name")) { - free(key); - continue; - } + if (tmp.h_name != NULL) continue; - j = 0; + vcount = in->dict[d].vcount[k]; + if (vcount == 0) continue; - 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; + tmp.h_name = (char *)in->dict[d].val[k][0]; } - else if ((family == AF_INET) && (h->h_addr_list == NULL) && (!strcmp("ip_address", key))) + else if (!strcmp(in->dict[d].key[k], "h_aliases")) { - addr_count = nvals; - h->h_addr_list = (char **)calloc(nvals + 1, addr_len); + if (tmp.h_aliases != NULL) continue; - 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); - } + vcount = in->dict[d].vcount[k]; + if (vcount == 0) continue; - h->h_addr_list[nvals] = NULL; - j = 0; + tmp.h_aliases = (char **)in->dict[d].val[k]; } - else if ((family == AF_INET6) && (h->h_addr_list == NULL) && (!strcmp("ipv6_address", key))) + else if (!strcmp(in->dict[d].key[k], "h_ipv4_addr_list")) { - addr_count = nvals; - h->h_addr_list = (char **)calloc(nvals + 1, addr_len); + if (v4addrs != NULL) continue; + + v4count = in->dict[d].vcount[k]; + if (v4count == 0) continue; - for (j = 0; j < nvals; j++) + v4addrs = (char **)calloc(v4count + 1, sizeof(char *)); + if (v4addrs == NULL) { - 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); + _free_addr_list(v6addrs); + return NULL; } - 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; + for (i = 0; i < v4count; i++) + { + v4addrs[i] = calloc(1, IPV4_ADDR_LEN); + if (v4addrs[i] == NULL) + { + _free_addr_list(v4addrs); + _free_addr_list(v6addrs); + return NULL; + } + + memset(&a4, 0, sizeof(struct in_addr)); + status = inet_pton(AF_INET, in->dict[d].val[k][i], &a4); + if (status != 1) + { + _free_addr_list(v4addrs); + _free_addr_list(v6addrs); + return NULL; + } + + memcpy(v4addrs[i], &a4, IPV4_ADDR_LEN); + } } - - free(key); - if (vals != NULL) + else if (!strcmp(in->dict[d].key[k], "h_ipv6_addr_list")) { - for (; j < nvals; j++) free(vals[j]); - free(vals); - } - } + if (v6addrs != NULL) continue; - 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); + v6count = in->dict[d].vcount[k]; + if (v6count == 0) continue; - 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); - } + v6addrs = (char **)calloc(v6count + 1, sizeof(char *)); + if (v6addrs == NULL) + { + _free_addr_list(v4addrs); + return NULL; + } - 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); + for (i = 0; i < v6count; i++) + { + v6addrs[i] = calloc(1, IPV6_ADDR_LEN); + if (v6addrs[i] == NULL) + { + _free_addr_list(v4addrs); + _free_addr_list(v6addrs); + return NULL; + } + + memset(&a6, 0, sizeof(struct in6_addr)); + status = inet_pton(AF_INET6, in->dict[d].val[k][i], &a6); + if (status != 1) + { + _free_addr_list(v4addrs); + _free_addr_list(v6addrs); + return NULL; + } + + memcpy(v6addrs[i], &(a6.__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 (tmp.h_name == NULL) tmp.h_name = ""; + if (tmp.h_aliases == NULL) tmp.h_aliases = empty; - if (h->h_addr_list == NULL) + if (want == WANT_A4_ONLY) { - freehostent(h); - *err = NO_DATA; - return NULL; - } - - if (h->h_name == NULL) h->h_name = strdup(""); - if (h->h_aliases == NULL) h->h_aliases = (char **)calloc(1, sizeof(char *)); - - return h; -} - -static struct hostent * -copy_host(struct hostent *in) -{ - int i, len, addr_len; - struct hostent *h; + _free_addr_list(v6addrs); + if (v4addrs == NULL) return NULL; - if (in == NULL) return NULL; - - h = (struct hostent *)calloc(1, sizeof(struct hostent)); - - h->h_name = LU_COPY_STRING(in->h_name); + tmp.h_addr_list = v4addrs; + out = copy_host(&tmp); + _free_addr_list(v4addrs); - len = 0; - if (in->h_aliases != NULL) - { - for (len = 0; in->h_aliases[len] != NULL; len++); + return out; } - - h->h_aliases = (char **)calloc(len + 1, sizeof(char *)); - for (i = 0; i < len; i++) + else if ((want == WANT_A6_ONLY) || ((want == WANT_A6_OR_MAPPED_A4_IF_NO_A6) && (v6count > 0))) { - h->h_aliases[i] = strdup(in->h_aliases[i]); - } + _free_addr_list(v4addrs); + if (v6addrs == NULL) return NULL; - h->h_addrtype = in->h_addrtype; - h->h_length = in->h_length; + tmp.h_addr_list = v6addrs; + out = copy_host(&tmp); + _free_addr_list(v6addrs); - len = 0; - if (in->h_addr_list != NULL) - { - for (len = 0; in->h_addr_list[len] != NULL; 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); + return out; } - return h; -} - -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; + /* + * At this point, want is WANT_A6_PLUS_MAPPED_A4, WANT_MAPPED_A4_ONLY, + * or WANT_A6_OR_MAPPED_A4_IF_NO_A6. In the last case, there are no ipv6 + * addresses, so that case degenerates into WANT_MAPPED_A4_ONLY. + */ + if (want == WANT_A6_OR_MAPPED_A4_IF_NO_A6) want = WANT_MAPPED_A4_ONLY; - if (in == NULL) + if (want == WANT_MAPPED_A4_ONLY) { - freehostent(h); - tdata->lu_entry = NULL; + _free_addr_list(v6addrs); + v6addrs = NULL; + v6count = 0; } - if (tdata->lu_entry == NULL) + status = _map_v4(&v6addrs, v6count, v4addrs, v4count); + _free_addr_list(v4addrs); + if (status != 0) { - tdata->lu_entry = in; - return; + _free_addr_list(v6addrs); + return NULL; } - free_host_data(h); + if (v6addrs == NULL) return NULL; - 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; + tmp.h_addr_list = v6addrs; + out = copy_host(&tmp); + _free_addr_list(v6addrs); - free(in); + return out; } __private_extern__ struct hostent * fake_hostent(const char *name, struct in_addr addr) { - int addr_len; - struct hostent *h; + struct hostent tmp; + char *addrs[2]; + char *aliases[1]; 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 *)); + memset(&tmp, 0, ENTRY_SIZE); - h->h_addrtype = AF_INET; - h->h_length = sizeof(long); + tmp.h_name = (char *)name; + tmp.h_addrtype = AF_INET; + tmp.h_length = IPV4_ADDR_LEN; + tmp.h_addr_list = addrs; + addrs[0] = (char *)&(addr.s_addr); + addrs[1] = NULL; + tmp.h_aliases = aliases; + aliases[0] = NULL; - 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; + return copy_host(&tmp); } __private_extern__ struct hostent * fake_hostent6(const char *name, struct in6_addr addr) { - int addr_len; - struct hostent *h; + struct hostent tmp; + char *addrs[2]; + char *aliases[1]; 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; + memset(&tmp, 0, ENTRY_SIZE); - addr_len = sizeof(u_long *); - h->h_addr_list = (char **)calloc(2, addr_len); + tmp.h_name = (char *)name; + tmp.h_addrtype = AF_INET6; + tmp.h_length = IPV6_ADDR_LEN; + tmp.h_addr_list = addrs; + addrs[0] = (char *)&(addr.__u6_addr.__u6_addr32[0]); + addrs[1] = NULL; + tmp.h_aliases = aliases; + aliases[0] = NULL; - 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; -} - -__private_extern__ unsigned int -get_host_cache_ttl() -{ - return _host_cache_ttl; -} - -__private_extern__ void -set_host_cache_ttl(unsigned int ttl) -{ - int i; - - pthread_mutex_lock(&_host_cache_lock); - - _host_cache_ttl = ttl; - - if (ttl == 0) - { - for (i = 0; i < HOST_CACHE_SIZE; i++) - { - if (_host_byname_cache[i] == NULL) continue; - - freehostent((struct hostent *)_host_byname_cache[i]); - _host_byname_cache[i] = NULL; - _host_byname_cache_flavor[i] = WANT_NOTHING; - _host_byname_cache_best_before[i] = 0; - } - - for (i = 0; i < HOST_CACHE_SIZE; i++) - { - if (_host_byaddr_cache[i] == NULL) continue; - - freehostent((struct hostent *)_host_byaddr_cache[i]); - _host_byaddr_cache[i] = NULL; - _host_byaddr_cache_flavor[i] = WANT_NOTHING; - _host_byaddr_cache_best_before[i] = 0; - } - } - - pthread_mutex_unlock(&_host_cache_lock); + return copy_host(&tmp); } static void cache_host(struct hostent *h, int want, int how) { - struct timeval now; struct hostent *hcache; - if (_host_cache_ttl == 0) return; if (h == NULL) return; pthread_mutex_lock(&_host_cache_lock); hcache = copy_host(h); - gettimeofday(&now, NULL); - if (how == CACHE_BYNAME) { - if (_host_byname_cache[_host_byname_cache_index] != NULL) - freehostent((struct hostent *)_host_byname_cache[_host_byname_cache_index]); + if (_host_byname_cache[_host_byname_cache_index] != NULL) LI_ils_free(_host_byname_cache[_host_byname_cache_index], ENTRY_SIZE); _host_byname_cache[_host_byname_cache_index] = hcache; _host_byname_cache_flavor[_host_byname_cache_index] = want; - _host_byname_cache_best_before[_host_byname_cache_index] = now.tv_sec + _host_cache_ttl; _host_byname_cache_index = (_host_byname_cache_index + 1) % HOST_CACHE_SIZE; } else { - if (_host_byaddr_cache[_host_byaddr_cache_index] != NULL) - freehostent((struct hostent *)_host_byaddr_cache[_host_byaddr_cache_index]); + if (_host_byaddr_cache[_host_byaddr_cache_index] != NULL) LI_ils_free(_host_byaddr_cache[_host_byaddr_cache_index], ENTRY_SIZE); _host_byaddr_cache[_host_byaddr_cache_index] = hcache; _host_byaddr_cache_flavor[_host_byaddr_cache_index] = want; - _host_byaddr_cache_best_before[_host_byaddr_cache_index] = now.tv_sec + _host_cache_ttl; _host_byaddr_cache_index = (_host_byaddr_cache_index + 1) % HOST_CACHE_SIZE; } + _host_cache_init = 1; + pthread_mutex_unlock(&_host_cache_lock); } +static int +host_cache_check() +{ + uint32_t i, status; + + /* don't consult cache if it has not been initialized */ + if (_host_cache_init == 0) return 1; + + status = LI_L1_cache_check(ENTRY_KEY); + + /* don't consult cache if it is disabled or if we can't validate */ + if ((status == LI_L1_CACHE_DISABLED) || (status == LI_L1_CACHE_FAILED)) return 1; + + /* return 0 if cache is OK */ + if (status == LI_L1_CACHE_OK) return 0; + + /* flush cache */ + pthread_mutex_lock(&_host_cache_lock); + + for (i = 0; i < HOST_CACHE_SIZE; i++) + { + LI_ils_free(_host_byname_cache[i], ENTRY_SIZE); + _host_byname_cache[i] = NULL; + _host_byname_cache_flavor[i] = WANT_NOTHING; + + LI_ils_free(_host_byaddr_cache[i], ENTRY_SIZE); + _host_byaddr_cache[i] = NULL; + _host_byaddr_cache_flavor[i] = WANT_NOTHING; + } + + _host_byname_cache_index = 0; + _host_byaddr_cache_index = 0; + + pthread_mutex_unlock(&_host_cache_lock); + + /* don't consult cache - it's now empty */ + return 1; +} + + static struct hostent * cache_gethostbyname(const char *name, int want) { int i; struct hostent *h, *res; char **aliases; - struct timeval now; - if (_host_cache_ttl == 0) return NULL; if (name == NULL) return NULL; + if (host_cache_check() != 0) return NULL; pthread_mutex_lock(&_host_cache_lock); - gettimeofday(&now, NULL); - for (i = 0; i < HOST_CACHE_SIZE; i++) { - if (_host_byname_cache_best_before[i] == 0) continue; - if ((unsigned int)now.tv_sec > _host_byname_cache_best_before[i]) continue; - if (_host_byname_cache_flavor[i] != want) continue; h = (struct hostent *)_host_byname_cache[i]; + if (h == NULL) continue; if (h->h_name != NULL) { @@ -568,26 +529,21 @@ cache_gethostbyaddr(const char *addr, int want) { int i, j, len; struct hostent *h, *res; - struct timeval now; if (addr == NULL) return NULL; - if (_host_cache_ttl == 0) return NULL; + if (host_cache_check() != 0) return NULL; pthread_mutex_lock(&_host_cache_lock); - gettimeofday(&now, NULL); - len = IPV4_ADDR_LEN; if (want > WANT_A4_ONLY) len = IPV6_ADDR_LEN; for (i = 0; i < HOST_CACHE_SIZE; i++) { - if (_host_byaddr_cache_best_before[i] == 0) continue; - if ((unsigned int)now.tv_sec > _host_byaddr_cache_best_before[i]) continue; - if (_host_byaddr_cache_flavor[i] != want) continue; h = (struct hostent *)_host_byaddr_cache[i]; + if (h == NULL) continue; if (h->h_addr_list == NULL) continue; @@ -607,316 +563,277 @@ cache_gethostbyaddr(const char *addr, int want) } static struct hostent * -lu_gethostbyaddr(const char *addr, int want, int *err) +ds_gethostbyaddr(const char *paddr, uint32_t family, int *err) { - 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 hostent *entry; + kvbuf_t *request; + kvarray_t *reply; + kern_return_t status; + static int proc = -1; struct in_addr addr4; struct in6_addr addr6; + char tmp[64]; + int want; - family = AF_INET; - len = IPV4_ADDR_LEN; - if ((want == WANT_A6_ONLY) || (want == WANT_A6_PLUS_MAPPED_A4)) + if (paddr == NULL) { - family = AF_INET6; - len = IPV6_ADDR_LEN; + if (err != NULL) *err = NO_RECOVERY; + return NULL; } - if ((family == AF_INET) && (proc4 < 0)) + if (proc < 0) { - if (_lookup_link(_lu_port, "gethostbyaddr", &proc4) != KERN_SUCCESS) + status = LI_DSLookupGetProcedureNumber("gethostbyaddr", &proc); + if (status != KERN_SUCCESS) { - *err = NO_RECOVERY; + if (err != NULL) *err = NO_RECOVERY; return NULL; } } - else if ((family == AF_INET6) && (proc6 < 0)) + + memset(&addr4, 0, sizeof(struct in_addr)); + memset(&addr6, 0, sizeof(struct in6_addr)); + memset(tmp, 0, sizeof(tmp)); + want = WANT_A4_ONLY; + + if (family == AF_INET) { - if (_lookup_link(_lu_port, "getipv6nodebyaddr", &proc6) != KERN_SUCCESS) + want = WANT_A4_ONLY; + memcpy(&(addr4.s_addr), paddr, IPV4_ADDR_LEN); + if (inet_ntop(family, &addr4, tmp, sizeof(tmp)) == NULL) { - *err = NO_RECOVERY; + if (err != NULL) *err = NO_RECOVERY; return NULL; } } - - address = NULL; - - if (family == AF_INET) + else if (family == AF_INET6) { - memmove(&(addr4.s_addr), addr, IPV4_ADDR_LEN); - address = (char *)&(addr4.s_addr); - proc = proc4; + want = WANT_A6_ONLY; + memcpy(addr6.s6_addr, paddr, IPV6_ADDR_LEN); + if (inet_ntop(family, &addr6, tmp, sizeof(tmp)) == NULL) + { + if (err != NULL) *err = NO_RECOVERY; + return NULL; + } } 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 = HOST_NOT_FOUND; + if (err != NULL) *err = NO_RECOVERY; 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)) + request = kvbuf_query("ksku", "address", tmp, "family", family); + if (request == NULL) { - xdr_destroy(&inxdr); - vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); - *err = NO_RECOVERY; + if (err != NULL) *err = NO_RECOVERY; return NULL; } - if (count == 0) + reply = NULL; + status = LI_DSLookupQuery(proc, request, &reply); + kvbuf_free(request); + + if (status != KERN_SUCCESS) { - xdr_destroy(&inxdr); - vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); - *err = HOST_NOT_FOUND; + if (err != NULL) *err = NO_RECOVERY; return NULL; } - *err = 0; + if (err != NULL) *err = 0; + entry = extract_host(reply, want); - h = extract_host(&inxdr, want, err); - xdr_destroy(&inxdr); - vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); + if ((entry == NULL) && (err != NULL)) *err = HOST_NOT_FOUND; + kvarray_free(reply); - return h; + return entry; } static struct hostent * -lu_gethostbyname(const char *name, int want, int *err) +ds_gethostbyname(const char *name, uint32_t want, int *err) { - struct hostent *h; - unsigned int datalen; - char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT]; - XDR outxdr; - XDR inxdr; - static int proc4 = -1; - static int proc6 = -1; - char *lookup_buf; - int proc, count, family; + struct hostent *entry; + kvbuf_t *request; + kvarray_t *reply; + kern_return_t status; + static int proc = -1; + uint32_t want4, want6; - family = AF_INET; - if (want > WANT_A4_ONLY) family = AF_INET6; + want4 = 1; + want6 = 1; + + if (want == WANT_A4_ONLY) want6 = 0; + else if (want == WANT_A6_ONLY) want4 = 0; + else if (WANT_MAPPED_A4_ONLY) want6 = 0; - if (((want == WANT_MAPPED_A4_ONLY) || (family == AF_INET)) && (proc4 < 0)) + if (name == NULL) { - if (_lookup_link(_lu_port, "gethostbyname", &proc4) != KERN_SUCCESS) - { - *err = NO_RECOVERY; - return NULL; - } + if (err != NULL) *err = NO_RECOVERY; + return NULL; } - else if ((family == AF_INET6) && (proc6 < 0)) + + if (proc < 0) { - if (_lookup_link(_lu_port, "getipv6nodebyname", &proc6) != KERN_SUCCESS) + status = LI_DSLookupGetProcedureNumber("gethostbyname", &proc); + if (status != KERN_SUCCESS) { - *err = NO_RECOVERY; + if (err != NULL) *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, (_lu_string *)&name)) + request = kvbuf_query("kskuku", "name", name, "ipv4", want4, "ipv6", want6); + if (request == NULL) { - xdr_destroy(&outxdr); - *err = NO_RECOVERY; + if (err != NULL) *err = NO_RECOVERY; return NULL; } - datalen = 0; - lookup_buf = NULL; + reply = NULL; + status = LI_DSLookupQuery(proc, request, &reply); + kvbuf_free(request); - if (_lookup_all(_lu_port, proc, (unit *)namebuf, xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, &lookup_buf, &datalen) != KERN_SUCCESS) + if (status != KERN_SUCCESS) { - xdr_destroy(&outxdr); - *err = HOST_NOT_FOUND; + if (err != NULL) *err = NO_RECOVERY; 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); + if (err != NULL) *err = 0; + entry = extract_host(reply, want); + if ((entry == NULL) && (err != NULL)) *err = HOST_NOT_FOUND; + kvarray_free(reply); - 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); - 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); - - return h; + return entry; } static void -lu_endhostent() +ds_endhostent() { - 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); + LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY)); } static void -lu_sethostent() +ds_sethostent() { - lu_endhostent(); + ds_endhostent(); } static struct hostent * -lu_gethostent(int want, int *err) +ds_gethostent(int *err) { + struct hostent *entry; + struct li_thread_info *tdata; + kvarray_t *reply, *vma; + kern_return_t status; static int proc = -1; - struct lu_thread_info *tdata; - struct hostent *h; - tdata = _lu_data_create_key(_lu_data_key_host, free_lu_thread_info_host); + tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); 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 (err != NULL) *err = NO_RECOVERY; + return NULL; } - if (tdata->lu_vm == NULL) + if (tdata->li_vm == NULL) { if (proc < 0) { - if (_lookup_link(_lu_port, "gethostent", &proc) != KERN_SUCCESS) + status = LI_DSLookupGetProcedureNumber("gethostent", &proc); + if (status != KERN_SUCCESS) { - lu_endhostent(); - *err = NO_RECOVERY; + if (err != NULL) *err = NO_RECOVERY; + LI_data_free_kvarray(tdata); + tdata->li_vm = NULL; return NULL; } } - if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS) + reply = NULL; + status = LI_DSLookupQuery(proc, NULL, &reply); + + if (status != KERN_SUCCESS) { - lu_endhostent(); - *err = HOST_NOT_FOUND; + if (err != NULL) *err = NO_RECOVERY; + LI_data_free_kvarray(tdata); + tdata->li_vm = NULL; return NULL; } - /* mig stubs measure size in words (4 bytes) */ - tdata->lu_vm_length *= 4; + tdata->li_vm = (char *)reply; + } - if (tdata->lu_xdr != NULL) - { - xdr_destroy(tdata->lu_xdr); - free(tdata->lu_xdr); - } - tdata->lu_xdr = (XDR *)calloc(1, sizeof(XDR)); + if (err != NULL) *err = 0; - 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_endhostent(); - *err = NO_RECOVERY; - return NULL; - } + vma = (kvarray_t *)(tdata->li_vm); + if (vma == NULL) + { + if (err != NULL) *err = HOST_NOT_FOUND; + return NULL; } - if (tdata->lu_vm_cursor == 0) + /* + * gethostent only returns IPv4 addresses, but the reply + * from Directory Service may contain a mix of IPv4 and Ipv6 + * entries. extract_host will return NULL if the current + * dictionary is not the family we want, so we loop until + * we get the next IPv4 entry or we run out of entries. + */ + entry = NULL; + while ((vma->curr < vma->count) && (entry == NULL)) { - lu_endhostent(); - *err = HOST_NOT_FOUND; - return NULL; + entry = extract_host(vma, WANT_A4_ONLY); } - h = extract_host(tdata->lu_xdr, want, err); - if (h == NULL) + if (entry == NULL) { - lu_endhostent(); - *err = HOST_NOT_FOUND; + if (err != NULL) *err = HOST_NOT_FOUND; + LI_data_free_kvarray(tdata); + tdata->li_vm = NULL; return NULL; } - *err = 0; - tdata->lu_vm_cursor--; - - return h; + return entry; } static struct hostent * -gethostbyaddrerrno(const char *addr, int len, int type, int *err) +gethostbyaddrerrno(const char *addr, int len, uint32_t family, int *err) { struct hostent *res = NULL; - int want, from_cache; + int want, add_to_cache; - *err = 0; + if (err != NULL) *err = 0; want = WANT_A4_ONLY; - if (type == AF_INET6) want = WANT_A6_ONLY; + if (family == AF_INET6) want = WANT_A6_ONLY; - if ((type == AF_INET6) && (len == 16) && (is_a4_mapped((const char *)addr) || is_a4_compat((const char *)addr))) + if ((family == AF_INET6) && (len == IPV6_ADDR_LEN) && (is_a4_mapped((const char *)addr) || is_a4_compat((const char *)addr))) { addr += 12; len = 4; - type = AF_INET; + family = AF_INET; want = WANT_MAPPED_A4_ONLY; } - from_cache = 0; + add_to_cache = 0; res = cache_gethostbyaddr(addr, want); if (res != NULL) { - from_cache = 1; } - else if (_lu_running()) + else if (_ds_running()) { - res = lu_gethostbyaddr(addr, want, err); + res = ds_gethostbyaddr(addr, family, err); + if (res != NULL) add_to_cache = 1; } else { pthread_mutex_lock(&_host_lock); - res = copy_host(_old_gethostbyaddr(addr, len, type)); - *err = h_errno; + res = copy_host(LI_files_gethostbyaddr(addr, len, family)); + if (err != NULL) *err = h_errno; pthread_mutex_unlock(&_host_lock); } - if (from_cache == 0) cache_host(res, want, CACHE_BYADDR); + if (add_to_cache == 1) cache_host(res, want, CACHE_BYADDR); return res; } @@ -925,33 +842,26 @@ struct hostent * gethostbyaddr(const void *addr, socklen_t len, int type) { struct hostent *res; - struct lu_thread_info *tdata; + struct li_thread_info *tdata; res = gethostbyaddrerrno(addr, len, type, &h_errno); - if (res == NULL) - { - return NULL; - } + 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); - } + tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); + if (tdata == NULL) return NULL; - recycle_host(tdata, res); - return (struct hostent *)tdata->lu_entry; + LI_data_recycle(tdata, res, ENTRY_SIZE); + return (struct hostent *)tdata->li_entry; } - + struct hostent * gethostbynameerrno(const char *name, int *err) { struct hostent *res = NULL; struct in_addr addr; - int i, is_addr, from_cache; + int i, is_addr, add_to_cache; - *err = 0; + if (err != NULL) *err = 0; /* * If name is all dots and digits without a trailing dot, @@ -962,13 +872,13 @@ gethostbynameerrno(const char *name, int *err) */ if (name == NULL) { - *err = HOST_NOT_FOUND; + if (err != NULL) *err = HOST_NOT_FOUND; return NULL; } if (name[0] == '\0') { - *err = HOST_NOT_FOUND; + if (err != NULL) *err = HOST_NOT_FOUND; return NULL; } @@ -984,13 +894,13 @@ gethostbynameerrno(const char *name, int *err) if ((is_addr == 1) && (name[i-1] == '.')) is_addr = 0; res = NULL; - from_cache = 0; + add_to_cache = 0; if (is_addr == 1) { if (inet_aton(name, &addr) == 0) { - *err = HOST_NOT_FOUND; + if (err != NULL) *err = HOST_NOT_FOUND; return NULL; } res = fake_hostent(name, addr); @@ -1003,17 +913,17 @@ gethostbynameerrno(const char *name, int *err) if (res != NULL) { - from_cache = 1; } - else if (_lu_running()) + else if (_ds_running()) { - res = lu_gethostbyname(name, WANT_A4_ONLY, err); + res = ds_gethostbyname(name, WANT_A4_ONLY, err); + if (res != NULL) add_to_cache = 1; } else { pthread_mutex_lock(&_host_lock); - res = copy_host(_old_gethostbyname(name)); - *err = h_errno; + res = copy_host(LI_files_gethostbyname(name)); + if (err != NULL) *err = h_errno; pthread_mutex_unlock(&_host_lock); } @@ -1021,7 +931,7 @@ gethostbynameerrno(const char *name, int *err) { if (inet_aton(name, &addr) == 0) { - *err = HOST_NOT_FOUND; + if (err != NULL) *err = HOST_NOT_FOUND; return NULL; } @@ -1032,7 +942,7 @@ gethostbynameerrno(const char *name, int *err) } } - if (from_cache == 0) cache_host(res, WANT_A4_ONLY, CACHE_BYNAME); + if (add_to_cache == 1) cache_host(res, WANT_A4_ONLY, CACHE_BYNAME); return res; } @@ -1041,89 +951,74 @@ struct hostent * gethostbyname(const char *name) { struct hostent *res; - struct lu_thread_info *tdata; + struct li_thread_info *tdata; res = gethostbynameerrno(name, &h_errno); - if (res == NULL) - { - return NULL; - } + 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); - } + tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); + if (tdata == NULL) return NULL; - recycle_host(tdata, res); - return (struct hostent *)tdata->lu_entry; + LI_data_recycle(tdata, res, ENTRY_SIZE); + return (struct hostent *)tdata->li_entry; } struct hostent * -gethostbyname2(const char *name, int af) +gethostbyname2(const char *name, int family) { struct hostent *res; - struct lu_thread_info *tdata; + struct li_thread_info *tdata; - res = getipnodebyname(name, af, 0, &h_errno); + res = getipnodebyname(name, family, 0, &h_errno); if (res == NULL) { errno = EAFNOSUPPORT; 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); - } + tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); + if (tdata == NULL) return NULL; - recycle_host(tdata, res); - return (struct hostent *)tdata->lu_entry; + LI_data_recycle(tdata, res, ENTRY_SIZE); + return (struct hostent *)tdata->li_entry; } struct hostent * gethostent(void) { struct hostent *res = NULL; - struct lu_thread_info *tdata; + struct li_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); - } + tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); + if (tdata == NULL) return NULL; - if (_lu_running()) + if (_ds_running()) { - res = lu_gethostent(WANT_A4_ONLY, &h_errno); + res = ds_gethostent(&h_errno); } else { pthread_mutex_lock(&_host_lock); - res = copy_host(_old_gethostent()); + res = copy_host(LI_files_gethostent()); pthread_mutex_unlock(&_host_lock); } - recycle_host(tdata, res); - return (struct hostent *)tdata->lu_entry; + LI_data_recycle(tdata, res, ENTRY_SIZE); + return (struct hostent *)tdata->li_entry; } void sethostent(int stayopen) { - if (_lu_running()) lu_sethostent(); - else _old_sethostent(stayopen); + if (_ds_running()) ds_sethostent(); + else LI_files_sethostent(stayopen); } void endhostent(void) { - if (_lu_running()) lu_endhostent(); - else _old_endhostent(); + if (_ds_running()) ds_endhostent(); + else LI_files_endhostent(); } __private_extern__ int @@ -1148,7 +1043,7 @@ is_a4_mapped(const char *s) return 1; } - + __private_extern__ int is_a4_compat(const char *s) { @@ -1180,17 +1075,14 @@ is_a4_compat(const char *s) } struct hostent * -getipnodebyaddr(const void *src, size_t len, int af, int *err) +getipnodebyaddr(const void *src, size_t len, int family, int *err) { struct hostent *res; - *err = 0; + if (err != NULL) *err = 0; - res = gethostbyaddrerrno((const char *)src, len, af, err); - if (res == NULL) - { - return NULL; - } + res = gethostbyaddrerrno((const char *)src, len, family, err); + if (res == NULL) return NULL; if (res->h_name == NULL) { @@ -1202,9 +1094,9 @@ getipnodebyaddr(const void *src, size_t len, int af, int *err) } struct hostent * -getipnodebyname(const char *name, int af, int flags, int *err) +getipnodebyname(const char *name, int family, int flags, int *err) { - int status, want, really_want, if4, if6, from_cache; + int status, want, if4, if6, add_to_cache; struct hostent *res; struct ifaddrs *ifa, *ifap; struct in_addr addr4; @@ -1213,9 +1105,9 @@ getipnodebyname(const char *name, int af, int flags, int *err) memset(&addr4, 0, sizeof(struct in_addr)); memset(&addr6, 0, sizeof(struct in6_addr)); - *err = 0; + if (err != NULL) *err = 0; - if (af == AF_INET) + if (family == AF_INET) { status = inet_aton(name, &addr4); if (status == 1) @@ -1225,21 +1117,22 @@ getipnodebyname(const char *name, int af, int flags, int *err) return res; } } - else if (af == AF_INET6) + else if (family == AF_INET6) { - status = inet_pton(af, name, &addr6); + status = inet_pton(family, 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; + if (err != NULL) *err = HOST_NOT_FOUND; return NULL; } @@ -1255,7 +1148,7 @@ getipnodebyname(const char *name, int af, int flags, int *err) } else { - *err = NO_RECOVERY; + if (err != NULL) *err = NO_RECOVERY; return NULL; } @@ -1270,7 +1163,7 @@ getipnodebyname(const char *name, int af, int flags, int *err) { if (getifaddrs(&ifa) < 0) { - *err = NO_RECOVERY; + if (err != NULL) *err = NO_RECOVERY; return NULL; } @@ -1287,7 +1180,7 @@ getipnodebyname(const char *name, int af, int flags, int *err) /* Bail out if there are no interfaces */ if ((if4 == 0) && (if6 == 0)) { - *err = NO_ADDRESS; + if (err != NULL) *err = NO_ADDRESS; return NULL; } } @@ -1297,184 +1190,215 @@ getipnodebyname(const char *name, int af, int flags, int *err) * If user asked for AF_INET, we only want V4 addresses. */ want = WANT_A4_ONLY; - really_want = want; - if (af == AF_INET) + if (family == AF_INET) { - want = WANT_A4_ONLY; if ((flags & AI_ADDRCONFIG) && (if4 == 0)) { - *err = NO_ADDRESS; + if (err != NULL) *err = NO_ADDRESS; return NULL; } } else { - /* af == AF_INET6 */ + /* family == AF_INET6 */ want = WANT_A6_ONLY; - really_want = want; - if (flags & (AI_V4MAPPED|AI_V4MAPPED_CFG)) + + 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; + want = WANT_A6_OR_MAPPED_A4_IF_NO_A6; } } else { if ((flags & AI_ADDRCONFIG) && (if6 == 0)) { - *err = NO_ADDRESS; + if (err != NULL) *err = NO_ADDRESS; return NULL; } } } - from_cache = 0; + add_to_cache = 0; res = cache_gethostbyname(name, want); if (res != NULL) { - from_cache = 1; } - else if (_lu_running()) + else if (_ds_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); - } + res = ds_gethostbyname(name, want, err); + if (res != NULL) add_to_cache = 1; } else { pthread_mutex_lock(&_host_lock); - res = copy_host(_old_gethostbyname(name)); - *err = h_errno; + res = copy_host(LI_files_gethostbyname2(name, family)); + if (err != NULL) *err = h_errno; pthread_mutex_unlock(&_host_lock); } if (res == NULL) { - *err = HOST_NOT_FOUND; + if (err != NULL) *err = HOST_NOT_FOUND; return NULL; } - if (from_cache == 0) cache_host(res, want, CACHE_BYNAME); + if (add_to_cache == 1) cache_host(res, want, CACHE_BYNAME); return res; } +static int +ether_extract_mac(kvarray_t *in, struct ether_addr *e) +{ + uint32_t d, k, kcount, t[6]; + int i; + + if (in == NULL) return -1; + if (e == NULL) return -1; + + d = in->curr; + in->curr++; + + if (d >= in->count) return -1; + + kcount = in->dict[d].kcount; + + for (k = 0; k < kcount; k++) + { + if (!strcmp(in->dict[d].key[k], "mac")) + { + if (in->dict[d].vcount[k] == 0) continue; + i = sscanf(in->dict[d].val[k][0], " %x:%x:%x:%x:%x:%x", &t[0], &t[1], &t[2], &t[3], &t[4], &t[5]); + if (i != 6) return -1; + for (i = 0; i < 6; i++) e->ether_addr_octet[i] = t[i]; + return 0; + } + } + + return -1; +} + /* * Given a host's name, this routine returns its 48 bit ethernet address. * Returns zero if successful, non-zero otherwise. */ -int -lu_ether_hostton(const char *host, struct ether_addr *e) +static int +ds_ether_hostton(const char *host, struct ether_addr *e) { - unsigned int i, n, j, x[6]; - ni_proplist *q, **r; - char *s; - + static int proc = -1; + kvbuf_t *request; + kvarray_t *reply; + kern_return_t status; + if (host == NULL) return -1; - if (e == NULL) return -1; - - q = lookupd_make_query("2", "kvk", "name", host, "en_address"); - if (q == NULL) return -1; - - n = lookupd_query(q, &r); - ni_proplist_free(q); - free(q); - - if (n == 0) return -1; - if (r[0] == NULL) return -1; - - i = ni_proplist_match(*r[0], "en_address", NULL); - if (i == (unsigned int)NI_INDEX_NULL) return -1; - - if (r[0]->ni_proplist_val[i].nip_val.ni_namelist_len == 0) return -1; - - s = r[0]->ni_proplist_val[i].nip_val.ni_namelist_val[0]; - j = sscanf(s, " %x:%x:%x:%x:%x:%x", &x[0], &x[1], &x[2], &x[3], &x[4], &x[5]); - if (j != 6) - { - for (i = 0; i < n; i++) - { - ni_proplist_free(r[i]); - free(r[i]); - } - free(r); - return -1; + + if (proc < 0) + { + status = LI_DSLookupGetProcedureNumber("getmacbyname", &proc); + if (status != KERN_SUCCESS) return -1; } - - for (i = 0; i < 6; i++) e->ether_addr_octet[i] = x[i]; - - for (i = 0; i < n; i++) + + request = kvbuf_query_key_val("name", host); + if (request == NULL) return -1; + + reply = NULL; + status = LI_DSLookupQuery(proc, request, &reply); + kvbuf_free(request); + + if (status != KERN_SUCCESS) return -1; + + status = ether_extract_mac(reply, e); + kvarray_free(reply); + + return status; +} + +static int +ether_extract_name(kvarray_t *in, char *name) +{ + uint32_t d, k, kcount; + + if (in == NULL) return -1; + if (name == NULL) return -1; + + d = in->curr; + in->curr++; + + if (d >= in->count) return -1; + + kcount = in->dict[d].kcount; + + for (k = 0; k < kcount; k++) { - ni_proplist_free(r[i]); - free(r[i]); + if (!strcmp(in->dict[d].key[k], "name")) + { + memcpy(name, in->dict[d].val[k][0], strlen(in->dict[d].val[k][0]) + 1); + return 0; + } } - - free(r); - return 0; + + return -1; } /* * Given a 48 bit ethernet address, this routine return its host name. * Returns zero if successful, non-zero otherwise. */ -int -lu_ether_ntohost(char *host, const struct ether_addr *e) +static int +ds_ether_ntohost(char *host, const struct ether_addr *e) { - unsigned int i, n, len, x[6]; - ni_proplist *q, **r; + uint32_t i, x[6]; char str[256]; - + static int proc = -1; + kvbuf_t *request; + kvarray_t *reply; + kern_return_t status; + if (host == NULL) return -1; if (e == NULL) return -1; - + + if (proc < 0) + { + status = LI_DSLookupGetProcedureNumber("gethostbymac", &proc); + if (status != KERN_SUCCESS) return -1; + } + for (i = 0; i < 6; i++) x[i] = e->ether_addr_octet[i]; sprintf(str, "%x:%x:%x:%x:%x:%x", x[0], x[1], x[2], x[3], x[4], x[5]); - - q = lookupd_make_query("2", "kv", "en_address", str); - if (q == NULL) return -1; - - n = lookupd_query(q, &r); - ni_proplist_free(q); - free(q); - if (n == 0) return -1; - if (r[0] == NULL) return -1; - - i = ni_proplist_match(*r[0], "name", NULL); - if (i == (unsigned int)NI_INDEX_NULL) return -1; - - if (r[0]->ni_proplist_val[i].nip_val.ni_namelist_len == 0) return -1; - - len = strlen(r[0]->ni_proplist_val[i].nip_val.ni_namelist_val[0]) + 1; - memcpy(host, r[0]->ni_proplist_val[i].nip_val.ni_namelist_val[0], len); - - for (i = 0; i < n; i++) ni_proplist_free(r[i]); - free(r); - return 0; + + request = kvbuf_query_key_val("mac", str); + if (request == NULL) return -1; + + reply = NULL; + status = LI_DSLookupQuery(proc, request, &reply); + kvbuf_free(request); + + if (status != KERN_SUCCESS) return -1; + + status = ether_extract_name(reply, host); + kvarray_free(reply); + + return status; } int ether_hostton(const char *host, struct ether_addr *e) { - if (_lu_running()) return lu_ether_hostton(host, e); + if (_ds_running()) return ds_ether_hostton(host, e); return _old_ether_hostton(host, e); } int ether_ntohost(char *host, const struct ether_addr *e) { - if (_lu_running()) return lu_ether_ntohost(host, e); + if (_ds_running()) return ds_ether_ntohost(host, e); return _old_ether_ntohost(host, e); } diff --git a/lookup.subproj/lu_host.h b/lookup.subproj/lu_host.h index 3261116..109fb71 100644 --- a/lookup.subproj/lu_host.h +++ b/lookup.subproj/lu_host.h @@ -26,24 +26,24 @@ #define _LU_HOST_H_ #include +#include "lu_utils.h" - -#define WANT_NOTHING 0xfeedface -#define WANT_A4_ONLY 0 -#define WANT_A6_ONLY 1 -#define WANT_A6_PLUS_MAPPED_A4 2 -#define WANT_MAPPED_A4_ONLY 3 +#define WANT_NOTHING 0 +#define WANT_A4_ONLY 1 +#define WANT_A6_ONLY 2 +#define WANT_A6_PLUS_MAPPED_A4 3 +#define WANT_MAPPED_A4_ONLY 4 /* ONLY TO BE USED BY getipv6nodebyaddr */ -#define WANT_A6_OR_MAPPED_A4_IF_NO_A6 -1 +#define WANT_A6_OR_MAPPED_A4_IF_NO_A6 5 __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); +struct hostent *extract_host(kvarray_t *in, int want); +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); diff --git a/lookup.subproj/lu_host_async.c b/lookup.subproj/lu_host_async.c index 6b50471..14a0eca 100644 --- a/lookup.subproj/lu_host_async.c +++ b/lookup.subproj/lu_host_async.c @@ -23,946 +23,333 @@ */ #include -/* async gethostbyXXX function prototypes */ #include #include #include #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); +#define IPV6_ADDR_LEN 16 +#define IPV4_ADDR_LEN 4 -extern int h_errno; - -#define msgh_request_port msgh_remote_port -#define msgh_reply_port msgh_local_port - - -typedef union +typedef struct { - 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 + void *user_context; + int want; +} my_context_t; -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) +mach_port_t +gethostbyaddr_async_start(const char *addr, int len, int family, gethostbyaddr_async_callback callback, void *context) { - 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(MACH_MSG_TYPE_COPY_SEND, 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; - 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_mod_refs(mach_task_self(), *replyPort, MACH_PORT_RIGHT_RECEIVE, -1); - *replyPort = MACH_PORT_NULL; - break; - default: - break; - } - - return mr; -} + static int proc = 1; + int32_t want, status; + kvbuf_t *request; + mach_port_t mp; + my_context_t *my_context; -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; + mp = MACH_PORT_NULL; - /* - * typedef struct { - * mach_msg_header_t Head; - * NDR_record_t NDR; - * kern_return_t RetCode; - * } mig_reply_error_t; - */ + if (addr == NULL) return MACH_PORT_NULL; + if (len == 0) return MACH_PORT_NULL; + if ((family != AF_INET) && (family != AF_INET6)) return MACH_PORT_NULL; - register Reply *OutP = msg; - mach_msg_format_0_trailer_t *TrailerP; - boolean_t msgh_simple; + want = WANT_A4_ONLY; + if (family == AF_INET6) want = WANT_A6_ONLY; - if (OutP->Head.msgh_id != (4241776 + 100)) + if ((family == AF_INET6) && (len == IPV6_ADDR_LEN) && (is_a4_mapped((const char *)addr) || is_a4_compat((const char *)addr))) { - if (OutP->Head.msgh_id == MACH_NOTIFY_SEND_ONCE) return MIG_SERVER_DIED; - else return MIG_REPLY_MISMATCH; + addr += 12; + len = 4; + family = AF_INET; + want = WANT_MAPPED_A4_ONLY; } - 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 (OutP->NDR.int_rep != NDR_record.int_rep) + if (proc < 0) { - if (msgh_simple) - { - ((mig_reply_error_t *)OutP)->RetCode = OSReadSwapInt32(&(((mig_reply_error_t *)OutP)->RetCode), 0); - } - else - { - OutP->outdataCnt = OSReadSwapInt32(&(OutP->outdataCnt), 0); - } + status = LI_DSLookupGetProcedureNumber("gethostbyaddr", &proc); + if (status != KERN_SUCCESS) return MACH_PORT_NULL; } - 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; -} + request = kvbuf_query("ksku", "address", addr, "family", want); + if (request == NULL) return MACH_PORT_NULL; -static a_requests_t * -request_extract(mach_port_t port) -{ - a_requests_t *request0, *request; + my_context = (my_context_t *)calloc(1, sizeof(my_context_t)); + if (my_context == NULL) return MACH_PORT_NULL; - pthread_mutex_lock(&a_requests_lock); + my_context->user_context = context; + my_context->want = want; - request0 = NULL; - request = a_requests; + status = LI_async_start(&mp, proc, request, (void *)callback, my_context); - while (request != NULL) - { - if (port == request->replyPort) - { - /* request found, remove from list */ - if (request0 != NULL) - { - 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; + kvbuf_free(request); + return mp; } -static void -request_queue(a_requests_t *request) +void +gethostbyaddr_async_cancel(mach_port_t port) { - pthread_mutex_lock(&a_requests_lock); + my_context_t *my_context; - request->next = a_requests; - a_requests = request; + my_context = NULL; - pthread_mutex_unlock(&a_requests_lock); + LI_async_call_cancel(port, (void **)&my_context); - return; + if (my_context != NULL) free(my_context); } -static boolean_t -sendCannedReply(a_requests_t *request, int *error) +void +gethostbyaddr_async_handleReply(void *msg) { - /* - * 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; + gethostbyaddr_async_callback callback; + struct hostent *out; + uint32_t len, want; + int status; + kvarray_t *reply; + my_context_t *my_context; + void *context; - mach_port_t sendPort; - mach_msg_type_name_t sendType; + callback = (gethostbyaddr_async_callback)NULL; + my_context = NULL; + context = NULL; + len = 0; + reply = NULL; - /* - * allocate reply port - */ - kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &request->replyPort); - if (kr != KERN_SUCCESS) + status = LI_async_handle_reply(msg, &reply, (void **)&callback, (void **)&my_context); + if ((status != KERN_SUCCESS) || (reply == NULL)) { - *error = NO_RECOVERY; - return FALSE; + if (status == MIG_REPLY_MISMATCH) return; + if (callback != NULL) + { + if (my_context != NULL) context = my_context->user_context; + callback(NULL, context); + free(my_context); + return; + } } - kr = mach_port_extract_right(mach_task_self(), request->replyPort, MACH_MSG_TYPE_MAKE_SEND_ONCE, &sendPort, &sendType); - if (kr != KERN_SUCCESS) + want = WANT_A4_ONLY; + if (my_context != NULL) { - (void)mach_port_destroy(mach_task_self(), request->replyPort); - request->replyPort = MACH_PORT_NULL; - *error = NO_RECOVERY; - return FALSE; + context = my_context->user_context; + want = my_context->want; + free(my_context); } - /* - * queue reply message - */ - msgh_size = sizeof(Out); - OutP->Head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0); -// OutP->Head.msgh_size = msgh_size; /* msgh_size passed as argument */ - OutP->Head.msgh_request_port = sendPort; - 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, MACH_SEND_MSG, msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - if (mr != MACH_MSG_SUCCESS) - { - if (mr == MACH_SEND_INVALID_REPLY) - { - (void)mach_port_destroy(mach_task_self(), request->replyPort); - request->replyPort = MACH_PORT_NULL; - } - - *error = NO_RECOVERY; - return FALSE; - } + out = extract_host(reply, want); + kvarray_free(reply); - return TRUE; + callback(out, context); } -static void -_async_cancel(mach_port_t port) +mach_port_t +getipnodebyaddr_async_start(const void *addr, size_t len, int family, int *error, getipnodebyaddr_async_callback callback, void *context) { - a_requests_t *request; - - request = request_extract(port); - if (request) - { - (void)mach_port_mod_refs(mach_task_self(), request->replyPort, MACH_PORT_RIGHT_RECEIVE, -1); - if (request->request.data) free(request->request.data); - if (request->hent) freehostent(request->hent); - free(request); - } + static int proc = 1; + int32_t want, status; + kvbuf_t *request; + mach_port_t mp; + my_context_t *my_context; - return; -} + mp = MACH_PORT_NULL; -static 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; - static int proc4 = -1; - struct in_addr *v4addr; - static int proc6 = -1; - struct in6_addr *v6addr; + if (addr == NULL) return MACH_PORT_NULL; + if (len == 0) return MACH_PORT_NULL; + if ((family != AF_INET) && (family != AF_INET6)) return MACH_PORT_NULL; want = WANT_A4_ONLY; - if (type == AF_INET6) want = WANT_A6_ONLY; + if (family == AF_INET6) want = WANT_A6_ONLY; - if ((type == AF_INET6) && (len == 16) && (is_a4_mapped((const char *)addr) || is_a4_compat((const char *)addr))) + if ((family == AF_INET6) && (len == IPV6_ADDR_LEN) && (is_a4_mapped((const char *)addr) || is_a4_compat((const char *)addr))) { addr += 12; len = 4; - type = AF_INET; + family = AF_INET; want = WANT_MAPPED_A4_ONLY; } - switch (type) + if (proc < 0) { - case AF_INET: - { - 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 MACH_PORT_NULL; - } - - v4addr = malloc(len); - memmove(v4addr, addr, len); - - address = (void *)v4addr; - proc = proc4; - break; - } - - case AF_INET6: - { - 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 MACH_PORT_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; - break; - } - - default: - *error = NO_RECOVERY; - return MACH_PORT_NULL; + status = LI_DSLookupGetProcedureNumber("gethostbyaddr", &proc); + if (status != KERN_SUCCESS) 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; - } + request = kvbuf_query("ksku", "address", addr, "family", want); + if (request == NULL) return MACH_PORT_NULL; - return request->replyPort; -} + my_context = (my_context_t *)calloc(1, sizeof(my_context_t)); + if (my_context == NULL) return MACH_PORT_NULL; -static 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; - } + my_context->user_context = context; + my_context->want = want; - *requestP = request; - *he = NULL; - *error = 0; + status = LI_async_start(&mp, proc, request, (void *)callback, my_context); - /* 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_cancel(mach_port_t port) -{ - _async_cancel(port); - return; -} - -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_mod_refs(mach_task_self(), request->replyPort, MACH_PORT_RIGHT_RECEIVE, -1); - if (request->request.data) free(request->request.data); - free(request); - if (he != NULL) 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; - } - - cb.nodeAddr = callout; - mp = _gethostbyaddr_async_start(addr, len, af, cb, context, error); + kvbuf_free(request); return mp; } void getipnodebyaddr_async_cancel(mach_port_t port) { - _async_cancel(port); - return; -} + my_context_t *my_context; -void -getipnodebyaddr_async_handleReply(void *replyMsg) -{ - int error = 0; - struct hostent *he = NULL; - a_requests_t *request = NULL; + my_context = 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_mod_refs(mach_task_self(), request->replyPort, MACH_PORT_RIGHT_RECEIVE, -1); - if (request->request.data) free(request->request.data); - free(request); - /* - * Note: it is up to the callback function to call - * freehostent(). - */ - } + LI_async_call_cancel(port, (void **)&my_context); - return; + if (my_context != NULL) free(my_context); } -static mach_port_t -_gethostbyname_async_start(const char *name, int want, int *error, a_request_callout_t callout, void *context) +void +getipnodebyaddr_async_handleReply(void *msg) { - int af; - boolean_t is_addr = FALSE; - mach_port_t mp = MACH_PORT_NULL; - XDR outxdr; - static int proc; - a_requests_t *request; - static int proc4 = -1; - static int proc6 = -1; - struct in_addr v4addr; - struct in6_addr v6addr; - - 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)) - { - 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) */ - { - 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: - { - 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: - { - 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; - } + getipnodebyaddr_async_callback callback; + struct hostent *out; + uint32_t len, want; + int status; + kvarray_t *reply; + my_context_t *my_context; + void *context; - default: - free(request); - *error = NO_RECOVERY; - return MACH_PORT_NULL; - } + callback = (getipnodebyaddr_async_callback)NULL; + my_context = NULL; + context = NULL; + len = 0; + reply = NULL; - if (is_addr) + status = LI_async_handle_reply(msg, &reply, (void **)&callback, (void **)&my_context); + if ((status != KERN_SUCCESS) || (reply == NULL)) { - /* - * queue reply message - */ - if (sendCannedReply(request, error)) + if (status == MIG_REPLY_MISMATCH) return; + if (callback != NULL) { - request_queue(request); - return request->replyPort; - } - else - { - freehostent(request->hent); - free(request); - return MACH_PORT_NULL; + if (my_context != NULL) context = my_context->user_context; + callback(NULL, NO_RECOVERY, context); + free(my_context); + return; } } - 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)) + want = WANT_A4_ONLY; + if (my_context != NULL) { - xdr_destroy(&outxdr); - free(request->request.data); - free(request); - *error = NO_RECOVERY; - return MACH_PORT_NULL; + context = my_context->user_context; + want = my_context->want; + free(my_context); } - request->request.dataLen = xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT; + out = extract_host(reply, want); + kvarray_free(reply); - /* - * 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 + if (out == NULL) { - free(request->request.data); - free(request); - *error = NO_RECOVERY; - mp = MACH_PORT_NULL; + callback(NULL, HOST_NOT_FOUND, context); + return; } - xdr_destroy(&outxdr); - return mp; + callback(out, 0, context); } -static boolean_t -_gethostbyname_async_handleReply(void *replyMsg, a_requests_t **requestP, struct hostent **he, int *error) +mach_port_t +gethostbyname_async_start(const char *name, gethostbyname_async_callback callback, void *context) { - 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; + static int proc = 1; + int32_t status; + kvbuf_t *request; + mach_port_t mp; - if (token.val[0] != 0) - { - vm_deallocate(mach_task_self(), (vm_address_t)data, datalen); - *error = NO_RECOVERY; - return TRUE; - } + mp = MACH_PORT_NULL; - xdrmem_create(&inxdr, data, datalen, XDR_DECODE); + if (name == NULL) return MACH_PORT_NULL; - count = 0; - if (!xdr_int(&inxdr, &count)) + if (proc < 0) { - xdr_destroy(&inxdr); - vm_deallocate(mach_task_self(), (vm_address_t)data, datalen); - *error = NO_RECOVERY; - return TRUE; + status = LI_DSLookupGetProcedureNumber("gethostbyname", &proc); + if (status != KERN_SUCCESS) return MACH_PORT_NULL; } - if (count == 0) - { - xdr_destroy(&inxdr); - vm_deallocate(mach_task_self(), (vm_address_t)data, datalen); - *error = HOST_NOT_FOUND; - return TRUE; - } + request = kvbuf_query("ksksks", "name", name, "ipv4", "1", "ipv6", "0"); + if (request == NULL) return MACH_PORT_NULL; - 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 == MACH_PORT_NULL) - { - h_errno = error; - } + status = LI_async_start(&mp, proc, request, (void *)callback, context); + kvbuf_free(request); return mp; } void gethostbyname_async_cancel(mach_port_t port) { - _async_cancel(port); - return; + LI_async_call_cancel(port, NULL); } void -gethostbyname_async_handleReply(void *replyMsg) +gethostbyname_async_handleReply(void *msg) { - int error; - struct hostent *he; - a_requests_t *request; + gethostbyname_async_callback callback; + struct hostent *out; + uint32_t len; + int status; + kvarray_t *reply; + void *context; + + callback = (gethostbyname_async_callback)NULL; + context = NULL; + len = 0; + reply = NULL; - if (_gethostbyname_async_handleReply(replyMsg, &request, &he, &error)) + status = LI_async_handle_reply(msg, &reply, (void **)&callback, (void **)&context); + if ((status != KERN_SUCCESS) || (reply == NULL)) { - /* if we have an answer to provide */ - h_errno = error; - (request->callout.hostAddr)(he, request->context); - - (void)mach_port_mod_refs(mach_task_self(), request->replyPort, MACH_PORT_RIGHT_RECEIVE, -1); - if (request->request.data) free(request->request.data); - free(request); - if (he != NULL) freehostent(he); + if (status == MIG_REPLY_MISMATCH) return; + if (callback != NULL) + { + callback(NULL, context); + return; + } } - return; + out = extract_host(reply, AF_INET); + kvarray_free(reply); + + callback(out, context); } mach_port_t -getipnodebyname_async_start(const char *name, int af, int flags, int *error, getipnodebyname_async_callback callout, void *context) +getipnodebyname_async_start(const char *name, int family, int flags, int *err, getipnodebyname_async_callback callback, 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; + static int proc = 1; + int32_t status, want, want4, want6, if4, if6; + kvbuf_t *request; + mach_port_t mp; struct ifaddrs *ifa, *ifap; + struct in_addr addr4; + struct in6_addr addr6; + my_context_t *my_context; - if (!_lu_running()) - { - h_errno = NO_RECOVERY; - return MACH_PORT_NULL; - } + if (name == NULL) return MACH_PORT_NULL; + + if (err != NULL) *err = 0; + + if4 = 0; + if6 = 0; + mp = MACH_PORT_NULL; + memset(&addr4, 0, sizeof(struct in_addr)); + memset(&addr6, 0, sizeof(struct in6_addr)); - /* - * IF AI_ADDRCONFIG is set, we need to know what interface flavors we really have. - */ if (flags & AI_ADDRCONFIG) { if (getifaddrs(&ifa) < 0) { - *error = NO_RECOVERY; + if (err != NULL) *err = NO_RECOVERY; return MACH_PORT_NULL; } @@ -970,14 +357,8 @@ getipnodebyname_async_start(const char *name, int af, int flags, int *error, get { 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++; - } + if (ifap->ifa_addr->sa_family == AF_INET) if4++; + else if (ifap->ifa_addr->sa_family == AF_INET6) if6++; } freeifaddrs(ifa); @@ -985,7 +366,7 @@ getipnodebyname_async_start(const char *name, int af, int flags, int *error, get /* Bail out if there are no interfaces */ if ((if4 == 0) && (if6 == 0)) { - *error = NO_ADDRESS; + if (err != NULL) *err = NO_RECOVERY; return MACH_PORT_NULL; } } @@ -994,108 +375,133 @@ getipnodebyname_async_start(const char *name, int af, int flags, int *error, get * Figure out what we want. * If user asked for AF_INET, we only want V4 addresses. */ - switch (af) + want = WANT_A4_ONLY; + + if (family == AF_INET) { - case AF_INET: + if ((flags & AI_ADDRCONFIG) && (if4 == 0)) { - want = WANT_A4_ONLY; - if ((flags & AI_ADDRCONFIG) && (if4 == 0)) - { - *error = NO_ADDRESS; - return MACH_PORT_NULL; - } + if (err != NULL) *err = NO_RECOVERY; + return MACH_PORT_NULL; } - break; + } + else + { + /* family == AF_INET6 */ + want = WANT_A6_ONLY; - case AF_INET6: + if (flags & (AI_V4MAPPED | AI_V4MAPPED_CFG)) { - want = WANT_A6_ONLY; - if (flags & (AI_V4MAPPED|AI_V4MAPPED_CFG)) + if (flags & AI_ALL) { - if (flags & AI_ALL) - { - want = WANT_A6_PLUS_MAPPED_A4; - } - else - { - want = WANT_A6_OR_MAPPED_A4_IF_NO_A6; - } + want = WANT_A6_PLUS_MAPPED_A4; } else { - if ((flags & AI_ADDRCONFIG) && (if6 == 0)) - { - *error = NO_ADDRESS; - return MACH_PORT_NULL; - } + want = WANT_A6_OR_MAPPED_A4_IF_NO_A6; + } + } + else + { + if ((flags & AI_ADDRCONFIG) && (if6 == 0)) + { + if (err != NULL) *err = NO_RECOVERY; + return MACH_PORT_NULL; } } - break; } - cb.nodeName = callout; - mp = _gethostbyname_async_start(name, want, &h_errno, cb, context); + if (proc < 0) + { + status = LI_DSLookupGetProcedureNumber("gethostbyname", &proc); + if (status != KERN_SUCCESS) return MACH_PORT_NULL; + } + + my_context = (my_context_t *)calloc(1, sizeof(my_context_t)); + if (my_context == NULL) + { + *err = NO_RECOVERY; + return MACH_PORT_NULL; + } + + my_context->user_context = context; + my_context->want = want; + + want4 = 1; + want6 = 1; + + if (want == WANT_A4_ONLY) want6 = 0; + else if (want == WANT_A6_ONLY) want4 = 0; + else if (WANT_MAPPED_A4_ONLY) want6 = 0; + + request = kvbuf_query("kskuku", "name", name, "ipv4", want4, "ipv6", want6); + if (request == NULL) return MACH_PORT_NULL; + + status = LI_async_start(&mp, proc, request, (void *)callback, my_context); + + kvbuf_free(request); return mp; } void getipnodebyname_async_cancel(mach_port_t port) { - _async_cancel(port); - return; + my_context_t *my_context; + + my_context = NULL; + + LI_async_call_cancel(port, (void **)&my_context); + + if (my_context != NULL) free(my_context); } void -getipnodebyname_async_handleReply(void *replyMsg) +getipnodebyname_async_handleReply(void *msg) { - int error = 0; - struct hostent *he = NULL; - a_requests_t *request = NULL; - static int proc4 = -1; + getipnodebyname_async_callback callback; + struct hostent *out; + uint32_t len, want; + int status, err; + kvarray_t *reply; + my_context_t *my_context; + void *context; + + callback = (getipnodebyname_async_callback)NULL; + my_context = NULL; + context = NULL; + len = 0; + reply = NULL; - if (_gethostbyname_async_handleReply(replyMsg, &request, &he, &error)) + status = LI_async_handle_reply(msg, &reply, (void **)&callback, (void **)&my_context); + if ((status != KERN_SUCCESS) || (reply == NULL)) { - /* - * 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))) + if (status == MIG_REPLY_MISMATCH) return; + if (callback != NULL) { - /* - * no host found (yet), if requested we send a - * followup query to lookupd. - */ - 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; - } + if (my_context != NULL) context = my_context->user_context; + callback(NULL, NO_RECOVERY, context); + free(my_context); + return; } + } + + want = WANT_A4_ONLY; + if (my_context != NULL) + { + context = my_context->user_context; + want = my_context->want; + free(my_context); + } -answer: - (request->callout.nodeName)(he, error, request->context); - (void)mach_port_mod_refs(mach_task_self(), request->replyPort, MACH_PORT_RIGHT_RECEIVE, -1); - if (request->request.data != NULL) free(request->request.data); - free(request); - /* - * Note: it is up to the callback function to call - * freehostent(). - */ + out = extract_host(reply, want); + kvarray_free(reply); + + if (out == NULL) + { + err = HOST_NOT_FOUND; + callback(NULL, err, context); + return; } - return; + callback(out, 0, context); } diff --git a/lookup.subproj/lu_netgroup.c b/lookup.subproj/lu_netgroup.c index 1badf48..f140a03 100644 --- a/lookup.subproj/lu_netgroup.c +++ b/lookup.subproj/lu_netgroup.c @@ -25,339 +25,236 @@ * Netgroup 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" -#define FIX(x) ((x == NULL) ? NULL : (_lu_string *)&(x)) - -struct lu_netgrent +struct li_netgrent { char *ng_host; char *ng_user; char *ng_domain; }; -static void -free_netgroup_data(struct lu_netgrent *ng) +#define ENTRY_SIZE sizeof(struct li_netgrent) +#define ENTRY_KEY _li_data_key_netgroup + +static struct li_netgrent * +copy_netgroup(struct li_netgrent *in) { - if (ng == NULL) return; + if (in == NULL) return NULL; - 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); + return (struct li_netgrent *)LI_ils_create("sss", in->ng_host, in->ng_user, in->ng_domain); } -static void -free_netgroup(struct lu_netgrent *ng) -{ - if (ng == NULL) return; - free_netgroup_data(ng); - free(ng); - } - -static void -free_lu_thread_info_netgroup(void *x) +/* + * Extract the next netgroup entry from a kvarray. + */ +static struct li_netgrent * +extract_netgroup(kvarray_t *in) { - struct lu_thread_info *tdata; + struct li_netgrent tmp; + uint32_t d, k, kcount; - if (x == NULL) return; - - tdata = (struct lu_thread_info *)x; - - if (tdata->lu_entry != NULL) - { - free_netgroup((struct lu_netgrent *)tdata->lu_entry); - tdata->lu_entry = NULL; - } + if (in == NULL) return NULL; - _lu_data_free_vm_xdr(tdata); + d = in->curr; + in->curr++; - free(tdata); -} - -static struct lu_netgrent * -extract_netgroup(XDR *xdr) -{ - char *h, *u, *d; - struct lu_netgrent *ng; + if (d >= in->count) return NULL; - if (xdr == NULL) return NULL; + memset(&tmp, 0, ENTRY_SIZE); - h = NULL; - u = NULL; - d = NULL; + kcount = in->dict[d].kcount; - if (!xdr_string(xdr, &h, LU_LONG_STRING_LENGTH)) + for (k = 0; k < kcount; k++) { - return NULL; - } + if (!strcmp(in->dict[d].key[k], "user")) + { + if (tmp.ng_user != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; - if (!xdr_string(xdr, &u, LU_LONG_STRING_LENGTH)) - { - free(h); - return NULL; - } + tmp.ng_user = (char *)in->dict[d].val[k][0]; + } + else if (!strcmp(in->dict[d].key[k], "host")) + { + if (tmp.ng_host != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; - if (!xdr_string(xdr, &d, LU_LONG_STRING_LENGTH)) - { - free(h); - free(u); - return NULL; - } + tmp.ng_host = (char *)in->dict[d].val[k][0]; + } + else if (!strcmp(in->dict[d].key[k], "domain")) + { + if (tmp.ng_domain != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; - ng = (struct lu_netgrent *)calloc(1, sizeof(struct lu_netgrent)); + tmp.ng_domain = (char *)in->dict[d].val[k][0]; + } + } - ng->ng_host = h; - ng->ng_user = u; - ng->ng_domain = d; + if (tmp.ng_user == NULL) tmp.ng_user = ""; + if (tmp.ng_host == NULL) tmp.ng_host = ""; + if (tmp.ng_domain == NULL) tmp.ng_domain = ""; - return ng; + return copy_netgroup(&tmp); } -#ifdef NOTDEF -static struct lu_netgrent * -copy_netgroup(struct lu_netgrent *in) +static int +check_innetgr(kvarray_t *in) { - struct lu_netgrent *ng; - - if (in == NULL) return NULL; - - ng = (struct group *)calloc(1, sizeof(struct lu_netgrent)); - - 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); + uint32_t d, k, kcount; - return ng; -} -#endif + if (in == NULL) return 0; -static void -recycle_netgroup(struct lu_thread_info *tdata, struct lu_netgrent *in) -{ - struct lu_netgrent *ng; - - if (tdata == NULL) return; - ng = (struct lu_netgrent *)tdata->lu_entry; + d = in->curr; + if (d >= in->count) return 0; - if (in == NULL) - { - free_netgroup(ng); - tdata->lu_entry = NULL; - } + kcount = in->dict[d].kcount; - if (tdata->lu_entry == NULL) + for (k = 0; k < kcount; k++) { - tdata->lu_entry = in; - return; + if (!strcmp(in->dict[d].key[k], "result")) + { + if (in->dict[d].vcount[k] == 0) continue; + return atoi(in->dict[d].val[k][0]); + } } - free_netgroup_data(ng); - - ng->ng_host = in->ng_host; - ng->ng_user = in->ng_user; - ng->ng_domain = in->ng_domain; - - free(in); + return 0; } - static int -lu_innetgr(const char *group, const char *host, const char *user, - const char *domain) +ds_innetgr(const char *group, const char *host, const char *user, const char *domain) { - unsigned datalen; - XDR xdr; - char namebuf[4*_LU_MAXLUSTRLEN + 3*BYTES_PER_XDR_UNIT]; + int is_innetgr; + kvbuf_t *request; + kvarray_t *reply; + kern_return_t status; static int proc = -1; - int size; - int res; - _lu_innetgr_args args; - char *lookup_buf; if (proc < 0) { - if (_lookup_link(_lu_port, "innetgr", &proc) != KERN_SUCCESS) - { - return 0; - } - } - - args.group = (char *)group; - args.host = FIX(host); - args.user = FIX(user); - args.domain = FIX(domain); - - xdrmem_create(&xdr, namebuf, sizeof(namebuf), XDR_ENCODE); - if (!xdr__lu_innetgr_args(&xdr, &args)) - { - xdr_destroy(&xdr); - return 0; + status = LI_DSLookupGetProcedureNumber("innetgr", &proc); + if (status != KERN_SUCCESS) return 0; } - size = xdr_getpos(&xdr) / BYTES_PER_XDR_UNIT; - xdr_destroy(&xdr); + /* Encode NULL */ + if (group == NULL) group = ""; + if (host == NULL) host = ""; + if (user == NULL) user = ""; + if (domain == NULL) domain = ""; - datalen = 0; - lookup_buf = NULL; + request = kvbuf_query("ksksksks", "netgroup", group, "host", host, "user", user, "domain", domain); + if (request == NULL) return 0; - if (_lookup_all(_lu_port, proc, (unit *)namebuf, size, &lookup_buf, &datalen) != KERN_SUCCESS) - { - return 0; - } - - datalen *= BYTES_PER_XDR_UNIT; - if ((lookup_buf == NULL) || (datalen == 0)) return 0; + reply = NULL; + status = LI_DSLookupQuery(proc, request, &reply); + kvbuf_free(request); - xdrmem_create(&xdr, lookup_buf, datalen, XDR_DECODE); - if (!xdr_int(&xdr, &res)) - { - xdr_destroy(&xdr); - vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); - return 0; - } + if (status != KERN_SUCCESS) return 0; - xdr_destroy(&xdr); - vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); + is_innetgr = check_innetgr(reply); + kvarray_free(reply); - return 1; + return is_innetgr; } static void -lu_endnetgrent(void) +ds_endnetgrent(void) { - 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); + LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY)); } - /* * This is different than the other setXXXent routines * since this is really more like getnetgrbyname() than * getnetgrent(). */ static void -lu_setnetgrent(const char *name) +ds_setnetgrent(const char *name) { - unsigned datalen; - char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT]; - XDR outxdr; + struct li_thread_info *tdata; + kvbuf_t *request; + kvarray_t *reply; + kern_return_t status; 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); - } + tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); + if (tdata == NULL) return; - lu_endnetgrent(); + if (tdata->li_vm != NULL) return; if (proc < 0) { - if (_lookup_link(_lu_port, "getnetgrent", &proc) != KERN_SUCCESS) + status = LI_DSLookupGetProcedureNumber("getnetgrent", &proc); + if (status != KERN_SUCCESS) { - lu_endnetgrent(); + LI_data_free_kvarray(tdata); return; } } - xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE); - if (!xdr__lu_string(&outxdr, (_lu_string *)&name)) - { - xdr_destroy(&outxdr); - lu_endnetgrent(); - return; - } - - 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) - { - lu_endnetgrent(); - return; - } + request = kvbuf_query_key_val("netgroup", name); + if (request == NULL) return; - /* mig stubs measure size in words (4 bytes) */ - tdata->lu_vm_length *= 4; + reply = NULL; + status = LI_DSLookupQuery(proc, request, &reply); + kvbuf_free(request); - if (tdata->lu_xdr != NULL) - { - xdr_destroy(tdata->lu_xdr); - free(tdata->lu_xdr); + if (status != KERN_SUCCESS) + { + LI_data_free_kvarray(tdata); + return; } - 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(); + tdata->li_vm = (char *)reply; } -static struct lu_netgrent * -lu_getnetgrent(void) +static struct li_netgrent * +ds_getnetgrent(void) { - struct lu_netgrent *ng; - struct lu_thread_info *tdata; + struct li_netgrent *entry; + struct li_thread_info *tdata; - tdata = _lu_data_create_key(_lu_data_key_netgroup, free_lu_thread_info_netgroup); + tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); if (tdata == NULL) return NULL; - if (tdata->lu_vm_cursor == 0) - { - lu_endnetgrent(); - return NULL; - } - - ng = extract_netgroup(tdata->lu_xdr); - if (ng == NULL) + entry = extract_netgroup((kvarray_t *)(tdata->li_vm)); + if (entry == NULL) { - lu_endnetgrent(); + ds_endnetgrent(); return NULL; } - tdata->lu_vm_cursor--; - - return ng; + return entry; } int innetgr(const char *group, const char *host, const char *user, const char *domain) { - if (_lu_running()) return (lu_innetgr(group, host, user, domain)); + if (_ds_running()) return (ds_innetgr(group, host, user, domain)); return 0; } int getnetgrent(char **host, char **user, char **domain) { - struct lu_netgrent *res = NULL; - struct lu_thread_info *tdata; + struct li_netgrent *res = NULL; + struct li_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); - } + tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); + if (tdata == NULL) return 0; res = NULL; - if (_lu_running()) res = lu_getnetgrent(); + if (_ds_running()) res = ds_getnetgrent(); - recycle_netgroup(tdata, res); + LI_data_recycle(tdata, res, ENTRY_SIZE); if (res == NULL) return 0; if (host != NULL) *host = res->ng_host; @@ -370,11 +267,11 @@ getnetgrent(char **host, char **user, char **domain) void setnetgrent(const char *name) { - if (_lu_running()) lu_setnetgrent(name); + if (_ds_running()) ds_setnetgrent(name); } void endnetgrent(void) { - if (_lu_running()) lu_endnetgrent(); + if (_ds_running()) ds_endnetgrent(); } diff --git a/lookup.subproj/lu_network.c b/lookup.subproj/lu_network.c index 8f9a551..4f74394 100644 --- a/lookup.subproj/lu_network.c +++ b/lookup.subproj/lu_network.c @@ -29,16 +29,11 @@ #include #include #include -#include -#include #include #include #include #include #include - -#include "_lu_types.h" -#include "lookup.h" #include "lu_utils.h" static pthread_mutex_t _network_lock = PTHREAD_MUTEX_INITIALIZER; @@ -55,409 +50,146 @@ extern struct netent *_old_getnetent(); extern void _old_setnetent(); extern void _old_endnetent(); -extern mach_port_t _lu_port; -extern int _lu_running(void); +#define ENTRY_SIZE sizeof(struct netent) +#define ENTRY_KEY _li_data_key_network -static void -free_network_data(struct netent *n) +static struct netent * +copy_network(struct netent *in) { - char **aliases; - - if (n == NULL) return; - - free(n->n_name); - - aliases = n->n_aliases; - if (aliases != NULL) - { - while (*aliases != NULL) free(*aliases++); - free(n->n_aliases); - } -} + if (in == NULL) return NULL; -static void -free_network(struct netent *n) -{ - if (n == NULL) return; - free_network_data(n); - free(n); + return (struct netent *)LI_ils_create("s*44", in->n_name, in->n_aliases, in->n_addrtype, in->n_net); } -static void -free_lu_thread_info_network(void *x) +/* + * Extract the next network entry from a kvarray. + */ +static void * +extract_network(kvarray_t *in) { - struct lu_thread_info *tdata; - - if (x == NULL) return; + struct netent tmp; + uint32_t d, k, kcount; + char *empty[1]; - 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); -} + if (in == NULL) return NULL; -static struct netent * -extract_network(XDR *xdr) -{ - struct netent *n; - int i, j, nvals, nkeys, status; - char *key, **vals; + d = in->curr; + in->curr++; - if (xdr == NULL) return NULL; + if (d >= in->count) return NULL; - if (!xdr_int(xdr, &nkeys)) return NULL; + empty[0] = NULL; + memset(&tmp, 0, ENTRY_SIZE); - n = (struct netent *)calloc(1, sizeof(struct netent)); + tmp.n_addrtype = AF_INET; - n->n_addrtype = AF_INET; + kcount = in->dict[d].kcount; - for (i = 0; i < nkeys; i++) + for (k = 0; k < kcount; k++) { - key = NULL; - vals = NULL; - nvals = 0; - - status = _lu_xdr_attribute(xdr, &key, &vals, &nvals); - if (status < 0) + if (!strcmp(in->dict[d].key[k], "n_name")) { - free_network(n); - return NULL; - } + if (tmp.n_name != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; - if (nvals == 0) - { - free(key); - continue; + tmp.n_name = (char *)in->dict[d].val[k][0]; } - - j = 0; - - if ((n->n_name == NULL) && (!strcmp("name", key))) + else if (!strcmp(in->dict[d].key[k], "n_net")) { - 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; + if (in->dict[d].vcount[k] == 0) continue; + tmp.n_net = inet_network(in->dict[d].val[k][0]); } - else if (!strcmp("address", key)) + else if (!strcmp(in->dict[d].key[k], "n_addrtype")) { - n->n_net = inet_network(vals[0]); + if (in->dict[d].vcount[k] == 0) continue; + tmp.n_addrtype = atoi(in->dict[d].val[k][0]); } - - free(key); - if (vals != NULL) + else if (!strcmp(in->dict[d].key[k], "n_aliases")) { - 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 *)); + if (tmp.n_aliases != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; - return n; -} - -static struct netent * -copy_network(struct netent *in) -{ - int i, len; - struct netent *n; - - if (in == NULL) return NULL; - - n = (struct netent *)calloc(1, sizeof(struct netent)); - - 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++) - { - 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; - } - - if (tdata->lu_entry == NULL) - { - tdata->lu_entry = in; - return; + tmp.n_aliases = (char **)in->dict[d].val[k]; + } } - free_network_data(n); + if (tmp.n_name == NULL) tmp.n_name = ""; + if (tmp.n_aliases == NULL) tmp.n_aliases = empty; - 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); + return copy_network(&tmp); } static struct netent * -lu_getnetbyaddr(long addr, int type) +ds_getnetbyaddr(uint32_t addr, int type) { - struct netent *n; - unsigned datalen; - XDR inxdr; static int proc = -1; - char *lookup_buf; - int count; + unsigned char f1, f2, f3; + char val[64]; if (type != AF_INET) return NULL; - if (proc < 0) - { - if (_lookup_link(_lu_port, "getnetbyaddr", &proc) != KERN_SUCCESS) - { - return NULL; - } - } - - addr = htonl(addr); - datalen = 0; - lookup_buf = NULL; - - if (_lookup_all(_lu_port, proc, (unit *)&addr, 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; - } + f1 = addr & 0xff; + addr >>= 8; + f2 = addr & 0xff; + addr >>= 8; + f3 = addr & 0xff; - n = extract_network(&inxdr); - xdr_destroy(&inxdr); - vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); + if (f3 != 0) snprintf(val, sizeof(val), "%u.%u.%u", f3, f2, f1); + else if (f2 != 0) snprintf(val, sizeof(val), "%u.%u", f2, f1); + else snprintf(val, sizeof(val), "%u", f1); - return n; + return (struct netent *)LI_getone("getnetbyaddr", &proc, extract_network, "net", val); } static struct netent * -lu_getnetbyname(const char *name) +ds_getnetbyname(const char *name) { - struct netent *n; - unsigned datalen; - char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT]; - XDR outxdr; - XDR inxdr; static int proc = -1; - char *lookup_buf; - int count; - - if (proc < 0) - { - if (_lookup_link(_lu_port, "getnetbyname", &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; - } - n = extract_network(&inxdr); - xdr_destroy(&inxdr); - vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); - - return n; + return (struct netent *)LI_getone("getnetbyname", &proc, extract_network, "name", name); } static void -lu_endnetent() +ds_endnetent() { - 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); + LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY)); } static void -lu_setnetent() +ds_setnetent() { - lu_endnetent(); + ds_endnetent(); } static struct netent * -lu_getnetent() +ds_getnetent() { static int proc = -1; - struct lu_thread_info *tdata; - struct netent *n; - - 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) - { - if (proc < 0) - { - if (_lookup_link(_lu_port, "getnetent", &proc) != KERN_SUCCESS) - { - lu_endnetent(); - return NULL; - } - } - - if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS) - { - lu_endnetent(); - 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_endnetent(); - return NULL; - } - } - - if (tdata->lu_vm_cursor == 0) - { - lu_endnetent(); - return NULL; - } - - n = extract_network(tdata->lu_xdr); - if (n == NULL) - { - lu_endnetent(); - return NULL; - } - tdata->lu_vm_cursor--; - - return n; + return (struct netent *)LI_getent("getnetent", &proc, extract_network, ENTRY_KEY, ENTRY_SIZE); } static struct netent * -getnet(const char *name, long addr, int type, int source) +getnet(const char *name, uint32_t addr, int type, int source) { struct netent *res = NULL; - struct lu_thread_info *tdata; + struct li_thread_info *tdata; - 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); - } + tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); + if (tdata == NULL) return NULL; - if (_lu_running()) + if (_ds_running()) { switch (source) { case N_GET_NAME: - res = lu_getnetbyname(name); + res = ds_getnetbyname(name); break; case N_GET_ADDR: - res = lu_getnetbyaddr(addr, type); + res = ds_getnetbyaddr(addr, type); break; case N_GET_ENT: - res = lu_getnetent(); + res = ds_getnetent(); break; default: res = NULL; } @@ -465,6 +197,7 @@ getnet(const char *name, long addr, int type, int source) else { pthread_mutex_lock(&_network_lock); + switch (source) { case N_GET_NAME: @@ -478,11 +211,12 @@ getnet(const char *name, long addr, int type, int source) break; default: res = NULL; } + pthread_mutex_unlock(&_network_lock); } - recycle_network(tdata, res); - return (struct netent *)tdata->lu_entry; + LI_data_recycle(tdata, res, ENTRY_SIZE); + return (struct netent *)tdata->li_entry; } struct netent * @@ -506,13 +240,13 @@ getnetent(void) void setnetent(int stayopen) { - if (_lu_running()) lu_setnetent(); + if (_ds_running()) ds_setnetent(); else _old_setnetent(stayopen); } void endnetent(void) { - if (_lu_running()) lu_endnetent(); + if (_ds_running()) ds_endnetent(); else _old_endnetent(); } diff --git a/lookup.subproj/lu_overrides.h b/lookup.subproj/lu_overrides.h index c7134b2..a83713e 100644 --- a/lookup.subproj/lu_overrides.h +++ b/lookup.subproj/lu_overrides.h @@ -35,26 +35,12 @@ #include __BEGIN_DECLS -struct passwd *_old_getpwnam __P((const char *)); -struct passwd *_old_getpwuid __P((uid_t)); -struct passwd *_old_getpwent __P((void)); -int _old_setpwent __P((void)); -void _old_endpwent __P((void)); -int _old_putpwpasswd(); /*XXX*/ - struct group *_old_getgrnam __P((const char *)); struct group *_old_getgrgid __P((gid_t)); int _old_setgrent __P((void)); struct group *_old_getgrent __P((void)); void _old_endgrent __P((void)); -struct hostent *_old_gethostbyname __P((const char *)); -struct hostent *_old_gethostbyaddr __P((const char *, int, int)); -void _old_sethostent __P((int)); -struct hostent *_old_gethostent __P((void)); -void _old_endhostent __P((void)); -void _old_sethostfile __P((const char *)); - struct netent *_old_getnetbyname(); struct netent *_old_getnetbyaddr(); void _old_setnetent(); diff --git a/lookup.subproj/lu_printer.c b/lookup.subproj/lu_printer.c index e455b4c..0b7d195 100644 --- a/lookup.subproj/lu_printer.c +++ b/lookup.subproj/lu_printer.c @@ -29,433 +29,28 @@ #include #include #include -#include -#include #include - -#include "_lu_types.h" -#include "lookup.h" #include "printerdb.h" #include "lu_utils.h" -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 void -free_printer_data(prdb_ent *p) -{ - char **names; - int i; - - if (p == NULL) return; - - names = p->pe_name; - if (names != NULL) - { - while (*names) free(*names++); - free(p->pe_name); - } - - for (i = 0; i < p->pe_nprops; i++) - { - free(p->pe_prop[i].pp_key); - free(p->pe_prop[i].pp_value); - } - - free(p->pe_prop); -} - -static void -free_printer(prdb_ent *p) -{ - if (p == NULL) return; - free_printer_data(p); - free(p); -} - -static void -free_lu_thread_info_printer(void *x) -{ - struct lu_thread_info *tdata; - - if (x == NULL) return; - - tdata = (struct lu_thread_info *)x; - - if (tdata->lu_entry != NULL) - { - free_printer((prdb_ent *)tdata->lu_entry); - tdata->lu_entry = 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; - - p = (prdb_ent *)calloc(1, sizeof(prdb_ent)); - - for (i = 0; i < nkeys; i++) - { - key = NULL; - vals = NULL; - nvals = 0; - - status = _lu_xdr_attribute(xdr, &key, &vals, &nvals); - if (status < 0) - { - free_printer(p); - return NULL; - } - - j = 0; - - 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); - } - } - - 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)); - - return p; -} - -static prdb_ent * -copy_printer(prdb_ent *in) -{ - 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) - { - 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 -recycle_printer(struct lu_thread_info *tdata, struct prdb_ent *in) -{ - 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 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; - static int proc = -1; - char *lookup_buf; - int count; - - if (proc < 0) - { - if (_lookup_link(_lu_port, "prdb_getbyname", &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_printer(&inxdr); - xdr_destroy(&inxdr); - vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); - - return p; -} - -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; - 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 (tdata->lu_vm == NULL) - { - if (proc < 0) - { - if (_lookup_link(_lu_port, "prdb_get", &proc) != KERN_SUCCESS) - { - lu_prdb_end(); - return NULL; - } - } - - if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS) - { - lu_prdb_end(); - 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_prdb_end(); - return NULL; - } - } - - if (tdata->lu_vm_cursor == 0) - { - lu_prdb_end(); - return NULL; - } - - p = extract_printer(tdata->lu_xdr); - if (p == NULL) - { - lu_prdb_end(); - 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); - } - - recycle_printer(tdata, res); - return (prdb_ent *)tdata->lu_entry; -} - const prdb_ent * prdb_getbyname(const char *name) { - return (const prdb_ent *)getprinter(name, P_GET_NAME); + return NULL; } const prdb_ent * prdb_get(void) { - return (const prdb_ent *)getprinter(NULL, P_GET_ENT); + return NULL; } void prdb_set(const char *name) { - if (_lu_running()) lu_prdb_set(); - else _old_prdb_set(); } void prdb_end(void) { - 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 e91932d..ac78109 100644 --- a/lookup.subproj/lu_protocol.c +++ b/lookup.subproj/lu_protocol.c @@ -29,13 +29,9 @@ #include #include #include -#include -#include #include #include - -#include "_lu_types.h" -#include "lookup.h" +#include #include "lu_utils.h" extern struct protoent *_old_getprotobynumber(); @@ -44,410 +40,150 @@ extern struct protoent *_old_getprotoent(); extern void _old_setprotoent(); extern void _old_endprotoent(); +static pthread_mutex_t _protocol_lock = PTHREAD_MUTEX_INITIALIZER; + #define PROTO_GET_NAME 1 #define PROTO_GET_NUM 2 #define PROTO_GET_ENT 3 -static void -free_protocol_data(struct protoent *p) -{ - char **aliases; - - if (p == NULL) return; - - if (p->p_name != NULL) free(p->p_name); - aliases = p->p_aliases; - if (aliases != NULL) - { - while (*aliases != NULL) free(*aliases++); - free(p->p_aliases); - } -} +#define ENTRY_SIZE sizeof(struct protoent) +#define ENTRY_KEY _li_data_key_protocol -static void -free_protocol(struct protoent *p) +static struct protoent * +copy_protocol(struct protoent *in) { - if (p == NULL) return; - free_protocol_data(p); - free(p); + if (in == NULL) return NULL; + + return (struct protoent *)LI_ils_create("s*4", in->p_name, in->p_aliases, in->p_proto); } -static void -free_lu_thread_info_protocol(void *x) +/* + * Extract the next protocol entry from a kvarray. + */ +static void * +extract_protocol(kvarray_t *in) { - struct lu_thread_info *tdata; - - if (x == NULL) return; + struct protoent tmp; + uint32_t d, k, kcount; + char *empty[1]; - 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); -} + if (in == NULL) return NULL; -static struct protoent * -extract_protocol(XDR *xdr) -{ - struct protoent *p; - int i, j, nvals, nkeys, status; - char *key, **vals; + d = in->curr; + in->curr++; - if (xdr == NULL) return NULL; + if (d >= in->count) return NULL; - if (!xdr_int(xdr, &nkeys)) return NULL; + empty[0] = NULL; + memset(&tmp, 0, ENTRY_SIZE); - p = (struct protoent *)calloc(1, sizeof(struct protoent)); + kcount = in->dict[d].kcount; - for (i = 0; i < nkeys; i++) + for (k = 0; k < kcount; k++) { - key = NULL; - vals = NULL; - nvals = 0; - - status = _lu_xdr_attribute(xdr, &key, &vals, &nvals); - if (status < 0) + if (!strcmp(in->dict[d].key[k], "p_name")) { - free_protocol(p); - return NULL; - } + if (tmp.p_name != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; - if (nvals == 0) - { - free(key); - continue; + tmp.p_name = (char *)in->dict[d].val[k][0]; } - - j = 0; - - if ((p->p_name == NULL) && (!strcmp("name", key))) + else if (!strcmp(in->dict[d].key[k], "p_proto")) { - 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; + if (in->dict[d].vcount[k] == 0) continue; + tmp.p_proto = atoi(in->dict[d].val[k][0]); } - else if (!strcmp("number", key)) + else if (!strcmp(in->dict[d].key[k], "p_aliases")) { - p->p_proto = atoi(vals[0]); - } + if (tmp.p_aliases != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; - free(key); - if (vals != NULL) - { - for (; j < nvals; j++) free(vals[j]); - free(vals); + tmp.p_aliases = (char **)in->dict[d].val[k]; } } - 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; - - if (in == NULL) return NULL; - - p = (struct protoent *)calloc(1, sizeof(struct protoent)); - - 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++) - { - p->p_aliases[i] = strdup(in->p_aliases[i]); - } + if (tmp.p_name == NULL) tmp.p_name = ""; + if (tmp.p_aliases == NULL) tmp.p_aliases = empty; - return p; -} - -static void -recycle_protocol(struct lu_thread_info *tdata, struct protoent *in) -{ - struct protoent *p; - - if (tdata == NULL) return; - p = (struct protoent *)tdata->lu_entry; - - if (in == NULL) - { - free_protocol(p); - tdata->lu_entry = NULL; - } - - 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); + return copy_protocol(&tmp); } +/* + * Send a query to the system information daemon. + */ static struct protoent * -lu_getprotobynumber(long number) +ds_getprotobynumber(uint32_t number) { - struct protoent *p; - unsigned int datalen; - XDR inxdr; static int proc = -1; - char *lookup_buf; - int count; - - if (proc < 0) - { - if (_lookup_link(_lu_port, "getprotobynumber", &proc) != KERN_SUCCESS) - { - return NULL; - } - } + char val[16]; - number = htonl(number); - datalen = 0; - lookup_buf = NULL; - - if (_lookup_all(_lu_port, proc, (unit *)&number, 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_protocol(&inxdr); - xdr_destroy(&inxdr); - vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); - - return p; + snprintf(val, sizeof(val), "%u", number); + return (struct protoent *)LI_getone("getprotobynumber", &proc, extract_protocol, "number", val); } +/* + * Send a query to the system information daemon. + */ static struct protoent * -lu_getprotobyname(const char *name) +ds_getprotobyname(const char *name) { - struct protoent *p; - unsigned int datalen; - char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT]; - XDR outxdr; - XDR inxdr; static int proc = -1; - char *lookup_buf; - int count; - if (proc < 0) - { - if (_lookup_link(_lu_port, "getprotobyname", &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_protocol(&inxdr); - xdr_destroy(&inxdr); - vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); - - return p; + return (struct protoent *)LI_getone("getprotobyname", &proc, extract_protocol, "name", name); } +/* + * Clean up / initialize / reinitialize the kvarray used to hold a list of all protocol entries. + */ static void -lu_endprotoent() +ds_endprotoent() { - struct lu_thread_info *tdata; - - tdata = _lu_data_create_key(_lu_data_key_protocol, free_lu_thread_info_protocol); - _lu_data_free_vm_xdr(tdata); + LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY)); } static void -lu_setprotoent() +ds_setprotoent() { - lu_endprotoent(); + ds_endprotoent(); } - static struct protoent * -lu_getprotoent() +ds_getprotoent() { - struct protoent *p; static int proc = -1; - 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 (tdata->lu_vm == NULL) - { - if (proc < 0) - { - if (_lookup_link(_lu_port, "getprotoent", &proc) != KERN_SUCCESS) - { - lu_endprotoent(); - return NULL; - } - } - - if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS) - { - lu_endprotoent(); - 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_endprotoent(); - return NULL; - } - } - - if (tdata->lu_vm_cursor == 0) - { - lu_endprotoent(); - return NULL; - } - - p = extract_protocol(tdata->lu_xdr); - if (p == NULL) - { - lu_endprotoent(); - return NULL; - } - - tdata->lu_vm_cursor--; - - return p; + return (struct protoent *)LI_getent("getprotoent", &proc, extract_protocol, ENTRY_KEY, ENTRY_SIZE); } static struct protoent * getproto(const char *name, int number, int source) { struct protoent *res = NULL; - struct lu_thread_info *tdata; + struct li_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); - } + tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); + if (tdata == NULL) return NULL; - if (_lu_running()) + if (_ds_running()) { switch (source) { case PROTO_GET_NAME: - res = lu_getprotobyname(name); + res = ds_getprotobyname(name); break; case PROTO_GET_NUM: - res = lu_getprotobynumber(number); + res = ds_getprotobynumber(number); break; case PROTO_GET_ENT: - res = lu_getprotoent(); + res = ds_getprotoent(); break; default: res = NULL; } } else { + pthread_mutex_lock(&_protocol_lock); + switch (source) { case PROTO_GET_NAME: @@ -461,10 +197,12 @@ getproto(const char *name, int number, int source) break; default: res = NULL; } + + pthread_mutex_unlock(&_protocol_lock); } - recycle_protocol(tdata, res); - return (struct protoent *)tdata->lu_entry; + LI_data_recycle(tdata, res, ENTRY_SIZE); + return (struct protoent *)tdata->li_entry; } struct protoent * @@ -488,13 +226,13 @@ getprotoent(void) void setprotoent(int stayopen) { - if (_lu_running()) lu_setprotoent(); + if (_ds_running()) ds_setprotoent(); else _old_setprotoent(stayopen); } void endprotoent(void) { - if (_lu_running()) lu_endprotoent(); + if (_ds_running()) ds_endprotoent(); else _old_endprotoent(); } diff --git a/lookup.subproj/lu_rpc.c b/lookup.subproj/lu_rpc.c index 5381201..5919e09 100644 --- a/lookup.subproj/lu_rpc.c +++ b/lookup.subproj/lu_rpc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -32,11 +32,9 @@ #include #include #include +#include #include #include - -#include "_lu_types.h" -#include "lookup.h" #include "lu_utils.h" #include "lu_overrides.h" @@ -46,400 +44,147 @@ static pthread_mutex_t _rpc_lock = PTHREAD_MUTEX_INITIALIZER; #define RPC_GET_NUM 2 #define RPC_GET_ENT 3 -static void -free_rpc_data(struct rpcent *r) -{ - char **aliases; - - if (r == NULL) return; - - if (r->r_name != NULL) free(r->r_name); +#define ENTRY_SIZE sizeof(struct rpcent) +#define ENTRY_KEY _li_data_key_rpc - aliases = r->r_aliases; - if (aliases != NULL) - { - while (*aliases != NULL) free(*aliases++); - free(r->r_aliases); - } -} - -static void -free_rpc(struct rpcent *r) +static struct rpcent * +copy_rpc(struct rpcent *in) { - if (r == NULL) return; - free_rpc_data(r); - free(r); + if (in == NULL) return NULL; + + return (struct rpcent *)LI_ils_create("s*4", in->r_name, in->r_aliases, in->r_number); } -static void -free_lu_thread_info_rpc(void *x) +/* + * Extract the next rpc entry from a kvarray. + */ +static void * +extract_rpc(kvarray_t *in) { - struct lu_thread_info *tdata; + struct rpcent tmp; + uint32_t d, k, kcount; + char *empty[1]; - 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; - } + if (in == NULL) return NULL; - _lu_data_free_vm_xdr(tdata); + d = in->curr; + in->curr++; - free(tdata); -} + if (d >= in->count) return NULL; -static struct rpcent * -extract_rpc(XDR *xdr) -{ - struct rpcent *r; - int i, j, nvals, nkeys, status; - char *key, **vals; + empty[0] = NULL; + memset(&tmp, 0, ENTRY_SIZE); - if (xdr == NULL) return NULL; + kcount = in->dict[d].kcount; - if (!xdr_int(xdr, &nkeys)) return NULL; - - r = (struct rpcent *)calloc(1, sizeof(struct rpcent)); - - for (i = 0; i < nkeys; i++) + for (k = 0; k < kcount; k++) { - key = NULL; - vals = NULL; - nvals = 0; - - status = _lu_xdr_attribute(xdr, &key, &vals, &nvals); - if (status < 0) + if (!strcmp(in->dict[d].key[k], "r_name")) { - free_rpc(r); - return NULL; - } + if (tmp.r_name != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; - if (nvals == 0) - { - free(key); - continue; + tmp.r_name = (char *)in->dict[d].val[k][0]; } - - j = 0; - - if ((r->r_name == NULL) && (!strcmp("name", key))) + else if (!strcmp(in->dict[d].key[k], "r_number")) { - 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]); + if (in->dict[d].vcount[k] == 0) continue; + tmp.r_number = atoi(in->dict[d].val[k][0]); } - - free(key); - if (vals != NULL) + else if (!strcmp(in->dict[d].key[k], "r_aliases")) { - for (; j < nvals; j++) free(vals[j]); - free(vals); - } - } + if (tmp.r_aliases != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; - 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; - - if (in == NULL) return NULL; - - r = (struct rpcent *)calloc(1, sizeof(struct rpcent)); - - r->r_name = LU_COPY_STRING(in->r_name); - - len = 0; - if (in->r_aliases != NULL) - { - for (len = 0; in->r_aliases[len] != NULL; len++); - } - - r->r_aliases = (char **)calloc(len + 1, sizeof(char *)); - for (i = 0; i < len; i++) - { - r->r_aliases[i] = strdup(in->r_aliases[i]); - } - - r->r_number = in->r_number; - - 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; + tmp.r_aliases = (char **)in->dict[d].val[k]; + } } - free_rpc_data(r); + if (tmp.r_name == NULL) tmp.r_name = ""; + if (tmp.r_aliases == NULL) tmp.r_aliases = empty; - r->r_name = in->r_name; - r->r_aliases = in->r_aliases; - r->r_number = in->r_number; - - free(in); + return copy_rpc(&tmp); } +/* + * Send a query to the system information daemon. + */ static struct rpcent * -lu_getrpcbynumber(long number) +ds_getrpcbynumber(uint32_t number) { - struct rpcent *r; - unsigned datalen; - XDR inxdr; static int proc = -1; - char *lookup_buf; - int count; - - if (proc < 0) - { - if (_lookup_link(_lu_port, "getrpcbynumber", &proc) != KERN_SUCCESS) - { - return NULL; - } - } - - number = htonl(number); - datalen = 0; - lookup_buf = NULL; + char val[16]; - if (_lookup_all(_lu_port, proc, (unit *)&number, 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; - } - - r = extract_rpc(&inxdr); - xdr_destroy(&inxdr); - vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); - - return r; + snprintf(val, sizeof(val), "%u", number); + return (struct rpcent *)LI_getone("getrpcbynumber", &proc, extract_rpc, "number", val); } +/* + * Send a query to the system information daemon. + */ static struct rpcent * -lu_getrpcbyname(const char *name) +ds_getrpcbyname(const char *name) { - struct rpcent *r; - unsigned datalen; - char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT]; - XDR outxdr, inxdr; static int proc = -1; - char *lookup_buf; - int count; - - if (proc < 0) - { - if (_lookup_link(_lu_port, "getrpcbyname", &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; - } - - r = extract_rpc(&inxdr); - xdr_destroy(&inxdr); - vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); - return r; + return (struct rpcent *)LI_getone("getrpcbyname", &proc, extract_rpc, "name", name); } +/* + * Clean up / initialize / reinitialize the kvarray used to hold a list of all rpc entries. + */ static void -lu_endrpcent(void) +ds_endrpcent(void) { - 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); + LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY)); } static void -lu_setrpcent() +ds_setrpcent(void) { - lu_endrpcent(); + ds_endrpcent(); } +/* + * Get an entry from the getrpcent kvarray. + * Calls the system information daemon if the list doesn't exist (first call), + * or extracts the next entry if the list has been fetched. + */ static struct rpcent * -lu_getrpcent() +ds_getrpcent(void) { - struct rpcent *r; static int proc = -1; - 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 (tdata->lu_vm == NULL) - { - if (proc < 0) - { - if (_lookup_link(_lu_port, "getrpcent", &proc) != KERN_SUCCESS) - { - lu_endrpcent(); - return NULL; - } - } - - if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS) - { - lu_endrpcent(); - 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_endrpcent(); - return NULL; - } - } - - if (tdata->lu_vm_cursor == 0) - { - lu_endrpcent(); - return NULL; - } - - r = extract_rpc(tdata->lu_xdr); - if (r == NULL) - { - lu_endrpcent(); - return NULL; - } - tdata->lu_vm_cursor--; - - return r; + return (struct rpcent *)LI_getent("getrpcent", &proc, extract_rpc, ENTRY_KEY, ENTRY_SIZE); } +/* + * Checks if the system information daemon is running. + * If so, calls the appropriate fetch routine. + * If not, calls the appropriate "_old" routine. + * Places the result in thread-specific memory. + */ static struct rpcent * -getrpc(const char *name, long number, int source) +getrpc(const char *name, uint32_t number, int source) { struct rpcent *res = NULL; - struct lu_thread_info *tdata; + struct li_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); - } + tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); + if (tdata == NULL) return NULL; - if (_lu_running()) + if (_ds_running()) { switch (source) { case RPC_GET_NAME: - res = lu_getrpcbyname(name); + res = ds_getrpcbyname(name); break; case RPC_GET_NUM: - res = lu_getrpcbynumber(number); + res = ds_getrpcbynumber(number); break; case RPC_GET_ENT: - res = lu_getrpcent(); + res = ds_getrpcent(); break; default: res = NULL; } @@ -447,6 +192,7 @@ getrpc(const char *name, long number, int source) else { pthread_mutex_lock(&_rpc_lock); + switch (source) { case RPC_GET_NAME: @@ -460,11 +206,12 @@ getrpc(const char *name, long number, int source) break; default: res = NULL; } + pthread_mutex_unlock(&_rpc_lock); } - recycle_rpc(tdata, res); - return (struct rpcent *)tdata->lu_entry; + LI_data_recycle(tdata, res, ENTRY_SIZE); + return (struct rpcent *)tdata->li_entry; } struct rpcent * @@ -474,9 +221,16 @@ getrpcbyname(const char *name) } struct rpcent * +#ifdef __LP64__ +getrpcbynumber(int number) +#else getrpcbynumber(long number) +#endif { - return getrpc(NULL, number, RPC_GET_NUM); + uint32_t n; + + n = number; + return getrpc(NULL, n, RPC_GET_NUM); } struct rpcent * @@ -488,13 +242,13 @@ getrpcent(void) void setrpcent(int stayopen) { - if (_lu_running()) lu_setrpcent(); + if (_ds_running()) ds_setrpcent(); else _old_setrpcent(stayopen); } void endrpcent(void) { - if (_lu_running()) lu_endrpcent(); + if (_ds_running()) ds_endrpcent(); else _old_endrpcent(); } diff --git a/lookup.subproj/lu_service.c b/lookup.subproj/lu_service.c index 58b3996..f249e96 100644 --- a/lookup.subproj/lu_service.c +++ b/lookup.subproj/lu_service.c @@ -29,24 +29,17 @@ #include #include #include -#include -#include #include #include #include - -#include "_lu_types.h" -#include "lookup.h" #include "lu_utils.h" #define SERVICE_CACHE_SIZE 10 -#define DEFAULT_SERVICE_CACHE_TTL 10 static pthread_mutex_t _service_cache_lock = PTHREAD_MUTEX_INITIALIZER; static void *_service_cache[SERVICE_CACHE_SIZE] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -static unsigned int _service_cache_best_before[SERVICE_CACHE_SIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned int _service_cache_index = 0; -static unsigned int _service_cache_ttl = DEFAULT_SERVICE_CACHE_TTL; +static unsigned int _service_cache_init = 0; static pthread_mutex_t _service_lock = PTHREAD_MUTEX_INITIALIZER; @@ -61,264 +54,146 @@ extern void _old_setservent(); extern void _old_endservent(); extern void _old_setservfile(); -static void -free_service_data(struct servent *s) -{ - char **aliases; - - if (s == NULL) return; - - if (s->s_name != NULL) free(s->s_name); - if (s->s_proto != NULL) free(s->s_proto); - - aliases = s->s_aliases; - if (aliases != NULL) - { - while (*aliases != NULL) free(*aliases++); - free(s->s_aliases); - } -} +#define ENTRY_SIZE sizeof(struct servent) +#define ENTRY_KEY _li_data_key_service -static void -free_service(struct servent *s) +static struct servent * +copy_service(struct servent *in) { - if (s == NULL) return; - free_service_data(s); - free(s); + if (in == NULL) return NULL; + + return LI_ils_create("s*4s", in->s_name, in->s_aliases, in->s_port, in->s_proto); } -static void -free_lu_thread_info_service(void *x) +/* + * Extract the next service entry from a kvarray. + */ +static void * +extract_service(kvarray_t *in) { - struct lu_thread_info *tdata; - - if (x == NULL) return; + struct servent tmp; + uint32_t d, k, kcount; + char *empty[1]; - tdata = (struct lu_thread_info *)x; - - if (tdata->lu_entry != NULL) - { - free_service((struct servent *)tdata->lu_entry); - tdata->lu_entry = NULL; - } + if (in == NULL) return NULL; - _lu_data_free_vm_xdr(tdata); + d = in->curr; + in->curr++; - free(tdata); -} + if (d >= in->count) return NULL; -static struct servent * -extract_service(XDR *xdr, const char *proto) -{ - struct servent *s; - int i, j, nvals, nkeys, status; - char *key, **vals; + empty[0] = NULL; + memset(&tmp, 0, ENTRY_SIZE); - if (xdr == NULL) return NULL; + kcount = in->dict[d].kcount; - if (!xdr_int(xdr, &nkeys)) return NULL; - - s = (struct servent *)calloc(1, sizeof(struct servent)); - - for (i = 0; i < nkeys; i++) + for (k = 0; k < kcount; k++) { - key = NULL; - vals = NULL; - nvals = 0; - - status = _lu_xdr_attribute(xdr, &key, &vals, &nvals); - if (status < 0) + if (!strcmp(in->dict[d].key[k], "s_name")) { - free_service(s); - return NULL; - } + if (tmp.s_name != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; - if (nvals == 0) - { - free(key); - continue; + tmp.s_name = (char *)in->dict[d].val[k][0]; } - - 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))) + else if (!strcmp(in->dict[d].key[k], "s_aliases")) { - if ((proto == NULL) || (proto[0] == '\0')) - { - s->s_proto = vals[0]; - j = 1; - } - else - { - s->s_proto = strdup(proto); - } + if (tmp.s_aliases != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.s_aliases = (char **)in->dict[d].val[k]; } - else if ((s->s_port == 0) && (!strcmp("port", key))) + else if (!strcmp(in->dict[d].key[k], "s_port")) { - s->s_port = htons(atoi(vals[0])); + if (in->dict[d].vcount[k] == 0) continue; + tmp.s_port = htons(atoi(in->dict[d].val[k][0])); } - - free(key); - if (vals != NULL) + else if (!strcmp(in->dict[d].key[k], "s_proto")) { - for (; j < nvals; j++) free(vals[j]); - free(vals); + if (tmp.s_proto != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.s_proto = (char *)in->dict[d].val[k][0]; } } - 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 *)); + if (tmp.s_name == NULL) tmp.s_name = ""; + if (tmp.s_proto == NULL) tmp.s_proto = ""; + if (tmp.s_aliases == NULL) tmp.s_aliases = empty; - return s; + return copy_service(&tmp); } -static struct servent * -copy_service(struct servent *in) +static void +cache_service(struct servent *s) { - int i, len; - struct servent *s; - - if (in == NULL) return NULL; - - s = (struct servent *)calloc(1, sizeof(struct servent)); + struct servent *scache; - s->s_name = LU_COPY_STRING(in->s_name); + if (s == NULL) return; - len = 0; - if (in->s_aliases != NULL) - { - for (len = 0; in->s_aliases[len] != NULL; len++); - } + pthread_mutex_lock(&_service_cache_lock); - s->s_aliases = (char **)calloc(len + 1, sizeof(char *)); - for (i = 0; i < len; i++) - { - s->s_aliases[i] = strdup(in->s_aliases[i]); - } + scache = copy_service(s); + + if (_service_cache[_service_cache_index] != NULL) LI_ils_free(_service_cache[_service_cache_index], ENTRY_SIZE); + _service_cache[_service_cache_index] = scache; + _service_cache_index = (_service_cache_index + 1) % SERVICE_CACHE_SIZE; - s->s_proto = LU_COPY_STRING(in->s_proto); - s->s_port = in->s_port; + _service_cache_init = 1; - return s; + pthread_mutex_unlock(&_service_cache_lock); } -static void -recycle_service(struct lu_thread_info *tdata, struct servent *in) +static int +service_cache_check() { - struct servent *s; - - if (tdata == NULL) return; - s = (struct servent *)tdata->lu_entry; + uint32_t i, status; - if (in == NULL) - { - free_service(s); - tdata->lu_entry = NULL; - } + /* don't consult cache if it has not been initialized */ + if (_service_cache_init == 0) return 1; - if (tdata->lu_entry == NULL) - { - tdata->lu_entry = in; - return; - } + status = LI_L1_cache_check(ENTRY_KEY); - free_service_data(s); + /* don't consult cache if it is disabled or if we can't validate */ + if ((status == LI_L1_CACHE_DISABLED) || (status == LI_L1_CACHE_FAILED)) return 1; - s->s_name = in->s_name; - s->s_aliases = in->s_aliases; - s->s_proto = in->s_proto; - s->s_port = in->s_port; - - free(in); -} - -__private_extern__ unsigned int -get_service_cache_ttl() -{ - return _service_cache_ttl; -} - -__private_extern__ void -set_service_cache_ttl(unsigned int ttl) -{ - int i; + /* return 0 if cache is OK */ + if (status == LI_L1_CACHE_OK) return 0; + /* flush cache */ pthread_mutex_lock(&_service_cache_lock); - _service_cache_ttl = ttl; - - if (ttl == 0) + for (i = 0; i < SERVICE_CACHE_SIZE; i++) { - for (i = 0; i < SERVICE_CACHE_SIZE; i++) - { - if (_service_cache[i] == NULL) continue; - - free_service((struct servent *)_service_cache[i]); - _service_cache[i] = NULL; - _service_cache_best_before[i] = 0; - } + LI_ils_free(_service_cache[i], ENTRY_SIZE); + _service_cache[i] = NULL; } - pthread_mutex_unlock(&_service_cache_lock); -} - -static void -cache_service(struct servent *s) -{ - struct timeval now; - struct servent *scache; - - if (_service_cache_ttl == 0) return; - if (s == NULL) return; - - pthread_mutex_lock(&_service_cache_lock); - - scache = copy_service(s); - - gettimeofday(&now, NULL); - - if (_service_cache[_service_cache_index] != NULL) - free_service((struct servent *)_service_cache[_service_cache_index]); - - _service_cache[_service_cache_index] = scache; - _service_cache_best_before[_service_cache_index] = now.tv_sec + _service_cache_ttl; - _service_cache_index = (_service_cache_index + 1) % SERVICE_CACHE_SIZE; + _service_cache_index = 0; pthread_mutex_unlock(&_service_cache_lock); + + /* don't consult cache - it's now empty */ + return 1; } + static struct servent * cache_getservbyname(const char *name, const char *proto) { int i; struct servent *s, *res; - struct timeval now; char **aliases; - if (_service_cache_ttl == 0) return NULL; if (name == NULL) return NULL; + if (service_cache_check() != 0) return NULL; pthread_mutex_lock(&_service_cache_lock); - gettimeofday(&now, NULL); - for (i = 0; i < SERVICE_CACHE_SIZE; i++) { - if (_service_cache_best_before[i] == 0) continue; - if ((unsigned int)now.tv_sec > _service_cache_best_before[i]) continue; - s = (struct servent *)_service_cache[i]; + if (s == NULL) continue; if (s->s_name != NULL) { @@ -363,20 +238,15 @@ cache_getservbyport(int port, const char *proto) { int i; struct servent *s, *res; - struct timeval now; - if (_service_cache_ttl == 0) return NULL; + if (service_cache_check() != 0) return NULL; pthread_mutex_lock(&_service_cache_lock); - gettimeofday(&now, NULL); - for (i = 0; i < SERVICE_CACHE_SIZE; i++) { - if (_service_cache_best_before[i] == 0) continue; - if ((unsigned int)now.tv_sec > _service_cache_best_before[i]) continue; - s = (struct servent *)_service_cache[i]; + if (s == NULL) continue; if (port == s->s_port) { @@ -394,258 +264,108 @@ cache_getservbyport(int port, const char *proto) } static struct servent * -lu_getservbyport(int port, const char *proto) +ds_getservbyport(int port, const char *proto) { - struct servent *s; - unsigned int datalen; - XDR outxdr, inxdr; + struct servent *entry; + kvbuf_t *request; + kvarray_t *reply; + kern_return_t status; static int proc = -1; - char output_buf[_LU_MAXLUSTRLEN + 3 * BYTES_PER_XDR_UNIT]; - char *lookup_buf; - int count; + uint16_t sport; + char val[16]; if (proc < 0) { - if (_lookup_link(_lu_port, "getservbyport", &proc) != KERN_SUCCESS) - { - return NULL; - } + status = LI_DSLookupGetProcedureNumber("getservbyport", &proc); + if (status != KERN_SUCCESS) return NULL; } - /* Encode NULL for xmission to lookupd. */ - if (proto == NULL) proto = ""; - - /* convert to host order */ - port = ntohs(port); - - xdrmem_create(&outxdr, output_buf, sizeof(output_buf), XDR_ENCODE); - if (!xdr_int(&outxdr, &port) || !xdr__lu_string(&outxdr, (_lu_string *)&proto)) - { - xdr_destroy(&outxdr); - return NULL; - } - - 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; - } + /* Encode NULL */ + if (proto == NULL) proto = ""; - xdr_destroy(&outxdr); + sport = port; + snprintf(val, sizeof(val), "%d", ntohs(sport)); - datalen *= BYTES_PER_XDR_UNIT; - if ((lookup_buf == NULL) || (datalen == 0)) return NULL; + request = kvbuf_query("ksks", "port", val, "proto", proto); + if (request == NULL) return NULL; - xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE); + reply = NULL; + status = LI_DSLookupQuery(proc, request, &reply); + kvbuf_free(request); - count = 0; - if (!xdr_int(&inxdr, &count)) - { - xdr_destroy(&inxdr); - vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); - return NULL; - } + if (status != KERN_SUCCESS) return NULL; - if (count == 0) - { - xdr_destroy(&inxdr); - vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); - return NULL; - } + entry = extract_service(reply); + kvarray_free(reply); - /* - * 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); - - return s; + return entry; } static struct servent * -lu_getservbyname(const char *name, const char *proto) +ds_getservbyname(const char *name, const char *proto) { - struct servent *s; - unsigned int datalen; - char *lookup_buf; - char output_buf[2 * (_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT)]; - XDR outxdr, inxdr; + struct servent *entry; + kvbuf_t *request; + kvarray_t *reply; + kern_return_t status; static int proc = -1; - int count; if (proc < 0) { - if (_lookup_link(_lu_port, "getservbyname", &proc) != KERN_SUCCESS) - { - return NULL; - } + status = LI_DSLookupGetProcedureNumber("getservbyname", &proc); + if (status != KERN_SUCCESS) return NULL; } - /* Encode NULL for xmission to lookupd. */ + /* Encode NULL */ + if (name == NULL) name = ""; if (proto == NULL) proto = ""; - xdrmem_create(&outxdr, output_buf, sizeof(output_buf), XDR_ENCODE); - if (!xdr__lu_string(&outxdr, (_lu_string *)&name) || - !xdr__lu_string(&outxdr, (_lu_string *)&proto)) - { - xdr_destroy(&outxdr); - return NULL; - } - - 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; - } + request = kvbuf_query("ksks", "name", name, "proto", proto); + if (request == NULL) return NULL; - xdr_destroy(&outxdr); + reply = NULL; + status = LI_DSLookupQuery(proc, request, &reply); + kvbuf_free(request); - datalen *= BYTES_PER_XDR_UNIT; - if ((lookup_buf == NULL) || (datalen == 0)) return NULL; + if (status != KERN_SUCCESS) return NULL; - xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE); + entry = extract_service(reply); + kvarray_free(reply); - 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; - } - - /* - * 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); - - return s; + return entry; } static void -lu_endservent() +ds_endservent() { - 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); + LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY)); } static void -lu_setservent() +ds_setservent() { - lu_endservent(); + ds_endservent(); } static struct servent * -lu_getservent() +ds_getservent() { - struct servent *s; static int proc = -1; - 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 (tdata->lu_vm == NULL) - { - if (proc < 0) - { - if (_lookup_link(_lu_port, "getservent", &proc) != KERN_SUCCESS) - { - lu_endservent(); - return NULL; - } - } - - if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS) - { - lu_endservent(); - 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_endservent(); - return NULL; - } - } - - if (tdata->lu_vm_cursor == 0) - { - lu_endservent(); - return NULL; - } - - s = extract_service(tdata->lu_xdr, NULL); - if (s == NULL) - { - lu_endservent(); - return NULL; - } - - tdata->lu_vm_cursor--; - - return s; + return (struct servent *)LI_getent("getservent", &proc, extract_service, ENTRY_KEY, ENTRY_SIZE); } static struct servent * getserv(const char *name, const char *proto, int port, int source) { struct servent *res = NULL; - struct lu_thread_info *tdata; - int from_cache; + struct li_thread_info *tdata; + int add_to_cache; - 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); - } + tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); + if (tdata == NULL) return NULL; - from_cache = 0; + add_to_cache = 0; res = NULL; switch (source) @@ -661,23 +381,24 @@ getserv(const char *name, const char *proto, int port, int source) if (res != NULL) { - from_cache = 1; } - else if (_lu_running()) + else if (_ds_running()) { switch (source) { case S_GET_NAME: - res = lu_getservbyname(name, proto); + res = ds_getservbyname(name, proto); break; case S_GET_PORT: - res = lu_getservbyport(port, proto); + res = ds_getservbyport(port, proto); break; case S_GET_ENT: - res = lu_getservent(); + res = ds_getservent(); break; default: res = NULL; } + + if (res != NULL) add_to_cache = 1; } else { @@ -698,10 +419,10 @@ getserv(const char *name, const char *proto, int port, int source) pthread_mutex_unlock(&_service_lock); } - if (from_cache == 0) cache_service(res); + if (add_to_cache == 1) cache_service(res); - recycle_service(tdata, res); - return (struct servent *)tdata->lu_entry; + LI_data_recycle(tdata, res, ENTRY_SIZE); + return (struct servent *)tdata->li_entry; } struct servent * @@ -725,13 +446,13 @@ getservent(void) void setservent(int stayopen) { - if (_lu_running()) lu_setservent(); + if (_ds_running()) ds_setservent(); else _old_setservent(); } void endservent(void) { - if (_lu_running()) lu_endservent(); + if (_ds_running()) ds_endservent(); else _old_endservent(); } diff --git a/lookup.subproj/lu_user.c b/lookup.subproj/lu_user.c index e7f92af..b44cd41 100644 --- a/lookup.subproj/lu_user.c +++ b/lookup.subproj/lu_user.c @@ -29,27 +29,20 @@ #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" #define USER_CACHE_SIZE 10 -#define DEFAULT_USER_CACHE_TTL 10 static pthread_mutex_t _user_cache_lock = PTHREAD_MUTEX_INITIALIZER; -static void *_user_cache[USER_CACHE_SIZE] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -static unsigned int _user_cache_best_before[USER_CACHE_SIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static void *_user_cache[USER_CACHE_SIZE] = { NULL }; static unsigned int _user_cache_index = 0; -static unsigned int _user_cache_ttl = DEFAULT_USER_CACHE_TTL; +static unsigned int _user_cache_init = 0; static pthread_mutex_t _user_lock = PTHREAD_MUTEX_INITIALIZER; @@ -57,172 +50,120 @@ static pthread_mutex_t _user_lock = PTHREAD_MUTEX_INITIALIZER; #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); -} +#define ENTRY_SIZE sizeof(struct passwd) +#define ENTRY_KEY _li_data_key_user -static void -free_user(struct passwd *p) -{ - if (p == NULL) return; - free_user_data(p); - free(p); -} +__private_extern__ struct passwd *LI_files_getpwent(); +__private_extern__ struct passwd *LI_files_getpwnam(const char *name); +__private_extern__ struct passwd *LI_files_getpwuid(uid_t uid); +__private_extern__ void LI_files_setpwent(); +__private_extern__ void LI_files_endpwent(); -static void -free_lu_thread_info_user(void *x) +static struct passwd * +copy_user(struct passwd *in) { - 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); + if (in == NULL) return NULL; - free(tdata); + return (struct passwd *)LI_ils_create("ss44LssssL", in->pw_name, in->pw_passwd, in->pw_uid, in->pw_gid, in->pw_change, in->pw_class, in->pw_gecos, in->pw_dir, in->pw_shell, in->pw_expire); } -static struct passwd * -extract_user(XDR *xdr) +/* + * Extract the next user entry from a kvarray. + */ +static void * +extract_user(kvarray_t *in) { - int i, j, nvals, nkeys, status; - char *key, **vals; - struct passwd *p; + struct passwd tmp; + uint32_t d, k, kcount; - if (xdr == NULL) return NULL; + if (in == NULL) return NULL; - if (!xdr_int(xdr, &nkeys)) return NULL; + d = in->curr; + in->curr++; - p = (struct passwd *)calloc(1, sizeof(struct passwd)); + if (d >= in->count) return NULL; - p->pw_uid = -2; - p->pw_gid = -2; + memset(&tmp, 0, ENTRY_SIZE); - for (i = 0; i < nkeys; i++) - { - key = NULL; - vals = NULL; - nvals = 0; + tmp.pw_uid = -2; + tmp.pw_gid = -2; - status = _lu_xdr_attribute(xdr, &key, &vals, &nvals); - if (status < 0) - { - free_user(p); - return NULL; - } + kcount = in->dict[d].kcount; - if (nvals == 0) + for (k = 0; k < kcount; k++) + { + if (!strcmp(in->dict[d].key[k], "pw_name")) { - free(key); - continue; - } - - j = 0; + if (tmp.pw_name != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; - if ((p->pw_name == NULL) && (!strcmp("name", key))) - { - p->pw_name = vals[0]; - j = 1; + tmp.pw_name = (char *)in->dict[d].val[k][0]; } - else if ((p->pw_passwd == NULL) && (!strcmp("passwd", key))) + else if (!strcmp(in->dict[d].key[k], "pw_passwd")) { - p->pw_passwd = vals[0]; - j = 1; + if (tmp.pw_passwd != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.pw_passwd = (char *)in->dict[d].val[k][0]; } - else if ((p->pw_class == NULL) && (!strcmp("class", key))) + else if (!strcmp(in->dict[d].key[k], "pw_uid")) { - p->pw_class = vals[0]; - j = 1; + if (in->dict[d].vcount[k] == 0) continue; + tmp.pw_uid = atoi(in->dict[d].val[k][0]); } - else if ((p->pw_gecos == NULL) && (!strcmp("realname", key))) + else if (!strcmp(in->dict[d].key[k], "pw_gid")) { - p->pw_gecos = vals[0]; - j = 1; + if (in->dict[d].vcount[k] == 0) continue; + tmp.pw_gid = atoi(in->dict[d].val[k][0]); } - else if ((p->pw_dir == NULL) && (!strcmp("home", key))) + else if (!strcmp(in->dict[d].key[k], "pw_change")) { - p->pw_dir = vals[0]; - j = 1; + if (in->dict[d].vcount[k] == 0) continue; + tmp.pw_change = atol(in->dict[d].val[k][0]); } - else if ((p->pw_shell == NULL) && (!strcmp("shell", key))) + else if (!strcmp(in->dict[d].key[k], "pw_expire")) { - p->pw_shell = vals[0]; - j = 1; + if (in->dict[d].vcount[k] == 0) continue; + tmp.pw_expire = atol(in->dict[d].val[k][0]); } - else if ((p->pw_uid == (uid_t)-2) && (!strcmp("uid", key))) + else if (!strcmp(in->dict[d].key[k], "pw_class")) { - p->pw_uid = atoi(vals[0]); - if ((p->pw_uid == 0) && (strcmp(vals[0], "0"))) p->pw_uid = -2; + if (tmp.pw_class != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.pw_class = (char *)in->dict[d].val[k][0]; } - else if ((p->pw_gid == (gid_t)-2) && (!strcmp("gid", key))) + else if (!strcmp(in->dict[d].key[k], "pw_gecos")) { - p->pw_gid = atoi(vals[0]); - if ((p->pw_gid == 0) && (strcmp(vals[0], "0"))) p->pw_gid = -2; + if (tmp.pw_gecos != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.pw_gecos = (char *)in->dict[d].val[k][0]; } - else if (!strcmp("change", key)) - { - p->pw_change = atoi(vals[0]); - } - else if (!strcmp("expire", key)) + else if (!strcmp(in->dict[d].key[k], "pw_dir")) { - p->pw_expire = atoi(vals[0]); - } + if (tmp.pw_dir != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; - free(key); - if (vals != NULL) + tmp.pw_dir = (char *)in->dict[d].val[k][0]; + } + else if (!strcmp(in->dict[d].key[k], "pw_shell")) { - for (; j < nvals; j++) free(vals[j]); - free(vals); + if (tmp.pw_shell != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.pw_shell = (char *)in->dict[d].val[k][0]; } } - 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(""); + if (tmp.pw_name == NULL) tmp.pw_name = ""; + if (tmp.pw_passwd == NULL) tmp.pw_passwd = ""; + if (tmp.pw_class == NULL) tmp.pw_class = ""; + if (tmp.pw_gecos == NULL) tmp.pw_gecos = ""; + if (tmp.pw_dir == NULL) tmp.pw_dir = ""; + if (tmp.pw_shell == NULL) tmp.pw_shell = ""; - 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; + return copy_user(&tmp); } static int @@ -317,117 +258,74 @@ copy_user_r(struct passwd *in, struct passwd *out, char *buffer, int buflen) } static void -recycle_user(struct lu_thread_info *tdata, struct passwd *in) +cache_user(struct passwd *pw) { - struct passwd *p; + struct passwd *pwcache; - if (tdata == NULL) return; - p = (struct passwd *)tdata->lu_entry; + if (pw == NULL) return; - if (in == NULL) - { - free_user(p); - tdata->lu_entry = NULL; - } + pthread_mutex_lock(&_user_cache_lock); - if (tdata->lu_entry == NULL) - { - tdata->lu_entry = in; - return; - } + pwcache = copy_user(pw); - free_user_data(p); + if (_user_cache[_user_cache_index] != NULL) LI_ils_free(_user_cache[_user_cache_index], ENTRY_SIZE); - 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; + _user_cache[_user_cache_index] = pwcache; + _user_cache_index = (_user_cache_index + 1) % USER_CACHE_SIZE; - free(in); -} + _user_cache_init = 1; -__private_extern__ unsigned int -get_user_cache_ttl() -{ - return _user_cache_ttl; + pthread_mutex_unlock(&_user_cache_lock); } -__private_extern__ void -set_user_cache_ttl(unsigned int ttl) +static int +user_cache_check() { - int i; - - pthread_mutex_lock(&_user_cache_lock); + uint32_t i, status; - _user_cache_ttl = ttl; - - if (ttl == 0) - { - for (i = 0; i < USER_CACHE_SIZE; i++) - { - if (_user_cache[i] == NULL) continue; + /* don't consult cache if it has not been initialized */ + if (_user_cache_init == 0) return 1; - free_user((struct passwd *)_user_cache[i]); - _user_cache[i] = NULL; - _user_cache_best_before[i] = 0; - } - } - - pthread_mutex_unlock(&_user_cache_lock); -} + status = LI_L1_cache_check(ENTRY_KEY); -static void -cache_user(struct passwd *pw) -{ - struct timeval now; - struct passwd *pwcache; + /* don't consult cache if it is disabled or if we can't validate */ + if ((status == LI_L1_CACHE_DISABLED) || (status == LI_L1_CACHE_FAILED)) return 1; - if (_user_cache_ttl == 0) return; - if (pw == NULL) return; + /* return 0 if cache is OK */ + if (status == LI_L1_CACHE_OK) return 0; + /* flush cache */ pthread_mutex_lock(&_user_cache_lock); - pwcache = copy_user(pw); - - gettimeofday(&now, NULL); + for (i = 0; i < USER_CACHE_SIZE; i++) + { + LI_ils_free(_user_cache[i], ENTRY_SIZE); + _user_cache[i] = NULL; + } - if (_user_cache[_user_cache_index] != NULL) - free_user((struct passwd *)_user_cache[_user_cache_index]); - - _user_cache[_user_cache_index] = pwcache; - _user_cache_best_before[_user_cache_index] = now.tv_sec + _user_cache_ttl; - _user_cache_index = (_user_cache_index + 1) % USER_CACHE_SIZE; + _user_cache_index = 0; pthread_mutex_unlock(&_user_cache_lock); + + /* don't consult cache - it's now empty */ + return 1; } static struct passwd * cache_getpwnam(const char *name) { - int i; + uint32_t i; struct passwd *pw, *res; - struct timeval now; - if (_user_cache_ttl == 0) return NULL; if (name == NULL) return NULL; + if (user_cache_check() != 0) return NULL; pthread_mutex_lock(&_user_cache_lock); - gettimeofday(&now, NULL); - for (i = 0; i < USER_CACHE_SIZE; i++) { - if (_user_cache_best_before[i] == 0) continue; - if ((unsigned int)now.tv_sec > _user_cache_best_before[i]) continue; - pw = (struct passwd *)_user_cache[i]; - + if (pw == NULL) continue; if (pw->pw_name == NULL) continue; if (!strcmp(name, pw->pw_name)) @@ -443,26 +341,21 @@ cache_getpwnam(const char *name) } static struct passwd * -cache_getpwuid(int uid) +cache_getpwuid(uid_t uid) { - int i; + uint32_t i; struct passwd *pw, *res; - struct timeval now; - if (_user_cache_ttl == 0) return NULL; + if (user_cache_check() != 0) return NULL; pthread_mutex_lock(&_user_cache_lock); - gettimeofday(&now, NULL); - for (i = 0; i < USER_CACHE_SIZE; i++) { - if (_user_cache_best_before[i] == 0) continue; - if ((unsigned int)now.tv_sec > _user_cache_best_before[i]) continue; - pw = (struct passwd *)_user_cache[i]; + if (pw == NULL) continue; - if ((uid_t)uid == pw->pw_uid) + if (uid == pw->pw_uid) { res = copy_user(pw); pthread_mutex_unlock(&_user_cache_lock); @@ -471,274 +364,56 @@ cache_getpwuid(int uid) } pthread_mutex_unlock(&_user_cache_lock); + return NULL; } static struct passwd * -lu_getpwuid(int uid) +ds_getpwuid(uid_t uid) { - struct passwd *p; - unsigned int datalen; - XDR inxdr; static int proc = -1; - int count; - char *lookup_buf; + char val[16]; - 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; + snprintf(val, sizeof(val), "%d", (int)uid); + return (struct passwd *)LI_getone("getpwuid", &proc, extract_user, "uid", val); } static struct passwd * -lu_getpwnam(const char *name) +ds_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; + return (struct passwd *)LI_getone("getpwnam", &proc, extract_user, "login", name); } static void -lu_endpwent(void) +ds_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); + LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY)); } static int -lu_setpwent(void) +ds_setpwent(void) { - lu_endpwent(); + ds_endpwent(); return 1; } static struct passwd * -lu_getpwent() +ds_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; + return (struct passwd *)LI_getent("getpwent", &proc, extract_user, ENTRY_KEY, ENTRY_SIZE); } static struct passwd * getpw_internal(const char *name, uid_t uid, int source) { - static char *loginName = NULL; - static struct passwd *loginEnt = NULL; struct passwd *res; - char *l; - int from_cache; + int add_to_cache; - if (loginName == NULL) - { - l = getlogin(); - if ((l != NULL) && (strcmp("root", l) != 0)) - { - 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; - } - } - - from_cache = 0; + add_to_cache = 0; res = NULL; switch (source) @@ -754,44 +429,47 @@ getpw_internal(const char *name, uid_t uid, int source) if (res != NULL) { - from_cache = 1; } - else if (_lu_running()) + else if (_ds_running()) { switch (source) { case PW_GET_NAME: - res = lu_getpwnam(name); + res = ds_getpwnam(name); break; case PW_GET_UID: - res = lu_getpwuid(uid); + res = ds_getpwuid(uid); break; case PW_GET_ENT: - res = lu_getpwent(); + res = ds_getpwent(); break; default: res = NULL; } + + if (res != NULL) add_to_cache = 1; } else { pthread_mutex_lock(&_user_lock); + switch (source) { case PW_GET_NAME: - res = copy_user(_old_getpwnam(name)); + res = copy_user(LI_files_getpwnam(name)); break; case PW_GET_UID: - res = copy_user(_old_getpwuid(uid)); + res = copy_user(LI_files_getpwuid(uid)); break; case PW_GET_ENT: - res = copy_user(_old_getpwent()); + res = copy_user(LI_files_getpwent()); break; default: res = NULL; } + pthread_mutex_unlock(&_user_lock); } - if (from_cache == 0) cache_user(res); + if (add_to_cache == 1) cache_user(res); return res; } @@ -800,20 +478,15 @@ static struct passwd * getpw(const char *name, uid_t uid, int source) { struct passwd *res = NULL; - struct lu_thread_info *tdata; + struct li_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); - } + tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); + if (tdata == NULL) return NULL; res = getpw_internal(name, uid, source); - recycle_user(tdata, res); - - return (struct passwd *)tdata->lu_entry; + LI_data_recycle(tdata, res, ENTRY_SIZE); + return (struct passwd *)tdata->li_entry; } static int @@ -823,19 +496,15 @@ getpw_r(const char *name, uid_t uid, int source, struct passwd *pwd, char *buffe int status; *result = NULL; - errno = 0; res = getpw_internal(name, uid, source); - if (res == NULL) return -1; + if (res == NULL) return 0; status = copy_user_r(res, pwd, buffer, bufsize); - free_user(res); - if (status != 0) - { - errno = ERANGE; - return -1; - } + LI_ils_free(res, ENTRY_SIZE); + + if (status != 0) return ERANGE; *result = pwd; return 0; @@ -859,19 +528,18 @@ getpwent(void) return getpw(NULL, -2, PW_GET_ENT); } -int +void setpwent(void) { - if (_lu_running()) lu_setpwent(); - else _old_setpwent(); - return 1; + if (_ds_running()) ds_setpwent(); + else LI_files_setpwent(); } void endpwent(void) { - if (_lu_running()) lu_endpwent(); - else _old_endpwent(); + if (_ds_running()) ds_endpwent(); + else LI_files_endpwent(); } int diff --git a/lookup.subproj/lu_utils.c b/lookup.subproj/lu_utils.c index 5970cf2..02e8d14 100644 --- a/lookup.subproj/lu_utils.c +++ b/lookup.subproj/lu_utils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,98 +22,101 @@ * @APPLE_LICENSE_HEADER_END@ */ +#include #include #include #include +#include #include -#ifdef DEBUG +#include +#include #include +#include +#ifdef DEBUG +#include #endif -#include "_lu_types.h" -#include "lookup.h" #include "lu_utils.h" #include "netdb_async.h" +#include "DSlibinfoMIG.h" +#include "DSlibinfoMIGAsyncReply.h" #define MAX_LOOKUP_ATTEMPTS 10 #define _LU_MAXLUSTRLEN 256 -#define QBUF_SIZE 4096 +#define QBUF_SIZE 16384 +#define KVBUF_START_SIZE 128 + +#define LI_MESSAGE_SEND_ID 4241776 +#define LI_MESSAGE_REPLY_ID 4241876 + +#define ILS_MAGIC_SIZE 8 +#define ILS_MAGIC "ILSMAGIC" -#define LU_MESSAGE_SEND_ID 4241776 -#define LU_MESSAGE_REPLY_ID 4241876 +#define L1_CACHE_NOTIFICATION_KEY_GLOBAL "com.apple.system.DirectoryService.InvalidateCache" +#define L1_CACHE_NOTIFICATION_KEY_GROUP "com.apple.system.DirectoryService.InvalidateCache.group" +#define L1_CACHE_NOTIFICATION_KEY_HOST "com.apple.system.DirectoryService.InvalidateCache.host" +#define L1_CACHE_NOTIFICATION_KEY_SERVICE "com.apple.system.DirectoryService.InvalidateCache.service" +#define L1_CACHE_NOTIFICATION_KEY_USER "com.apple.system.DirectoryService.InvalidateCache.user" + +/* GLOBAL */ +uint32_t gL1CacheEnabled = 1; + +static const uint32_t align_32[] = { 0, 1, 2, 0, 4, 0, 0, 0, 4 }; +static const uint32_t align_64[] = { 0, 1, 2, 0, 4, 0, 0, 0, 8 }; static pthread_key_t _info_key = 0; static pthread_once_t _info_key_initialized = PTHREAD_ONCE_INIT; -struct _lu_data_s +static pthread_mutex_t _notify_lock = PTHREAD_MUTEX_INITIALIZER; +static int _L1_notify_token[] = +{ + -1, /* global */ + -1, /* group */ + -1, /* host */ + -1, /* service */ + -1 /* user */ +}; + +struct _li_data_s { - unsigned int icount; - unsigned int *ikey; + uint32_t icount; + uint32_t *ikey; void **idata; - void (**idata_destructor)(void *); }; -typedef struct _lu_async_request_s +typedef struct _li_async_request_s { mach_port_t reply_port; uint32_t retry; uint32_t proc; void *context; void *callback; - ooline_data request_buffer; - mach_msg_type_number_t request_buffer_len; - struct _lu_async_request_s *next; -} _lu_async_request_t; + char request[MAX_MIG_INLINE_DATA]; + mach_msg_type_number_t requestCnt; + char reply[MAX_MIG_INLINE_DATA]; + mach_msg_type_number_t replyCnt; + vm_address_t ooreply; + mach_msg_type_number_t ooreplyCnt; + security_token_t token; + struct _li_async_request_s *next; +} _li_async_request_t; -typedef struct -{ - mach_msg_header_t head; - NDR_record_t NDR; - int proc; - mach_msg_type_number_t query_data_len; - unit query_data[QBUF_SIZE]; -} _lu_query_msg_t; - -typedef struct -{ - mach_msg_header_t head; - mach_msg_body_t msgh_body; - mach_msg_ool_descriptor_t reply_data; - NDR_record_t NDR; - mach_msg_type_number_t reply_data_len; - mach_msg_format_0_trailer_t trailer; -} _lu_reply_msg_t; - -static pthread_mutex_t _lu_worklist_lock = PTHREAD_MUTEX_INITIALIZER; -static _lu_async_request_t *_lu_worklist = NULL; - -/* Send an asynchronous query message to lookupd */ +static pthread_mutex_t _li_worklist_lock = PTHREAD_MUTEX_INITIALIZER; +static _li_async_request_t *_li_worklist = NULL; + +/* Send an asynchronous query message. */ static kern_return_t -_lu_async_send(_lu_async_request_t *r) +_LI_async_send(_li_async_request_t *r) { - _lu_query_msg_t in; - register _lu_query_msg_t *inp = ∈ mach_msg_return_t status; - unsigned int msgh_size; + mach_vm_address_t cb; if (r == NULL) return KERN_FAILURE; if (r->retry == 0) return MIG_SERVER_DIED; r->retry--; - if (r->request_buffer_len > QBUF_SIZE) return MIG_ARRAY_TOO_LARGE; - - msgh_size = (sizeof(_lu_query_msg_t) - 16384) + ((4 * r->request_buffer_len)); - inp->head.msgh_bits = MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE); - inp->head.msgh_remote_port = _lu_port; - inp->head.msgh_local_port = r->reply_port; - inp->head.msgh_id = LU_MESSAGE_SEND_ID; - inp->NDR = NDR_record; - inp->proc = r->proc; - inp->query_data_len = r->request_buffer_len; - memcpy(inp->query_data, r->request_buffer, 4 * r->request_buffer_len); - - status = mach_msg(&inp->head, MACH_SEND_MSG, msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - if (status == MACH_MSG_SUCCESS) return KERN_SUCCESS; + cb = (mach_vm_address_t)(r->callback); + status = libinfoDSmig_Query_async(_ds_port, r->reply_port, r->proc, r->request, r->requestCnt, cb); if (status == MACH_SEND_INVALID_REPLY) { @@ -124,25 +127,25 @@ _lu_async_send(_lu_async_request_t *r) return status; } -static _lu_async_request_t * -_lu_worklist_remove(mach_port_t p) +static _li_async_request_t * +_LI_worklist_remove(mach_port_t p) { - _lu_async_request_t *r, *n; + _li_async_request_t *r, *n; if (p == MACH_PORT_NULL) return NULL; - if (_lu_worklist == NULL) return NULL; + if (_li_worklist == NULL) return NULL; - pthread_mutex_lock(&_lu_worklist_lock); + pthread_mutex_lock(&_li_worklist_lock); - if (_lu_worklist->reply_port == p) + if (_li_worklist->reply_port == p) { - r = _lu_worklist; - _lu_worklist = r->next; - pthread_mutex_unlock(&_lu_worklist_lock); + r = _li_worklist; + _li_worklist = r->next; + pthread_mutex_unlock(&_li_worklist_lock); return r; } - for (r = _lu_worklist; r != NULL; r = r->next) + for (r = _li_worklist; r != NULL; r = r->next) { n = r->next; if (n == NULL) break; @@ -150,167 +153,223 @@ _lu_worklist_remove(mach_port_t p) if (n->reply_port == p) { r->next = n->next; - pthread_mutex_unlock(&_lu_worklist_lock); + pthread_mutex_unlock(&_li_worklist_lock); return n; } } - pthread_mutex_unlock(&_lu_worklist_lock); + pthread_mutex_unlock(&_li_worklist_lock); return NULL; } -static _lu_async_request_t * -_lu_worklist_find(mach_port_t p) +static _li_async_request_t * +_LI_worklist_find(mach_port_t p) { - _lu_async_request_t *r; + _li_async_request_t *r; if (p == MACH_PORT_NULL) return NULL; - if (_lu_worklist == NULL) return NULL; + if (_li_worklist == NULL) return NULL; - pthread_mutex_lock(&_lu_worklist_lock); + pthread_mutex_lock(&_li_worklist_lock); - for (r = _lu_worklist; r != NULL; r = r->next) + for (r = _li_worklist; r != NULL; r = r->next) { if (r->reply_port == p) { - pthread_mutex_unlock(&_lu_worklist_lock); + pthread_mutex_unlock(&_li_worklist_lock); return r; } } - pthread_mutex_unlock(&_lu_worklist_lock); + pthread_mutex_unlock(&_li_worklist_lock); return NULL; } static void -_lu_free_request(_lu_async_request_t *r) +_LI_free_request(_li_async_request_t *r) { if (r == NULL) return; - if (r->request_buffer != NULL) free(r->request_buffer); - r->request_buffer = NULL; - - if (r->reply_port != MACH_PORT_NULL) mach_port_destroy(mach_task_self(), r->reply_port); + if (r->reply_port != MACH_PORT_NULL) mach_port_mod_refs(mach_task_self(), r->reply_port, MACH_PORT_RIGHT_RECEIVE, -1); r->reply_port = MACH_PORT_NULL; free(r); } -/* Receive an asynchronous reply message from lookupd */ +/* + * This is a callback for DSLibinfoMIGAsyncReplyServer.c + */ +__private_extern__ kern_return_t +libinfoDSmig_do_Response_async(mach_port_t server, char *reply, mach_msg_type_number_t replyCnt, vm_offset_t ooreply, mach_msg_type_number_t ooreplyCnt, mach_vm_address_t callbackAddr, security_token_t servertoken) +{ + _li_async_request_t *r; + + r = _LI_worklist_find(server); + + if (r != NULL) + { + r->ooreply = ooreply; + r->ooreplyCnt = ooreplyCnt; + if (replyCnt > 0) memcpy(r->reply, reply, replyCnt); + r->replyCnt = replyCnt; + r->token = servertoken; + } + else if (ooreplyCnt != 0) + { + vm_deallocate(mach_task_self(), ooreply, ooreplyCnt); + } + + return KERN_SUCCESS; +} + +/* Receive an asynchronous reply message. */ kern_return_t -lu_async_receive(mach_port_t p, char **buf, uint32_t *len) +LI_async_receive(mach_port_t p, kvarray_t **reply) { - _lu_reply_msg_t *r; kern_return_t status; - uint32_t size; - _lu_async_request_t *req; - boolean_t msgh_simple; + _li_async_request_t *r; + kvbuf_t *out; + int flags; - size = sizeof(_lu_reply_msg_t); + flags = MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT) | MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0); - r = (_lu_reply_msg_t *)calloc(1, size); - if (r == NULL) return KERN_RESOURCE_SHORTAGE; + /* use mach_msg_server_once to do the work here */ + status = mach_msg_server_once(DSlibinfoMIGAsyncReply_server, 65536, p, flags); - r->head.msgh_local_port = p; - r->head.msgh_size = size; - status = mach_msg(&(r->head), MACH_RCV_MSG, 0, size, r->head.msgh_local_port, 0, MACH_PORT_NULL); - if (status != KERN_SUCCESS) - { - free(r); - return status; - } + if (status != KERN_SUCCESS) return status; - msgh_simple = !(r->head.msgh_bits & MACH_MSGH_BITS_COMPLEX); + r = _LI_worklist_remove(p); + if (r == NULL) return KERN_FAILURE; - req = _lu_worklist_remove(r->head.msgh_local_port); - if (req == NULL) + out = (kvbuf_t *)calloc(1, sizeof(kvbuf_t)); + if (out == NULL) { - free(r); + if (r->ooreplyCnt > 0) vm_deallocate(mach_task_self(), r->ooreply, r->ooreplyCnt); return KERN_FAILURE; } - if (msgh_simple && ((mig_reply_error_t *) r)->RetCode != KERN_SUCCESS) + if (r->ooreplyCnt > 0) { - _lu_free_request(req); - status = ((mig_reply_error_t *) r)->RetCode; - free(r); - return status; + out->datalen = r->ooreplyCnt; + out->databuf = malloc(r->ooreplyCnt); + if (out->databuf == NULL) + { + free(out); + *reply = NULL; + vm_deallocate(mach_task_self(), r->ooreply, r->ooreplyCnt); + return KERN_FAILURE; + } + + memcpy(out->databuf, (char *)r->ooreply, r->ooreplyCnt); + vm_deallocate(mach_task_self(), r->ooreply, r->ooreplyCnt); } + else if (r->replyCnt > 0) + { + out->datalen = r->replyCnt; + out->databuf = malloc(r->replyCnt); + if (out->databuf == NULL) + { + free(out); + *reply = NULL; + return KERN_FAILURE; + } - *buf = r->reply_data.address; - *len = r->reply_data.size; + memcpy(out->databuf, r->reply, r->replyCnt); + } - free(r); + *reply = kvbuf_decode(out); + if (*reply == NULL) + { + /* DS returned no data */ + free(out->databuf); + free(out); + } + + _LI_free_request(r); - _lu_free_request(req); return KERN_SUCCESS; } static void -_lu_worklist_append(_lu_async_request_t *r) +_LI_worklist_append(_li_async_request_t *r) { - _lu_async_request_t *p; + _li_async_request_t *p; if (r == NULL) return; - pthread_mutex_lock(&_lu_worklist_lock); + pthread_mutex_lock(&_li_worklist_lock); - if (_lu_worklist == NULL) + if (_li_worklist == NULL) { - _lu_worklist = r; - pthread_mutex_unlock(&_lu_worklist_lock); + _li_worklist = r; + pthread_mutex_unlock(&_li_worklist_lock); return; } - for (p = _lu_worklist; p->next != NULL; p = p->next); + for (p = _li_worklist; p->next != NULL; p = p->next); p->next = r; - pthread_mutex_unlock(&_lu_worklist_lock); + pthread_mutex_unlock(&_li_worklist_lock); } void -lu_async_call_cancel(mach_port_t p) +LI_async_call_cancel(mach_port_t p, void **context) { - _lu_async_request_t *req; + _li_async_request_t *req; - req = _lu_worklist_remove(p); - if (req != NULL) _lu_free_request(req); - else if (p != MACH_PORT_NULL) mach_port_destroy(mach_task_self(), p); + req = _LI_worklist_remove(p); + + if (req != NULL) + { + if (context != NULL) *context = req->context; + _LI_free_request(req); + } + else if (p != MACH_PORT_NULL) + { + mach_port_mod_refs(mach_task_self(), p, MACH_PORT_RIGHT_RECEIVE, -1); + } +} + +void +lu_async_call_cancel(mach_port_t p) +{ + LI_async_call_cancel(p, NULL); } -static _lu_async_request_t * -_lu_create_request(uint32_t proc, const char *buf, uint32_t len, void *callback, void *context) +static _li_async_request_t * +_LI_create_request(uint32_t proc, kvbuf_t *query, void *callback, void *context) { - _lu_async_request_t *r; + _li_async_request_t *r; kern_return_t status; + mach_port_t target; - if (_lu_port == MACH_PORT_NULL) return NULL; + if (_ds_running() == 0) return NULL; + if (query == NULL) return NULL; + if (query->datalen > MAX_MIG_INLINE_DATA) return NULL; - r = (_lu_async_request_t *)calloc(1, sizeof(_lu_async_request_t)); + r = (_li_async_request_t *)calloc(1, sizeof(_li_async_request_t)); if (r == NULL) return NULL; status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &(r->reply_port)); if (status != KERN_SUCCESS) { - _lu_free_request(r); + _LI_free_request(r); return NULL; } + target = MACH_PORT_NULL; + + /* Request no-senders notification so we can tell when server dies */ + mach_port_request_notification(mach_task_self(), r->reply_port, MACH_NOTIFY_NO_SENDERS, 1, r->reply_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &target); + r->retry = MAX_LOOKUP_ATTEMPTS; r->context = context; r->callback = callback; r->proc = proc; - r->request_buffer = malloc(len * BYTES_PER_XDR_UNIT); - if (r->request_buffer == NULL) - { - free(r); - return NULL; - } - - memcpy(r->request_buffer, buf, len * BYTES_PER_XDR_UNIT); - r->request_buffer_len = len; + memcpy(r->request, query->databuf, query->datalen); + r->requestCnt = query->datalen; r->next = NULL; @@ -318,9 +377,9 @@ _lu_create_request(uint32_t proc, const char *buf, uint32_t len, void *callback, } kern_return_t -lu_async_start(mach_port_t *p, uint32_t proc, const char *buf, uint32_t len, void *callback, void *context) +LI_async_start(mach_port_t *p, uint32_t proc, kvbuf_t *query, void *callback, void *context) { - _lu_async_request_t *r; + _li_async_request_t *r; kern_return_t status; uint32_t retry; @@ -328,483 +387,167 @@ lu_async_start(mach_port_t *p, uint32_t proc, const char *buf, uint32_t len, voi *p = MACH_PORT_NULL; - if (!_lu_running()) return KERN_FAILURE; + if (_ds_running() == 0) return KERN_FAILURE; + if (_ds_port == MACH_PORT_NULL) return KERN_FAILURE; /* Make a request struct to keep track */ - r = _lu_create_request(proc, buf, len, callback, context); + r = _LI_create_request(proc, query, callback, context); if (r == NULL) return KERN_FAILURE; status = MIG_SERVER_DIED; for (retry = 0; (status == MIG_SERVER_DIED) && (retry < MAX_LOOKUP_ATTEMPTS); retry++) { - /* send to lookupd */ - status = _lu_async_send(r); + status = _LI_async_send(r); } if (status != KERN_SUCCESS) { - _lu_free_request(r); + _LI_free_request(r); return status; } /* Add request to worklist */ - _lu_worklist_append(r); + _LI_worklist_append(r); *p = r->reply_port; + return KERN_SUCCESS; } kern_return_t -lu_async_send(mach_port_t *p, uint32_t proc, const char *buf, uint32_t len) +LI_async_send(mach_port_t *p, uint32_t proc, kvbuf_t *query) { - return lu_async_start(p, proc, buf, len, NULL, NULL); + return LI_async_start(p, proc, query, NULL, NULL); } -int -lu_async_handle_reply(void *msg, char **buf, uint32_t *len, void **callback, void **context) +kern_return_t +LI_async_handle_reply(mach_msg_header_t *msg, kvarray_t **reply, void **callback, void **context) { - _lu_reply_msg_t *r; - _lu_async_request_t *req; + _li_async_request_t *req; + kvbuf_t *out; kern_return_t status; uint32_t retry; - boolean_t msgh_simple; + mig_reply_error_t *bufReply; if (msg == NULL) return -1; - r = (_lu_reply_msg_t *)msg; /* If reply status was an error, resend */ - if (r->head.msgh_id != LU_MESSAGE_REPLY_ID) - { - if (r->head.msgh_id == MACH_NOTIFY_SEND_ONCE) - { - /* if MiG server (lookupd) died */ - req = _lu_worklist_find(r->head.msgh_local_port); - if (req == NULL) return -1; - - status = MIG_SERVER_DIED; - for (retry = 0; (status == MIG_SERVER_DIED) && (retry < MAX_LOOKUP_ATTEMPTS); retry++) - { - /* send to lookupd */ - status = _lu_async_send(req); - } - - if (status != KERN_SUCCESS) return -1; - } - return MIG_REPLY_MISMATCH; - } - - msgh_simple = !(r->head.msgh_bits & MACH_MSGH_BITS_COMPLEX); - - req = _lu_worklist_remove(r->head.msgh_local_port); - if (req == NULL) return -1; - - *callback = req->callback; - *context = req->context; - _lu_free_request(req); - - if (msgh_simple && ((mig_reply_error_t *) r)->RetCode != KERN_SUCCESS) - { - return ((mig_reply_error_t *) r)->RetCode; - } - - *buf = r->reply_data.address; - *len = r->reply_data.size; - - return 0; -} - -ni_proplist * -_lookupd_xdr_dictionary(XDR *inxdr) -{ - int i, nkeys, j, nvals; - char *key, *val; - ni_proplist *l; - - if (!xdr_int(inxdr, &nkeys)) return NULL; - - l = (ni_proplist *)malloc(sizeof(ni_proplist)); - if (l == NULL) return NULL; - - NI_INIT(l); - - l->ni_proplist_len = nkeys; - l->ni_proplist_val = NULL; - if (nkeys > 0) - { - l->ni_proplist_val = (ni_property *)calloc(nkeys, sizeof(ni_property)); - if (l->ni_proplist_val == NULL) - { - free(l); - return NULL; - } - } - - for (i = 0; i < nkeys; i++) + if (msg->msgh_id == MACH_NOTIFY_NO_SENDERS) { - key = NULL; - if (!xdr_string(inxdr, &key, -1)) - { - ni_proplist_free(l); - return NULL; - } - - l->ni_proplist_val[i].nip_name = key; - - if (!xdr_int(inxdr, &nvals)) - { - ni_proplist_free(l); - return NULL; - } - - l->ni_proplist_val[i].nip_val.ni_namelist_len = nvals; - if (nvals > 0) - { - l->ni_proplist_val[i].nip_val.ni_namelist_val = (ni_name *)calloc(nvals, sizeof(ni_name)); - if (l->ni_proplist_val[i].nip_val.ni_namelist_val == NULL) - { - ni_proplist_free(l); - return NULL; - } - } + /* if server died */ + req = _LI_worklist_find(msg->msgh_local_port); + if (req == NULL) return -1; - for (j = 0; j < nvals; j++) + status = MIG_SERVER_DIED; + for (retry = 0; (status == MIG_SERVER_DIED) && (retry < MAX_LOOKUP_ATTEMPTS); retry++) { - val = NULL; - if (!xdr_string(inxdr, &val, -1)) - { - ni_proplist_free(l); - return NULL; - } - - l->ni_proplist_val[i].nip_val.ni_namelist_val[j] = val; + /* send message */ + status = _LI_async_send(req); } - } - - return l; -} - -int -lookupd_query(ni_proplist *l, ni_proplist ***out) -{ - unsigned datalen; - XDR outxdr; - XDR inxdr; - int proc; - char *listbuf, *s; - char databuf[_LU_MAXLUSTRLEN * BYTES_PER_XDR_UNIT]; - int n, i, j, na; - kern_return_t status; - ni_property *p; - - if (l == NULL) return 0; - if (out == NULL) return 0; - - if (_lu_port == MACH_PORT_NULL) return 0; - - status = _lookup_link(_lu_port, "query", &proc); - if (status != KERN_SUCCESS) return 0; - - xdrmem_create(&outxdr, databuf, sizeof(databuf), XDR_ENCODE); - na = l->ni_proplist_len; + if (status != KERN_SUCCESS) return -1; - /* Encode attribute count */ - if (!xdr_int(&outxdr, &na)) - { - xdr_destroy(&outxdr); - return 0; + return MIG_REPLY_MISMATCH; } - for (i = 0; i < l->ni_proplist_len; i++) - { - p = &(l->ni_proplist_val[i]); - s = p->nip_name; - if (!xdr_string(&outxdr, &s, _LU_MAXLUSTRLEN)) - { - xdr_destroy(&outxdr); - return 0; - } - - if (!xdr_int(&outxdr, &(p->nip_val.ni_namelist_len))) - { - xdr_destroy(&outxdr); - return 0; - } + /* need to implement the msg_server_once type code here */ + mach_msg_size_t reply_alloc = round_page(65536 + MAX_TRAILER_SIZE); - for (j = 0; j < p->nip_val.ni_namelist_len; j++) - { - s = p->nip_val.ni_namelist_val[j]; - if (!xdr_string(&outxdr, &s, _LU_MAXLUSTRLEN)) - { - xdr_destroy(&outxdr); - return 0; - } - } - } + status = vm_allocate(mach_task_self(), (vm_address_t *) &bufReply, reply_alloc, VM_MAKE_TAG(VM_MEMORY_MACH_MSG) | TRUE); + if (status != KERN_SUCCESS) return status; - listbuf = NULL; - datalen = 0; + status = DSlibinfoMIGAsyncReply_server(msg, (mach_msg_header_t *)bufReply); - n = xdr_getpos(&outxdr); - status = _lookup_all(_lu_port, proc, (void *)databuf, n, &listbuf, &datalen); - if (status != KERN_SUCCESS) - { - xdr_destroy(&outxdr); - return 0; - } + /* we just destroy the reply, because there isn't one */ + if (bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) mach_msg_destroy(&bufReply->Head); - xdr_destroy(&outxdr); - datalen *= BYTES_PER_XDR_UNIT; - xdrmem_create(&inxdr, listbuf, datalen, XDR_DECODE); + vm_deallocate(mach_task_self(), (vm_address_t) bufReply, reply_alloc); - if (!xdr_int(&inxdr, &n)) - { - xdr_destroy(&inxdr); - return 0; - } + if (status == FALSE) return KERN_FAILURE; - if (n == 0) - { - xdr_destroy(&inxdr); - return 0; - } + req = _LI_worklist_remove(msg->msgh_local_port); + if (req == NULL) return KERN_FAILURE; - *out = (ni_proplist **)malloc(n * sizeof(ni_proplist *)); + *callback = req->callback; + *context = req->context; + + out = (kvbuf_t *)calloc(1, sizeof(kvbuf_t)); if (out == NULL) { - xdr_destroy(&inxdr); - return 0; - } - - for (i = 0; i < n; i++) - { - (*out)[i] = _lookupd_xdr_dictionary(&inxdr); + if (req->ooreplyCnt > 0) vm_deallocate(mach_task_self(), req->ooreply, req->ooreplyCnt); + return KERN_FAILURE; } - xdr_destroy(&inxdr); - - vm_deallocate(mach_task_self(), (vm_address_t)listbuf, datalen); - - return n; -} - -ni_proplist * -lookupd_make_query(char *cat, char *fmt, ...) -{ - va_list ap; - char *arg, *f; - int na, x; - ni_proplist *l; - ni_property *p; - - if (fmt == NULL) return NULL; - if (fmt[0] != 'k') return NULL; - - l = (ni_proplist *)malloc(sizeof(ni_proplist)); - if (l == NULL) return NULL; - - NI_INIT(l); - - na = 0; - x = -1; - - if (cat != NULL) + if (req->ooreplyCnt > 0) { - l->ni_proplist_val = (ni_property *)malloc(sizeof(ni_property)); - if (l->ni_proplist_val == NULL) + out->datalen = req->ooreplyCnt; + out->databuf = malloc(req->ooreplyCnt); + if (out->databuf == NULL) { - free(l); - return NULL; + free(out); + *reply = NULL; + vm_deallocate(mach_task_self(), req->ooreply, req->ooreplyCnt); + return KERN_FAILURE; } - p = &(l->ni_proplist_val[0]); - arg = "_lookup_category"; - p->nip_name = strdup(arg); - if (p->nip_name == NULL) - { - ni_proplist_free(l); - return NULL; - } - - p->nip_val.ni_namelist_len = 1; - p->nip_val.ni_namelist_val = (ni_name *)malloc(sizeof(ni_name)); - if (p->nip_val.ni_namelist_val == NULL) - { - ni_proplist_free(l); - return NULL; - } - - p->nip_val.ni_namelist_val[0] = strdup(cat); - if (p->nip_val.ni_namelist_val[0] == NULL) - { - ni_proplist_free(l); - return NULL; - } - - l->ni_proplist_len++; - x++; + memcpy(out->databuf, (char *)req->ooreply, req->ooreplyCnt); + vm_deallocate(mach_task_self(), req->ooreply, req->ooreplyCnt); } - - va_start(ap, fmt); - for (f = fmt; (*f) != '\0'; f++) + else if (req->replyCnt > 0) { - arg = va_arg(ap, char *); - if (*f == 'k') + out->datalen = req->replyCnt; + out->databuf = malloc(req->replyCnt); + if (out->databuf == NULL) { - l->ni_proplist_val = (ni_property *)reallocf(l->ni_proplist_val, (l->ni_proplist_len + 1) * sizeof(ni_property)); - if (l->ni_proplist_val == NULL) - { - ni_proplist_free(l); - return NULL; - } - - p = &(l->ni_proplist_val[l->ni_proplist_len]); - p->nip_name = strdup(arg); - if (p->nip_name == NULL) - { - ni_proplist_free(l); - return NULL; - } - - p->nip_val.ni_namelist_len = 0; - p->nip_val.ni_namelist_val = NULL; - - l->ni_proplist_len++; - x++; + free(out); + *reply = NULL; + return KERN_FAILURE; } - else - { - p = &(l->ni_proplist_val[x]); - if (p->nip_val.ni_namelist_len == 0) - { - p->nip_val.ni_namelist_val = (ni_name *)malloc(sizeof(ni_name)); - } - else - { - p->nip_val.ni_namelist_val = (ni_name *)reallocf(p->nip_val.ni_namelist_val, (p->nip_val.ni_namelist_len + 1) * sizeof(ni_name)); - } - - if (p->nip_val.ni_namelist_val == NULL) - { - ni_proplist_free(l); - return NULL; - } - - p->nip_val.ni_namelist_val[p->nip_val.ni_namelist_len] = strdup(arg); - if (p->nip_val.ni_namelist_val[p->nip_val.ni_namelist_len] == NULL) - { - ni_proplist_free(l); - return NULL; - } - p->nip_val.ni_namelist_len++; - } + memcpy(out->databuf, req->reply, req->replyCnt); } - va_end(ap); - - return l; -} - -void -ni_property_merge(ni_property *a, ni_property *b) -{ - int i, j, addme; - if (a == NULL) return; - if (b == NULL) return; - - for (j = 0; j < b->nip_val.ni_namelist_len; j++) + *reply = kvbuf_decode(out); + if (*reply == NULL) { - addme = 1; - for (i = 0; i < (a->nip_val.ni_namelist_len) && (addme == 1); i++) - { - if (!strcmp(a->nip_val.ni_namelist_val[i], b->nip_val.ni_namelist_val[j])) addme = 0; - } - - if (addme == 1) - { - a->nip_val.ni_namelist_val = (ni_name *)reallocf(a->nip_val.ni_namelist_val, (a->nip_val.ni_namelist_len + 1) * sizeof(ni_name)); - if (a->nip_val.ni_namelist_val == NULL) return; - - a->nip_val.ni_namelist_val[a->nip_val.ni_namelist_len] = strdup(b->nip_val.ni_namelist_val[j]); - if (a->nip_val.ni_namelist_val[a->nip_val.ni_namelist_len] == NULL) - { - free(a->nip_val.ni_namelist_val); - a->nip_val.ni_namelist_val = NULL; - return; - } - - a->nip_val.ni_namelist_len++; - } + /* DS returned no data */ + free(out->databuf); + free(out); } + + _LI_free_request(req); + + return KERN_SUCCESS; } -void -ni_proplist_merge(ni_proplist *a, ni_proplist *b) +static void +_LI_thread_info_free(void *x) { - ni_index wa, wb; - int addme; + struct li_thread_info *tdata; - if (a == NULL) return; - if (b == NULL) return; - - for (wb = 0; wb < b->ni_proplist_len; wb++) - { - addme = 1; - for (wa = 0; (wa < a->ni_proplist_len) && (addme == 1) ; wa++) - { - if (!strcmp(a->ni_proplist_val[wa].nip_name, b->ni_proplist_val[wb].nip_name)) addme = 0; - } - if (addme == 1) - { - a->ni_proplist_val = (ni_property *)reallocf(a->ni_proplist_val, (a->ni_proplist_len + 1) * sizeof(ni_property)); - if (a->ni_proplist_val == NULL) return; + if (x == NULL) return; - a->ni_proplist_val[a->ni_proplist_len].nip_name = strdup(b->ni_proplist_val[wb].nip_name); - if (a->ni_proplist_val[a->ni_proplist_len].nip_name == NULL) - { - free(a->ni_proplist_val); - a->ni_proplist_val = NULL; - return NULL; - } - - a->ni_proplist_val[a->ni_proplist_len].nip_val.ni_namelist_len = 0; - a->ni_proplist_val[a->ni_proplist_len].nip_val.ni_namelist_val = NULL; - a->ni_proplist_len++; - } - } + tdata = (struct li_thread_info *)x; + LI_ils_free(tdata->li_entry, tdata->li_entry_size); + LI_data_free_kvarray(tdata); - for (wb = 0; wb < b->ni_proplist_len; wb++) - { - for (wa = 0; wa < a->ni_proplist_len; wa++) - { - if (!strcmp(a->ni_proplist_val[wa].nip_name, b->ni_proplist_val[wb].nip_name)) - { - ni_property_merge(&(a->ni_proplist_val[wa]), &(b->ni_proplist_val[wb])); - } - } - } + free(tdata); } static void -_lu_data_free(void *x) +_LI_data_free(void *x) { - struct _lu_data_s *t; + struct _li_data_s *t; int i; if (x == NULL) return; - t = (struct _lu_data_s *)x; + t = (struct _li_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]); - } - + _LI_thread_info_free(t->idata[i]); t->idata[i] = NULL; - t->idata_destructor[i] = NULL; } if (t->ikey != NULL) free(t->ikey); @@ -813,47 +556,44 @@ _lu_data_free(void *x) 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() +_LI_data_init() { - pthread_key_create(&_info_key, _lu_data_free); + pthread_key_create(&_info_key, _LI_data_free); return; } -static struct _lu_data_s * -_lu_data_get() +static struct _li_data_s * +_LI_data_get() { - struct _lu_data_s *libinfo_data; + struct _li_data_s *libinfo_data; /* * Only one thread should create the _info_key */ - pthread_once(&_info_key_initialized, _lu_data_init); + pthread_once(&_info_key_initialized, _LI_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)); + libinfo_data = (struct _li_data_s *)calloc(1, sizeof(struct _li_data_s)); if (libinfo_data == NULL) return NULL; pthread_setspecific(_info_key, libinfo_data); return libinfo_data; } -void * -_lu_data_create_key(unsigned int key, void (*destructor)(void *)) +__private_extern__ void * +LI_data_find_key(uint32_t key) { - struct _lu_data_s *libinfo_data; - unsigned int i, n; + struct _li_data_s *libinfo_data; + uint32_t i; - libinfo_data = _lu_data_get(); + libinfo_data = _LI_data_get(); if (libinfo_data == NULL) return NULL; for (i = 0; i < libinfo_data->icount; i++) @@ -861,305 +601,1861 @@ _lu_data_create_key(unsigned int key, void (*destructor)(void *)) if (libinfo_data->ikey[i] == key) return libinfo_data->idata[i]; } - i = libinfo_data->icount; - n = i + 1; + return NULL; +} + +__private_extern__ void * +LI_data_create_key(uint32_t key, size_t esize) +{ + struct _li_data_s *libinfo_data; + struct li_thread_info *tdata; + uint32_t i, n; + + libinfo_data = _LI_data_get(); + if (libinfo_data == NULL) return NULL; + + 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->ikey = (uint32_t *)malloc(sizeof(uint32_t)); libinfo_data->idata = (void **)malloc(sizeof(void *)); - libinfo_data->idata_destructor = (void (**)(void *))malloc(sizeof(void (*)(void *))); } else { - libinfo_data->ikey = (unsigned int *)reallocf(libinfo_data->ikey, n * sizeof(unsigned int)); + libinfo_data->ikey = (uint32_t *)reallocf(libinfo_data->ikey, n * sizeof(uint32_t)); libinfo_data->idata = (void **)reallocf(libinfo_data->idata, n * sizeof(void *)); - libinfo_data->idata_destructor = (void (**)(void *))reallocf(libinfo_data->idata_destructor, n * sizeof(void (*)(void *))); } - if ((libinfo_data->ikey == NULL) || (libinfo_data->idata == NULL) || (libinfo_data->idata_destructor == NULL)) + if ((libinfo_data->ikey == NULL) || (libinfo_data->idata == NULL)) { if (libinfo_data->ikey != NULL) free(libinfo_data->ikey); + libinfo_data->ikey = NULL; + if (libinfo_data->idata != NULL) free(libinfo_data->idata); - if (libinfo_data->idata_destructor != NULL) free(libinfo_data->idata_destructor); + libinfo_data->idata = NULL; + return NULL; } + tdata = (struct li_thread_info *)calloc(1, sizeof(struct li_thread_info)); + if (tdata == NULL) return NULL; + + tdata->li_entry_size = esize; + libinfo_data->ikey[i] = key; - libinfo_data->idata[i] = NULL; - libinfo_data->idata_destructor[i] = destructor; + libinfo_data->idata[i] = tdata; libinfo_data->icount++; - return NULL; + return tdata; } -static unsigned int -_lu_data_index(unsigned int key, struct _lu_data_s *libinfo_data) +static uint32_t +_LI_data_index(uint32_t key, struct _li_data_s *libinfo_data) { - unsigned int i; + uint32_t i; - if (libinfo_data == NULL) return (unsigned int)-1; + if (libinfo_data == NULL) return (uint32_t)-1; for (i = 0; i < libinfo_data->icount; i++) { if (libinfo_data->ikey[i] == key) return i; } - return (unsigned int)-1; + return (uint32_t)-1; } void -_lu_data_set_key(unsigned int key, void *data) +_LI_data_set_key(uint32_t key, void *data) { - struct _lu_data_s *libinfo_data; - unsigned int i; + struct _li_data_s *libinfo_data; + uint32_t i; - libinfo_data = _lu_data_get(); + libinfo_data = _LI_data_get(); if (libinfo_data == NULL) return; - i = _lu_data_index(key, libinfo_data); - if (i == (unsigned int)-1) return; + i = _LI_data_index(key, libinfo_data); + if (i == (uint32_t)-1) return; libinfo_data->idata[i] = data; } void * -_lu_data_get_key(unsigned int key) +_LI_data_get_key(uint32_t key) { - struct _lu_data_s *libinfo_data; - unsigned int i; + struct _li_data_s *libinfo_data; + uint32_t i; - libinfo_data = _lu_data_get(); + libinfo_data = _LI_data_get(); if (libinfo_data == NULL) return NULL; - i = _lu_data_index(key, libinfo_data); - if (i == (unsigned int)-1) return NULL; + i = _LI_data_index(key, libinfo_data); + if (i == (uint32_t)-1) return NULL; return libinfo_data->idata[i]; } -void -_lu_data_free_vm_xdr(struct lu_thread_info *tdata) +__private_extern__ void +LI_data_free_kvarray(struct li_thread_info *tdata) { if (tdata == NULL) return; + if (tdata->li_vm == 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; - } + kvarray_free((kvarray_t *)tdata->li_vm); + tdata->li_vm = NULL; } -int -_lu_xdr_attribute(XDR *xdr, char **key, char ***val, unsigned int *count) +__private_extern__ void +LI_data_recycle(struct li_thread_info *tdata, void *entry, size_t entrysize) { - unsigned int i, j, len; - char **x, *s; + if (tdata == NULL) return; - if (xdr == NULL) return -1; - if (key == NULL) return -1; - if (val == NULL) return -1; - if (count == NULL) return -1; + LI_ils_free(tdata->li_entry, entrysize); + tdata->li_entry = entry; +} - *key = NULL; - *val = NULL; - *count = 0; +#define KVBUF_CHUNK 256 - if (!xdr_string(xdr, key, -1)) return -1; +/* + * kvbuf_t is a list of key/value dictionaries. + * + * First 4 bytes are the number of dictionaries. + * For each dictionary, first 4 bytes is the key / value list count. + * For each value list, first 4 bytes is the list length. + * Keys and values are a 4-byte length followed by a nul-terminated string + * + * When the databuf needs to grow, we add memory in KVBUF_CHUNK size + * increments to reduce malloc / realloc activity. + * The _size variable stores the actual allocated size. + * The datalen variable stores the used data size. + * + * The _dict variable holds an offset from the start of the buffer + * to the "current" dictionary. kvbuf_reset() resets this, + * and kvbuf_next_dict() bumps the offset so that databuf + _dict + * points to the next dictionary. + * + * The _key variable holds an offset from the start of the buffer + * to the "current" key. kvbuf_reset() resets this, and + * kvbuf_next_key() bumps the offset so that databuf + _key + * points to the next key. + * + * The _val variable holds an offset from the start of the buffer + * to the "current" value. kvbuf_reset() resets this, and + * kvbuf_next_val() bumps the offset so that databuf + _val + * points to the next value. + * + * The cache_entry_list_to_kvbuf() routine contains the only + * code that builds an array. + * + */ - if (!xdr_int(xdr, &len)) - { - free(*key); - *key = NULL; - return -1; - } +/* + * kvbuf_query is a simple utility for constructing a + * kvbuf with a single dictionary. The format string may + * contain the chars "k", "s", "i", and "u". "k" denotes a key + * (keys are always strings), "s" denotes a string value, + * "i" denotes a 32 bit signed int, and "u" denotes an unsigned. + */ +__private_extern__ kvbuf_t * +kvbuf_query(char *fmt, ...) +{ + va_list ap; + char *arg, *f, str[32]; + int32_t iarg; + uint32_t uarg; + kvbuf_t *kv; - if (len == 0) return 0; - *count = len; + if (fmt == NULL) return NULL; - x = (char **)calloc(len + 1, sizeof(char *)); - if (x == NULL) return -1; + kv = kvbuf_new(); + if (kv == NULL) return NULL; - *val = x; + kvbuf_add_dict(kv); - for (i = 0; i < len; i++) + va_start(ap, fmt); + for (f = fmt; (*f) != '\0'; f++) { - s = NULL; - if (!xdr_string(xdr, &s, -1)) + if (*f == 'k') + { + arg = va_arg(ap, char *); + kvbuf_add_key(kv, arg); + } + else if (*f == 's') + { + arg = va_arg(ap, char *); + kvbuf_add_val(kv, arg); + } + else if (*f == 'i') { - for (j = 0; j < i; j++) free(x[j]); - free(x); - *val = NULL; - free(*key); - *key = NULL; - *count = 0; - return -1; + iarg = va_arg(ap, int32_t); + snprintf(str, sizeof(str), "%d", iarg); + kvbuf_add_val(kv, str); + } + else if (*f == 'u') + { + uarg = va_arg(ap,uint32_t); + snprintf(str, sizeof(str), "%u", uarg); + kvbuf_add_val(kv, str); } - x[i] = s; } + va_end(ap); - x[len] = NULL; - - return 0; + return kv; } -kern_return_t -_lookup_link(mach_port_t server, lookup_name name, int *procno) +__private_extern__ kvbuf_t * +kvbuf_query_key_val(const char *key, const char *val) { - kern_return_t status; - security_token_t token; - unsigned int n; + kvbuf_t *kv; + uint32_t x, kl, vl, vc; + char *p; - token.val[0] = -1; - token.val[1] = -1; + if (key == NULL) return NULL; - status = MIG_SERVER_DIED; - for (n = 0; (status == MIG_SERVER_DIED) && (n < MAX_LOOKUP_ATTEMPTS); n++) + kl = strlen(key) + 1; + + vl = 0; + vc = 0; + + if (val != NULL) { - status = _lookup_link_secure(server, name, procno, &token); + vl = strlen(val) + 1; + vc = 1; } - if (status != KERN_SUCCESS) + kv = (kvbuf_t *)calloc(1, sizeof(kvbuf_t)); + if (kv == NULL) return NULL; + + kv->_size = (5 * sizeof(uint32_t)) + kl + vl; + kv->datalen = kv->_size; + + kv->databuf = calloc(1, kv->_size); + if (kv->databuf == NULL) { -#ifdef DEBUG - syslog(LOG_DEBUG, "pid %u _lookup_link %s status %u", getpid(), name, status); -#endif - return status; + free(kv); + return NULL; } - if (token.val[0] != 0) + p = kv->databuf; + + /* 1 dict */ + x = htonl(1); + memcpy(p, &x, sizeof(uint32_t)); + p += sizeof(uint32_t); + + /* 1 key */ + memcpy(p, &x, sizeof(uint32_t)); + p += sizeof(uint32_t); + + /* key length */ + x = htonl(kl); + memcpy(p, &x, sizeof(uint32_t)); + p += sizeof(uint32_t); + + /* key */ + memcpy(p, key, kl); + p += kl; + + /* number of values */ + x = htonl(vc); + memcpy(p, &x, sizeof(uint32_t)); + p += sizeof(uint32_t); + + if (vc > 0) { -#ifdef DEBUG - syslog(LOG_DEBUG, "pid %u _lookup_link %s auth failure uid=%d", getpid(), name, token.val[0]); -#endif - return KERN_FAILURE; + /* value length */ + x = htonl(vl); + memcpy(p, &x, sizeof(uint32_t)); + p += sizeof(uint32_t); + + /* value */ + memcpy(p, val, vl); } -#ifdef DEBUG - syslog(LOG_DEBUG, "pid %u _lookup_link %s = %d", getpid(), name, *procno); -#endif - return status; + return kv; } -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) +__private_extern__ kvbuf_t * +kvbuf_query_key_int(const char *key, int32_t i) { - kern_return_t status; - security_token_t token; - unsigned int n; + char str[32]; - token.val[0] = -1; - token.val[1] = -1; + snprintf(str, sizeof(str), "%d", i); + return kvbuf_query_key_val(key, str); +} - status = MIG_SERVER_DIED; - for (n = 0; (status == MIG_SERVER_DIED) && (n < MAX_LOOKUP_ATTEMPTS); n++) +__private_extern__ kvbuf_t * +kvbuf_query_key_uint(const char *key, uint32_t u) +{ + char str[32]; + + snprintf(str, sizeof(str), "%u", u); + return kvbuf_query_key_val(key, str); +} + +kvbuf_t * +kvbuf_new(void) +{ + kvbuf_t *kv; + + kv = (kvbuf_t *)calloc(1, sizeof(kvbuf_t)); + if (kv == NULL) return NULL; + + kv->_size = KVBUF_START_SIZE; + kv->databuf = calloc(1, kv->_size); + if (kv->databuf == NULL) { - status = _lookup_one_secure(server, proc, indata, indataCnt, outdata, outdataCnt, &token); + free(kv); + return NULL; } - if (status != KERN_SUCCESS) + kv->datalen = sizeof(uint32_t); + kv->_dict = kv->datalen; + + return kv; +} + +kvbuf_t * +kvbuf_init(char *buffer, uint32_t length) +{ + kvbuf_t *kv; + + kv = (kvbuf_t *)calloc(1, sizeof(kvbuf_t)); + if (kv == NULL) return NULL; + + kv->_size = length; + kv->datalen = length; + kv->databuf = calloc(1, length); + if (kv->databuf == NULL) { -#ifdef DEBUG - syslog(LOG_DEBUG, "pid %u _lookup_one %d status %u", getpid(), proc, status); -#endif - return status; + free(kv); + kv = NULL; } - - if (token.val[0] != 0) + else { -#ifdef DEBUG - syslog(LOG_DEBUG, "pid %u _lookup_one %d auth failure uid=%d", getpid(), proc, token.val[0]); -#endif - return KERN_FAILURE; + memcpy(kv->databuf, buffer, length); } -#ifdef DEBUG - syslog(LOG_DEBUG, "pid %u _lookup_one %d", getpid(), proc); -#endif - return status; + return kv; } -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) +static void +kvbuf_grow(kvbuf_t *kv, uint32_t delta) { - kern_return_t status; - security_token_t token; - unsigned int n; + uint32_t newlen, n; + char *p; - token.val[0] = -1; - token.val[1] = -1; + if (kv == NULL) return; + if (delta == 0) return; - 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 (kv->databuf == NULL) delta += sizeof(uint32_t); - if (status != KERN_SUCCESS) + n = (delta + KVBUF_CHUNK - 1) / KVBUF_CHUNK; + newlen = kv->datalen + (n * KVBUF_CHUNK); + + if (newlen <= kv->_size) return; + + kv->_size = newlen; + + if (kv->databuf == NULL) { -#ifdef DEBUG - syslog(LOG_DEBUG, "pid %u _lookup_all %d status %u", getpid(), proc, status); -#endif - return status; - } + kv->databuf = calloc(1, kv->_size); + if (kv->databuf == NULL) + { + memset(kv, 0, sizeof(kvbuf_t)); + return; + } - if (token.val[0] != 0) + kv->datalen = sizeof(uint32_t); + kv->_dict = sizeof(uint32_t); + } + else { -#ifdef DEBUG - syslog(LOG_DEBUG, "pid %u _lookup_all %d auth failure uid=%d", getpid(), proc, token.val[0]); -#endif - return KERN_FAILURE; + kv->databuf = reallocf(kv->databuf, kv->_size); + if (kv->databuf == NULL) + { + memset(kv, 0, sizeof(kvbuf_t)); + return; + } + + p = kv->databuf + kv->datalen; + memset(p, 0, kv->_size - kv->datalen); } +} -#ifdef DEBUG - syslog(LOG_DEBUG, "pid %u _lookup_all %d", getpid(), proc); -#endif - return status; +void +kvbuf_add_dict(kvbuf_t *kv) +{ + char *p; + uint32_t x, dict_count; + + if (kv == NULL) return; + + /* Add a key count */ + kvbuf_grow(kv, sizeof(uint32_t)); + if (kv->databuf == NULL) return; + + kv->_dict = kv->datalen; + kv->datalen += sizeof(uint32_t); + + kv->_key = kv->datalen; + kv->_vlist = 0; + kv->_val = 0; + + /* increment and rewrite the dict count */ + p = kv->databuf; + + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + dict_count = ntohl(x); + + dict_count++; + x = htonl(dict_count); + memcpy(p, &x, sizeof(uint32_t)); } -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) +void +kvbuf_add_key(kvbuf_t *kv, const char *key) { - kern_return_t status; - security_token_t token; - unsigned int n; + uint32_t kl, x, key_count, delta; + char *p; - token.val[0] = -1; - token.val[1] = -1; + if (kv == NULL) return; + if (key == NULL) return; - status = MIG_SERVER_DIED; - for (n = 0; (status == MIG_SERVER_DIED) && (n < MAX_LOOKUP_ATTEMPTS); n++) + kl = strlen(key) + 1; + + /* Grow to hold key len, key, and value list count. */ + delta = (2 * sizeof(uint32_t)) + kl; + kvbuf_grow(kv, delta); + + if (kv->databuf == NULL) return; + + /* increment and rewrite the key count for the current dictionary */ + p = kv->databuf + kv->_dict; + + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + key_count = ntohl(x); + + if (key_count == 0) kv->_key = kv->_dict + sizeof(uint32_t); + else kv->_key = kv->datalen; + + key_count++; + x = htonl(key_count); + memcpy(p, &x, sizeof(uint32_t)); + + /* append key to data buffer */ + p = kv->databuf + kv->datalen; + + x = htonl(kl); + memcpy(p, &x, sizeof(uint32_t)); + p += sizeof(uint32_t); + memcpy(p, key, kl); + p += kl; + + kv->_vlist = kv->datalen + sizeof(uint32_t) + kl; + + x = 0; + memcpy(p, &x, sizeof(uint32_t)); + + kv->datalen += delta; + kv->_val = kv->datalen; +} + +void +kvbuf_add_val_len(kvbuf_t *kv, const char *val, uint32_t len) +{ + uint32_t x, val_count, delta; + char *p; + + if (kv == NULL) return; + if (val == NULL) return; + if (len == 0) return; + + /* Grow to hold val len and value. */ + delta = sizeof(uint32_t) + len; + kvbuf_grow(kv, delta); + + if (kv->databuf == NULL) return; + + /* increment and rewrite the value count for the value_list dictionary */ + p = kv->databuf + kv->_vlist; + + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + val_count = ntohl(x); + val_count++; + x = htonl(val_count); + memcpy(p, &x, sizeof(uint32_t)); + + /* append val to data buffer */ + p = kv->databuf + kv->_val; + + x = htonl(len); + memcpy(p, &x, sizeof(uint32_t)); + p += sizeof(uint32_t); + memcpy(p, val, len); + p += len; + + kv->datalen += delta; + kv->_val = kv->datalen; +} + +/* + * WARNING! Kludge Alert! + * + * This call just looks for the buffer length encoded into a serialized kvbuf_t, + * which preceeds a pointer to a key or value. Obviously, calling it with anything + * other than a pointer value which is embedded in a kvbuf_t is asking for trouble. + */ +uint32_t +kvbuf_get_len(const char *p) +{ + uint32_t x; + + x = 0; + memcpy(&x, p - sizeof(uint32_t), sizeof(uint32_t)); + return ntohl(x); +} + +void +kvbuf_add_val(kvbuf_t *kv, const char *val) +{ + if (kv == NULL) return; + if (val == NULL) return; + + kvbuf_add_val_len(kv, val, strlen(val) + 1); +} + +void +kvbuf_free(kvbuf_t *kv) +{ + if (kv == NULL) return; + if (kv->databuf != NULL) free(kv->databuf); + memset(kv, 0, sizeof(kvbuf_t)); + free(kv); +} + +/* appends a kvbuf to an existing kvbuf */ +void +kvbuf_append_kvbuf(kvbuf_t *kv, const kvbuf_t *kv2) +{ + uint32_t curr_count, new_count, temp; + + if (kv == NULL) return; + if (kv2 == NULL) return; + + curr_count = 0; + new_count = 0; + + memcpy(&temp, kv->databuf, sizeof(uint32_t)); + curr_count = ntohl(temp); + + memcpy(&temp, kv2->databuf, sizeof(uint32_t)); + new_count = ntohl(temp); + + /* nothing to do */ + if (new_count == 0) return; + + /* add the dictionary count to the current dictionary counts */ + curr_count += new_count; + + temp = htonl(curr_count); + memcpy(kv->databuf, &temp, sizeof(uint32_t)); + + /* grow the current buffer so we can append the new buffer */ + temp = kv2->datalen - sizeof(uint32_t); + + kvbuf_grow(kv, temp); + + memcpy(kv->databuf + kv->datalen, kv2->databuf + sizeof(uint32_t), temp); + kv->datalen += temp; +} + +/* returns number of dictionaries */ +uint32_t +kvbuf_reset(kvbuf_t *kv) +{ + uint32_t x; + + if (kv == NULL) return 0; + if (kv->databuf == NULL) return 0; + + kv->_dict = 0; + kv->_key = 0; + kv->_vlist = 0; + kv->_val = 0; + + if (kv->datalen < sizeof(uint32_t)) return 0; + + x = 0; + memcpy(&x, kv->databuf, sizeof(uint32_t)); + return ntohl(x); +} + +/* advance to next dictionary, returns key count */ +uint32_t +kvbuf_next_dict(kvbuf_t *kv) +{ + uint32_t x, k, v, kcount, vcount, kl, vl; + char *p; + + if (kv == NULL) return 0; + if (kv->databuf == NULL) return 0; + + kv->_key = 0; + kv->_vlist = 0; + kv->_val = 0; + + if (kv->_dict == 0) { - status = _lookup_ooall_secure(server, proc, indata, indataCnt, outdata, outdataCnt, &token); + /* first dict */ + if (kv->datalen < sizeof(uint32_t)) return 0; + kv->_dict = sizeof(uint32_t); + + if (kv->datalen < (kv->_dict + sizeof(uint32_t))) return 0; + + p = kv->databuf + kv->_dict; + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + kcount = ntohl(x); + + return kcount; } - if (status != KERN_SUCCESS) + p = kv->databuf + kv->_dict; + + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + p += sizeof(uint32_t); + kv->_dict += sizeof(uint32_t); + kcount = ntohl(x); + + for (k = 0; k < kcount; k++) { -#ifdef DEBUG - syslog(LOG_DEBUG, "pid %u _lookup_ooall %d status %u", getpid(), proc, status); -#endif - return status; + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + p += sizeof(uint32_t); + kv->_dict += sizeof(uint32_t); + kl = ntohl(x); + p += kl; + kv->_dict += kl; + + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + p += sizeof(uint32_t); + kv->_dict += sizeof(uint32_t); + vcount = ntohl(x); + + for (v = 0; v < vcount; v++) + { + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + p += sizeof(uint32_t); + kv->_dict += sizeof(uint32_t); + vl = ntohl(x); + p += vl; + kv->_dict += vl; + } } - if (token.val[0] != 0) + if (kv->datalen < (kv->_dict + sizeof(uint32_t))) return 0; + + p = kv->databuf + kv->_dict; + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + kcount = ntohl(x); + + return kcount; +} + +/* advance to next key, returns key and sets val_count */ +char * +kvbuf_next_key(kvbuf_t *kv, uint32_t *val_count) +{ + uint32_t x, kl, v, vl, vc; + char *p, *out; + + if (kv == NULL) return NULL; + if (val_count == NULL) return NULL; + + *val_count = 0; + + if (kv->databuf == NULL) return NULL; + if (kv->_dict == 0) return NULL; + + kv->_vlist = 0; + kv->_val = 0; + + if (kv->_key == 0) { -#ifdef DEBUG - syslog(LOG_DEBUG, "pid %u _lookup_ooall %d auth failure uid=%d", getpid(), proc, token.val[0]); -#endif - return KERN_FAILURE; + /* first key */ + if (kv->datalen < (kv->_dict + sizeof(uint32_t))) return NULL; + kv->_key = kv->_dict + sizeof(uint32_t); } + else + { + p = kv->databuf + kv->_key; + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + kl = ntohl(x); + + if (kv->datalen < (kv->_key + sizeof(uint32_t) + kl)) return NULL; + + p += (sizeof(uint32_t) + kl); + kv->_key += (sizeof(uint32_t) + kl); + + /* skip over values */ + if (kv->datalen < (kv->_key + sizeof(uint32_t))) return NULL; + + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + vc = ntohl(x); + + p += sizeof(uint32_t); + kv->_key += sizeof(uint32_t); + + for (v = 0; v < vc; v++) + { + if (kv->datalen < (kv->_key + sizeof(uint32_t))) return NULL; + + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + vl = ntohl(x); + + if (kv->datalen < (kv->_key + kl)) return NULL; + + p += (sizeof(uint32_t) + vl); + kv->_key += (sizeof(uint32_t) + vl); + } + } + + if (kv->datalen < (kv->_key + sizeof(uint32_t))) return NULL; + + p = kv->databuf + kv->_key; + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + kl = ntohl(x); + + p += sizeof(uint32_t); + out = p; + + kv->_vlist = kv->_key + sizeof(uint32_t) + kl; + if (kv->datalen < (kv->_vlist + sizeof(uint32_t))) + { + kv->_vlist = 0; + return NULL; + } + + p = kv->databuf + kv->_vlist; + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + *val_count = ntohl(x); + + return out; +} + +char * +kvbuf_next_val(kvbuf_t *kv) +{ + return kvbuf_next_val_len(kv, NULL); +} + +char * +kvbuf_next_val_len(kvbuf_t *kv, uint32_t *len) +{ + uint32_t x = 0; + uint32_t vltemp = 0; + char *p; + + if (kv == NULL) return NULL; + if (kv->databuf == NULL) return NULL; + if (kv->_vlist == 0) return NULL; + + if (kv->_val == 0) + { + /* first val */ + if (kv->datalen < (kv->_vlist + sizeof(uint32_t))) return NULL; + kv->_val = kv->_vlist + sizeof(uint32_t); + + p = kv->databuf + kv->_val; + + memcpy(&x, p, sizeof(uint32_t)); + vltemp = ntohl(x); + } + else + { + p = kv->databuf + kv->_val; + + memcpy(&x, p, sizeof(uint32_t)); + vltemp = ntohl(x); + + if (kv->datalen < (kv->_val + sizeof(uint32_t) + vltemp)) return NULL; + + p += (sizeof(uint32_t) + vltemp); + kv->_val += (sizeof(uint32_t) + vltemp); + } + + if (kv->datalen < (kv->_val + sizeof(uint32_t))) return NULL; + + if (len != NULL) (*len) = vltemp; + p = kv->databuf + kv->_val + sizeof(uint32_t); + return p; +} + +/* + * Builds a kvarray_t / kvdict_t structure on top of a kvbuf_t. + * It allocates the appropriate number of kvdict_t structures + * for the array, sets all the counters, and fills in pointers + * for keys and valuse. The pointers are NOT to newly allocated + * strings: they just point into the kvbuf data buffer. + * + * To dispose of the kvarray_t and all of the associated + * memory AND to free the original kvbuf, clients only + * need to call kvarray_free(). + */ +kvarray_t * +kvbuf_decode(kvbuf_t *kv) +{ + kvarray_t *a; + uint32_t x, d, k, v; + char *p; + + if (kv == NULL) return NULL; + if (kv->databuf == NULL) return NULL; + + if (kv->datalen < sizeof(uint32_t)) return NULL; + + p = kv->databuf; + kv->_size = kv->datalen; + + /* array count */ + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + p += sizeof(uint32_t); + kv->_size -= sizeof(uint32_t); + x = ntohl(x); + + if (x == 0) return NULL; + + a = (kvarray_t *)calloc(1, sizeof(kvarray_t)); + if (a == NULL) return NULL; + + a->count = x; + a->dict = (kvdict_t *)calloc(a->count, sizeof(kvdict_t)); + if (a->dict == NULL) + { + free(a); + return NULL; + } + + for (d = 0; d < a->count; d++) + { + if (kv->_size < sizeof(uint32_t)) + { + kvarray_free(a); + return NULL; + } + + /* key count */ + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + p += sizeof(uint32_t); + kv->_size -= sizeof(uint32_t); + a->dict[d].kcount = ntohl(x); + + if (a->dict[d].kcount > 0) + { + a->dict[d].key = (const char **)calloc(a->dict[d].kcount, sizeof(const char *)); + if (a->dict[d].key == NULL) + { + kvarray_free(a); + return NULL; + } + + a->dict[d].vcount = (uint32_t *)calloc(a->dict[d].kcount, sizeof(uint32_t)); + if (a->dict[d].vcount == NULL) + { + kvarray_free(a); + return NULL; + } + + a->dict[d].val = (const char ***)calloc(a->dict[d].kcount, sizeof(char **)); + if (a->dict[d].val == NULL) + { + kvarray_free(a); + return NULL; + } + } + + for (k = 0; k < a->dict[d].kcount; k++) + { + /* get key */ + if (kv->_size < sizeof(uint32_t)) + { + kvarray_free(a); + return NULL; + } + + /* key length */ + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + p += sizeof(uint32_t); + kv->_size -= sizeof(uint32_t); + x = ntohl(x); + + if (kv->_size < x) + { + kvarray_free(a); + return NULL; + } + + /* key data */ + a->dict[d].key[k] = p; + + p += x; + kv->_size -= x; + + if (kv->_size < sizeof(uint32_t)) + { + kvarray_free(a); + return NULL; + } + + /* val count */ + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + p += sizeof(uint32_t); + kv->_size -= sizeof(uint32_t); + a->dict[d].vcount[k] = ntohl(x); + + if (a->dict[d].vcount[k] > 0) + { + /* N.B. we add a NULL pointer at the end of the list */ + a->dict[d].val[k] = (const char **)calloc(a->dict[d].vcount[k] + 1, sizeof(const char *)); + if (a->dict[d].val[k] == NULL) + { + kvarray_free(a); + return NULL; + } + } + + for (v = 0; v < a->dict[d].vcount[k]; v++) + { + /* get val */ + if (kv->_size < sizeof(uint32_t)) + { + kvarray_free(a); + return NULL; + } + + /* val length */ + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + p += sizeof(uint32_t); + kv->_size -= sizeof(uint32_t); + x = ntohl(x); + + if (kv->_size < x) + { + kvarray_free(a); + return NULL; + } + + /* val data */ + a->dict[d].val[k][v] = p; + + p += x; + kv->_size -= x; + } + } + } + + a->kv = kv; + return a; +} + +void +kvarray_free(kvarray_t *a) +{ + uint32_t d, k; + + if (a == NULL) return; + + for (d = 0; d < a->count; d++) + { + for (k = 0; k < a->dict[d].kcount; k++) + { + if (a->dict[d].val == NULL) continue; + if (a->dict[d].val[k] != NULL) free(a->dict[d].val[k]); + } + + if (a->dict[d].key != NULL) free(a->dict[d].key); + if (a->dict[d].vcount != NULL) free(a->dict[d].vcount); + if (a->dict[d].val != NULL) free(a->dict[d].val); + } + + a->count = 0; + + if (a->dict != NULL) free(a->dict); + a->dict = NULL; + + if (a->kv != NULL) kvbuf_free(a->kv); + a->kv = NULL; + + free(a); +} + +kern_return_t +LI_DSLookupGetProcedureNumber(const char *name, int32_t *procno) +{ + kern_return_t status; + security_token_t token; + uint32_t n, len; + + if (name == NULL) return KERN_FAILURE; + + len = strlen(name) + 1; + if (len == 1) return KERN_FAILURE; + + token.val[0] = -1; + token.val[1] = -1; + + if (_ds_running() == 0) return KERN_FAILURE; + if (_ds_port == MACH_PORT_NULL) return KERN_FAILURE; + + status = MIG_SERVER_DIED; + for (n = 0; (_ds_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (n < MAX_LOOKUP_ATTEMPTS); n++) + { + status = libinfoDSmig_GetProcedureNumber(_ds_port, (char *)name, procno, &token); + + if (status == MACH_SEND_INVALID_DEST) + { + mach_port_mod_refs(mach_task_self(), _ds_port, MACH_PORT_RIGHT_SEND, -1); + status = bootstrap_look_up(bootstrap_port, kDSStdMachDSLookupPortName, &_ds_port); + if ((status != BOOTSTRAP_SUCCESS) && (status != BOOTSTRAP_UNKNOWN_SERVICE)) _ds_port = MACH_PORT_NULL; + status = MIG_SERVER_DIED; + } + } + + if (status != KERN_SUCCESS) + { +#ifdef DEBUG + asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupGetProcedureNumber %s status %u", name, status); +#endif + return status; + } + + if (token.val[0] != 0) + { +#ifdef DEBUG + asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupGetProcedureNumber %s auth failure uid=%d", name, token.val[0]); +#endif + return KERN_FAILURE; + } + +#ifdef DEBUG + asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupGetProcedureNumber %s = %d", name, *procno); +#endif + return status; +} + +__private_extern__ kern_return_t +LI_DSLookupQuery(int32_t procno, kvbuf_t *request, kvarray_t **reply) +{ + kern_return_t status; + security_token_t token; + uint32_t n; + mach_msg_type_number_t illen, oolen; + char ilbuf[MAX_MIG_INLINE_DATA]; + vm_offset_t oobuf; + kvbuf_t *out; + + if (reply == NULL) return KERN_FAILURE; + if ((request != NULL) && ((request->databuf == NULL) || (request->datalen == 0))) return KERN_FAILURE; + + token.val[0] = -1; + token.val[1] = -1; + *reply = NULL; + + if (_ds_running() == 0) return KERN_FAILURE; + if (_ds_port == MACH_PORT_NULL) return KERN_FAILURE; + + status = MIG_SERVER_DIED; + for (n = 0; (_ds_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (n < MAX_LOOKUP_ATTEMPTS); n++) + { + illen = 0; + oolen = 0; + oobuf = 0; + + if (request != NULL) + { + status = libinfoDSmig_Query(_ds_port, procno, request->databuf, request->datalen, ilbuf, &illen, &oobuf, &oolen, &token); + } + else + { + status = libinfoDSmig_Query(_ds_port, procno, "", 0, ilbuf, &illen, &oobuf, &oolen, &token); + } + + if (status == MACH_SEND_INVALID_DEST) + { + mach_port_mod_refs(mach_task_self(), _ds_port, MACH_PORT_RIGHT_SEND, -1); + status = bootstrap_look_up(bootstrap_port, kDSStdMachDSLookupPortName, &_ds_port); + if ((status != BOOTSTRAP_SUCCESS) && (status != BOOTSTRAP_UNKNOWN_SERVICE)) _ds_port = MACH_PORT_NULL; + status = MIG_SERVER_DIED; + } + } + + if (status != KERN_SUCCESS) + { +#ifdef DEBUG + asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupQuery %d status %u", procno, status); +#endif + return status; + } + + if (token.val[0] != 0) + { #ifdef DEBUG - syslog(LOG_DEBUG, "pid %u _lookup_ooall %d", getpid(), proc); + asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupQuery %d auth failure uid=%d", procno, token.val[0]); +#endif + if (oolen > 0) vm_deallocate(mach_task_self(), (vm_address_t)oobuf, oolen); + return KERN_FAILURE; + } + + out = (kvbuf_t *)calloc(1, sizeof(kvbuf_t)); + if (out == NULL) + { + if (oolen > 0) vm_deallocate(mach_task_self(), (vm_address_t)oobuf, oolen); + return KERN_FAILURE; + } + + if (oolen > 0) + { + out->datalen = oolen; + out->databuf = malloc(oolen); + if (out->databuf == NULL) + { + free(out); + *reply = NULL; + vm_deallocate(mach_task_self(), (vm_address_t)oobuf, oolen); + return KERN_FAILURE; + } + + memcpy(out->databuf, (char *)oobuf, oolen); + vm_deallocate(mach_task_self(), (vm_address_t)oobuf, oolen); + } + else if (illen > 0) + { + out->datalen = illen; + out->databuf = malloc(illen); + if (out->databuf == NULL) + { + free(out); + *reply = NULL; + return KERN_FAILURE; + } + + memcpy(out->databuf, ilbuf, illen); + } + + *reply = kvbuf_decode(out); + if (*reply == NULL) + { + /* DS returned no data */ + free(out->databuf); + free(out); + } + +#ifdef DEBUG + asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupQuery %d status OK", procno); #endif return status; } + +/* + * Get an entry from a kvarray. + * Calls the system information daemon if the list doesn't exist (first call), + * or extracts the next entry if the list has been fetched. + */ +__private_extern__ void * +LI_getent(const char *procname, int *procnum, void *(*extract)(kvarray_t *), int tkey, size_t esize) +{ + void *entry; + struct li_thread_info *tdata; + kvarray_t *reply; + kern_return_t status; + + tdata = LI_data_create_key(tkey, esize); + if (tdata == NULL) return NULL; + + if (tdata->li_vm == NULL) + { + if (*procnum < 0) + { + status = LI_DSLookupGetProcedureNumber(procname, procnum); + if (status != KERN_SUCCESS) + { + LI_data_free_kvarray(tdata); + tdata->li_vm = NULL; + return NULL; + } + } + + reply = NULL; + status = LI_DSLookupQuery(*procnum, NULL, &reply); + + if (status != KERN_SUCCESS) + { + LI_data_free_kvarray(tdata); + tdata->li_vm = NULL; + return NULL; + } + + tdata->li_vm = (char *)reply; + } + + entry = extract((kvarray_t *)(tdata->li_vm)); + if (entry == NULL) + { + LI_data_free_kvarray(tdata); + tdata->li_vm = NULL; + return NULL; + } + + return entry; +} + +__private_extern__ void * +LI_getone(const char *procname, int *procnum, void *(*extract)(kvarray_t *), const char *key, const char *val) +{ + void *entry; + kvbuf_t *request; + kvarray_t *reply; + kern_return_t status; + + if (*procnum < 0) + { + status = LI_DSLookupGetProcedureNumber(procname, procnum); + if (status != KERN_SUCCESS) return NULL; + } + + request = kvbuf_query_key_val(key, val); + if (request == NULL) return NULL; + + reply = NULL; + status = LI_DSLookupQuery(*procnum, request, &reply); + kvbuf_free(request); + + if (status != KERN_SUCCESS) return NULL; + + entry = extract(reply); + kvarray_free(reply); + + return entry; +} + +__private_extern__ +int LI_L1_cache_check(int tkey) +{ + int check, x; + const char *notify_key; + + /* check if L1 cache is disabled */ + if (gL1CacheEnabled == 0) return LI_L1_CACHE_DISABLED; + + /* Initialize on first call */ + if (_L1_notify_token[0] == -1) + { + pthread_mutex_lock(&_notify_lock); + if (_L1_notify_token[0] == -1) notify_register_check(L1_CACHE_NOTIFICATION_KEY_GLOBAL, &(_L1_notify_token[0])); + pthread_mutex_unlock(&_notify_lock); + } + + if (_L1_notify_token[0] == -1) return LI_L1_CACHE_FAILED; + + check = 1; + if (notify_check(_L1_notify_token[0], &check) != 0) return LI_L1_CACHE_FAILED; + if (check == 1) return LI_L1_CACHE_STALE; + + x = 0; + notify_key = NULL; + + switch (tkey) + { + case _li_data_key_group: + { + x = 1; + notify_key = L1_CACHE_NOTIFICATION_KEY_GROUP; + break; + } + case _li_data_key_host: + { + x = 2; + notify_key = L1_CACHE_NOTIFICATION_KEY_HOST; + break; + } + case _li_data_key_service: + { + x = 3; + notify_key = L1_CACHE_NOTIFICATION_KEY_SERVICE; + break; + } + case _li_data_key_user: + { + x = 4; + notify_key = L1_CACHE_NOTIFICATION_KEY_USER; + break; + } + default: break; + } + + if ((x != 0) && (notify_key != NULL)) + { + /* Initialize on first call */ + if (_L1_notify_token[x] == -1) + { + pthread_mutex_lock(&_notify_lock); + if (_L1_notify_token[x] == -1) notify_register_check(notify_key, &(_L1_notify_token[x])); + pthread_mutex_unlock(&_notify_lock); + } + + if (_L1_notify_token[x] == -1) return LI_L1_CACHE_FAILED; + + check = 1; + if (notify_check(_L1_notify_token[x], &check) != 0) return LI_L1_CACHE_FAILED; + if (check == 1) return LI_L1_CACHE_STALE; + } + + return LI_L1_CACHE_OK; +} + +static uint32_t +padsize(size_t curr, size_t item, const uint32_t *align) +{ + uint32_t na, diff; + + if (item > 8) item = 8; + + na = align[item]; + if (na == 0) return 0; + + diff = curr % na; + if (diff == 0) return 0; + + return na - diff; +} + + +/* + * Create a structure using in-line memory (i.e. all one blob). + * This reduces malloc/free workload. + * + * Structutre components may be strings, 1, 2, 4, or 8-byte values, + * lists of strings, or lists of 4, 8, or 16-byte values. + * + * Format keys: + * s NUL terminated string + * 1 1 byte value + * 2 2 byte value + * 4 4 byte value + * 8 8 byte value + * L long (32 or 64 bits, depending on architecture) + * * NULL-terminated list of strings + * a NULL-terminated list of 4-byte values + * b NULL-terminated list of 8-byte values + * c NULL-terminated list of 16-byte values + * + */ +__private_extern__ void * +LI_ils_create(char *fmt, ...) +{ + va_list ap; + char *arg, *f; + char **list; + void *hp, *dp, *lp, *ils; + uint8_t u8; + uint16_t u16; + uint32_t u32, i, pad; + uint64_t u64; + unsigned long l; + size_t memsize, hsize, csize, slen, largest; + const uint32_t *align; + + if (fmt == NULL) return NULL; + + largest = 0; + align = align_32; + if (sizeof(char *) == 8) align = align_64; + + /* first pass: calculate size */ + memsize = ILS_MAGIC_SIZE; + hsize = 0; + + va_start(ap, fmt); + + for (f = fmt; (*f) != '\0'; f++) + { + csize = 0; + slen = 0; + + if (*f == 's') + { + if (largest < sizeof(char *)) largest = sizeof(char *); + + csize = sizeof(char *) + padsize(hsize, sizeof(char *), align); + arg = va_arg(ap, char *); + if (arg != NULL) slen = strlen(arg) + 1; + } + else if (*f == '1') + { + if (largest < 1) largest = 1; + + csize = 1; + u8 = va_arg(ap, int); + } + else if (*f == '2') + { + if (largest < 2) largest = 2; + + csize = 2 + padsize(hsize, 2, align); + u16 = va_arg(ap, int); + } + else if (*f == '4') + { + if (largest < 4) largest = 4; + + csize = 4 + padsize(hsize, 4, align); + u32 = va_arg(ap, uint32_t); + } + else if (*f == '8') + { + if (largest < 8) largest = 8; + + csize = 8 + padsize(hsize, 8, align); + u64 = va_arg(ap, uint64_t); + } + else if (*f == 'L') + { + if (largest < sizeof(unsigned long)) largest = sizeof(unsigned long); + + csize = sizeof(unsigned long) + padsize(hsize, sizeof(unsigned long), align); + l = va_arg(ap, unsigned long); + } + else if (*f == '*') + { + /* NULL-terminated list of strings */ + if (largest < sizeof(char *)) largest = sizeof(char *); + + csize = sizeof(char *) + padsize(hsize, sizeof(char *), align); + list = va_arg(ap, char **); + if (list != NULL) + { + for (i = 0; list[i] != NULL; i++) + { + slen += sizeof(char *); + slen += (strlen(list[i]) + 1); + } + + slen += sizeof(char *); + } + } + else if (*f == 'a') + { + /* NULL-terminated list of 4-byte values */ + if (largest < sizeof(char *)) largest = sizeof(char *); + + csize = sizeof(char *) + padsize(hsize, sizeof(char *), align); + list = va_arg(ap, char **); + if (list != NULL) + { + for (i = 0; list[i] != NULL; i++) + { + slen += sizeof(char *); + slen += 4; + } + + slen += sizeof(char *); + } + } + else if (*f == 'b') + { + /* NULL-terminated list of 8-byte values */ + if (largest < sizeof(char *)) largest = sizeof(char *); + + csize = sizeof(char *) + padsize(hsize, sizeof(char *), align); + list = va_arg(ap, char **); + if (list != NULL) + { + for (i = 0; list[i] != NULL; i++) + { + slen += sizeof(char *); + slen += 8; + } + + slen += sizeof(char *); + } + } + else if (*f == 'c') + { + /* NULL-terminated list of 16-byte values */ + if (largest < sizeof(char *)) largest = sizeof(char *); + + csize = sizeof(char *) + padsize(hsize, sizeof(char *), align); + list = va_arg(ap, char **); + if (list != NULL) + { + for (i = 0; list[i] != NULL; i++) + { + slen += sizeof(char *); + slen += 16; + } + + slen += sizeof(char *); + } + } + else return NULL; + + memsize += csize; + memsize += slen; + hsize += csize; + } + + va_end(ap); + + pad = padsize(hsize, largest, align); + memsize += pad; + hsize += pad; + + ils = malloc(memsize); + if (ils == NULL) + { + errno = ENOMEM; + return NULL; + } + + /* insert magic cookie */ + dp = ils + hsize; + memcpy(dp, ILS_MAGIC, ILS_MAGIC_SIZE); + dp += ILS_MAGIC_SIZE; + + hp = ils; + hsize = 0; + + /* second pass: copy data */ + va_start(ap, fmt); + for (f = fmt; (*f) != '\0'; f++) + { + if (*f == 's') + { + pad = padsize(hsize, sizeof(char *), align); + if (pad != 0) + { + memset(hp, 0, pad); + hp += pad; + hsize += pad; + } + + arg = va_arg(ap, char *); + if (arg == NULL) + { + memset(hp, 0, sizeof(char *)); + } + else + { + memcpy(hp, &dp, sizeof(char *)); + slen = strlen(arg) + 1; + memcpy(dp, arg, slen); + dp += slen; + } + + hp += sizeof(char *); + hsize += sizeof(char *); + } + else if (*f == '1') + { + u8 = va_arg(ap, int); + memcpy(hp, &u8, sizeof(uint8_t)); + hp += sizeof(uint8_t); + } + else if (*f == '2') + { + pad = padsize(hsize, 2, align); + if (pad != 0) + { + memset(hp, 0, pad); + hp += pad; + hsize += pad; + } + + u16 = va_arg(ap, int); + memcpy(hp, &u16, sizeof(uint16_t)); + + hp += sizeof(uint16_t); + hsize += sizeof(uint16_t); + } + else if (*f == '4') + { + pad = padsize(hsize, 4, align); + if (pad != 0) + { + memset(hp, 0, pad); + hp += pad; + hsize += pad; + } + + u32 = va_arg(ap, uint32_t); + memcpy(hp, &u32, sizeof(uint32_t)); + + hp += sizeof(uint32_t); + hsize += sizeof(uint32_t); + } + else if (*f == '8') + { + pad = padsize(hsize, 8, align); + if (pad != 0) + { + memset(hp, 0, pad); + hp += pad; + hsize += pad; + } + + u64 = va_arg(ap, uint64_t); + memcpy(hp, &u64, sizeof(uint64_t)); + + hp += sizeof(uint64_t); + hsize += sizeof(uint64_t); + } + else if (*f == 'L') + { + pad = padsize(hsize, sizeof(unsigned long), align); + if (pad != 0) + { + memset(hp, 0, pad); + hp += pad; + hsize += pad; + } + + l = va_arg(ap, unsigned long); + memcpy(hp, &l, sizeof(unsigned long)); + + hp += sizeof(unsigned long); + hsize += sizeof(unsigned long); + } + else if (*f == '*') + { + pad = padsize(hsize, sizeof(char *), align); + if (pad != 0) + { + memset(hp, 0, pad); + hp += pad; + hsize += pad; + } + + list = va_arg(ap, char **); + + if (list == NULL) + { + memset(hp, 0, sizeof(char *)); + } + else + { + memcpy(hp, &dp, sizeof(char *)); + + for (i = 0; list[i] != NULL; i++); + + lp = dp; + dp += ((i + 1) * sizeof(char *)); + + for (i = 0; list[i] != NULL; i++) + { + memcpy(lp, &dp, sizeof(char *)); + lp += sizeof(char *); + slen = strlen(list[i]) + 1; + memcpy(dp, list[i], slen); + dp += slen; + } + + memset(lp, 0, sizeof(char *)); + } + + hp += sizeof(char *); + hsize += sizeof(char *); + } + else if (*f == 'a') + { + pad = padsize(hsize, sizeof(char *), align); + if (pad != 0) + { + memset(hp, 0, pad); + hp += pad; + hsize += pad; + } + + list = va_arg(ap, char **); + + if (list == NULL) + { + memset(hp, 0, sizeof(char *)); + } + else + { + memcpy(hp, &dp, sizeof(char *)); + + for (i = 0; list[i] != NULL; i++); + + lp = dp; + dp += ((i + 1) * sizeof(char *)); + + for (i = 0; list[i] != NULL; i++) + { + memcpy(lp, &dp, sizeof(char *)); + lp += sizeof(char *); + slen = 4; + memcpy(dp, list[i], slen); + dp += slen; + } + + memset(lp, 0, sizeof(char *)); + } + + hp += sizeof(char *); + hsize += sizeof(char *); + } + else if (*f == 'b') + { + pad = padsize(hsize, sizeof(char *), align); + if (pad != 0) + { + memset(hp, 0, pad); + hp += pad; + hsize += pad; + } + + list = va_arg(ap, char **); + + if (list == NULL) + { + memset(hp, 0, sizeof(char *)); + } + else + { + memcpy(hp, &dp, sizeof(char *)); + + for (i = 0; list[i] != NULL; i++); + + lp = dp; + dp += ((i + 1) * sizeof(char *)); + + for (i = 0; list[i] != NULL; i++) + { + memcpy(lp, &dp, sizeof(char *)); + lp += sizeof(char *); + slen = 8; + memcpy(dp, list[i], slen); + dp += slen; + } + + memset(lp, 0, sizeof(char *)); + } + + hp += sizeof(char *); + hsize += sizeof(char *); + } + else if (*f == 'c') + { + pad = padsize(hsize, sizeof(char *), align); + if (pad != 0) + { + memset(hp, 0, pad); + hp += pad; + hsize += pad; + } + + list = va_arg(ap, char **); + + if (list == NULL) + { + memset(hp, 0, sizeof(char *)); + } + else + { + memcpy(hp, &dp, sizeof(char *)); + + for (i = 0; list[i] != NULL; i++); + + lp = dp; + dp += ((i + 1) * sizeof(char *)); + + for (i = 0; list[i] != NULL; i++) + { + memcpy(lp, &dp, sizeof(char *)); + lp += sizeof(char *); + slen = 16; + memcpy(dp, list[i], slen); + dp += slen; + } + + memset(lp, 0, sizeof(char *)); + } + + hp += sizeof(char *); + hsize += sizeof(char *); + } + } + + va_end(ap); + + pad = padsize(hsize, largest, align); + if (pad > 0) memset(hp, 0, pad); + + return ils; +} + +__private_extern__ int +LI_ils_free(void *ils, size_t len) +{ + char *p; + + if (ils == NULL) return 0; + + p = ils + len; + if (memcmp(p, ILS_MAGIC, ILS_MAGIC_SIZE) != 0) return -1; + + free(ils); + + return 0; +} + +kern_return_t +_lookup_link(mach_port_t server, char *name, int *procno) +{ + syslog(LOG_ERR, "RED ALERT! lookupd call %s from pid %u", name, getpid()); + return KERN_FAILURE; +} + +kern_return_t +_lookup_one(mach_port_t server, int proc, char *indata, mach_msg_type_number_t indataCnt, char *outdata, mach_msg_type_number_t *outdataCnt) +{ + return KERN_FAILURE; +} + +kern_return_t +_lookup_all(mach_port_t server, int proc, char *indata, mach_msg_type_number_t indataCnt, char **outdata, mach_msg_type_number_t *outdataCnt) +{ + return KERN_FAILURE; +} + +kern_return_t +_lookup_ooall(mach_port_t server, int proc, char *indata, mach_msg_type_number_t indataCnt, char **outdata, mach_msg_type_number_t *outdataCnt) +{ + return KERN_FAILURE; +} diff --git a/lookup.subproj/lu_utils.h b/lookup.subproj/lu_utils.h index ae987c0..77273a5 100644 --- a/lookup.subproj/lu_utils.h +++ b/lookup.subproj/lu_utils.h @@ -29,57 +29,93 @@ #ifndef _LU_UTILS_H_ #define _LU_UTILS_H_ -#import -#include +#include "DSlibinfoMIG_types.h" +#include "kvbuf.h" #include -#define LU_COPY_STRING(x) strdup(((x) == NULL) ? "" : x) +#define _li_data_key_alias 10010 +#define _li_data_key_bootp 10020 +#define _li_data_key_bootparams 10030 +#define _li_data_key_fstab 10040 +#define _li_data_key_group 10050 +#define _li_data_key_host 10060 +#define _li_data_key_netgroup 10070 +#define _li_data_key_network 10080 +#define _li_data_key_printer 10090 +#define _li_data_key_protocol 10100 +#define _li_data_key_rpc 10110 +#define _li_data_key_service 10120 +#define _li_data_key_user 10130 -#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 +/* + * Return values for LI_L1_cache_check. + */ +#define LI_L1_CACHE_OK 0 +#define LI_L1_CACHE_STALE 1 +#define LI_L1_CACHE_DISABLED 2 +#define LI_L1_CACHE_FAILED 3 -struct lu_thread_info +struct li_thread_info { - void *lu_entry; - XDR *lu_xdr; - char *lu_vm; - unsigned int lu_vm_length; - unsigned int lu_vm_cursor; + void *li_entry; + size_t li_entry_size; + char *li_vm; + uint32_t li_vm_length; + uint32_t li_vm_cursor; + uint32_t li_flags; }; -extern mach_port_t _lu_port; -extern unit *_lookup_buf; -extern int _lu_running(void); +extern mach_port_t _ds_port; +extern int _ds_running(void); + +/* + * Thread-local data management + */ +__private_extern__ void *LI_data_find_key(uint32_t key); +__private_extern__ void *LI_data_create_key(uint32_t key, size_t esize); +__private_extern__ void LI_data_set_key(uint32_t key, void *data); +__private_extern__ void *LI_data_get_key(uint32_t key); +__private_extern__ void LI_data_free_kvarray(struct li_thread_info *tdata); +__private_extern__ void LI_data_recycle(struct li_thread_info *tdata, void *entry, size_t entrysize); +__private_extern__ void *LI_ils_create(char *fmt, ...); +__private_extern__ int LI_ils_free(void *ils, size_t len); + +kern_return_t _lookup_link(mach_port_t server, char *name, int *procno); +kern_return_t _lookup_one(mach_port_t server, int proc, char *indata, mach_msg_type_number_t indataCnt, char *outdata, mach_msg_type_number_t *outdataCnt); +kern_return_t _lookup_all(mach_port_t server, int proc, char *indata, mach_msg_type_number_t indataCnt, char **outdata, mach_msg_type_number_t *outdataCnt); +kern_return_t _lookup_ooall(mach_port_t server, int proc, char *indata, mach_msg_type_number_t indataCnt, char **outdata, mach_msg_type_number_t *outdataCnt); + +/* + * Directory Service queries + */ +kern_return_t LI_DSLookupGetProcedureNumber(const char *name, int *procno); -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); +__private_extern__ kern_return_t LI_DSLookupQuery(int32_t proc, kvbuf_t *request, kvarray_t **reply); +__private_extern__ void *LI_getent(const char *procname, int *procnum, void *(*extract)(kvarray_t *), int tkey, size_t esize); +__private_extern__ void *LI_getone(const char *procname, int *procnum, void *(*extract)(kvarray_t *), const char *key, const char *val); -int _lu_xdr_attribute(XDR *xdr, char **key, char ***val, unsigned int *count); +/* + * L1 cache + * Takes _li_data_key_xxx as an argument. + * Returns 0 is the cache is valid, non-zero if it is invalid. + */ +__private_extern__ int LI_L1_cache_check(int tkey); -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); +/* + * Async support + */ +void LI_async_call_cancel(mach_port_t p, void **context); +kern_return_t LI_async_handle_reply(mach_msg_header_t *msg, kvarray_t **reply, void **callback, void **context); +kern_return_t LI_async_receive(mach_port_t p, kvarray_t **reply); +kern_return_t LI_async_send(mach_port_t *p, uint32_t proc, kvbuf_t *query); +kern_return_t LI_async_start(mach_port_t *p, uint32_t proc, kvbuf_t *query, void *callback, void *context); -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); +/* + * kvbuf query support + */ +__private_extern__ kvbuf_t *kvbuf_query(char *fmt, ...); +__private_extern__ kvbuf_t *kvbuf_query_key_int(const char *key, int32_t i); +__private_extern__ kvbuf_t *kvbuf_query_key_uint(const char *key, uint32_t u); +__private_extern__ kvbuf_t *kvbuf_query_key_val(const char *key, const char *val); #endif /* ! _LU_UTILS_H_ */ diff --git a/lookup.subproj/netdb.h b/lookup.subproj/netdb.h index 916842e..95e485d 100644 --- a/lookup.subproj/netdb.h +++ b/lookup.subproj/netdb.h @@ -81,8 +81,8 @@ #ifndef _NETDB_H_ #define _NETDB_H_ -#include #include <_types.h> +#include #include /* IPPORT_RESERVED */ #ifndef _SIZE_T @@ -118,9 +118,9 @@ struct hostent { int h_addrtype; /* host address type */ int h_length; /* length of address */ char **h_addr_list; /* list of addresses from name server */ -#ifndef _POSIX_C_SOURCE +#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) #define h_addr h_addr_list[0] /* address, for backward compatiblity */ -#endif /* !_POSIX_C_SOURCE */ +#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ }; /* @@ -158,54 +158,54 @@ struct addrinfo { struct addrinfo *ai_next; /* next structure in linked list */ }; -#ifndef _POSIX_C_SOURCE +#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) struct rpcent { char *r_name; /* name of server for this rpc program */ char **r_aliases; /* alias list */ int r_number; /* rpc program number */ }; -#endif /* !_POSIX_C_SOURCE */ +#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ /* * Error return codes from gethostbyname() and gethostbyaddr() * (left in extern int h_errno). */ -#ifndef _POSIX_C_SOURCE +#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) #define NETDB_INTERNAL -1 /* see errno */ #define NETDB_SUCCESS 0 /* no problem */ -#endif /* !_POSIX_C_SOURCE */ +#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ #define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */ #define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL */ #define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ #define NO_DATA 4 /* Valid name, no data record of requested type */ -#ifndef _POSIX_C_SOURCE +#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) #define NO_ADDRESS NO_DATA /* no address, look for MX record */ -#endif /* !_POSIX_C_SOURCE */ +#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ /* * Error return codes from getaddrinfo() */ -#ifndef _POSIX_C_SOURCE +#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) #define EAI_ADDRFAMILY 1 /* address family for hostname not supported */ -#endif /* !_POSIX_C_SOURCE */ +#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ #define EAI_AGAIN 2 /* temporary failure in name resolution */ #define EAI_BADFLAGS 3 /* invalid value for ai_flags */ #define EAI_FAIL 4 /* non-recoverable failure in name resolution */ #define EAI_FAMILY 5 /* ai_family not supported */ #define EAI_MEMORY 6 /* memory allocation failure */ -#ifndef _POSIX_C_SOURCE +#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) #define EAI_NODATA 7 /* no address associated with hostname */ -#endif /* !_POSIX_C_SOURCE */ +#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ #define EAI_NONAME 8 /* hostname nor servname provided, or not known */ #define EAI_SERVICE 9 /* servname not supported for ai_socktype */ #define EAI_SOCKTYPE 10 /* ai_socktype not supported */ #define EAI_SYSTEM 11 /* system error returned in errno */ -#ifndef _POSIX_C_SOURCE +#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) #define EAI_BADHINTS 12 #define EAI_PROTOCOL 13 #define EAI_MAX 14 -#else /* _POSIX_C_SOURCE */ +#else /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */ #define EAI_OVERFLOW 14 /* An argument buffer overflowed */ -#endif /* !_POSIX_C_SOURCE */ +#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ /* * Flag values for getaddrinfo() @@ -214,27 +214,27 @@ struct rpcent { #define AI_CANONNAME 0x00000002 /* fill ai_canonname */ #define AI_NUMERICHOST 0x00000004 /* prevent name resolution */ /* valid flags for addrinfo */ -#ifndef _POSIX_C_SOURCE +#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) #define AI_MASK (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST) -#endif /* !_POSIX_C_SOURCE */ +#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ #define AI_ALL 0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */ -#ifndef _POSIX_C_SOURCE +#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) #define AI_V4MAPPED_CFG 0x00000200 /* accept IPv4-mapped if kernel supports */ -#endif /* !_POSIX_C_SOURCE */ +#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ #define AI_ADDRCONFIG 0x00000400 /* only if any address is assigned */ #define AI_V4MAPPED 0x00000800 /* accept IPv4-mapped IPv6 address */ /* special recommended flags for getipnodebyname */ -#ifndef _POSIX_C_SOURCE +#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) #define AI_DEFAULT (AI_V4MAPPED_CFG | AI_ADDRCONFIG) -#endif /* !_POSIX_C_SOURCE */ +#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ /* * Constants for getnameinfo() */ -#ifndef _POSIX_C_SOURCE +#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) #define NI_MAXHOST 1025 #define NI_MAXSERV 32 -#endif /* !_POSIX_C_SOURCE */ +#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ /* * Flag values for getnameinfo() */ @@ -243,16 +243,17 @@ struct rpcent { #define NI_NAMEREQD 0x00000004 #define NI_NUMERICSERV 0x00000008 #define NI_DGRAM 0x00000010 -#ifndef _POSIX_C_SOURCE +#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) #define NI_WITHSCOPEID 0x00000020 /* * Scope delimit character */ #define SCOPE_DELIMITER '%' -#endif /* !_POSIX_C_SOURCE */ +#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ __BEGIN_DECLS + void endhostent(void); void endnetent(void); void endprotoent(void); @@ -283,20 +284,29 @@ void sethostent(int); void setnetent(int); void setprotoent(int); void setservent(int); -#ifndef _POSIX_C_SOURCE + +#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) void freehostent(struct hostent *); struct hostent *gethostbyname2(const char *, int); struct hostent *getipnodebyaddr(const void *, size_t, int, int *); struct hostent *getipnodebyname(const char *, int, int, int *); struct rpcent *getrpcbyname(const char *name); +#ifdef __LP64__ +struct rpcent *getrpcbynumber(int number); +#else struct rpcent *getrpcbynumber(long number); +#endif struct rpcent *getrpcent(void); void setrpcent(int stayopen); void endrpcent(void); void herror(const char *); const char *hstrerror(int); -int innetgr(const char *, const char *, const char *, const char *); -#endif /* !_POSIX_C_SOURCE */ +int innetgr(const char *, const char *, const char *, const char *); +int getnetgrent(char **, char **, char **); +void endnetgrent(void); +void setnetgrent(const char *); +#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ + __END_DECLS #endif /* !_NETDB_H_ */ diff --git a/lookup.subproj/netdb_async.h b/lookup.subproj/netdb_async.h index 6b72111..3f6b347 100644 --- a/lookup.subproj/netdb_async.h +++ b/lookup.subproj/netdb_async.h @@ -39,41 +39,6 @@ __BEGIN_DECLS -/* - * Private asynchronous lookup API - */ - -/* - * Cancel an outstanding call and free its resources. - */ -extern void lu_async_call_cancel(mach_port_t p); - -/* - * Make an asynchronous lookupd call. - * Sends data buffer to lookupd and returns a port. - * The buffer must be encoded for lookupd. - */ -extern kern_return_t lu_async_start(mach_port_t *p, uint32_t proc, const char *buf, uint32_t len, void *callback, void *context); -extern kern_return_t lu_async_send(mach_port_t *p, uint32_t proc, const char *buf, uint32_t len); - -/* - * Receive a reply for an asynchronous lookupd call. - * Receives the reply message and gets a raw (undecoded) data buffer. - */ -extern kern_return_t lu_async_receive(mach_port_t p, char **buf, uint32_t *len); - -/* - * Takes a reply message and provides the callback, context, and raw data buffers. - * This routine does not invoke the callback. Type-specific asynchronous - * routines built on top of this API will decode the data buffer and invoke - * the callback routine. - */ -extern int lu_async_handle_reply(void *msg, char **buf, uint32_t *len, void **callback, void **context); - - -/* - * Type-specific routines. - */ /* * getaddrinfo @@ -83,6 +48,7 @@ int32_t getaddrinfo_async_start(mach_port_t *p, const char *nodename, const char int32_t getaddrinfo_async_send(mach_port_t *p, const char *nodename, const char *servname, const struct addrinfo *hints); int32_t getaddrinfo_async_receive(mach_port_t p, struct addrinfo **res); int32_t getaddrinfo_async_handle_reply(void *msg); +void getaddrinfo_async_cancel(mach_port_t p); /* @@ -93,6 +59,7 @@ int32_t getnameinfo_async_start(mach_port_t *p, const struct sockaddr *sa, size_ int32_t getnameinfo_async_send(mach_port_t *p, const struct sockaddr *sa, size_t salen, int flags); int32_t getnameinfo_async_receive(mach_port_t p, char **host, char **serv); int32_t getnameinfo_async_handle_reply(void *msg); +void getnameinfo_async_cancel(mach_port_t p); /* * DNS @@ -102,12 +69,10 @@ int32_t dns_async_start(mach_port_t *p, const char *name, uint16_t dnsclass, uin int32_t dns_async_send(mach_port_t *p, const char *name, uint16_t dnsclass, uint16_t dnstype, uint32_t do_search); int32_t dns_async_receive(mach_port_t p, char **buf, uint32_t *len, struct sockaddr **from, uint32_t *fromlen); int32_t dns_async_handle_reply(void *msg); +void dns_async_cancel(mach_port_t p); /* - * Host lookup asynchronous API - * These routines don't use the asynchronous lookupd access support - * described above. There will eventually be converted. - * The API is syntactically similar. + * Host lookup */ /* diff --git a/lookup.subproj/netgr.h b/lookup.subproj/netgr.h deleted file mode 100644 index a1a4cda..0000000 --- a/lookup.subproj/netgr.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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@ - */ -/* - * Netgroup lookup routines - * Copyright (c) 1989 by NeXT, Inc. - */ - -#ifndef _NETGR_H_ -#define _NETGR_H_ - -#include - -__BEGIN_DECLS -int innetgr(const char * name, const char *host, const char *user, const char *domain); -int getnetgrent(char **host, char **user, char **domain); -void endnetgrent(void); -void setnetgrent(const char *netgroup); -__END_DECLS - -#endif /* !_NETGR_H_ */ diff --git a/mdns.subproj/DNSServiceDiscovery.c b/mdns.subproj/DNSServiceDiscovery.c deleted file mode 100644 index a311769..0000000 --- a/mdns.subproj/DNSServiceDiscovery.c +++ /dev/null @@ -1,672 +0,0 @@ -/* - * 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 mig_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, - IPPort 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; - IPPort IpPort; - char *portptr = (char *)&port; - - if (!serverPort) { - return NULL; - } - - if (!txtRecord) { - txtRecord = ""; - } - - 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; - - // older versions of this code passed the port via mach IPC as an int. - // we continue to pass it as 4 bytes to maintain binary compatibility, - // but now ensure that the network byte order is preserved by using a struct - IpPort.bytes[0] = 0; - IpPort.bytes[1] = 0; - IpPort.bytes[2] = portptr[0]; - IpPort.bytes[3] = portptr[1]; - - result = DNSServiceRegistrationCreate_rpc(serverPort, clientPort, (char *)name, (char *)regtype, (char *)domain, IpPort, (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 deleted file mode 100644 index 2539467..0000000 --- a/mdns.subproj/DNSServiceDiscovery.h +++ /dev/null @@ -1,292 +0,0 @@ -/* - * 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 - -#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 -) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED; - -/***************************************************************************/ -/* 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 -) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED; - -/***************************************************************************/ -/* 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 -) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED; - -/***************************************************************************/ -/* 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 -) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED; - -/***************************************************************************/ -/* 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) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED; - -/*! - @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) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED; - -/***************************************************************************/ -/* 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) -AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED; - -/*! - @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) -AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED; - -/*! - @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) -AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED; - - -__END_DECLS - -#endif /* __DNS_SERVICE_DISCOVERY_H */ diff --git a/mdns.subproj/DNSServiceDiscoveryDefines.h b/mdns.subproj/DNSServiceDiscoveryDefines.h deleted file mode 100644 index 9f021d9..0000000 --- a/mdns.subproj/DNSServiceDiscoveryDefines.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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 "com.apple.mDNSResponder" - -typedef char DNSCString[1024]; -typedef char sockaddr_t[128]; - -typedef const char * record_data_t; -typedef struct { char bytes[4]; } IPPort; - -#endif /* __DNS_SERVICE_DISCOVERY_DEFINES_H */ - diff --git a/mdns.subproj/DNSServiceDiscoveryReply.defs b/mdns.subproj/DNSServiceDiscoveryReply.defs deleted file mode 100644 index d26c20b..0000000 --- a/mdns.subproj/DNSServiceDiscoveryReply.defs +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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 deleted file mode 100644 index d14917a..0000000 --- a/mdns.subproj/DNSServiceDiscoveryRequest.defs +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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; -type IPPort = struct[4] of char ctype:IPPort; - -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: IPPort; - in txtRecord: DNSCString); - - -simpleroutine DNSServiceResolverResolve_rpc( - server: mach_port_t; - in client: mach_port_t; - in name: DNSCString; - in regtype: DNSCString; - in domain: DNSCString); - -routine DNSServiceRegistrationAddRecord_rpc( - server: mach_port_t; - in client: mach_port_t; - in record_type: int; - in record_data: record_data; - in ttl: uint32_t; - out record_reference: natural_t); - -simpleroutine DNSServiceRegistrationUpdateRecord_rpc( - server: mach_port_t; - in client: mach_port_t; - in record_reference: natural_t; - in record_data: record_data; - in ttl: uint32_t); - -simpleroutine DNSServiceRegistrationRemoveRecord_rpc( - server: mach_port_t; - in client: mach_port_t; - in record_reference: natural_t); - diff --git a/mdns.subproj/Makefile b/mdns.subproj/Makefile deleted file mode 100644 index cda015f..0000000 --- a/mdns.subproj/Makefile +++ /dev/null @@ -1,52 +0,0 @@ -# -# Generated by the Apple Project Builder. -# -# NOTE: Do NOT change this file -- Project Builder maintains it. -# -# Put all of your customizations in files called Makefile.preamble -# and Makefile.postamble (both optional), and Makefile will include them. -# - -NAME = mdns - -PROJECTVERSION = 2.8 -PROJECT_TYPE = Component - -HFILES = DNSServiceDiscoveryDefines.h DNSServiceDiscovery.h dns_sd.h dnssd_ipc.h - -CFILES = DNSServiceDiscovery.c dnssd_clientstub.c dnssd_ipc.c dnssd_clientlib.c - -OTHERSRCS = Makefile.preamble Makefile Makefile.postamble\ - DNSServiceDiscoveryReply.defs DNSServiceDiscoveryRequest.defs - - -MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles -CODE_GEN_STYLE = DYNAMIC -MAKEFILE = subproj.make -NEXTSTEP_INSTALLDIR = /usr/local/lib/system -LIBS = -DEBUG_LIBS = $(LIBS) -PROF_LIBS = $(LIBS) - -PUBLIC_HEADERS = dns_sd.h - - - -NEXTSTEP_PUBLIC_HEADERS_DIR = /usr/include - -NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc -WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc -PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc -NEXTSTEP_JAVA_COMPILER = /usr/bin/javac -WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe -PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac - -include $(MAKEFILEDIR)/platform.make - --include Makefile.preamble - -include $(MAKEFILEDIR)/$(MAKEFILE) - --include Makefile.postamble - --include Makefile.dependencies diff --git a/mdns.subproj/Makefile.postamble b/mdns.subproj/Makefile.postamble deleted file mode 100644 index 11fac3f..0000000 --- a/mdns.subproj/Makefile.postamble +++ /dev/null @@ -1,110 +0,0 @@ -############################################################################### -# 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) $(DSTROOT)$(PUBLIC_HDR_INSTALLDIR)$(MDNS_HEADER_DIR_SUFFIX) - $(SILENT) $(FASTCP) $(INTERNAL_MDNS_HDRS) $(DSTROOT)$(PRIVATE_HDR_INSTALLDIR)$(MDNS_HEADER_DIR_SUFFIX) - $(SILENT) $(FASTCP) $(PUBLIC_MDNS_HEADERS) $(DSTROOT)$(PUBLIC_HDR_INSTALLDIR)$(MDNS_HEADER_DIR_SUFFIX) - -$(DSTROOT)$(PRIVATE_HDR_INSTALLDIR)$(MDNS_HEADER_DIR_SUFFIX): - $(MKDIRS) $@ - -$(DSTROOT)$(PUBLIC_HDR_INSTALLDIR)$(MDNS_HEADER_DIR_SUFFIX): - $(MKDIRS) $@ diff --git a/mdns.subproj/Makefile.preamble b/mdns.subproj/Makefile.preamble deleted file mode 100644 index c3ae97e..0000000 --- a/mdns.subproj/Makefile.preamble +++ /dev/null @@ -1,160 +0,0 @@ -############################################################################### -# 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 -INTERNAL_MDNS_HDRS = DNSServiceDiscoveryRequest.defs\ - DNSServiceDiscoveryRequest.h \ - DNSServiceDiscoveryReply.defs\ - DNSServiceDiscoveryReply.h \ - DNSServiceDiscoveryDefines.h - -# public headers -PUBLIC_MDNS_HEADERS = DNSServiceDiscovery.h - -BEFORE_INSTALLHDRS += $(SFILE_DIR) $(INTERNAL_MDNS_HDRS) -AFTER_INSTALLHDRS += mdns_hdrs -PRIVATE_HEADER_DIR = /AppleInternal/Developer/Headers -MDNS_HEADER_DIR_SUFFIX = /DNSServiceDiscovery - - -# for building 64-bit -# Libinfo need to build with gcc-3.5 and 3-way fat -NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER) diff --git a/mdns.subproj/PB.project b/mdns.subproj/PB.project deleted file mode 100644 index ee7d0e0..0000000 --- a/mdns.subproj/PB.project +++ /dev/null @@ -1,34 +0,0 @@ -{ - DYNAMIC_CODE_GEN = YES; - English_RESOURCES = {}; - FILESTABLE = { - H_FILES = (DNSServiceDiscoveryDefines.h, DNSServiceDiscovery.h, dns_sd.h, dnssd_ipc.h); - OTHER_LINKED = (DNSServiceDiscovery.c, dnssd_clientstub.c, dnssd_ipc.c); - OTHER_RESOURCES = (); - OTHER_SOURCES = ( - Makefile.preamble, - Makefile, - Makefile.postamble, - DNSServiceDiscoveryReply.defs, - DNSServiceDiscoveryRequest.defs - ); - PUBLIC_HEADERS = (dns_sd.h); - SUBPROJECTS = (); - }; - LANGUAGE = English; - MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; - NEXTSTEP_BUILDTOOL = /usr/bin/gnumake; - NEXTSTEP_INSTALLDIR = /usr/local/lib/system; - NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; - NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; - NEXTSTEP_PUBLICHEADERSDIR = /usr/include; - PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; - PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; - PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; - PROJECTNAME = mdns; - PROJECTTYPE = Component; - PROJECTVERSION = 2.8; - WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; - WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; - WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; -} diff --git a/mdns.subproj/dns_sd.h b/mdns.subproj/dns_sd.h deleted file mode 100644 index a7411a3..0000000 --- a/mdns.subproj/dns_sd.h +++ /dev/null @@ -1,1644 +0,0 @@ -/* - * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * 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 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _DNS_SD_H -#define _DNS_SD_H - -#ifdef __cplusplus - extern "C" { -#endif - -/* standard calling convention under Win32 is __stdcall */ -#if defined(_WIN32) -#define DNSSD_API __stdcall -#else -#define DNSSD_API -#endif - -#if defined(__FreeBSD_version) && (__FreeBSD_version < 500000) -/* stdint.h does not exist on FreeBSD 4.x; its types are defined in sys/types.h instead */ -#include -#elif defined(__sun__) -#include -#elif defined(_WIN32) -#include -#define _UNUSED -#define bzero(a, b) memset(a, 0, b) -typedef UINT8 uint8_t; -typedef INT8 int8_t; -typedef UINT16 uint16_t; -typedef INT16 int16_t; -typedef UINT32 uint32_t; -typedef INT32 int32_t; -#else -#include -#endif - -/* DNSServiceRef, DNSRecordRef - * - * Opaque internal data types. - * Note: client is responsible for serializing access to these structures if - * they are shared between concurrent threads. - */ - -typedef struct _DNSServiceRef_t *DNSServiceRef; -typedef struct _DNSRecordRef_t *DNSRecordRef; - -/* General flags used in functions defined below */ -enum - { - kDNSServiceFlagsMoreComing = 0x1, - /* MoreComing indicates to a callback that at least one more result is - * queued and will be delivered following immediately after this one. - * Applications should not update their UI to display browse - * results when the MoreComing flag is set, because this would - * result in a great deal of ugly flickering on the screen. - * Applications should instead wait until until MoreComing is not set, - * and then update their UI. - * When MoreComing is not set, that doesn't mean there will be no more - * answers EVER, just that there are no more answers immediately - * available right now at this instant. If more answers become available - * in the future they will be delivered as usual. - */ - - kDNSServiceFlagsAdd = 0x2, - kDNSServiceFlagsDefault = 0x4, - /* Flags for domain enumeration and browse/query reply callbacks. - * "Default" applies only to enumeration and is only valid in - * conjuction with "Add". An enumeration callback with the "Add" - * flag NOT set indicates a "Remove", i.e. the domain is no longer - * valid. - */ - - kDNSServiceFlagsNoAutoRename = 0x8, - /* Flag for specifying renaming behavior on name conflict when registering - * non-shared records. By default, name conflicts are automatically handled - * by renaming the service. NoAutoRename overrides this behavior - with this - * flag set, name conflicts will result in a callback. The NoAutorename flag - * is only valid if a name is explicitly specified when registering a service - * (ie the default name is not used.) - */ - - kDNSServiceFlagsShared = 0x10, - kDNSServiceFlagsUnique = 0x20, - /* Flag for registering individual records on a connected - * DNSServiceRef. Shared indicates that there may be multiple records - * with this name on the network (e.g. PTR records). Unique indicates that the - * record's name is to be unique on the network (e.g. SRV records). - */ - - kDNSServiceFlagsBrowseDomains = 0x40, - kDNSServiceFlagsRegistrationDomains = 0x80, - /* Flags for specifying domain enumeration type in DNSServiceEnumerateDomains. - * BrowseDomains enumerates domains recommended for browsing, RegistrationDomains - * enumerates domains recommended for registration. - */ - - kDNSServiceFlagsLongLivedQuery = 0x100, - /* Flag for creating a long-lived unicast query for the DNSServiceQueryRecord call. */ - - kDNSServiceFlagsAllowRemoteQuery = 0x200, - /* Flag for creating a record for which we will answer remote queries - * (queries from hosts more than one hop away; hosts not directly connected to the local link). - */ - - kDNSServiceFlagsForceMulticast = 0x400 - /* Flag for signifying that a query or registration should be performed exclusively via multicast DNS, - * even for a name in a domain (e.g. foo.apple.com.) that would normally imply unicast DNS. - */ - }; - -/* - * The values for DNS Classes and Types are listed in RFC 1035, and are available - * on every OS in its DNS header file. Unfortunately every OS does not have the - * same header file containing DNS Class and Type constants, and the names of - * the constants are not consistent. For example, BIND 8 uses "T_A", - * BIND 9 uses "ns_t_a", Windows uses "DNS_TYPE_A", etc. - * For this reason, these constants are also listed here, so that code using - * the DNS-SD programming APIs can use these constants, so that the same code - * can compile on all our supported platforms. - */ - -enum - { - kDNSServiceClass_IN = 1 /* Internet */ - }; - -enum - { - kDNSServiceType_A = 1, /* Host address. */ - kDNSServiceType_NS = 2, /* Authoritative server. */ - kDNSServiceType_MD = 3, /* Mail destination. */ - kDNSServiceType_MF = 4, /* Mail forwarder. */ - kDNSServiceType_CNAME = 5, /* Canonical name. */ - kDNSServiceType_SOA = 6, /* Start of authority zone. */ - kDNSServiceType_MB = 7, /* Mailbox domain name. */ - kDNSServiceType_MG = 8, /* Mail group member. */ - kDNSServiceType_MR = 9, /* Mail rename name. */ - kDNSServiceType_NULL = 10, /* Null resource record. */ - kDNSServiceType_WKS = 11, /* Well known service. */ - kDNSServiceType_PTR = 12, /* Domain name pointer. */ - kDNSServiceType_HINFO = 13, /* Host information. */ - kDNSServiceType_MINFO = 14, /* Mailbox information. */ - kDNSServiceType_MX = 15, /* Mail routing information. */ - kDNSServiceType_TXT = 16, /* Text strings. */ - kDNSServiceType_RP = 17, /* Responsible person. */ - kDNSServiceType_AFSDB = 18, /* AFS cell database. */ - kDNSServiceType_X25 = 19, /* X_25 calling address. */ - kDNSServiceType_ISDN = 20, /* ISDN calling address. */ - kDNSServiceType_RT = 21, /* Router. */ - kDNSServiceType_NSAP = 22, /* NSAP address. */ - kDNSServiceType_NSAP_PTR = 23, /* Reverse NSAP lookup (deprecated). */ - kDNSServiceType_SIG = 24, /* Security signature. */ - kDNSServiceType_KEY = 25, /* Security key. */ - kDNSServiceType_PX = 26, /* X.400 mail mapping. */ - kDNSServiceType_GPOS = 27, /* Geographical position (withdrawn). */ - kDNSServiceType_AAAA = 28, /* Ip6 Address. */ - kDNSServiceType_LOC = 29, /* Location Information. */ - kDNSServiceType_NXT = 30, /* Next domain (security). */ - kDNSServiceType_EID = 31, /* Endpoint identifier. */ - kDNSServiceType_NIMLOC = 32, /* Nimrod Locator. */ - kDNSServiceType_SRV = 33, /* Server Selection. */ - kDNSServiceType_ATMA = 34, /* ATM Address */ - kDNSServiceType_NAPTR = 35, /* Naming Authority PoinTeR */ - kDNSServiceType_KX = 36, /* Key Exchange */ - kDNSServiceType_CERT = 37, /* Certification record */ - kDNSServiceType_A6 = 38, /* IPv6 address (deprecates AAAA) */ - kDNSServiceType_DNAME = 39, /* Non-terminal DNAME (for IPv6) */ - kDNSServiceType_SINK = 40, /* Kitchen sink (experimentatl) */ - kDNSServiceType_OPT = 41, /* EDNS0 option (meta-RR) */ - kDNSServiceType_TKEY = 249, /* Transaction key */ - kDNSServiceType_TSIG = 250, /* Transaction signature. */ - kDNSServiceType_IXFR = 251, /* Incremental zone transfer. */ - kDNSServiceType_AXFR = 252, /* Transfer zone of authority. */ - kDNSServiceType_MAILB = 253, /* Transfer mailbox records. */ - kDNSServiceType_MAILA = 254, /* Transfer mail agent records. */ - kDNSServiceType_ANY = 255 /* Wildcard match. */ - }; - - -/* possible error code values */ -enum - { - kDNSServiceErr_NoError = 0, - kDNSServiceErr_Unknown = -65537, /* 0xFFFE FFFF */ - kDNSServiceErr_NoSuchName = -65538, - kDNSServiceErr_NoMemory = -65539, - kDNSServiceErr_BadParam = -65540, - kDNSServiceErr_BadReference = -65541, - kDNSServiceErr_BadState = -65542, - kDNSServiceErr_BadFlags = -65543, - kDNSServiceErr_Unsupported = -65544, - kDNSServiceErr_NotInitialized = -65545, - kDNSServiceErr_AlreadyRegistered = -65547, - kDNSServiceErr_NameConflict = -65548, - kDNSServiceErr_Invalid = -65549, - kDNSServiceErr_Firewall = -65550, - kDNSServiceErr_Incompatible = -65551, /* client library incompatible with daemon */ - kDNSServiceErr_BadInterfaceIndex = -65552, - kDNSServiceErr_Refused = -65553, - kDNSServiceErr_NoSuchRecord = -65554, - kDNSServiceErr_NoAuth = -65555, - kDNSServiceErr_NoSuchKey = -65556, - kDNSServiceErr_NATTraversal = -65557, - kDNSServiceErr_DoubleNAT = -65558, - kDNSServiceErr_BadTime = -65559 - /* mDNS Error codes are in the range - * FFFE FF00 (-65792) to FFFE FFFF (-65537) */ - }; - - -/* Maximum length, in bytes, of a domain name represented as an escaped C-String */ -/* including the final trailing dot, and the C-String terminating NULL at the end */ - -#define kDNSServiceMaxDomainName 1005 - -/* - * Notes on DNS Name Escaping - * -- or -- - * "Why is kDNSServiceMaxDomainName 1005, when the maximum legal domain name is 255 bytes?" - * - * All strings used in DNS-SD are UTF-8 strings. - * With few exceptions, most are also escaped using standard DNS escaping rules: - * - * '\\' represents a single literal '\' in the name - * '\.' represents a single literal '.' in the name - * '\ddd', where ddd is a three-digit decimal value from 000 to 255, - * represents a single literal byte with that value. - * A bare unescaped '.' is a label separator, marking a boundary between domain and subdomain. - * - * The exceptions, that do not use escaping, are the routines where the full - * DNS name of a resource is broken, for convenience, into servicename/regtype/domain. - * In these routines, the "servicename" is NOT escaped. It does not need to be, since - * it is, by definition, just a single literal string. Any characters in that string - * represent exactly what they are. The "regtype" portion is, technically speaking, - * escaped, but since legal regtypes are only allowed to contain letters, digits, - * and hyphens, the issue is moot. The "domain" portion is also escaped, though - * most domains in use on the public Internet today, like regtypes, don't contain - * any characters that need to be escaped. As DNS-SD becomes more popular, rich-text - * domains for service discovery will become common, so software should be written - * to cope with domains with escaping. - * - * For most software, these issues are transparent. When browsing, the discovered - * servicenames should simply be displayed as-is. When resolving, the discovered - * servicename/regtype/domain are simply passed unchanged to DNSServiceResolve(). - * When a DNSServiceResolve() succeeds, the returned fullname is already in - * the correct format to pass to standard system DNS APIs such as res_query(). - * For converting from servicename/regtype/domain to a single properly-escaped - * full DNS name, the helper function DNSServiceConstructFullName() is provided. - * - * The following (highly contrived) example illustrates the escaping process. - * Suppose you have an service called "Dr. Smith\Dr. Johnson", of type "_ftp._tcp" - * in subdomain "4th. Floor" of subdomain "Building 2" of domain "apple.com." - * The full (escaped) DNS name of this service's SRV record would be: - * Dr\.\032Smith\\Dr\.\032Johnson._ftp._tcp.4th\.\032Floor.Building\0322.apple.com. - */ - - -/* - * Constants for specifying an interface index - * - * Specific interface indexes are identified via a 32-bit unsigned integer returned - * by the if_nametoindex() family of calls. - * - * If the client passes 0 for interface index, that means "do the right thing", - * which (at present) means, "if the name is in an mDNS local multicast domain - * (e.g. 'local.', '254.169.in-addr.arpa.', '0.8.E.F.ip6.arpa.') then multicast - * on all applicable interfaces, otherwise send via unicast to the appropriate - * DNS server." Normally, most clients will use 0 for interface index to - * automatically get the default sensible behaviour. - * - * If the client passes a positive interface index, then for multicast names that - * indicates to do the operation only on that one interface. For unicast names the - * interface index is ignored unless kDNSServiceFlagsForceMulticast is also set. - * - * If the client passes kDNSServiceInterfaceIndexLocalOnly when registering - * a service, then that service will be found *only* by other local clients - * on the same machine that are browsing using kDNSServiceInterfaceIndexLocalOnly - * or kDNSServiceInterfaceIndexAny. - * If a client has a 'private' service, accessible only to other processes - * running on the same machine, this allows the client to advertise that service - * in a way such that it does not inadvertently appear in service lists on - * all the other machines on the network. - * - * If the client passes kDNSServiceInterfaceIndexLocalOnly when browsing - * then it will find *all* records registered on that same local machine. - * Clients explicitly wishing to discover *only* LocalOnly services can - * accomplish this by inspecting the interfaceIndex of each service reported - * to their DNSServiceBrowseReply() callback function, and discarding those - * where the interface index is not kDNSServiceInterfaceIndexLocalOnly. - */ - -#define kDNSServiceInterfaceIndexAny 0 -#define kDNSServiceInterfaceIndexLocalOnly ( (uint32_t) -1 ) - - -typedef uint32_t DNSServiceFlags; -typedef int32_t DNSServiceErrorType; - - -/********************************************************************************************* - * - * Unix Domain Socket access, DNSServiceRef deallocation, and data processing functions - * - *********************************************************************************************/ - - -/* DNSServiceRefSockFD() - * - * Access underlying Unix domain socket for an initialized DNSServiceRef. - * The DNS Service Discovery implmementation uses this socket to communicate between - * the client and the mDNSResponder daemon. The application MUST NOT directly read from - * or write to this socket. Access to the socket is provided so that it can be used as a - * run loop source, or in a select() loop: when data is available for reading on the socket, - * DNSServiceProcessResult() should be called, which will extract the daemon's reply from - * the socket, and pass it to the appropriate application callback. By using a run loop or - * select(), results from the daemon can be processed asynchronously. Without using these - * constructs, DNSServiceProcessResult() will block until the response from the daemon arrives. - * The client is responsible for ensuring that the data on the socket is processed in a timely - * fashion - the daemon may terminate its connection with a client that does not clear its - * socket buffer. - * - * sdRef: A DNSServiceRef initialized by any of the DNSService calls. - * - * return value: The DNSServiceRef's underlying socket descriptor, or -1 on - * error. - */ - -int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef); - - -/* DNSServiceProcessResult() - * - * Read a reply from the daemon, calling the appropriate application callback. This call will - * block until the daemon's response is received. Use DNSServiceRefSockFD() in - * conjunction with a run loop or select() to determine the presence of a response from the - * server before calling this function to process the reply without blocking. Call this function - * at any point if it is acceptable to block until the daemon's response arrives. Note that the - * client is responsible for ensuring that DNSServiceProcessResult() is called whenever there is - * a reply from the daemon - the daemon may terminate its connection with a client that does not - * process the daemon's responses. - * - * sdRef: A DNSServiceRef initialized by any of the DNSService calls - * that take a callback parameter. - * - * return value: Returns kDNSServiceErr_NoError on success, otherwise returns - * an error code indicating the specific failure that occurred. - */ - -DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef); - - -/* DNSServiceRefDeallocate() - * - * Terminate a connection with the daemon and free memory associated with the DNSServiceRef. - * Any services or records registered with this DNSServiceRef will be deregistered. Any - * Browse, Resolve, or Query operations called with this reference will be terminated. - * - * Note: If the reference's underlying socket is used in a run loop or select() call, it should - * be removed BEFORE DNSServiceRefDeallocate() is called, as this function closes the reference's - * socket. - * - * Note: If the reference was initialized with DNSServiceCreateConnection(), any DNSRecordRefs - * created via this reference will be invalidated by this call - the resource records are - * deregistered, and their DNSRecordRefs may not be used in subsequent functions. Similarly, - * if the reference was initialized with DNSServiceRegister, and an extra resource record was - * added to the service via DNSServiceAddRecord(), the DNSRecordRef created by the Add() call - * is invalidated when this function is called - the DNSRecordRef may not be used in subsequent - * functions. - * - * Note: This call is to be used only with the DNSServiceRef defined by this API. It is - * not compatible with dns_service_discovery_ref objects defined in the legacy Mach-based - * DNSServiceDiscovery.h API. - * - * sdRef: A DNSServiceRef initialized by any of the DNSService calls. - * - */ - -void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef); - - -/********************************************************************************************* - * - * Domain Enumeration - * - *********************************************************************************************/ - -/* DNSServiceEnumerateDomains() - * - * Asynchronously enumerate domains available for browsing and registration. - * - * The enumeration MUST be cancelled via DNSServiceRefDeallocate() when no more domains - * are to be found. - * - * Note that the names returned are (like all of DNS-SD) UTF-8 strings, - * and are escaped using standard DNS escaping rules. - * (See "Notes on DNS Name Escaping" earlier in this file for more details.) - * A graphical browser displaying a hierarchical tree-structured view should cut - * the names at the bare dots to yield individual labels, then de-escape each - * label according to the escaping rules, and then display the resulting UTF-8 text. - * - * DNSServiceDomainEnumReply Callback Parameters: - * - * sdRef: The DNSServiceRef initialized by DNSServiceEnumerateDomains(). - * - * flags: Possible values are: - * kDNSServiceFlagsMoreComing - * kDNSServiceFlagsAdd - * kDNSServiceFlagsDefault - * - * interfaceIndex: Specifies the interface on which the domain exists. (The index for a given - * interface is determined via the if_nametoindex() family of calls.) - * - * errorCode: Will be kDNSServiceErr_NoError (0) on success, otherwise indicates - * the failure that occurred (other parameters are undefined if errorCode is nonzero). - * - * replyDomain: The name of the domain. - * - * context: The context pointer passed to DNSServiceEnumerateDomains. - * - */ - -typedef void (DNSSD_API *DNSServiceDomainEnumReply) - ( - DNSServiceRef sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, - const char *replyDomain, - void *context - ); - - -/* DNSServiceEnumerateDomains() Parameters: - * - * - * sdRef: A pointer to an uninitialized DNSServiceRef. If the call succeeds - * then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError, - * and the enumeration operation will run indefinitely until the client - * terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate(). - * - * flags: Possible values are: - * kDNSServiceFlagsBrowseDomains to enumerate domains recommended for browsing. - * kDNSServiceFlagsRegistrationDomains to enumerate domains recommended - * for registration. - * - * interfaceIndex: If non-zero, specifies the interface on which to look for domains. - * (the index for a given interface is determined via the if_nametoindex() - * family of calls.) Most applications will pass 0 to enumerate domains on - * all interfaces. See "Constants for specifying an interface index" for more details. - * - * callBack: The function to be called when a domain is found or the call asynchronously - * fails. - * - * context: An application context pointer which is passed to the callback function - * (may be NULL). - * - * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous - * errors are delivered to the callback), otherwise returns an error code indicating - * the error that occurred (the callback is not invoked and the DNSServiceRef - * is not initialized.) - */ - -DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains - ( - DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceDomainEnumReply callBack, - void *context /* may be NULL */ - ); - - -/********************************************************************************************* - * - * Service Registration - * - *********************************************************************************************/ - -/* Register a service that is discovered via Browse() and Resolve() calls. - * - * - * DNSServiceRegisterReply() Callback Parameters: - * - * sdRef: The DNSServiceRef initialized by DNSServiceRegister(). - * - * flags: Currently unused, reserved for future use. - * - * errorCode: Will be kDNSServiceErr_NoError on success, otherwise will - * indicate the failure that occurred (including name conflicts, if the - * kDNSServiceFlagsNoAutoRename flag was passed to the - * callout.) Other parameters are undefined if errorCode is nonzero. - * - * name: The service name registered (if the application did not specify a name in - * DNSServiceRegister(), this indicates what name was automatically chosen). - * - * regtype: The type of service registered, as it was passed to the callout. - * - * domain: The domain on which the service was registered (if the application did not - * specify a domain in DNSServiceRegister(), this indicates the default domain - * on which the service was registered). - * - * context: The context pointer that was passed to the callout. - * - */ - -typedef void (DNSSD_API *DNSServiceRegisterReply) - ( - DNSServiceRef sdRef, - DNSServiceFlags flags, - DNSServiceErrorType errorCode, - const char *name, - const char *regtype, - const char *domain, - void *context - ); - - -/* DNSServiceRegister() Parameters: - * - * sdRef: A pointer to an uninitialized DNSServiceRef. If the call succeeds - * then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError, - * and the registration will remain active indefinitely until the client - * terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate(). - * - * interfaceIndex: If non-zero, specifies the interface on which to register the service - * (the index for a given interface is determined via the if_nametoindex() - * family of calls.) Most applications will pass 0 to register on all - * available interfaces. See "Constants for specifying an interface index" for more details. - * - * flags: Indicates the renaming behavior on name conflict (most applications - * will pass 0). See flag definitions above for details. - * - * name: If non-NULL, specifies the service name to be registered. - * Most applications will not specify a name, in which case the - * computer name is used (this name is communicated to the client via - * the callback). - * - * regtype: The service type followed by the protocol, separated by a dot - * (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp". - * New service types should be registered at htp://www.dns-sd.org/ServiceTypes.html. - * - * domain: If non-NULL, specifies the domain on which to advertise the service. - * Most applications will not specify a domain, instead automatically - * registering in the default domain(s). - * - * host: If non-NULL, specifies the SRV target host name. Most applications - * will not specify a host, instead automatically using the machine's - * default host name(s). Note that specifying a non-NULL host does NOT - * create an address record for that host - the application is responsible - * for ensuring that the appropriate address record exists, or creating it - * via DNSServiceRegisterRecord(). - * - * port: The port, in network byte order, on which the service accepts connections. - * Pass 0 for a "placeholder" service (i.e. a service that will not be discovered - * by browsing, but will cause a name conflict if another client tries to - * register that same name). Most clients will not use placeholder services. - * - * txtLen: The length of the txtRecord, in bytes. Must be zero if the txtRecord is NULL. - * - * txtRecord: The txt record rdata. May be NULL. Note that a non-NULL txtRecord - * MUST be a properly formatted DNS TXT record, i.e. - * ... - * - * callBack: The function to be called when the registration completes or asynchronously - * fails. The client MAY pass NULL for the callback - The client will NOT be notified - * of the default values picked on its behalf, and the client will NOT be notified of any - * asynchronous errors (e.g. out of memory errors, etc.) that may prevent the registration - * of the service. The client may NOT pass the NoAutoRename flag if the callback is NULL. - * The client may still deregister the service at any time via DNSServiceRefDeallocate(). - * - * context: An application context pointer which is passed to the callback function - * (may be NULL). - * - * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous - * errors are delivered to the callback), otherwise returns an error code indicating - * the error that occurred (the callback is never invoked and the DNSServiceRef - * is not initialized.) - * - */ - -DNSServiceErrorType DNSSD_API DNSServiceRegister - ( - DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *name, /* may be NULL */ - const char *regtype, - const char *domain, /* may be NULL */ - const char *host, /* may be NULL */ - uint16_t port, - uint16_t txtLen, - const void *txtRecord, /* may be NULL */ - DNSServiceRegisterReply callBack, /* may be NULL */ - void *context /* may be NULL */ - ); - - -/* DNSServiceAddRecord() - * - * Add a record to a registered service. The name of the record will be the same as the - * registered service's name. - * The record can later be updated or deregistered by passing the RecordRef initialized - * by this function to DNSServiceUpdateRecord() or DNSServiceRemoveRecord(). - * - * - * Parameters; - * - * sdRef: A DNSServiceRef initialized by DNSServiceRegister(). - * - * RecordRef: A pointer to an uninitialized DNSRecordRef. Upon succesfull completion of this - * call, this ref may be passed to DNSServiceUpdateRecord() or DNSServiceRemoveRecord(). - * If the above DNSServiceRef is passed to DNSServiceRefDeallocate(), RecordRef is also - * invalidated and may not be used further. - * - * flags: Currently ignored, reserved for future use. - * - * rrtype: The type of the record (e.g. kDNSServiceType_TXT, kDNSServiceType_SRV, etc) - * - * rdlen: The length, in bytes, of the rdata. - * - * rdata: The raw rdata to be contained in the added resource record. - * - * ttl: The time to live of the resource record, in seconds. Pass 0 to use a default value. - * - * return value: Returns kDNSServiceErr_NoError on success, otherwise returns an - * error code indicating the error that occurred (the RecordRef is not initialized). - */ - -DNSServiceErrorType DNSSD_API DNSServiceAddRecord - ( - DNSServiceRef sdRef, - DNSRecordRef *RecordRef, - DNSServiceFlags flags, - uint16_t rrtype, - uint16_t rdlen, - const void *rdata, - uint32_t ttl - ); - - -/* DNSServiceUpdateRecord - * - * Update a registered resource record. The record must either be: - * - The primary txt record of a service registered via DNSServiceRegister() - * - A record added to a registered service via DNSServiceAddRecord() - * - An individual record registered by DNSServiceRegisterRecord() - * - * - * Parameters: - * - * sdRef: A DNSServiceRef that was initialized by DNSServiceRegister() - * or DNSServiceCreateConnection(). - * - * RecordRef: A DNSRecordRef initialized by DNSServiceAddRecord, or NULL to update the - * service's primary txt record. - * - * flags: Currently ignored, reserved for future use. - * - * rdlen: The length, in bytes, of the new rdata. - * - * rdata: The new rdata to be contained in the updated resource record. - * - * ttl: The time to live of the updated resource record, in seconds. - * - * return value: Returns kDNSServiceErr_NoError on success, otherwise returns an - * error code indicating the error that occurred. - */ - -DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord - ( - DNSServiceRef sdRef, - DNSRecordRef RecordRef, /* may be NULL */ - DNSServiceFlags flags, - uint16_t rdlen, - const void *rdata, - uint32_t ttl - ); - - -/* DNSServiceRemoveRecord - * - * Remove a record previously added to a service record set via DNSServiceAddRecord(), or deregister - * an record registered individually via DNSServiceRegisterRecord(). - * - * Parameters: - * - * sdRef: A DNSServiceRef initialized by DNSServiceRegister() (if the - * record being removed was registered via DNSServiceAddRecord()) or by - * DNSServiceCreateConnection() (if the record being removed was registered via - * DNSServiceRegisterRecord()). - * - * recordRef: A DNSRecordRef initialized by a successful call to DNSServiceAddRecord() - * or DNSServiceRegisterRecord(). - * - * flags: Currently ignored, reserved for future use. - * - * return value: Returns kDNSServiceErr_NoError on success, otherwise returns an - * error code indicating the error that occurred. - */ - -DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord - ( - DNSServiceRef sdRef, - DNSRecordRef RecordRef, - DNSServiceFlags flags - ); - - -/********************************************************************************************* - * - * Service Discovery - * - *********************************************************************************************/ - -/* Browse for instances of a service. - * - * - * DNSServiceBrowseReply() Parameters: - * - * sdRef: The DNSServiceRef initialized by DNSServiceBrowse(). - * - * flags: Possible values are kDNSServiceFlagsMoreComing and kDNSServiceFlagsAdd. - * See flag definitions for details. - * - * interfaceIndex: The interface on which the service is advertised. This index should - * be passed to DNSServiceResolve() when resolving the service. - * - * errorCode: Will be kDNSServiceErr_NoError (0) on success, otherwise will - * indicate the failure that occurred. Other parameters are undefined if - * the errorCode is nonzero. - * - * serviceName: The discovered service name. This name should be displayed to the user, - * and stored for subsequent use in the DNSServiceResolve() call. - * - * regtype: The service type, which is usually (but not always) the same as was passed - * to DNSServiceBrowse(). One case where the discovered service type may - * not be the same as the requested service type is when using subtypes: - * The client may want to browse for only those ftp servers that allow - * anonymous connections. The client will pass the string "_ftp._tcp,_anon" - * to DNSServiceBrowse(), but the type of the service that's discovered - * is simply "_ftp._tcp". The regtype for each discovered service instance - * should be stored along with the name, so that it can be passed to - * DNSServiceResolve() when the service is later resolved. - * - * domain: The domain of the discovered service instance. This may or may not be the - * same as the domain that was passed to DNSServiceBrowse(). The domain for each - * discovered service instance should be stored along with the name, so that - * it can be passed to DNSServiceResolve() when the service is later resolved. - * - * context: The context pointer that was passed to the callout. - * - */ - -typedef void (DNSSD_API *DNSServiceBrowseReply) - ( - DNSServiceRef sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, - const char *serviceName, - const char *regtype, - const char *replyDomain, - void *context - ); - - -/* DNSServiceBrowse() Parameters: - * - * sdRef: A pointer to an uninitialized DNSServiceRef. If the call succeeds - * then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError, - * and the browse operation will run indefinitely until the client - * terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate(). - * - * flags: Currently ignored, reserved for future use. - * - * interfaceIndex: If non-zero, specifies the interface on which to browse for services - * (the index for a given interface is determined via the if_nametoindex() - * family of calls.) Most applications will pass 0 to browse on all available - * interfaces. See "Constants for specifying an interface index" for more details. - * - * regtype: The service type being browsed for followed by the protocol, separated by a - * dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp". - * - * domain: If non-NULL, specifies the domain on which to browse for services. - * Most applications will not specify a domain, instead browsing on the - * default domain(s). - * - * callBack: The function to be called when an instance of the service being browsed for - * is found, or if the call asynchronously fails. - * - * context: An application context pointer which is passed to the callback function - * (may be NULL). - * - * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous - * errors are delivered to the callback), otherwise returns an error code indicating - * the error that occurred (the callback is not invoked and the DNSServiceRef - * is not initialized.) - */ - -DNSServiceErrorType DNSSD_API DNSServiceBrowse - ( - DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *regtype, - const char *domain, /* may be NULL */ - DNSServiceBrowseReply callBack, - void *context /* may be NULL */ - ); - - -/* DNSServiceResolve() - * - * Resolve a service name discovered via DNSServiceBrowse() to a target host name, port number, and - * txt record. - * - * Note: Applications should NOT use DNSServiceResolve() solely for txt record monitoring - use - * DNSServiceQueryRecord() instead, as it is more efficient for this task. - * - * Note: When the desired results have been returned, the client MUST terminate the resolve by calling - * DNSServiceRefDeallocate(). - * - * Note: DNSServiceResolve() behaves correctly for typical services that have a single SRV record and - * a single TXT record (the TXT record may be empty.) To resolve non-standard services with multiple - * SRV or TXT records, DNSServiceQueryRecord() should be used. - * - * DNSServiceResolveReply Callback Parameters: - * - * sdRef: The DNSServiceRef initialized by DNSServiceResolve(). - * - * flags: Currently unused, reserved for future use. - * - * interfaceIndex: The interface on which the service was resolved. - * - * errorCode: Will be kDNSServiceErr_NoError (0) on success, otherwise will - * indicate the failure that occurred. Other parameters are undefined if - * the errorCode is nonzero. - * - * fullname: The full service domain name, in the form ... - * (This name is escaped following standard DNS rules, making it suitable for - * passing to standard system DNS APIs such as res_query(), or to the - * special-purpose functions included in this API that take fullname parameters. - * See "Notes on DNS Name Escaping" earlier in this file for more details.) - * - * hosttarget: The target hostname of the machine providing the service. This name can - * be passed to functions like gethostbyname() to identify the host's IP address. - * - * port: The port, in network byte order, on which connections are accepted for this service. - * - * txtLen: The length of the txt record, in bytes. - * - * txtRecord: The service's primary txt record, in standard txt record format. - * - - * context: The context pointer that was passed to the callout. - * - */ - -typedef void (DNSSD_API *DNSServiceResolveReply) - ( - DNSServiceRef sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, - const char *fullname, - const char *hosttarget, - uint16_t port, - uint16_t txtLen, - const char *txtRecord, - void *context - ); - - -/* DNSServiceResolve() Parameters - * - * sdRef: A pointer to an uninitialized DNSServiceRef. If the call succeeds - * then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError, - * and the resolve operation will run indefinitely until the client - * terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate(). - * - * flags: Currently ignored, reserved for future use. - * - * interfaceIndex: The interface on which to resolve the service. If this resolve call is - * as a result of a currently active DNSServiceBrowse() operation, then the - * interfaceIndex should be the index reported in the DNSServiceBrowseReply - * callback. If this resolve call is using information previously saved - * (e.g. in a preference file) for later use, then use interfaceIndex 0, because - * the desired service may now be reachable via a different physical interface. - * See "Constants for specifying an interface index" for more details. - * - * name: The name of the service instance to be resolved, as reported to the - * DNSServiceBrowseReply() callback. - * - * regtype: The type of the service instance to be resolved, as reported to the - * DNSServiceBrowseReply() callback. - * - * domain: The domain of the service instance to be resolved, as reported to the - * DNSServiceBrowseReply() callback. - * - * callBack: The function to be called when a result is found, or if the call - * asynchronously fails. - * - * context: An application context pointer which is passed to the callback function - * (may be NULL). - * - * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous - * errors are delivered to the callback), otherwise returns an error code indicating - * the error that occurred (the callback is never invoked and the DNSServiceRef - * is not initialized.) - */ - -DNSServiceErrorType DNSSD_API DNSServiceResolve - ( - DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *name, - const char *regtype, - const char *domain, - DNSServiceResolveReply callBack, - void *context /* may be NULL */ - ); - - -/********************************************************************************************* - * - * Special Purpose Calls (most applications will not use these) - * - *********************************************************************************************/ - -/* DNSServiceCreateConnection() - * - * Create a connection to the daemon allowing efficient registration of - * multiple individual records. - * - * - * Parameters: - * - * sdRef: A pointer to an uninitialized DNSServiceRef. Deallocating - * the reference (via DNSServiceRefDeallocate()) severs the - * connection and deregisters all records registered on this connection. - * - * return value: Returns kDNSServiceErr_NoError on success, otherwise returns - * an error code indicating the specific failure that occurred (in which - * case the DNSServiceRef is not initialized). - */ - -DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef); - - -/* DNSServiceRegisterRecord - * - * Register an individual resource record on a connected DNSServiceRef. - * - * Note that name conflicts occurring for records registered via this call must be handled - * by the client in the callback. - * - * - * DNSServiceRegisterRecordReply() parameters: - * - * sdRef: The connected DNSServiceRef initialized by - * DNSServiceDiscoveryConnect(). - * - * RecordRef: The DNSRecordRef initialized by DNSServiceRegisterRecord(). If the above - * DNSServiceRef is passed to DNSServiceRefDeallocate(), this DNSRecordRef is - * invalidated, and may not be used further. - * - * flags: Currently unused, reserved for future use. - * - * errorCode: Will be kDNSServiceErr_NoError on success, otherwise will - * indicate the failure that occurred (including name conflicts.) - * Other parameters are undefined if errorCode is nonzero. - * - * context: The context pointer that was passed to the callout. - * - */ - - typedef void (DNSSD_API *DNSServiceRegisterRecordReply) - ( - DNSServiceRef sdRef, - DNSRecordRef RecordRef, - DNSServiceFlags flags, - DNSServiceErrorType errorCode, - void *context - ); - - -/* DNSServiceRegisterRecord() Parameters: - * - * sdRef: A DNSServiceRef initialized by DNSServiceCreateConnection(). - * - * RecordRef: A pointer to an uninitialized DNSRecordRef. Upon succesfull completion of this - * call, this ref may be passed to DNSServiceUpdateRecord() or DNSServiceRemoveRecord(). - * (To deregister ALL records registered on a single connected DNSServiceRef - * and deallocate each of their corresponding DNSServiceRecordRefs, call - * DNSServiceRefDealloocate()). - * - * flags: Possible values are kDNSServiceFlagsShared or kDNSServiceFlagsUnique - * (see flag type definitions for details). - * - * interfaceIndex: If non-zero, specifies the interface on which to register the record - * (the index for a given interface is determined via the if_nametoindex() - * family of calls.) Passing 0 causes the record to be registered on all interfaces. - * See "Constants for specifying an interface index" for more details. - * - * fullname: The full domain name of the resource record. - * - * rrtype: The numerical type of the resource record (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc) - * - * rrclass: The class of the resource record (usually kDNSServiceClass_IN) - * - * rdlen: Length, in bytes, of the rdata. - * - * rdata: A pointer to the raw rdata, as it is to appear in the DNS record. - * - * ttl: The time to live of the resource record, in seconds. Pass 0 to use a default value. - * - * callBack: The function to be called when a result is found, or if the call - * asynchronously fails (e.g. because of a name conflict.) - * - * context: An application context pointer which is passed to the callback function - * (may be NULL). - * - * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous - * errors are delivered to the callback), otherwise returns an error code indicating - * the error that occurred (the callback is never invoked and the DNSRecordRef is - * not initialized.) - */ - -DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord - ( - DNSServiceRef sdRef, - DNSRecordRef *RecordRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *fullname, - uint16_t rrtype, - uint16_t rrclass, - uint16_t rdlen, - const void *rdata, - uint32_t ttl, - DNSServiceRegisterRecordReply callBack, - void *context /* may be NULL */ - ); - - -/* DNSServiceQueryRecord - * - * Query for an arbitrary DNS record. - * - * - * DNSServiceQueryRecordReply() Callback Parameters: - * - * sdRef: The DNSServiceRef initialized by DNSServiceQueryRecord(). - * - * flags: Possible values are kDNSServiceFlagsMoreComing and - * kDNSServiceFlagsAdd. The Add flag is NOT set for PTR records - * with a ttl of 0, i.e. "Remove" events. - * - * interfaceIndex: The interface on which the query was resolved (the index for a given - * interface is determined via the if_nametoindex() family of calls). - * See "Constants for specifying an interface index" for more details. - * - * errorCode: Will be kDNSServiceErr_NoError on success, otherwise will - * indicate the failure that occurred. Other parameters are undefined if - * errorCode is nonzero. - * - * fullname: The resource record's full domain name. - * - * rrtype: The resource record's type (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc) - * - * rrclass: The class of the resource record (usually kDNSServiceClass_IN). - * - * rdlen: The length, in bytes, of the resource record rdata. - * - * rdata: The raw rdata of the resource record. - * - * ttl: The resource record's time to live, in seconds. - * - * context: The context pointer that was passed to the callout. - * - */ - -typedef void (DNSSD_API *DNSServiceQueryRecordReply) - ( - DNSServiceRef DNSServiceRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, - const char *fullname, - uint16_t rrtype, - uint16_t rrclass, - uint16_t rdlen, - const void *rdata, - uint32_t ttl, - void *context - ); - - -/* DNSServiceQueryRecord() Parameters: - * - * sdRef: A pointer to an uninitialized DNSServiceRef. If the call succeeds - * then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError, - * and the query operation will run indefinitely until the client - * terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate(). - * - * flags: Pass kDNSServiceFlagsLongLivedQuery to create a "long-lived" unicast - * query in a non-local domain. Without setting this flag, unicast queries - * will be one-shot - that is, only answers available at the time of the call - * will be returned. By setting this flag, answers (including Add and Remove - * events) that become available after the initial call is made will generate - * callbacks. This flag has no effect on link-local multicast queries. - * - * interfaceIndex: If non-zero, specifies the interface on which to issue the query - * (the index for a given interface is determined via the if_nametoindex() - * family of calls.) Passing 0 causes the name to be queried for on all - * interfaces. See "Constants for specifying an interface index" for more details. - * - * fullname: The full domain name of the resource record to be queried for. - * - * rrtype: The numerical type of the resource record to be queried for - * (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc) - * - * rrclass: The class of the resource record (usually kDNSServiceClass_IN). - * - * callBack: The function to be called when a result is found, or if the call - * asynchronously fails. - * - * context: An application context pointer which is passed to the callback function - * (may be NULL). - * - * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous - * errors are delivered to the callback), otherwise returns an error code indicating - * the error that occurred (the callback is never invoked and the DNSServiceRef - * is not initialized.) - */ - -DNSServiceErrorType DNSSD_API DNSServiceQueryRecord - ( - DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *fullname, - uint16_t rrtype, - uint16_t rrclass, - DNSServiceQueryRecordReply callBack, - void *context /* may be NULL */ - ); - - -/* DNSServiceReconfirmRecord - * - * Instruct the daemon to verify the validity of a resource record that appears to - * be out of date (e.g. because tcp connection to a service's target failed.) - * Causes the record to be flushed from the daemon's cache (as well as all other - * daemons' caches on the network) if the record is determined to be invalid. - * - * Parameters: - * - * flags: Currently unused, reserved for future use. - * - * interfaceIndex: If non-zero, specifies the interface of the record in question. - * Passing 0 causes all instances of this record to be reconfirmed. - * - * fullname: The resource record's full domain name. - * - * rrtype: The resource record's type (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc) - * - * rrclass: The class of the resource record (usually kDNSServiceClass_IN). - * - * rdlen: The length, in bytes, of the resource record rdata. - * - * rdata: The raw rdata of the resource record. - * - */ - -void DNSSD_API DNSServiceReconfirmRecord - ( - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *fullname, - uint16_t rrtype, - uint16_t rrclass, - uint16_t rdlen, - const void *rdata - ); - - -/********************************************************************************************* - * - * General Utility Functions - * - *********************************************************************************************/ - -/* DNSServiceConstructFullName() - * - * Concatenate a three-part domain name (as returned by the above callbacks) into a - * properly-escaped full domain name. Note that callbacks in the above functions ALREADY ESCAPE - * strings where necessary. - * - * Parameters: - * - * fullName: A pointer to a buffer that where the resulting full domain name is to be written. - * The buffer must be kDNSServiceMaxDomainName (1005) bytes in length to - * accommodate the longest legal domain name without buffer overrun. - * - * service: The service name - any dots or slashes must NOT be escaped. - * May be NULL (to construct a PTR record name, e.g. - * "_ftp._tcp.apple.com"). - * - * regtype: The service type followed by the protocol, separated by a dot - * (e.g. "_ftp._tcp"). - * - * domain: The domain name, e.g. "apple.com.". Literal dots or backslashes, - * if any, must be escaped, e.g. "1st\. Floor.apple.com." - * - * return value: Returns 0 on success, -1 on error. - * - */ - -int DNSSD_API DNSServiceConstructFullName - ( - char *fullName, - const char *service, /* may be NULL */ - const char *regtype, - const char *domain - ); - - -/********************************************************************************************* - * - * TXT Record Construction Functions - * - *********************************************************************************************/ - -/* - * A typical calling sequence for TXT record construction is something like: - * - * Client allocates storage for TXTRecord data (e.g. declare buffer on the stack) - * TXTRecordCreate(); - * TXTRecordSetValue(); - * TXTRecordSetValue(); - * TXTRecordSetValue(); - * ... - * DNSServiceRegister( ... TXTRecordGetLength(), TXTRecordGetBytesPtr() ... ); - * TXTRecordDeallocate(); - * Explicitly deallocate storage for TXTRecord data (if not allocated on the stack) - */ - - -/* TXTRecordRef - * - * Opaque internal data type. - * Note: Represents a DNS-SD TXT record. - */ - -typedef struct _TXTRecordRef_t { char privatedata[16]; } TXTRecordRef; - - -/* TXTRecordCreate() - * - * Creates a new empty TXTRecordRef referencing the specified storage. - * - * If the buffer parameter is NULL, or the specified storage size is not - * large enough to hold a key subsequently added using TXTRecordSetValue(), - * then additional memory will be added as needed using malloc(). - * - * On some platforms, when memory is low, malloc() may fail. In this - * case, TXTRecordSetValue() will return kDNSServiceErr_NoMemory, and this - * error condition will need to be handled as appropriate by the caller. - * - * You can avoid the need to handle this error condition if you ensure - * that the storage you initially provide is large enough to hold all - * the key/value pairs that are to be added to the record. - * The caller can precompute the exact length required for all of the - * key/value pairs to be added, or simply provide a fixed-sized buffer - * known in advance to be large enough. - * A no-value (key-only) key requires (1 + key length) bytes. - * A key with empty value requires (1 + key length + 1) bytes. - * A key with non-empty value requires (1 + key length + 1 + value length). - * For most applications, DNS-SD TXT records are generally - * less than 100 bytes, so in most cases a simple fixed-sized - * 256-byte buffer will be more than sufficient. - * Recommended size limits for DNS-SD TXT Records are discussed in - * - * - * Note: When passing parameters to and from these TXT record APIs, - * the key name does not include the '=' character. The '=' character - * is the separator between the key and value in the on-the-wire - * packet format; it is not part of either the key or the value. - * - * txtRecord: A pointer to an uninitialized TXTRecordRef. - * - * bufferLen: The size of the storage provided in the "buffer" parameter. - * - * buffer: The storage used to hold the TXTRecord data. - * This storage must remain valid for as long as - * the TXTRecordRef. - */ - -void DNSSD_API TXTRecordCreate - ( - TXTRecordRef *txtRecord, - uint16_t bufferLen, - void *buffer - ); - - -/* TXTRecordDeallocate() - * - * Releases any resources allocated in the course of preparing a TXT Record - * using TXTRecordCreate()/TXTRecordSetValue()/TXTRecordRemoveValue(). - * Ownership of the buffer provided in TXTRecordCreate() returns to the client. - * - * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate(). - * - */ - -void DNSSD_API TXTRecordDeallocate - ( - TXTRecordRef *txtRecord - ); - - -/* TXTRecordSetValue() - * - * Adds a key (optionally with value) to a TXTRecordRef. If the "key" already - * exists in the TXTRecordRef, then the current value will be replaced with - * the new value. - * Keys may exist in four states with respect to a given TXT record: - * - Absent (key does not appear at all) - * - Present with no value ("key" appears alone) - * - Present with empty value ("key=" appears in TXT record) - * - Present with non-empty value ("key=value" appears in TXT record) - * For more details refer to "Data Syntax for DNS-SD TXT Records" in - * - * - * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate(). - * - * key: A null-terminated string which only contains printable ASCII - * values (0x20-0x7E), excluding '=' (0x3D). Keys should be - * 8 characters or less (not counting the terminating null). - * - * valueSize: The size of the value. - * - * value: Any binary value. For values that represent - * textual data, UTF-8 is STRONGLY recommended. - * For values that represent textual data, valueSize - * should NOT include the terminating null (if any) - * at the end of the string. - * If NULL, then "key" will be added with no value. - * If non-NULL but valueSize is zero, then "key=" will be - * added with empty value. - * - * return value: Returns kDNSServiceErr_NoError on success. - * Returns kDNSServiceErr_Invalid if the "key" string contains - * illegal characters. - * Returns kDNSServiceErr_NoMemory if adding this key would - * exceed the available storage. - */ - -DNSServiceErrorType DNSSD_API TXTRecordSetValue - ( - TXTRecordRef *txtRecord, - const char *key, - uint8_t valueSize, /* may be zero */ - const void *value /* may be NULL */ - ); - - -/* TXTRecordRemoveValue() - * - * Removes a key from a TXTRecordRef. The "key" must be an - * ASCII string which exists in the TXTRecordRef. - * - * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate(). - * - * key: A key name which exists in the TXTRecordRef. - * - * return value: Returns kDNSServiceErr_NoError on success. - * Returns kDNSServiceErr_NoSuchKey if the "key" does not - * exist in the TXTRecordRef. - * - */ - -DNSServiceErrorType DNSSD_API TXTRecordRemoveValue - ( - TXTRecordRef *txtRecord, - const char *key - ); - - -/* TXTRecordGetLength() - * - * Allows you to determine the length of the raw bytes within a TXTRecordRef. - * - * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate(). - * - * return value: Returns the size of the raw bytes inside a TXTRecordRef - * which you can pass directly to DNSServiceRegister() or - * to DNSServiceUpdateRecord(). - * Returns 0 if the TXTRecordRef is empty. - * - */ - -uint16_t DNSSD_API TXTRecordGetLength - ( - const TXTRecordRef *txtRecord - ); - - -/* TXTRecordGetBytesPtr() - * - * Allows you to retrieve a pointer to the raw bytes within a TXTRecordRef. - * - * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate(). - * - * return value: Returns a pointer to the raw bytes inside the TXTRecordRef - * which you can pass directly to DNSServiceRegister() or - * to DNSServiceUpdateRecord(). - * - */ - -const void * DNSSD_API TXTRecordGetBytesPtr - ( - const TXTRecordRef *txtRecord - ); - - -/********************************************************************************************* - * - * TXT Record Parsing Functions - * - *********************************************************************************************/ - -/* - * A typical calling sequence for TXT record parsing is something like: - * - * Receive TXT record data in DNSServiceResolve() callback - * if (TXTRecordContainsKey(txtLen, txtRecord, "key")) then do something - * val1ptr = TXTRecordGetValuePtr(txtLen, txtRecord, "key1", &len1); - * val2ptr = TXTRecordGetValuePtr(txtLen, txtRecord, "key2", &len2); - * ... - * bcopy(val1ptr, myval1, len1); - * bcopy(val2ptr, myval2, len2); - * ... - * return; - * - * If you wish to retain the values after return from the DNSServiceResolve() - * callback, then you need to copy the data to your own storage using bcopy() - * or similar, as shown in the example above. - * - * If for some reason you need to parse a TXT record you built yourself - * using the TXT record construction functions above, then you can do - * that using TXTRecordGetLength and TXTRecordGetBytesPtr calls: - * TXTRecordGetValue(TXTRecordGetLength(x), TXTRecordGetBytesPtr(x), key, &len); - * - * Most applications only fetch keys they know about from a TXT record and - * ignore the rest. - * However, some debugging tools wish to fetch and display all keys. - * To do that, use the TXTRecordGetCount() and TXTRecordGetItemAtIndex() calls. - */ - -/* TXTRecordContainsKey() - * - * Allows you to determine if a given TXT Record contains a specified key. - * - * txtLen: The size of the received TXT Record. - * - * txtRecord: Pointer to the received TXT Record bytes. - * - * key: A null-terminated ASCII string containing the key name. - * - * return value: Returns 1 if the TXT Record contains the specified key. - * Otherwise, it returns 0. - * - */ - -int DNSSD_API TXTRecordContainsKey - ( - uint16_t txtLen, - const void *txtRecord, - const char *key - ); - - -/* TXTRecordGetValuePtr() - * - * Allows you to retrieve the value for a given key from a TXT Record. - * - * txtLen: The size of the received TXT Record - * - * txtRecord: Pointer to the received TXT Record bytes. - * - * key: A null-terminated ASCII string containing the key name. - * - * valueLen: On output, will be set to the size of the "value" data. - * - * return value: Returns NULL if the key does not exist in this TXT record, - * or exists with no value (to differentiate between - * these two cases use TXTRecordContainsKey()). - * Returns pointer to location within TXT Record bytes - * if the key exists with empty or non-empty value. - * For empty value, valueLen will be zero. - * For non-empty value, valueLen will be length of value data. - */ - -const void * DNSSD_API TXTRecordGetValuePtr - ( - uint16_t txtLen, - const void *txtRecord, - const char *key, - uint8_t *valueLen - ); - - -/* TXTRecordGetCount() - * - * Returns the number of keys stored in the TXT Record. The count - * can be used with TXTRecordGetItemAtIndex() to iterate through the keys. - * - * txtLen: The size of the received TXT Record. - * - * txtRecord: Pointer to the received TXT Record bytes. - * - * return value: Returns the total number of keys in the TXT Record. - * - */ - -uint16_t DNSSD_API TXTRecordGetCount - ( - uint16_t txtLen, - const void *txtRecord - ); - - -/* TXTRecordGetItemAtIndex() - * - * Allows you to retrieve a key name and value pointer, given an index into - * a TXT Record. Legal index values range from zero to TXTRecordGetCount()-1. - * It's also possible to iterate through keys in a TXT record by simply - * calling TXTRecordGetItemAtIndex() repeatedly, beginning with index zero - * and increasing until TXTRecordGetItemAtIndex() returns kDNSServiceErr_Invalid. - * - * On return: - * For keys with no value, *value is set to NULL and *valueLen is zero. - * For keys with empty value, *value is non-NULL and *valueLen is zero. - * For keys with non-empty value, *value is non-NULL and *valueLen is non-zero. - * - * txtLen: The size of the received TXT Record. - * - * txtRecord: Pointer to the received TXT Record bytes. - * - * index: An index into the TXT Record. - * - * keyBufLen: The size of the string buffer being supplied. - * - * key: A string buffer used to store the key name. - * On return, the buffer contains a null-terminated C string - * giving the key name. DNS-SD TXT keys are usually - * 8 characters or less. To hold the maximum possible - * key name, the buffer should be 256 bytes long. - * - * valueLen: On output, will be set to the size of the "value" data. - * - * value: On output, *value is set to point to location within TXT - * Record bytes that holds the value data. - * - * return value: Returns kDNSServiceErr_NoError on success. - * Returns kDNSServiceErr_NoMemory if keyBufLen is too short. - * Returns kDNSServiceErr_Invalid if index is greater than - * TXTRecordGetCount()-1. - */ - -DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex - ( - uint16_t txtLen, - const void *txtRecord, - uint16_t index, - uint16_t keyBufLen, - char *key, - uint8_t *valueLen, - const void **value - ); - -#ifdef __APPLE_API_PRIVATE - -/* - * Mac OS X specific functionality - * 3rd party clients of this API should not depend on future support or availability of this routine - */ - -/* DNSServiceSetDefaultDomainForUser() - * - * Set the default domain for the caller's UID. Future browse and registration - * calls by this user that do not specify an explicit domain will browse and - * register in this wide-area domain in addition to .local. In addition, this - * domain will be returned as a Browse domain via domain enumeration calls. - * - * - * Parameters: - * - * flags: Pass kDNSServiceFlagsAdd to add a domain for a user. Call without - * this flag set to clear a previously added domain. - * - * domain: The domain to be used for the caller's UID. - * - * return value: Returns kDNSServiceErr_NoError on succeses, otherwise returns - * an error code indicating the error that occurred - */ - -DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser - ( - DNSServiceFlags flags, - const char *domain - ); - -#endif //__APPLE_API_PRIVATE - -#ifdef __cplusplus - } -#endif - -#endif /* _DNS_SD_H */ diff --git a/mdns.subproj/dnssd_clientlib.c b/mdns.subproj/dnssd_clientlib.c deleted file mode 100755 index d3c36ad..0000000 --- a/mdns.subproj/dnssd_clientlib.c +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * 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 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: dnssd_clientlib.c,v $ -Revision 1.3 2004/09/16 23:45:23 majka -Integrated 3775315 and 3765280. - -Revision 1.2.16.1 2004/09/02 19:43:41 ksekar -: Sync dns-sd client files between Libinfo and -mDNSResponder projects - -Revision 1.7 2004/06/26 03:16:34 shersche -clean up warning messages on Win32 platform - -Submitted by: herscher - -Revision 1.6 2004/06/12 01:09:45 cheshire -To be callable from the broadest range of clients on Windows (e.g. Visual Basic, C#, etc.) -API routines have to be declared as "__stdcall", instead of the C default, "__cdecl" - -Revision 1.5 2004/05/25 18:29:33 cheshire -Move DNSServiceConstructFullName() from dnssd_clientstub.c to dnssd_clientlib.c, -so that it's also accessible to dnssd_clientshim.c (single address space) clients. - -Revision 1.4 2004/05/25 17:08:55 cheshire -Fix compiler warning (doesn't make sense for function return type to be const) - -Revision 1.3 2004/05/21 21:41:35 cheshire -Add TXT record building and parsing APIs - -Revision 1.2 2004/05/20 22:22:21 cheshire -Enable code that was bracketed by "#if 0" - -Revision 1.1 2004/03/12 21:30:29 cheshire -Build a System-Context Shared Library from mDNSCore, for the benefit of developers -like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code. - - */ - -#include -#include - -#include "dns_sd.h" - -#if MDNS_BUILDINGSHAREDLIBRARY || MDNS_BUILDINGSTUBLIBRARY -#pragma export on -#endif - -#if defined(_WIN32) -// disable warning "conversion from to uint16_t" -#pragma warning(disable:4244) -#endif - -/********************************************************************************************* - * - * Supporting Functions - * - *********************************************************************************************/ - -#define mdnsIsDigit(X) ((X) >= '0' && (X) <= '9') - -static int DomainEndsInDot(const char *dom) - { - while (dom[0] && dom[1]) - { - if (dom[0] == '\\') // advance past escaped byte sequence - { - if (mdnsIsDigit(dom[1]) && mdnsIsDigit(dom[2]) && mdnsIsDigit(dom[3])) - dom += 4; // If "\ddd" then skip four - else dom += 2; // else if "\x" then skip two - } - else dom++; // else goto next character - } - return (dom[0] == '.'); - } - -static uint8_t *InternalTXTRecordSearch - ( - uint16_t txtLen, - const void *txtRecord, - const char *key, - unsigned long *keylen - ) - { - uint8_t *p = (uint8_t*)txtRecord; - uint8_t *e = p + txtLen; - *keylen = (unsigned long) strlen(key); - while (pbuffer = buffer; - txtRec->buflen = buffer ? bufferLen : (uint16_t)0; - txtRec->datalen = 0; - txtRec->malloced = 0; - } - -void TXTRecordDeallocate(TXTRecordRef *txtRecord) - { - if (txtRec->malloced) free(txtRec->buffer); - } - -DNSServiceErrorType TXTRecordSetValue - ( - TXTRecordRef *txtRecord, - const char *key, - uint8_t valueSize, - const void *value - ) - { - uint8_t *start, *p; - const char *k; - unsigned long keysize, keyvalsize; - - for (k = key; *k; k++) if (*k < 0x20 || *k > 0x7E || *k == '=') return(kDNSServiceErr_Invalid); - keysize = (unsigned long)(k - key); - keyvalsize = 1 + keysize + (value ? (1 + valueSize) : 0); - if (keysize < 1 || keyvalsize > 255) return(kDNSServiceErr_Invalid); - (void)TXTRecordRemoveValue(txtRecord, key); - if (txtRec->datalen + keyvalsize > txtRec->buflen) - { - unsigned char *newbuf; - unsigned long newlen = txtRec->datalen + keyvalsize; - if (newlen > 0xFFFF) return(kDNSServiceErr_Invalid); - newbuf = malloc((size_t)newlen); - if (!newbuf) return(kDNSServiceErr_NoMemory); - memcpy(newbuf, txtRec->buffer, txtRec->datalen); - if (txtRec->malloced) free(txtRec->buffer); - txtRec->buffer = newbuf; - txtRec->buflen = (uint16_t)(newlen); - txtRec->malloced = 1; - } - start = txtRec->buffer + txtRec->datalen; - p = start + 1; - memcpy(p, key, keysize); - p += keysize; - if (value) - { - *p++ = '='; - memcpy(p, value, valueSize); - p += valueSize; - } - *start = (uint8_t)(p - start - 1); - txtRec->datalen += p - start; - return(kDNSServiceErr_NoError); - } - -DNSServiceErrorType TXTRecordRemoveValue - ( - TXTRecordRef *txtRecord, - const char *key - ) - { - unsigned long keylen, itemlen, remainder; - uint8_t *item = InternalTXTRecordSearch(txtRec->datalen, txtRec->buffer, key, &keylen); - if (!item) return(kDNSServiceErr_NoSuchKey); - itemlen = (unsigned long)(1 + item[0]); - remainder = (unsigned long)((txtRec->buffer + txtRec->datalen) - (item + itemlen)); - // Use memmove because memcpy behaviour is undefined for overlapping regions - memmove(item, item + itemlen, remainder); - txtRec->datalen -= itemlen; - return(kDNSServiceErr_NoError); - } - -uint16_t TXTRecordGetLength (const TXTRecordRef *txtRecord) { return(txtRec->datalen); } -const void * TXTRecordGetBytesPtr(const TXTRecordRef *txtRecord) { return(txtRec->buffer); } - -/********************************************************************************************* - * - * TXT Record Parsing Functions - * - *********************************************************************************************/ - -int TXTRecordContainsKey - ( - uint16_t txtLen, - const void *txtRecord, - const char *key - ) - { - unsigned long keylen; - return (InternalTXTRecordSearch(txtLen, txtRecord, key, &keylen) ? 1 : 0); - } - -const void * TXTRecordGetValuePtr - ( - uint16_t txtLen, - const void *txtRecord, - const char *key, - uint8_t *valueLen - ) - { - unsigned long keylen; - uint8_t *item = InternalTXTRecordSearch(txtLen, txtRecord, key, &keylen); - if (!item || item[0] <= keylen) return(NULL); // If key not found, or found with no value, return NULL - *valueLen = (uint8_t)(item[0] - (keylen + 1)); - return (item + 1 + keylen + 1); - } - -uint16_t TXTRecordGetCount - ( - uint16_t txtLen, - const void *txtRecord - ) - { - uint16_t count = 0; - uint8_t *p = (uint8_t*)txtRecord; - uint8_t *e = p + txtLen; - while (pe) ? (uint16_t)0 : count); - } - -DNSServiceErrorType TXTRecordGetItemAtIndex - ( - uint16_t txtLen, - const void *txtRecord, - uint16_t index, - uint16_t keyBufLen, - char *key, - uint8_t *valueLen, - const void **value - ) - { - uint16_t count = 0; - uint8_t *p = (uint8_t*)txtRecord; - uint8_t *e = p + txtLen; - while (p= keyBufLen) return(kDNSServiceErr_NoMemory); - memcpy(key, x, len); - key[len] = 0; - if (x+len Socket-based APIs aren't endian-safe - -Revision 1.16 2004/09/17 20:19:00 majka -Integrated 3804522 - -Revision 1.15.2.1 2004/09/17 20:15:30 ksekar -*** empty log message *** - -Revision 1.15 2004/09/16 23:45:24 majka -Integrated 3775315 and 3765280. - -Revision 1.14.4.1 2004/09/02 19:43:41 ksekar -: Sync dns-sd client files between Libinfo and -mDNSResponder projects - -Revision 1.28 2004/08/11 17:10:04 cheshire -Fix signed/unsigned warnings - -Revision 1.27 2004/08/11 00:54:16 cheshire -Change "hdr->op.request_op" to just "hdr->op" - -Revision 1.26 2004/07/26 06:07:27 shersche -fix bugs when using an error socket to communicate with the daemon - -Revision 1.25 2004/07/26 05:54:02 shersche -DNSServiceProcessResult() returns NoError if socket read returns EWOULDBLOCK - -Revision 1.24 2004/07/20 06:46:21 shersche - fix endless loop in my_read() if recv returns 0 -Bug #: 3730123 - -Revision 1.23 2004/06/29 00:48:38 cheshire -Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; -use an explicit while() loop instead. - -Revision 1.22 2004/06/26 03:16:34 shersche -clean up warning messages on Win32 platform - -Submitted by: herscher - -Revision 1.21 2004/06/18 04:53:56 rpantos -Use platform layer for socket types. Introduce USE_TCP_LOOPBACK. Remove dependency on mDNSClientAPI.h. - -Revision 1.20 2004/06/12 00:50:22 cheshire -Changes for Windows compatibility - -Revision 1.19 2004/05/25 18:29:33 cheshire -Move DNSServiceConstructFullName() from dnssd_clientstub.c to dnssd_clientlib.c, -so that it's also accessible to dnssd_clientshim.c (single address space) clients. - -Revision 1.18 2004/05/18 23:51:27 cheshire -Tidy up all checkin comments to use consistent "" format for bug numbers - -Revision 1.17 2004/05/06 18:42:58 ksekar -General dns_sd.h API cleanup, including the following radars: -: Remove flags with zero value -: Passing in NULL causes a crash. - -Revision 1.16 2004/03/12 22:00:37 cheshire -Added: #include - -Revision 1.15 2004/01/20 18:36:29 ksekar -Propagated Libinfo fix for : SU: -DNSServiceUpdateRecord() doesn't allow you to update the TXT record -into TOT mDNSResponder. - -Revision 1.14 2004/01/19 22:39:17 cheshire -Don't use "MSG_WAITALL"; it makes send() return "Invalid argument" on Linux; -use an explicit while() loop instead. (In any case, this should only make a difference -with non-blocking sockets, which we don't use on the client side right now.) - -Revision 1.13 2004/01/19 21:46:52 cheshire -Fix compiler warning - -Revision 1.12 2003/12/23 20:46:47 ksekar -: sync dnssd files between libinfo & mDNSResponder - -Revision 1.11 2003/12/08 21:11:42 rpantos -Changes necessary to support mDNSResponder on Linux. - -Revision 1.10 2003/10/13 23:50:53 ksekar -Updated dns_sd clientstub files to bring copies in synch with -top-of-tree Libinfo: A memory leak in dnssd_clientstub.c is fixed, -and comments in dns_sd.h are improved. - -Revision 1.9 2003/08/15 21:30:39 cheshire -Bring up to date with LibInfo version - -Revision 1.8 2003/08/13 23:54:52 ksekar -Bringing dnssd_clientstub.c up to date with Libinfo, per radar 3376640 - -Revision 1.7 2003/08/12 19:56:25 cheshire -Update to APSL 2.0 - - */ - -#include -#include -#if defined(_WIN32) -#include -#include -#define sockaddr_mdns sockaddr_in -#define AF_MDNS AF_INET -#else -#include -#include -#define sockaddr_mdns sockaddr_un -#define AF_MDNS AF_LOCAL -#endif - -#include "dnssd_ipc.h" - -#if defined(_WIN32) -// disable warning: "'type cast' : from data pointer 'void *' to -// function pointer" -#pragma warning(disable:4055) - -// disable warning: "nonstandard extension, function/data pointer -// conversion in expression" -#pragma warning(disable:4152) - -#define sleep(X) Sleep((X) * 1000) - -static int g_initWinsock = 0; -#endif - - -#define CTL_PATH_PREFIX "/tmp/dnssd_clippath." -// error socket (if needed) is named "dnssd_clipath.[pid].xxx:n" where xxx are the -// last 3 digits of the time (in seconds) and n is the 6-digit microsecond time - -// general utility functions -typedef struct _DNSServiceRef_t - { - dnssd_sock_t sockfd; // connected socket between client and daemon - uint32_t op; // request_op_t or reply_op_t - process_reply_callback process_reply; - void *app_callback; - void *app_context; - uint32_t max_index; //largest assigned record index - 0 if no additl. recs registered - } _DNSServiceRef_t; - -typedef struct _DNSRecordRef_t - { - void *app_context; - DNSServiceRegisterRecordReply app_callback; - DNSRecordRef recref; - uint32_t record_index; // index is unique to the ServiceDiscoveryRef - DNSServiceRef sdr; - } _DNSRecordRef_t; - -// exported functions - -// write len bytes. return 0 on success, -1 on error -static int my_write(dnssd_sock_t sd, char *buf, int len) - { - // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; use an explicit while() loop instead. - //if (send(sd, buf, len, MSG_WAITALL) != len) return -1; - while (len) - { - ssize_t num_written = send(sd, buf, len, 0); - if (num_written < 0 || num_written > len) return -1; - buf += num_written; - len -= num_written; - } - return 0; - } - -// read len bytes. return 0 on success, -1 on error -static int my_read(dnssd_sock_t sd, char *buf, int len) - { - // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; use an explicit while() loop instead. - //if (recv(sd, buf, len, MSG_WAITALL) != len) return -1; - while (len) - { - ssize_t num_read = recv(sd, buf, len, 0); - if ((num_read == 0) || (num_read < 0) || (num_read > len)) return -1; - buf += num_read; - len -= num_read; - } - return 0; - } - -/* create_hdr - * - * allocate and initialize an ipc message header. value of len should initially be the - * length of the data, and is set to the value of the data plus the header. data_start - * is set to point to the beginning of the data section. reuse_socket should be non-zero - * for calls that can receive an immediate error return value on their primary socket. - * if zero, the path to a control socket is appended at the beginning of the message buffer. - * data_start is set past this string. - */ - -static ipc_msg_hdr *create_hdr(uint32_t op, size_t *len, char **data_start, int reuse_socket) - { - char *msg = NULL; - ipc_msg_hdr *hdr; - int datalen; - char ctrl_path[256]; - - if (!reuse_socket) - { -#if defined(USE_TCP_LOOPBACK) - *len += 2; // Allocate space for two-byte port number -#else - struct timeval time; - if (gettimeofday(&time, NULL) < 0) return NULL; - sprintf(ctrl_path, "%s%d-%.3lx-%.6lu", CTL_PATH_PREFIX, (int)getpid(), - (unsigned long)(time.tv_sec & 0xFFF), (unsigned long)(time.tv_usec)); - *len += strlen(ctrl_path) + 1; -#endif - } - - datalen = (int) *len; - *len += sizeof(ipc_msg_hdr); - - // write message to buffer - msg = malloc(*len); - if (!msg) return NULL; - - bzero(msg, *len); - hdr = (void *)msg; - hdr->datalen = datalen; - hdr->version = VERSION; - hdr->op = op; - if (reuse_socket) hdr->flags |= IPC_FLAGS_REUSE_SOCKET; - *data_start = msg + sizeof(ipc_msg_hdr); -#if defined(USE_TCP_LOOPBACK) - // Put dummy data in for the port, since we don't know what - // it is yet. The data will get filled in before we - // send the message. This happens in deliver_request(). - if (!reuse_socket) put_short(0, data_start); -#else - if (!reuse_socket) put_string(ctrl_path, data_start); -#endif - return hdr; - } - - // return a connected service ref (deallocate with DNSServiceRefDeallocate) -static DNSServiceRef connect_to_server(void) - { - dnssd_sockaddr_t saddr; - DNSServiceRef sdr; - static unsigned int NumTries = 0; - -#if defined(_WIN32) - if (!g_initWinsock) - { - WSADATA wsaData; - DNSServiceErrorType err; - - g_initWinsock = 1; - - err = WSAStartup( MAKEWORD( 2, 2 ), &wsaData ); - - if (err != 0) return NULL; - } -#endif - - sdr = malloc(sizeof(_DNSServiceRef_t)); - if (!sdr) return(NULL); - sdr->sockfd = socket(AF_DNSSD, SOCK_STREAM, 0); - if (sdr->sockfd == dnssd_InvalidSocket) { free(sdr); return NULL; } -#if defined(USE_TCP_LOOPBACK) - saddr.sin_family = AF_INET; - saddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR); - saddr.sin_port = htons(MDNS_TCP_SERVERPORT); -#else - saddr.sun_family = AF_LOCAL; - strcpy(saddr.sun_path, MDNS_UDS_SERVERPATH); -#endif - while (1) - { - int err = connect(sdr->sockfd, (struct sockaddr *) &saddr, sizeof(saddr)); - if (!err) break; // If we succeeded, return sdr - // If we failed, then it may be because the daemon is still launching. - // This can happen for processes that launch early in the boot process, while the - // daemon is still coming up. Rather than fail here, we'll wait a bit and try again. - // If, after ten seconds, we still can't connect to the daemon, - // then we give up and return a failure code. - if (++NumTries < 3) - sleep(1); // Sleep a bit, then try again - else - { - dnssd_close(sdr->sockfd); - sdr->sockfd = dnssd_InvalidSocket; - free(sdr); - return NULL; - } - } - return sdr; - } - -static DNSServiceErrorType deliver_request(void *msg, DNSServiceRef sdr, int reuse_sd) - { - ipc_msg_hdr *hdr = msg; - uint32_t datalen = hdr->datalen; - dnssd_sockaddr_t caddr, daddr; // (client and daemon address structs) - char *data = (char *)msg + sizeof(ipc_msg_hdr); - dnssd_sock_t listenfd = dnssd_InvalidSocket, errsd = dnssd_InvalidSocket; - int ret; - unsigned int len = sizeof(caddr); - DNSServiceErrorType err = kDNSServiceErr_Unknown; - - if (!hdr || sdr->sockfd < 0) return kDNSServiceErr_Unknown; - - if (!reuse_sd) - { - // setup temporary error socket - if ((listenfd = socket(AF_DNSSD, SOCK_STREAM, 0)) < 0) - goto cleanup; - bzero(&caddr, sizeof(caddr)); - -#if defined(USE_TCP_LOOPBACK) - { - union { uint16_t s; u_char b[2]; } port; - caddr.sin_family = AF_INET; - caddr.sin_port = 0; - caddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR); - ret = bind(listenfd, (struct sockaddr*) &caddr, sizeof(caddr)); - if (ret < 0) goto cleanup; - if (getsockname(listenfd, (struct sockaddr*) &caddr, &len) < 0) goto cleanup; - listen(listenfd, 1); - port.s = caddr.sin_port; - data[0] = port.b[0]; // don't switch the byte order, as the - data[1] = port.b[1]; // daemon expects it in network byte order - } -#else - { - mode_t mask = umask(0); - caddr.sun_family = AF_LOCAL; -#ifndef NOT_HAVE_SA_LEN // According to Stevens (section 3.2), there is no portable way to - // determine whether sa_len is defined on a particular platform. - caddr.sun_len = sizeof(struct sockaddr_un); -#endif - strcpy(caddr.sun_path, data); - ret = bind(listenfd, (struct sockaddr *)&caddr, sizeof(caddr)); - umask(mask); - if (ret < 0) goto cleanup; - listen(listenfd, 1); - } -#endif - } - - ConvertHeaderBytes(hdr); - if (my_write(sdr->sockfd, msg, datalen + sizeof(ipc_msg_hdr)) < 0) - goto cleanup; - free(msg); - msg = NULL; - - if (reuse_sd) errsd = sdr->sockfd; - else - { - len = sizeof(daddr); - errsd = accept(listenfd, (struct sockaddr *)&daddr, &len); - if (errsd < 0) goto cleanup; - } - - if (my_read(errsd, (char*)&err, (int)sizeof(err)) < 0) - err = kDNSServiceErr_Unknown; - else - err = ntohl(err); - -cleanup: - if (!reuse_sd && listenfd > 0) dnssd_close(listenfd); - if (!reuse_sd && errsd > 0) dnssd_close(errsd); -#if !defined(USE_TCP_LOOPBACK) - if (!reuse_sd && data) unlink(data); -#endif - if (msg) free(msg); - return err; - } - -int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef) - { - if (!sdRef) return -1; - return (int) sdRef->sockfd; - } - -// handle reply from server, calling application client callback. If there is no reply -// from the daemon on the socket contained in sdRef, the call will block. -DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef) - { - ipc_msg_hdr hdr; - char *data; - - if (!sdRef || sdRef->sockfd < 0 || !sdRef->process_reply) - return kDNSServiceErr_BadReference; - - if (my_read(sdRef->sockfd, (void *)&hdr, sizeof(hdr)) < 0) - // return NoError on EWOULDBLOCK. This will handle the case - // where a non-blocking socket is told there is data, but - // it was a false positive. - return (dnssd_errno() == dnssd_EWOULDBLOCK) ? kDNSServiceErr_NoError : kDNSServiceErr_Unknown; - ConvertHeaderBytes(&hdr); - if (hdr.version != VERSION) - return kDNSServiceErr_Incompatible; - data = malloc(hdr.datalen); - if (!data) return kDNSServiceErr_NoMemory; - if (my_read(sdRef->sockfd, data, hdr.datalen) < 0) - return kDNSServiceErr_Unknown; - sdRef->process_reply(sdRef, &hdr, data); - free(data); - return kDNSServiceErr_NoError; - } - -void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef) - { - if (!sdRef) return; - if (sdRef->sockfd > 0) dnssd_close(sdRef->sockfd); - free(sdRef); - } - -static void handle_resolve_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) - { - DNSServiceFlags flags; - char fullname[kDNSServiceMaxDomainName]; - char target[kDNSServiceMaxDomainName]; - uint16_t txtlen; - union { uint16_t s; u_char b[2]; } port; - uint32_t ifi; - DNSServiceErrorType err; - char *txtrecord; - int str_error = 0; - (void)hdr; //unused - - flags = get_flags(&data); - ifi = get_long(&data); - err = get_error_code(&data); - if (get_string(&data, fullname, kDNSServiceMaxDomainName) < 0) str_error = 1; - if (get_string(&data, target, kDNSServiceMaxDomainName) < 0) str_error = 1; - port.b[0] = *data++; - port.b[1] = *data++; - txtlen = get_short(&data); - txtrecord = get_rdata(&data, txtlen); - - if (!err && str_error) err = kDNSServiceErr_Unknown; - ((DNSServiceResolveReply)sdr->app_callback)(sdr, flags, ifi, err, fullname, target, port.s, txtlen, txtrecord, sdr->app_context); - } - -DNSServiceErrorType DNSSD_API DNSServiceResolve - ( - DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *name, - const char *regtype, - const char *domain, - DNSServiceResolveReply callBack, - void *context - ) - { - char *msg = NULL, *ptr; - size_t len; - ipc_msg_hdr *hdr; - DNSServiceRef sdr; - DNSServiceErrorType err; - - if (!sdRef) return kDNSServiceErr_BadParam; - *sdRef = NULL; - - if (!name || !regtype || !domain || !callBack) return kDNSServiceErr_BadParam; - - // calculate total message length - len = sizeof(flags); - len += sizeof(interfaceIndex); - len += strlen(name) + 1; - len += strlen(regtype) + 1; - len += strlen(domain) + 1; - - hdr = create_hdr(resolve_request, &len, &ptr, 1); - if (!hdr) goto error; - msg = (void *)hdr; - - put_flags(flags, &ptr); - put_long(interfaceIndex, &ptr); - put_string(name, &ptr); - put_string(regtype, &ptr); - put_string(domain, &ptr); - - sdr = connect_to_server(); - if (!sdr) goto error; - err = deliver_request(msg, sdr, 1); - if (err) - { - DNSServiceRefDeallocate(sdr); - return err; - } - sdr->op = resolve_request; - sdr->process_reply = handle_resolve_response; - sdr->app_callback = callBack; - sdr->app_context = context; - *sdRef = sdr; - - return err; - -error: - if (msg) free(msg); - if (*sdRef) { free(*sdRef); *sdRef = NULL; } - return kDNSServiceErr_Unknown; - } - -static void handle_query_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) - { - DNSServiceFlags flags; - uint32_t interfaceIndex, ttl; - DNSServiceErrorType errorCode; - char name[kDNSServiceMaxDomainName]; - uint16_t rrtype, rrclass, rdlen; - char *rdata; - int str_error = 0; - (void)hdr;//Unused - - flags = get_flags(&data); - interfaceIndex = get_long(&data); - errorCode = get_error_code(&data); - if (get_string(&data, name, kDNSServiceMaxDomainName) < 0) str_error = 1; - rrtype = get_short(&data); - rrclass = get_short(&data); - rdlen = get_short(&data); - rdata = get_rdata(&data, rdlen); - ttl = get_long(&data); - - if (!errorCode && str_error) errorCode = kDNSServiceErr_Unknown; - ((DNSServiceQueryRecordReply)sdr->app_callback)(sdr, flags, interfaceIndex, errorCode, name, rrtype, rrclass, - rdlen, rdata, ttl, sdr->app_context); - return; - } - -DNSServiceErrorType DNSSD_API DNSServiceQueryRecord -( - DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *name, - uint16_t rrtype, - uint16_t rrclass, - DNSServiceQueryRecordReply callBack, - void *context - ) - { - char *msg = NULL, *ptr; - size_t len; - ipc_msg_hdr *hdr; - DNSServiceRef sdr; - DNSServiceErrorType err; - - if (!sdRef) return kDNSServiceErr_BadParam; - *sdRef = NULL; - - if (!name) name = "\0"; - - // calculate total message length - len = sizeof(flags); - len += sizeof(uint32_t); //interfaceIndex - len += strlen(name) + 1; - len += 2 * sizeof(uint16_t); // rrtype, rrclass - - hdr = create_hdr(query_request, &len, &ptr, 1); - if (!hdr) goto error; - msg = (void *)hdr; - - put_flags(flags, &ptr); - put_long(interfaceIndex, &ptr); - put_string(name, &ptr); - put_short(rrtype, &ptr); - put_short(rrclass, &ptr); - - sdr = connect_to_server(); - if (!sdr) goto error; - err = deliver_request(msg, sdr, 1); - if (err) - { - DNSServiceRefDeallocate(sdr); - return err; - } - - sdr->op = query_request; - sdr->process_reply = handle_query_response; - sdr->app_callback = callBack; - sdr->app_context = context; - *sdRef = sdr; - return err; - -error: - if (msg) free(msg); - if (*sdRef) { free(*sdRef); *sdRef = NULL; } - return kDNSServiceErr_Unknown; - } - -static void handle_browse_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) - { - DNSServiceFlags flags; - uint32_t interfaceIndex; - DNSServiceErrorType errorCode; - char replyName[256], replyType[kDNSServiceMaxDomainName], - replyDomain[kDNSServiceMaxDomainName]; - int str_error = 0; - (void)hdr;//Unused - - flags = get_flags(&data); - interfaceIndex = get_long(&data); - errorCode = get_error_code(&data); - if (get_string(&data, replyName, 256) < 0) str_error = 1; - if (get_string(&data, replyType, kDNSServiceMaxDomainName) < 0) str_error = 1; - if (get_string(&data, replyDomain, kDNSServiceMaxDomainName) < 0) str_error = 1; - if (!errorCode && str_error) errorCode = kDNSServiceErr_Unknown; - ((DNSServiceBrowseReply)sdr->app_callback)(sdr, flags, interfaceIndex, errorCode, replyName, replyType, replyDomain, sdr->app_context); - } - -DNSServiceErrorType DNSSD_API DNSServiceBrowse -( - DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *regtype, - const char *domain, - DNSServiceBrowseReply callBack, - void *context - ) - { - char *msg = NULL, *ptr; - size_t len; - ipc_msg_hdr *hdr; - DNSServiceRef sdr; - DNSServiceErrorType err; - - if (!sdRef) return kDNSServiceErr_BadParam; - *sdRef = NULL; - - if (!domain) domain = ""; - - len = sizeof(flags); - len += sizeof(interfaceIndex); - len += strlen(regtype) + 1; - len += strlen(domain) + 1; - - hdr = create_hdr(browse_request, &len, &ptr, 1); - if (!hdr) goto error; - msg = (char *)hdr; - put_flags(flags, &ptr); - put_long(interfaceIndex, &ptr); - put_string(regtype, &ptr); - put_string(domain, &ptr); - - sdr = connect_to_server(); - if (!sdr) goto error; - err = deliver_request(msg, sdr, 1); - if (err) - { - DNSServiceRefDeallocate(sdr); - return err; - } - sdr->op = browse_request; - sdr->process_reply = handle_browse_response; - sdr->app_callback = callBack; - sdr->app_context = context; - *sdRef = sdr; - return err; - -error: - if (msg) free(msg); - if (*sdRef) { free(*sdRef); *sdRef = NULL; } - return kDNSServiceErr_Unknown; - } - -DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser -( - DNSServiceFlags flags, - const char *domain - ) - { - DNSServiceRef sdr; - DNSServiceErrorType err; - char *ptr = NULL; - size_t len = sizeof(flags) + strlen(domain) + 1; - ipc_msg_hdr *hdr = create_hdr(setdomain_request, &len, &ptr, 1); - - if (!hdr) return kDNSServiceErr_Unknown; - put_flags(flags, &ptr); - put_string(domain, &ptr); - - sdr = connect_to_server(); - if (!sdr) { free(hdr); return kDNSServiceErr_Unknown; } - err = deliver_request((char *)hdr, sdr, 1); // deliver_request frees the message for us - DNSServiceRefDeallocate(sdr); - return err; - } - - -static void handle_regservice_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) - { - DNSServiceFlags flags; - uint32_t interfaceIndex; - DNSServiceErrorType errorCode; - char name[256], regtype[kDNSServiceMaxDomainName], domain[kDNSServiceMaxDomainName]; - int str_error = 0; - (void)hdr;//Unused - - flags = get_flags(&data); - interfaceIndex = get_long(&data); - errorCode = get_error_code(&data); - if (get_string(&data, name, 256) < 0) str_error = 1; - if (get_string(&data, regtype, kDNSServiceMaxDomainName) < 0) str_error = 1; - if (get_string(&data, domain, kDNSServiceMaxDomainName) < 0) str_error = 1; - if (!errorCode && str_error) errorCode = kDNSServiceErr_Unknown; - ((DNSServiceRegisterReply)sdr->app_callback)(sdr, flags, errorCode, name, regtype, domain, sdr->app_context); - } - -DNSServiceErrorType DNSSD_API DNSServiceRegister - ( - DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *name, - const char *regtype, - const char *domain, - const char *host, - uint16_t PortInNetworkByteOrder, - uint16_t txtLen, - const void *txtRecord, - DNSServiceRegisterReply callBack, - void *context - ) - { - char *msg = NULL, *ptr; - size_t len; - ipc_msg_hdr *hdr; - DNSServiceRef sdr; - DNSServiceErrorType err; - union { uint16_t s; u_char b[2]; } port = { PortInNetworkByteOrder }; - - if (!sdRef) return kDNSServiceErr_BadParam; - *sdRef = NULL; - - if (!name) name = ""; - if (!regtype) return kDNSServiceErr_BadParam; - if (!domain) domain = ""; - if (!host) host = ""; - if (!txtRecord) txtRecord = (void*)""; - - // auto-name must also have auto-rename - if (!name[0] && (flags & kDNSServiceFlagsNoAutoRename)) - return kDNSServiceErr_BadParam; - - // no callback must have auto-name - if (!callBack && name[0]) return kDNSServiceErr_BadParam; - - len = sizeof(DNSServiceFlags); - len += sizeof(uint32_t); // interfaceIndex - len += strlen(name) + strlen(regtype) + strlen(domain) + strlen(host) + 4; - len += 2 * sizeof(uint16_t); // port, txtLen - len += txtLen; - - hdr = create_hdr(reg_service_request, &len, &ptr, 1); - if (!hdr) goto error; - if (!callBack) hdr->flags |= IPC_FLAGS_NOREPLY; - msg = (char *)hdr; - put_flags(flags, &ptr); - put_long(interfaceIndex, &ptr); - put_string(name, &ptr); - put_string(regtype, &ptr); - put_string(domain, &ptr); - put_string(host, &ptr); - *ptr++ = port.b[0]; - *ptr++ = port.b[1]; - put_short(txtLen, &ptr); - put_rdata(txtLen, txtRecord, &ptr); - - sdr = connect_to_server(); - if (!sdr) goto error; - err = deliver_request(msg, sdr, 1); - if (err) - { - DNSServiceRefDeallocate(sdr); - return err; - } - - sdr->op = reg_service_request; - sdr->process_reply = callBack ? handle_regservice_response : NULL; - sdr->app_callback = callBack; - sdr->app_context = context; - *sdRef = sdr; - - return err; - -error: - if (msg) free(msg); - if (*sdRef) { free(*sdRef); *sdRef = NULL; } - return kDNSServiceErr_Unknown; - } - -static void handle_enumeration_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) - { - DNSServiceFlags flags; - uint32_t interfaceIndex; - DNSServiceErrorType err; - char domain[kDNSServiceMaxDomainName]; - int str_error = 0; - (void)hdr;//Unused - - flags = get_flags(&data); - interfaceIndex = get_long(&data); - err = get_error_code(&data); - if (get_string(&data, domain, kDNSServiceMaxDomainName) < 0) str_error = 1; - if (!err && str_error) err = kDNSServiceErr_Unknown; - ((DNSServiceDomainEnumReply)sdr->app_callback)(sdr, flags, interfaceIndex, err, domain, sdr->app_context); - } - -DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains -( - DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceDomainEnumReply callBack, - void *context - ) - { - char *msg = NULL, *ptr; - size_t len; - ipc_msg_hdr *hdr; - DNSServiceRef sdr; - DNSServiceErrorType err; - int f1 = (flags & kDNSServiceFlagsBrowseDomains) != 0; - int f2 = (flags & kDNSServiceFlagsRegistrationDomains) != 0; - if (f1 + f2 != 1) return kDNSServiceErr_BadParam; - - if (!sdRef) return kDNSServiceErr_BadParam; - *sdRef = NULL; - - len = sizeof(DNSServiceFlags); - len += sizeof(uint32_t); - - hdr = create_hdr(enumeration_request, &len, &ptr, 1); - if (!hdr) goto error; - msg = (void *)hdr; - - put_flags(flags, &ptr); - put_long(interfaceIndex, &ptr); - - sdr = connect_to_server(); - if (!sdr) goto error; - err = deliver_request(msg, sdr, 1); - if (err) - { - DNSServiceRefDeallocate(sdr); - return err; - } - - sdr->op = enumeration_request; - sdr->process_reply = handle_enumeration_response; - sdr->app_callback = callBack; - sdr->app_context = context; - *sdRef = sdr; - return err; - -error: - if (msg) free(msg); - if (*sdRef) { free(*sdRef); *sdRef = NULL; } - return kDNSServiceErr_Unknown; - } - -static void handle_regrecord_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) - { - DNSServiceFlags flags; - uint32_t interfaceIndex; - DNSServiceErrorType errorCode; - DNSRecordRef rref = hdr->client_context.context; - - if (sdr->op != connection) - { - rref->app_callback(rref->sdr, rref, 0, kDNSServiceErr_Unknown, rref->app_context); - return; - } - flags = get_flags(&data); - interfaceIndex = get_long(&data); - errorCode = get_error_code(&data); - - rref->app_callback(rref->sdr, rref, flags, errorCode, rref->app_context); - } - -DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef) - { - if (!sdRef) return kDNSServiceErr_BadParam; - *sdRef = connect_to_server(); - if (!*sdRef) - return kDNSServiceErr_Unknown; - (*sdRef)->op = connection; - (*sdRef)->process_reply = handle_regrecord_response; - return 0; - } - -DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord -( - DNSServiceRef sdRef, - DNSRecordRef *RecordRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *fullname, - uint16_t rrtype, - uint16_t rrclass, - uint16_t rdlen, - const void *rdata, - uint32_t ttl, - DNSServiceRegisterRecordReply callBack, - void *context - ) - { - char *msg = NULL, *ptr; - size_t len; - ipc_msg_hdr *hdr = NULL; - DNSServiceRef tmp = NULL; - DNSRecordRef rref = NULL; - int f1 = (flags & kDNSServiceFlagsShared) != 0; - int f2 = (flags & kDNSServiceFlagsUnique) != 0; - if (f1 + f2 != 1) return kDNSServiceErr_BadParam; - - if (!sdRef || sdRef->op != connection || sdRef->sockfd < 0) - return kDNSServiceErr_BadReference; - *RecordRef = NULL; - - len = sizeof(DNSServiceFlags); - len += 2 * sizeof(uint32_t); // interfaceIndex, ttl - len += 3 * sizeof(uint16_t); // rrtype, rrclass, rdlen - len += strlen(fullname) + 1; - len += rdlen; - - hdr = create_hdr(reg_record_request, &len, &ptr, 0); - if (!hdr) goto error; - msg = (char *)hdr; - put_flags(flags, &ptr); - put_long(interfaceIndex, &ptr); - put_string(fullname, &ptr); - put_short(rrtype, &ptr); - put_short(rrclass, &ptr); - put_short(rdlen, &ptr); - put_rdata(rdlen, rdata, &ptr); - put_long(ttl, &ptr); - - rref = malloc(sizeof(_DNSRecordRef_t)); - if (!rref) goto error; - rref->app_context = context; - rref->app_callback = callBack; - rref->record_index = sdRef->max_index++; - rref->sdr = sdRef; - *RecordRef = rref; - hdr->client_context.context = rref; - hdr->reg_index = rref->record_index; - - return deliver_request(msg, sdRef, 0); - -error: - if (rref) free(rref); - if (tmp) free(tmp); - if (hdr) free(hdr); - return kDNSServiceErr_Unknown; - } - -//sdRef returned by DNSServiceRegister() -DNSServiceErrorType DNSSD_API DNSServiceAddRecord - ( - DNSServiceRef sdRef, - DNSRecordRef *RecordRef, - DNSServiceFlags flags, - uint16_t rrtype, - uint16_t rdlen, - const void *rdata, - uint32_t ttl - ) - { - ipc_msg_hdr *hdr; - size_t len = 0; - char *ptr; - DNSRecordRef rref; - - if (!sdRef || (sdRef->op != reg_service_request) || !RecordRef) - return kDNSServiceErr_BadReference; - *RecordRef = NULL; - - len += 2 * sizeof(uint16_t); //rrtype, rdlen - len += rdlen; - len += sizeof(uint32_t); - len += sizeof(DNSServiceFlags); - - hdr = create_hdr(add_record_request, &len, &ptr, 0); - if (!hdr) return kDNSServiceErr_Unknown; - put_flags(flags, &ptr); - put_short(rrtype, &ptr); - put_short(rdlen, &ptr); - put_rdata(rdlen, rdata, &ptr); - put_long(ttl, &ptr); - - rref = malloc(sizeof(_DNSRecordRef_t)); - if (!rref) goto error; - rref->app_context = NULL; - rref->app_callback = NULL; - rref->record_index = sdRef->max_index++; - rref->sdr = sdRef; - *RecordRef = rref; - hdr->client_context.context = rref; - hdr->reg_index = rref->record_index; - return deliver_request((char *)hdr, sdRef, 0); - -error: - if (hdr) free(hdr); - if (rref) free(rref); - if (*RecordRef) *RecordRef = NULL; - return kDNSServiceErr_Unknown; -} - -//DNSRecordRef returned by DNSServiceRegisterRecord or DNSServiceAddRecord -DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord - ( - DNSServiceRef sdRef, - DNSRecordRef RecordRef, - DNSServiceFlags flags, - uint16_t rdlen, - const void *rdata, - uint32_t ttl - ) - { - ipc_msg_hdr *hdr; - size_t len = 0; - char *ptr; - - if (!sdRef) return kDNSServiceErr_BadReference; - - len += sizeof(uint16_t); - len += rdlen; - len += sizeof(uint32_t); - len += sizeof(DNSServiceFlags); - - hdr = create_hdr(update_record_request, &len, &ptr, 0); - if (!hdr) return kDNSServiceErr_Unknown; - hdr->reg_index = RecordRef ? RecordRef->record_index : TXT_RECORD_INDEX; - put_flags(flags, &ptr); - put_short(rdlen, &ptr); - put_rdata(rdlen, rdata, &ptr); - put_long(ttl, &ptr); - return deliver_request((char *)hdr, sdRef, 0); - } - -DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord -( - DNSServiceRef sdRef, - DNSRecordRef RecordRef, - DNSServiceFlags flags - ) - { - ipc_msg_hdr *hdr; - size_t len = 0; - char *ptr; - DNSServiceErrorType err; - - if (!sdRef || !RecordRef || !sdRef->max_index) - return kDNSServiceErr_BadReference; - - len += sizeof(flags); - hdr = create_hdr(remove_record_request, &len, &ptr, 0); - if (!hdr) return kDNSServiceErr_Unknown; - hdr->reg_index = RecordRef->record_index; - put_flags(flags, &ptr); - err = deliver_request((char *)hdr, sdRef, 0); - if (!err) free(RecordRef); - return err; - } - -void DNSSD_API DNSServiceReconfirmRecord -( - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *fullname, - uint16_t rrtype, - uint16_t rrclass, - uint16_t rdlen, - const void *rdata - ) - { - char *ptr; - size_t len; - ipc_msg_hdr *hdr; - DNSServiceRef tmp; - - len = sizeof(DNSServiceFlags); - len += sizeof(uint32_t); - len += strlen(fullname) + 1; - len += 3 * sizeof(uint16_t); - len += rdlen; - tmp = connect_to_server(); - if (!tmp) return; - hdr = create_hdr(reconfirm_record_request, &len, &ptr, 1); - if (!hdr) return; - - put_flags(flags, &ptr); - put_long(interfaceIndex, &ptr); - put_string(fullname, &ptr); - put_short(rrtype, &ptr); - put_short(rrclass, &ptr); - put_short(rdlen, &ptr); - put_rdata(rdlen, rdata, &ptr); - ConvertHeaderBytes(hdr); - my_write(tmp->sockfd, (char *)hdr, (int) len); - free(hdr); - DNSServiceRefDeallocate(tmp); - } - diff --git a/mdns.subproj/dnssd_ipc.c b/mdns.subproj/dnssd_ipc.c deleted file mode 100644 index 0854ada..0000000 --- a/mdns.subproj/dnssd_ipc.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * 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 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: dnssd_ipc.c,v $ -Revision 1.10 2004/09/22 20:05:38 majka -Integrated -3725573 - Need Error Codes for handling Lighthouse setup failure on NAT -3805822 - Socket-based APIs aren't endian-safe -3806739 - DNSServiceSetDefaultDomainForUser header comments incorrect - -Revision 1.9.4.1 2004/09/20 21:54:33 ksekar - Socket-based APIs aren't endian-safe - -Revision 1.9 2004/09/16 23:45:24 majka -Integrated 3775315 and 3765280. - -Revision 1.8.4.1 2004/09/02 19:43:41 ksekar -: Sync dns-sd client files between Libinfo and -mDNSResponder projects - -Revision 1.11 2004/06/18 04:56:09 rpantos -casting goodness - -Revision 1.10 2004/06/12 01:08:14 cheshire -Changes for Windows compatibility - -Revision 1.9 2004/05/18 23:51:27 cheshire -Tidy up all checkin comments to use consistent "" format for bug numbers - -Revision 1.8 2003/11/05 22:44:57 ksekar -: No bounds checking when reading data from client -Reviewed by: Stuart Cheshire - -Revision 1.7 2003/08/12 19:56:25 cheshire -Update to APSL 2.0 - - */ - -#include "dnssd_ipc.h" - -void put_long(const uint32_t l, char **ptr) - { - (*ptr)[0] = (char)((l >> 24) & 0xFF); - (*ptr)[1] = (char)((l >> 16) & 0xFF); - (*ptr)[2] = (char)((l >> 8) & 0xFF); - (*ptr)[3] = (char)((l ) & 0xFF); - *ptr += sizeof(uint32_t); - } - -uint32_t get_long(char **ptr) - { - uint8_t *p = (uint8_t*) *ptr; - *ptr += sizeof(uint32_t); - return((uint32_t) ((uint32_t)p[0] << 24 | (uint32_t)p[1] << 16 | (uint32_t)p[2] << 8 | p[3])); - } - -void put_short(uint16_t s, char **ptr) - { - (*ptr)[0] = (char)((s >> 8) & 0xFF); - (*ptr)[1] = (char)((s ) & 0xFF); - *ptr += sizeof(uint16_t); - } - -uint16_t get_short(char **ptr) - { - uint8_t *p = (uint8_t*) *ptr; - *ptr += sizeof(uint16_t); - return((uint16_t) ((uint16_t)p[0] << 8 | p[1])); - } - -int put_string(const char *str, char **ptr) - { - if (!str) str = ""; - strcpy(*ptr, str); - *ptr += strlen(str) + 1; - return 0; - } - -int get_string(char **ptr, char *buffer, int buflen) - { - int overrun = (int)strlen(*ptr) < buflen ? 0 : -1; - strncpy(buffer, *ptr, buflen - 1); - buffer[buflen - 1] = '\0'; - *ptr += strlen(buffer) + 1; - return overrun; - } - -void put_rdata(const int rdlen, const char *rdata, char **ptr) - { - memcpy(*ptr, rdata, rdlen); - *ptr += rdlen; - } - -char *get_rdata(char **ptr, int rdlen) - { - char *rd = *ptr; - *ptr += rdlen; - return rd; - } - -void ConvertHeaderBytes(ipc_msg_hdr *hdr) - { - hdr->version = htonl(hdr->version); - hdr->datalen = htonl(hdr->datalen); - hdr->flags = htonl(hdr->flags); - hdr->op = htonl(hdr->op ); - hdr->reg_index = htonl(hdr->reg_index); - } diff --git a/mdns.subproj/dnssd_ipc.h b/mdns.subproj/dnssd_ipc.h deleted file mode 100644 index cecfd46..0000000 --- a/mdns.subproj/dnssd_ipc.h +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * 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 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: dnssd_ipc.h,v $ -Revision 1.9 2004/09/22 20:05:38 majka -Integrated -3725573 - Need Error Codes for handling Lighthouse setup failure on NAT -3805822 - Socket-based APIs aren't endian-safe -3806739 - DNSServiceSetDefaultDomainForUser header comments incorrect - -Revision 1.8.2.1 2004/09/20 21:54:33 ksekar - Socket-based APIs aren't endian-safe - -Revision 1.8 2004/09/17 20:19:01 majka -Integrated 3804522 - -Revision 1.7.2.1 2004/09/17 20:15:30 ksekar -*** empty log message *** - -Revision 1.7 2004/09/16 23:45:24 majka -Integrated 3775315 and 3765280. - -Revision 1.6.4.1 2004/09/02 19:43:41 ksekar -: Sync dns-sd client files between Libinfo and -mDNSResponder projects - -Revision 1.11 2004/08/10 06:24:56 cheshire -Use types with precisely defined sizes for 'op' and 'reg_index', for better -compatibility if the daemon and the client stub are built using different compilers - -Revision 1.10 2004/07/07 17:39:25 shersche -Change MDNS_SERVERPORT from 5533 to 5354. - -Revision 1.9 2004/06/25 00:26:27 rpantos -Changes to fix the Posix build on Solaris. - -Revision 1.8 2004/06/18 04:56:51 rpantos -Add layer for platform code - -Revision 1.7 2004/06/12 01:08:14 cheshire -Changes for Windows compatibility - -Revision 1.6 2003/08/12 19:56:25 cheshire -Update to APSL 2.0 - - */ - -#ifndef DNSSD_IPC_H -#define DNSSD_IPC_H - -#include "dns_sd.h" - - -// -// Common cross platform services -// -#if defined(WIN32) -# include -# define dnssd_InvalidSocket INVALID_SOCKET -# define dnssd_EWOULDBLOCK WSAEWOULDBLOCK -# define dnssd_EINTR WSAEINTR -# define MSG_WAITALL 0 -# define dnssd_sock_t SOCKET -# define dnssd_sockbuf_t -# define dnssd_close(sock) closesocket(sock) -# define dnssd_errno() WSAGetLastError() -# define ssize_t int -# define getpid _getpid -#else -# include -# include -# include -# include -# include -# include -# include -# include -# include -# define dnssd_InvalidSocket -1 -# define dnssd_EWOULDBLOCK EWOULDBLOCK -# define dnssd_EINTR EINTR -# define dnssd_EPIPE EPIPE -# define dnssd_sock_t int -# define dnssd_close(sock) close(sock) -# define dnssd_errno() errno -#endif - -#if defined(USE_TCP_LOOPBACK) -# define AF_DNSSD AF_INET -# define MDNS_TCP_SERVERADDR "127.0.0.1" -# define MDNS_TCP_SERVERPORT 5354 -# define LISTENQ 5 -# define dnssd_sockaddr_t struct sockaddr_in -#else -# define AF_DNSSD AF_LOCAL -# define MDNS_UDS_SERVERPATH "/var/run/mDNSResponder" -# define LISTENQ 100 - // longest legal control path length -# define MAX_CTLPATH 256 -# define dnssd_sockaddr_t struct sockaddr_un -#endif - - -//#define UDSDEBUG // verbose debug output - -// Compatibility workaround -#ifndef AF_LOCAL -#define AF_LOCAL AF_UNIX -#endif - -// General UDS constants -#define TXT_RECORD_INDEX ((uint32_t)(-1)) // record index for default text record - -// IPC data encoding constants and types -#define VERSION 1 -#define IPC_FLAGS_NOREPLY 1 // set flag if no asynchronous replies are to be sent to client -#define IPC_FLAGS_REUSE_SOCKET 2 // set flag if synchronous errors are to be sent via the primary socket - // (if not set, first string in message buffer must be path to error socket - -typedef enum - { - connection = 1, // connected socket via DNSServiceConnect() - reg_record_request, // reg/remove record only valid for connected sockets - remove_record_request, - enumeration_request, - reg_service_request, - browse_request, - resolve_request, - query_request, - reconfirm_record_request, - add_record_request, - update_record_request, - setdomain_request - } request_op_t; - -typedef enum - { - enumeration_reply = 64, - reg_service_reply, - browse_reply, - resolve_reply, - query_reply, - reg_record_reply - } reply_op_t; - -typedef struct ipc_msg_hdr_struct ipc_msg_hdr; - -// client stub callback to process message from server and deliver results to -// client application - -typedef void (*process_reply_callback) - ( - DNSServiceRef sdr, - ipc_msg_hdr *hdr, - char *msg - ); - -// allow 64-bit client to interoperate w/ 32-bit daemon -typedef union - { - void *context; - uint32_t ptr64[2]; - } client_context_t; - -typedef struct __attribute__((__packed__)) ipc_msg_hdr_struct - { - uint32_t version; - uint32_t datalen; - uint32_t flags; - uint32_t op; // request_op_t or reply_op_t - client_context_t client_context; // context passed from client, returned by server in corresponding reply - uint32_t reg_index; // identifier for a record registered via DNSServiceRegisterRecord() on a - // socket connected by DNSServiceConnect(). Must be unique in the scope of the connection, such that and - // index/socket pair uniquely identifies a record. (Used to select records for removal by DNSServiceRemoveRecord()) - } ipc_msg_hdr_struct; - -// it is advanced to point to the next field, or the end of the message -// routines to write to and extract data from message buffers. -// caller responsible for bounds checking. -// ptr is the address of the pointer to the start of the field. -// it is advanced to point to the next field, or the end of the message - -void put_long(const uint32_t l, char **ptr); -uint32_t get_long(char **ptr); - -void put_short(uint16_t s, char **ptr); -uint16_t get_short(char **ptr); - -#define put_flags put_long -#define get_flags get_long - -#define put_error_code put_long -#define get_error_code get_long - -int put_string(const char *str, char **ptr); -int get_string(char **ptr, char *buffer, int buflen); - -void put_rdata(const int rdlen, const char *rdata, char **ptr); -char *get_rdata(char **ptr, int rdlen); // return value is rdata pointed to by *ptr - - // rdata is not copied from buffer. - -void ConvertHeaderBytes(ipc_msg_hdr *hdr); - -#endif // DNSSD_IPC_H diff --git a/membership.subproj/DSmemberdMIG.defs b/membership.subproj/DSmemberdMIG.defs new file mode 100644 index 0000000..3c5bf1a --- /dev/null +++ b/membership.subproj/DSmemberdMIG.defs @@ -0,0 +1 @@ +#include <../include/DSmemberdMIG.defs> diff --git a/membership.subproj/Makefile b/membership.subproj/Makefile index 2544a39..9f7473c 100644 --- a/membership.subproj/Makefile +++ b/membership.subproj/Makefile @@ -12,11 +12,12 @@ NAME = membership PROJECTVERSION = 2.8 PROJECT_TYPE = Component -HFILES = membership.h membershipPriv.h memberd_defines.h ntsid.h +HFILES = membership.h membershipPriv.h ntsid.h CFILES = membership.c -OTHERSRCS = Makefile.preamble Makefile Makefile.postamble memberd.defs +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble DSmemberdMIG.defs \ + mbr_check_membership.3 mbr_uid_to_uuid.3 mbr_uid_to_uuid_so.3 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles CODE_GEN_STYLE = DYNAMIC diff --git a/membership.subproj/Makefile.postamble b/membership.subproj/Makefile.postamble index e69de29..f20fb6f 100644 --- a/membership.subproj/Makefile.postamble +++ b/membership.subproj/Makefile.postamble @@ -0,0 +1,11 @@ +install-man-page: $(DSTROOT)/usr/share/man/man3 + install -d $(DSTROOT)/usr/share/man/man3 + install -c -m 644 mbr_check_membership.3 $(DSTROOT)/usr/share/man/man3 + install -c -m 644 mbr_uid_to_uuid.3 $(DSTROOT)/usr/share/man/man3 + install -c -m 644 mbr_uid_to_uuid_so.3 $(DSTROOT)/usr/share/man/man3/mbr_gid_to_uuid.3 + install -c -m 644 mbr_uid_to_uuid_so.3 $(DSTROOT)/usr/share/man/man3/mbr_sid_to_uuid.3 + install -c -m 644 mbr_uid_to_uuid_so.3 $(DSTROOT)/usr/share/man/man3/mbr_uuid_to_id.3 + install -c -m 644 mbr_uid_to_uuid_so.3 $(DSTROOT)/usr/share/man/man3/mbr_uuid_to_sid.3 + +$(DSTROOT)/usr/share/man/man3: + $(MKDIRS) $@ diff --git a/membership.subproj/Makefile.preamble b/membership.subproj/Makefile.preamble index 6d8c68a..c77ddea 100644 --- a/membership.subproj/Makefile.preamble +++ b/membership.subproj/Makefile.preamble @@ -1,11 +1,12 @@ +AFTER_POSTINSTALL += install-man-page OTHER_PRIVATE_HEADERS = membershipPriv.h -# Additional flags (MiG generated files) -DEFSFILES = memberd.defs -OTHER_OFILES = memberdUser.o +# Enable MIG type checking +OTHER_CFLAGS += -D__MigTypeCheck=1 -D__DARWIN_NON_CANCELABLE=1 -# private headers -INTERNAL_HDRS = memberd.defs memberd.h +# Additional flags (MiG generated files) +DEFSFILES = DSmemberdMIG.defs +OTHER_OFILES = DSmemberdMIGUser.o BEFORE_INSTALLHDRS += $(SFILE_DIR) $(INTERNAL_HDRS) # AFTER_INSTALLHDRS += mdns_hdrs diff --git a/membership.subproj/PB.project b/membership.subproj/PB.project index 9fafc15..3e5c151 100644 --- a/membership.subproj/PB.project +++ b/membership.subproj/PB.project @@ -2,9 +2,7 @@ DYNAMIC_CODE_GEN = YES; FILESTABLE = { H_FILES = ( - membership.h, membershipPriv.h, - memberd_defines.h, ntsid.h ); OTHER_LINKED = (membership.c); @@ -12,7 +10,7 @@ Makefile.preamble, Makefile, Makefile.postamble, - memberd.defs + DSmemberdMIG.defs ); PRECOMPILED_HEADERS = (); PROJECT_HEADERS = (); diff --git a/membership.subproj/mbr_check_membership.3 b/membership.subproj/mbr_check_membership.3 new file mode 100644 index 0000000..e268baa --- /dev/null +++ b/membership.subproj/mbr_check_membership.3 @@ -0,0 +1,93 @@ +.\" Copyright (c) 2005-2007 Apple 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. +.\" 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. +.\" 4. Neither the name of Apple Computer 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 APPLE COMPUTER 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 February 3, 2005 +.Dt MBR_CHECK_MEMBERSHIP 3 +.Os "Mac OS X" +.Sh NAME +.Nm mbr_check_membership +.Nd check whether a user is a member of a group +.Sh SYNOPSIS +.In membership.h +.Ft int +.Fn mbr_check_membership "uuid_t user" "uuid_t group" "int *ismember" +.Sh DESCRIPTION +.Fn mbr_check_membership +tests if a given user is a member of a group, individually or as a member of a nested group. +.Fa ismember +is set to 1 if the user is a member of the group, and 0 otherwise. +.Pp +Users may belong to any number of grouos. +.Fn mbr_check_membership +should be always be used to check group membership, rather than +calling +.Xr getgroups 2 , +and checking the returned list of gids. +The +.Xr setgroups 2 +and +.Xr getgroups 2 +routines are limited to a fixed number of gids, +and so may not include all of a user's groups. +.Pp +There are two special cases. +If the two uuids are equal, then +.Fa ismember +is set to 1. +If the +.Fa group +uuid is equal to the reserved "everyone" uuid (ABCDEFAB-CDEF-ABCD-EFAB-CDEF0000000C), then +.Fa ismember +will be set to 1 for any valid user. +.Pp +Group membership information is managed by the +.Xr DirectoryService 8 +daemon. +.Sh RETURN VALUES +.Fn mbr_check_membership +returns 0 on success. +It returns EIO if it is unable to communicate with the +.Xr DirectoryService 8 +daemon. +ENOENT is returned if +.Fa user +cannot be found. +.Pp +Note that +.Fn mbr_check_membership +does not test whether +.Fa group +exists or not. +Querying membership for a nonexistant group will result in +.Fa ismember +being to 0 and a return value of 0. +.Sh SEE ALSO +.Xr setgroups 2 , +.Xr getgroups 2 , +.Xr mbr_uid_to_uuid 3 , +.Xr DirectoryService 8 \ No newline at end of file diff --git a/membership.subproj/mbr_uid_to_uuid.3 b/membership.subproj/mbr_uid_to_uuid.3 new file mode 100644 index 0000000..2e7aeec --- /dev/null +++ b/membership.subproj/mbr_uid_to_uuid.3 @@ -0,0 +1,101 @@ +.\" Copyright (c) 2005-2007 Apple 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. +.\" 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. +.\" 4. Neither the name of Apple Computer 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 APPLE COMPUTER 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 February 3, 2005 +.Dt MBR_UID_TO_UUID 3 +.Os "Mac OS X" +.Sh NAME +.Nm mbr_uid_to_uuid, +.Nm mbr_gid_to_uuid, +.Nm mbr_uuid_to_id, +.Nm mbr_sid_to_uuid, +.Nm mbr_uuid_to_sid +.Nd user and group identifier translation functions +.Sh SYNOPSIS +.In membership.h +.Ft int +.Fn mbr_uid_to_uuid "uid_t id" "uuid_t uu" +.Ft int +.Fn mbr_gid_to_uuid "gid_t id" "uuid_t uu" +.Ft int +.Fn mbr_uuid_to_id "const uuid_t uu" "uid_t *id" "int *id_type" +.Ft int +.Fn mbr_sid_to_uuid "const nt_sid_t *sid" "uuid_t uu" +.Ft int +.Fn mbr_uuid_to_sid "const uuid_t uu" "nt_sid_t *sid" +.Sh DESCRIPTION +Users and groups can be referred to in multiple ways. +In addition to the traditional uid and gid, +every user or group can be referenced by a 128 bit uuid. +Additionally, if the user or group is hosted on a PDC +or Active Directory server, it will have a 128 bit or larger sid. +.Pp +These routines communicate with the +.Xr DirectoryService 8 +daemon. +.Pp +.Fn mbr_uid_to_uuid +takes a uid and looks up the associated user account. +It provides the the uuid for that user as an output parameter. +.Pp +.Fn mbr_gid_to_uuid +similarly gets the uuid associated with a group. +.Pp +.Fn mbr_uuid_to_id +takes a uuid that refers to a user or group and fetches the corresponding uid or gid. +.Fa id_type +is set to ID_TYPE_UID or ID_TYPE_GID to indicate which type was found. +Note that +.Fn mbr_uuid_to_id +always returns an id even if the uuid is not found. +This returned id is not persistant, +but can be used to map back to the uuid during runtime. +To determine if the uuid exists, the returned id can be used in a call to +.Xr getpwuid 3 +or +.Xr getgrgid 3 . +.Pp +.Fn mbr_sid_to_uuid +takes a sid and returns the associated uuid. +Like +.Fn mbr_uuid_to_id , +.Fn mbr_sid_to_uuid +always returns a uuid for the sid, even if the sid can not be found. +.Pp +.Fn mbr_uuid_to_sid +returns a sid for the associated uuid. +.Sh RETURN VALUES +These functions return 0 on success, or EIO if communications with the +.Xr DirectoryService 8 +daemon fails. +ENOENT is returned if the mapping can not be performed. +.Sh SEE ALSO +.Xr getpwuid 3 , +.Xr getgrgid 3 , +.Xr mbr_check_membership 3 , +.Xr DirectoryService 8 \ No newline at end of file diff --git a/membership.subproj/mbr_uid_to_uuid_so.3 b/membership.subproj/mbr_uid_to_uuid_so.3 new file mode 100644 index 0000000..af5c721 --- /dev/null +++ b/membership.subproj/mbr_uid_to_uuid_so.3 @@ -0,0 +1 @@ +.so man3/mbr_uid_to_uuid.3 diff --git a/membership.subproj/memberd.defs b/membership.subproj/memberd.defs deleted file mode 100644 index 34c65b3..0000000 --- a/membership.subproj/memberd.defs +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2004-2007 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 memberd 8000; - -serverprefix Server; - -#include -#include -import "memberd_defines.h"; - -type kauth_identity_extlookup = struct [200] of uint8_t; -type guid_t = struct [16] of uint8_t; - -type StatBlock = struct [16] of uint32_t; - -type GIDArray = array [16] of uint32_t; - -type string = c_string[*:256]; - -routine _mbr_DoMembershipCall -( - server: mach_port_t; - inout request: kauth_identity_extlookup; - UserSecToken token : security_token_t -); - -routine _mbr_GetStats -( - server: mach_port_t; - out stats: StatBlock; - UserSecToken token : security_token_t -); - -routine _mbr_ClearStats -( - server: mach_port_t; - UserSecToken token : security_token_t -); - -routine _mbr_MapName -( - server: mach_port_t; - in isUser: uint8_t; - in name: string; - out guid: guid_t; - UserSecToken token : security_token_t -); - -routine _mbr_GetGroups -( - server: mach_port_t; - in uid: uint32_t; - out numGroups: uint32_t; - out gids: GIDArray; - UserSecToken token : security_token_t -); - -routine _mbr_ClearCache -( - server: mach_port_t; - UserSecToken token : security_token_t -); - -routine _mbr_DumpState -( - server: mach_port_t; - in logOnly: uint8_t; - UserSecToken token : security_token_t -); diff --git a/membership.subproj/memberd_defines.h b/membership.subproj/memberd_defines.h deleted file mode 100644 index 6fbb468..0000000 --- a/membership.subproj/memberd_defines.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2004 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 USER_API_DEFINES -#define USER_API_DEFINES -#import -#import - -typedef struct kauth_identity_extlookup kauth_identity_extlookup; -typedef char* string; - -typedef struct StatBlock -{ - uint32_t fTotalUpTime; - uint32_t fTotalCallsHandled; - uint32_t fAverageuSecPerCall; - uint32_t fCacheHits; - uint32_t fCacheMisses; - uint32_t fTotalRecordLookups; - uint32_t fNumFailedRecordLookups; - uint32_t fAverageuSecPerRecordLookup; - uint32_t fTotalMembershipSearches; - uint32_t fAverageuSecPerMembershipSearch; - uint32_t fTotalLegacySearches; - uint32_t fAverageuSecPerLegacySearch; - uint32_t fTotalGUIDMemberSearches; - uint32_t fAverageuSecPerGUIDMemberSearch; - uint32_t fTotalNestedMemberSearches; - uint32_t fAverageuSecPerNestedMemberSearch; -} StatBlock; - -typedef uint32_t GIDArray[16]; - -#endif \ No newline at end of file diff --git a/membership.subproj/membership.c b/membership.subproj/membership.c index 30014af..a650f90 100644 --- a/membership.subproj/membership.c +++ b/membership.subproj/membership.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2007 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2004-2007 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,95 +22,189 @@ #include "membership.h" #include "membershipPriv.h" -#include "memberd.h" - +#include "DSmemberdMIG.h" +#include "DSmemberdMIG_types.h" #include -#include #include +#include #include #include -static mach_port_t GetServerPort() + +extern mach_port_t _ds_port; +extern int _ds_running(void); + +static const uint8_t _mbr_root_uuid[] = {0xff, 0xff, 0xee, 0xee, 0xdd, 0xdd, 0xcc, 0xcc, 0xbb, 0xbb, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00}; + +#define MAX_LOOKUP_ATTEMPTS 10 + +__private_extern__ uid_t +audit_token_uid(audit_token_t a) { - kern_return_t result; - static mach_port_t bsPort = 0; - static mach_port_t fServerPort = 0; + /* + * This should really call audit_token_to_au32, + * but that's in libbsm, not in a Libsystem library. + */ + return (uid_t)a.val[1]; +} - if (bsPort == 0) +static int +_mbr_MembershipCall(struct kauth_identity_extlookup *req) +{ + audit_token_t token; + kern_return_t status; + uint32_t i; + + if (_ds_running() == 0) return EIO; + if (_ds_port == MACH_PORT_NULL) return EIO; + + memset(&token, 0, sizeof(audit_token_t)); + + status = MIG_SERVER_DIED; + for (i = 0; (_ds_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (i < MAX_LOOKUP_ATTEMPTS); i++) { - result = task_get_bootstrap_port(mach_task_self(), &bsPort); - result = bootstrap_look_up(bsPort, "com.apple.memberd", &fServerPort); + status = memberdDSmig_MembershipCall(_ds_port, req, &token); + if (status == MACH_SEND_INVALID_DEST) + { + mach_port_mod_refs(mach_task_self(), _ds_port, MACH_PORT_RIGHT_SEND, -1); + _ds_port = MACH_PORT_NULL; + _ds_running(); + status = MIG_SERVER_DIED; + } } - return fServerPort; + if (status != KERN_SUCCESS) return EIO; + if (audit_token_uid(token) != 0) return EAUTH; + + return 0; +} + +static int +_mbr_MapName(char *name, int type, guid_t *uu) +{ + kern_return_t status; + audit_token_t token; + uint32_t i; + + if (name == NULL) return EINVAL; + if (strlen(name) > 255) return EINVAL; + + if (_ds_running() == 0) return EIO; + if (_ds_port == MACH_PORT_NULL) return EIO; + + memset(&token, 0, sizeof(audit_token_t)); + + status = MIG_SERVER_DIED; + for (i = 0; (_ds_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (i < MAX_LOOKUP_ATTEMPTS); i++) + { + status = memberdDSmig_MapName(_ds_port, type, name, uu, &token); + if (status == KERN_FAILURE) return ENOENT; + + if (status == MACH_SEND_INVALID_DEST) + { + mach_port_mod_refs(mach_task_self(), _ds_port, MACH_PORT_RIGHT_SEND, -1); + _ds_port = MACH_PORT_NULL; + _ds_running(); + status = MIG_SERVER_DIED; + } + } + + if (status != KERN_SUCCESS) return EIO; + if (audit_token_uid(token) != 0) return EAUTH; + + return 0; +} + +static int +_mbr_ClearCache() +{ + kern_return_t status; + uint32_t i; + + if (_ds_running() == 0) return EIO; + if (_ds_port == MACH_PORT_NULL) return EIO; + + status = MIG_SERVER_DIED; + for (i = 0; (_ds_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (i < MAX_LOOKUP_ATTEMPTS); i++) + { + status = memberdDSmig_ClearCache(_ds_port); + if (status == MACH_SEND_INVALID_DEST) + { + mach_port_mod_refs(mach_task_self(), _ds_port, MACH_PORT_RIGHT_SEND, -1); + _ds_port = MACH_PORT_NULL; + _ds_running(); + status = MIG_SERVER_DIED; + } + } + + if (status != KERN_SUCCESS) return EIO; + + return 0; } int mbr_uid_to_uuid(uid_t id, uuid_t uu) { struct kauth_identity_extlookup request; - security_token_t token; - int result = 0; + int status; - token.val[0] = -1; - token.val[1] = -1; + if (id == 0) + { + memcpy(uu, _mbr_root_uuid, sizeof(uuid_t)); + return 0; + } - request.el_seqno = 1; /* used as byte order field */ + /* used as a byte order field */ + request.el_seqno = 1; request.el_flags = KAUTH_EXTLOOKUP_VALID_UID | KAUTH_EXTLOOKUP_WANT_UGUID; request.el_uid = id; - result = _mbr_DoMembershipCall(GetServerPort(), &request, &token); - if (result != KERN_SUCCESS) return EIO; - if (token.val[0] != 0) return EAUTH; - if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_UGUID) != 0) - memcpy(uu, &request.el_uguid, sizeof(guid_t)); - else - result = ENOENT; + status = _mbr_MembershipCall(&request); + if (status != 0) return status; + if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_UGUID) == 0) return ENOENT; - return result; + memcpy(uu, &request.el_uguid, sizeof(guid_t)); + return 0; } int mbr_gid_to_uuid(gid_t id, uuid_t uu) { struct kauth_identity_extlookup request; - security_token_t token; - kern_return_t result; - int error = 0; - - token.val[0] = -1; - token.val[1] = -1; + int status; - request.el_seqno = 1; /* used as byte order field */ + request.el_seqno = 1; request.el_flags = KAUTH_EXTLOOKUP_VALID_GID | KAUTH_EXTLOOKUP_WANT_GGUID; request.el_gid = id; - result = _mbr_DoMembershipCall(GetServerPort(), &request, &token); - if (result != KERN_SUCCESS) return EIO; - if (token.val[0] != 0) return EAUTH; - if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GGUID) != 0) - memcpy(uu, &request.el_gguid, sizeof(guid_t)); - else - error = ENOENT; + status = _mbr_MembershipCall(&request); + if (status != 0) return status; + if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GGUID) == 0) return ENOENT; - return error; + memcpy(uu, &request.el_gguid, sizeof(guid_t)); + return 0; } int mbr_uuid_to_id(const uuid_t uu, uid_t *id, int *id_type) { struct kauth_identity_extlookup request; - security_token_t token; - kern_return_t result; - int error = 0; + int status; - token.val[0] = -1; - token.val[1] = -1; + if (id == NULL) return EIO; + if (id_type == NULL) return EIO; - request.el_seqno = 1; /* used as byte order field */ + if (!memcmp(uu, _mbr_root_uuid, sizeof(uuid_t))) + { + *id = 0; + *id_type = ID_TYPE_UID; + return 0; + } + + request.el_seqno = 1; request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GGUID | KAUTH_EXTLOOKUP_WANT_UID | KAUTH_EXTLOOKUP_WANT_GID; memcpy(&request.el_uguid, uu, sizeof(guid_t)); memcpy(&request.el_gguid, uu, sizeof(guid_t)); - result = _mbr_DoMembershipCall(GetServerPort(), &request, &token); - if (result != KERN_SUCCESS) return EIO; - if (token.val[0] != 0) return EAUTH; + + status = _mbr_MembershipCall(&request); + if (status != 0) return status; if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_UID) != 0) { @@ -124,194 +218,140 @@ int mbr_uuid_to_id(const uuid_t uu, uid_t *id, int *id_type) } else { - error = ENOENT; + return ENOENT; } - return error; + return 0; } int mbr_sid_to_uuid(const nt_sid_t *sid, uuid_t uu) { struct kauth_identity_extlookup request; - security_token_t token; - kern_return_t result; - int error = 0; + int status; - token.val[0] = -1; - token.val[1] = -1; - - request.el_seqno = 1; /* used as byte order field */ + request.el_seqno = 1; request.el_flags = KAUTH_EXTLOOKUP_VALID_GSID | KAUTH_EXTLOOKUP_WANT_GGUID; memset(&request.el_gsid, 0, sizeof(ntsid_t)); memcpy(&request.el_gsid, sid, KAUTH_NTSID_SIZE(sid)); - result = _mbr_DoMembershipCall(GetServerPort(), &request, &token); - if (result != KERN_SUCCESS) return EIO; - if (token.val[0] != 0) return EAUTH; - if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GGUID) != 0) - memcpy(uu, &request.el_gguid, sizeof(guid_t)); - else - error = ENOENT; + status = _mbr_MembershipCall(&request); + if (status != 0) return status; + if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GGUID) == 0) return ENOENT; - return error; + memcpy(uu, &request.el_gguid, sizeof(guid_t)); + return 0; } -int mbr_uuid_to_sid(const uuid_t uu, nt_sid_t *sid) +int mbr_uuid_to_sid_type(const uuid_t uu, nt_sid_t *sid, int *id_type) { struct kauth_identity_extlookup request; - security_token_t token; - kern_return_t result; - int error = 0; + int status; - token.val[0] = -1; - token.val[1] = -1; - - request.el_seqno = 1; /* used as byte order field */ - request.el_flags = KAUTH_EXTLOOKUP_VALID_GGUID | KAUTH_EXTLOOKUP_WANT_GSID; + request.el_seqno = 1; + request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GGUID | KAUTH_EXTLOOKUP_WANT_USID | KAUTH_EXTLOOKUP_WANT_GSID; + memcpy(&request.el_uguid, uu, sizeof(guid_t)); memcpy(&request.el_gguid, uu, sizeof(guid_t)); - result = _mbr_DoMembershipCall(GetServerPort(), &request, &token); - if (result != KERN_SUCCESS) return EIO; - if (token.val[0] != 0) return EAUTH; - if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GSID) != 0) + status = _mbr_MembershipCall(&request); + if (status != 0) return status; + + if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_USID) != 0) + { + *id_type = SID_TYPE_USER; + memcpy(sid, &request.el_usid, sizeof(nt_sid_t)); + } + else if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GSID) != 0) + { + *id_type = SID_TYPE_GROUP; memcpy(sid, &request.el_gsid, sizeof(nt_sid_t)); + } else - error = ENOENT; + { + return ENOENT; + } + + return 0; +} + +int mbr_uuid_to_sid(const uuid_t uu, nt_sid_t *sid) +{ + int type, status; - return error; + type = 0; + + status = mbr_uuid_to_sid_type(uu, sid, &type); + if (status != 0) return status; + + return 0; } int mbr_check_membership(uuid_t user, uuid_t group, int *ismember) { struct kauth_identity_extlookup request; - security_token_t token; - kern_return_t result; - int error = 0; - - token.val[0] = -1; - token.val[1] = -1; + int status; - request.el_seqno = 1; /* used as byte order field */ + request.el_seqno = 1; request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GGUID | KAUTH_EXTLOOKUP_WANT_MEMBERSHIP; memcpy(&request.el_uguid, user, sizeof(guid_t)); memcpy(&request.el_gguid, group, sizeof(guid_t)); - result = _mbr_DoMembershipCall(GetServerPort(), &request, &token); - if (result != KERN_SUCCESS) return EIO; - if (token.val[0] != 0) return EAUTH; - if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) != 0) - *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0); - else - error = ENOENT; + status = _mbr_MembershipCall(&request); + if (status != 0) return status; + if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) == 0) return ENOENT; - return error; + *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0); + return 0; } -int mbr_check_membership_refresh(uuid_t user, uuid_t group, int *ismember) +int mbr_check_membership_refresh(const uuid_t user, uuid_t group, int *ismember) { struct kauth_identity_extlookup request; - security_token_t token; - kern_return_t result; - int error = 0; + int status; - token.val[0] = -1; - token.val[1] = -1; - - request.el_seqno = 1; /* used as byte order field */ - request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GGUID | KAUTH_EXTLOOKUP_WANT_MEMBERSHIP | (1 << 15); + request.el_seqno = 1; + request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GGUID | KAUTH_EXTLOOKUP_WANT_MEMBERSHIP | (1<<15); memcpy(&request.el_uguid, user, sizeof(guid_t)); memcpy(&request.el_gguid, group, sizeof(guid_t)); - result = _mbr_DoMembershipCall(GetServerPort(), &request, &token); - if (result != KERN_SUCCESS) return EIO; - if (token.val[0] != 0) return EAUTH; - if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) != 0) - *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0); - else - error = ENOENT; + status = _mbr_MembershipCall(&request); + if (status != 0) return status; + if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) == 0) return ENOENT; - return error; + *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0); + return 0; } int mbr_check_membership_by_id(uuid_t user, gid_t group, int *ismember) { struct kauth_identity_extlookup request; - security_token_t token; - kern_return_t result; - int error = 0; - - token.val[0] = -1; - token.val[1] = -1; + int status; - request.el_seqno = 1; /* used as byte order field */ + request.el_seqno = 1; request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GID | KAUTH_EXTLOOKUP_WANT_MEMBERSHIP; memcpy(&request.el_uguid, user, sizeof(guid_t)); request.el_gid = group; - result = _mbr_DoMembershipCall(GetServerPort(), &request, &token); - if (result != KERN_SUCCESS) return EIO; - if (token.val[0] != 0) return EAUTH; - if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) != 0) - *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0); - else - error = ENOENT; + status = _mbr_MembershipCall(&request); + if (status != 0) return status; + if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) == 0) return ENOENT; - return error; + *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0); + return 0; } int mbr_reset_cache() { - security_token_t token; - kern_return_t result; - - token.val[0] = -1; - token.val[1] = -1; - - result = _mbr_ClearCache(GetServerPort(), &token); - if (result != KERN_SUCCESS) return EIO; - if (token.val[0] != 0) return EAUTH; - - return 0; + return _mbr_ClearCache(); } int mbr_user_name_to_uuid(const char *name, uuid_t uu) { - security_token_t token; - kern_return_t result; - - if (name == NULL) return EINVAL; - if (strlen(name) > 255) return EINVAL; - - token.val[0] = -1; - token.val[1] = -1; - - result = _mbr_MapName(GetServerPort(), 1, (char *)name, (guid_t *)uu, &token); - if (result == KERN_FAILURE) return ENOENT; - else if (result != KERN_SUCCESS) return EIO; - - if (token.val[0] != 0) return EAUTH; - - return 0; + return _mbr_MapName((char *)name, 1, (guid_t *)uu); } int mbr_group_name_to_uuid(const char *name, uuid_t uu) { - security_token_t token; - kern_return_t result; - - if (name == NULL) return EINVAL; - if (strlen(name) > 255) return EINVAL; - - token.val[0] = -1; - token.val[1] = -1; - - result = _mbr_MapName(GetServerPort(), 0, (char *)name, (guid_t *)uu, &token); - if (result == KERN_FAILURE) return ENOENT; - else if (result != KERN_SUCCESS) return EIO; - - if (token.val[0] != 0) return EAUTH; - - return 0; + return _mbr_MapName((char *)name, 0, (guid_t *)uu); } int mbr_check_service_membership(const uuid_t user, const char *servicename, int *ismember) @@ -323,7 +363,7 @@ int mbr_check_service_membership(const uuid_t user, const char *servicename, int int result, dummy; if (servicename == NULL) return EINVAL; - if (strlen(servicename) > (255 - strlen(prefix))) return EINVAL; + if (strlen(servicename) > 255 - strlen(prefix)) return EINVAL; /* start by checking "all services" */ result = mbr_group_name_to_uuid(all_services, group_uu); @@ -362,7 +402,8 @@ static char *ConvertBytesToDecimal(char *buffer, unsigned long long value) buffer[24] = '\0'; buffer[23] = '0'; - if (value == 0) return &buffer[23]; + if (value == 0) + return &buffer[23]; temp = &buffer[24]; while (value != 0) @@ -396,7 +437,7 @@ int mbr_sid_to_string(const nt_sid_t *sid, char *string) current++; strcpy(current, ConvertBytesToDecimal(tempBuffer, temp)); - for (i = 0; i < sid->sid_authcount; i++) + for(i=0; i < sid->sid_authcount; i++) { current = current + strlen(current); *current = '-'; @@ -409,12 +450,14 @@ int mbr_sid_to_string(const nt_sid_t *sid, char *string) int mbr_string_to_sid(const char *string, nt_sid_t *sid) { - char *current = string+2; + char *current = (char *)string+2; int count = 0; long long temp; + if (string == NULL) return EINVAL; + memset(sid, 0, sizeof(nt_sid_t)); - if ((string[0] != 'S') || (string[1] != '-')) return EINVAL; + if (string[0] != 'S' || string[1] != '-') return EINVAL; sid->sid_kind = strtol(current, ¤t, 10); if (*current == '\0') return EINVAL; @@ -424,7 +467,7 @@ int mbr_string_to_sid(const char *string, nt_sid_t *sid) /* convert to BigEndian before copying */ temp = OSSwapHostToBigInt64(temp); memcpy(sid->sid_authority, ((char*)&temp)+2, 6); - while ((*current != '\0') && (count < NTSID_MAX_AUTHORITIES)) + while (*current != '\0' && count < NTSID_MAX_AUTHORITIES) { current++; sid->sid_authorities[count] = strtol(current, ¤t, 10); @@ -442,7 +485,7 @@ static void ConvertBytesToHex(char **string, char **data, int numBytes) { int i; - for (i = 0; i < numBytes; i++) + for (i=0; i < numBytes; i++) { unsigned char hi = ((**data) >> 4) & 0xf; unsigned char low = (**data) & 0xf; @@ -465,7 +508,7 @@ static void ConvertBytesToHex(char **string, char **data, int numBytes) int mbr_uuid_to_string(const uuid_t uu, char *string) { - char *guid = (char *)uu; + char *guid = (char*)uu; char *strPtr = string; ConvertBytesToHex(&strPtr, &guid, 4); *strPtr = '-'; strPtr++; @@ -486,28 +529,23 @@ int mbr_string_to_uuid(const char *string, uuid_t uu) short dataIndex = 0; int isFirstNibble = 1; - if (strlen(string) > MBR_UU_STRING_SIZE) - return EINVAL; + if (string == NULL) return EINVAL; + if (strlen(string) > MBR_UU_STRING_SIZE) return EINVAL; while (*string != '\0' && dataIndex < 16) { char nibble; - if ((*string >= '0') && (*string <= '9')) - { + if (*string >= '0' && *string <= '9') nibble = *string - '0'; - } - else if ((*string >= 'A') && (*string <= 'F')) - { + else if (*string >= 'A' && *string <= 'F') nibble = *string - 'A' + 10; - } - else if ((*string >= 'a') && (*string <= 'f')) - { + else if (*string >= 'a' && *string <= 'f') nibble = *string - 'a' + 10; - } else { - if (*string != '-') return EINVAL; + if (*string != '-') + return EINVAL; string++; continue; } @@ -531,3 +569,4 @@ int mbr_string_to_uuid(const char *string, uuid_t uu) return 0; } + diff --git a/membership.subproj/membershipPriv.h b/membership.subproj/membershipPriv.h index 580b8db..35a6fe3 100644 --- a/membership.subproj/membershipPriv.h +++ b/membership.subproj/membershipPriv.h @@ -26,18 +26,26 @@ #include #include -int mbr_reset_cache(); -int mbr_user_name_to_uuid(const char* name, uuid_t uu); -int mbr_group_name_to_uuid(const char* name, uuid_t uu); -int mbr_check_membership_by_id(uuid_t user, gid_t group, int* ismember); -int mbr_check_service_membership(const uuid_t user, const char* servicename, int* ismember); - #define MBR_UU_STRING_SIZE 37 #define MBR_MAX_SID_STRING_SIZE 200 -int mbr_uuid_to_string(const uuid_t uu, char* string); -int mbr_string_to_uuid(const char* string, uuid_t uu); -int mbr_sid_to_string(const nt_sid_t* sid, char* string); -int mbr_string_to_sid(const char* string, nt_sid_t* sid); +#define SID_TYPE_USER 0 +#define SID_TYPE_GROUP 1 + +__BEGIN_DECLS + +int mbr_reset_cache(); +int mbr_user_name_to_uuid(const char *name, uuid_t uu); +int mbr_group_name_to_uuid(const char *name, uuid_t uu); +int mbr_check_membership_by_id(uuid_t user, gid_t group, int *ismember); +int mbr_check_service_membership(const uuid_t user, const char *servicename, int *ismember); +int mbr_check_membership_refresh(const uuid_t user, uuid_t group, int *ismember); +int mbr_uuid_to_string(const uuid_t uu, char *string); +int mbr_string_to_uuid(const char *string, uuid_t uu); +int mbr_sid_to_string(const nt_sid_t *sid, char *string); +int mbr_string_to_sid(const char *string, nt_sid_t *sid); +int mbr_uuid_to_sid_type(const uuid_t uu, nt_sid_t *sid, int *id_type); + +__END_DECLS #endif /* !_MEMBERSHIPPRIV_H_ */ diff --git a/netinfo.subproj/Makefile b/netinfo.subproj/Makefile index 015435b..1be3dea 100644 --- a/netinfo.subproj/Makefile +++ b/netinfo.subproj/Makefile @@ -12,14 +12,10 @@ NAME = netinfo PROJECTVERSION = 2.8 PROJECT_TYPE = Component -HFILES = clib.h mm.h ni.h ni_util.h sys_interfaces.h - -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 netinfo.3 netinfo.5 +HFILES = +CFILES = ni_stub.c +OTHERSRCS = Makefile Makefile.preamble MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles CODE_GEN_STYLE = DYNAMIC @@ -28,12 +24,9 @@ LIBS = DEBUG_LIBS = $(LIBS) PROF_LIBS = $(LIBS) - -PRIVATE_HEADERS = ni.h ni_util.h nibind_prot.x ni_prot.x - - - -NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +PRIVATE_HEADERS = +# NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER) WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc NEXTSTEP_JAVA_COMPILER = /usr/bin/javac diff --git a/netinfo.subproj/Makefile.postamble b/netinfo.subproj/Makefile.postamble deleted file mode 100644 index 0c5d83e..0000000 --- a/netinfo.subproj/Makefile.postamble +++ /dev/null @@ -1,12 +0,0 @@ -MAN3DIR=/usr/share/man/man3 -MAN5DIR=/usr/share/man/man5 - -install-netinfo-man: - 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 - -%_xdr.c: %.x - $(RPCGEN) $(ALL_RPCFLAGS) -c -o $(SYM_DIR)/$*_xdr.c $*.x diff --git a/netinfo.subproj/Makefile.preamble b/netinfo.subproj/Makefile.preamble index 8637aab..004b71b 100644 --- a/netinfo.subproj/Makefile.preamble +++ b/netinfo.subproj/Makefile.preamble @@ -1,10 +1,4 @@ -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_PRIVATE_HEADERS = $(NETINFO_HEADERS) -BEFORE_INSTALLHEADERS += $(NETINFO_HEADERS) -PRIVATE_HEADER_DIR = /usr/local/include/netinfo +OTHER_CFLAGS += -D__DARWIN_NON_CANCELABLE=1 # for building 64-bit # Libinfo need to build with gcc-3.5 and 3-way fat diff --git a/netinfo.subproj/PB.project b/netinfo.subproj/PB.project index a527e89..0d879af 100644 --- a/netinfo.subproj/PB.project +++ b/netinfo.subproj/PB.project @@ -1,18 +1,10 @@ { DYNAMIC_CODE_GEN = YES; 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, - netinfo.3, - netinfo.5 - ); - PRIVATE_HEADERS = (ni.h, ni_util.h, ni_prot.x, nibind_prot.x); + H_FILES = (); + OTHER_LINKED = (ni_stub.c); + OTHER_SOURCES = (Makefile.preamble, Makefile); + PRIVATE_HEADERS = (); }; LANGUAGE = English; MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; diff --git a/netinfo.subproj/clib.h b/netinfo.subproj/clib.h deleted file mode 100644 index c9db33b..0000000 --- a/netinfo.subproj/clib.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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@ - */ -/* - * Standard libc stuff used by source files in this directory - * Copyright (C) 1989 by NeXT, Inc. - */ - -enum clnt_stat multi_call(unsigned, - struct in_addr *, unsigned long, unsigned long, unsigned long, - xdrproc_t, void *, unsigned, xdrproc_t, - void *, - int (*)(), int); -//bool_t xdr_free(xdrproc_t, void *); diff --git a/netinfo.subproj/mm.h b/netinfo.subproj/mm.h deleted file mode 100644 index 7c32dee..0000000 --- a/netinfo.subproj/mm.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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@ - */ -/* - * Useful memory managment macros - * Copyright (C) 1989 by NeXT, Inc. - */ -#define mm_used() mstats() - -#define MM_ALLOC(obj) obj = ((void *)malloc(sizeof(*(obj)))) - -#define MM_FREE(obj) free((void *)(obj)) - -#define MM_ZERO(obj) bzero((void *)(obj), sizeof(*(obj))) - -#define MM_BCOPY(b1, b2, size) bcopy((void *)(b1), (void *)(b2), \ - (unsigned)(size)) - -#define MM_BEQ(b1, b2, size) (bcmp((void *)(b1), (void *)(b2), \ - (unsigned)(size)) == 0) - -#define MM_ALLOC_ARRAY(obj, len) \ - obj = ((void *)malloc(sizeof(*(obj)) * (len))) - -#define MM_ZERO_ARRAY(obj, len) bzero((void *)(obj), sizeof(*obj) * len) - -#define MM_FREE_ARRAY(obj, len) free((void *)(obj)) - -#define MM_GROW_ARRAY(obj, len) \ - ((obj == NULL) ? (MM_ALLOC_ARRAY((obj), (len) + 1)) : \ - (obj = (void *)realloc((void *)(obj), \ - sizeof(*(obj)) * ((len) + 1)))) - -#define MM_SHRINK_ARRAY(obj, len) \ - obj = (void *)realloc((void *)(obj), \ - sizeof(*(obj)) * ((len) - 1)) - diff --git a/netinfo.subproj/multi_call.c b/netinfo.subproj/multi_call.c deleted file mode 100644 index 2d12086..0000000 --- a/netinfo.subproj/multi_call.c +++ /dev/null @@ -1,352 +0,0 @@ -/* - * 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@ - */ -/* - * multi_call: send out multiple call messages, wait for first reply - * Copyright (C) 1991 by NeXT, Inc. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef NETINFOD -# include "socket_lock.h" -# include "clib.h" -# define multi_call _multi_call -#else -# define socket_lock() -# define socket_unlock() -# include "clib.h" -#endif - - -#define NRETRIES 5 -#define USECS_PER_SEC 1000000 - - -/* - * Wrapper for gethostname() syscall - */ -static char * -get_hostname(void) -{ - int len; - static char hostname[MAXHOSTNAMELEN + 1]; - - len = gethostname(hostname, sizeof(hostname)); - if (len < 0) { - hostname[0] = 0; - } else { - hostname[len] = 0; - } - return (hostname); -} - - -/* - * Encode a call message - */ -static int -encodemsg( - char *buf, - int buflen, - struct rpc_msg *call, - unsigned prognum, - unsigned versnum, - unsigned procnum, - xdrproc_t xdr_args, - void *arg - ) -{ - XDR xdr; - unsigned size; - unsigned pos; - - xdrmem_create(&xdr, buf, buflen, XDR_ENCODE); - if (!xdr_callmsg(&xdr, call) || - !xdr_u_int(&xdr, &prognum) || - !xdr_u_int(&xdr, &versnum) || - !xdr_u_int(&xdr, &procnum)) { - return (0); - } - pos = xdr_getpos(&xdr); - xdr_setpos(&xdr, pos + BYTES_PER_XDR_UNIT); - if (!(*xdr_args)(&xdr, arg)) { - return (0); - } - size = xdr_getpos(&xdr) - pos; - xdr_setpos(&xdr, pos); - if (!xdr_u_int(&xdr, &size)) { - return (0); - } - return (pos + BYTES_PER_XDR_UNIT + size); -} - -/* - * Decode a reply message - */ -static int -decodemsg( - XDR *xdr, - xdrproc_t xdr_res, - void *res - ) -{ - unsigned port; - unsigned len; - long *buf; - XDR bufxdr; - - if (!xdr_u_int(xdr, &port) || - !xdr_u_int(xdr, &len) || - !(buf = (long *)xdr_inline(xdr, len))) { - return (0); - } - xdrmem_create(&bufxdr, (char *)buf, len * BYTES_PER_XDR_UNIT, - XDR_DECODE); - if (!(*xdr_res)(&bufxdr, res)) { - return (0); - } - return (1); - -} - -/* - * Do the real work - */ -enum clnt_stat -multi_call( - unsigned naddrs, - struct in_addr *addrs, - u_long prognum, - u_long versnum, - u_long procnum, - xdrproc_t xdr_args, - void *argsvec, - unsigned argsize, - xdrproc_t xdr_res, - void *res, - int (*eachresult)(void *, struct sockaddr_in *, int), - int timeout - ) -{ - struct authunix_parms aup; - char credbuf[MAX_AUTH_BYTES]; - struct opaque_auth cred; - struct opaque_auth verf; - int gids[NGROUPS]; - int s; - struct timeval tv; - struct timeval subtimeout; - unsigned long long utimeout; - int callno; - int serverno; - struct rpc_msg call; - struct rpc_msg reply; - struct sockaddr_in sin; - struct sockaddr_in from; - int fromsize; - char buf[UDPMSGSIZE]; - int buflen; - unsigned trans_id; - int dtablesize = getdtablesize(); - XDR xdr; - int sendlen; - fd_set fds; - - /* - * Fill in Unix auth stuff - */ - aup.aup_time = time(0); - aup.aup_machname = get_hostname(); - aup.aup_uid = getuid(); - aup.aup_gid = getgid(); - aup.aup_gids = gids; - aup.aup_len = getgroups(NGROUPS, aup.aup_gids); - - /* - * Encode unix auth - */ - xdrmem_create(&xdr, credbuf, sizeof(credbuf), XDR_ENCODE); - if (!xdr_authunix_parms(&xdr, &aup)) { - return (RPC_CANTENCODEARGS); - } - cred.oa_flavor = AUTH_UNIX; - cred.oa_base = credbuf; - cred.oa_length = xdr_getpos(&xdr); - - verf.oa_flavor = AUTH_NULL; - verf.oa_length = 0; - - /* - * Set up call header information - */ - trans_id = time(0) ^ getpid(); - call.rm_xid = trans_id; - call.rm_direction = CALL; - call.rm_call.cb_rpcvers = 2; - call.rm_call.cb_prog = PMAPPROG; - call.rm_call.cb_vers = PMAPVERS; - call.rm_call.cb_proc = PMAPPROC_CALLIT; - call.rm_call.cb_cred = cred; - call.rm_call.cb_verf = verf; - - - /* - * Open socket - */ - socket_lock(); - s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - socket_unlock(); - if (s < 0) { - syslog(LOG_ERR, "multi_call: socket: %m"); - return (RPC_FAILED); - } - - /* - * Init timeouts - */ - utimeout = ((unsigned long long) timeout) * USECS_PER_SEC; - subtimeout.tv_sec = (utimeout >> NRETRIES) / USECS_PER_SEC; - subtimeout.tv_usec = (utimeout >> NRETRIES) % USECS_PER_SEC; - tv = subtimeout; - - /* - * Init address info - */ - sin.sin_family = AF_INET; - sin.sin_port = htons(PMAPPORT); - bzero(sin.sin_zero, sizeof(sin.sin_zero)); - - for (callno = 0; callno <= NRETRIES; callno++) { - /* - * Send a call message to each host with the appropriate args - */ - for (serverno = 0; serverno < naddrs; serverno++) { - call.rm_xid = trans_id + serverno; - buflen = encodemsg(buf, sizeof(buf), &call, - prognum, versnum, procnum, - xdr_args, (argsvec + - (serverno * argsize))); - if (buflen == 0) { - /* - * Encode failed - */ - continue; - } - sin.sin_addr = addrs[serverno]; - sendlen = sendto(s, buf, buflen, 0, - (struct sockaddr *)&sin, sizeof(sin)); - if (sendlen != buflen) { - syslog(LOG_ERR, - "Cannot send multicall packet to %s: %m", - inet_ntoa(addrs[serverno])); - } - } - - /* - * Double the timeout from previous timeout, if necessary - */ - if (callno > 1) { - tv.tv_sec *= 2; - tv.tv_usec *= 2; - if (tv.tv_usec >= USECS_PER_SEC) { - tv.tv_usec -= USECS_PER_SEC; - tv.tv_sec++; - } - } - - -#ifdef NETINFOD - /* - * Check for cancel by user - */ - if (alert_aborted()) { - socket_lock(); - close(s); - socket_unlock(); - return (RPC_FAILED); - } -#endif - /* - * Wait for reply - */ - FD_ZERO(&fds); - FD_SET(s, &fds); - switch (select(dtablesize, &fds, NULL, NULL, &tv)) { - case -1: - syslog(LOG_ERR, "select failure: %m"); - continue; - case 0: - continue; - default: - break; - } - - /* - * Receive packet - */ - fromsize = sizeof(from); - buflen = recvfrom(s, buf, sizeof(buf), 0, - (struct sockaddr *)&from, &fromsize); - if (buflen < 0) { - continue; - } - - /* - * Decode packet and if no errors, call eachresult - */ - xdrmem_create(&xdr, buf, buflen, XDR_DECODE); - reply.rm_reply.rp_acpt.ar_results.proc = xdr_void; - reply.rm_reply.rp_acpt.ar_results.where = NULL; - if (xdr_replymsg(&xdr, &reply) && - (reply.rm_xid >= trans_id) && - (reply.rm_xid < trans_id + naddrs) && - (reply.rm_reply.rp_stat == MSG_ACCEPTED) && - (reply.acpted_rply.ar_stat == SUCCESS) && - decodemsg(&xdr, xdr_res, res)) { - if ((*eachresult)(res, &from, - reply.rm_xid - trans_id)) { - xdr_free(xdr_res, res); - socket_lock(); - close(s); - socket_unlock(); - return (RPC_SUCCESS); - } - } - xdr_free(xdr_res, res); - } - socket_lock(); - close(s); - socket_unlock(); - return (RPC_TIMEDOUT); -} - - - - diff --git a/netinfo.subproj/netinfo.3 b/netinfo.subproj/netinfo.3 deleted file mode 100644 index 50486b7..0000000 --- a/netinfo.subproj/netinfo.3 +++ /dev/null @@ -1,425 +0,0 @@ -.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 deleted file mode 100644 index aea5803..0000000 --- a/netinfo.subproj/netinfo.5 +++ /dev/null @@ -1,278 +0,0 @@ -.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.h b/netinfo.subproj/ni.h deleted file mode 100644 index 8f364e6..0000000 --- a/netinfo.subproj/ni.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * 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@ - */ -/* - * NetInfo library entry points - * Copyright (C) 1989 by NeXT, Inc. - */ - -#ifndef __NI_HEADER__ -#define __NI_HEADER__ - -#ifndef SUN_RPC -#define SUN_RPC 1 -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -typedef const char *ni_name_const; -#include - -/* - * Define some shortcuts - */ -#define ninl_len ni_namelist_len -#define ninl_val ni_namelist_val - -#define nipl_len ni_proplist_len -#define nipl_val ni_proplist_val - -#define niil_len ni_idlist_len -#define niil_val ni_idlist_val - -#define niel_len ni_entrylist_len -#define niel_val ni_entrylist_val - -#define nipll_len ni_proplist_list_len -#define nipll_val ni_proplist_list_val - -/* - * Arg struct for ni_fancyopen - */ -typedef struct ni_fancyopenargs { - int rtimeout; /* read timeout - 0 for default */ - int wtimeout; /* write timeout - 0 for default */ - int abort; /* give up on timeout or failure? */ - int needwrite; /* need to do writes on this handle? */ -} ni_fancyopenargs; - - -void *ni_new(void *, const char *); -void *ni_connect(struct sockaddr_in *, const char *); -ni_status ni_addrtag(void *, struct sockaddr_in *, ni_name *); -void ni_free(void *); -const char *ni_error(ni_status); - -ni_status ni_statistics(void *, ni_proplist *); -ni_status ni_root(void *, ni_id *); -ni_status ni_self(void *, ni_id *); -ni_status ni_parent(void *, ni_id *, ni_index *); - -ni_status ni_create(void *, ni_id *, ni_proplist, ni_id *, ni_index); -ni_status ni_destroy(void *, ni_id *, ni_id); - -ni_status ni_read(void *, ni_id *, ni_proplist *); -ni_status ni_write(void *, ni_id *, ni_proplist); - -ni_status ni_children(void *, ni_id *, ni_idlist *); -ni_status ni_list(void *, ni_id *, ni_name_const, ni_entrylist *); -ni_status ni_listall(void *, ni_id *, ni_proplist_list *); -ni_status ni_lookup(void *, ni_id *, ni_name_const, ni_name_const, - ni_idlist *); -ni_status ni_lookupread(void *, ni_id *, ni_name_const, ni_name_const, - ni_proplist *); -ni_status ni_lookupprop(void *, ni_id *, ni_name_const, ni_namelist *); -ni_status ni_renameprop(void *, ni_id *, ni_index, ni_name_const); -ni_status ni_listprops(void *, ni_id *, ni_namelist *); - -ni_status ni_createprop(void *, ni_id *, ni_property, ni_index); -ni_status ni_destroyprop(void *, ni_id *, ni_index); -ni_status ni_readprop(void *, ni_id *, ni_index, ni_namelist *); -ni_status ni_writeprop(void *, ni_id *, ni_index, ni_namelist); - -ni_status ni_createname(void *, ni_id *, ni_index, ni_name_const, ni_index); -ni_status ni_destroyname(void *, ni_id *, ni_index, ni_index); -ni_status ni_readname(void *, ni_id *, ni_index, ni_index, ni_name *); -ni_status ni_writename(void *, ni_id *, ni_index, ni_index, ni_name_const); - -ni_status ni_pathsearch(void *, ni_id *, ni_name_const); -ni_status ni_open(void *, ni_name_const, void **); -ni_status ni_fancyopen(void *, ni_name_const, void **, ni_fancyopenargs *); - -ni_status ni_pwdomain(void *, ni_name *); - -ni_status ni_resync(void *); - -ni_status ni_setuser(void *, ni_name_const); -ni_status ni_setpassword(void *, ni_name_const); -void ni_setreadtimeout(void *, int); -void ni_setwritetimeout(void *, int); -void ni_setabort(void *, int); -void ni_needwrite(void *, int); - -#ifdef __cplusplus -} -#endif - -#endif __NI_HEADER__ - diff --git a/netinfo.subproj/ni_error.c b/netinfo.subproj/ni_error.c deleted file mode 100644 index 63aaff8..0000000 --- a/netinfo.subproj/ni_error.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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@ - */ -/* - * NetInfo error status -> string conversion. - * Copyright (C) 1989 by NeXT, Inc. - */ -#include - -static const struct { - ni_status status; - char *message; -} ni_errmsgs[] = { - { NI_OK, "Operation succeeded" }, - { NI_BADID, "ID is invalid" }, - { NI_STALE, "Write attempted on stale version of object" }, - { NI_NOSPACE, "No space available for write operation" }, - { NI_PERM, "Permission denied" }, - { NI_NODIR, "No such directory" }, - { NI_NOPROP, "No such property" }, - { NI_NONAME, "No such name" }, - { NI_NOTEMPTY, "Cannot delete name object with children" }, - { NI_UNRELATED, "Object is not child of parent: cannot destroy" }, - { NI_SERIAL, "Serialization error" }, - { NI_NETROOT, "Hit network root domain" }, - { NI_NORESPONSE, "No response from remote parent" }, - { NI_RDONLY, "No writes allowed: all objects are read-only" }, - { NI_SYSTEMERR, "Remote system error" }, - { NI_ALIVE, "Can't regenerate: already in use" }, - { NI_NOTMASTER, "Operation makes no sense on clone" }, - { NI_CANTFINDADDRESS, "Can't find address of server" }, - { NI_DUPTAG, "Duplicate domain tag: can't serve it" }, - { NI_NOTAG, "No such tag" }, - { NI_AUTHERROR, "Authentication error" }, - { NI_NOUSER, "No such user" }, - { NI_MASTERBUSY, "Master server is busy" }, - { NI_INVALIDDOMAIN, "Invalid domain" }, - { NI_BADOP, "Invalid operation on master" }, - { NI_FAILED, "Communication failure" } -}; - -#define NI_ERRMSGSZ (sizeof(ni_errmsgs)/sizeof(ni_errmsgs[0])) - -const char * -ni_error( - ni_status status - ) -{ - int i; - - for (i = 0; i < NI_ERRMSGSZ; i++) { - if (ni_errmsgs[i].status == status) { - return (ni_errmsgs[i].message); - } - } - return ("(unknown error)"); -} diff --git a/netinfo.subproj/ni_glue.c b/netinfo.subproj/ni_glue.c deleted file mode 100644 index 43c146d..0000000 --- a/netinfo.subproj/ni_glue.c +++ /dev/null @@ -1,2325 +0,0 @@ -/* - * 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@ - */ -/* - * Glues the library routines to the stub routines - * Copyright (C) 1989 by NeXT, Inc. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "clib.h" -#include "sys_interfaces.h" - -#define LOCAL_PORT 1033 - -#define NI_TIMEOUT_SHORT 5 /* 5 second timeout for transactions */ -#define NI_TIMEOUT_LONG 60 /* 60 second timeout for writes */ -#define NI_TRIES 5 /* number of retries per timeout (udp only) */ -#define NI_SLEEPTIME 4 /* 4 second sleeptime, in case of errors */ -#define NI_MAXSLEEPTIME 16 /* 16 second max sleep time */ -#define NI_MAXCONNTRIES 2 /* Try to form a connection twice before sleeping */ - -/* Hack for determining if an IP address is a broadcast address. -GRS */ -/* Note that addr is network byte order (big endian) - BKM */ - -#define IS_BROADCASTADDR(addr) (((unsigned char *) &addr)[0] == 0xFF) - -#ifndef INADDR_LOOPBACK -#define INADDR_LOOPBACK (u_long)0x7f000001 -#endif -#define debug(msg) syslog(LOG_ERR, msg) - -#define clnt_debug(ni, msg) /* do nothing */ - -typedef struct ni_private -{ - int naddrs; /* number of addresses */ - struct in_addr *addrs; /* addresses of servers - network byte order */ - int whichwrite; /* which one of the above is the master */ - ni_name *tags; /* tags of servers */ - int pid; /* pid, to detect forks */ - int tsock; /* tcp socket */ - int tport; /* tcp local port name - host byte order */ - CLIENT *tc; /* tcp client */ - long tv_sec; /* timeout for this call */ - long rtv_sec; /* read timeout - 0 if default */ - long wtv_sec; /* write timeout - 0 if default */ - int abort; /* abort on timeout? */ - int needwrite; /* need to lock writes? */ - int uid; /* user id */ - ni_name passwd; /* password */ -} ni_private; - -#define NIP(ni) ((ni_private *)(ni)) - -#define RCALLIT(a, b, c) callit((ni_private *)(a), (void *(*)())(b), (void *)c, 0) -#define WCALLIT(a, b, c) callit((ni_private *)(a), (void *(*)())(b), (void *)c, 1) - -static const ni_name NAME_NAME = "name"; -static const ni_name NAME_SERVES = "serves"; -static const ni_name NAME_MACHINES = "machines"; -static const ni_name NAME_IP_ADDRESS = "ip_address"; -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; -} getreg_stuff; - -static int socket_open(struct sockaddr_in *raddr, int, int, int, int, int); -extern int bindresvport(int, struct sockaddr_in *); - -/* - * Keep track of our port, in case somebody closes our socket on us. - */ -static int -getmyport(int sock) -{ - struct sockaddr_in sin; - int sinlen; - - sinlen = sizeof(struct sockaddr_in); - if (getsockname(sock, (struct sockaddr *)&sin, &sinlen) != 0) return -1; - - if (sin.sin_port == 0) - { - if (bind(sock, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) != 0) return -1; - - sinlen = sizeof(struct sockaddr_in); - if (getsockname(sock, (struct sockaddr *)&sin, &sinlen) != 0) return -1; - } - - return ntohs(sin.sin_port); -} - - -static void -createauth(ni_private *ni) -{ - if (ni->passwd != NULL && ni->tc != NULL) - { - auth_destroy(ni->tc->cl_auth); - ni->tc->cl_auth = authunix_create(ni->passwd, ni->uid, 0, 0, NULL); - } -} - - -static void -fixtimeout(struct timeval *tv, long sec, int tries) -{ - tv->tv_sec = sec / tries; - tv->tv_usec = ((sec % tries) * 1000000) / tries; -} - - -static void -ni_settimeout(ni_private *ni, int timeout) -{ - struct timeval tv; - - tv.tv_sec = timeout; - tv.tv_usec = 0; - ni->tv_sec = timeout; - if (ni->tc != NULL) clnt_control(ni->tc, CLSET_TIMEOUT, (char *)&tv); -} - - -/* - * Connect to a given address/tag - */ -static int -connectit(ni_private *ni) -{ - struct sockaddr_in sin; - int sock, islocal; - CLIENT *cl; - struct timeval tv; - enum clnt_stat stat; - nibind_getregister_res res; - interface_list_t *ilist; - - sock = -1; - bzero(&sin, sizeof(sin)); - sin.sin_port = 0; - sin.sin_family = AF_INET; - - tv.tv_sec = ni->rtv_sec == 0 ? NI_TIMEOUT_SHORT : ni->rtv_sec; - tv.tv_usec = 0; - - ni_settimeout(ni, tv.tv_sec); - fixtimeout(&tv, ni->tv_sec, NI_TRIES); - - /* - * If connecting to local domain, try using the "well-known" port first. - */ - islocal = 0; - - if (!strcmp(ni->tags[0], "local")) - { - if (ni->addrs[0].s_addr == htonl(INADDR_LOOPBACK)) - { - islocal = 1; - } - else - { - ilist = _libinfo_ni_sys_interfaces(); - if (_libinfo_ni_sys_is_my_address(ilist, &ni->addrs[0])) islocal = 1; - _libinfo_ni_sys_interfaces_release(ilist); - } - - if (islocal != 0) - { - sin.sin_port = htons(LOCAL_PORT); - sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sock = socket_open(&sin, NI_PROG, NI_VERS, ni->tv_sec, NI_TRIES, IPPROTO_TCP); - } - } - - /* - * If connecting to a domain other than the local domain, * or if connection to local didn't work with local's well-known port, * then go through portmap & nibindd to find the port and connect. - */ - if (sock < 0) - { - sin.sin_port = 0; - sin.sin_addr = ni->addrs[0]; - - sock = socket_open(&sin, NIBIND_PROG, NIBIND_VERS, ni->tv_sec, NI_TRIES, IPPROTO_UDP); - if (sock < 0) return 0; - - cl = clntudp_create(&sin, NIBIND_PROG, NIBIND_VERS, tv, &sock); - if (cl == NULL) - { - close(sock); - return 0; - } - - tv.tv_sec = ni->rtv_sec == 0 ? NI_TIMEOUT_SHORT : ni->rtv_sec; - tv.tv_usec = 0; - - stat = clnt_call(cl, NIBIND_GETREGISTER, (xdrproc_t)xdr_ni_name, (char *)&ni->tags[0], (xdrproc_t)xdr_nibind_getregister_res, (char *)&res, tv); - clnt_destroy(cl); - close(sock); - if (stat != RPC_SUCCESS || res.status != NI_OK) return 0; - - sin.sin_port = htons(res.nibind_getregister_res_u.addrs.tcp_port); - sock = socket_open(&sin, NI_PROG, NI_VERS, ni->tv_sec, NI_TRIES, IPPROTO_TCP); - } - - if (sock < 0) return 0; - - cl = clnttcp_create(&sin, NI_PROG, NI_VERS, &sock, 0, 0); - if (cl == NULL) - { - close(sock); - return 0; - } - - clnt_control(cl, CLSET_TIMEOUT, (char *)&tv); - ni->tc = cl; - ni->tsock = sock; - ni->tport = getmyport(sock); - createauth(ni); - fcntl(ni->tsock, F_SETFD, 1); - return 1; -} - - -void -ni_setabort(void *ni, int abort) -{ - if (ni == NULL) return; - - ((ni_private *)ni)->abort = abort; -} - - -void -ni_setwritetimeout(void *ni, int timeout) -{ - if (ni == NULL) return; - - ((ni_private *)ni)->wtv_sec = timeout; -} - - -void -ni_setreadtimeout(void *ni, int timeout) -{ - if (ni == NULL) return; - - ((ni_private *)ni)->rtv_sec = timeout; -} - - -void -ni_needwrite(void *ni, int needwrite) -{ - if (ni == NULL) return; - - ((ni_private *)ni)->needwrite = needwrite; -} - - -/* - * Returns a client handle to the NetInfo server, if it's running - */ -static int -connectlocal(ni_private *ni) -{ - int printed = 0; - - ni->naddrs = 1; - ni->addrs = (struct in_addr *)malloc(sizeof(struct in_addr)); - ni->addrs[0].s_addr = htonl(INADDR_LOOPBACK); - ni->tags = (ni_name *)malloc(sizeof(ni_name)); - ni->tags[0] = ni_name_dup("local"); - ni->whichwrite = 0; - - while (connectit(ni) == 0) - { - if (printed == 0) - { - syslog(LOG_ERR, "NetInfo timeout connecting to local domain, sleeping"); - printed = 1; - } - - sleep(NI_SLEEPTIME); - /* wait forever */ - } - - if (printed != 0) syslog(LOG_INFO, "NetInfo connection to local domain waking"); - - return 1; -} - - -/* - * Destroy the client handle - */ -static void -clnt_kill(CLIENT *cl, int sock, int port) -{ - int save = 0; - int p; - - p = getmyport(sock); - - if ((sock >= 0) && (p != -1) && (p != port)) - { - /* Somebody has the reused the socket. */ - save = 1; - } - - if (cl != NULL) - { - if (cl->cl_auth != NULL) auth_destroy(cl->cl_auth); - clnt_destroy(cl); - } - - if (save == 0) close(sock); -} - - -/* - * Reinitialize everything - */ -static void -reinit(ni_private *ni) -{ - if (ni == NULL) return; - - if (ni->tc != NULL) - { - clnt_kill(ni->tc, ni->tsock, ni->tport); - ni->tc = NULL; - } - - ni->tsock = -1; - ni->tport = -1; - ni->pid = getpid(); -} - - -/* - * Switch to a new server - */ -static void -ni_switch(ni_private *ni, ni_index which) -{ - struct in_addr tmp_addr; - ni_name tmp_tag; - - if (ni == NULL) return; - if (which == 0) return; - - reinit(ni); - tmp_addr = ni->addrs[0]; - tmp_tag = ni->tags[0]; - - ni->addrs[0] = ni->addrs[which]; - ni->tags[0] = ni->tags[which]; - - ni->addrs[which] = tmp_addr; - ni->tags[which] = tmp_tag; - - if (ni->whichwrite == 0) ni->whichwrite = which; - else if (ni->whichwrite == which) ni->whichwrite = 0; -} - - -/* - * Swap two servers' positions - */ -static void -ni_swap(ni_private *ni, ni_index a, ni_index b) -{ - struct in_addr tmp_addr; - ni_name tmp_tag; - - if (a == b) return; - - tmp_addr = ni->addrs[a]; - tmp_tag = ni->tags[a]; - - ni->addrs[a] = ni->addrs[b]; - ni->tags[a] = ni->tags[b]; - - ni->addrs[b] = tmp_addr; - ni->tags[b] = tmp_tag; - - if (ni->whichwrite == a) ni->whichwrite = b; - else if (ni->whichwrite == b) ni->whichwrite = a; -} - -static ni_status -ni_ping(unsigned short port, struct in_addr addr) -{ - struct sockaddr_in sin; - int sock; - CLIENT *cl; - struct timeval timeout, retry; - enum clnt_stat stat; - - memset(&sin, 0, sizeof(struct sockaddr_in)); - - sin.sin_family = AF_INET; - sin.sin_port = port; - sin.sin_addr = addr; - - timeout.tv_sec = NI_TIMEOUT_SHORT; - timeout.tv_usec = 0; - - retry.tv_sec = 1; - retry.tv_usec = 0; - - sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (sock < 0) return NI_FAILED; - - cl = clntudp_create(&sin, NI_PROG, NI_VERS, timeout, &sock); - if (cl == NULL) - { - close(sock); - return NI_FAILED; - } - - clnt_control(cl, CLSET_RETRY_TIMEOUT, (char *)&retry); - - stat = clnt_call(cl, _NI_PING, (xdrproc_t)xdr_void, (char *)NULL, (xdrproc_t)xdr_void, (char *)NULL, timeout); - clnt_destroy(cl); - close(sock); - - if (stat != RPC_SUCCESS) return NI_FAILED; - - return NI_OK; -} - -/* - * Callback routine for multi_call - * XXX: should save returned port numbers - */ -static bool_t -eachresult(void *vstuff, struct sockaddr_in *sin, int which) -{ - ni_status status; - getreg_stuff *stuff = (getreg_stuff *)vstuff; - - if (stuff->res.status != NI_OK) return FALSE; - - /* - * Actually talk to server (netinfod) to make sure it is alive - * before switching. If we got this far, nibindd gave us a - * port number for an address and tag. We connect to that - * port and do a ni_root() query before accepting the server. - */ - status = ni_ping(htons(stuff->res.nibind_getregister_res_u.addrs.udp_port), stuff->ni->addrs[which]); - if (status != NI_OK) return FALSE; - - ni_switch(stuff->ni, which); - return TRUE; -} - - -/* - * shuffle addresses - */ -static void -shuffle(ni_private *ni) -{ - int *shuffle; - int i, j, rfd, rv, te; - unsigned int re; - static int initialized = 0; - - if (ni == NULL) return; - if (ni->naddrs <= 1) return; - - rfd = open("/dev/random", O_RDONLY, 0); - shuffle = (int *)malloc(ni->naddrs * sizeof(int)); - for (i = 0; i < ni->naddrs; i++) shuffle[i] = i; - for (i = 0, j = ni->naddrs; j > 0; i++, j--) - { - /* get a random number */ - if ((rfd < 0) || (read(rfd, &rv, sizeof(rv)) != sizeof(rv))) - { - /* if we could not read from /dev/random */ - if (initialized == 0) - { - srandom(gethostid() ^ time(NULL)); - initialized = 1; - } - rv = random(); - } - - re = (unsigned int)rv % j; /* pick one of the remaining entries */ - te = shuffle[re]; /* grab the random entry */ - shuffle[re] = shuffle[j-1]; /* the last entry moves to the random slot */ - shuffle[j-1] = te; /* the last slot gets the random entry */ - ni_swap(ni, re, j-1); /* and swap the actual NI addresses */ - } - - free(shuffle); - if (rfd > 0) close(rfd); - return; -} - - -static int -rebind(ni_private *ni) -{ - enum clnt_stat stat; - getreg_stuff stuff; - int sleeptime = NI_SLEEPTIME; - int printed = 0; - int nlocal; - int nnetwork; - interface_list_t *ilist; - int i; - - if (ni->naddrs == 1) - { - ni->whichwrite = 0; - return 1; - } - - /* - * Majka - 1994.04.27 - * re-order the servers so that: - * servers on the local host are at the start of the list, then - * servers on the local network are next, then - * all other servers are next - */ - - ilist = _libinfo_ni_sys_interfaces(); - - /* - * shuffle addresses - */ - shuffle(ni); - - /* - * move local servers to the head of the list - */ - nlocal = 0; - for (i = nlocal; i < ni->naddrs; i++) - { - if (_libinfo_ni_sys_is_my_address(ilist, &ni->addrs[i])) - { - ni_swap(ni, nlocal, i); - nlocal++; - } - } - - /* - * move servers on this network to follow local servers - */ - nnetwork = nlocal; - for (i = nnetwork; i < ni->naddrs; i++) - { - if (_libinfo_ni_sys_is_my_network(ilist, &ni->addrs[i]) || IS_BROADCASTADDR(ni->addrs[i].s_addr)) - { - ni_swap(ni, nnetwork, i); - nnetwork++; - } - } - - _libinfo_ni_sys_interfaces_release(ilist); - - stuff.ni = ni; - for (;;) - { - /* - * call local servers first - */ - if (nlocal > 0) - { - for (i = 0; i < nlocal; i++) - { - syslog(LOG_DEBUG, "NetInfo connect call to: %s/%s (local %d)", inet_ntoa(ni->addrs[i]), ni->tags[i], i); - } - - stat = multi_call(nlocal, ni->addrs, NIBIND_PROG, NIBIND_VERS, NIBIND_GETREGISTER, (xdrproc_t)xdr_ni_name, (void *)ni->tags, sizeof(ni_name), (xdrproc_t)xdr_nibind_getregister_res, (void *)&stuff, eachresult, NI_TIMEOUT_SHORT); - if (stat == RPC_SUCCESS) break; - } - - /* - * call local servers and this network's servers - */ - if (nnetwork > nlocal) - { - for (i = 0; i < nnetwork; i++) - { - syslog(LOG_DEBUG, "NetInfo connect call to: %s/%s (network %d)", inet_ntoa(ni->addrs[i]), ni->tags[i], i); - } - - stat = multi_call(nnetwork, ni->addrs, NIBIND_PROG, NIBIND_VERS, NIBIND_GETREGISTER, (xdrproc_t)xdr_ni_name, (void *)ni->tags, sizeof(ni_name), (xdrproc_t)xdr_nibind_getregister_res, (void *)&stuff, eachresult, NI_TIMEOUT_SHORT); - if (stat == RPC_SUCCESS) break; - } - - /* - * call all servers - */ - for (i = 0; i < ni->naddrs; i++) - { - syslog(LOG_DEBUG, "NetInfo connect call to: %s/%s (world %d)", inet_ntoa(ni->addrs[i]), ni->tags[i], i); - } - stat = multi_call(ni->naddrs, ni->addrs, NIBIND_PROG, NIBIND_VERS, NIBIND_GETREGISTER, (xdrproc_t)xdr_ni_name, (void *)ni->tags, sizeof(ni_name), (xdrproc_t)xdr_nibind_getregister_res, (void *)&stuff, eachresult, (ni->rtv_sec == 0) ? NI_TIMEOUT_SHORT : ni->rtv_sec); - if (stat == RPC_SUCCESS) break; - - if (ni->abort) return 0; - - if (printed == 0) - { - if (ni->whichwrite >= 0) - { - syslog(LOG_WARNING, - "NetInfo connect timeout (domain with master %s/%s), sleeping", inet_ntoa(ni->addrs[ni->whichwrite]), ni->tags[ni->whichwrite]); - } - else - { - syslog(LOG_WARNING, "NetInfo connect timeout (domain with server %s/%s), sleeping", inet_ntoa(ni->addrs[0]), ni->tags[0]); - } - - printed = 1; - } - - sleep(sleeptime); - if (sleeptime < NI_MAXSLEEPTIME) - { - /* backoff */ - sleeptime *= 2; - } - } - - syslog(LOG_INFO, "NetInfo connected to %s/%s", inet_ntoa(ni->addrs[0]), ni->tags[0]); - - return 1; -} - - -/* - * Confirm that our tcp socket is still valid - */ -static int -confirm_tcp(ni_private *ni, int needwrite) -{ - int p; - - if (ni->tsock != -1) - { - p = getmyport(ni->tsock); - if ((p != -1) && (p == ni->tport)) - { - /* All is well */ - return 1; - } - - if (p == -1) - { - /* Socket has died. Close it so it doesn't become a zombie. */ - close(ni->tsock); - } - - /* - * Somebody has reused our socket. - */ - 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 == 0) && (rebind(ni) == 0) && (ni->abort != 0)) return 0; - - return connectit(ni); -} - - -static int -setmaster(ni_private *ni) -{ - ni_id root; - ni_namelist nl; - ni_name sep; - ni_idlist idl; - ni_name master; - ni_index i; - ni_index j; - ni_id id; - struct in_addr addr; - int needwrite; - - if (ni->naddrs == 1) - { - /* One server - must be the master */ - ni->whichwrite = 0; - return 1; - } - - needwrite = ni->needwrite; - ni->needwrite = 0; - if (ni_root(ni, &root) != NI_OK) - { - ni->needwrite = needwrite; - return 0; - } - - NI_INIT(&nl); - if (ni_lookupprop(ni, &root, NAME_MASTER, &nl) != NI_OK) - { - ni->needwrite = needwrite; - return 0; - } - - if (nl.ninl_len == 0) - { - ni->needwrite = needwrite; - return 0; - } - - sep = index(nl.ninl_val[0], '/'); - if (sep == NULL) - { - ni->needwrite = needwrite; - return 0; - } - - *sep++ = 0; - master = nl.ninl_val[0]; - - NI_INIT(&idl); - if (ni_lookup(ni, &root, NAME_NAME, NAME_MACHINES, &idl) != NI_OK) - { - ni->needwrite = needwrite; - ni_namelist_free(&nl); - return 0; - } - - if (idl.niil_len < 1) - { - ni->needwrite = needwrite; - return 0; - } - - id.nii_object = idl.niil_val[0]; - ni_idlist_free(&idl); - - NI_INIT(&idl); - if (ni_lookup(ni, &id, NAME_NAME, master, &idl) != NI_OK) - { - ni_namelist_free(&nl); - ni->needwrite = needwrite; - return 0; - } - - ni_namelist_free(&nl); - if (idl.niil_len < 1) - { - ni->needwrite = needwrite; - return 0; - } - - id.nii_object = idl.niil_val[0]; - ni_idlist_free(&idl); - NI_INIT(&nl); - if (ni_lookupprop(ni, &id, NAME_IP_ADDRESS, &nl) != NI_OK) return 0; - - for (i = 0; i < nl.ninl_len; i++) - { - addr.s_addr = inet_addr(nl.ninl_val[i]); - for (j = 0; j < ni->naddrs; j++) - { - if (addr.s_addr == ni->addrs[j].s_addr) - { - ni->whichwrite = j; - ni_namelist_free(&nl); - ni->needwrite = needwrite; - return 1; - } - } - } - - ni->needwrite = needwrite; - ni_namelist_free(&nl); - return 0; -} - - -static void * -callit(ni_private *ni, void *(*stub)(), void *args, int needwrite) -{ - void *resp; - struct rpc_err err; - int i; - int sleeptime = 0; - int printed = 0; - - if (getpid() != ni->pid) reinit(ni); - - if (needwrite || ni->needwrite) - { - if (ni->whichwrite >= 0) - { - ni_switch(ni, ni->whichwrite); - } - else - { - if (setmaster(ni) == 0) return NULL; - ni_switch(ni, ni->whichwrite); - } - - if (needwrite == 0) - { - ni_settimeout(ni, (ni->rtv_sec == 0 ? NI_TIMEOUT_SHORT : ni->rtv_sec)); - needwrite = 1; - } - else - { - ni_settimeout(ni, (ni->wtv_sec == 0 ? NI_TIMEOUT_LONG : ni->wtv_sec)); - } - } - else - { - ni_settimeout(ni, (ni->rtv_sec == 0 ? NI_TIMEOUT_SHORT : ni->rtv_sec)); - } - - for (;;) - { - /* - * Try more than once, in case server closed connection. - */ - for (i = 0; i < NI_MAXCONNTRIES; i++) - { - if (!confirm_tcp(ni, needwrite)) break; - - if ((resp = (*stub)(args, ni->tc)) != NULL) - { - if (printed != 0) syslog(LOG_INFO, "NetInfo connected to %s/%s", inet_ntoa(ni->addrs[0]), ni->tags[0]); - return resp; - } - - if (ni->tc != NULL) - { - clnt_geterr(ni->tc, &err); - if (err.re_status != RPC_CANTRECV) break; - } - - if ((i + 1) < NI_MAXCONNTRIES) - { - /* Server closed connection. Reinit and try again. */ - reinit(ni); - } - } - - if (err.re_status == RPC_PROCUNAVAIL) return NULL; - - if (needwrite || ni->abort) - { - /* - * We time out for writes or if it is explicitly - * requested. - */ - if (ni->abort) reinit(ni); - - syslog(LOG_ERR, "NetInfo connection failed for server %s/%s", inet_ntoa(ni->addrs[0]), ni->tags[0]); - return NULL; - } - - if (printed != 0) - { - if (ni->tc != NULL) - { - if ((sleeptime != 0) || (err.re_status != RPC_TIMEDOUT)) - { - /* - * Do not print message on - * first timeout. It is likely - * we will find another server soon. - * Let's not needlessly alarm the - * poor user! - */ - syslog(LOG_ERR, "%s on connection to %s/%s", clnt_sperror(ni->tc,"NetInfo connection timeout"), inet_ntoa(ni->addrs[0]), ni->tags[0]); - printed = 1; - } - else - { - /* first attempt failed */ - syslog(LOG_NOTICE, "%s on initial connection to %s/%s", clnt_sperror(ni->tc,"NetInfo connection timeout"), inet_ntoa(ni->addrs[0]), ni->tags[0]); - } - } - else - { - syslog(LOG_ERR, "NetInfo connection failed for server %s/%s", inet_ntoa(ni->addrs[0]), ni->tags[0]); - printed = 1; - } - } - - if (sleeptime > 0) - { - sleep(sleeptime); - /* backoff */ - if (sleeptime < NI_MAXSLEEPTIME) sleeptime *= 2; - } - else - { - /* - * Do not sleep on the first timeout. - * It is likely we will find another server quickly. - */ - sleeptime = NI_SLEEPTIME; - } - - reinit(ni); - rebind(ni); - } -} - - -static void -ni_clear(ni_private *ni) -{ - ni->needwrite = 0; - ni->naddrs = 0; - ni->addrs = NULL; - ni->tags = NULL; - ni->tc = NULL; - ni->tsock = -1; - ni->tport = -1; - ni->whichwrite = -1; - ni->passwd = NULL; -} - - -static void * -ni_alloc(void) -{ - ni_private *ni; - - ni = (ni_private *)malloc(sizeof(*ni)); - ni->naddrs = 0; - ni->whichwrite = -1; - ni->pid = getpid(); - ni->tsock = -1; - ni->tport = -1; - ni->tc = NULL; - ni->tv_sec = NI_TIMEOUT_SHORT; - ni->rtv_sec = 0; - ni->wtv_sec = 0; - ni->abort = 0; - ni->passwd = NULL; - ni->uid = getuid(); - ni->needwrite = 0; - return (void *)ni; -} - - -void * -_ni_dup(void *ni) -{ - ni_private *dupni; - ni_index i; - - if (ni == NULL) return NULL; - - dupni = (ni_private *)ni_alloc(); - *dupni = *NIP(ni); - ni_clear(dupni); - dupni->naddrs = NIP(ni)->naddrs; - dupni->whichwrite = NIP(ni)->whichwrite; - if (dupni->naddrs > 0) - { - dupni->addrs = ((struct in_addr *) malloc(NIP(ni)->naddrs * sizeof(struct in_addr))); - bcopy(NIP(ni)->addrs, dupni->addrs, NIP(ni)->naddrs * sizeof(struct in_addr)); - dupni->tags = ((ni_name *) malloc(NIP(ni)->naddrs * sizeof(ni_name))); - for (i = 0; i < NIP(ni)->naddrs; i++) - { - dupni->tags[i] = ni_name_dup(NIP(ni)->tags[i]); - } - } - - if (NIP(ni)->passwd != NULL) dupni->passwd = ni_name_dup(NIP(ni)->passwd); - return (void *)dupni; -} - - -static int -match(ni_name domain, ni_name domtag, ni_name *tag) -{ - int len = strlen(domain); - ni_name sep; - - sep = index(domtag, '/'); - if (sep == NULL) return 0; - - if ((strncmp(domain, domtag, len) == 0) && (domtag[len] == '/')) - { - *tag = ni_name_dup(sep + 1); - return 1; - } - - return 0; -} - - -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) -{ - ni_id id; - ni_namelist nl; - struct in_addr addr; - int i; - ni_status status; - - if (ni == NULL) return 0; - if (tag == NULL) return 0; - if (target_ni == NULL) return 0; - - id.nii_object = ido; - NI_INIT(&nl); - - status = ni_lookupprop(ni, &id, NAME_IP_ADDRESS, &nl); - if (status != NI_OK) return 0; - - if (nl.ni_namelist_len == 0) return 0; - - if (target_ni->naddrs == 0) - { - target_ni->addrs = (struct in_addr *)malloc(nl.ni_namelist_len * sizeof(struct in_addr)); - target_ni->tags = (ni_name *)malloc(nl.ni_namelist_len * sizeof(ni_name)); - } - else - { - target_ni->addrs = (struct in_addr *)realloc(target_ni->addrs, ((target_ni->naddrs + nl.ni_namelist_len) * sizeof(struct in_addr))); - target_ni->tags = (ni_name *)realloc(target_ni->tags, ((target_ni->naddrs + nl.ni_namelist_len) * sizeof(ni_name))); - } - - for (i = 0; i < nl.ni_namelist_len; i++) - { - addr.s_addr = inet_addr(nl.ni_namelist_val[i]); - target_ni->addrs[target_ni->naddrs] = addr; - target_ni->tags[target_ni->naddrs] = ni_name_dup(tag); - target_ni->naddrs++; - } - - ni_namelist_free(&nl); - return 1; -} - -static int -get_daddr(ni_private *ni, ni_name dom, ni_private *target_ni) -{ - ni_id nid; - ni_idlist ids; - ni_entrylist entries; - ni_proplist pl; - ni_index i; - ni_index j; - ni_name tag; - - if (ni == NULL) return 0; - if (dom == NULL) return 0; - if (target_ni == 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, &nid, NAME_NAME, NAME_MACHINES, &ids) != NI_OK) return 0; - - nid.nii_object = ids.niil_val[0]; - ni_idlist_free(&ids); - - NI_INIT(&entries); - 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) 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); -} - -static ni_status -getparent(ni_private *oldni, ni_private **newni) -{ - ni_rparent_res *resp; - ni_private *ni = NULL; - ni_private *dupni; - int found = 0; - ni_index i; - struct in_addr raddr; - int printed = 0; - int inlist = 0; - - if (oldni == NULL) return 0; - if (newni == NULL) return 0; - - while (found == 0) - { - /* - * First, find our parent, any parent - */ - for (;;) - { - resp = RCALLIT(oldni, _ni_rparent_2, NULL); - if (resp == NULL) return NI_FAILED; - if (resp->status != NI_NORESPONSE) break; - - if (printed != 0) - { - syslog(LOG_WARNING, "NetInfo timeout finding server for parent of %s/%s, sleeping", inet_ntoa(oldni->addrs[0]), oldni->tags[0]); - printed = 1; - } - - sleep(NI_SLEEPTIME); - } - - if (printed) - { - raddr.s_addr = htonl(resp->ni_rparent_res_u.binding.addr); - - syslog(LOG_INFO, "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; - - ni = ni_alloc(); - *ni = *oldni; - ni_clear(ni); - ni->naddrs = 1; - ni->addrs = (struct in_addr *)malloc(sizeof(struct in_addr)); - ni->addrs[0].s_addr=htonl(resp->ni_rparent_res_u.binding.addr); - ni->tags = (ni_name *)malloc(sizeof(ni_name)); - ni->tags[0] = ni_name_dup(resp->ni_rparent_res_u.binding.tag); - - xdr_free((xdrproc_t)xdr_ni_rparent_res, (void *)resp); - - dupni = ni; - ni = ni_alloc(); - *ni = *dupni; - ni_clear(ni); - if (get_daddr(dupni, ".", ni) == 0) - { - if (oldni->abort == 1) - { - ni_free(dupni); - break; - } - } - else - { - /* - * 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) - { - ni_switch(ni, i); - inlist++; - break; - } - } - - /* - * Reuse dupni client info - */ - ni->tsock = dupni->tsock; - ni->tport = dupni->tport; - ni->tc = dupni->tc; - dupni->tsock = -1; - dupni->tport = -1; - dupni->tc = NULL; - found = 1; - - /* - * If returned parent wasn't in list, it's a rogue. - * Log an error and drop the connection. - */ - if (inlist == 0) - { - syslog(LOG_ERR, "Rogue NetInfo server detected: %s/%s", inet_ntoa(dupni->addrs[0]), dupni->tags[0]); - reinit(ni); - } - - } - ni_free(dupni); - } - - if (found) - { - *newni = ni; - return NI_OK; - } - - if (ni != NULL) ni_free(ni); - return NI_FAILED; -} - - -void * -ni_connect(struct sockaddr_in *sin, const char *tag) -{ - void *ni; - - if (sin == NULL) return NULL; - if (tag == NULL) return NULL; - - ni = ni_alloc(); - NIP(ni)->naddrs = 1; - NIP(ni)->addrs = (struct in_addr *)malloc(sizeof(struct in_addr)); - NIP(ni)->addrs[0] = sin->sin_addr; - NIP(ni)->tags = (ni_name *)malloc(sizeof(ni_name)); - NIP(ni)->tags[0] = ni_name_dup(tag); - return ni; -} - - -ni_status -ni_addrtag(void *ni, struct sockaddr_in *addr, ni_name *tag) -{ - if (ni == NULL) return NI_FAILED; - if (addr == NULL) return NI_FAILED; - if (tag == NULL) return NI_FAILED; - - if (!confirm_tcp(ni, 0)) return NI_FAILED; - - *tag = ni_name_dup(NIP(ni)->tags[0]); - addr->sin_addr = NIP(ni)->addrs[0]; - addr->sin_port = htons(NIP(ni)->tport); - addr->sin_family = AF_INET; - bzero(addr->sin_zero, sizeof(addr->sin_zero)); - - return NI_OK; -} - - -void * -ni_new(void *oldni, const char *domain) -{ - ni_private *ni; - ni_status status; - ni_name sep, addr, tag; - struct sockaddr_in sin; - struct hostent *he; - - if (domain == NULL) return NULL; - - sep = index(domain, '@'); - if (sep != NULL) - { - tag = strncpy((char *)malloc(sep - domain + 1), domain, sep - domain); - tag[sep - domain] = '\0'; - - addr = NULL; - asprintf(&addr, "%s", sep + 1); - - sin.sin_addr.s_addr = inet_addr(addr); - if (sin.sin_addr.s_addr == INADDR_NONE) - { - he = gethostbyname(addr); - if (he == NULL) - { - free(addr); - free(tag); - return NULL; - } - - bcopy(he->h_addr_list[0], &sin.sin_addr.s_addr, he->h_length); - } - - ni = ni_connect(&sin, tag); - free(addr); - free(tag); - - return (void *)ni; - } - - ni = NULL; - - if (oldni == NULL) - { - ni = ni_alloc(); - if (connectlocal(ni) == 0) - { - free(ni); - return NULL; - } - - if (strcmp(domain, ".") == 0) return (void *)ni; - - if (strcmp(domain, "..") == 0) - { - oldni = ni; - status = getparent((ni_private *)oldni, &ni); - ni_free(oldni); - if (status != NI_OK) return NULL; - return (void *)ni; - } - - ni_free(ni); - return NULL; - } - - if (strcmp(domain, "..") == 0) - { - status = getparent((ni_private *)oldni, &ni); - if (status != NI_OK) return NULL; - return (void *)ni; - } - - ni = ni_alloc(); - *ni = *NIP(oldni); - ni_clear(ni); - if (get_daddr(oldni, (ni_name)domain, ni) == 0) - { - ni_free(ni); - return NULL; - } - - return (void *)ni; -} - - -void -ni_free(void *ni) -{ - ni_index i; - - if (ni == NULL) return; - - if (NIP(ni)->tc != NULL) clnt_kill(NIP(ni)->tc, NIP(ni)->tsock, NIP(ni)->tport); - - if (NIP(ni)->naddrs > 0) - { - for (i = 0; i < NIP(ni)->naddrs; i++) ni_name_free(&NIP(ni)->tags[i]); - free(NIP(ni)->tags); - free(NIP(ni)->addrs); - } - - if (NIP(ni)->passwd != NULL) ni_name_free(&NIP(ni)->passwd); - - free(ni); -} - - -/* - * The rest of these are just wrappers that end up doing - * RPC calls to the local NetInfo server. - */ -ni_status -ni_statistics(void *ni, ni_proplist *pl) -{ - ni_proplist *resp; - - if (ni == NULL) return NI_FAILED; - if (pl == NULL) return NI_FAILED; - - resp = (ni_proplist *)RCALLIT(ni, _ni_statistics_2, NULL); - if (resp == NULL) - { - clnt_debug(ni, "_ni_statistics"); - return NI_FAILED; - } - - *pl = *resp; - return NI_OK; -} - - -ni_status -ni_root(void *ni, ni_id *id) -{ - ni_id_res *resp; - - if (ni == NULL) return NI_FAILED; - if (id == NULL) return NI_FAILED; - - resp = RCALLIT(ni, _ni_root_2, id); - if (resp == NULL) - { - clnt_debug(ni, "_ni_root"); - return NI_FAILED; - } - - if (resp->status == NI_OK) *id = resp->ni_id_res_u.id; - - return resp->status; -} - - -ni_status -ni_self(void *ni, ni_id *id) -{ - ni_id_res *resp; - - if (ni == NULL) return NI_FAILED; - if (id == NULL) return NI_FAILED; - - resp = RCALLIT(ni, _ni_self_2, id); - if (resp == NULL) - { - clnt_debug(ni, "_ni_self"); - return NI_FAILED; - } - - if (resp->status == NI_OK) *id = resp->ni_id_res_u.id; - - return resp->status; -} - - -ni_status -ni_parent(void *ni, ni_id *id, ni_index *parent_id_p) -{ - ni_parent_res *resp; - - if (ni == NULL) return NI_FAILED; - if (id == NULL) return NI_FAILED; - if (parent_id_p == NULL) return NI_FAILED; - - resp = RCALLIT(ni, _ni_parent_2, id); - if (resp == NULL) - { - clnt_debug(ni, "_ni_parent"); - return NI_FAILED; - } - - if (resp->status == NI_OK) - { - *parent_id_p = resp->ni_parent_res_u.stuff.object_id; - *id = resp->ni_parent_res_u.stuff.self_id; - } - - return resp->status; -} - - -ni_status -ni_children(void *ni, ni_id *id, ni_idlist *children) -{ - ni_children_res *resp; - - if (ni == NULL) return NI_FAILED; - if (id == NULL) return NI_FAILED; - if (children == NULL) return NI_FAILED; - - resp = RCALLIT(ni, _ni_children_2, id); - if (resp == NULL) - { - clnt_debug(ni, "_ni_children"); - return NI_FAILED; - } - - if (resp->status == NI_OK) - { - *children = resp->ni_children_res_u.stuff.children; - *id = resp->ni_children_res_u.stuff.self_id; - } - - return resp->status; -} - - -ni_status -ni_create(void *ni, ni_id *parent_id, ni_proplist pl, ni_id *child_id_p, ni_index where) -{ - ni_create_args args; - ni_create_res *resp; - - if (ni == NULL) return NI_FAILED; - if (parent_id == NULL) return NI_FAILED; - if (child_id_p == NULL) return NI_FAILED; - - args.id = *parent_id; - args.props = pl; - args.where = where; - args.target_id = NULL; - - resp = WCALLIT(ni, _ni_create_2, &args); - if (resp == NULL) - { - clnt_debug(ni, "_ni_create"); - return NI_FAILED; - } - - if (resp->status == NI_OK) - { - *child_id_p = resp->ni_create_res_u.stuff.id; - *parent_id = resp->ni_create_res_u.stuff.self_id; - } - - return resp->status; -} - - -ni_status -ni_destroy(void *ni, ni_id *parent_id, ni_id self_id) -{ - ni_id_res *resp; - ni_destroy_args args; - - if (ni == NULL) return NI_FAILED; - if (parent_id == NULL) return NI_FAILED; - - args.parent_id = *parent_id; - args.self_id = self_id; - - resp = WCALLIT(ni, _ni_destroy_2, &args); - if (resp == NULL) - { - clnt_debug(ni, "_ni_destroy"); - return NI_FAILED; - } - - if (resp->status == NI_OK) *parent_id = resp->ni_id_res_u.id; - - return resp->status; -} - - -ni_status -ni_write(void *ni, ni_id *self_id, ni_proplist pl) -{ - ni_proplist_stuff args; - ni_id_res *resp; - - if (ni == NULL) return NI_FAILED; - if (self_id == NULL) return NI_FAILED; - - args.id = *self_id; - args.props = pl; - - resp = WCALLIT(ni, _ni_write_2, &args); - if (resp == NULL) - { - clnt_debug(ni, "_ni_write"); - return NI_FAILED; - } - - if (resp->status == NI_OK) *self_id = resp->ni_id_res_u.id; - - return resp->status; -} - - -ni_status -ni_read(void *ni, ni_id *self_id, ni_proplist *pl) -{ - ni_proplist_res *resp; - - if (ni == NULL) return NI_FAILED; - if (self_id == NULL) return NI_FAILED; - if (pl == NULL) return NI_FAILED; - - resp = RCALLIT(ni, _ni_read_2, self_id); - if (resp == NULL) - { - clnt_debug(ni, "_ni_read"); - return NI_FAILED; - } - - if (resp->status == NI_OK) - { - *self_id = resp->ni_proplist_res_u.stuff.id; - *pl = resp->ni_proplist_res_u.stuff.props; - } - - return resp->status; -} - - -ni_status -ni_lookup(void *ni, ni_id *id, ni_name_const pname, ni_name_const pval, ni_idlist *hits) -{ - ni_lookup_res *resp; - ni_lookup_args args; - - if (ni == NULL) return NI_FAILED; - if (id == NULL) return NI_FAILED; - if (pname == NULL) return NI_FAILED; - /* pval may be NULL */ - if (hits == NULL) return NI_FAILED; - - args.id = *id; - args.key = (ni_name)pname; - args.value = (ni_name)pval; - - resp = RCALLIT(ni, _ni_lookup_2, &args); - if (resp == NULL) - { - clnt_debug(ni, "_ni_lookup"); - return NI_FAILED; - } - - if (resp->status == NI_OK) - { - *hits = resp->ni_lookup_res_u.stuff.idlist; - *id = resp->ni_lookup_res_u.stuff.self_id; - } - - return resp->status; -} - - -ni_status -ni_lookupread(void *ni, ni_id *id, ni_name_const pname, ni_name_const pval, ni_proplist *props) -{ - ni_proplist_res *resp; - ni_lookup_args args; - - if (ni == NULL) return NI_FAILED; - if (id == NULL) return NI_FAILED; - if (pname == NULL) return NI_FAILED; - /* pval may be NULL*/ - if (props == NULL) return NI_FAILED; - - args.id = *id; - args.key = (ni_name)pname; - args.value = (ni_name)pval; - - resp = RCALLIT(ni, _ni_lookupread_2, &args); - if (resp == NULL) - { - clnt_debug(ni, "_ni_lookupread"); - return NI_FAILED; - } - - if (resp->status == NI_OK) - { - *props = resp->ni_proplist_res_u.stuff.props; - *id = resp->ni_proplist_res_u.stuff.id; - } - - return resp->status; -} - - -ni_status -ni_list(void *ni, ni_id *id, ni_name_const pname, ni_entrylist *entries) -{ - ni_list_res *resp; - ni_name_args args; - - if (ni == NULL) return NI_FAILED; - if (id == NULL) return NI_FAILED; - if (pname == NULL) return NI_FAILED; - if (entries == NULL) return NI_FAILED; - - args.id = *id; - args.name = (ni_name)pname; - - resp = RCALLIT(ni, _ni_list_2, &args); - if (resp == NULL) - { - clnt_debug(ni, "_ni_list"); - return NI_FAILED; - } - - if (resp->status == NI_OK) - { - *entries = resp->ni_list_res_u.stuff.entries; - *id = resp->ni_list_res_u.stuff.self_id; - } - - return resp->status; -} - - -ni_status -ni_listall(void *ni, ni_id *id, ni_proplist_list *entries) -{ - ni_listall_res *resp; - - if (ni == NULL) return NI_FAILED; - if (id == NULL) return NI_FAILED; - if (entries == NULL) return NI_FAILED; - - resp = RCALLIT(ni, _ni_listall_2, id); - if (resp == NULL) - { - clnt_debug(ni, "_ni_listall"); - return NI_FAILED; - } - - if (resp->status == NI_OK) - { - *entries = resp->ni_listall_res_u.stuff.entries; - *id = resp->ni_listall_res_u.stuff.self_id; - } - - return resp->status; -} - - -ni_status -ni_readprop(void *ni, ni_id *id, ni_index which, ni_namelist *propval_p) -{ - ni_namelist_res *resp; - ni_prop_args args; - - if (ni == NULL) return NI_FAILED; - if (id == NULL) return NI_FAILED; - if (propval_p == NULL) return NI_FAILED; - - args.id = *id; - args.prop_index = which; - - resp = RCALLIT(ni, _ni_readprop_2, &args); - if (resp == NULL) - { - clnt_debug(ni, "_ni_readprop"); - return NI_FAILED; - } - - if (resp->status == NI_OK) - { - *propval_p = resp->ni_namelist_res_u.stuff.values; - *id = resp->ni_namelist_res_u.stuff.self_id; - } - - return resp->status; -} - - -ni_status -ni_writeprop(void *ni, ni_id *id, ni_index which, ni_namelist propval) -{ - ni_id_res *resp; - ni_writeprop_args args; - - if (ni == NULL) return NI_FAILED; - if (id == NULL) return NI_FAILED; - - args.id = *id; - args.prop_index = which; - args.values = propval; - - resp = WCALLIT(ni, _ni_writeprop_2, &args); - if (resp == NULL) - { - clnt_debug(ni, "_ni_writeprop"); - return NI_FAILED; - } - - if (resp->status == NI_OK) *id = resp->ni_id_res_u.id; - - return resp->status; -} - - -ni_status -ni_listprops(void *ni, ni_id *id, ni_namelist *propnames) -{ - ni_namelist_res *resp; - - if (ni == NULL) return NI_FAILED; - if (id == NULL) return NI_FAILED; - if (propnames == NULL) return NI_FAILED; - - resp = RCALLIT(ni, _ni_listprops_2, id); - if (resp == NULL) - { - clnt_debug(ni, "_ni_listprops"); - return NI_FAILED; - } - - if (resp->status == NI_OK) - { - *propnames = resp->ni_namelist_res_u.stuff.values; - *id = resp->ni_namelist_res_u.stuff.self_id; - } - - return resp->status; -} - - -ni_status -ni_createprop(void *ni, ni_id *id, ni_property prop, ni_index where) -{ - ni_id_res *resp; - ni_createprop_args args; - - if (ni == NULL) return NI_FAILED; - if (id == NULL) return NI_FAILED; - - args.id = *id; - args.prop = prop; - args.where = where; - - resp = WCALLIT(ni, _ni_createprop_2, &args); - if (resp == NULL) - { - clnt_debug(ni, "_ni_createprop"); - return NI_FAILED; - } - - if (resp->status == NI_OK) *id = resp->ni_id_res_u.id; - - return resp->status; -} - - -ni_status -ni_destroyprop(void *ni, ni_id *id, ni_index which) -{ - ni_id_res *resp; - ni_prop_args args; - - if (ni == NULL) return NI_FAILED; - if (id == NULL) return NI_FAILED; - - args.id = *id; - args.prop_index = which; - - resp = WCALLIT(ni, _ni_destroyprop_2, &args); - if (resp == NULL) - { - clnt_debug(ni, "_ni_destroyprop"); - return NI_FAILED; - } - - if (resp->status == NI_OK) *id = resp->ni_id_res_u.id; - - return resp->status; -} - - -ni_status -ni_renameprop(void *ni, ni_id *id, ni_index prop_index, ni_name_const name) -{ - ni_id_res *resp; - ni_propname_args args; - - if (ni == NULL) return NI_FAILED; - if (id == NULL) return NI_FAILED; - if (name == NULL) return NI_FAILED; - - args.id = *id; - args.prop_index = prop_index; - args.name = (ni_name)name; - - resp = WCALLIT(ni, _ni_renameprop_2, &args); - if (resp == NULL) - { - clnt_debug(ni, "_ni_renameprop"); - return NI_FAILED; - } - - if (resp->status == NI_OK) *id = resp->ni_id_res_u.id; - - return resp->status; -} - - -ni_status -ni_createname(void *ni, ni_id *id, ni_index prop_index, ni_name_const name, ni_index where) -{ - ni_id_res *resp; - ni_createname_args args; - - if (ni == NULL) return NI_FAILED; - if (id == NULL) return NI_FAILED; - if (name == NULL) return NI_FAILED; - - args.id = *id; - args.prop_index = prop_index; - args.name = (ni_name)name; - args.where = where; - - resp = WCALLIT(ni, _ni_createname_2, &args); - if (resp == NULL) - { - clnt_debug(ni, "_ni_createname"); - return NI_FAILED; - } - - if (resp->status == NI_OK) *id = resp->ni_id_res_u.id; - - return resp->status; -} - - -ni_status -ni_destroyname(void *ni, ni_id *id, ni_index prop_index, ni_index name_index) -{ - ni_id_res *resp; - ni_nameindex_args args; - - if (ni == NULL) return NI_FAILED; - if (id == NULL) return NI_FAILED; - - args.id = *id; - args.prop_index = prop_index; - args.name_index = name_index; - - resp = WCALLIT(ni, _ni_destroyname_2, &args); - if (resp == NULL) - { - clnt_debug(ni, "_ni_destroyname"); - return NI_FAILED; - } - - if (resp->status == NI_OK) *id = resp->ni_id_res_u.id; - - return resp->status; -} - - -ni_status -ni_writename(void *ni, ni_id *id, ni_index prop_index, ni_index name_index, ni_name_const name) -{ - ni_id_res *resp; - ni_writename_args args; - - if (ni == NULL) return NI_FAILED; - if (id == NULL) return NI_FAILED; - if (name == NULL) return NI_FAILED; - - args.id = *id; - args.prop_index = prop_index; - args.name_index = name_index; - args.name = (ni_name)name; - - resp = WCALLIT(ni, _ni_writename_2, &args); - if (resp == NULL) - { - clnt_debug(ni, "_ni_writename"); - return NI_FAILED; - } - - if (resp->status == NI_OK) *id = resp->ni_id_res_u.id; - - return resp->status; -} - - -ni_status -ni_readname(void *ni, ni_id *id, ni_index prop_index, ni_index name_index, ni_name *name) -{ - ni_readname_res *resp; - ni_nameindex_args args; - - if (ni == NULL) return NI_FAILED; - if (id == NULL) return NI_FAILED; - if (name == NULL) return NI_FAILED; - - args.id = *id; - args.prop_index = prop_index; - args.name_index = name_index; - - resp = RCALLIT(ni, _ni_readname_2, &args); - if (resp == NULL) - { - clnt_debug(ni, "_ni_readname"); - return NI_FAILED; - } - - if (resp->status == NI_OK) - { - *id = resp->ni_readname_res_u.stuff.id; - *name = resp->ni_readname_res_u.stuff.name; - } - - return resp->status; -} - - -ni_status -ni_resync(void *ni) -{ - ni_status *resp; - - if (ni == NULL) return NI_FAILED; - - resp = (ni_status *)RCALLIT(ni, _ni_resync_2, NULL); - if (resp == NULL) - { - clnt_debug(ni, "_ni_resync"); - return NI_FAILED; - } - - return *resp; -} - - -ni_status -ni_setuser(void *ni, ni_name_const user) -{ - ni_id id; - ni_idlist ids; - ni_namelist nl; - char *p; - ni_status status; - - if (ni == NULL) return NI_FAILED; - - if (user == NULL) - { - NIP(ni)->uid = getuid(); - return ni_setpassword(ni, NULL); - } - - status = ni_root(ni, &id); - if (status != NI_OK) return NI_NOUSER; - - NI_INIT(&ids); - status = ni_lookup(ni, &id, NAME_NAME, NAME_USERS, &ids); - if (status != NI_OK) return NI_NOUSER; - - id.nii_object = ids.niil_val[0]; - ni_idlist_free(&ids); - - NI_INIT(&ids); - status = ni_lookup(ni, &id, NAME_NAME, user, &ids); - if (status != NI_OK) return NI_NOUSER; - - id.nii_object = ids.niil_val[0]; - ni_idlist_free(&ids); - - NI_INIT(&nl); - status = ni_lookupprop(ni, &id, NAME_UID, &nl); - if (status != NI_OK) return NI_NOUSER; - - if (nl.ninl_len == 0) return NI_NOUSER; - - for (p = nl.ninl_val[0]; *p; p++) - { - if (isdigit(*p) == 0) - { - ni_namelist_free(&nl); - return NI_NOUSER; - } - } - - NIP(ni)->uid = atoi(nl.ninl_val[0]); - if (NIP(ni)->passwd == NULL) NIP(ni)->passwd = ni_name_dup(""); - - createauth(NIP(ni)); - return NI_OK; -} - - -ni_status -ni_setpassword(void *ni, ni_name_const passwd) -{ - char *p; - - if (ni == NULL) return NI_FAILED; - - if (NIP(ni)->passwd != NULL) ni_name_free(&NIP(ni)->passwd); - - if (passwd == NULL) - { - NIP(ni)->passwd = NULL; - if (NIP(ni)->tc != NULL) - { - auth_destroy(NIP(ni)->tc->cl_auth); - NIP(ni)->tc->cl_auth = authnone_create(); - } - return NI_OK; - } - - NIP(ni)->passwd = ni_name_dup(passwd); - - /* Our trivial encryption scheme */ - for (p = NIP(ni)->passwd; *p; p++) *p = ~(*p); - createauth(NIP(ni)); - return NI_OK; -} - - -/* - * The procedure pmap_getport_to below is derived - * from Sun Microsystems RPC source code. As such the following - * statement applies to it.: - * - * Sun RPC is a product of Sun Microsystems, Inc. and is provided for - * unrestricted use provided that this legend is included on all tape - * media and as a part of the software program in whole or part. Users - * may copy or modify Sun RPC without charge, but are not authorized - * to license or distribute it to anyone else except as part of a product or - * program developed by the user. - * - * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE - * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * - * Sun RPC is provided with no support and without any obligation on the - * part of Sun Microsystems, Inc. to assist in its use, correction, - * modification or enhancement. - * - * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE - * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC - * OR ANY PART THEREOF. - * - * In no event will Sun Microsystems, Inc. be liable for any lost revenue - * or profits or other special, indirect and consequential damages, even if - * Sun has been advised of the possibility of such damages. - * - * Sun Microsystems, Inc. - * 2550 Garcia Avenue - * Mountain View, California 94043 - */ -/* - * Client interface to pmap rpc service. - * - * Find the mapped port for program,version. - * Calls the pmap service remotely to do the lookup. - * Returns 0 if no map exists. - */ -static u_short -pmap_getport_to(address, program, version, protocol, timeout_secs, ntries) - struct sockaddr_in *address; - u_long program; - u_long version; - u_int protocol; - int timeout_secs; - int ntries; -{ - u_short port = 0; - int sock = -1; - register CLIENT *client; - struct pmap parms; - struct timeval timeout; - - sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (sock < 0) return 0; - - address->sin_port = htons(PMAPPORT); - timeout.tv_usec = ((timeout_secs % ntries) * 1000000) / ntries; - timeout.tv_sec = (timeout_secs / ntries); - - client = clntudp_bufcreate(address, PMAPPROG, PMAPVERS, timeout, &sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); - if (client != NULL) - { - parms.pm_prog = program; - parms.pm_vers = version; - parms.pm_prot = protocol; - parms.pm_port = 0; /* not needed or used */ - timeout.tv_usec = 0; - timeout.tv_sec = timeout_secs; - - if (CLNT_CALL(client, PMAPPROC_GETPORT, (xdrproc_t)xdr_pmap, (char *)&parms, (xdrproc_t)xdr_u_short, (char *)&port, timeout) != RPC_SUCCESS) - { - rpc_createerr.cf_stat = RPC_PMAPFAILURE; - clnt_geterr(client, &rpc_createerr.cf_error); - port = 0; - } - else if (port == 0) - { - rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; - } - } - - if (client != NULL) clnt_destroy(client); - - close(sock); - address->sin_port = 0; - return port; -} - - -/* - * Open a socket, but do not use the default portmap timeout - */ -static int -socket_open(struct sockaddr_in *raddr, int prog, int vers, int timeout, int ntries, int proto) -{ - struct sockaddr_in bindsin; - int sock; - int reuse = 1; - u_short port; - - memset(&bindsin, 0, sizeof(bindsin)); - - /* - * If no port number given ask the pmap for one - */ - if (raddr->sin_port == 0) - { - port = pmap_getport_to(raddr, prog, vers, IPPROTO_UDP, timeout, ntries); - if (port == 0) return -1; - - raddr->sin_port = htons(port); - } - - sock = socket(AF_INET, proto == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM, proto); - if (sock < 0) return -1; - - if ((bindresvport(sock, NULL) < 0) && (errno == EADDRNOTAVAIL)) - { - /* XXX - we're hitting this case way too often under load */ - /* fail gracefully: some address is better than none most of the time */ - syslog(LOG_DEBUG, "Libinfo[%s():%d] bindresvport(): %m", __func__, __LINE__); - if (bind(sock, (struct sockaddr *)&bindsin, sizeof(bindsin)) < 0) - { - /* The system is really sad now if it can't give me any address... */ - syslog(LOG_DEBUG, "Libinfo[%s():%d] bind(): %m", __func__, __LINE__); - close(sock); - return -1; - } - } - - setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(int)); - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)); - - if (proto == IPPROTO_TCP) - { - if (connect(sock, (struct sockaddr *)raddr, sizeof(*raddr)) < 0) - { - syslog(LOG_DEBUG, "Libinfo[%s():%d] connect(): %m", __func__, __LINE__); - close(sock); - return -1; - } - } - - return sock; -} diff --git a/netinfo.subproj/ni_prot.x b/netinfo.subproj/ni_prot.x deleted file mode 100644 index a83e0fe..0000000 --- a/netinfo.subproj/ni_prot.x +++ /dev/null @@ -1,502 +0,0 @@ -/* - * 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@ - */ -/* - * NetInfo protocol specification - * Copyright (C) 1989 by NeXT, Inc. - */ - -/* Preamble appearing on all generated output */ -#ifndef NOPREAMBLE -%/* -% * Output of the RPC protocol compiler: DO NOT EDIT -% * Copyright (C) 1989 by NeXT, Inc. -% */ -#endif - -#ifndef RPC_HDR -%#include -#endif - -const NI_NAME_MAXLEN = 65535; -const NI_NAMELIST_MAXLEN = 65535; -const NI_PROPLIST_MAXLEN = 65535; -const NI_IDLIST_MAXLEN = 1048576; - -/* - * Every object has a unique ID. One part of the ID identifies the object - * itself. The other identifies the instance of the object. Every time - * an object is written or an object is destroyed and then reallocated, - * its instance is incremented. - * - * All read operations ignore the instance field. All write operations - * refuse to operate on the object if there is an instance mismatch. - */ - -/* - * Don't go through unnecessary overhead for xdr_ni_index using typedef - * rpcgen needs an optimizer so we don't have to do this! - */ -#ifdef RPC_HDR -%typedef unsigned long ni_index; -#endif -#define ni_index unsigned long - -struct ni_id { - ni_index nii_object; - ni_index nii_instance; -}; - - -/* - * Names are assumed to contain human-readable ASCII characters. - */ -typedef string ni_name; - - -typedef ni_name ni_namelist; - -/* - * A property - */ -struct ni_property { - ni_name nip_name; - ni_namelist nip_val; -}; - -/* - * A list of properties - */ -typedef ni_property ni_proplist; - -/* - * A list of IDs (yet another variable-length array) - */ -typedef ni_index ni_idlist; - - -/* - * A name object - */ -struct ni_object { - ni_id nio_id; - ni_proplist nio_props; - ni_index nio_parent; - ni_idlist nio_children; -}; - - -/* - * All operations return a status indicating either that the requested - * operation succeeded or why it failed. - */ -enum ni_status { - NI_OK, /* Operation succeeded */ - NI_BADID, /* ID is invalid */ - NI_STALE, /* Write attempted on stale version of object */ - NI_NOSPACE, /* No space available for write operation */ - NI_PERM, /* Permission denied */ - NI_NODIR, /* No such directory */ - NI_NOPROP, /* No such property */ - NI_NONAME, /* No such name */ - NI_NOTEMPTY, /* Cannot delete name object with children */ - NI_UNRELATED, /* Object is not child of parent: cannot destroy */ - NI_SERIAL, /* Serialization error */ - NI_NETROOT, /* Hit network root domain */ - NI_NORESPONSE, /* No response from remote parent */ - NI_RDONLY, /* No writes allowed: all objects are read-only */ - NI_SYSTEMERR, /* generic remote error */ - NI_ALIVE, /* Can't regenerate: already in use */ - NI_NOTMASTER, /* Operation makes no sense on clone */ - NI_CANTFINDADDRESS, /* Can't find address of server */ - NI_DUPTAG, /* Duplicate domain tag: can't serve it */ - NI_NOTAG, /* No such tag */ - NI_AUTHERROR, /* Authentication error */ - NI_NOUSER, /* No such user */ - NI_MASTERBUSY, /* Master server is busy */ - NI_INVALIDDOMAIN, /* Invalid Domain */ - NI_BADOP, /* Invalid operation on master */ - NI_FAILED = 9999 /* generic local error */ -}; - -/* - * Wrappers needed to handle arguments and results - */ -union ni_id_res switch (ni_status status) { -case NI_OK: - ni_id id; -default: - void; -}; - -struct ni_parent_stuff { - ni_index object_id; - ni_id self_id; -}; - -union ni_parent_res switch (ni_status status) { -case NI_OK: - struct ni_parent_stuff stuff; -default: - void; -}; - -struct ni_children_stuff { - ni_idlist children; - ni_id self_id; -}; - -union ni_children_res switch (ni_status status) { -case NI_OK: - ni_children_stuff stuff; -default: - void; -}; - -struct ni_entry { - ni_index id; - ni_namelist *names; -}; - -typedef ni_entry ni_entrylist; - -struct ni_list_stuff { - ni_entrylist entries; - ni_id self_id; -}; - -union ni_list_res switch (ni_status status) { -case NI_OK: - ni_list_stuff stuff; -default: - void; -}; - -struct ni_proplist_stuff { - ni_id id; - ni_proplist props; -}; - -struct ni_create_args { - ni_id id; - ni_proplist props; - ni_index where; - ni_id *target_id; -}; - -union ni_proplist_res switch (ni_status status) { -case NI_OK: - ni_proplist_stuff stuff; -default: - void; -}; - -struct ni_create_stuff { - ni_id id; - ni_id self_id; -}; - -union ni_create_res switch (ni_status status) { -case NI_OK: - ni_create_stuff stuff; -default: - void; -}; - -struct ni_destroy_args { - ni_id parent_id; - ni_id self_id; -}; - -struct ni_lookup_args { - ni_id id; - ni_name key; - ni_name value; -}; - -struct ni_lookup_stuff { - ni_idlist idlist; - ni_id self_id; -}; - -union ni_lookup_res switch (ni_status status) { -case NI_OK: - ni_lookup_stuff stuff; -default: - void; -}; - - -struct ni_name_args { - ni_id id; - ni_name name; -}; - -struct ni_createprop_args { - ni_id id; - ni_property prop; - ni_index where; -}; - -struct ni_writeprop_args { - ni_id id; - ni_index prop_index; - ni_namelist values; -}; - -struct ni_prop_args { - ni_id id; - ni_index prop_index; -}; - -struct ni_namelist_stuff { - ni_namelist values; - ni_id self_id; -}; - -union ni_namelist_res switch (ni_status status) { -case NI_OK: - ni_namelist_stuff stuff; -default: - void; -}; - -struct ni_propname_args { - ni_id id; - ni_index prop_index; - ni_name name; -}; - -struct ni_createname_args { - ni_id id; - ni_index prop_index; - ni_name name; - ni_index where; -}; - -struct ni_nameindex_args { - ni_id id; - ni_index prop_index; - ni_index name_index; -}; - -struct ni_writename_args { - ni_id id; - ni_index prop_index; - ni_index name_index; - ni_name name; -}; - -struct ni_readname_stuff { - ni_id id; - ni_name name; -}; - -union ni_readname_res switch (ni_status status) { -case NI_OK: - ni_readname_stuff stuff; -default: - void; -}; - -struct ni_binding { - ni_name tag; - unsigned addr; -}; - -union ni_rparent_res switch (ni_status status) { -case NI_OK: - ni_binding binding; -default: - void; -}; - -typedef struct ni_object_node *ni_object_list; -struct ni_object_node { - ni_object object; - ni_object_list next; -}; - -struct ni_readall_stuff { - unsigned checksum; - ni_index highestid; - ni_object_list list; -}; - -union ni_readall_res switch (ni_status status) { -case NI_OK: - ni_readall_stuff stuff; -default: - void; -}; - -typedef ni_proplist ni_proplist_list; - -struct ni_listall_stuff { - ni_id self_id; - ni_proplist_list entries; -}; - -union ni_listall_res switch (ni_status status) { -case NI_OK: - ni_listall_stuff stuff; -default: - void; -}; - - -program NI_PROG { - version NI_VERS { - void - _NI_PING(void) = 0; - /* - * Get various server statistics - */ - ni_proplist - _NI_STATISTICS(void) = 1; - - /* - * Procedures dealing with nodes - */ - ni_id_res - _NI_ROOT(void) = 2; - - ni_id_res - _NI_SELF(ni_id) = 3; - - ni_parent_res - _NI_PARENT(ni_id) = 4; - - ni_create_res - _NI_CREATE(ni_create_args) = 5; - - ni_id_res - _NI_DESTROY(ni_destroy_args) = 6; - - ni_proplist_res - _NI_READ(ni_id) = 7; - - ni_id_res - _NI_WRITE(ni_proplist_stuff) = 8; - - ni_children_res - _NI_CHILDREN(ni_id) = 9; - - ni_lookup_res - _NI_LOOKUP(ni_lookup_args) = 10; - - ni_list_res - _NI_LIST(ni_name_args) = 11; - - /* - * Procedures dealing with properties - */ - ni_id_res - _NI_CREATEPROP(ni_createprop_args) = 12; - - ni_id_res - _NI_DESTROYPROP(ni_prop_args) = 13; - - ni_namelist_res - _NI_READPROP(ni_prop_args) = 14; - - ni_id_res - _NI_WRITEPROP(ni_writeprop_args) = 15; - - ni_id_res - _NI_RENAMEPROP(ni_propname_args) = 16; - - ni_namelist_res - _NI_LISTPROPS(ni_id) = 17; - - /* - * Procedures dealing with names - */ - ni_id_res - _NI_CREATENAME(ni_createname_args) = 18; - - ni_id_res - _NI_DESTROYNAME(ni_nameindex_args) = 19; - - ni_readname_res - _NI_READNAME(ni_nameindex_args) = 20; - - ni_id_res - _NI_WRITENAME(ni_writename_args) = 21; - - /* - * Returns the address of this domain's remote parent - */ - ni_rparent_res - _NI_RPARENT(void) = 22; - - /* - * List all properties of each subdirectory, not just - * just a single named property. - * - * WARNING: this routine is dangerous and may be - * removed from future implementations of the protocol. - * While it is good the the network in that there is - * less data on it because a lot is done in a single call, - * it is bad for the server because it ties it up and locks - * others out. - */ - ni_listall_res - _NI_LISTALL(ni_id) = 23; - - /* - * Answers only if the given binding is served - */ - void - _NI_BIND(ni_binding) = 24; - - /* - * Read the entire database if the checksum is different - * Implemented by master only. - */ - ni_readall_res - _NI_READALL(unsigned) = 25; - - /* - * Informs server that master has crashed. Hands out - * latest checksum. - */ - void - _NI_CRASHED(unsigned) = 26; - - /* - * If master, force clones to resync. - * If clone, resync with master. - */ - ni_status - _NI_RESYNC(void) = 27; - - - /* - * Extra procedure added for performance - * Terminates on first hit, returns proplist - */ - ni_proplist_res - _NI_LOOKUPREAD(ni_lookup_args) = 28; - } = 2; -} = 200100000; diff --git a/netinfo.subproj/ni_pwdomain.c b/netinfo.subproj/ni_pwdomain.c deleted file mode 100644 index e6e1a23..0000000 --- a/netinfo.subproj/ni_pwdomain.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * 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 (C) 1990 by NeXT, Inc. All rights reserved. - */ - -/* - * ni_pwdomain function: present working domain for a netinfo handle - * - * usage: - * ni_status ni_pwdomain(void *ni, ni_name *buf) - * - * pwd is returned in buf, which can be freed with ni_name_free - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sys_interfaces.h" - -extern char *inet_ntoa(); - -static const char NAME_NAME[] = "name"; -static const char NAME_MACHINES[] = "machines"; -static const char NAME_IP_ADDRESS[] = "ip_address"; -static const char NAME_SERVES[] = "serves"; -static const char NAME_UNKNOWN[] = "###UNKNOWN###"; - -static ni_name -escape_domain(ni_name name) -{ - int extra; - char *p; - char *s; - ni_name newname; - - extra = 0; - for (p = name; *p; p++) - { - if ((*p == '/') || (*p == '\\')) extra++; - } - - newname = malloc(strlen(name) + extra + 1); - s = newname; - for (p = name; *p; p++) - { - if ((*p == '/') || (*p == '\\')) *s++ = '\\'; - *s++ = *p; - } - - *s = 0; - return newname; - -} - -static char * -finddomain(void *ni, struct in_addr addr, ni_name tag) -{ - ni_id nid; - ni_idlist idl; - ni_namelist nl; - ni_index i; - ni_name slash; - ni_name domain; - ni_status status; - - status = ni_root(ni, &nid); - if (status != NI_OK) return NULL; - - status = ni_lookup(ni, &nid, NAME_NAME, NAME_MACHINES, &idl); - if (status != NI_OK) return NULL; - - nid.nii_object = idl.niil_val[0]; - ni_idlist_free(&idl); - - status = ni_lookup(ni, &nid, NAME_IP_ADDRESS, inet_ntoa(addr), &idl); - if (status != NI_OK) return NULL; - - nid.nii_object = idl.niil_val[0]; - ni_idlist_free(&idl); - - status = ni_lookupprop(ni, &nid, NAME_SERVES, &nl); - if (status != NI_OK) return NULL; - - for (i = 0; i < nl.ninl_len; i++) - { - slash = rindex(nl.ninl_val[i], '/'); - if (slash == NULL) continue; - - if (ni_name_match(slash + 1, tag)) - { - *slash = 0; - domain = escape_domain(nl.ninl_val[i]); - ni_namelist_free(&nl); - return domain; - } - } - - ni_namelist_free(&nl); - - return NULL; -} - -static char * -ni_domainof(void *ni, void *parent) -{ - struct sockaddr_in addr; - ni_name tag; - ni_name dom; - ni_status status; - interface_list_t *ilist; - int i; - - status = ni_addrtag(ni, &addr, &tag); - if (status != NI_OK) return ni_name_dup(NAME_UNKNOWN); - - dom = finddomain(parent, addr.sin_addr, tag); - if (dom != NULL) - { - ni_name_free(&tag); - return dom; - } - - ilist = _libinfo_ni_sys_interfaces(); - if (ilist == NULL) return ni_name_dup(NAME_UNKNOWN); - if (_libinfo_ni_sys_is_my_address(ilist, &(addr.sin_addr))) - { - /* Try all my non-loopback interfaces */ - for (i = 0; i < ilist->count; i++) - { - if (ilist->interface[i].addr.s_addr == htonl(INADDR_LOOPBACK)) continue; - - addr.sin_addr.s_addr = ilist->interface[i].addr.s_addr; - dom = finddomain(parent, addr.sin_addr, tag); - if (dom != NULL) - { - ni_name_free(&tag); - _libinfo_ni_sys_interfaces_release(ilist); - return dom; - } - } - } - _libinfo_ni_sys_interfaces_release(ilist); - - dom = malloc(strlen(tag) + 256); - sprintf(dom, "%s@%s", tag, inet_ntoa(addr.sin_addr.s_addr)); - ni_name_free(&tag); - return dom; -} - -static ni_status -_ni_pwdomain(void *ni, ni_name *buf) -{ - void *nip; - ni_status status; - int len; - char *dom; - - /* Open domain name */ - nip = ni_new(ni, ".."); - if (nip == NULL) - { - (*buf) = malloc(2); - (*buf)[0] = 0; - return NI_OK; - } - - /* Get parent's name */ - status = _ni_pwdomain(nip, buf); - if (status != NI_OK) return status; - - /* Get my name relative to my parent */ - dom = ni_domainof(ni, nip); - - /* Append my relative name to my parent's name */ - len = strlen(*buf); - *buf = realloc(*buf, len + 1 + strlen(dom) + 1); - (*buf)[len] = '/'; - strcpy(&(*buf)[len + 1], dom); - ni_name_free(&dom); - ni_free(nip); - - return NI_OK; -} - -/* - * Just call the recursive ni_pwdomain above, and then fix for case of root - * domain or error - */ -ni_status -ni_pwdomain(void *ni, ni_name *buf) -{ - ni_status status; - - *buf = NULL; - status = _ni_pwdomain(ni, buf); - if (status != NI_OK) - { - if (*buf != NULL) ni_name_free(buf); - return status; - } - - if ((*buf)[0] == 0) - { - (*buf)[0] = '/'; - (*buf)[1] = 0; - } - - return NI_OK; -} diff --git a/netinfo.subproj/ni_stub.c b/netinfo.subproj/ni_stub.c new file mode 100644 index 0000000..183d72d --- /dev/null +++ b/netinfo.subproj/ni_stub.c @@ -0,0 +1,171 @@ +#include +#include +#include + +#define NI_FAILED 9999 +#define RPC_FAILED 16 + +typedef struct +{ + int a; + int b; +} stub_type_0; + +typedef struct +{ + int a; + void *b; +} stub_type_1; + +typedef struct +{ + void *a; + stub_type_1 b; +} stub_type_2; + +static stub_type_1 empty_stub_type_1() +{ + stub_type_1 a; + + memset(&a, 0, sizeof(stub_type_1)); + return a; +} + +static stub_type_2 empty_stub_type_2() +{ + stub_type_2 a; + + memset(&a, 0, sizeof(stub_type_2)); + return a; +} + +static int debug_log(const char *func) +{ + syslog(LOG_ERR, "NetInfo stub: %s", func); + return NI_FAILED; +} + +const char *ni_error(int a) { return "Communication failure"; } +int multi_call(int a, void *b, int c, int d, int e, void *f, void *g, int h, void *i, void *j, int (*k)(void *, void *, int), int l) { return RPC_FAILED; } +stub_type_2 ni_prop_dup(stub_type_2 a) { return empty_stub_type_2(); } +int ni_name_match(void *a, void *b) { return 0; } +void *ni_name_dup(void *a) { return NULL; } + +stub_type_1 ni_idlist_dup(stub_type_1 a) { return empty_stub_type_1(); } +stub_type_1 ni_proplist_dup(stub_type_1 a) { return empty_stub_type_1(); } +stub_type_1 ni_namelist_dup(stub_type_1 a) { return empty_stub_type_1(); } + +int ni_idlist_delete(void *a, int b) { return -1; } +int ni_proplist_match(stub_type_1 a, void *b, void *c) { return -1; } +int ni_namelist_match(stub_type_1 a, void *b) { return -1; } + +void ni_idlist_insert(void *a, int b, int c) {} +void ni_idlist_free(void *a) {} +void ni_proplist_insert(void *a, stub_type_2 b, int c) {} +void ni_proplist_delete(void *a, int b) {} +void ni_proplist_free(void *a) {} +void ni_proplist_list_free(void *a) {} +void ni_prop_free(void *a) {} +void ni_name_free(void *a) {} +void ni_namelist_free(void *a) {} +void ni_namelist_insert(void *a, void *b, int c) {} +void ni_namelist_delete(void *a, int b) {} +void ni_entrylist_insert(void *a, stub_type_1 b) {} +void ni_entrylist_delete(void *a, int b) {} +void ni_entrylist_free(void *a) {} +void ni_parse_url(void *a, void *b, void *c, void *d, void *e, void *f) {} +void ni_setabort(void *a, int b) {} +void ni_setwritetimeout(void *a, int b) {} +void ni_setreadtimeout(void *a, int b) {} +void ni_needwrite(void *a, int b) {} +void ni_free(void *a) {} + +int ni_find(void *a, void *b, void *c, int d) { return debug_log(__FUNCTION__); } +int ni_open(void *a, void *b, void *c) { return debug_log(__FUNCTION__); } +int ni_fancyopen(void *a, void *b, void *c, void *d) { return debug_log(__FUNCTION__); } +int ni_host_domain(void *a, void *b, void *c) { return debug_log(__FUNCTION__); } +int ni_url(void *a, void *b, void *c) { return debug_log(__FUNCTION__); } + +void *_ni_dup(void *a) { debug_log(__FUNCTION__); return NULL; } +void *ni_connect(void *a, void *b) { debug_log(__FUNCTION__); return NULL; } +void *ni_new(void *a, void *b) { debug_log(__FUNCTION__); return NULL; } + +int ni_lookupprop(void *a, void *b, void *c, void *d) { return NI_FAILED; } +int ni_search(void *a, void *b, void *c, void *d, int e, void *f) { return NI_FAILED; } +int ni_pathsearch(void *a, void *b, void *c) { return NI_FAILED; } +int ni_pwdomain(void *a, void *b) { return NI_FAILED; } +int ni_addrtag(void *a, void *b, void *c) { return NI_FAILED; } +int ni_statistics(void *q, void *b) { return NI_FAILED; } +int ni_root(void *a, void *b) { return NI_FAILED; } +int ni_self(void *a, void *b) { return NI_FAILED; } +int ni_parent(void *q, void *b, void *c) { return NI_FAILED; } +int ni_children(void *q, void *b, void *c) { return NI_FAILED; } +int ni_create(void *a, void *b, stub_type_1 c, void *d, int e) { return NI_FAILED; } +int ni_destroy(void *a, void *b, stub_type_0 c) { return NI_FAILED; } +int ni_write(void *a, void *b, stub_type_1 c) { return NI_FAILED; } +int ni_read(void *a, void *b, void *c) { return NI_FAILED; } +int ni_lookup(void *a, void *b, void *c, void *d, void *e) { return NI_FAILED; } +int ni_lookupread(void *a, void *b, void *c, void *d, void *e) { return NI_FAILED; } +int ni_list(void *a, void *b, void *c, void *d) { return NI_FAILED; } +int ni_listall(void *a, void *b, void *c) { return NI_FAILED; } +int ni_readprop(void *a, void *b, int c, void *d) { return NI_FAILED; } +int ni_writeprop(void *a, void *b, int c, stub_type_1 d) { return NI_FAILED; } +int ni_listprops(void *a, void *b, void *c) { return NI_FAILED; } +int ni_createprop(void *a, void *b, stub_type_2 c, int d) { return NI_FAILED; } +int ni_destroyprop(void *a, void *b, int c) { return NI_FAILED; } +int ni_renameprop(void *a, void *b, int c, void *d) { return NI_FAILED; } +int ni_createname(void *a, void *b, int c, void *d, int e) { return NI_FAILED; } +int ni_destroyname(void *a, void *b, int c, int d) { return NI_FAILED; } +int ni_writename(void *a, void *b, int c, int d, void *e) { return NI_FAILED; } +int ni_readname(void *a, void *b, int c, int d, void *e) { return NI_FAILED; } +int ni_resync(void *a) { return NI_FAILED; } +int ni_setuser(void *a, void *b) { return NI_FAILED; } +int ni_setpassword(void *a, void *b) { return NI_FAILED; } + +int xdr_ni_id(void *a, void *b) { return 0; } +int xdr_ni_name(void *a, void *b) { return 0; } +int xdr_ni_namelist(void *a, void *b) { return 0; } +int xdr_ni_property(void *a, void *b) { return 0; } +int xdr_ni_proplist(void *a, void *b) { return 0; } +int xdr_ni_idlist(void *a, void *b) { return 0; } +int xdr_ni_object(void *a, void *b) { return 0; } +int xdr_ni_status(void *a, void *b) { return 0; } +int xdr_ni_id_res(void *a, void *b) { return 0; } +int xdr_ni_parent_stuff(void *a, void *b) { return 0; } +int xdr_ni_parent_res(void *a, void *b) { return 0; } +int xdr_ni_children_stuff(void *a, void *b) { return 0; } +int xdr_ni_children_res(void *a, void *b) { return 0; } +int xdr_ni_entry(void *a, void *b) { return 0; } +int xdr_ni_entrylist(void *a, void *b) { return 0; } +int xdr_ni_list_stuff(void *a, void *b) { return 0; } +int xdr_ni_list_res(void *a, void *b) { return 0; } +int xdr_ni_proplist_stuff(void *a, void *b) { return 0; } +int xdr_ni_create_args(void *a, void *b) { return 0; } +int xdr_ni_proplist_res(void *a, void *b) { return 0; } +int xdr_ni_create_stuff(void *a, void *b) { return 0; } +int xdr_ni_create_res(void *a, void *b) { return 0; } +int xdr_ni_destroy_args(void *a, void *b) { return 0; } +int xdr_ni_lookup_args(void *a, void *b) { return 0; } +int xdr_ni_lookup_stuff(void *a, void *b) { return 0; } +int xdr_ni_lookup_res(void *a, void *b) { return 0; } +int xdr_ni_name_args(void *a, void *b) { return 0; } +int xdr_ni_createprop_args(void *a, void *b) { return 0; } +int xdr_ni_writeprop_args(void *a, void *b) { return 0; } +int xdr_ni_prop_args(void *a, void *b) { return 0; } +int xdr_ni_namelist_stuff(void *a, void *b) { return 0; } +int xdr_ni_namelist_res(void *a, void *b) { return 0; } +int xdr_ni_propname_args(void *a, void *b) { return 0; } +int xdr_ni_createname_args(void *a, void *b) { return 0; } +int xdr_ni_nameindex_args(void *a, void *b) { return 0; } +int xdr_ni_writename_args(void *a, void *b) { return 0; } +int xdr_ni_readname_stuff(void *a, void *b) { return 0; } +int xdr_ni_readname_res(void *a, void *b) { return 0; } +int xdr_ni_binding(void *a, void *b) { return 0; } +int xdr_ni_rparent_res(void *a, void *b) { return 0; } +int xdr_ni_object_list(void *a, void *b) { return 0; } +int xdr_ni_object_node(void *a, void *b) { return 0; } +int xdr_ni_readall_stuff(void *a, void *b) { return 0; } +int xdr_ni_readall_res(void *a, void *b) { return 0; } +int xdr_ni_proplist_list(void *a, void *b) { return 0; } +int xdr_ni_listall_stuff(void *a, void *b) { return 0; } +int xdr_ni_listall_res(void *a, void *b) { return 0; } diff --git a/netinfo.subproj/ni_useful.c b/netinfo.subproj/ni_useful.c deleted file mode 100644 index 9364584..0000000 --- a/netinfo.subproj/ni_useful.c +++ /dev/null @@ -1,746 +0,0 @@ -/* - * 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@ - */ -/* - * Useful stuff for programming netinfo - * Copyright (C) 1989 by NeXT, Inc. - */ -#include -#include -#include -#include -#include -#include -#include - -extern void *_ni_dup(void *); - -static const char * -eatslash( - const char *path - ) -{ - while (*path == '/') { - path++; - } - return (path); -} - -static void -unescape( - ni_name *name - ) -{ - ni_name newname; - ni_name p; - int len; - int i; - - p = *name; - len = strlen(p); - newname = malloc(len + 1); - for (i = 0; *p != 0; i++) { - if (*p == '\\') { - p++; - } - newname[i] = *p++; - } - ni_name_free(name); - newname[i] = 0; - *name = newname; -} - -static const char * -escindex( - const char *str, - char ch - ) -{ - char *p; - - p = index(str, ch); - if (p == NULL) { - return (NULL); - } - if (p == str) { - return (p); - } - if (p[-1] == '\\') { - return (escindex(p + 1, ch)); - } - return (p); -} - -static void -setstuff( - void *ni, - ni_fancyopenargs *args - ) -{ - if (args != NULL) { - ni_setabort(ni, args->abort); - if (args->rtimeout) { - ni_setreadtimeout(ni, args->rtimeout); - } - if (args->wtimeout) { - ni_setwritetimeout(ni, args->wtimeout); - } - } -} - -static void * -ni_relopen( - void *ni, - const char *domain, - int freeold, - ni_fancyopenargs *args - ) -{ - void *newni; - void *tmpni; - char *start; - char *slash; - char *component; - - /* look for @
in last component of domain */ - start = (char *)domain; - while ((slash = (char *)escindex(start, '/')) != NULL) { - /* found a slash, keep looking for the last one */ - start = slash + 1; - } - if (index(start, '@') != NULL) { - /* - * last component in @
form, skip - * all of the leading components. - */ - component = ni_name_dup(start); - newni = ni_new(NULL, component); - free(component); - if (newni != NULL && args != NULL) - setstuff(newni, args); - if (ni != NULL && freeold) - ni_free(ni); - return (newni); - } - - component = ni_name_dup(domain); - slash = (char *)escindex(component, '/'); - if (slash != NULL) { - *slash = 0; - } - unescape(&component); - - tmpni = NULL; - if (ni != NULL && args != NULL) { - tmpni = _ni_dup(ni); - if (freeold) { - ni_free(ni); - } - ni = tmpni; - setstuff(ni, args); - } - - newni = ni_new(ni, component); - free(component); - - if (tmpni != NULL) { - ni_free(ni); - ni = NULL; - } - - if (ni != NULL && freeold) { - ni_free(ni); - } - - - if (newni == NULL) { - return (NULL); - } - setstuff(newni, args); - ni = newni; - if (slash != NULL) { - slash = (char *)escindex(domain, '/'); - domain = eatslash(slash + 1); - return (ni_relopen(ni, domain, TRUE, NULL)); - } else { - return (ni); - } -} - -static void * -ni_rootopen( - ni_fancyopenargs *args - ) -{ - void *ni; - void *newni; - - ni = ni_new(NULL, "."); - if (ni == NULL) { - return (NULL); - } - setstuff(ni, args); - for (;;) { - newni = ni_new(ni, ".."); - if (newni == NULL) { - break; - } - ni_free(ni); - ni = newni; - } - return (ni); -} - -static ni_name -ni_name_dupn( - ni_name_const start, - ni_name_const stop - ) -{ - int len; - ni_name new; - - if (stop != NULL) { - len = stop - start; - } else { - len = strlen(start); - } - new = malloc(len + 1); - bcopy(start, new, len); - new[len] = 0; - return (new); -} - - -static ni_status -ni_relsearch( - void *ni, - const char *path, - ni_id *id - ) -{ - char *slash; - char *equal; - ni_name key; - ni_name val; - ni_idlist idl; - ni_status status; - - slash = (char *)escindex(path, '/'); - equal = (char *)escindex(path, '='); - if (equal != NULL && (slash == NULL || equal < slash)) { - key = ni_name_dupn(path, equal); - val = ni_name_dupn(equal + 1, slash); - } else { - if (equal == NULL || (slash != NULL && slash < equal)) { - key = ni_name_dup("name"); - val = ni_name_dupn(path, slash); - } else { - key = ni_name_dupn(path, equal); - val = ni_name_dupn(equal + 1, slash); - } - } - unescape(&key); - unescape(&val); - NI_INIT(&idl); - status = ni_lookup(ni, id, key, val, &idl); - if (status != NI_OK) { - ni_name_free(&key); - ni_name_free(&val); - return (status); - } - id->nii_object = idl.niil_val[0]; - ni_name_free(&key); - ni_name_free(&val); - ni_idlist_free(&idl); - if (slash == NULL) { - ni_self(ni, id); - return (NI_OK); - } - path = eatslash(slash); - return (ni_relsearch(ni, path, id)); -} - -ni_status -ni_open( - void *ni, - const char *domain, - void **newni - ) -{ - return (ni_fancyopen(ni, domain, newni, NULL)); -} - -ni_status -ni_fancyopen( - void *ni, - const char *domain, - void **newni, - ni_fancyopenargs *args - ) -{ - void *tmp = NULL; - int rootopen = 0; - - if (*domain == '/') { - tmp = ni_rootopen(args); - if (tmp == NULL) { - return (NI_FAILED); /* XXX: should return real error */ - } - domain = eatslash(domain); - ni = tmp; - rootopen++; - } - if (*domain != 0) { - tmp = ni_relopen(ni, domain, FALSE, args); - if (rootopen) { - ni_free(ni); - } - } - if (tmp == NULL) { - return (NI_FAILED); - } - *newni = tmp; - ni_needwrite(*newni, args == NULL ? 0 : args->needwrite); - return (NI_OK); -} - -ni_status -ni_pathsearch( - void *ni, - ni_id *id, - const char *path - ) -{ - ni_status status; - - if (*path == '/') { - status = ni_root(ni, id); - if (status != NI_OK) { - return (status); - } - } - path = eatslash(path); - if (*path != 0) { - status = ni_relsearch(ni, path, id); - if (status != NI_OK) { - return (status); - } - } - return (NI_OK); -} - -static char ** -_ni_append_string(char *s, char **l) -{ - int i, len; - - if (s == NULL) return l; - if (l == NULL) - { - l = (char **)malloc(2 * sizeof(char *)); - l[0] = strdup(s); - l[1] = NULL; - return l; - } - - for (i = 0; l[i] != NULL; i++); - len = i + 1; /* count the NULL on the end of the list too! */ - - l = (char **)realloc(l, (len + 1) * sizeof(char *)); - - l[len - 1] = strdup(s); - l[len] = NULL; - return l; -} - -static char ** -_ni_explode_string(char *s, char c) -{ - char **l = NULL; - char *p, *t; - int i, n; - - if (s == NULL) return NULL; - - p = s; - while (p[0] != '\0') - { - for (i = 0; ((p[i] != '\0') && p[i] != c); i++); - n = i; - t = malloc(n + 1); - for (i = 0; i < n; i++) t[i] = p[i]; - t[n] = '\0'; - l = _ni_append_string(t, l); - free(t); - t = NULL; - if (p[i] == '\0') return l; - if (p[i + 1] == '\0') l = _ni_append_string("", l); - p = p + i + 1; - } - return l; -} - -static void -_ni_free_list(char **l) -{ - int i; - - if (l == NULL) return; - for (i = 0; l[i] != NULL; i++) - { - if (l[i] != NULL) free(l[i]); - l[i] = NULL; - } - if (l != NULL) free(l); -} - -ni_status -ni_host_domain(char *host, char *domspec, void **domain) -{ - void *d0, *d1; - struct sockaddr_in server; - ni_name tag; - int i, is_tag, is_local, is_relative; - ni_status status; - char **path; - struct hostent *h; - - is_local = 1; - - /* NULL host implies localhost */ - if (host == NULL) - { - server.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - } - else - { - is_local = 0; - server.sin_addr.s_addr = inet_addr(host); - if (server.sin_addr.s_addr == -1) - { - h = gethostbyname(host); - if (h == NULL) - { - *domain = (void *)NULL; - return NI_CANTFINDADDRESS; - } - bcopy(h->h_addr_list[0], &server.sin_addr.s_addr, h->h_length); - } - } - - is_relative = 1; - is_tag = 1; - - if (domspec == NULL) - { - is_tag = 0; - is_relative = 0; - } - else if (domspec[0] == '/') - { - is_tag = 0; - is_relative = 0; - } - else if (!strcmp(domspec, ".")) is_tag = 0; - else if (!strcmp(domspec, "..")) is_tag = 0; - else if (!strncmp(domspec, "./", 2)) is_tag = 0; - else if (!strncmp(domspec, "../", 3)) is_tag = 0; - - if (is_tag == 1) - { - d0 = ni_connect(&server, domspec); - status = ni_addrtag(d0, &server, &tag); - ni_name_free(&tag); - if (status != NI_OK) - { - *domain = (void *)NULL; - return NI_FAILED; - } - - *domain = d0; - return NI_OK; - } - - if (is_local) - { - if (domspec == NULL) status = ni_open(NULL, ".", domain); - else status = ni_open(NULL, domspec, domain); - return status; - } - - d0 = ni_connect(&server, "local"); - status = ni_addrtag(d0, &server, &tag); - ni_name_free(&tag); - if (status != NI_OK) - { - *domain = (void *)NULL; - return NI_FAILED; - } - - if ((domspec == NULL) || (!strcmp(domspec, "."))) - { - *domain = d0; - return NI_OK; - } - - if (is_relative == 1) - { - path = _ni_explode_string(domspec, '/'); - } - else - { - path = _ni_explode_string(domspec + 1, '/'); - - status = NI_OK; - while (status == NI_OK) - { - status = ni_open(d0, "..", &d1); - if (status == NI_OK) - { - ni_free(d0); - d0 = d1; - } - } - - if (!strcmp(domspec, "/")) - { - *domain = d0; - return NI_OK; - } - } - - for (i = 0; path[i] != NULL; i++) - { - status = ni_open(d0, path[i], &d1); - if (status != NI_OK) - { - _ni_free_list(path); - *domain = (void *)NULL; - return NI_FAILED; - } - ni_free(d0); - d0 = d1; - } - - _ni_free_list(path); - *domain = d0; - return NI_OK; -} - -static void -_ni_parse_url_hostspec(char *s, char **u, char **p, char **h) -{ - - char *p_at, *p_colon; - int ulen, plen, hlen; - - if (s == NULL) return; - if (s[0] == '\0') return; - - /* Check for [[[user][:[passwd]]]@]host */ - p_at = strchr(s, '@'); - if (p_at == NULL) - { - hlen = strlen(s); - if (hlen == 0) return; - - *h = malloc(hlen + 1); - strcpy(*h, s); - return; - } - - *p_at = '\0'; - p_at++; - hlen = strlen(p_at); - if (hlen > 0) - { - *h = malloc(hlen + 1); - strcpy(*h, p_at); - } - - if (s[0] == '\0') return; - - p_colon = strchr(s, ':'); - if (p_colon == NULL) - { - ulen = strlen(s); - if (ulen == 0) return; - - *u = malloc(ulen + 1); - strcpy(*u, s); - return; - } - - *p_colon = '\0'; - p_colon++; - plen = strlen(p_colon); - if (plen > 0) - { - *p = malloc(plen + 1); - strcpy(*p, p_colon); - } - - ulen = strlen(s); - if (ulen > 0) - { - *u = malloc(ulen + 1); - strcpy(*u, s); - } -} - -void -ni_parse_url(char *url, char **user, char **password, char **host, - char **domspec, char **dirspec) -{ - int i, x, len; - char *str; - - *host = NULL; - *user = NULL; - *password = NULL; - *domspec = NULL; - *dirspec = NULL; - - /* - * url ::= "netinfo://" [/[][:[]]] - * hostspec ::= [[[user][:[password]]]@]hostref - * hostref ::= | - * domainspec ::= | - * dirspec ::= | - */ - - x = strlen("netinfo://"); - - if (strncmp(url, "netinfo://", x)) return; - - /* - * Look for part - * Defults to NULL user, password and host - * NULL host implies localhost - */ - len = 0; - for (i = x; (url[i] != '\0') && (url[i] != '/'); i++) len++; - - if (len != 0) - { - str = malloc(len + 1); - bcopy(url + x, str, len); - str[len] = '\0'; - - _ni_parse_url_hostspec(str, user, password, host); - - free(str); - } - - /* - * Look for part - * NULL domainspec implies "." - */ - if (url[i] != '\0') i++; - x = i; - len = 0; - for (; (url[i] != '\0') && (url[i] != ':'); i++) len++; - - if (len > 0) - { - *domspec = malloc(len + 1); - bcopy(url + x, *domspec, len); - (*domspec)[len] = '\0'; - } - - /* - * Look for part - * NULL implies "/" - */ - if (url[i] != '\0') i++; - x = i; - len = 0; - for (; url[i] != '\0'; i++) len++; - if (len > 0) - { - *dirspec = malloc(len + 1); - bcopy(url + x, *dirspec, len); - (*dirspec)[len] = '\0'; - } -} - -ni_status -ni_url(char *url, void **domain, ni_id *dir) -{ - int nilen; - char *user, *password, *host; - char *domspec, *dirspec; - ni_status status; - - nilen = strlen("netinfo://"); - - if (strncmp(url, "netinfo://", nilen)) - { - *domain = (void *)NULL; - return NI_CANTFINDADDRESS; - } - - ni_parse_url(url, &user, &password, &host, &domspec, &dirspec); - - status = ni_host_domain(host, domspec, domain); - if (host != NULL) free(host); - if (domspec != NULL) free(domspec); - if (status != NI_OK) - { - if (user != NULL) free(user); - if (password != NULL) free(password); - if (dirspec != NULL) free(dirspec); - return status; - } - - if (user != NULL) - { - ni_setuser(*domain, user); - free(user); - } - - if (password != NULL) - { - ni_setpassword(*domain, password); - free(password); - } - - if (dirspec == NULL) - { - status = ni_root(*domain, dir); - return status; - } - - if ((dirspec[0] >= '0') && (dirspec[0] <= '9')) - { - dir->nii_object = atoi(dirspec); - free(dirspec); - status = ni_self(*domain, dir); - return status; - } - - status = ni_pathsearch(*domain, dir, dirspec); - free(dirspec); - return status; -} diff --git a/netinfo.subproj/ni_util.c b/netinfo.subproj/ni_util.c deleted file mode 100644 index e99f78c..0000000 --- a/netinfo.subproj/ni_util.c +++ /dev/null @@ -1,541 +0,0 @@ -/* - * 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@ - */ -/* - * Utility routines for netinfo data structures - * Copyright (C) 1989 by NeXT, Inc. - */ -#include -#include -#include -#include -#include -#include "mm.h" - -void -ni_idlist_insert( - ni_idlist *cl, - ni_index id, - ni_index where - ) -{ - ni_index i; - - MM_GROW_ARRAY(cl->niil_val, cl->niil_len); - for (i = cl->niil_len; i > where; i--) { - cl->niil_val[i] = cl->niil_val[i - 1]; - } - cl->niil_val[i] = id; - cl->niil_len++; -} - -int -ni_idlist_delete( - ni_idlist *idlist, - ni_index id - ) -{ - ni_index j; - ni_index i; - - for (i = 0; i < idlist->niil_len; i++) { - if (idlist->niil_val[i] == id) { - for (j = i + 1; j < idlist->niil_len; j++) { - idlist->niil_val[j - 1] = idlist->niil_val[j]; - } - MM_SHRINK_ARRAY(idlist->niil_val, idlist->niil_len--); - return(1); - } - } - return (0); -} - - -void -ni_idlist_free( - ni_idlist *idlist - ) -{ - if (idlist->niil_val != NULL) { - MM_FREE_ARRAY(idlist->niil_val, idlist->niil_len); - } - NI_INIT(idlist); -} - -ni_idlist -ni_idlist_dup( - const ni_idlist idlist - ) -{ - ni_idlist newlist; - ni_index i; - - newlist.niil_len = idlist.niil_len; - MM_ALLOC_ARRAY(newlist.niil_val, idlist.niil_len); - for (i = 0; i < idlist.niil_len; i++) { - newlist.niil_val[i] = idlist.niil_val[i]; - } - return (newlist); -} - -void -ni_proplist_insert( - ni_proplist *pl, - const ni_property prop, - ni_index where - ) -{ - ni_index i; - - MM_GROW_ARRAY(pl->nipl_val, pl->nipl_len); - for (i = pl->nipl_len; i > where; i--) { - pl->nipl_val[i] = pl->nipl_val[i - 1]; - } - pl->nipl_val[i] = ni_prop_dup(prop); - pl->nipl_len++; -} - -void -ni_proplist_delete( - ni_proplist *pl, - ni_index which - ) -{ - int i; - - ni_prop_free(&pl->nipl_val[which]); - for (i = which + 1; i < pl->nipl_len; i++) { - pl->nipl_val[i - 1] = pl->nipl_val[i]; - } - MM_SHRINK_ARRAY(pl->nipl_val, pl->nipl_len--); -} - -void -ni_proplist_free( - ni_proplist *pl - ) -{ - ni_index i; - - if (pl->nipl_val == NULL) { - return; - } - for (i = 0; i < pl->nipl_len; i++) { - ni_prop_free(&pl->nipl_val[i]); - } - MM_FREE_ARRAY(pl->nipl_val, pl->nipl_len); - NI_INIT(pl); -} - -void -ni_proplist_list_free( - ni_proplist_list *pll - ) -{ - ni_index i; - - if (pll->nipll_val == NULL) { - return; - } - for (i = 0; i < pll->nipll_len; i++) { - ni_proplist_free(&pll->nipll_val[i]); - } - MM_FREE_ARRAY(pll->nipll_val, pll->nipll_len); - NI_INIT(pll); -} - -ni_proplist -ni_proplist_dup( - const ni_proplist pl - ) -{ - ni_proplist newlist; - ni_index i; - - newlist.nipl_len = pl.nipl_len; - MM_ALLOC_ARRAY(newlist.nipl_val, pl.nipl_len); - for (i = 0; i < pl.nipl_len; i++) { - newlist.nipl_val[i].nip_name = ni_name_dup(pl.nipl_val[i].nip_name); - newlist.nipl_val[i].nip_val = ni_namelist_dup(pl.nipl_val[i].nip_val); - } - return (newlist); -} - -ni_index -ni_proplist_match( - const ni_proplist pl, - ni_name_const pname, - ni_name_const pval - ) -{ - ni_index i; - ni_index j; - ni_namelist nl; - - for (i = 0; i < pl.nipl_len; i++) { - if (ni_name_match(pname, pl.nipl_val[i].nip_name)) { - if (pval == NULL) { - return (i); - } - nl = pl.nipl_val[i].nip_val; - for (j = 0; j < nl.ninl_len; j++) { - if (ni_name_match(pval, nl.ninl_val[j])) { - return (i); - } - } - break; - } - } - return (NI_INDEX_NULL); -} - - -ni_property -ni_prop_dup( - const ni_property prop - ) -{ - ni_property newprop; - - newprop.nip_name = ni_name_dup(prop.nip_name); - newprop.nip_val = ni_namelist_dup(prop.nip_val); - return (newprop); -} - -void -ni_prop_free( - ni_property *prop - ) -{ - ni_name_free(&prop->nip_name); - ni_namelist_free(&prop->nip_val); -} - -int -ni_name_match( - ni_name_const nm1, - ni_name_const nm2 - ) -{ - return (strcmp(nm1, nm2) == 0); -} - -ni_name -ni_name_dup( - ni_name_const nm - ) -{ - return (strcpy(malloc(strlen(nm) + 1), nm)); -} - - -void -ni_name_free( - ni_name *nm - ) -{ - if (*nm != NULL) { - free(*nm); - *nm = NULL; - } -} - -ni_namelist -ni_namelist_dup( - const ni_namelist nl - ) -{ - ni_namelist newlist; - ni_index i; - - newlist.ninl_len = nl.ninl_len; - MM_ALLOC_ARRAY(newlist.ninl_val, newlist.ninl_len); - for (i = 0; i < nl.ninl_len; i++) { - newlist.ninl_val[i] = ni_name_dup(nl.ninl_val[i]); - } - return (newlist); -} - -void -ni_namelist_free( - ni_namelist *nl - ) -{ - ni_index i; - - if (nl->ninl_val == NULL) { - return; - } - for (i = 0; i < nl->ninl_len; i++) { - ni_name_free(&nl->ninl_val[i]); - } - MM_FREE_ARRAY(nl->ninl_val, nl->ninl_len); - NI_INIT(nl); -} - -void -ni_namelist_insert( - ni_namelist *nl, - ni_name_const nm, - ni_index where - ) -{ - ni_index i; - - MM_GROW_ARRAY(nl->ninl_val, nl->ninl_len); - for (i = nl->ninl_len; i > where; i--) { - nl->ninl_val[i] = nl->ninl_val[i - 1]; - } - nl->ninl_val[i] = ni_name_dup(nm); - nl->ninl_len++; -} - -void -ni_namelist_delete( - ni_namelist *nl, - ni_index which - ) -{ - int i; - - ni_name_free(&nl->ninl_val[which]); - for (i = which + 1; i < nl-> ninl_len; i++) { - nl->ninl_val[i - 1] = nl->ninl_val[i]; - } - MM_SHRINK_ARRAY(nl->ninl_val, nl->ninl_len--); -} - -ni_index -ni_namelist_match( - const ni_namelist nl, - ni_name_const nm - ) -{ - ni_index i; - - for (i = 0; i < nl.ninl_len; i++) { - if (ni_name_match(nl.ninl_val[i], nm)) { - return (i); - } - } - return (NI_INDEX_NULL); -} - -void -ni_entrylist_insert( - ni_entrylist *el, - const ni_entry en - ) -{ - ni_entry entry; - - MM_GROW_ARRAY(el->niel_val, el->niel_len); - entry.id = en.id; - if (en.names != NULL) { - MM_ALLOC(entry.names); - *entry.names = ni_namelist_dup(*en.names); - } else { - entry.names = NULL; - } - el->niel_val[el->niel_len++] = entry; -} - -void -ni_entrylist_delete( - ni_entrylist *el, - ni_index which - ) -{ - int i; - - if (el->niel_val[which].names != NULL) { - ni_namelist_free(el->niel_val[which].names); - } - for (i = which + 1; i < el-> niel_len; i++) { - el->niel_val[i - 1] = el->niel_val[i]; - } - MM_SHRINK_ARRAY(el->niel_val, el->niel_len--); -} - -void -ni_entrylist_free( - ni_entrylist *el - ) -{ - ni_index i; - - if (el->niel_val == NULL) { - return; - } - for (i = 0; i < el->niel_len; i++) { - if (el->niel_val[i].names != NULL) { - ni_namelist_free(el->niel_val[i].names); - MM_FREE(el->niel_val[i].names); - } - } - MM_FREE_ARRAY(el->niel_val, el->niel_len); - NI_INIT(el); -} - - - -/* - * We can do this without an addition to the protocol - */ -ni_status -ni_lookupprop( - void *ni, - ni_id *id, - ni_name_const pname, - ni_namelist *nl - ) -{ - ni_status status; - ni_namelist list; - ni_index which; - - NI_INIT(&list); - status = ni_listprops(ni, id, &list); - if (status != NI_OK) { - return (status); - } - which = ni_namelist_match(list, pname); - ni_namelist_free(&list); - if (which == NI_INDEX_NULL) { - return (NI_NOPROP); - } - return (ni_readprop(ni, id, which, nl)); -} - -/* - * Search from local domain to root domain to locate a path. - */ -ni_status -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; - - memset(&addr, 0, sizeof(struct sockaddr_in)); - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - 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) - { - *dom = d; - *nid = n; - return NI_OK; - } - - status = ni_open(d, "..", &p); - ni_free(d); - d = NULL; - if (status == NI_OK) d = p; - } - - return NI_NODIR; -} - -ni_status -ni_search(void *handle, ni_id *dir, ni_name name, ni_name expr, int flags, ni_entrylist *entries) -{ - regex_t *cexp; - int i, j, found; - ni_entrylist el; - ni_namelist *nl; - ni_status status; - - /* compile the regular expression */ - cexp = (regex_t *)malloc(sizeof(regex_t)); - memset(cexp, 0, sizeof(regex_t)); - i = regcomp(cexp, expr, flags); - if (i != 0) - { - free(cexp); - 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; - - nl = el.ni_entrylist_val[i].names; - - found = 0; - for (j = 0; j < nl->ni_namelist_len; j++) - { - if (regexec(cexp, nl->ni_namelist_val[j], 0, NULL, 0) != 0) continue; - found = 1; - break; - } - - if (found == 0) continue; - - if (entries->ni_entrylist_len == 0) - { - entries->ni_entrylist_val = malloc(sizeof(ni_entry)); - } - else - { - entries->ni_entrylist_val = (ni_entry *)realloc(entries->ni_entrylist_val, (entries->ni_entrylist_len + 1) * sizeof(ni_entry)); - } - - entries->ni_entrylist_val[entries->ni_entrylist_len].id = el.ni_entrylist_val[i].id; - entries->ni_entrylist_val[entries->ni_entrylist_len].names = el.ni_entrylist_val[i].names; - el.ni_entrylist_val[i].names = NULL; - entries->ni_entrylist_len++; - } - - ni_entrylist_free(&el); - regfree(cexp); - free(cexp); - - return NI_OK; -} diff --git a/netinfo.subproj/ni_util.h b/netinfo.subproj/ni_util.h deleted file mode 100644 index f0d599d..0000000 --- a/netinfo.subproj/ni_util.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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@ - */ -/* - * Utility routines for NetInfo - * Copyright (C) 1989 by NeXT, Inc. - */ - -#ifndef _NI_UTIL_H_ -#define _NI_UTIL_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define NI_INDEX_NULL ((ni_index)-1) -#define NI_INIT(objp) bzero((void *)(objp), sizeof(*(objp))) - -ni_name ni_name_dup(ni_name_const); -void ni_name_free(ni_name *); -int ni_name_match(ni_name_const, ni_name_const); - -ni_namelist ni_namelist_dup(const ni_namelist); -void ni_namelist_free(ni_namelist *); -void ni_namelist_insert(ni_namelist *, ni_name_const, ni_index); -void ni_namelist_delete(ni_namelist *, ni_index); -ni_index ni_namelist_match(const ni_namelist, ni_name_const); - -ni_property ni_prop_dup(const ni_property); -void ni_prop_free(ni_property *); - -void ni_proplist_insert(ni_proplist *, const ni_property, ni_index); -void ni_proplist_delete(ni_proplist *, ni_index); -ni_index ni_proplist_match(const ni_proplist, ni_name_const, ni_name_const); -ni_proplist ni_proplist_dup(const ni_proplist); -void ni_proplist_free(ni_proplist *); - -void ni_proplist_list_free(ni_proplist_list *); - -void ni_idlist_insert(ni_idlist *, ni_index, ni_index); -int ni_idlist_delete(ni_idlist *, ni_index); -ni_idlist ni_idlist_dup(const ni_idlist); -void ni_idlist_free(ni_idlist *); - -void ni_entrylist_insert(ni_entrylist *, ni_entry); -void ni_entrylist_delete(ni_entrylist *, ni_index); -void ni_entrylist_free(ni_entrylist *); - -int innetgr(const char *, const char *, const char *, const char *); - -/* - * Search for a directory for all subdirs with key=val, when val is - * a regular expression. Usage: - * status = ni_search(domain, directory, key, val, flags, &list); - * val and flags are passed to regcomp (see regex(3)). - */ -ni_status ni_search(void *, ni_id *, ni_name, ni_name, int, ni_entrylist *); - -/* - * Searches from local domain to root to find the first directory with a - * given pathname. Last argument is a timeout. Usage: - * status = ni_find(&domain, &dir, path, timeout); - */ -ni_status ni_find(void **, ni_id *, ni_name, unsigned int); - -/* - * Parses a NetInfo URL, and returns the domain and directory referenced - * by the URL. Usage: - * status = ni_url(ustring, &domain, &dir); - * - * BNF for NetInfo URLs: - * url ::= "netinfo://" [/[][:[]]] - * hostspec ::= [[[user][:[password]]]@]hostref - * hostref ::= | - * domainspec ::= | - * dirspec ::= | - */ -ni_status ni_url(char *, void **, ni_id *); - -#ifdef __cplusplus -} -#endif - -#endif !_NI_UTIL_H_ - diff --git a/netinfo.subproj/nibind_prot.x b/netinfo.subproj/nibind_prot.x deleted file mode 100644 index 19ef737..0000000 --- a/netinfo.subproj/nibind_prot.x +++ /dev/null @@ -1,116 +0,0 @@ -/* - * 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@ - */ -/* - * NetInfo binder protocol specification - * Copyright (C) 1989 by NeXT, Inc. - */ - -/* Preamble appearing on all generated output */ -#ifndef NOPREAMBLE -%/* -% * Output of the RPC protocol compiler: DO NOT EDIT -% * Copyright (C) 1989 by NeXT, Inc. -% */ -#endif - -#ifdef RPC_HDR -%#ifndef NI_PROG -%#include -%#endif -#else -%#include -#endif - -const NIBIND_MAXREGS = 32; - -struct nibind_addrinfo { - unsigned udp_port; - unsigned tcp_port; -}; - -struct nibind_registration { - ni_name tag; - nibind_addrinfo addrs; -}; - -union nibind_getregister_res switch (ni_status status) { -case NI_OK: - nibind_addrinfo addrs; -default: - void; -}; - -union nibind_listreg_res switch (ni_status status) { -case NI_OK: - nibind_registration regs; -default: - void; -}; - -struct nibind_clone_args { - ni_name tag; - ni_name master_name; - unsigned master_addr; - ni_name master_tag; -}; - -struct nibind_bind_args { - unsigned client_addr; - ni_name client_tag; - ni_name server_tag; -}; - -program NIBIND_PROG { - version NIBIND_VERS { - void - NIBIND_PING(void) = 0; - - ni_status - NIBIND_REGISTER(nibind_registration) = 1; - - ni_status - NIBIND_UNREGISTER(ni_name) = 2; - - nibind_getregister_res - NIBIND_GETREGISTER(ni_name) = 3; - - nibind_listreg_res - NIBIND_LISTREG(void) = 4; - - ni_status - NIBIND_CREATEMASTER(ni_name) = 5; - - ni_status - NIBIND_CREATECLONE(nibind_clone_args) = 6; - - ni_status - NIBIND_DESTROYDOMAIN(ni_name) = 7; - - /* - * Answers only if the given binding is served - */ - void - NIBIND_BIND(nibind_bind_args) = 8; - } = 1; -} = 200100001; diff --git a/netinfo.subproj/sys_interfaces.c b/netinfo.subproj/sys_interfaces.c deleted file mode 100644 index ff78452..0000000 --- a/netinfo.subproj/sys_interfaces.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2001 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@ - */ - -#include -#include -#include -#include -#include "sys_interfaces.h" - -__private_extern__ interface_list_t * -_libinfo_ni_sys_interfaces(void) -{ - interface_list_t *my_interfaces = NULL; - interface_t *iface; - struct ifaddrs *ifa, *p; - - if (getifaddrs(&ifa) < 0) return NULL; - - my_interfaces = (interface_list_t *)malloc(sizeof(interface_list_t)); - my_interfaces->count = 0; - my_interfaces->interface = NULL; - - for (p = ifa; p != NULL; p = p->ifa_next) - { - 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) - { - my_interfaces->interface = (interface_t *)malloc(sizeof(interface_t)); - } - else - { - my_interfaces->interface = (interface_t *)realloc(my_interfaces->interface, my_interfaces->count * sizeof(interface_t)); - } - - iface = &(my_interfaces->interface[my_interfaces->count - 1]); - memset(iface, 0, sizeof(interface_t)); - 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); - } - - freeifaddrs(ifa); - - return my_interfaces; -} - -__private_extern__ void -_libinfo_ni_sys_interfaces_release(interface_list_t *l) -{ - int i; - - if (l == NULL) return; - - for (i = 0; i < l->count; i++) - { - if (l->interface[i].name != NULL) free(l->interface[i].name); - } - - free(l->interface); - free(l); -} - -__private_extern__ int -_libinfo_ni_sys_is_my_address(interface_list_t *l, struct in_addr *a) -{ - int i; - - if (l == NULL) return 0; - - for (i = 0; i < l->count; i++) - { - if (a->s_addr == l->interface[i].addr.s_addr) return 1; - } - return 0; -} - -__private_extern__ int -_libinfo_ni_sys_is_my_network(interface_list_t *l, struct in_addr *a) -{ - int i; - - if (l == NULL) return 0; - - for (i = 0; i < l->count; i++) - { - if ((a->s_addr & l->interface[i].mask.s_addr) == - l->interface[i].netaddr.s_addr) return 1; - - } - return 0; -} diff --git a/netinfo.subproj/sys_interfaces.h b/netinfo.subproj/sys_interfaces.h deleted file mode 100644 index 8064075..0000000 --- a/netinfo.subproj/sys_interfaces.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2001 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@ - */ - -#ifndef __SYS_INTERFACES__ -#define __SYS_INTERFACES__ - -#include -#include -#include -#include - -typedef struct -{ - char *name; - 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 *_libinfo_ni_sys_interfaces(void); -void _libinfo_ni_sys_interfaces_release(interface_list_t *l); -int _libinfo_ni_sys_is_my_address(interface_list_t *l, struct in_addr *a); -int _libinfo_ni_sys_is_my_network(interface_list_t *l, struct in_addr *a); - -#endif /* __SYS_INTERFACES__ */ diff --git a/nis.subproj/Makefile b/nis.subproj/Makefile index 8792e4b..542d835 100644 --- a/nis.subproj/Makefile +++ b/nis.subproj/Makefile @@ -28,7 +28,7 @@ CFILES = getdomainname.c getnetgrent.c innetgr.c setdomainname.c\ 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\ - Makefile.postamble + yp.8 Makefile.postamble MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles diff --git a/nis.subproj/Makefile.postamble b/nis.subproj/Makefile.postamble index e8f240c..019c45f 100644 --- a/nis.subproj/Makefile.postamble +++ b/nis.subproj/Makefile.postamble @@ -112,9 +112,11 @@ MAN3DIR=/usr/share/man/man3 MAN5DIR=/usr/share/man/man5 +MAN8DIR=/usr/share/man/man8 install-nis-man: install -m 755 -o root -g wheel -d $(DSTROOT)$(MAN3DIR) + install -m 755 -o root -g wheel -d $(DSTROOT)$(MAN8DIR) install -m 644 -o root -g wheel -c yp_all.3 "$(DSTROOT)$(MAN3DIR)" install -m 644 -o root -g wheel -c yp_bind.3 "$(DSTROOT)$(MAN3DIR)" install -m 644 -o root -g wheel -c yp_first.3 "$(DSTROOT)$(MAN3DIR)" @@ -127,3 +129,5 @@ install-nis-man: install -m 644 -o root -g wheel -c ypclnt.3 "$(DSTROOT)$(MAN3DIR)" install -m 644 -o root -g wheel -c yperr_string.3 "$(DSTROOT)$(MAN3DIR)" install -m 644 -o root -g wheel -c ypprot_err.3 "$(DSTROOT)$(MAN3DIR)" + install -m 644 -o root -g wheel -c yp.8 "$(DSTROOT)$(MAN8DIR)" + diff --git a/nis.subproj/Makefile.preamble b/nis.subproj/Makefile.preamble index a5e57b4..a0abefb 100644 --- a/nis.subproj/Makefile.preamble +++ b/nis.subproj/Makefile.preamble @@ -1,6 +1,8 @@ AFTER_POSTINSTALL += install-nis-man PUBLIC_HEADER_DIR_SUFFIX = /rpcsvc +OTHER_CFLAGS += -D__DARWIN_NON_CANCELABLE=1 + # for building 64-bit # Libinfo need to build with gcc-3.5 and 3-way fat NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER) diff --git a/nis.subproj/xdr_ypmaplist.c b/nis.subproj/xdr_ypmaplist.c index 137ea49..14a3544 100644 --- a/nis.subproj/xdr_ypmaplist.c +++ b/nis.subproj/xdr_ypmaplist.c @@ -77,5 +77,5 @@ struct ypmaplist *objp; return FALSE; } return xdr_pointer(xdrs, (caddr_t *)&objp->next, - sizeof(struct ypmaplist), xdr_ypmaplist); + sizeof(struct ypmaplist), (xdrproc_t)xdr_ypmaplist); } diff --git a/nis.subproj/xdr_ypresp_maplist.c b/nis.subproj/xdr_ypresp_maplist.c index cce1529..db238de 100644 --- a/nis.subproj/xdr_ypresp_maplist.c +++ b/nis.subproj/xdr_ypresp_maplist.c @@ -77,5 +77,5 @@ struct ypresp_maplist *objp; return FALSE; } return xdr_pointer(xdrs, (caddr_t *)&objp->maps, - sizeof(struct ypmaplist), xdr_ypmaplist); + sizeof(struct ypmaplist), (xdrproc_t)xdr_ypmaplist); } diff --git a/nis.subproj/yp.8 b/nis.subproj/yp.8 new file mode 100644 index 0000000..b903753 --- /dev/null +++ b/nis.subproj/yp.8 @@ -0,0 +1,566 @@ +.\" Copyright (c) 1992/3 Theo de Raadt +.\" 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. 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. +.\" +.\" from: @(#)yp.8 1.0 (deraadt) 4/26/93 +.\" $FreeBSD: src/share/man/man8/yp.8,v 1.36 2005/01/21 08:36:40 ru Exp $ +.\" +.Dd April 5, 1993 +.Dt YP 8 +.Os +.Sh NAME +.Nm yp +.Nd description of the YP/NIS system +.Sh SYNOPSIS +.Nm +.Sh DESCRIPTION +The +.Nm YP +subsystem allows network management of passwd, group, netgroup, hosts, +services, rpc, bootparams and ethers file +entries through the functions +.Xr getpwent 3 , +.Xr getgrent 3 , +.Xr getnetgrent 3 , +.Xr gethostent 3 , +.Xr getnetent 3 , +.Xr getrpcent 3 , +and +.Xr ethers 3 . +The +.Xr bootparamd 8 +daemon makes direct +.Tn NIS +library calls since there are no +functions in the standard C library for reading bootparams. +.Tn NIS +support is enabled in +.Xr nsswitch.conf 5 . +.Pp +The +.Nm YP +subsystem is started automatically in +.Pa /etc/rc +if it has been initialized in +.Pa /etc/rc.conf +and if the directory +.Pa /var/yp +exists (which it does in the default distribution). +The default +.Tn NIS +domain must also be set with the +.Xr domainname 1 +command, which will happen automatically at system startup if it is +specified in +.Pa /etc/rc.conf . +.Pp +.Tn NIS +is an +.Tn RPC Ns -based +client/server system that allows a group of +machines within an +.Tn NIS +domain to share a common set of configuration files. +This permits a system +administrator to set up +.Tn NIS +client systems with only minimal configuration +data and add, remove or modify configuration data from a single location. +.Pp +The canonical copies of all +.Tn NIS +information are stored on a single machine +called the +.Tn NIS +.Em "master server" . +The databases used to store the information are called +.Tn NIS +.Em maps . +In +.Fx , +these maps are stored in +.Pa /var/yp/ Ns Aq Ar domainname +where +.Aq Ar domainname +is the name of the +.Tn NIS +domain being served. +A single +.Tn NIS +server can +support several domains at once, therefore it is possible to have several +such directories, one for each supported domain. +Each domain will have +its own independent set of maps. +.Pp +In +.Fx , +the +.Tn NIS +maps are Berkeley DB hashed database files (the +same format used for the +.Xr passwd 5 +database files). +Other operating systems that support +.Tn NIS +use old-style +.Nm ndbm +databases instead (largely because Sun Microsystems originally based +their +.Tn NIS +implementation on +.Nm ndbm , +and other vendors have simply licensed +Sun's code rather than design their own implementation with a different +database format). +On these systems, the databases are generally split +into +.Pa .dir +and +.Pa .pag +files which the +.Nm ndbm +code uses to hold separate parts of the hash +database. +The Berkeley DB hash method instead uses a single file for +both pieces of information. +This means that while you may have +.Pa passwd.byname.dir +and +.Pa passwd.byname.pag +files on other operating systems (both of which are really parts of the +same map), +.Fx +will have only one file called +.Pa passwd.byname . +The difference in format is not significant: only the +.Tn NIS +server, +.Xr ypserv 8 , +and related tools need to know the database format of the +.Tn NIS +maps. +Client +.Tn NIS +systems receive all +.Tn NIS +data in +.Tn ASCII +form. +.Pp +There are three main types of +.Tn NIS +systems: +.Bl -enum +.It +.Tn NIS +clients, +which query +.Tn NIS +servers for information. +.It +.Tn NIS +master servers, +which maintain the canonical copies of all +.Tn NIS +maps. +.It +.Tn NIS +slave servers, +which maintain backup copies of +.Tn NIS +maps that are periodically +updated by the master. +.El +.Pp +A +.Tn NIS +client establishes what is called a +.Em binding +to a particular +.Tn NIS +server using the +.Xr ypbind 8 +daemon. +The +.Xr ypbind 8 +utility checks the system's default domain (as set by the +.Xr domainname 1 +command) and begins broadcasting +.Tn RPC +requests on the local network. +These requests specify the name of the domain for which +.Xr ypbind 8 +is attempting to establish a binding. +If a server that has been +configured to serve the requested domain receives one of the broadcasts, +it will respond to +.Xr ypbind 8 , +which will record the server's address. +If there are several servers +available (a master and several slaves, for example), +.Xr ypbind 8 +will use the address of the first one to respond. +From that point +on, the client system will direct all of its +.Tn NIS +requests to that server. +The +.Xr ypbind 8 +utility will occasionally +.Dq ping +the server to make sure it is still up +and running. +If it fails to receive a reply to one of its pings +within a reasonable amount of time, +.Xr ypbind 8 +will mark the domain as unbound and begin broadcasting again in the +hopes of locating another server. +.Pp +.Tn NIS +master and slave servers handle all +.Tn NIS +requests with the +.Xr ypserv 8 +daemon. +The +.Xr ypserv 8 +utility is responsible for receiving incoming requests from +.Tn NIS +clients, +translating the requested domain and map name to a path to the +corresponding database file and transmitting data from the database +back to the client. +There is a specific set of requests that +.Xr ypserv 8 +is designed to handle, most of which are implemented as functions +within the standard C library: +.Bl -tag -width ".Fn yp_master" +.It Fn yp_order +check the creation date of a particular map +.It Fn yp_master +obtain the name of the +.Tn NIS +master server for a given +map/domain +.It Fn yp_match +lookup the data corresponding to a given in key in a particular +map/domain +.It Fn yp_first +obtain the first key/data pair in a particular map/domain +.It Fn yp_next +pass +.Xr ypserv 8 +a key in a particular map/domain and have it return the +key/data pair immediately following it (the functions +.Fn yp_first +and +.Fn yp_next +can be used to do a sequential search of an +.Tn NIS +map) +.It Fn yp_all +retrieve the entire contents of a map +.El +.Pp +There are a few other requests which +.Xr ypserv 8 +is capable of handling (i.e., acknowledge whether or not you can handle +a particular domain +.Pq Dv YPPROC_DOMAIN , +or acknowledge only if you can handle the domain and be silent otherwise +.Pq Dv YPPROC_DOMAIN_NONACK ) +but +these requests are usually generated only by +.Xr ypbind 8 +and are not meant to be used by standard utilities. +.Pp +On networks with a large number of hosts, it is often a good idea to +use a master server and several slaves rather than just a single master +server. +A slave server provides the exact same information as a master +server: whenever the maps on the master server are updated, the new +data should be propagated to the slave systems using the +.Xr yppush 8 +command. +The +.Tn NIS +.Pa Makefile +.Pq Pa /var/yp/Makefile +will do this automatically if the administrator comments out the +line which says +.Dq Li NOPUSH=true +.Va ( NOPUSH +is set to true by default because the default configuration is +for a small network with only one +.Tn NIS +server). +The +.Xr yppush 8 +command will initiate a transaction between the master and slave +during which the slave will transfer the specified maps from the +master server using +.Xr ypxfr 8 . +(The slave server calls +.Xr ypxfr 8 +automatically from within +.Xr ypserv 8 ; +therefore it is not usually necessary for the administrator +to use it directly. +It can be run manually if +desired, however.) +Maintaining +slave servers helps improve +.Tn NIS +performance on large +networks by: +.Bl -bullet +.It +Providing backup services in the event that the +.Tn NIS +master crashes +or becomes unreachable +.It +Spreading the client load out over several machines instead of +causing the master to become overloaded +.It +Allowing a single +.Tn NIS +domain to extend beyond +a local network (the +.Xr ypbind 8 +daemon might not be able to locate a server automatically if it resides on +a network outside the reach of its broadcasts. +It is possible to force +.Xr ypbind 8 +to bind to a particular server with +.Xr ypset 8 +but this is sometimes inconvenient. +This problem can be avoided simply by +placing a slave server on the local network.) +.El +.Pp +The +.Fx +.Xr ypserv 8 +is specially designed to provide enhanced security (compared to +other +.Tn NIS +implementations) when used exclusively with +.Fx +client +systems. +The +.Fx +password database system (which is derived directly +from +.Bx 4.4 ) +includes support for +.Em "shadow passwords" . +The standard password database does not contain users' encrypted +passwords: these are instead stored (along with other information) +in a separate database which is accessible only by the super-user. +If the encrypted password database were made available as an +.Tn NIS +map, this security feature would be totally disabled, since any user +is allowed to retrieve +.Tn NIS +data. +.Pp +To help prevent this, +.Fx Ns 's +.Tn NIS +server handles the shadow password maps +.Pa ( master.passwd.byname +and +.Pa master.passwd.byuid ) +in a special way: the server will only provide access to these +maps in response to requests that originate on privileged ports. +Since only the super-user is allowed to bind to a privileged port, +the server assumes that all such requests come from privileged +users. +All other requests are denied: requests from non-privileged +ports will receive only an error code from the server. +Additionally, +.Fx Ns 's +.Xr ypserv 8 +includes support for +.An Wietse Venema Ns 's +tcp wrapper package; with tcp +wrapper support enabled, the administrator can configure +.Xr ypserv 8 +to respond only to selected client machines. +.Pp +While these enhancements provide better security than stock +.Tn NIS , +they are by no means 100% effective. +It is still possible for +someone with access to your network to spoof the server into disclosing +the shadow password maps. +.Pp +On the client side, +.Fx Ns 's +.Xr getpwent 3 +functions will automatically search for the +.Pa master.passwd +maps and use them if they exist. +If they do, they will be used, and +all fields in these special maps (class, password age and account +expiration) will be decoded. +If they are not found, the standard +.Pa passwd +maps will be used instead. +.Sh COMPATIBILITY +When using a +.No non- Ns Fx +.Tn NIS +server for +.Xr passwd 5 +files, it is unlikely that the default MD5-based format that +.Fx +uses for passwords will be accepted by it. +If this is the case, the value of the +.Va passwd_format +setting in +.Xr login.conf 5 +should be changed to +.Qq Li des +for compatibility. +.Pp +Some systems, such as +.Tn SunOS +4.x, need +.Tn NIS +to be running in order +for their hostname resolution functions +.Fn ( gethostbyname , +.Fn gethostbyaddr , +etc.) to work properly. +On these systems, +.Xr ypserv 8 +performs +.Tn DNS +lookups when asked to return information about +a host that does not exist in its +.Pa hosts.byname +or +.Pa hosts.byaddr +maps. +.Fx Ns 's +resolver uses +.Tn DNS +by default (it can be made to use +.Tn NIS , +if desired), therefore its +.Tn NIS +server does not do +.Tn DNS +lookups +by default. +However, +.Xr ypserv 8 +can be made to perform +.Tn DNS +lookups if it is started with a special +flag. +It can also be made to register itself as an +.Tn NIS +v1 server +in order to placate certain systems that insist on the presence of +a v1 server +.No ( Fx +uses only +.Tn NIS +v2, but many other systems, +including +.Tn SunOS +4.x, search for both a v1 and v2 server when binding). +.Fx Ns 's +.Xr ypserv 8 +does not actually handle +.Tn NIS +v1 requests, but this +.Dq "kludge mode" +is useful for silencing stubborn systems that search for both +a v1 and v2 server. +.Pp +(Please see the +.Xr ypserv 8 +manual page for a detailed description of these special features +and flags.) +.Sh HISTORY +The +.Nm YP +subsystem was written from the ground up by +.An Theo de Raadt +to be compatible to Sun's implementation. +Bug fixes, improvements +and +.Tn NIS +server support were later added by +.An Bill Paul . +The server-side code was originally written by +.An Peter Eriksson +and +.An Tobias Reber +and is subject to the GNU Public License. +No Sun code was +referenced. +.Sh BUGS +While +.Fx +now has both +.Tn NIS +client and server capabilities, it does not yet have support for +.Xr ypupdated 8 +or the +.Fn yp_update +function. +Both of these require secure +.Tn RPC , +which +.Fx +does not +support yet either. +.Pp +The +.Xr getservent 3 +and +.Xr getprotoent 3 +functions do not yet have +.Tn NIS +support. +Fortunately, these files +do not need to be updated that often. +.Pp +Many more manual pages should be written, especially +.Xr ypclnt 3 . +For the time being, seek out a local Sun machine and read the +manuals for there. +.Pp +Neither Sun nor this author have found a clean way to handle +the problems that occur when ypbind cannot find its server +upon bootup. diff --git a/nis.subproj/yp_all.c b/nis.subproj/yp_all.c index 55778c8..e08a981 100644 --- a/nis.subproj/yp_all.c +++ b/nis.subproj/yp_all.c @@ -89,12 +89,12 @@ u_long *objp; memset(&out, 0, sizeof out); while(1) { if( !xdr_ypresp_all(xdrs, &out)) { - xdr_free(xdr_ypresp_all, (char *)&out); + xdr_free((xdrproc_t)xdr_ypresp_all, (char *)&out); *objp = (u_long)YP_YPERR; return FALSE; } if(out.more == 0) { - xdr_free(xdr_ypresp_all, (char *)&out); + xdr_free((xdrproc_t)xdr_ypresp_all, (char *)&out); return FALSE; } status = out.ypresp_all_u.val.stat; @@ -118,7 +118,7 @@ u_long *objp; free(key); key = NULL; } - xdr_free(xdr_ypresp_all, (char *)&out); + xdr_free((xdrproc_t)xdr_ypresp_all, (char *)&out); if (key == NULL || val == NULL) return FALSE; @@ -133,10 +133,10 @@ u_long *objp; return TRUE; break; case YP_NOMORE: - xdr_free(xdr_ypresp_all, (char *)&out); + xdr_free((xdrproc_t)xdr_ypresp_all, (char *)&out); return TRUE; default: - xdr_free(xdr_ypresp_all, (char *)&out); + xdr_free((xdrproc_t)xdr_ypresp_all, (char *)&out); *objp = status; return TRUE; } @@ -183,7 +183,7 @@ yp_all(indomain, inmap, incallback) ypresp_data = (void *) incallback->data; (void) clnt_call(clnt, YPPROC_ALL, - xdr_ypreq_nokey, &yprnk, xdr_ypresp_all_seq, &status, tv); + (xdrproc_t)xdr_ypreq_nokey, &yprnk, (xdrproc_t)xdr_ypresp_all_seq, &status, tv); clnt_destroy(clnt); if(status != YP_FALSE) r = ypprot_err(status); diff --git a/nis.subproj/yp_bind.c b/nis.subproj/yp_bind.c index a8b9c9d..14b20bb 100644 --- a/nis.subproj/yp_bind.c +++ b/nis.subproj/yp_bind.c @@ -71,8 +71,12 @@ static char *rcsid = "$OpenBSD: yp_bind.c,v 1.9 1997/04/29 21:25:20 deraadt Exp #include #include #include +#include +#include #include "ypinternal.h" +extern int notify_register_plain(char *, int *); + struct dom_binding *_ypbindlist = NULL; char _yp_domain[MAXHOSTNAMELEN] = { '\0' }; @@ -84,7 +88,6 @@ _yp_dobind(dom, ypdb) struct dom_binding **ypdb; { static int pid = -1; - char path[MAXPATHLEN]; struct dom_binding *ysd, *ysd2; struct ypbind_resp ypbr; struct timeval tv; @@ -92,141 +95,141 @@ _yp_dobind(dom, ypdb) struct ypbind_binding *bn; int clnt_sock, fd, gpid; CLIENT *client; - int new = 0, r; + int new = 0, r, proto; int count = 0; u_short port; + int status, notify_token; + uint64_t abort; + char *notify_name; /* * test if YP is running or not */ - if ((fd = open(YPBINDLOCK, O_RDONLY)) == -1) - return YPERR_YPBIND; - if (!(flock(fd, LOCK_EX | LOCK_NB) == -1 && errno == EWOULDBLOCK)) { - (void)close(fd); + if ((fd = open(YPBINDLOCK, O_RDONLY)) == -1) return YPERR_YPBIND; + + if (!((flock(fd, LOCK_EX | LOCK_NB) == -1) && (errno == EWOULDBLOCK))) + { + close(fd); return YPERR_YPBIND; } - (void)close(fd); + + close(fd); gpid = getpid(); - if (!(pid == -1 || pid == gpid)) { + if (!((pid == -1) || (pid == gpid))) + { ysd = _ypbindlist; - while (ysd) { - if (ysd->dom_client) - clnt_destroy(ysd->dom_client); + while (ysd) + { + if (ysd->dom_client) clnt_destroy(ysd->dom_client); ysd2 = ysd->dom_pnext; free(ysd); ysd = ysd2; } + _ypbindlist = NULL; } + pid = gpid; - if (ypdb != NULL) - *ypdb = NULL; + if (ypdb != NULL) *ypdb = NULL; - if (dom == NULL || strlen(dom) == 0) - return YPERR_BADARGS; + if ((dom == NULL) || (strlen(dom) == 0)) return YPERR_BADARGS; for (ysd = _ypbindlist; ysd; ysd = ysd->dom_pnext) - if (strcmp(dom, ysd->dom_domain) == 0) - break; - if (ysd == NULL) { - if ((ysd = malloc(sizeof *ysd)) == NULL) - return YPERR_YPERR; - (void)memset(ysd, 0, sizeof *ysd); + { + if (strcmp(dom, ysd->dom_domain) == 0) break; + } + + if (ysd == NULL) + { + ysd = calloc(1, sizeof(struct dom_binding)); + if (ysd == NULL) return YPERR_YPERR; ysd->dom_socket = -1; ysd->dom_vers = 0; new = 1; } -again: - if (ysd->dom_vers == 0) { - (void) snprintf(path, sizeof(path), "%s/%s.%d", - BINDINGDIR, dom, 2); - if ((fd = open(path, O_RDONLY)) == -1) { - /* - * no binding file, YP is dead, or not yet fully - * alive. - */ - goto trynet; - } - if (flock(fd, LOCK_EX | LOCK_NB) == -1 && - errno == EWOULDBLOCK) { - struct iovec iov[2]; - u_short ypb_port; - /* - * we fetch the ypbind port number, but do - * nothing with it. - */ - iov[0].iov_base = (caddr_t) &ypb_port; - iov[0].iov_len = sizeof ypb_port; - iov[1].iov_base = (caddr_t) &ypbr; - iov[1].iov_len = sizeof ypbr; - - r = readv(fd, iov, 2); - if (r != iov[0].iov_len + iov[1].iov_len) { - (void)close(fd); - ysd->dom_vers = -1; - goto again; - } - (void)close(fd); - goto gotdata; - } else { - /* no lock on binding file, YP is dead. */ - (void)close(fd); - if (new) - free(ysd); + /* + * Get notification token + * we use a self-notification token to allow a caller + * to signal the thread doing this bind call to quit. + */ + notify_name = NULL; + notify_token = -1; + + asprintf(¬ify_name, "self.thread.%lu", (unsigned long)pthread_self()); + if (notify_name != NULL) + { + status = notify_register_plain(notify_name, ¬ify_token); + free(notify_name); + } + +again: + if (notify_token != -1) + { + abort = 0; + status = notify_get_state(notify_token, &abort); + if (abort == ThreadStateExitRequested) + { + if (new) free(ysd); + notify_cancel(notify_token); return YPERR_YPBIND; } } -trynet: - if (ysd->dom_vers == -1 || ysd->dom_vers == 0) { - (void)memset(&clnt_sin, 0, sizeof clnt_sin); + + proto = YP_BIND_UDP; + if (ysd->dom_vers == YP_BIND_TCP) proto = YP_BIND_TCP; + + if ((ysd->dom_vers == 0) || (ysd->dom_vers == YP_BIND_UDP) || (ysd->dom_vers == YP_BIND_TCP)) + { + memset(&clnt_sin, 0, sizeof clnt_sin); clnt_sin.sin_len = sizeof(struct sockaddr_in); clnt_sin.sin_family = AF_INET; clnt_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); clnt_sock = RPC_ANYSOCK; - client = clnttcp_create(&clnt_sin, YPBINDPROG, YPBINDVERS, - &clnt_sock, 0, 0); - if (client == NULL) { + client = clnttcp_create(&clnt_sin, YPBINDPROG, YPBINDVERS, &clnt_sock, 0, 0); + if (client == NULL) + { clnt_pcreateerror("clnttcp_create"); - if (new) - free(ysd); + if (new) free(ysd); + if (notify_token != -1) notify_cancel(notify_token); return YPERR_YPBIND; } - if (ntohs(clnt_sin.sin_port) >= IPPORT_RESERVED || - ntohs(clnt_sin.sin_port) == 20) { + + if ((ntohs(clnt_sin.sin_port) >= IPPORT_RESERVED) || (ntohs(clnt_sin.sin_port) == 20)) + { /* * YP was not running, but someone has registered * ypbind with portmap -- this simply means YP is * not running. */ clnt_destroy(client); - if (new) - free(ysd); + if (new) free(ysd); + if (notify_token != -1) notify_cancel(notify_token); return YPERR_YPBIND; } + tv.tv_sec = _yplib_timeout; tv.tv_usec = 0; - r = clnt_call(client, YPBINDPROC_DOMAIN, xdr_domainname, - &dom, xdr_ypbind_resp, &ypbr, tv); - if (r != RPC_SUCCESS) { - if (new == 0 || count) - fprintf(stderr, - "YP server for domain %s not responding, still trying\n", - dom); + + r = clnt_call(client, YPBINDPROC_DOMAIN, (xdrproc_t)xdr_domainname, &dom, (xdrproc_t)xdr_ypbind_resp, &ypbr, tv); + if (r != RPC_SUCCESS) + { + if (new == 0 || count) fprintf(stderr, "YP server for domain %s not responding, still trying\n", dom); count++; clnt_destroy(client); - ysd->dom_vers = -1; + ysd->dom_vers = proto; goto again; } + clnt_destroy(client); -gotdata: + bn = &ypbr.ypbind_resp_u.ypbind_bindinfo; memcpy(&port, &bn->ypbind_binding_port, sizeof port); - if (ntohs(port) >= IPPORT_RESERVED || - ntohs(port) == 20) { + if ((ntohs(port) >= IPPORT_RESERVED) || (ntohs(port) == 20)) + { /* * This is bogus -- the ypbind wants me to * communicate to an insecure ypserv. We are @@ -234,46 +237,51 @@ gotdata: * but for now we'll simply ignore it; real YP * is obviously not running. */ - if (new) - free(ysd); + if (new) free(ysd); + if (notify_token != -1) notify_cancel(notify_token); return YPERR_YPBIND; } - (void)memset(&ysd->dom_server_addr, 0, - sizeof ysd->dom_server_addr); + + memset(&ysd->dom_server_addr, 0, sizeof ysd->dom_server_addr); ysd->dom_server_addr.sin_len = sizeof(struct sockaddr_in); ysd->dom_server_addr.sin_family = AF_INET; - memcpy(&ysd->dom_server_addr.sin_port, - &bn->ypbind_binding_port, - sizeof(ysd->dom_server_addr.sin_port)); - memcpy(&ysd->dom_server_addr.sin_addr.s_addr, - &bn->ypbind_binding_addr, - sizeof(ysd->dom_server_addr.sin_addr.s_addr)); + memcpy(&ysd->dom_server_addr.sin_port, &bn->ypbind_binding_port, sizeof(ysd->dom_server_addr.sin_port)); + memcpy(&ysd->dom_server_addr.sin_addr.s_addr, &bn->ypbind_binding_addr, sizeof(ysd->dom_server_addr.sin_addr.s_addr)); ysd->dom_server_port = ysd->dom_server_addr.sin_port; ysd->dom_vers = YPVERS; - (void)strncpy(ysd->dom_domain, dom, sizeof ysd->dom_domain-1); + strncpy(ysd->dom_domain, dom, sizeof ysd->dom_domain-1); ysd->dom_domain[sizeof ysd->dom_domain-1] = '\0'; } + tv.tv_sec = _yplib_timeout / 2; tv.tv_usec = 0; - if (ysd->dom_client) - clnt_destroy(ysd->dom_client); + + if (ysd->dom_client) clnt_destroy(ysd->dom_client); ysd->dom_socket = RPC_ANYSOCK; - ysd->dom_client = clntudp_create(&ysd->dom_server_addr, - YPPROG, YPVERS, tv, &ysd->dom_socket); - if (ysd->dom_client == NULL) { - clnt_pcreateerror("clntudp_create"); - ysd->dom_vers = -1; + + if (proto == YP_BIND_UDP) ysd->dom_client = clntudp_create(&ysd->dom_server_addr, YPPROG, YPVERS, tv, &ysd->dom_socket); + else ysd->dom_client = clnttcp_create(&ysd->dom_server_addr, YPPROG, YPVERS, &ysd->dom_socket, 0, 0); + + if (ysd->dom_client == NULL) + { + if (proto == YP_BIND_UDP) clnt_pcreateerror("clntudp_create"); + else clnt_pcreateerror("clnttcp_create"); + ysd->dom_vers = proto; goto again; } + + if (notify_token != -1) notify_cancel(notify_token); + if (fcntl(ysd->dom_socket, F_SETFD, 1) == -1) perror("fcntl: F_SETFD"); - if (new) { + if (new != 0) + { ysd->dom_pnext = _ypbindlist; _ypbindlist = ysd; } - if (ypdb != NULL) - *ypdb = ysd; + + if (ypdb != NULL) *ypdb = ysd; return 0; } diff --git a/nis.subproj/yp_first.c b/nis.subproj/yp_first.c index 5bdcf11..446d4b6 100644 --- a/nis.subproj/yp_first.c +++ b/nis.subproj/yp_first.c @@ -86,6 +86,7 @@ yp_first(indomain, inmap, outkey, outkeylen, outval, outvallen) struct dom_binding *ysd; struct timeval tv; int tries = 0, r; + static int proto = YP_BIND_UDP; if (indomain == NULL || *indomain == '\0' || strlen(indomain) > YPMAXDOMAIN || inmap == NULL || @@ -106,14 +107,18 @@ again: yprnk.map = (char *)inmap; (void)memset(&yprkv, 0, sizeof yprkv); - r = clnt_call(ysd->dom_client, YPPROC_FIRST, - xdr_ypreq_nokey, &yprnk, xdr_ypresp_key_val, &yprkv, tv); - if (r != RPC_SUCCESS) { - if (tries++) - clnt_perror(ysd->dom_client, "yp_first: clnt_call"); - ysd->dom_vers = -1; + r = clnt_call(ysd->dom_client, YPPROC_FIRST, (xdrproc_t)xdr_ypreq_nokey, &yprnk, (xdrproc_t)xdr_ypresp_key_val, &yprkv, tv); + if (r != RPC_SUCCESS) + { + if (tries++) clnt_perror(ysd->dom_client, "yp_first: clnt_call"); + + if (proto == YP_BIND_UDP) proto = YP_BIND_TCP; + else proto = YP_BIND_UDP; + ysd->dom_vers = proto; + goto again; } + if (!(r = ypprot_err(yprkv.stat))) { *outkeylen = yprkv.key.keydat_len; if ((*outkey = malloc(*outkeylen + 1)) == NULL) @@ -130,7 +135,7 @@ again: (*outval)[*outvallen] = '\0'; } } - xdr_free(xdr_ypresp_key_val, (char *) &yprkv); + xdr_free((xdrproc_t)xdr_ypresp_key_val, (char *) &yprkv); _yp_unbind(ysd); return r; } diff --git a/nis.subproj/yp_maplist.c b/nis.subproj/yp_maplist.c index e795ad2..ef7894b 100644 --- a/nis.subproj/yp_maplist.c +++ b/nis.subproj/yp_maplist.c @@ -81,6 +81,7 @@ yp_maplist(indomain, outmaplist) struct ypresp_maplist ypml; struct timeval tv; int tries = 0, r; + static int proto = YP_BIND_UDP; again: if (_yp_dobind(indomain, &ysd) != 0) @@ -91,14 +92,18 @@ again: memset(&ypml, 0, sizeof ypml); - r = clnt_call(ysd->dom_client, YPPROC_MAPLIST, - xdr_domainname, &indomain, xdr_ypresp_maplist, &ypml, tv); - if (r != RPC_SUCCESS) { - if (tries++) - clnt_perror(ysd->dom_client, "yp_maplist: clnt_call"); - ysd->dom_vers = -1; + r = clnt_call(ysd->dom_client, YPPROC_MAPLIST, (xdrproc_t)xdr_domainname, &indomain, (xdrproc_t)xdr_ypresp_maplist, &ypml, tv); + if (r != RPC_SUCCESS) + { + if (tries++) clnt_perror(ysd->dom_client, "yp_maplist: clnt_call"); + + if (proto == YP_BIND_UDP) proto = YP_BIND_TCP; + else proto = YP_BIND_UDP; + ysd->dom_vers = proto; + goto again; } + *outmaplist = ypml.maps; /* NO: xdr_free(xdr_ypresp_maplist, &ypml); */ _yp_unbind(ysd); diff --git a/nis.subproj/yp_master.c b/nis.subproj/yp_master.c index b3a0795..1e13be3 100644 --- a/nis.subproj/yp_master.c +++ b/nis.subproj/yp_master.c @@ -83,6 +83,7 @@ yp_master(indomain, inmap, outname) struct ypreq_nokey yprnk; struct timeval tv; int tries = 0, r; + static int proto = YP_BIND_UDP; if (indomain == NULL || *indomain == '\0' || strlen(indomain) > YPMAXDOMAIN || inmap == NULL || @@ -101,19 +102,23 @@ again: (void)memset(&yprm, 0, sizeof yprm); - r = clnt_call(ysd->dom_client, YPPROC_MASTER, - xdr_ypreq_nokey, &yprnk, xdr_ypresp_master, &yprm, tv); - if (r != RPC_SUCCESS) { - if (tries++) - clnt_perror(ysd->dom_client, "yp_master: clnt_call"); - ysd->dom_vers = -1; + r = clnt_call(ysd->dom_client, YPPROC_MASTER, (xdrproc_t)xdr_ypreq_nokey, &yprnk, (xdrproc_t)xdr_ypresp_master, &yprm, tv); + if (r != RPC_SUCCESS) + { + if (tries++) clnt_perror(ysd->dom_client, "yp_master: clnt_call"); + + if (proto == YP_BIND_UDP) proto = YP_BIND_TCP; + else proto = YP_BIND_UDP; + ysd->dom_vers = proto; + goto again; } + if (!(r = ypprot_err(yprm.stat))) { if ((*outname = strdup(yprm.peer)) == NULL) r = YPERR_RESRC; } - xdr_free(xdr_ypresp_master, (char *) &yprm); + xdr_free((xdrproc_t)xdr_ypresp_master, (char *) &yprm); _yp_unbind(ysd); return r; } diff --git a/nis.subproj/yp_order.c b/nis.subproj/yp_order.c index 44b7a7c..72946d7 100644 --- a/nis.subproj/yp_order.c +++ b/nis.subproj/yp_order.c @@ -82,7 +82,8 @@ yp_order(indomain, inmap, outorder) struct ypresp_order ypro; struct ypreq_nokey yprnk; struct timeval tv; - int r = 0; + int tries = 0, r = 0; + static int proto = YP_BIND_UDP; if (indomain == NULL || *indomain == '\0' || strlen(indomain) > YPMAXDOMAIN || inmap == NULL || @@ -102,7 +103,7 @@ again: (void)memset(&ypro, 0, sizeof ypro); r = clnt_call(ysd->dom_client, YPPROC_ORDER, - xdr_ypreq_nokey, &yprnk, xdr_ypresp_order, &ypro, tv); + (xdrproc_t)xdr_ypreq_nokey, &yprnk, (xdrproc_t)xdr_ypresp_order, &ypro, tv); /* * XXX * NIS+ YP emulation package does not impliment YPPROC_ORDER @@ -111,13 +112,21 @@ again: r = YPERR_YPERR; goto bail; } - if (r != RPC_SUCCESS) { - clnt_perror(ysd->dom_client, "yp_order: clnt_call"); - ysd->dom_vers = -1; + + if (r != RPC_SUCCESS) + { + /* call failed - switch protocols and try again */ + if (tries++) clnt_perror(ysd->dom_client, "yp_order: clnt_call"); + + if (proto == YP_BIND_UDP) proto = YP_BIND_TCP; + else proto = YP_BIND_UDP; + ysd->dom_vers = proto; + goto again; } + *outorder = ypro.ordernum; - xdr_free(xdr_ypresp_order, (char *) &ypro); + xdr_free((xdrproc_t)xdr_ypresp_order, (char *) &ypro); r = ypprot_err(ypro.stat); bail: _yp_unbind(ysd); diff --git a/nis.subproj/ypclnt.3 b/nis.subproj/ypclnt.3 index 0d8951e..669104a 100644 --- a/nis.subproj/ypclnt.3 +++ b/nis.subproj/ypclnt.3 @@ -51,7 +51,7 @@ .Nm ypprot_err .Nd Interface to the YP subsystem .Sh SYNOPSIS -.Fd #include +.Fd #include .Fd #include .Fd #include .Ft int @@ -339,4 +339,4 @@ The client cannot communicate with the YP server process. .Xr ypbind 8 , .Xr ypserv 8 .Sh AUTHOR -Theo De Raadt +Theo De Raadt \ No newline at end of file diff --git a/nis.subproj/ypinternal.h b/nis.subproj/ypinternal.h index 848c572..b40fbee 100644 --- a/nis.subproj/ypinternal.h +++ b/nis.subproj/ypinternal.h @@ -79,6 +79,14 @@ extern int _yplib_timeout; void _yp_unbind __P((struct dom_binding *)); int _yp_check __P((char **)); +/* allows callers to cancel yp_bind */ +#define ThreadStateExitRequested 4 + +/* used to tell _yp_dobind to use UDP or TCP */ +#define YP_BIND_UDP -1 +#define YP_BIND_TCP -2 + + #ifdef YPMATCHCACHE static bool_t ypmatch_add __P((const char *, const char *, diff --git a/nis.subproj/ypmatch_cache.c b/nis.subproj/ypmatch_cache.c index e689913..19ae149 100644 --- a/nis.subproj/ypmatch_cache.c +++ b/nis.subproj/ypmatch_cache.c @@ -188,6 +188,7 @@ yp_match(indomain, inmap, inkey, inkeylen, outval, outvallen) struct timeval tv; struct ypreq_key yprk; int tries = 0, r; + static int proto = YP_BIND_UDP; if (indomain == NULL || *indomain == '\0' || strlen(indomain) > YPMAXDOMAIN || inmap == NULL || @@ -227,14 +228,19 @@ again: memset(&yprv, 0, sizeof yprv); - r = clnt_call(ysd->dom_client, YPPROC_MATCH, - xdr_ypreq_key, &yprk, xdr_ypresp_val, &yprv, tv); - if (r != RPC_SUCCESS) { - if (tries++) - clnt_perror(ysd->dom_client, "yp_match: clnt_call"); - ysd->dom_vers = -1; + r = clnt_call(ysd->dom_client, YPPROC_MATCH, (xdrproc_t)xdr_ypreq_key, &yprk, (xdrproc_t)xdr_ypresp_val, &yprv, tv); + if (r != RPC_SUCCESS) + { + /* call failed - switch protocols and try again */ + if (tries++) clnt_perror(ysd->dom_client, "yp_match: clnt_call"); + + if (proto == YP_BIND_UDP) proto = YP_BIND_TCP; + else proto = YP_BIND_UDP; + ysd->dom_vers = proto; + goto again; } + if (!(r = ypprot_err(yprv.stat))) { *outvallen = yprv.val.valdat_len; if ((*outval = malloc(*outvallen + 1)) == NULL) { @@ -251,7 +257,7 @@ again: #endif } out: - xdr_free(xdr_ypresp_val, (char *) &yprv); + xdr_free((xdrproc_t)xdr_ypresp_val, (char *) &yprv); _yp_unbind(ysd); return r; } @@ -272,6 +278,7 @@ yp_next(indomain, inmap, inkey, inkeylen, outkey, outkeylen, outval, outvallen) struct dom_binding *ysd; struct timeval tv; int tries = 0, r; + static int proto = YP_BIND_UDP; if (indomain == NULL || *indomain == '\0' || strlen(indomain) > YPMAXDOMAIN || inmap == NULL || @@ -294,14 +301,19 @@ again: yprk.key.keydat_len = inkeylen; (void)memset(&yprkv, 0, sizeof yprkv); - r = clnt_call(ysd->dom_client, YPPROC_NEXT, - xdr_ypreq_key, &yprk, xdr_ypresp_key_val, &yprkv, tv); - if (r != RPC_SUCCESS) { - if (tries++) - clnt_perror(ysd->dom_client, "yp_next: clnt_call"); - ysd->dom_vers = -1; + r = clnt_call(ysd->dom_client, YPPROC_NEXT, (xdrproc_t)xdr_ypreq_key, &yprk, (xdrproc_t)xdr_ypresp_key_val, &yprkv, tv); + if (r != RPC_SUCCESS) + { + /* call failed - switch protocols and try again */ + if (tries++) clnt_perror(ysd->dom_client, "yp_next: clnt_call"); + + if (proto == YP_BIND_UDP) proto = YP_BIND_TCP; + else proto = YP_BIND_UDP; + ysd->dom_vers = proto; + goto again; } + if (!(r = ypprot_err(yprkv.stat))) { *outkeylen = yprkv.key.keydat_len; if ((*outkey = malloc(*outkeylen + 1)) == NULL) @@ -318,7 +330,7 @@ again: (*outval)[*outvallen] = '\0'; } } - xdr_free(xdr_ypresp_key_val, (char *) &yprkv); + xdr_free((xdrproc_t)xdr_ypresp_key_val, (char *) &yprkv); _yp_unbind(ysd); return r; } diff --git a/rpc.subproj/Makefile b/rpc.subproj/Makefile index 1139cb3..f74a525 100644 --- a/rpc.subproj/Makefile +++ b/rpc.subproj/Makefile @@ -25,7 +25,8 @@ CFILES = auth_none.c auth_unix.c authunix_prot.c bindresvport.c\ xdr_array.c xdr_float.c xdr_mem.c xdr_rec.c xdr_reference.c\ xdr_sizeof.c xdr_stdio.c getrpcport.c pmap_wakeup.c -OTHERSRCS = Makefile.preamble Makefile +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble \ + bindresvport.3 getrpcent.3 getrpcport.3 rpc.3 xdr.3 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles diff --git a/rpc.subproj/Makefile.postamble b/rpc.subproj/Makefile.postamble new file mode 100644 index 0000000..b851b91 --- /dev/null +++ b/rpc.subproj/Makefile.postamble @@ -0,0 +1,224 @@ +############################################################################### +# 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") +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0) +# 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:: +# @(if [ "$(CODE_GEN_STYLE)" != "STATIC" ]; then\ +# $(MAKE) install "CODE_GEN_STYLE=STATIC"\ +# "DSTROOT=$(DSTROOT)"\ +# "OBJROOT=$(OBJROOT)"\ +# "SYMROOT=$(SYMROOT)"\ +# "RC_CFLAGS = $(RC_CFLAGS)"\ +# "RC_ARCHS = $(RC_ARCHS)" ;\ +# fi ) + +install-man-page: + mkdir -p "$(DSTROOT)/usr/share/man/man3" + install -c -m 644 bindresvport.3 "$(DSTROOT)/usr/share/man/man3" + install -c -m 644 getrpcent.3 "$(DSTROOT)/usr/share/man/man3" + install -c -m 644 getrpcport.3 "$(DSTROOT)/usr/share/man/man3" + install -c -m 644 rpc.3 "$(DSTROOT)/usr/share/man/man3" + install -c -m 644 xdr.3 "$(DSTROOT)/usr/share/man/man3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getrpcent.3" "$(DSTROOT)/usr/share/man/man3/getrpcbyname.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getrpcent.3" "$(DSTROOT)/usr/share/man/man3/getrpcbynumber.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getrpcent.3" "$(DSTROOT)/usr/share/man/man3/endrpcent.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getrpcent.3" "$(DSTROOT)/usr/share/man/man3/setrpcent.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/auth_destroy.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/authnone_create.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/authunix_create.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/authunix_create_default.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/callrpc.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_broadcast.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_call.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_control.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_create.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_destroy.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_freeres.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_geterr.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_pcreateerror.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_perrno.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_perror.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_spcreateerror.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_sperrno.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_sperror.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clntraw_create.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnttcp_create.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clntudp_bufcreate.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clntudp_create.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/get_myaddress.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/pmap_getmaps.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/pmap_getport.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/pmap_rmtcall.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/pmap_set.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/pmap_unset.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/regsterrpc.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/rpc_createerr.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svc_destroy.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svc_fds.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svc_fdset.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svc_getargs.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svc_getcaller.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svc_getreg.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svc_getregset.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svc_register.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svc_run.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svc_sendreply.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svc_unregister.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svcerr_auth.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svcerr_decode.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svcerr_noproc.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svcerr_noprog.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svcerr_progvers.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svcerr_systemerr.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svcerr_weakauth.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svcfd_create.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svcraw_create.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svctcp_create.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svcudp_bufcreate.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/xdr_accepted_reply.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/xdr_authunix_parms.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/xdr_callhdr.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/xdr_callmsg.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/xdr_opaque_auth.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/xdr_pmap.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/xdr_pmaplist.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/xdr_rejected_reply.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/xdr_replymsg.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/xprt_register.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/xprt_unregister.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_array.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_bool.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_bytes.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_char.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_destroy.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_double.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_enum.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_float.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_free.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_getpos.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_inline.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_int.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_long.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdrmem_create.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_opaque.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_pointer.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdrrec_create.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdrrec_endofrecord.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdrrec_eof.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdrrec_skiprecord.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_reference.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_setpos.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_short.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdrstdio_create.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_string.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_u_char.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_u_long.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_u_short.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_union.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_vector.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_void.3" + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_wrapstring.3" + diff --git a/rpc.subproj/Makefile.preamble b/rpc.subproj/Makefile.preamble index 83c6f72..e827b3c 100644 --- a/rpc.subproj/Makefile.preamble +++ b/rpc.subproj/Makefile.preamble @@ -1,4 +1,5 @@ OTHER_CFLAGS = \ + -D__DARWIN_NON_CANCELABLE=1 \ -Dsetrpcent=_old_setrpcent \ -Dgetrpcent=_old_getrpcent \ -Dendrpcent=_old_endrpcent \ @@ -10,3 +11,5 @@ PUBLIC_HEADER_DIR_SUFFIX = /rpc # for building 64-bit # Libinfo need to build with gcc-3.5 and 3-way fat NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER) + +AFTER_POSTINSTALL += install-man-page diff --git a/rpc.subproj/auth.h b/rpc.subproj/auth.h index 4c3b528..1f9394e 100644 --- a/rpc.subproj/auth.h +++ b/rpc.subproj/auth.h @@ -91,7 +91,12 @@ enum auth_stat { AUTH_FAILED=7 /* some unknown reason */ }; -typedef unsigned long u_int32; /* 32-bit unsigned integers */ +/* 32-bit unsigned integers */ +#ifdef __LP64__ +typedef unsigned int u_int32; +#else +typedef unsigned long u_int32; +#endif union des_block { struct { diff --git a/rpc.subproj/auth_unix.c b/rpc.subproj/auth_unix.c index f2902c1..9bfe580 100644 --- a/rpc.subproj/auth_unix.c +++ b/rpc.subproj/auth_unix.c @@ -220,7 +220,7 @@ authunix_create_default() char machname[MAX_MACHINE_NAME + 1]; register int uid; register int gid; - int gids[NGROUPS]; + gid_t gids[NGROUPS]; if (gethostname(machname, MAX_MACHINE_NAME) == -1) abort(); @@ -232,7 +232,7 @@ authunix_create_default() if (len > maxgrplist) { len = maxgrplist; } - return (authunix_create(machname, uid, gid, len, gids)); + return (authunix_create(machname, uid, gid, len, (int *)gids)); } /* diff --git a/rpc.subproj/auth_unix.h b/rpc.subproj/auth_unix.h index 8870544..496defb 100644 --- a/rpc.subproj/auth_unix.h +++ b/rpc.subproj/auth_unix.h @@ -78,7 +78,11 @@ * Unix style credentials. */ struct authunix_parms { +#ifdef __LP64__ + unsigned int aup_time; +#else unsigned long aup_time; +#endif char *aup_machname; int aup_uid; int aup_gid; diff --git a/rpc.subproj/authunix_prot.c b/rpc.subproj/authunix_prot.c index 38864f2..52ca1a8 100644 --- a/rpc.subproj/authunix_prot.c +++ b/rpc.subproj/authunix_prot.c @@ -86,7 +86,7 @@ xdr_authunix_parms(xdrs, p) && xdr_int(xdrs, &(p->aup_uid)) && xdr_int(xdrs, &(p->aup_gid)) && xdr_array(xdrs, (caddr_t *)&(p->aup_gids), - &(p->aup_len), NGROUPS, sizeof(int), xdr_int) ) { + &(p->aup_len), NGROUPS, sizeof(int), (xdrproc_t)xdr_int) ) { return (TRUE); } return (FALSE); diff --git a/rpc.subproj/bindresvport.3 b/rpc.subproj/bindresvport.3 new file mode 100644 index 0000000..0ec6ffb --- /dev/null +++ b/rpc.subproj/bindresvport.3 @@ -0,0 +1,27 @@ +.\" from: @(#)bindresvport.3n 2.2 88/08/02 4.0 RPCSRC; from 1.7 88/03/14 SMI +.\" $Id: bindresvport.3,v 1.1 1999/04/13 23:15:36 wsanchez Exp $ +.\" +.Dd November 22, 1987 +.Dt BINDRESVPORT 3 +.Os +.Sh NAME +.Nm bindresvport +.Nd bind a socket to a privileged IP port +.Sh SYNOPSIS +.Fd #include +.Fd include +.Ft int +.Fn bindresvport "int sd" "struct sockaddr_in **sin" +.Sh DESCRIPTION +.Fn bindresvport +is used to bind a socket descriptor to a privileged +.Tn IP +port, that is, a +port number in the range 0-1023. +The routine returns 0 if it is successful, +otherwise -1 is returned and +.Va errno +set to reflect the cause of the error. +.Pp +Only root can bind to a privileged port; this call will fail for any +other users. diff --git a/rpc.subproj/bindresvport.c b/rpc.subproj/bindresvport.c index 2e47ff0..29d82d4 100644 --- a/rpc.subproj/bindresvport.c +++ b/rpc.subproj/bindresvport.c @@ -84,7 +84,7 @@ bindresvport_sa(sd, sa) struct sockaddr_in6 *sin6; int proto, portrange, portlow; u_int16_t port; - int salen; + u_int32_t salen; if (sa == NULL) { salen = sizeof(myaddr); @@ -120,7 +120,7 @@ bindresvport_sa(sd, sa) sa->sa_len = salen; if (port == 0) { - int oldlen = sizeof(old); + u_int32_t oldlen = sizeof(old); error = getsockopt(sd, proto, portrange, &old, &oldlen); if (error < 0) diff --git a/rpc.subproj/clnt.h b/rpc.subproj/clnt.h index 4aeca14..4ed9b51 100644 --- a/rpc.subproj/clnt.h +++ b/rpc.subproj/clnt.h @@ -123,12 +123,22 @@ struct rpc_err { int RE_errno; /* realated system error */ enum auth_stat RE_why; /* why the auth error occurred */ struct { +#ifdef __LP64__ + unsigned int low; /* lowest verion supported */ + unsigned int high; /* highest verion supported */ +#else unsigned long low; /* lowest verion supported */ unsigned long high; /* highest verion supported */ +#endif } RE_vers; struct { /* maybe meaningful if RPC_FAILED */ +#ifdef __LP64__ + int s1; + int s2; +#else long s1; long s2; +#endif } RE_lb; /* life boot & debugging only */ } ru; #define re_errno ru.RE_errno @@ -148,7 +158,11 @@ struct CLIENT { AUTH *cl_auth; /* authenticator */ struct clnt_ops { +#ifdef __LP64__ + enum clnt_stat (*cl_call)(CLIENT *, unsigned int, xdrproc_t, void *, xdrproc_t, void *, struct timeval); /* call remote procedure */ +#else enum clnt_stat (*cl_call)(CLIENT *, unsigned long, xdrproc_t, void *, xdrproc_t, void *, struct timeval); /* call remote procedure */ +#endif void (*cl_abort)(void); /* abort a call */ void (*cl_geterr)(CLIENT *, struct rpc_err *); /* get specific error code */ bool_t (*cl_freeres)(CLIENT *, xdrproc_t, void *); /* frees results */ @@ -169,7 +183,7 @@ struct CLIENT * enum clnt_stat * CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout) * CLIENT *rh; - * unsigned long proc; + * u_long proc; * xdrproc_t xargs; * caddr_t argsp; * xdrproc_t xres; @@ -245,16 +259,27 @@ struct CLIENT * and network administration. */ +#ifdef __LP64__ +#define RPCTEST_PROGRAM ((unsigned int)1) +#define RPCTEST_VERSION ((unsigned int)1) +#define RPCTEST_NULL_PROC ((unsigned int)2) +#define RPCTEST_NULL_BATCH_PROC ((unsigned int)3) +#else #define RPCTEST_PROGRAM ((unsigned long)1) #define RPCTEST_VERSION ((unsigned long)1) #define RPCTEST_NULL_PROC ((unsigned long)2) #define RPCTEST_NULL_BATCH_PROC ((unsigned long)3) +#endif /* * By convention, procedure 0 takes null arguments and returns them */ +#ifdef __LP64__ +#define NULLPROC ((unsigned int)0) +#else #define NULLPROC ((unsigned long)0) +#endif /* * Below are the client handle creation routines for the various @@ -266,11 +291,15 @@ struct CLIENT * Memory based rpc (for speed check and testing) * CLIENT * * clntraw_create(prog, vers) - * unsigned long prog; - * unsigned long vers; + * u_long prog; + * u_long vers; */ __BEGIN_DECLS +#ifdef __LP64__ +extern CLIENT *clntraw_create __P((unsigned int, unsigned int)); +#else extern CLIENT *clntraw_create __P((unsigned long, unsigned long)); +#endif __END_DECLS @@ -279,12 +308,16 @@ __END_DECLS * CLIENT * * clnt_create(host, prog, vers, prot); * char *host; -- hostname - * unsigned long prog; -- program number - * unsigned long vers; -- version number + * u_long prog; -- program number + * u_long vers; -- version number * char *prot; -- protocol */ __BEGIN_DECLS +#ifdef __LP64__ +extern CLIENT *clnt_create __P((char *, unsigned int, unsigned int, char *)); +#else extern CLIENT *clnt_create __P((char *, unsigned long, unsigned long, char *)); +#endif __END_DECLS @@ -293,19 +326,28 @@ __END_DECLS * CLIENT * * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) * struct sockaddr_in *raddr; - * unsigned long prog; - * unsigned long version; + * u_long prog; + * u_long version; * register int *sockp; * unsigned int sendsz; * unsigned int recvsz; */ __BEGIN_DECLS +#ifdef __LP64__ +extern CLIENT *clnttcp_create __P((struct sockaddr_in *, + unsigned int, + unsigned int, + int *, + unsigned int, + unsigned int)); +#else extern CLIENT *clnttcp_create __P((struct sockaddr_in *, - unsigned long, - unsigned long, - int *, - unsigned int, - unsigned int)); + unsigned long, + unsigned long, + int *, + unsigned int, + unsigned int)); +#endif __END_DECLS @@ -314,8 +356,8 @@ __END_DECLS * CLIENT * * clntudp_create(raddr, program, version, wait, sockp) * struct sockaddr_in *raddr; - * unsigned long program; - * unsigned long version; + * u_long program; + * u_long version; * struct timeval wait; * int *sockp; * @@ -323,26 +365,41 @@ __END_DECLS * CLIENT * * clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz) * struct sockaddr_in *raddr; - * unsigned long program; - * unsigned long version; + * u_long program; + * u_long version; * struct timeval wait; * int *sockp; * unsigned int sendsz; * unsigned int recvsz; */ __BEGIN_DECLS +#ifdef __LP64__ extern CLIENT *clntudp_create __P((struct sockaddr_in *, - unsigned long, - unsigned long, - struct timeval, - int *)); + unsigned int, + unsigned int, + struct timeval, + int *)); extern CLIENT *clntudp_bufcreate __P((struct sockaddr_in *, - unsigned long, - unsigned long, - struct timeval, - int *, - unsigned int, - unsigned int)); + unsigned int, + unsigned int, + struct timeval, + int *, + unsigned int, + unsigned int)); +#else +extern CLIENT *clntudp_create __P((struct sockaddr_in *, + unsigned long, + unsigned long, + struct timeval, + int *)); +extern CLIENT *clntudp_bufcreate __P((struct sockaddr_in *, + unsigned long, + unsigned long, + struct timeval, + int *, + unsigned int, + unsigned int)); +#endif __END_DECLS diff --git a/rpc.subproj/clnt_generic.c b/rpc.subproj/clnt_generic.c index 3901b60..231dd67 100644 --- a/rpc.subproj/clnt_generic.c +++ b/rpc.subproj/clnt_generic.c @@ -72,10 +72,17 @@ static char *rcsid = "$Id: clnt_generic.c,v 1.3 2002/02/19 20:36:22 epeyton Exp */ CLIENT * clnt_create(hostname, prog, vers, proto) +#ifdef __LP64__ + char *hostname; + uint32_t prog; + uint32_t vers; + char *proto; +#else char *hostname; u_long prog; u_long vers; char *proto; +#endif { struct hostent *h; struct protoent *p; diff --git a/rpc.subproj/clnt_perror.c b/rpc.subproj/clnt_perror.c index 84db735..a48c79a 100644 --- a/rpc.subproj/clnt_perror.c +++ b/rpc.subproj/clnt_perror.c @@ -131,9 +131,11 @@ clnt_sperror(rpch, s) break; case RPC_VERSMISMATCH: - (void) sprintf(str, - "; low version = %lu, high version = %lu", - e.re_vers.low, e.re_vers.high); +#ifdef __LP64__ + (void) sprintf(str, "; low version = %u, high version = %u", e.re_vers.low, e.re_vers.high); +#else + (void) sprintf(str, "; low version = %lu, high version = %lu", e.re_vers.low, e.re_vers.high); +#endif str += strlen(str); break; @@ -152,16 +154,20 @@ clnt_sperror(rpch, s) break; case RPC_PROGVERSMISMATCH: - (void) sprintf(str, - "; low version = %lu, high version = %lu", - e.re_vers.low, e.re_vers.high); +#ifdef __LP64__ + (void) sprintf(str, "; low version = %u, high version = %u", e.re_vers.low, e.re_vers.high); +#else + (void) sprintf(str, "; low version = %lu, high version = %lu", e.re_vers.low, e.re_vers.high); +#endif str += strlen(str); break; default: /* unknown */ - (void) sprintf(str, - "; s1 = %lu, s2 = %lu", - e.re_lb.s1, e.re_lb.s2); +#ifdef __LP64__ + (void) sprintf(str, "; s1 = %u, s2 = %u", e.re_lb.s1, e.re_lb.s2); +#else + (void) sprintf(str, "; s1 = %lu, s2 = %lu", e.re_lb.s1, e.re_lb.s2); +#endif str += strlen(str); break; } diff --git a/rpc.subproj/clnt_raw.c b/rpc.subproj/clnt_raw.c index 0fccf08..75a44aa 100644 --- a/rpc.subproj/clnt_raw.c +++ b/rpc.subproj/clnt_raw.c @@ -109,13 +109,18 @@ void svc_getreq(); */ CLIENT * clntraw_create(prog, vers) +#ifdef __LP64__ + uint32_t prog; + uint32_t vers; +#else u_long prog; u_long vers; +#endif { register struct clntraw_private *clp = clntraw_private; struct rpc_msg call_msg; XDR *xdrs = &clp->xdr_stream; - CLIENT *client = &clp->client_object; + CLIENT *client = &clp->client_object; if (clp == 0) { clp = (struct clntraw_private *)calloc(1, sizeof (*clp)); @@ -153,7 +158,7 @@ clntraw_create(prog, vers) static enum clnt_stat clntraw_call(h, proc, xargs, argsp, xresults, resultsp, timeout) CLIENT *h; - u_long proc; + rpc_uint proc; xdrproc_t xargs; caddr_t argsp; xdrproc_t xresults; @@ -175,12 +180,17 @@ call_again: xdrs->x_op = XDR_ENCODE; XDR_SETPOS(xdrs, 0); ((struct rpc_msg *)clp->mashl_callmsg)->rm_xid ++ ; +#ifdef __LP64__ if ((! XDR_PUTBYTES(xdrs, clp->mashl_callmsg, clp->mcnt)) || - (! XDR_PUTLONG(xdrs, (long *)&proc)) || + (! XDR_PUTLONG(xdrs, (int *)&proc)) || (! AUTH_MARSHALL(h->cl_auth, xdrs)) || - (! (*xargs)(xdrs, argsp))) { - return (RPC_CANTENCODEARGS); - } + (! (*xargs)(xdrs, argsp))) return (RPC_CANTENCODEARGS); +#else + if ((! XDR_PUTBYTES(xdrs, clp->mashl_callmsg, clp->mcnt)) || + (! XDR_PUTLONG(xdrs, (long *)&proc)) || + (! AUTH_MARSHALL(h->cl_auth, xdrs)) || + (! (*xargs)(xdrs, argsp))) return (RPC_CANTENCODEARGS); +#endif (void)XDR_GETPOS(xdrs); /* called just to cause overhead */ /* diff --git a/rpc.subproj/clnt_tcp.c b/rpc.subproj/clnt_tcp.c index 71afd9d..106d4be 100644 --- a/rpc.subproj/clnt_tcp.c +++ b/rpc.subproj/clnt_tcp.c @@ -63,7 +63,7 @@ static char *rcsid = "$Id: clnt_tcp.c,v 1.4 2002/03/15 22:07:48 majka Exp $"; * * TCP based RPC supports 'batched calls'. * A sequence of calls may be batched-up in a send buffer. The rpc call - * return immediately to the client even though the call was not necessarily + * returns immediately to the client even though the call was not necessarily * sent. The batching occurs if the results' xdr routine is NULL (0) AND * the rpc timeout value is zero (see clnt.h, rpc). * @@ -93,6 +93,8 @@ extern int errno; extern int bindresvport(); extern bool_t xdr_opaque_auth(); +__private_extern__ u_short pmap_getport_timeout(struct sockaddr_in *address, uint32_t program, uint32_t version, uint32_t protocol, struct timeval *timeout, struct timeval *totaltimeout); + static int readtcp(); static int writetcp(); @@ -115,8 +117,8 @@ static struct clnt_ops tcp_ops = { struct ct_data { int ct_sock; bool_t ct_closeit; - struct timeval ct_wait; - bool_t ct_waitset; /* wait set by clnt_control? */ + struct timeval ct_timeout; + bool_t ct_timeout_set; /* timeout set by clnt_control? */ struct sockaddr_in ct_addr; struct rpc_err ct_error; char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */ @@ -139,30 +141,26 @@ struct ct_data { * something more useful. */ CLIENT * -clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) - struct sockaddr_in *raddr; - u_long prog; - u_long vers; - register int *sockp; - u_int sendsz; - u_int recvsz; +clnttcp_create_timeout(struct sockaddr_in *raddr, uint32_t prog, uint32_t vers, int *sockp, uint32_t sendsz, uint32_t recvsz, struct timeval *retry_timeout, struct timeval *total_timeout) { CLIENT *h; register struct ct_data *ct = NULL; struct timeval now; struct rpc_msg call_msg; int rfd; + u_short port; - h = (CLIENT *)mem_alloc(sizeof(*h)); - if (h == NULL) { - (void)fprintf(stderr, "clnttcp_create: out of memory\n"); + h = (CLIENT *)mem_alloc(sizeof(*h)); + if (h == NULL) + { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto fooy; } + ct = (struct ct_data *)mem_alloc(sizeof(*ct)); - if (ct == NULL) { - (void)fprintf(stderr, "clnttcp_create: out of memory\n"); + if (ct == NULL) + { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto fooy; @@ -171,32 +169,38 @@ clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) /* * If no port number given ask the pmap for one */ - if (raddr->sin_port == 0) { - u_short port; - if ((port = pmap_getport(raddr, prog, vers, IPPROTO_TCP)) == 0) { + if (raddr->sin_port == 0) + { + port = pmap_getport_timeout(raddr, prog, vers, IPPROTO_TCP, retry_timeout, total_timeout); + if (port == 0) + { mem_free((caddr_t)ct, sizeof(struct ct_data)); mem_free((caddr_t)h, sizeof(CLIENT)); - return ((CLIENT *)NULL); + return NULL; } + raddr->sin_port = htons(port); } /* * If no socket given, open one */ - if (*sockp < 0) { + if (*sockp < 0) + { *sockp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - (void)bindresvport(*sockp, (struct sockaddr_in *)0); - if ((*sockp < 0) - || (connect(*sockp, (struct sockaddr *)raddr, - sizeof(*raddr)) < 0)) { + bindresvport(*sockp, (struct sockaddr_in *)0); + if ((*sockp < 0) || (connect(*sockp, (struct sockaddr *)raddr, sizeof(*raddr)) < 0)) + { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; - (void)close(*sockp); + close(*sockp); goto fooy; } + ct->ct_closeit = TRUE; - } else { + } + else + { ct->ct_closeit = FALSE; } @@ -204,8 +208,14 @@ clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) * Set up private data struct */ ct->ct_sock = *sockp; - ct->ct_wait.tv_usec = 0; - ct->ct_waitset = FALSE; + ct->ct_timeout.tv_sec = 60; + ct->ct_timeout.tv_usec = 0; + ct->ct_timeout_set = FALSE; + if (total_timeout != NULL) + { + ct->ct_timeout = *total_timeout; + ct->ct_timeout_set = TRUE; + } ct->ct_addr = *raddr; /* @@ -217,6 +227,7 @@ clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) 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; @@ -227,14 +238,13 @@ clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) /* * pre-serialize the staic part of the call msg and stash it away */ - xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, - XDR_ENCODE); - if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) { - if (ct->ct_closeit) { - (void)close(*sockp); - } + xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, XDR_ENCODE); + if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) + { + if (ct->ct_closeit) close(*sockp); goto fooy; } + ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs)); XDR_DESTROY(&(ct->ct_xdrs)); @@ -242,20 +252,37 @@ clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) * Create a client handle which uses xdrrec for serialization * and authnone for authentication. */ - xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz, - (caddr_t)ct, readtcp, writetcp); + xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz, (caddr_t)ct, readtcp, writetcp); h->cl_ops = &tcp_ops; - h->cl_private = (caddr_t) ct; + h->cl_private = (caddr_t)ct; h->cl_auth = authnone_create(); - return (h); + return h; fooy: - /* - * Something goofed, free stuff and barf - */ mem_free((caddr_t)ct, sizeof(struct ct_data)); mem_free((caddr_t)h, sizeof(CLIENT)); - return ((CLIENT *)NULL); + return NULL; +} + +CLIENT * +clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) +#ifdef __LP64__ +struct sockaddr_in *raddr; +uint32_t prog; +uint32_t vers; +int *sockp; +uint32_t sendsz; +uint32_t recvsz; +#else +struct sockaddr_in *raddr; +u_long prog; +u_long vers; +register int *sockp; +u_int sendsz; +u_int recvsz; +#endif +{ + return clnttcp_create_timeout(raddr, (uint32_t)prog, (uint32_t)vers, sockp, (uint32_t)sendsz, (uint32_t)recvsz, NULL, NULL); } static enum clnt_stat @@ -276,8 +303,8 @@ clnttcp_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout) register bool_t shipnow; int refreshes = 2; - if (!ct->ct_waitset) { - ct->ct_wait = timeout; + if (!ct->ct_timeout_set) { + ct->ct_timeout = timeout; } shipnow = @@ -288,10 +315,18 @@ call_again: xdrs->x_op = XDR_ENCODE; ct->ct_error.re_status = RPC_SUCCESS; x_id = ntohl(--(*msg_x_id)); +#ifdef __LP64__ if ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) || - (! XDR_PUTLONG(xdrs, (long *)&proc)) || + (! XDR_PUTLONG(xdrs, (int *)&proc)) || (! AUTH_MARSHALL(h->cl_auth, xdrs)) || - (! (*xdr_args)(xdrs, args_ptr))) { + (! (*xdr_args)(xdrs, args_ptr))) +#else + if ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) || + (! XDR_PUTLONG(xdrs, (long *)&proc)) || + (! AUTH_MARSHALL(h->cl_auth, xdrs)) || + (! (*xdr_args)(xdrs, args_ptr))) +#endif + { if (ct->ct_error.re_status == RPC_SUCCESS) ct->ct_error.re_status = RPC_CANTENCODEARGS; (void)xdrrec_endofrecord(xdrs, TRUE); @@ -316,7 +351,7 @@ call_again: while (TRUE) { reply_msg.acpted_rply.ar_verf = _null_auth; reply_msg.acpted_rply.ar_results.where = NULL; - reply_msg.acpted_rply.ar_results.proc = xdr_void; + reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void; if (! xdrrec_skiprecord(xdrs)) return (ct->ct_error.re_status); /* now decode and validate the response header */ @@ -394,11 +429,11 @@ clnttcp_control(cl, request, info) switch (request) { case CLSET_TIMEOUT: - ct->ct_wait = *(struct timeval *)info; - ct->ct_waitset = TRUE; + ct->ct_timeout = *(struct timeval *)info; + ct->ct_timeout_set = TRUE; break; case CLGET_TIMEOUT: - *(struct timeval *)info = ct->ct_wait; + *(struct timeval *)info = ct->ct_timeout; break; case CLGET_SERVER_ADDR: *(struct sockaddr_in *)info = ct->ct_addr; @@ -445,8 +480,7 @@ readtcp(ct, buf, len) FD_SET(ct->ct_sock, &mask); while (TRUE) { readfds = mask; - switch (select(ct->ct_sock+1, &readfds, NULL, NULL, - &(ct->ct_wait))) { + switch (select(ct->ct_sock+1, &readfds, NULL, NULL, &(ct->ct_timeout))) { case 0: ct->ct_error.re_status = RPC_TIMEDOUT; return (-1); diff --git a/rpc.subproj/clnt_udp.c b/rpc.subproj/clnt_udp.c index 446603a..53c618b 100644 --- a/rpc.subproj/clnt_udp.c +++ b/rpc.subproj/clnt_udp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2007 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -77,6 +77,8 @@ static char *rcsid = "$Id: clnt_udp.c,v 1.4 2002/03/15 22:07:49 majka Exp $"; extern int bindresvport(); extern bool_t xdr_opaque_auth(); +__private_extern__ u_short pmap_getport_timeout(struct sockaddr_in *address, uint32_t program, uint32_t version, uint32_t protocol, struct timeval *timeout, struct timeval *totaltimeout); + extern int errno; /* @@ -106,8 +108,8 @@ struct cu_data { bool_t cu_closeit; struct sockaddr_in cu_raddr; int cu_rlen; - struct timeval cu_wait; - struct timeval cu_total; + struct timeval cu_retry_timeout; + struct timeval cu_total_timeout; struct rpc_err cu_error; XDR cu_outxdrs; u_int cu_xdrpos; @@ -133,57 +135,60 @@ struct cu_data { * sendsz and recvsz are the maximum allowable packet sizes that can be * sent and received. */ -CLIENT * -clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz) - struct sockaddr_in *raddr; - u_long program; - u_long version; - struct timeval wait; - register int *sockp; - u_int sendsz; - u_int recvsz; +__private_extern__ CLIENT * +clntudp_bufcreate_timeout(struct sockaddr_in *raddr, uint32_t program, uint32_t version, int *sockp, uint32_t sendsz, uint32_t recvsz, struct timeval *retry_timeout, struct timeval *total_timeout) { CLIENT *cl; - register struct cu_data *cu = NULL; + struct cu_data *cu = NULL; struct timeval now; struct rpc_msg call_msg; int rfd; + u_short port; + socklen_t len; + unsigned int rsize; cl = (CLIENT *)mem_alloc(sizeof(CLIENT)); - if (cl == NULL) { - (void) fprintf(stderr, "clntudp_create: out of memory\n"); + if (cl == NULL) + { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto fooy; } + sendsz = ((sendsz + 3) / 4) * 4; recvsz = ((recvsz + 3) / 4) * 4; cu = (struct cu_data *)mem_alloc(sizeof(*cu) + sendsz + recvsz); - if (cu == NULL) { - (void) fprintf(stderr, "clntudp_create: out of memory\n"); + if (cu == NULL) + { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto fooy; } + cu->cu_outbuf = &cu->cu_inbuf[recvsz]; - if (raddr->sin_port == 0) { - u_short port; - if ((port = - pmap_getport(raddr, program, version, IPPROTO_UDP)) == 0) { - goto fooy; - } + if (raddr->sin_port == 0) + { + port = pmap_getport_timeout(raddr, program, version, IPPROTO_UDP, retry_timeout, total_timeout); + if (port == 0) goto fooy; + raddr->sin_port = htons(port); } + cl->cl_ops = &udp_ops; cl->cl_private = (caddr_t)cu; cu->cu_raddr = *raddr; cu->cu_rlen = sizeof (cu->cu_raddr); - cu->cu_wait = wait; - cu->cu_total.tv_sec = -1; - cu->cu_total.tv_usec = -1; cu->cu_sendsz = sendsz; cu->cu_recvsz = recvsz; + + cu->cu_retry_timeout.tv_sec = 1; + cu->cu_retry_timeout.tv_usec = 0; + if (retry_timeout != NULL) cu->cu_retry_timeout = *retry_timeout; + + cu->cu_total_timeout.tv_sec = -1; + cu->cu_total_timeout.tv_usec = -1; + if (total_timeout != NULL) cu->cu_total_timeout = *retry_timeout; 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))) @@ -191,57 +196,110 @@ clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz) 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; call_msg.rm_call.cb_vers = version; - xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf, - sendsz, XDR_ENCODE); - if (! xdr_callhdr(&(cu->cu_outxdrs), &call_msg)) { - goto fooy; - } + xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf, sendsz, XDR_ENCODE); + if (! xdr_callhdr(&(cu->cu_outxdrs), &call_msg)) goto fooy; + cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs)); - if (*sockp < 0) { + if (*sockp < 0) + { int dontblock = 1; *sockp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (*sockp < 0) { + if (*sockp < 0) + { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto fooy; } + /* attempt to bind to prov port */ (void)bindresvport(*sockp, (struct sockaddr_in *)0); - /* the sockets rpc controls are non-blocking */ + + /* the socket's rpc controls are non-blocking */ (void)ioctl(*sockp, FIONBIO, (char *) &dontblock); cu->cu_closeit = TRUE; - } else { + + /* set receive size */ + rsize = 0; + len = sizeof(rsize); + if (getsockopt(*sockp, SOL_SOCKET, SO_RCVBUF, (char *)&rsize, &len) != 0) + { + close(*sockp); + *sockp = -1; + goto fooy; + } + + len = sizeof(recvsz); + if ((recvsz > rsize) && (setsockopt(*sockp, SOL_SOCKET, SO_RCVBUF, (char *)&recvsz, len))) + { + close(*sockp); + *sockp = -1; + goto fooy; + } + } + else + { cu->cu_closeit = FALSE; } + cu->cu_sock = *sockp; cl->cl_auth = authnone_create(); return (cl); + fooy: - if (cu) - mem_free((caddr_t)cu, sizeof(*cu) + sendsz + recvsz); - if (cl) - mem_free((caddr_t)cl, sizeof(CLIENT)); - return ((CLIENT *)NULL); + if (cu) mem_free((caddr_t)cu, sizeof(*cu) + sendsz + recvsz); + if (cl) mem_free((caddr_t)cl, sizeof(CLIENT)); + return NULL; +} + +CLIENT * +clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz) +#ifdef __LP64__ +struct sockaddr_in *raddr; +uint32_t program; +uint32_t version; +struct timeval wait; +int *sockp; +uint32_t sendsz; +uint32_t recvsz; +#else +struct sockaddr_in *raddr; +u_long program; +u_long version; +struct timeval wait; +register int *sockp; +u_int sendsz; +u_int recvsz; +#endif +{ + return clntudp_bufcreate_timeout(raddr, (uint32_t)program, (uint32_t)version, sockp, (uint32_t)sendsz, (uint32_t)recvsz, &wait, NULL); } CLIENT * clntudp_create(raddr, program, version, wait, sockp) +#ifdef __LP64__ + struct sockaddr_in *raddr; + uint32_t program; + uint32_t version; + struct timeval wait; + int *sockp; +#else struct sockaddr_in *raddr; u_long program; u_long version; struct timeval wait; register int *sockp; +#endif { - return(clntudp_bufcreate(raddr, program, version, wait, sockp, - UDPMSGSIZE, UDPMSGSIZE)); + return clntudp_bufcreate(raddr, program, version, wait, sockp, UDPMSGSIZE, UDPMSGSIZE); } static enum clnt_stat @@ -258,7 +316,7 @@ clntudp_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout) register XDR *xdrs; register int outlen; register int inlen; - int fromlen; + u_int32_t fromlen; fd_set readfds; fd_set mask; struct sockaddr_in from; @@ -269,32 +327,45 @@ clntudp_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout) int nrefreshes = 2; /* number of times to refresh cred */ struct timeval timeout; - if (cu->cu_total.tv_usec == -1) { - timeout = utimeout; /* use supplied timeout */ - } else { - timeout = cu->cu_total; /* use default timeout */ + if (cu->cu_total_timeout.tv_sec == -1) + { + /* use supplied total timeout */ + timeout = utimeout; + } + else + { + /* use client's total timeout */ + timeout = cu->cu_total_timeout; } time_waited.tv_sec = 0; time_waited.tv_usec = 0; + call_again: xdrs = &(cu->cu_outxdrs); xdrs->x_op = XDR_ENCODE; XDR_SETPOS(xdrs, cu->cu_xdrpos); + /* * the transaction is the first thing in the out buffer */ (*(u_short *)(cu->cu_outbuf))++; +#ifdef __LP64__ + if ((! XDR_PUTLONG(xdrs, (int *)&proc)) || + (! AUTH_MARSHALL(cl->cl_auth, xdrs)) || + (! (*xargs)(xdrs, argsp))) + return (cu->cu_error.re_status = RPC_CANTENCODEARGS); +#else if ((! XDR_PUTLONG(xdrs, (long *)&proc)) || (! AUTH_MARSHALL(cl->cl_auth, xdrs)) || (! (*xargs)(xdrs, argsp))) return (cu->cu_error.re_status = RPC_CANTENCODEARGS); +#endif outlen = (int)XDR_GETPOS(xdrs); send_again: - if (sendto(cu->cu_sock, cu->cu_outbuf, outlen, 0, - (struct sockaddr *)&(cu->cu_raddr), cu->cu_rlen) - != outlen) { + if (sendto(cu->cu_sock, cu->cu_outbuf, outlen, 0, (struct sockaddr *)&(cu->cu_raddr), cu->cu_rlen) != outlen) + { cu->cu_error.re_errno = errno; return (cu->cu_error.re_status = RPC_CANTSEND); } @@ -302,9 +373,11 @@ send_again: /* * Hack to provide rpc-based message passing */ - if (timeout.tv_sec == 0 && timeout.tv_usec == 0) { + if (timeout.tv_sec == 0 && timeout.tv_usec == 0) + { return (cu->cu_error.re_status = RPC_TIMEDOUT); } + /* * sub-optimal code appears here because we have * some clock time to spare while the packets are in flight. @@ -315,14 +388,13 @@ send_again: reply_msg.acpted_rply.ar_results.proc = xresults; FD_ZERO(&mask); FD_SET(cu->cu_sock, &mask); - for (;;) { + for (;;) + { readfds = mask; - switch (select(cu->cu_sock+1, &readfds, NULL, - NULL, &(cu->cu_wait))) { - + switch (select(cu->cu_sock+1, &readfds, NULL, NULL, &(cu->cu_retry_timeout))) { case 0: - time_waited.tv_sec += cu->cu_wait.tv_sec; - time_waited.tv_usec += cu->cu_wait.tv_usec; + time_waited.tv_sec += cu->cu_retry_timeout.tv_sec; + time_waited.tv_usec += cu->cu_retry_timeout.tv_usec; while (time_waited.tv_usec >= 1000000) { time_waited.tv_sec++; time_waited.tv_usec -= 1000000; @@ -438,16 +510,16 @@ clntudp_control(cl, request, info) switch (request) { case CLSET_TIMEOUT: - cu->cu_total = *(struct timeval *)info; + cu->cu_total_timeout = *(struct timeval *)info; break; case CLGET_TIMEOUT: - *(struct timeval *)info = cu->cu_total; + *(struct timeval *)info = cu->cu_total_timeout; break; case CLSET_RETRY_TIMEOUT: - cu->cu_wait = *(struct timeval *)info; + cu->cu_retry_timeout = *(struct timeval *)info; break; case CLGET_RETRY_TIMEOUT: - *(struct timeval *)info = cu->cu_wait; + *(struct timeval *)info = cu->cu_retry_timeout; break; case CLGET_SERVER_ADDR: *(struct sockaddr_in *)info = cu->cu_raddr; diff --git a/rpc.subproj/getrpcent.3 b/rpc.subproj/getrpcent.3 new file mode 100644 index 0000000..dc4826d --- /dev/null +++ b/rpc.subproj/getrpcent.3 @@ -0,0 +1,93 @@ +.\" from: @(#)getrpcent.3n 2.2 88/08/02 4.0 RPCSRC; from 1.11 88/03/14 SMI +.\" $Id: getrpcent.3,v 1.1 1999/04/13 23:15:37 wsanchez Exp $ +.\" +.Dd December 14, 1987 +.Dt GETRPCENT 3 +.Os +.Sh NAME +.Nm getrpcent , +.Nm getrpcbyname , +.Nm getrpcbynumber , +.Nm endrpcent , +.Nm setrpcent +.Nd get RPC entry +.Sh SYNOPSIS +.Fd #include +.Ft struct rpcent * +.Fn getrpcent void +.Ft struct rpcent * +.Fn getrpcbyname "char *name" +.Ft struct rpcent * +.Fn getrpcbynumber "int number" +.Ft void +.Fn setrpcent "int stayopen" +.Ft void +.Fn endrpcent void +.Sh DESCRIPTION +.Fn getrpcent , +.Fn getrpcbyname , +and +.Fn getrpcbynumber , +each return a pointer to an object with the +following structure +containing the broken-out +fields of a line in the rpc program number data base, +.Pa /etc/rpc : +.Bd -literal -offset indent +struct rpcent { + char *r_name; /* name of server for this rpc program */ + char **r_aliases; /* alias list */ + long r_number; /* rpc program number */ +}; +.Ed +.Pp +The members of this structure are: +.Bl -tag -width r_aliases -offset indent +.It r_name +The name of the server for this rpc program. +.It r_aliases +A zero terminated list of alternate names for the rpc program. +.It r_number +The rpc program number for this service. +.El +.Pp +.Fn getrpcent +reads the next line of the file, opening the file if necessary. +.Pp +.Fn setrpcent +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 getrpcent +(either directly, or indirectly through one of +the other +.Dq getrpc +calls). +.Pp +.Fn endrpcent +closes the file. +.Pp +.Fn getrpcbyname +and +.Fn getrpcbynumber +sequentially search from the beginning +of the file until a matching rpc program name or +program number is found, or until end-of-file is encountered. +.Sh FILES +.Pa /etc/rpc +.Sh SEE ALSO +.Xr rpc 5 , +.Xr rpcinfo 8 , +.Xr ypserv 8 +.Sh DIAGNOSTICS +A +.Dv NULL +pointer is returned on +.Dv EOF +or error. +.Sh BUGS +All information +is contained in a static area +so it must be copied if it is +to be saved. diff --git a/rpc.subproj/getrpcent.c b/rpc.subproj/getrpcent.c index 74fc043..6e53c28 100644 --- a/rpc.subproj/getrpcent.c +++ b/rpc.subproj/getrpcent.c @@ -98,17 +98,30 @@ _rpcdata() struct rpcent * getrpcbynumber(number) +#ifdef __LP64__ + int32_t number; +#else register long number; +#endif { register struct rpcdata *d = _rpcdata(); register struct rpcent *p; +#ifdef __LP64__ + int x; + + x = number; +#endif if (d == 0) return (0); setrpcent(0); - while ((p = getrpcent())) { - if (p->r_number == number) - break; + while ((p = getrpcent())) + { +#ifdef __LP64__ + if (p->r_number == x) break; +#else + if (p->r_number == number) break; +#endif } endrpcent(); return (p); diff --git a/rpc.subproj/getrpcport.3 b/rpc.subproj/getrpcport.3 new file mode 100644 index 0000000..16ab68c --- /dev/null +++ b/rpc.subproj/getrpcport.3 @@ -0,0 +1,32 @@ +.\" from: @(#)getrpcport.3r 2.2 88/08/02 4.0 RPCSRC; from 1.12 88/02/26 SMI +.\" $Id: getrpcport.3,v 1.1 1999/04/13 23:15:37 wsanchez Exp $ +.\" +.Dd October 6, 1987 +.Dt GETRPCPORT 3 +.Os +.Sh NAME +.Nm getrpcport +.Nd get RPC port number +.Sh SYNOPSIS +.Fd #include +.Ft int +.Fn getrpcport "char *host" "int prognum" "int versnum" "int proto" +.Sh DESCRIPTION +.Fn getrpcport +returns the port number for version +.Fa versnum +of the RPC program +.Fa prognum +running on +.Fa host +and using protocol +.Fa proto . +It returns 0 if it cannot contact the portmapper, or if +.Fa prognum +is not registered. If +.Fa prognum +is registered but not with version +.Fa versnum , +it will still return a port number (for some version of the program) +indicating that the program is indeed registered. +The version mismatch will be detected upon the first call to the service. diff --git a/rpc.subproj/pmap_clnt.c b/rpc.subproj/pmap_clnt.c index 0a89232..9cb337b 100644 --- a/rpc.subproj/pmap_clnt.c +++ b/rpc.subproj/pmap_clnt.c @@ -76,11 +76,15 @@ static char *rcsid = "$Id: pmap_clnt.c,v 1.5 2004/12/19 22:45:44 zarzycki Exp $" #include "pmap_wakeup.h" -static struct timeval timeout = { 5, 0 }; -static struct timeval tottimeout = { 60, 0 }; +__private_extern__ CLIENT *clntudp_bufcreate_timeout(struct sockaddr_in *raddr, uint32_t program, uint32_t version, int *sockp, uint32_t sendsz, uint32_t recvsz, struct timeval *timeout, struct timeval *totaltimeout); -void clnt_perror(); +static struct timeval set_retry_timeout = { 5, 0 }; +static struct timeval set_total_timeout = { 60, 0 }; + +static struct timeval unset_retry_timeout = { 1, 0 }; +static struct timeval unset_total_timeout = { 5, 0 }; +void clnt_perror(); /* * Set a mapping between program,version and port. @@ -88,10 +92,17 @@ void clnt_perror(); */ bool_t pmap_set(program, version, protocol, port) +#ifdef __LP64__ + uint32_t program; + uint32_t version; + int32_t protocol; + uint16_t port; +#else u_long program; u_long version; int protocol; u_short port; +#endif { struct sockaddr_in myaddress; int socket = -1; @@ -99,28 +110,24 @@ pmap_set(program, version, protocol, port) struct pmap parms; bool_t rslt; - pmap_wakeup(); + if (pmap_wakeup() != 0) return FALSE; memset(&myaddress, 0, sizeof(struct sockaddr_in)); myaddress.sin_family = AF_INET; myaddress.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS, - timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); - if (client == (CLIENT *)NULL) - return (FALSE); + client = clntudp_bufcreate_timeout(&myaddress, PMAPPROG, PMAPVERS, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE, &set_retry_timeout, &set_total_timeout); + if (client == NULL) return FALSE; + parms.pm_prog = program; parms.pm_vers = version; parms.pm_prot = protocol; parms.pm_port = port; - if (CLNT_CALL(client, PMAPPROC_SET, xdr_pmap, &parms, xdr_bool, &rslt, - tottimeout) != RPC_SUCCESS) { - clnt_perror(client, "Cannot register service"); - return (FALSE); - } + if (CLNT_CALL(client, PMAPPROC_SET, (xdrproc_t)xdr_pmap, &parms, (xdrproc_t)xdr_bool, &rslt, set_total_timeout) != RPC_SUCCESS) return FALSE; + CLNT_DESTROY(client); - (void)close(socket); - return (rslt); + close(socket); + return rslt; } /* @@ -129,8 +136,13 @@ pmap_set(program, version, protocol, port) */ bool_t pmap_unset(program, version) +#ifdef __LP64__ + uint32_t program; + uint32_t version; +#else u_long program; u_long version; +#endif { struct sockaddr_in myaddress; int socket = -1; @@ -138,22 +150,23 @@ pmap_unset(program, version) struct pmap parms; bool_t rslt; - pmap_wakeup(); + if (pmap_wakeup() != 0) return FALSE; memset(&myaddress, 0, sizeof(struct sockaddr_in)); myaddress.sin_family = AF_INET; myaddress.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS, - timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); - if (client == (CLIENT *)NULL) - return (FALSE); + client = clntudp_bufcreate_timeout(&myaddress, PMAPPROG, PMAPVERS, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE, &unset_retry_timeout, &unset_total_timeout); + if (client == NULL) return FALSE; + parms.pm_prog = program; parms.pm_vers = version; - parms.pm_port = parms.pm_prot = 0; - CLNT_CALL(client, PMAPPROC_UNSET, xdr_pmap, &parms, xdr_bool, &rslt, - tottimeout); + parms.pm_port = 0; + parms.pm_prot = 0; + + CLNT_CALL(client, PMAPPROC_UNSET, (xdrproc_t)xdr_pmap, &parms, (xdrproc_t)xdr_bool, &rslt, unset_total_timeout); + CLNT_DESTROY(client); - (void)close(socket); - return (rslt); + close(socket); + return rslt; } diff --git a/rpc.subproj/pmap_clnt.h b/rpc.subproj/pmap_clnt.h index f89b81e..c07a819 100644 --- a/rpc.subproj/pmap_clnt.h +++ b/rpc.subproj/pmap_clnt.h @@ -88,20 +88,37 @@ #include __BEGIN_DECLS +#ifdef __LP64__ +extern bool_t pmap_set __P((unsigned int, unsigned int, int, int)); +extern bool_t pmap_unset __P((unsigned int, unsigned int)); +extern enum clnt_stat pmap_rmtcall __P((struct sockaddr_in *, + unsigned int, unsigned int, unsigned int, + xdrproc_t, caddr_t, + xdrproc_t, caddr_t, + struct timeval, unsigned int *)); +extern enum clnt_stat clnt_broadcast __P((unsigned int, unsigned int, unsigned int, + xdrproc_t, char *, + xdrproc_t, char *, + bool_t (*)())); +extern unsigned short pmap_getport __P((struct sockaddr_in *, + unsigned int, unsigned int, unsigned int)); +#else extern bool_t pmap_set __P((unsigned long, unsigned long, int, int)); extern bool_t pmap_unset __P((unsigned long, unsigned long)); -extern struct pmaplist *pmap_getmaps __P((struct sockaddr_in *)); extern enum clnt_stat pmap_rmtcall __P((struct sockaddr_in *, - unsigned long, unsigned long, unsigned long, - xdrproc_t, caddr_t, - xdrproc_t, caddr_t, - struct timeval, unsigned long *)); + unsigned long, unsigned long, unsigned long, + xdrproc_t, caddr_t, + xdrproc_t, caddr_t, + struct timeval, unsigned long *)); extern enum clnt_stat clnt_broadcast __P((unsigned long, unsigned long, unsigned long, - xdrproc_t, char *, - xdrproc_t, char *, - bool_t (*)())); + xdrproc_t, char *, + xdrproc_t, char *, + bool_t (*)())); extern unsigned short pmap_getport __P((struct sockaddr_in *, - unsigned long, unsigned long, unsigned int)); + unsigned long, unsigned long, unsigned int)); +#endif +extern struct pmaplist *pmap_getmaps __P((struct sockaddr_in *)); +extern int getrpcport __P((char *, int, int, int)); __END_DECLS #endif /* !_RPC_PMAPCLNT_H */ diff --git a/rpc.subproj/pmap_getmaps.c b/rpc.subproj/pmap_getmaps.c index 98eeedd..b359b9c 100644 --- a/rpc.subproj/pmap_getmaps.c +++ b/rpc.subproj/pmap_getmaps.c @@ -77,8 +77,6 @@ static char *rcsid = "$Id: pmap_getmaps.c,v 1.4 2004/12/19 22:45:44 zarzycki Exp #define NAMELEN 255 #define MAX_BROADCAST_SIZE 1400 -#include "pmap_wakeup.h" - extern int errno; /* @@ -94,16 +92,13 @@ pmap_getmaps(address) struct timeval minutetimeout; register CLIENT *client; - pmap_wakeup(); - minutetimeout.tv_sec = 60; minutetimeout.tv_usec = 0; address->sin_port = htons(PMAPPORT); client = clnttcp_create(address, PMAPPROG, PMAPVERS, &socket, 50, 500); if (client != (CLIENT *)NULL) { - if (CLNT_CALL(client, PMAPPROC_DUMP, xdr_void, NULL, xdr_pmaplist, - &head, minutetimeout) != RPC_SUCCESS) { + if (CLNT_CALL(client, PMAPPROC_DUMP, (xdrproc_t)xdr_void, NULL, (xdrproc_t)xdr_pmaplist, &head, minutetimeout) != RPC_SUCCESS) { clnt_perror(client, "pmap_getmaps rpc problem"); } CLNT_DESTROY(client); diff --git a/rpc.subproj/pmap_getport.c b/rpc.subproj/pmap_getport.c index 2c33f72..2a09492 100644 --- a/rpc.subproj/pmap_getport.c +++ b/rpc.subproj/pmap_getport.c @@ -70,48 +70,75 @@ static char *rcsid = "$Id: pmap_getport.c,v 1.4 2004/12/19 22:45:44 zarzycki Exp #include #include -#include "pmap_wakeup.h" - -static struct timeval timeout = { 5, 0 }; -static struct timeval tottimeout = { 60, 0 }; +static struct timeval default_timeout = { 5, 0 }; +static struct timeval default_tottimeout = { 60, 0 }; /* * Find the mapped port for program,version. * Calls the pmap service remotely to do the lookup. * Returns 0 if no map exists. */ -u_short -pmap_getport(address, program, version, protocol) - struct sockaddr_in *address; - u_long program; - u_long version; - u_int protocol; +__private_extern__ u_short +pmap_getport_timeout(struct sockaddr_in *address, uint32_t program, uint32_t version, uint32_t protocol, struct timeval *timeout, struct timeval *totaltimeout) { - u_short port = 0; - int socket = -1; + u_short port; + int socket; register CLIENT *client; struct pmap parms; + enum clnt_stat status; + struct timeval real_t, real_tt; + + real_t = default_timeout; + if (timeout != NULL) real_t = *timeout; - pmap_wakeup(); + real_tt = default_timeout; + if (totaltimeout != NULL) real_tt = *totaltimeout; + port = 0; + socket = -1; address->sin_port = htons(PMAPPORT); - client = clntudp_bufcreate(address, PMAPPROG, - PMAPVERS, timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); - if (client != (CLIENT *)NULL) { + client = clntudp_bufcreate(address, PMAPPROG, PMAPVERS, real_t, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); + if (client != NULL) + { parms.pm_prog = program; parms.pm_vers = version; parms.pm_prot = protocol; - parms.pm_port = 0; /* not needed or used */ - if (CLNT_CALL(client, PMAPPROC_GETPORT, xdr_pmap, &parms, - xdr_u_short, &port, tottimeout) != RPC_SUCCESS){ + /* not needed or used */ + parms.pm_port = 0; + + status = CLNT_CALL(client, PMAPPROC_GETPORT, (xdrproc_t)xdr_pmap, &parms, (xdrproc_t)xdr_u_short, &port, real_tt); + if (status != RPC_SUCCESS) + { rpc_createerr.cf_stat = RPC_PMAPFAILURE; clnt_geterr(client, &rpc_createerr.cf_error); - } else if (port == 0) { + } + else if (port == 0) + { rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; } + CLNT_DESTROY(client); } - (void)close(socket); + + close(socket); address->sin_port = 0; - return (port); + return port; } + +u_short +pmap_getport(address, program, version, protocol) +#ifdef __LP64__ +struct sockaddr_in *address; +uint32_t program; +uint32_t version; +uint32_t protocol; +#else +struct sockaddr_in *address; +u_long program; +u_long version; +u_int protocol; +#endif +{ + return pmap_getport_timeout(address, (uint32_t)program, (uint32_t)version, (uint32_t)protocol, NULL, NULL); +} + diff --git a/rpc.subproj/pmap_prot.h b/rpc.subproj/pmap_prot.h index a51ce23..c5dc139 100644 --- a/rpc.subproj/pmap_prot.h +++ b/rpc.subproj/pmap_prot.h @@ -96,6 +96,18 @@ #include #define PMAPPORT ((unsigned short)111) +#ifdef __LP64__ +#define PMAPPROG ((unsigned int)100000) +#define PMAPVERS ((unsigned int)2) +#define PMAPVERS_PROTO ((unsigned int)2) +#define PMAPVERS_ORIG ((unsigned int)1) +#define PMAPPROC_NULL ((unsigned int)0) +#define PMAPPROC_SET ((unsigned int)1) +#define PMAPPROC_UNSET ((unsigned int)2) +#define PMAPPROC_GETPORT ((unsigned int)3) +#define PMAPPROC_DUMP ((unsigned int)4) +#define PMAPPROC_CALLIT ((unsigned int)5) +#else #define PMAPPROG ((unsigned long)100000) #define PMAPVERS ((unsigned long)2) #define PMAPVERS_PROTO ((unsigned long)2) @@ -106,12 +118,20 @@ #define PMAPPROC_GETPORT ((unsigned long)3) #define PMAPPROC_DUMP ((unsigned long)4) #define PMAPPROC_CALLIT ((unsigned long)5) +#endif struct pmap { +#ifdef __LP64__ + unsigned int pm_prog; + unsigned int pm_vers; + unsigned int pm_prot; + unsigned int pm_port; +#else long unsigned pm_prog; long unsigned pm_vers; long unsigned pm_prot; long unsigned pm_port; +#endif }; struct pmaplist { diff --git a/rpc.subproj/pmap_prot2.c b/rpc.subproj/pmap_prot2.c index a5bd77d..6c286c7 100644 --- a/rpc.subproj/pmap_prot2.c +++ b/rpc.subproj/pmap_prot2.c @@ -133,8 +133,7 @@ xdr_pmaplist(xdrs, rp) */ if (freeing) next = &((*rp)->pml_next); - if (! xdr_reference(xdrs, (caddr_t *)rp, - (u_int)sizeof(struct pmaplist), xdr_pmap)) + if (! xdr_reference(xdrs, (caddr_t *)rp, (u_int)sizeof(struct pmaplist), (xdrproc_t)xdr_pmap)) return (FALSE); rp = (freeing) ? next : &((*rp)->pml_next); } diff --git a/rpc.subproj/pmap_rmt.c b/rpc.subproj/pmap_rmt.c index a91b2a2..c9813ba 100644 --- a/rpc.subproj/pmap_rmt.c +++ b/rpc.subproj/pmap_rmt.c @@ -79,8 +79,6 @@ static char *rcsid = "$Id: pmap_rmt.c,v 1.6 2004/12/19 22:45:44 zarzycki Exp $"; #include #define MAX_BROADCAST_SIZE 1400 -#include "pmap_wakeup.h" - static struct timeval timeout = { 3, 0 }; @@ -93,12 +91,21 @@ static struct timeval timeout = { 3, 0 }; */ enum clnt_stat pmap_rmtcall(addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout, port_ptr) +#ifdef __LP64__ + struct sockaddr_in *addr; + uint32_t prog, vers, proc; + xdrproc_t xdrargs, xdrres; + caddr_t argsp, resp; + struct timeval tout; + uint32_t *port_ptr; +#else struct sockaddr_in *addr; u_long prog, vers, proc; xdrproc_t xdrargs, xdrres; caddr_t argsp, resp; struct timeval tout; u_long *port_ptr; +#endif { int socket = -1; register CLIENT *client; @@ -106,8 +113,6 @@ pmap_rmtcall(addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout, port_pt struct rmtcallres r; enum clnt_stat stat; - pmap_wakeup(); - addr->sin_port = htons(PMAPPORT); client = clntudp_create(addr, PMAPPROG, PMAPVERS, timeout, &socket); if (client != (CLIENT *)NULL) { @@ -119,8 +124,7 @@ pmap_rmtcall(addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout, port_pt r.port_ptr = port_ptr; r.results_ptr = resp; r.xdr_results = xdrres; - stat = CLNT_CALL(client, PMAPPROC_CALLIT, xdr_rmtcall_args, &a, - xdr_rmtcallres, &r, tout); + stat = CLNT_CALL(client, PMAPPROC_CALLIT, (xdrproc_t)xdr_rmtcall_args, &a, (xdrproc_t)xdr_rmtcallres, &r, tout); CLNT_DESTROY(client); } else { stat = RPC_FAILED; @@ -174,9 +178,12 @@ xdr_rmtcallres(xdrs, crp) caddr_t port_ptr; port_ptr = (caddr_t)crp->port_ptr; - if (xdr_reference(xdrs, &port_ptr, sizeof (u_long), - xdr_u_long) && xdr_u_long(xdrs, &crp->resultslen)) { - crp->port_ptr = (u_long *)port_ptr; + if (xdr_reference(xdrs, &port_ptr, sizeof (u_long), (xdrproc_t)xdr_u_long) && xdr_u_long(xdrs, &crp->resultslen)) { +#ifdef __LP64__ + crp->port_ptr = (unsigned int *)port_ptr; +#else + crp->port_ptr = (unsigned long *)port_ptr; +#endif return ((*(crp->xdr_results))(xdrs, crp->results_ptr)); } return (FALSE); @@ -245,6 +252,16 @@ typedef bool_t (*resultproc_t)(); enum clnt_stat clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult) +#ifdef __LP64__ + uint32_t prog; /* program number */ + uint32_t vers; /* version number */ + uint32_t proc; /* procedure number */ + xdrproc_t xargs; /* xdr routine for args */ + caddr_t argsp; /* pointer to args */ + xdrproc_t xresults; /* xdr routine for results */ + caddr_t resultsp; /* pointer to results */ + resultproc_t eachresult; /* call with each result obtained */ +#else u_long prog; /* program number */ u_long vers; /* version number */ u_long proc; /* procedure number */ @@ -253,20 +270,26 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult) xdrproc_t xresults; /* xdr routine for results */ caddr_t resultsp; /* pointer to results */ resultproc_t eachresult; /* call with each result obtained */ +#endif { enum clnt_stat stat; AUTH *unix_auth = authunix_create_default(); XDR xdr_stream; register XDR *xdrs = &xdr_stream; - int outlen, inlen, fromlen, nets; + int outlen, inlen, nets; + unsigned int fromlen; register int sock; int on = 1; fd_set mask; fd_set readfds; register int i; bool_t done = FALSE; - u_long xid; - u_long port; + uint32_t xid; +#ifdef __LP64__ + unsigned int port; +#else + unsigned long port; +#endif struct in_addr addrs[20]; struct sockaddr_in baddr, raddr; /* broadcast and response addresses */ struct rmtcallargs a; @@ -276,6 +299,8 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult) char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE]; int rfd; + stat = RPC_SUCCESS; + /* * initialization: create a socket, a broadcast address, and * preserialize the arguments into a send buffer. @@ -355,7 +380,7 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult) recv_again: msg.acpted_rply.ar_verf = _null_auth; msg.acpted_rply.ar_results.where = (caddr_t)&r; - msg.acpted_rply.ar_results.proc = xdr_rmtcallres; + msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_rmtcallres; readfds = mask; switch (select(sock+1, &readfds, NULL, NULL, &t)) { @@ -373,8 +398,7 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult) } /* end of select results switch */ try_again: fromlen = sizeof(struct sockaddr); - inlen = recvfrom(sock, inbuf, UDPMSGSIZE, 0, - (struct sockaddr *)&raddr, &fromlen); + inlen = recvfrom(sock, inbuf, UDPMSGSIZE, 0, (struct sockaddr *)&raddr, &fromlen); if (inlen < 0) { if (errno == EINTR) goto try_again; @@ -406,7 +430,7 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult) #endif } xdrs->x_op = XDR_FREE; - msg.acpted_rply.ar_results.proc = xdr_void; + msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void; (void)xdr_replymsg(xdrs, &msg); (void)(*xresults)(xdrs, resultsp); xdr_destroy(xdrs); diff --git a/rpc.subproj/pmap_rmt.h b/rpc.subproj/pmap_rmt.h index a768d46..9ffbd1c 100644 --- a/rpc.subproj/pmap_rmt.h +++ b/rpc.subproj/pmap_rmt.h @@ -66,14 +66,23 @@ #include struct rmtcallargs { +#ifdef __LP64__ + unsigned int prog, vers, proc, arglen; +#else unsigned long prog, vers, proc, arglen; +#endif caddr_t args_ptr; xdrproc_t xdr_args; }; struct rmtcallres { +#ifdef __LP64__ + unsigned int *port_ptr; + unsigned int resultslen; +#else unsigned long *port_ptr; unsigned long resultslen; +#endif caddr_t results_ptr; xdrproc_t xdr_results; }; diff --git a/rpc.subproj/pmap_wakeup.c b/rpc.subproj/pmap_wakeup.c index 4d302e6..920ae86 100644 --- a/rpc.subproj/pmap_wakeup.c +++ b/rpc.subproj/pmap_wakeup.c @@ -6,7 +6,7 @@ #include "pmap_wakeup.h" -void pmap_wakeup(void) +int pmap_wakeup(void) { struct sockaddr_un sun; int fd; @@ -19,13 +19,14 @@ void pmap_wakeup(void) fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd == -1) - return; + return -1; if (connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) { close(fd); - return; + return -1; } read(fd, &b, sizeof(b)); close(fd); + return 0; } diff --git a/rpc.subproj/pmap_wakeup.h b/rpc.subproj/pmap_wakeup.h index b5dda38..4cab42b 100644 --- a/rpc.subproj/pmap_wakeup.h +++ b/rpc.subproj/pmap_wakeup.h @@ -1,6 +1,6 @@ #ifndef __PMAP_WAKEUP_H__ #define __PMAP_WAKEUP_H__ -void pmap_wakeup(void); +int pmap_wakeup(void); #endif diff --git a/rpc.subproj/rpc.3 b/rpc.subproj/rpc.3 new file mode 100644 index 0000000..767fe74 --- /dev/null +++ b/rpc.subproj/rpc.3 @@ -0,0 +1,1731 @@ +.\" from: @(#)rpc.3n 2.4 88/08/08 4.0 RPCSRC; from 1.19 88/06/24 SMI +.\" $Id: rpc.3,v 1.1 1999/04/13 23:15:37 wsanchez Exp $ +.\" +.TH RPC 3N "16 February 1988" +.SH NAME +rpc \- library routines for remote procedure calls +.SH SYNOPSIS AND DESCRIPTION +These routines allow C programs to make procedure +calls on other machines across the network. +First, the client calls a procedure to send a +data packet to the server. +Upon receipt of the packet, the server calls a dispatch routine +to perform the requested service, and then sends back a +reply. +Finally, the procedure call returns to the client. +.LP +Routines that are used for Secure RPC (DES authentication) are described in +.BR rpc_secure (3N). +Secure RPC can be used only if DES encryption is available. +.LP +.ft B +.nf +.sp .5 +#include +.fi +.ft R +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +void +auth_destroy(auth) +\s-1AUTH\s0 *auth; +.fi +.ft R +.IP +A macro that destroys the authentication information associated with +.IR auth . +Destruction usually involves deallocation of private data +structures. The use of +.I auth +is undefined after calling +.BR auth_destroy(\|) . +.br +.if t .ne 6 +.LP +.ft B +.nf +.sp .5 +\s-1AUTH\s0 * +authnone_create(\|) +.fi +.ft R +.IP +Create and returns an +.SM RPC +authentication handle that passes nonusable authentication +information with each remote procedure call. This is the +default authentication used by +.SM RPC. +.if t .ne 10 +.LP +.ft B +.nf +.sp .5 +\s-1AUTH\s0 * +authunix_create(host, uid, gid, len, aup_gids) +char *host; +int uid, gid, len, *aup.gids; +.fi +.ft R +.IP +Create and return an +.SM RPC +authentication handle that contains +.UX +authentication information. +The parameter +.I host +is the name of the machine on which the information was +created; +.I uid +is the user's user +.SM ID ; +.I gid +is the user's current group +.SM ID ; +.I len +and +.I aup_gids +refer to a counted array of groups to which the user belongs. +It is easy to impersonate a user. +.br +.if t .ne 5 +.LP +.ft B +.nf +.sp .5 +\s-1AUTH\s0 * +authunix_create_default(\|) +.fi +.ft R +.IP +Calls +.B authunix_create(\|) +with the appropriate parameters. +.br +.if t .ne 13 +.LP +.ft B +.nf +.sp .5 +callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out) +char *host; +u_long prognum, versnum, procnum; +char *in, *out; +xdrproc_t inproc, outproc; +.fi +.ft R +.IP +Call the remote procedure associated with +.IR prognum , +.IR versnum , +and +.I procnum +on the machine, +.IR host . +The parameter +.I in +is the address of the procedure's argument(s), and +.I out +is the address of where to place the result(s); +.I inproc +is used to encode the procedure's parameters, and +.I outproc +is used to decode the procedure's results. +This routine returns zero if it succeeds, or the value of +.B "enum clnt_stat" +cast to an integer if it fails. +The routine +.B clnt_perrno(\|) +is handy for translating failure statuses into messages. +.IP +Warning: calling remote procedures with this routine +uses +.SM UDP/IP +as a transport; see +.B clntudp_create(\|) +for restrictions. +You do not have control of timeouts or authentication using +this routine. +.br +.if t .ne 16 +.LP +.ft B +.nf +.sp .5 +enum clnt_stat +clnt_broadcast(prognum, versnum, procnum, inproc, in, outproc, out, eachresult) +u_long prognum, versnum, procnum; +char *in, *out; +xdrproc_t inproc, outproc; +resultproc_t eachresult; +.fi +.ft R +.IP +Like +.BR callrpc(\|) , +except the call message is broadcast to all locally +connected broadcast nets. Each time it receives a +response, this routine calls +.BR eachresult(\|) , +whose form is: +.IP +.RS 1i +.ft B +.nf +eachresult(out, addr) +char *out; +struct sockaddr_in *addr; +.ft R +.fi +.RE +.IP +where +.I out +is the same as +.I out +passed to +.BR clnt_broadcast(\|) , +except that the remote procedure's output is decoded there; +.I addr +points to the address of the machine that sent the results. +If +.B eachresult(\|) +returns zero, +.B clnt_broadcast(\|) +waits for more replies; otherwise it returns with appropriate +status. +.IP +Warning: broadcast sockets are limited in size to the +maximum transfer unit of the data link. For ethernet, +this value is 1500 bytes. +.br +.if t .ne 13 +.LP +.ft B +.nf +.sp .5 +enum clnt_stat +clnt_call(clnt, procnum, inproc, in, outproc, out, tout) +\s-1CLIENT\s0 *clnt; +u_long +procnum; +xdrproc_t inproc, outproc; +char *in, *out; +struct timeval tout; +.fi +.ft R +.IP +A macro that calls the remote procedure +.I procnum +associated with the client handle, +.IR clnt , +which is obtained with an +.SM RPC +client creation routine such as +.BR clnt_create(\|) . +The parameter +.I in +is the address of the procedure's argument(s), and +.I out +is the address of where to place the result(s); +.I inproc +is used to encode the procedure's parameters, and +.I outproc +is used to decode the procedure's results; +.I tout +is the time allowed for results to come back. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +clnt_destroy(clnt) +\s-1CLIENT\s0 *clnt; +.fi +.ft R +.IP +A macro that destroys the client's +.SM RPC +handle. Destruction usually involves deallocation +of private data structures, including +.I clnt +itself. Use of +.I clnt +is undefined after calling +.BR clnt_destroy(\|) . +If the +.SM RPC +library opened the associated socket, it will close it also. +Otherwise, the socket remains open. +.br +.if t .ne 10 +.LP +.ft B +.nf +.sp .5 +\s-1CLIENT\s0 * +clnt_create(host, prog, vers, proto) +char *host; +u_long prog, vers; +char *proto; +.fi +.ft R +.IP +Generic client creation routine. +.I host +identifies the name of the remote host where the server +is located. +.I proto +indicates which kind of transport protocol to use. The +currently supported values for this field are \(lqudp\(rq +and \(lqtcp\(rq. +Default timeouts are set, but can be modified using +.BR clnt_control(\|) . +.IP +Warning: Using +.SM UDP +has its shortcomings. Since +.SM UDP\s0-based +.SM RPC +messages can only hold up to 8 Kbytes of encoded data, +this transport cannot be used for procedures that take +large arguments or return huge results. +.br +.if t .ne 10 +.LP +.ft B +.nf +.sp .5 +bool_t +clnt_control(cl, req, info) +\s-1CLIENT\s0 *cl; +char *info; +.fi +.ft R +.IP +A macro used to change or retrieve various information +about a client object. +.I req +indicates the type of operation, and +.I info +is a pointer to the information. For both +.SM UDP +and +.SM TCP\s0, +the supported values of +.I req +and their argument types and what they do are: +.IP +.nf +.ta +2.0i +2.0i +2.0i +.SM CLSET_TIMEOUT\s0 struct timeval set total timeout +.SM CLGET_TIMEOUT\s0 struct timeval get total timeout +.fi +.IP +Note: if you set the timeout using +.BR clnt_control(\|) , +the timeout parameter passed to +.B clnt_call(\|) +will be ignored in all future calls. +.IP +.nf +.SM CLGET_SERVER_ADDR\s0 struct sockaddr_in get server's address +.fi +.br +.IP +The following operations are valid for +.SM UDP +only: +.IP +.nf +.ta +2.0i +2.0i +2.0i +.SM CLSET_RETRY_TIMEOUT\s0 struct timeval set the retry timeout +.SM CLGET_RETRY_TIMEOUT\s0 struct timeval get the retry timeout +.fi +.br +.IP +The retry timeout is the time that +.SM "UDP RPC" +waits for the server to reply before +retransmitting the request. +.br +.if t .ne 10 +.LP +.ft B +.nf +.sp .5 +clnt_freeres(clnt, outproc, out) +\s-1CLIENT\s0 *clnt; +xdrproc_t outproc; +char *out; +.fi +.ft R +.IP +A macro that frees any data allocated by the +.SM RPC/XDR +system when it decoded the results of an +.SM RPC +call. The +parameter +.I out +is the address of the results, and +.I outproc +is the +.SM XDR +routine describing the results. +This routine returns one if the results were successfully +freed, +and zero otherwise. +.br +.if t .ne 6 +.LP +.ft B +.nf +.sp .5 +void +clnt_geterr(clnt, errp) +\s-1CLIENT\s0 *clnt; +struct rpc_err *errp; +.fi +.ft R +.IP +A macro that copies the error structure out of the client +handle +to the structure at address +.IR errp . +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +void +clnt_pcreateerror(s) +char *s; +.fi +.ft R +.IP +Print a message to standard error indicating +why a client +.SM RPC +handle could not be created. +The message is prepended with string +.I s +and a colon. +Used when a +.BR clnt_create(\|) , +.BR clntraw_create(\|) , +.BR clnttcp_create(\|) , +or +.B clntudp_create(\|) +call fails. +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +void +clnt_perrno(stat) +enum clnt_stat stat; +.fi +.ft R +.IP +Print a message to standard error corresponding +to the condition indicated by +.IR stat . +Used after +.BR callrpc(\|) . +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +clnt_perror(clnt, s) +\s-1CLIENT\s0 *clnt; +char *s; +.fi +.ft R +.IP +Print a message to standard error indicating why an +.SM RPC +call failed; +.I clnt +is the handle used to do the call. +The message is prepended with string +.I s +and a colon. +Used after +.BR clnt_call(\|) . +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +char * +clnt_spcreateerror +char *s; +.fi +.ft R +.IP +Like +.BR clnt_pcreateerror(\|) , +except that it returns a string +instead of printing to the standard error. +.IP +Bugs: returns pointer to static data that is overwritten +on each call. +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +char * +clnt_sperrno(stat) +enum clnt_stat stat; +.fi +.ft R +.IP +Take the same arguments as +.BR clnt_perrno(\|) , +but instead of sending a message to the standard error +indicating why an +.SM RPC +call failed, return a pointer to a string which contains +the message. The string ends with a +.SM NEWLINE\s0. +.IP +.B clnt_sperrno(\|) +is used instead of +.B clnt_perrno(\|) +if the program does not have a standard error (as a program +running as a server quite likely does not), or if the +programmer +does not want the message to be output with +.BR printf , +or if a message format different than that supported by +.B clnt_perrno(\|) +is to be used. +Note: unlike +.B clnt_sperror(\|) +and +.BR clnt_spcreaterror(\|) , +.B clnt_sperrno(\|) +returns pointer to static data, but the +result will not get overwritten on each call. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +char * +clnt_sperror(rpch, s) +\s-1CLIENT\s0 *rpch; +char *s; +.fi +.ft R +.IP +Like +.BR clnt_perror(\|) , +except that (like +.BR clnt_sperrno(\|) ) +it returns a string instead of printing to standard error. +.IP +Bugs: returns pointer to static data that is overwritten +on each call. +.br +.if t .ne 10 +.LP +.ft B +.nf +.sp .5 +\s-1CLIENT\s0 * +clntraw_create(prognum, versnum) +u_long prognum, versnum; +.fi +.ft R +.IP +This routine creates a toy +.SM RPC +client for the remote program +.IR prognum , +version +.IR versnum . +The transport used to pass messages to the service is +actually a buffer within the process's address space, so the +corresponding +.SM RPC +server should live in the same address space; see +.BR svcraw_create(\|) . +This allows simulation of +.SM RPC +and acquisition of +.SM RPC +overheads, such as round trip times, without any +kernel interference. This routine returns +.SM NULL +if it fails. +.br +.if t .ne 15 +.LP +.ft B +.nf +.sp .5 +\s-1CLIENT\s0 * +clnttcp_create(addr, prognum, versnum, sockp, sendsz, recvsz) +struct sockaddr_in *addr; +u_long prognum, versnum; +int *sockp; +u_int sendsz, recvsz; +.fi +.ft R +.IP +This routine creates an +.SM RPC +client for the remote program +.IR prognum , +version +.IR versnum ; +the client uses +.SM TCP/IP +as a transport. The remote program is located at Internet +address +.IR *addr . +If +.\"The following in-line font conversion is necessary for the hyphen indicator +\fB\%addr\->sin_port\fR +is zero, then it is set to the actual port that the remote +program is listening on (the remote +.B portmap +service is consulted for this information). The parameter +.I sockp +is a socket; if it is +.BR \s-1RPC_ANYSOCK\s0 , +then this routine opens a new one and sets +.IR sockp . +Since +.SM TCP\s0-based +.SM RPC +uses buffered +.SM I/O , +the user may specify the size of the send and receive buffers +with the parameters +.I sendsz +and +.IR recvsz ; +values of zero choose suitable defaults. +This routine returns +.SM NULL +if it fails. +.br +.if t .ne 15 +.LP +.ft B +.nf +.sp .5 +\s-1CLIENT\s0 * +clntudp_create(addr, prognum, versnum, wait, sockp) +struct sockaddr_in *addr; +u_long prognum, versnum; +struct timeval wait; +int *sockp; +.fi +.ft R +.IP +This routine creates an +.SM RPC +client for the remote program +.IR prognum , +version +.IR versnum ; +the client uses use +.SM UDP/IP +as a transport. The remote program is located at Internet +address +.IR addr . +If +\fB\%addr\->sin_port\fR +is zero, then it is set to actual port that the remote +program is listening on (the remote +.B portmap +service is consulted for this information). The parameter +.I sockp +is a socket; if it is +.BR \s-1RPC_ANYSOCK\s0 , +then this routine opens a new one and sets +.IR sockp . +The +.SM UDP +transport resends the call message in intervals of +.B wait +time until a response is received or until the call times +out. +The total time for the call to time out is specified by +.BR clnt_call(\|) . +.IP +Warning: since +.SM UDP\s0-based +.SM RPC +messages can only hold up to 8 Kbytes +of encoded data, this transport cannot be used for procedures +that take large arguments or return huge results. +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +\s-1CLIENT\s0 * +clntudp_bufcreate(addr, prognum, versnum, wait, sockp, sendsize, recosize) +struct sockaddr_in *addr; +u_long prognum, versnum; +struct timeval wait; +int *sockp; +unsigned int sendsize; +unsigned int recosize; +.fi +.ft R +.IP +This routine creates an +.SM RPC +client for the remote program +.IR prognum , +on +.IR versnum ; +the client uses use +.SM UDP/IP +as a transport. The remote program is located at Internet +address +.IR addr . +If +\fB\%addr\->sin_port\fR +is zero, then it is set to actual port that the remote +program is listening on (the remote +.B portmap +service is consulted for this information). The parameter +.I sockp +is a socket; if it is +.BR \s-1RPC_ANYSOCK\s0 , +then this routine opens a new one and sets +.BR sockp . +The +.SM UDP +transport resends the call message in intervals of +.B wait +time until a response is received or until the call times +out. +The total time for the call to time out is specified by +.BR clnt_call(\|) . +.IP +This allows the user to specify the maximun packet size for sending and receiving +.SM UDP\s0-based +.SM RPC +messages. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +void +get_myaddress(addr) +struct sockaddr_in *addr; +.fi +.ft R +.IP +Stuff the machine's +.SM IP +address into +.IR *addr , +without consulting the library routines that deal with +.BR /etc/hosts . +The port number is always set to +.BR htons(\s-1PMAPPORT\s0) . +.br +.if t .ne 10 +.LP +.ft B +.nf +.sp .5 +struct pmaplist * +pmap_getmaps(addr) +struct sockaddr_in *addr; +.fi +.ft R +.IP +A user interface to the +.B portmap +service, which returns a list of the current +.SM RPC +program-to-port mappings +on the host located at +.SM IP +address +.IR *addr . +This routine can return +.SM NULL . +The command +.RB ` "rpcinfo \-p" ' +uses this routine. +.br +.if t .ne 12 +.LP +.ft B +.nf +.sp .5 +u_short +pmap_getport(addr, prognum, versnum, protocol) +struct sockaddr_in *addr; +u_long prognum, versnum, protocol; +.fi +.ft R +.IP +A user interface to the +.B portmap +service, which returns the port number +on which waits a service that supports program number +.IR prognum , +version +.IR versnum , +and speaks the transport protocol associated with +.IR protocol . +The value of +.I protocol +is most likely +.B +.SM IPPROTO_UDP +or +.BR \s-1IPPROTO_TCP\s0 . +A return value of zero means that the mapping does not exist +or that +the +.SM RPC +system failured to contact the remote +.B portmap +service. In the latter case, the global variable +.B rpc_createerr(\|) +contains the +.SM RPC +status. +.br +.if t .ne 15 +.LP +.ft B +.nf +.sp .5 +enum clnt_stat +pmap_rmtcall(addr, prognum, versnum, procnum, inproc, in, outproc, out, tout, portp) +struct sockaddr_in *addr; +u_long prognum, versnum, procnum; +char *in, *out; +xdrproc_t inproc, outproc; +struct timeval tout; +u_long *portp; +.fi +.ft R +.IP +A user interface to the +.B portmap +service, which instructs +.B portmap +on the host at +.SM IP +address +.I *addr +to make an +.SM RPC +call on your behalf to a procedure on that host. +The parameter +.I *portp +will be modified to the program's port number if the +procedure +succeeds. The definitions of other parameters are discussed +in +.B callrpc(\|) +and +.BR clnt_call(\|) . +This procedure should be used for a \(lqping\(rq and nothing +else. +See also +.BR clnt_broadcast(\|) . +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +pmap_set(prognum, versnum, protocol, port) +u_long prognum, versnum, protocol; +u_short port; +.fi +.ft R +.IP +A user interface to the +.B portmap +service, which establishes a mapping between the triple +.RI [ prognum , versnum , protocol\fR] +and +.I port +on the machine's +.B portmap +service. The value of +.I protocol +is most likely +.B +.SM IPPROTO_UDP +or +.BR \s-1IPPROTO_TCP\s0 . +This routine returns one if it succeeds, zero otherwise. +Automatically done by +.BR svc_register(\|) . +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +pmap_unset(prognum, versnum) +u_long prognum, versnum; +.fi +.ft R +.IP +A user interface to the +.B portmap +service, which destroys all mapping between the triple +.RI [ prognum , versnum , *\fR] +and +.B ports +on the machine's +.B portmap +service. This routine returns one if it succeeds, zero +otherwise. +.br +.if t .ne 15 +.LP +.ft B +.nf +.sp .5 +registerrpc(prognum, versnum, procnum, procname, inproc, outproc) +u_long prognum, versnum, procnum; +char *(*procname) (\|) ; +xdrproc_t inproc, outproc; +.fi +.ft R +.IP +Register procedure +.I procname +with the +.SM RPC +service package. If a request arrives for program +.IR prognum , +version +.IR versnum , +and procedure +.IR procnum , +.I procname +is called with a pointer to its parameter(s); +.I progname +should return a pointer to its static result(s); +.I inproc +is used to decode the parameters while +.I outproc +is used to encode the results. +This routine returns zero if the registration succeeded, \-1 +otherwise. +.IP +Warning: remote procedures registered in this form +are accessed using the +.SM UDP/IP +transport; see +.B svcudp_create(\|) +for restrictions. +.br +.if t .ne 5 +.LP +.ft B +.nf +.sp .5 +struct rpc_createerr rpc_createerr; +.fi +.ft R +.IP +A global variable whose value is set by any +.SM RPC +client creation routine +that does not succeed. Use the routine +.B clnt_pcreateerror(\|) +to print the reason why. +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +svc_destroy(xprt) +\s-1SVCXPRT\s0 * +xprt; +.fi +.ft R +.IP +A macro that destroys the +.SM RPC +service transport handle, +.IR xprt . +Destruction usually involves deallocation +of private data structures, including +.I xprt +itself. Use of +.I xprt +is undefined after calling this routine. +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +fd_set svc_fdset; +.fi +.ft R +.IP +A global variable reflecting the +.SM RPC +service side's +read file descriptor bit mask; it is suitable as a parameter +to the +.B select +system call. This is only of interest +if a service implementor does not call +.BR svc_run(\|) , +but rather does his own asynchronous event processing. +This variable is read-only (do not pass its address to +.BR select !), +yet it may change after calls to +.B svc_getreqset(\|) +or any creation routines. +.br +.if t .ne 6 +.LP +.ft B +.nf +.sp .5 +int svc_fds; +.fi +.ft R +.IP +Similar to +.BR svc_fedset(\|) , +but limited to 32 descriptors. This +interface is obsoleted by +.BR svc_fdset(\|) . +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +svc_freeargs(xprt, inproc, in) +\s-1SVCXPRT\s0 *xprt; +xdrproc_t inproc; +char *in; +.fi +.ft R +.IP +A macro that frees any data allocated by the +.SM RPC/XDR +system when it decoded the arguments to a service procedure +using +.BR svc_getargs(\|) . +This routine returns 1 if the results were successfully +freed, +and zero otherwise. +.br +.if t .ne 10 +.LP +.ft B +.nf +.sp .5 +svc_getargs(xprt, inproc, in) +\s-1SVCXPRT\s0 *xprt; +xdrproc_t inproc; +char *in; +.fi +.ft R +.IP +A macro that decodes the arguments of an +.SM RPC +request +associated with the +.SM RPC +service transport handle, +.IR xprt . +The parameter +.I in +is the address where the arguments will be placed; +.I inproc +is the +.SM XDR +routine used to decode the arguments. +This routine returns one if decoding succeeds, and zero +otherwise. +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +struct sockaddr_in * +svc_getcaller(xprt) +\s-1SVCXPRT\s0 *xprt; +.fi +.ft R +.IP +The approved way of getting the network address of the caller +of a procedure associated with the +.SM RPC +service transport handle, +.IR xprt . +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +svc_getreqset(rdfds) +fd_set *rdfds; +.fi +.ft R +.IP +This routine is only of interest if a service implementor +does not call +.BR svc_run(\|) , +but instead implements custom asynchronous event processing. +It is called when the +.B select +system call has determined that an +.SM RPC +request has arrived on some +.SM RPC +.B socket(s) ; +.I rdfds +is the resultant read file descriptor bit mask. +The routine returns when all sockets associated with the +value of +.I rdfds +have been serviced. +.br +.if t .ne 6 +.LP +.ft B +.nf +.sp .5 +svc_getreq(rdfds) +int rdfds; +.fi +.ft R +.IP +Similar to +.BR svc_getreqset(\|) , +but limited to 32 descriptors. This interface is obsoleted by +.BR svc_getreqset(\|) . +.br +.if t .ne 17 +.LP +.ft B +.nf +.sp .5 +svc_register(xprt, prognum, versnum, dispatch, protocol) +\s-1SVCXPRT\s0 *xprt; +u_long prognum, versnum; +void (*dispatch) (\|); +u_long protocol; +.fi +.ft R +.IP +Associates +.I prognum +and +.I versnum +with the service dispatch procedure, +.IR dispatch . +If +.I protocol +is zero, the service is not registered with the +.B portmap +service. If +.I protocol +is non-zero, then a mapping of the triple +.RI [ prognum , versnum , protocol\fR] +to +\fB\%xprt\->xp_port\fR +is established with the local +.B portmap +service (generally +.I protocol +is zero, +.B +.SM IPPROTO_UDP +or +.B +.SM IPPROTO_TCP +). +The procedure +.I dispatch +has the following form: +.RS 1i +.ft B +.nf +dispatch(request, xprt) +struct svc_req *request; +\s-1SVCXPRT\s0 *xprt; +.ft R +.fi +.RE +.IP +The +.B svc_register(\|) +routine returns one if it succeeds, and zero otherwise. +.br +.if t .ne 6 +.LP +.ft B +.nf +.sp .5 +svc_run(\|) +.fi +.ft R +.IP +This routine never returns. It waits for +.SM RPC +requests to arrive, and calls the appropriate service +procedure using +.B svc_getreq(\|) +when one arrives. This procedure is usually waiting for a +.B select(\|) +system call to return. +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +svc_sendreply(xprt, outproc, out) +\s-1SVCXPRT\s0 *xprt; +xdrproc_t outproc; +char *out; +.fi +.ft R +.IP +Called by an +.SM RPC +service's dispatch routine to send the results of a +remote procedure call. The parameter +.I xprt +is the request's associated transport handle; +.I outproc +is the +.SM XDR +routine which is used to encode the results; and +.I out +is the address of the results. +This routine returns one if it succeeds, zero otherwise. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +void +svc_unregister(prognum, versnum) +u_long prognum, versnum; +.fi +.ft R +.IP +Remove all mapping of the double +.RI [ prognum , versnum ] +to dispatch routines, and of the triple +.RI [ prognum , versnum , *\fR] +to port number. +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +void +svcerr_auth(xprt, why) +\s-1SVCXPRT\s0 *xprt; +enum auth_stat why; +.fi +.ft R +.IP +Called by a service dispatch routine that refuses to perform +a remote procedure call due to an authentication error. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +void +svcerr_decode(xprt) +\s-1SVCXPRT\s0 *xprt; +.fi +.ft R +.IP +Called by a service dispatch routine that cannot successfully +decode its parameters. See also +.BR svc_getargs(\|) . +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +void +svcerr_noproc(xprt) +\s-1SVCXPRT\s0 *xprt; +.fi +.ft R +.IP +Called by a service dispatch routine that does not implement +the procedure number that the caller requests. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +void +svcerr_noprog(xprt) +\s-1SVCXPRT\s0 *xprt; +.fi +.ft R +.IP +Called when the desired program is not registered with the +.SM RPC +package. Service implementors usually do not need this routine. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +void +svcerr_progvers(xprt) +\s-1SVCXPRT\s0 *xprt; +.fi +.ft R +.IP +Called when the desired version of a program is not registered +with the +.SM RPC +package. Service implementors usually do not need this routine. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +void +svcerr_systemerr(xprt) +\s-1SVCXPRT\s0 *xprt; +.fi +.ft R +.IP +Called by a service dispatch routine when it detects a system +error +not covered by any particular protocol. +For example, if a service can no longer allocate storage, +it may call this routine. +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +void +svcerr_weakauth(xprt) +\s-1SVCXPRT\s0 *xprt; +.fi +.ft R +.IP +Called by a service dispatch routine that refuses to perform +a remote procedure call due to insufficient +authentication parameters. The routine calls +.BR "svcerr_auth(xprt, \s-1AUTH_TOOWEAK\s0)" . +.br +.if t .ne 11 +.LP +.ft B +.nf +.sp .5 +\s-1SVCXPRT\s0 * +svcraw_create(\|) +.fi +.ft R +.IP +This routine creates a toy +.SM RPC +service transport, to which it returns a pointer. The +transport +is really a buffer within the process's address space, +so the corresponding +.SM RPC +client should live in the same +address space; +see +.BR clntraw_create(\|) . +This routine allows simulation of +.SM RPC +and acquisition of +.SM RPC +overheads (such as round trip times), without any kernel +interference. +This routine returns +.SM NULL +if it fails. +.br +.if t .ne 11 +.LP +.ft B +.nf +.sp .5 +\s-1SVCXPRT\s0 * +svctcp_create(sock, send_buf_size, recv_buf_size) +int sock; +u_int send_buf_size, recv_buf_size; +.fi +.ft R +.IP +This routine creates a +.SM TCP/IP\s0-based +.SM RPC +service transport, to which it returns a pointer. +The transport is associated with the socket +.IR sock , +which may be +.BR \s-1RPC_ANYSOCK\s0 , +in which case a new socket is created. +If the socket is not bound to a local +.SM TCP +port, then this routine binds it to an arbitrary port. Upon +completion, +\fB\%xprt\->xp_sock\fR +is the transport's socket descriptor, and +\fB\%xprt\->xp_port\fR +is the transport's port number. +This routine returns +.SM NULL +if it fails. Since +.SM TCP\s0-based +.SM RPC +uses buffered +.SM I/O , +users may specify the size of buffers; values of zero +choose suitable defaults. +.br +.if t .ne 11 +.LP +.ft B +.nf +.sp .5 +\s-1SVCXPRT\s0 * +svcfd_create(fd, sendsize, recvsize) +int fd; +u_int sendsize; +u_int recvsize; +.fi +.ft R +.IP +Create a service on top of any open descriptor. Typically, +this +descriptor is a connected socket for a stream protocol such +as +.SM TCP\s0. +.I sendsize +and +.I recvsize +indicate sizes for the send and receive buffers. If they are +zero, a reasonable default is chosen. +.br +.if t .ne 10 +.LP +.ft B +.nf +.sp .5 +\s-1SVCXPRT\s0 * +svcudp_bufcreate(sock, sendsize, recosize) +int sock; +.fi +.ft R +.IP +This routine creates a +.SM UDP/IP\s0-based +.SM RPC +service transport, to which it returns a pointer. +The transport is associated with the socket +.IR sock , +which may be +.B \s-1RPC_ANYSOCK\s0 , +in which case a new socket is created. +If the socket is not bound to a local +.SM UDP +port, then this routine binds it to an arbitrary port. Upon +completion, +\fB\%xprt\->xp_sock\fR +is the transport's socket descriptor, and +\fB\%xprt\->xp_port\fR +is the transport's port number. +This routine returns +.SM NULL +if it fails. +.IP +This allows the user to specify the maximun packet size for sending and +receiving +.SM UDP\s0-based +.SM RPC messages. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +xdr_accepted_reply(xdrs, ar) +\s-1XDR\s0 *xdrs; +struct accepted_reply *ar; +.fi +.ft R +.IP +Used for encoding +.SM RPC +reply messages. This routine is useful for users who +wish to generate +\s-1RPC\s0-style +messages without using the +.SM RPC +package. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +xdr_authunix_parms(xdrs, aupp) +\s-1XDR\s0 *xdrs; +struct authunix_parms *aupp; +.fi +.ft R +.IP +Used for describing +.SM UNIX +credentials. This routine is useful for users +who wish to generate these credentials without using the +.SM RPC +authentication package. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +void +xdr_callhdr(xdrs, chdr) +\s-1XDR\s0 *xdrs; +struct rpc_msg *chdr; +.fi +.ft R +.IP +Used for describing +.SM RPC +call header messages. +This routine is useful for users who wish to generate +.SM RPC\s0-style +messages without using the +.SM RPC +package. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +xdr_callmsg(xdrs, cmsg) +\s-1XDR\s0 *xdrs; +struct rpc_msg *cmsg; +.fi +.ft R +.IP +Used for describing +.SM RPC +call messages. +This routine is useful for users who wish to generate +.SM RPC\s0-style +messages without using the +.SM RPC +package. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +xdr_opaque_auth(xdrs, ap) +\s-1XDR\s0 *xdrs; +struct opaque_auth *ap; +.fi +.ft R +.IP +Used for describing +.SM RPC +authentication information messages. +This routine is useful for users who wish to generate +.SM RPC\s0-style +messages without using the +.SM RPC +package. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +xdr_pmap(xdrs, regs) +\s-1XDR\s0 *xdrs; +struct pmap *regs; +.fi +.ft R +.IP +Used for describing parameters to various +.B portmap +procedures, externally. +This routine is useful for users who wish to generate +these parameters without using the +.B pmap +interface. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +xdr_pmaplist(xdrs, rp) +\s-1XDR\s0 *xdrs; +struct pmaplist **rp; +.fi +.ft R +.IP +Used for describing a list of port mappings, externally. +This routine is useful for users who wish to generate +these parameters without using the +.B pmap +interface. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +xdr_rejected_reply(xdrs, rr) +\s-1XDR\s0 *xdrs; +struct rejected_reply *rr; +.fi +.ft R +.IP +Used for describing +.SM RPC +reply messages. +This routine is useful for users who wish to generate +.SM RPC\s0-style +messages without using the +.SM RPC +package. +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +xdr_replymsg(xdrs, rmsg) +\s-1XDR\s0 *xdrs; +struct rpc_msg *rmsg; +.fi +.ft R +.IP +Used for describing +.SM RPC +reply messages. +This routine is useful for users who wish to generate +.SM RPC +style messages without using the +.SM RPC +package. +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +void +xprt_register(xprt) +\s-1SVCXPRT\s0 *xprt; +.fi +.ft R +.IP +After +.SM RPC +service transport handles are created, +they should register themselves with the +.SM RPC +service package. +This routine modifies the global variable +.BR svc_fds(\|) . +Service implementors usually do not need this routine. +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +void +xprt_unregister(xprt) +\s-1SVCXPRT\s0 *xprt; +.fi +.ft R +.IP +Before an +.SM RPC +service transport handle is destroyed, +it should unregister itself with the +.SM RPC +service package. +This routine modifies the global variable +.BR svc_fds(\|) . +Service implementors usually do not need this routine. +.SH SEE ALSO +.BR rpc_secure (3N), +.BR xdr (3N) +.br +The following manuals: +.RS +.ft I +Remote Procedure Calls: Protocol Specification +.br +Remote Procedure Call Programming Guide +.br +rpcgen Programming Guide +.br +.ft R +.RE +.IR "\s-1RPC\s0: Remote Procedure Call Protocol Specification" , +.SM RFC1050, Sun Microsystems, Inc., +.SM USC-ISI\s0. + diff --git a/rpc.subproj/rpc_callmsg.c b/rpc.subproj/rpc_callmsg.c index 69a65ed..789fd00 100644 --- a/rpc.subproj/rpc_callmsg.c +++ b/rpc.subproj/rpc_callmsg.c @@ -79,7 +79,11 @@ xdr_callmsg(xdrs, cmsg) register XDR *xdrs; register struct rpc_msg *cmsg; { +#ifdef __LP64__ + int *buf; +#else register long *buf; +#endif register struct opaque_auth *oa; if (xdrs->x_op == XDR_ENCODE) { @@ -89,10 +93,17 @@ xdr_callmsg(xdrs, cmsg) if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) { return (FALSE); } +#ifdef __LP64__ + buf = (int *)XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT + + RNDUP(cmsg->rm_call.cb_cred.oa_length) + + 2 * BYTES_PER_XDR_UNIT + + RNDUP(cmsg->rm_call.cb_verf.oa_length)); +#else buf = (long *)XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT - + RNDUP(cmsg->rm_call.cb_cred.oa_length) - + 2 * BYTES_PER_XDR_UNIT - + RNDUP(cmsg->rm_call.cb_verf.oa_length)); + + RNDUP(cmsg->rm_call.cb_cred.oa_length) + + 2 * BYTES_PER_XDR_UNIT + + RNDUP(cmsg->rm_call.cb_verf.oa_length)); +#endif if (buf != NULL) { IXDR_PUT_LONG(buf, cmsg->rm_xid); IXDR_PUT_ENUM(buf, cmsg->rm_direction); @@ -111,7 +122,11 @@ xdr_callmsg(xdrs, cmsg) IXDR_PUT_LONG(buf, oa->oa_length); if (oa->oa_length) { bcopy(oa->oa_base, (caddr_t)buf, oa->oa_length); +#ifdef __LP64__ + buf += RNDUP(oa->oa_length) / sizeof (int); +#else buf += RNDUP(oa->oa_length) / sizeof (long); +#endif } oa = &cmsg->rm_call.cb_verf; IXDR_PUT_ENUM(buf, oa->oa_flavor); @@ -119,6 +134,7 @@ xdr_callmsg(xdrs, cmsg) if (oa->oa_length) { bcopy(oa->oa_base, (caddr_t)buf, oa->oa_length); /* no real need.... + * N.B. Fix this for __LP64__ if it is uncommented * buf += RNDUP(oa->oa_length) / sizeof (long); */ } @@ -126,7 +142,11 @@ xdr_callmsg(xdrs, cmsg) } } if (xdrs->x_op == XDR_DECODE) { +#ifdef __LP64__ + buf = (int *)XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT); +#else buf = (long *)XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT); +#endif if (buf != NULL) { cmsg->rm_xid = IXDR_GET_LONG(buf); cmsg->rm_direction = IXDR_GET_ENUM(buf, enum msg_type); @@ -151,7 +171,11 @@ xdr_callmsg(xdrs, cmsg) oa->oa_base = (caddr_t) mem_alloc(oa->oa_length); } +#ifdef __LP64__ + buf = (int *)XDR_INLINE(xdrs, RNDUP(oa->oa_length)); +#else buf = (long *)XDR_INLINE(xdrs, RNDUP(oa->oa_length)); +#endif if (buf == NULL) { if (xdr_opaque(xdrs, oa->oa_base, oa->oa_length) == FALSE) { @@ -161,13 +185,17 @@ xdr_callmsg(xdrs, cmsg) bcopy((caddr_t)buf, oa->oa_base, oa->oa_length); /* no real need.... - buf += RNDUP(oa->oa_length) / - sizeof (long); + * N.B. Fix this for __LP64__ if it is uncommented * + buf += RNDUP(oa->oa_length) / sizeof (long); */ } } oa = &cmsg->rm_call.cb_verf; +#ifdef __LP64__ + buf = (int *)XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT); +#else buf = (long *)XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT); +#endif if (buf == NULL) { if (xdr_enum(xdrs, &oa->oa_flavor) == FALSE || xdr_u_int(xdrs, &oa->oa_length) == FALSE) { @@ -185,7 +213,11 @@ xdr_callmsg(xdrs, cmsg) oa->oa_base = (caddr_t) mem_alloc(oa->oa_length); } +#ifdef __LP64__ + buf = (int *)XDR_INLINE(xdrs, RNDUP(oa->oa_length)); +#else buf = (long *)XDR_INLINE(xdrs, RNDUP(oa->oa_length)); +#endif if (buf == NULL) { if (xdr_opaque(xdrs, oa->oa_base, oa->oa_length) == FALSE) { @@ -195,8 +227,8 @@ xdr_callmsg(xdrs, cmsg) bcopy((caddr_t)buf, oa->oa_base, oa->oa_length); /* no real need... - buf += RNDUP(oa->oa_length) / - sizeof (long); + * N.B. Fix this for __LP64__ if it is uncommented * + buf += RNDUP(oa->oa_length) / sizeof (long); */ } } diff --git a/rpc.subproj/rpc_msg.h b/rpc.subproj/rpc_msg.h index 6f5611b..ec2d929 100644 --- a/rpc.subproj/rpc_msg.h +++ b/rpc.subproj/rpc_msg.h @@ -64,7 +64,11 @@ #ifndef _RPC_RPCMSG_H #define _RPC_RPCMSG_H +#ifdef __LP64__ +#define RPC_MSG_VERSION ((unsigned int) 2) +#else #define RPC_MSG_VERSION ((unsigned long) 2) +#endif #define RPC_SERVICE_PORT ((unsigned short) 2048) /* @@ -111,8 +115,13 @@ struct accepted_reply { enum accept_stat ar_stat; union { struct { - unsigned long low; - unsigned long high; +#ifdef __LP64__ + unsigned int low; + unsigned int high; +#else + unsigned long low; + unsigned long high; +#endif } AR_versions; struct { caddr_t where; @@ -131,8 +140,13 @@ struct rejected_reply { enum reject_stat rj_stat; union { struct { +#ifdef __LP64__ + unsigned int low; + unsigned int high; +#else unsigned long low; unsigned long high; +#endif } RJ_versions; enum auth_stat RJ_why; /* why authentication did not work */ } ru; @@ -157,10 +171,17 @@ struct reply_body { * Body of an rpc request call. */ struct call_body { +#ifdef __LP64__ + unsigned int cb_rpcvers; /* must be equal to two */ + unsigned int cb_prog; + unsigned int cb_vers; + unsigned int cb_proc; +#else unsigned long cb_rpcvers; /* must be equal to two */ unsigned long cb_prog; unsigned long cb_vers; unsigned long cb_proc; +#endif struct opaque_auth cb_cred; struct opaque_auth cb_verf; /* protocol specific - provided by client */ }; @@ -169,7 +190,11 @@ struct call_body { * The rpc message */ struct rpc_msg { +#ifdef __LP64__ + unsigned int rm_xid; +#else unsigned long rm_xid; +#endif enum msg_type rm_direction; union { struct call_body RM_cmb; diff --git a/rpc.subproj/rpc_prot.c b/rpc.subproj/rpc_prot.c index 101bdcb..0299d1d 100644 --- a/rpc.subproj/rpc_prot.c +++ b/rpc.subproj/rpc_prot.c @@ -162,8 +162,8 @@ xdr_rejected_reply(xdrs, rr) } static struct xdr_discrim reply_dscrm[3] = { - { (int)MSG_ACCEPTED, xdr_accepted_reply }, - { (int)MSG_DENIED, xdr_rejected_reply }, + { (int)MSG_ACCEPTED, (xdrproc_t)xdr_accepted_reply }, + { (int)MSG_DENIED, (xdrproc_t)xdr_rejected_reply }, { __dontcare__, NULL_xdrproc_t } }; /* @@ -243,8 +243,13 @@ accepted(acpt_stat, error) } /* something's wrong, but we don't know what ... */ error->re_status = RPC_FAILED; +#ifdef __LP64__ + error->re_lb.s1 = (int)MSG_ACCEPTED; + error->re_lb.s2 = (int)acpt_stat; +#else error->re_lb.s1 = (long)MSG_ACCEPTED; error->re_lb.s2 = (long)acpt_stat; +#endif } static void @@ -266,8 +271,13 @@ rejected(rjct_stat, error) } /* something's wrong, but we don't know what ... */ error->re_status = RPC_FAILED; +#ifdef __LP64__ + error->re_lb.s1 = (int)MSG_DENIED; + error->re_lb.s2 = (int)rjct_stat; +#else error->re_lb.s1 = (long)MSG_DENIED; error->re_lb.s2 = (long)rjct_stat; +#endif } /* @@ -296,7 +306,11 @@ _seterr_reply(msg, error) default: error->re_status = RPC_FAILED; +#ifdef __LP64__ + error->re_lb.s1 = (int)(msg->rm_reply.rp_stat); +#else error->re_lb.s1 = (long)(msg->rm_reply.rp_stat); +#endif break; } switch (error->re_status) { diff --git a/rpc.subproj/svc.c b/rpc.subproj/svc.c index b0a6a9a..b17fe4e 100644 --- a/rpc.subproj/svc.c +++ b/rpc.subproj/svc.c @@ -150,11 +150,19 @@ xprt_unregister(xprt) */ bool_t svc_register(xprt, prog, vers, dispatch, protocol) +#ifdef __LP64__ + SVCXPRT *xprt; + uint32_t prog; + uint32_t vers; + void (*dispatch)(); + int32_t protocol; +#else SVCXPRT *xprt; u_long prog; u_long vers; void (*dispatch)(); int protocol; +#endif { struct svc_callout *prev; register struct svc_callout *s; @@ -186,8 +194,13 @@ pmap_it: */ void svc_unregister(prog, vers) +#ifdef __LP64__ + uint32_t prog; + uint32_t vers; +#else u_long prog; u_long vers; +#endif { struct svc_callout *prev; register struct svc_callout *s; @@ -347,9 +360,15 @@ svcerr_noprog(xprt) */ void svcerr_progvers(xprt, low_vers, high_vers) +#ifdef __LP64__ + register SVCXPRT *xprt; + uint32_t low_vers; + uint32_t high_vers; +#else register SVCXPRT *xprt; u_long low_vers; u_long high_vers; +#endif { struct rpc_msg rply; diff --git a/rpc.subproj/svc.h b/rpc.subproj/svc.h index 55df0fd..ca1270d 100644 --- a/rpc.subproj/svc.h +++ b/rpc.subproj/svc.h @@ -171,9 +171,15 @@ typedef struct { * Service request */ struct svc_req { +#ifdef __LP64__ + unsigned int rq_prog; /* service program number */ + unsigned int rq_vers; /* service protocol version */ + unsigned int rq_proc; /* the desired procedure */ +#else unsigned long rq_prog; /* service program number */ unsigned long rq_vers; /* service protocol version */ unsigned long rq_proc; /* the desired procedure */ +#endif struct opaque_auth rq_cred; /* raw creds from the wire */ caddr_t rq_clntcred; /* read only cooked cred */ SVCXPRT *rq_xprt; /* associated transport */ @@ -185,24 +191,32 @@ struct svc_req { * * svc_register(xprt, prog, vers, dispatch, protocol) * SVCXPRT *xprt; - * unsigned long prog; - * unsigned long vers; + * u_long prog; + * u_long vers; * void (*dispatch)(...); // fixincludes needs the ..., even in a comment * int protocol; like TCP or UDP, zero means do not register */ __BEGIN_DECLS +#ifdef __LP64__ +extern bool_t svc_register __P((SVCXPRT *, unsigned int, unsigned int, void (*)(), int)); +#else extern bool_t svc_register __P((SVCXPRT *, unsigned long, unsigned long, void (*)(), int)); +#endif __END_DECLS /* * Service un-registration * * svc_unregister(prog, vers) - * unsigned long prog; - * unsigned long vers; + * u_long prog; + * u_long vers; */ __BEGIN_DECLS +#ifdef __LP64__ +extern void svc_unregister __P((unsigned int, unsigned int)); +#else extern void svc_unregister __P((unsigned long, unsigned long)); +#endif __END_DECLS /* @@ -259,7 +273,11 @@ extern bool_t svc_sendreply __P((SVCXPRT *, xdrproc_t, char *)); extern void svcerr_decode __P((SVCXPRT *)); extern void svcerr_weakauth __P((SVCXPRT *)); extern void svcerr_noproc __P((SVCXPRT *)); +#ifdef __LP64__ +extern void svcerr_progvers __P((SVCXPRT *, unsigned int, unsigned int)); +#else extern void svcerr_progvers __P((SVCXPRT *, unsigned long, unsigned long)); +#endif extern void svcerr_auth __P((SVCXPRT *, enum auth_stat)); extern void svcerr_noprog __P((SVCXPRT *)); extern void svcerr_systemerr __P((SVCXPRT *)); diff --git a/rpc.subproj/svc_auth_unix.c b/rpc.subproj/svc_auth_unix.c index e96e505..3412d81 100644 --- a/rpc.subproj/svc_auth_unix.c +++ b/rpc.subproj/svc_auth_unix.c @@ -83,7 +83,11 @@ _svcauth_unix(rqst, msg) register enum auth_stat stat; XDR xdrs; register struct authunix_parms *aup; +#ifdef __LP64__ + int *buf; +#else register long *buf; +#endif struct area { struct authunix_parms area_aup; char area_machname[MAX_MACHINE_NAME+1]; @@ -98,7 +102,11 @@ _svcauth_unix(rqst, msg) aup->aup_gids = area->area_gids; auth_len = (u_int)msg->rm_call.cb_cred.oa_length; xdrmem_create(&xdrs, msg->rm_call.cb_cred.oa_base, auth_len,XDR_DECODE); +#ifdef __LP64__ + buf = (int *)XDR_INLINE(&xdrs, auth_len); +#else buf = (long *)XDR_INLINE(&xdrs, auth_len); +#endif if (buf != NULL) { aup->aup_time = IXDR_GET_LONG(buf); str_len = IXDR_GET_U_LONG(buf); @@ -109,7 +117,11 @@ _svcauth_unix(rqst, msg) bcopy((caddr_t)buf, aup->aup_machname, str_len); aup->aup_machname[str_len] = 0; str_len = RNDUP(str_len); +#ifdef __LP64__ + buf += str_len / sizeof (int); +#else buf += str_len / sizeof (long); +#endif aup->aup_uid = IXDR_GET_LONG(buf); aup->aup_gid = IXDR_GET_LONG(buf); gid_len = IXDR_GET_U_LONG(buf); @@ -127,7 +139,8 @@ _svcauth_unix(rqst, msg) */ if ((5 + gid_len) * BYTES_PER_XDR_UNIT + str_len > auth_len) { /* LIBRARY CODE SHOULD NOT PRINT - (void) printf("bad auth_len gid %d str %d auth %d\n", gid_len, str_len, auth_len); + (void) printf("bad auth_len gid %d str %d auth %d\n", + gid_len, str_len, auth_len); */ stat = AUTH_BADCRED; goto done; diff --git a/rpc.subproj/svc_simple.c b/rpc.subproj/svc_simple.c index 2268732..3796844 100644 --- a/rpc.subproj/svc_simple.c +++ b/rpc.subproj/svc_simple.c @@ -89,8 +89,11 @@ registerrpc(prognum, versnum, procnum, progname, inproc, outproc) { if (procnum == NULLPROC) { - (void) fprintf(stderr, - "can't reassign procedure number %ld\n", NULLPROC); +#ifdef __LP64__ + (void) fprintf(stderr, "can't reassign procedure number %d\n", NULLPROC); +#else + (void) fprintf(stderr, "can't reassign procedure number %ld\n", NULLPROC); +#endif return (-1); } if (transp == 0) { @@ -136,7 +139,7 @@ universal(rqstp, transp) * enforce "procnum 0 is echo" convention */ if (rqstp->rq_proc == NULLPROC) { - if (svc_sendreply(transp, xdr_void, (char *)NULL) == FALSE) { + if (svc_sendreply(transp, (xdrproc_t)xdr_void, (char *)NULL) == FALSE) { (void) fprintf(stderr, "xxx\n"); exit(1); } @@ -153,7 +156,7 @@ universal(rqstp, transp) return; } outdata = (*(pl->p_progname))(xdrbuf); - if (outdata == NULL && pl->p_outproc != xdr_void) + if (outdata == NULL && pl->p_outproc != (xdrproc_t)xdr_void) /* there was an error */ return; if (!svc_sendreply(transp, pl->p_outproc, outdata)) { diff --git a/rpc.subproj/svc_tcp.c b/rpc.subproj/svc_tcp.c index 59303fe..23c6f65 100644 --- a/rpc.subproj/svc_tcp.c +++ b/rpc.subproj/svc_tcp.c @@ -158,7 +158,7 @@ svctcp_create(sock, sendsize, recvsize) register SVCXPRT *xprt; register struct tcp_rendezvous *r; struct sockaddr_in addr; - int len = sizeof(struct sockaddr_in); + unsigned int len = sizeof(struct sockaddr_in); if (sock == RPC_ANYSOCK) { if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { @@ -266,13 +266,12 @@ rendezvous_request(xprt) int sock; struct tcp_rendezvous *r; struct sockaddr_in addr; - int len; + unsigned int len; r = (struct tcp_rendezvous *)xprt->xp_p1; again: len = sizeof(struct sockaddr_in); - if ((sock = accept(xprt->xp_sock, (struct sockaddr *)&addr, - &len)) < 0) { + if ((sock = accept(xprt->xp_sock, (struct sockaddr *)&addr, &len)) < 0) { if (errno == EINTR) goto again; return (FALSE); diff --git a/rpc.subproj/svc_udp.c b/rpc.subproj/svc_udp.c index 5f836b4..3cbd9f4 100644 --- a/rpc.subproj/svc_udp.c +++ b/rpc.subproj/svc_udp.c @@ -129,7 +129,7 @@ svcudp_bufcreate(sock, sendsz, recvsz) register SVCXPRT *xprt; register struct svcudp_data *su; struct sockaddr_in addr; - int len = sizeof(struct sockaddr_in); + unsigned int len = sizeof(struct sockaddr_in); if (sock == RPC_ANYSOCK) { if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { @@ -209,8 +209,7 @@ svcudp_recv(xprt, msg) again: xprt->xp_addrlen = sizeof(struct sockaddr_in); - rlen = recvfrom(xprt->xp_sock, rpc_buffer(xprt), (int) su->su_iosz, - 0, (struct sockaddr *)&(xprt->xp_raddr), &(xprt->xp_addrlen)); + rlen = recvfrom(xprt->xp_sock, rpc_buffer(xprt), (int) su->su_iosz, 0, (struct sockaddr *)&(xprt->xp_raddr), (unsigned int *)&(xprt->xp_addrlen)); if (rlen == -1 && errno == EINTR) goto again; if (rlen < 4*sizeof(u_long)) diff --git a/rpc.subproj/types.h b/rpc.subproj/types.h index 33ae11c..0fe5adc 100644 --- a/rpc.subproj/types.h +++ b/rpc.subproj/types.h @@ -91,4 +91,12 @@ #endif #include +#ifdef __LP64__ +typedef int rpc_int; +typedef unsigned int rpc_uint; +#else +typedef long rpc_int; +typedef unsigned long rpc_uint; +#endif + #endif /* !_RPC_TYPES_H */ diff --git a/rpc.subproj/xdr.3 b/rpc.subproj/xdr.3 new file mode 100644 index 0000000..029eb4f --- /dev/null +++ b/rpc.subproj/xdr.3 @@ -0,0 +1,829 @@ +.\" @(#)xdr.3n 2.2 88/08/03 4.0 RPCSRC; from 1.16 88/03/14 SMI +.\" $FreeBSD: src/lib/libc/xdr/xdr.3,v 1.16 2002/12/19 09:40:28 ru Exp $ +.\" +.Dd February 16, 1988 +.Dt XDR 3 +.Os +.Sh NAME +.Nm xdr , +.Nm xdr_array , +.Nm xdr_bool , +.Nm xdr_bytes , +.Nm xdr_char , +.Nm xdr_destroy , +.Nm xdr_double , +.Nm xdr_enum , +.Nm xdr_float , +.Nm xdr_free , +.Nm xdr_getpos , +.Nm xdr_hyper , +.Nm xdr_inline , +.Nm xdr_int , +.Nm xdr_long , +.Nm xdr_longlong_t , +.Nm xdrmem_create , +.Nm xdr_opaque , +.Nm xdr_pointer , +.Nm xdrrec_create , +.Nm xdrrec_endofrecord , +.Nm xdrrec_eof , +.Nm xdrrec_skiprecord , +.Nm xdr_reference , +.Nm xdr_setpos , +.Nm xdr_short , +.Nm xdrstdio_create , +.Nm xdr_string , +.Nm xdr_u_char , +.Nm xdr_u_hyper , +.Nm xdr_u_int , +.Nm xdr_u_long , +.Nm xdr_u_longlong_t , +.Nm xdr_u_short , +.Nm xdr_union , +.Nm xdr_vector , +.Nm xdr_void , +.Nm xdr_wrapstring +.Nd "library routines for external data representation" +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In rpc/types.h +.In rpc/xdr.h +.Pp +See +.Sx DESCRIPTION +for function declarations. +.Sh DESCRIPTION +These routines allow C programmers to describe +arbitrary data structures in a machine-independent fashion. +Data for remote procedure calls are transmitted using these +routines. +.Pp +.Bl -tag -width indent -compact +.It Xo +.Ft int +.Xc +.It Xo +.Fo xdr_array +.Fa "XDR *xdrs" +.Fa "char **arrp" +.Fa "u_int *sizep" +.Fa "u_int maxsize" +.Fa "u_int elsize" +.Fa "xdrproc_t elproc" +.Fc +.Xc +.Pp +A filter primitive that translates between variable-length +arrays +and their corresponding external representations. +The +.Fa arrp +argument +is the address of the pointer to the array, while +.Fa sizep +is the address of the element count of the array; +this element count cannot exceed +.Fa maxsize . +The +.Fa elsize +argument +is the +.Ic sizeof +each of the array's elements, and +.Fa elproc +is an +.Tn XDR +filter that translates between +the array elements' C form, and their external +representation. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_bool "XDR *xdrs" "bool_t *bp" +.Xc +.Pp +A filter primitive that translates between booleans (C +integers) +and their external representations. +When encoding data, this +filter produces values of either one or zero. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_bytes "XDR *xdrs" "char **sp" "u_int *sizep" "u_int maxsize" +.Xc +.Pp +A filter primitive that translates between counted byte +strings and their external representations. +The +.Fa sp +argument +is the address of the string pointer. +The length of the +string is located at address +.Fa sizep ; +strings cannot be longer than +.Fa maxsize . +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_char "XDR *xdrs" "char *cp" +.Xc +.Pp +A filter primitive that translates between C characters +and their external representations. +This routine returns one if it succeeds, zero otherwise. +Note: encoded characters are not packed, and occupy 4 bytes +each. +For arrays of characters, it is worthwhile to +consider +.Fn xdr_bytes , +.Fn xdr_opaque +or +.Fn xdr_string . +.Pp +.It Xo +.Ft void +.Xc +.It Xo +.Fn xdr_destroy "XDR *xdrs" +.Xc +.Pp +A macro that invokes the destroy routine associated with the +.Tn XDR +stream, +.Fa xdrs . +Destruction usually involves freeing private data structures +associated with the stream. +Using +.Fa xdrs +after invoking +.Fn xdr_destroy +is undefined. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_double "XDR *xdrs" "double *dp" +.Xc +.Pp +A filter primitive that translates between C +.Vt double +precision numbers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_enum "XDR *xdrs" "enum_t *ep" +.Xc +.Pp +A filter primitive that translates between C +.Vt enum Ns s +(actually integers) and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_float "XDR *xdrs" "float *fp" +.Xc +.Pp +A filter primitive that translates between C +.Vt float Ns s +and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft void +.Xc +.It Xo +.Fn xdr_free "xdrproc_t proc" "char *objp" +.Xc +.Pp +Generic freeing routine. +The first argument is the +.Tn XDR +routine for the object being freed. +The second argument +is a pointer to the object itself. +Note: the pointer passed +to this routine is +.Em not +freed, but what it points to +.Em is +freed (recursively). +.Pp +.It Xo +.Ft u_int +.Xc +.It Xo +.Fn xdr_getpos "XDR *xdrs" +.Xc +.Pp +A macro that invokes the get\-position routine +associated with the +.Tn XDR +stream, +.Fa xdrs . +The routine returns an unsigned integer, +which indicates the position of the +.Tn XDR +byte stream. +A desirable feature of +.Tn XDR +streams is that simple arithmetic works with this number, +although the +.Tn XDR +stream instances need not guarantee this. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_hyper "XDR *xdrs" "quad_t *llp" +.Xc +A filter primitive that translates between ANSI C +.Vt "long long" +integers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft "long *" +.Xc +.It Xo +.Fn xdr_inline "XDR *xdrs" "int len" +.Xc +.Pp +A macro that invokes the in-line routine associated with the +.Tn XDR +stream, +.Fa xdrs . +The routine returns a pointer +to a contiguous piece of the stream's buffer; +.Fa len +is the byte length of the desired buffer. +Note: pointer is cast to +.Vt "long *" . +.Pp +Warning: +.Fn xdr_inline +may return +.Dv NULL +(0) +if it cannot allocate a contiguous piece of a buffer. +Therefore the behavior may vary among stream instances; +it exists for the sake of efficiency. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_int "XDR *xdrs" "int *ip" +.Xc +.Pp +A filter primitive that translates between C integers +and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_long "XDR *xdrs" "long *lp" +.Xc +.Pp +A filter primitive that translates between C +.Vt long +integers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_longlong_t "XDR *xdrs" "quad_t *llp" +.Xc +A filter primitive that translates between ANSI C +.Vt "long long" +integers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft void +.Xc +.It Xo +.Fn xdrmem_create "XDR *xdrs" "char *addr" "u_int size" "enum xdr_op op" +.Xc +.Pp +This routine initializes the +.Tn XDR +stream object pointed to by +.Fa xdrs . +The stream's data is written to, or read from, +a chunk of memory at location +.Fa addr +whose length is no more than +.Fa size +bytes long. +The +.Fa op +argument +determines the direction of the +.Tn XDR +stream +(either +.Dv XDR_ENCODE , +.Dv XDR_DECODE , +or +.Dv XDR_FREE ) . +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_opaque "XDR *xdrs" "char *cp" "u_int cnt" +.Xc +.Pp +A filter primitive that translates between fixed size opaque +data +and its external representation. +The +.Fa cp +argument +is the address of the opaque object, and +.Fa cnt +is its size in bytes. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_pointer "XDR *xdrs" "char **objpp" "u_int objsize" "xdrproc_t xdrobj" +.Xc +.Pp +Like +.Fn xdr_reference +except that it serializes +.Dv NULL +pointers, whereas +.Fn xdr_reference +does not. +Thus, +.Fn xdr_pointer +can represent +recursive data structures, such as binary trees or +linked lists. +.Pp +.It Xo +.Ft void +.Xc +.It Xo +.Fo xdrrec_create +.Fa "XDR *xdrs" +.Fa "u_int sendsize" +.Fa "u_int recvsize" +.Fa "char *handle" +.Fa "int \*(lp*readit\*(rp\*(lp\*(rp" +.Fa "int \*(lp*writeit\*(rp\*(lp\*(rp" +.Fc +.Xc +.Pp +This routine initializes the +.Tn XDR +stream object pointed to by +.Fa xdrs . +The stream's data is written to a buffer of size +.Fa sendsize ; +a value of zero indicates the system should use a suitable +default. +The stream's data is read from a buffer of size +.Fa recvsize ; +it too can be set to a suitable default by passing a zero +value. +When a stream's output buffer is full, +.Fn writeit +is called. +Similarly, when a stream's input buffer is empty, +.Fn readit +is called. +The behavior of these two routines is similar to +the +system calls +.Xr read 2 +and +.Xr write 2 , +except that +.Fa handle +is passed to the former routines as the first argument. +Note: the +.Tn XDR +stream's +.Fa op +field must be set by the caller. +.Pp +Warning: this +.Tn XDR +stream implements an intermediate record stream. +Therefore there are additional bytes in the stream +to provide record boundary information. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdrrec_endofrecord "XDR *xdrs" "int sendnow" +.Xc +.Pp +This routine can be invoked only on +streams created by +.Fn xdrrec_create . +The data in the output buffer is marked as a completed +record, +and the output buffer is optionally written out if +.Fa sendnow +is non-zero. +This routine returns one if it succeeds, zero +otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdrrec_eof "XDR *xdrs" +.Xc +.Pp +This routine can be invoked only on +streams created by +.Fn xdrrec_create . +After consuming the rest of the current record in the stream, +this routine returns one if the stream has no more input, +zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdrrec_skiprecord "XDR *xdrs" +.Xc +.Pp +This routine can be invoked only on +streams created by +.Fn xdrrec_create . +It tells the +.Tn XDR +implementation that the rest of the current record +in the stream's input buffer should be discarded. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_reference "XDR *xdrs" "char **pp" "u_int size" "xdrproc_t proc" +.Xc +.Pp +A primitive that provides pointer chasing within structures. +The +.Fa pp +argument +is the address of the pointer; +.Fa size +is the +.Ic sizeof +the structure that +.Fa *pp +points to; and +.Fa proc +is an +.Tn XDR +procedure that filters the structure +between its C form and its external representation. +This routine returns one if it succeeds, zero otherwise. +.Pp +Warning: this routine does not understand +.Dv NULL +pointers. +Use +.Fn xdr_pointer +instead. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_setpos "XDR *xdrs" "u_int pos" +.Xc +.Pp +A macro that invokes the set position routine associated with +the +.Tn XDR +stream +.Fa xdrs . +The +.Fa pos +argument +is a position value obtained from +.Fn xdr_getpos . +This routine returns one if the +.Tn XDR +stream could be repositioned, +and zero otherwise. +.Pp +Warning: it is difficult to reposition some types of +.Tn XDR +streams, so this routine may fail with one +type of stream and succeed with another. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_short "XDR *xdrs" "short *sp" +.Xc +.Pp +A filter primitive that translates between C +.Vt short +integers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Li "#ifdef _STDIO_H_" +.It Li "/* XDR using stdio library */" +.It Xo +.Ft void +.Xc +.It Xo +.Fn xdrstdio_create "XDR *xdrs" "FILE *file" "enum xdr_op op" +.Xc +.It Li "#endif" +.Pp +This routine initializes the +.Tn XDR +stream object pointed to by +.Fa xdrs . +The +.Tn XDR +stream data is written to, or read from, the Standard +.Tn I/O +stream +.Fa file . +The +.Fa op +argument +determines the direction of the +.Tn XDR +stream (either +.Dv XDR_ENCODE , +.Dv XDR_DECODE , +or +.Dv XDR_FREE ) . +.Pp +Warning: the destroy routine associated with such +.Tn XDR +streams calls +.Xr fflush 3 +on the +.Fa file +stream, but never +.Xr fclose 3 . +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_string "XDR *xdrs" "char **sp" "u_int maxsize" +.Xc +.Pp +A filter primitive that translates between C strings and +their +corresponding external representations. +Strings cannot be longer than +.Fa maxsize . +Note: +.Fa sp +is the address of the string's pointer. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_u_char "XDR *xdrs" "unsigned char *ucp" +.Xc +.Pp +A filter primitive that translates between +.Vt unsigned +C characters and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_u_hyper "XDR *xdrs" "u_quad_t *ullp" +.Xc +A filter primitive that translates between +.Vt unsigned +ANSI C +.Vt long long +integers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_u_int "XDR *xdrs" "unsigned *up" +.Xc +.Pp +A filter primitive that translates between C +.Vt unsigned +integers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_u_long "XDR *xdrs" "unsigned long *ulp" +.Xc +.Pp +A filter primitive that translates between C +.Vt "unsigned long" +integers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_u_longlong_t "XDR *xdrs" "u_quad_t *ullp" +.Xc +A filter primitive that translates between +.Vt unsigned +ANSI C +.Vt "long long" +integers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_u_short "XDR *xdrs" "unsigned short *usp" +.Xc +.Pp +A filter primitive that translates between C +.Vt "unsigned short" +integers and their external representations. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fo xdr_union +.Fa "XDR *xdrs" +.Fa "enum_t *dscmp" +.Fa "char *unp" +.Fa "const struct xdr_discrim *choices" +.Fa "xdrproc_t defaultarm" +.Fc +.Xc +.Pp +A filter primitive that translates between a discriminated C +.Vt union +and its corresponding external representation. +It first +translates the discriminant of the union located at +.Fa dscmp . +This discriminant is always an +.Vt enum_t . +Next the union located at +.Fa unp +is translated. +The +.Fa choices +argument +is a pointer to an array of +.Vt xdr_discrim +structures. +Each structure contains an ordered pair of +.Bq Va value , proc . +If the union's discriminant is equal to the associated +.Va value , +then the +.Fn proc +is called to translate the union. +The end of the +.Vt xdr_discrim +structure array is denoted by a routine of value +.Dv NULL . +If the discriminant is not found in the +.Fa choices +array, then the +.Fn defaultarm +procedure is called (if it is not +.Dv NULL ) . +Returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fo xdr_vector +.Fa "XDR *xdrs" +.Fa "char *arrp" +.Fa "u_int size" +.Fa "u_int elsize" +.Fa "xdrproc_t elproc" +.Fc +.Xc +.Pp +A filter primitive that translates between fixed-length +arrays +and their corresponding external representations. +The +.Fa arrp +argument +is the address of the pointer to the array, while +.Fa size +is the element count of the array. +The +.Fa elsize +argument +is the +.Ic sizeof +each of the array's elements, and +.Fa elproc +is an +.Tn XDR +filter that translates between +the array elements' C form, and their external +representation. +This routine returns one if it succeeds, zero otherwise. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_void void +.Xc +.Pp +This routine always returns one. +It may be passed to +.Tn RPC +routines that require a function argument, +where nothing is to be done. +.Pp +.It Xo +.Ft int +.Xc +.It Xo +.Fn xdr_wrapstring "XDR *xdrs" "char **sp" +.Xc +.Pp +A primitive that calls +.Fn xdr_string xdrs sp MAXUN.UNSIGNED ; +where +.Dv MAXUN.UNSIGNED +is the maximum value of an unsigned integer. +The +.Fn xdr_wrapstring +function +is handy because the +.Tn RPC +package passes a maximum of two +.Tn XDR +routines as arguments, and +.Fn xdr_string , +one of the most frequently used primitives, requires three. +Returns one if it succeeds, zero otherwise. +.El +.Sh SEE ALSO +.Xr rpc 3 +.Rs +.%T "eXternal Data Representation Standard: Protocol Specification" +.Re +.Rs +.%T "eXternal Data Representation: Sun Technical Notes" +.Re +.Rs +.%T "XDR: External Data Representation Standard" +.%O RFC1014 +.%Q "Sun Microsystems, Inc., USC\-ISI" +.Re diff --git a/rpc.subproj/xdr.c b/rpc.subproj/xdr.c index d9b60a5..3cf13bb 100644 --- a/rpc.subproj/xdr.c +++ b/rpc.subproj/xdr.c @@ -77,14 +77,25 @@ static char *sccsid = "@(#)xdr.c 2.1 88/07/29 4.0 RPCSRC"; #include #include +#ifdef __LP64__ +#define xdrlong_t int +#else +#define xdrlong_t long +#endif + typedef quad_t longlong_t; /* ANSI long long type */ typedef u_quad_t u_longlong_t; /* ANSI unsigned long long type */ /* * constants specific to the xdr "protocol" */ +#ifdef __LP64__ +#define XDR_FALSE ((int) 0) +#define XDR_TRUE ((int) 1) +#else #define XDR_FALSE ((long) 0) #define XDR_TRUE ((long) 1) +#endif #define LASTUNSIGNED ((u_int) 0-1) /* @@ -126,19 +137,19 @@ xdr_int(xdrs, ip) XDR *xdrs; int *ip; { - long l; + xdrlong_t l; switch (xdrs->x_op) { case XDR_ENCODE: - l = (long) *ip; - return (XDR_PUTLONG(xdrs, &l)); + l = *ip; + return (XDR_PUTLONG(xdrs, (const xdrlong_t *)&l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &l)) { return (FALSE); } - *ip = (int) l; + *ip = l; return (TRUE); case XDR_FREE: @@ -156,19 +167,19 @@ xdr_u_int(xdrs, up) XDR *xdrs; u_int *up; { - u_long l; + xdrlong_t l; switch (xdrs->x_op) { case XDR_ENCODE: - l = (u_long) *up; - return (XDR_PUTLONG(xdrs, (long *)&l)); + l = *up; + return (XDR_PUTLONG(xdrs, (const xdrlong_t *)&l)); case XDR_DECODE: - if (!XDR_GETLONG(xdrs, (long *)&l)) { + if (!XDR_GETLONG(xdrs, &l)) { return (FALSE); } - *up = (u_int) l; + *up = l; return (TRUE); case XDR_FREE: @@ -186,7 +197,11 @@ xdr_u_int(xdrs, up) bool_t xdr_long(xdrs, lp) XDR *xdrs; +#ifdef __LP64__ + int *lp; +#else long *lp; +#endif { switch (xdrs->x_op) { case XDR_ENCODE: @@ -207,13 +222,17 @@ xdr_long(xdrs, lp) bool_t xdr_u_long(xdrs, ulp) XDR *xdrs; +#ifdef __LP64__ + unsigned int *ulp; +#else u_long *ulp; -{ +#endif +{ switch (xdrs->x_op) { case XDR_ENCODE: - return (XDR_PUTLONG(xdrs, (long *)ulp)); + return (XDR_PUTLONG(xdrs, (const xdrlong_t *)ulp)); case XDR_DECODE: - return (XDR_GETLONG(xdrs, (long *)ulp)); + return (XDR_GETLONG(xdrs, (xdrlong_t *)ulp)); case XDR_FREE: return (TRUE); } @@ -231,19 +250,19 @@ xdr_int32_t(xdrs, int32_p) XDR *xdrs; int32_t *int32_p; { - long l; + xdrlong_t l; switch (xdrs->x_op) { case XDR_ENCODE: - l = (long) *int32_p; - return (XDR_PUTLONG(xdrs, &l)); + l = *int32_p; + return (XDR_PUTLONG(xdrs, (const xdrlong_t *)&l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &l)) { return (FALSE); } - *int32_p = (int32_t) l; + *int32_p = l; return (TRUE); case XDR_FREE: @@ -262,19 +281,17 @@ xdr_u_int32_t(xdrs, u_int32_p) XDR *xdrs; u_int32_t *u_int32_p; { - u_long l; + u_int32_t l; switch (xdrs->x_op) { case XDR_ENCODE: - l = (u_long) *u_int32_p; - return (XDR_PUTLONG(xdrs, (long *)&l)); + l = *u_int32_p; + return (XDR_PUTLONG(xdrs, (xdrlong_t *)&l)); case XDR_DECODE: - if (!XDR_GETLONG(xdrs, (long *)&l)) { - return (FALSE); - } - *u_int32_p = (u_int32_t) l; + if (!XDR_GETLONG(xdrs, (xdrlong_t *)&l)) return (FALSE); + *u_int32_p = l; return (TRUE); case XDR_FREE: @@ -293,19 +310,19 @@ xdr_short(xdrs, sp) XDR *xdrs; short *sp; { - long l; + xdrlong_t l; switch (xdrs->x_op) { case XDR_ENCODE: - l = (long) *sp; - return (XDR_PUTLONG(xdrs, &l)); + l = *sp; + return (XDR_PUTLONG(xdrs, (const xdrlong_t *)&l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &l)) { return (FALSE); } - *sp = (short) l; + *sp = l; return (TRUE); case XDR_FREE: @@ -323,19 +340,19 @@ xdr_u_short(xdrs, usp) XDR *xdrs; u_short *usp; { - u_long l; + xdrlong_t l; switch (xdrs->x_op) { case XDR_ENCODE: - l = (u_long) *usp; - return (XDR_PUTLONG(xdrs, (long *)&l)); + l = *usp; + return (XDR_PUTLONG(xdrs, (const xdrlong_t *)&l)); case XDR_DECODE: - if (!XDR_GETLONG(xdrs, (long *)&l)) { + if (!XDR_GETLONG(xdrs, &l)) { return (FALSE); } - *usp = (u_short) l; + *usp = l; return (TRUE); case XDR_FREE: @@ -354,19 +371,19 @@ xdr_int16_t(xdrs, int16_p) XDR *xdrs; int16_t *int16_p; { - long l; + xdrlong_t l; switch (xdrs->x_op) { case XDR_ENCODE: - l = (long) *int16_p; - return (XDR_PUTLONG(xdrs, &l)); + l = *int16_p; + return (XDR_PUTLONG(xdrs, (const xdrlong_t *)&l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &l)) { return (FALSE); } - *int16_p = (int16_t) l; + *int16_p = l; return (TRUE); case XDR_FREE: @@ -384,19 +401,19 @@ xdr_u_int16_t(xdrs, u_int16_p) XDR *xdrs; u_int16_t *u_int16_p; { - u_long l; + xdrlong_t l; switch (xdrs->x_op) { case XDR_ENCODE: - l = (u_long) *u_int16_p; - return (XDR_PUTLONG(xdrs, (long *)&l)); + l = *u_int16_p; + return (XDR_PUTLONG(xdrs, (const xdrlong_t *)&l)); case XDR_DECODE: - if (!XDR_GETLONG(xdrs, (long *)&l)) { + if (!XDR_GETLONG(xdrs, &l)) { return (FALSE); } - *u_int16_p = (u_int16_t) l; + *u_int16_p = l; return (TRUE); case XDR_FREE: @@ -433,7 +450,7 @@ xdr_u_char(xdrs, cp) XDR *xdrs; u_char *cp; { - u_int u; + u_int32_t u; u = (*cp); if (!xdr_u_int(xdrs, &u)) { @@ -451,13 +468,13 @@ xdr_bool(xdrs, bp) XDR *xdrs; bool_t *bp; { - long lb; + xdrlong_t lb; switch (xdrs->x_op) { case XDR_ENCODE: lb = *bp ? XDR_TRUE : XDR_FALSE; - return (XDR_PUTLONG(xdrs, &lb)); + return (XDR_PUTLONG(xdrs, (const xdrlong_t *)&lb)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &lb)) { @@ -486,8 +503,8 @@ xdr_enum(xdrs, ep) /* * enums are treated as ints */ - /* LINTED */ if (sizeof (enum sizecheck) == sizeof (long)) { - return (xdr_long(xdrs, (long *)(void *)ep)); + /* LINTED */ if (sizeof (enum sizecheck) == sizeof (int)) { + return (xdr_long(xdrs, (xdrlong_t *)(void *)ep)); } else /* LINTED */ if (sizeof (enum sizecheck) == sizeof (int)) { return (xdr_int(xdrs, (int *)(void *)ep)); } else /* LINTED */ if (sizeof (enum sizecheck) == sizeof (short)) { @@ -508,7 +525,7 @@ xdr_opaque(xdrs, cp, cnt) caddr_t cp; u_int cnt; { - u_int rndup; + u_int32_t rndup; static int crud[BYTES_PER_XDR_UNIT]; /* @@ -562,7 +579,7 @@ xdr_bytes(xdrs, cpp, sizep, maxsize) u_int maxsize; { char *sp = *cpp; /* sp is the actual string pointer */ - u_int nodesize; + u_int32_t nodesize; /* * first deal with the length since xdr bytes are counted @@ -686,8 +703,8 @@ xdr_string(xdrs, cpp, maxsize) u_int maxsize; { char *sp = *cpp; /* sp is the actual string pointer */ - u_int size; - u_int nodesize; + u_int32_t size; + u_int32_t nodesize; /* * first deal with the length since xdr strings are counted-strings @@ -770,19 +787,19 @@ xdr_int64_t(xdrs, llp) XDR *xdrs; int64_t *llp; { - u_long ul[2]; + u_int32_t ul[2]; switch (xdrs->x_op) { case XDR_ENCODE: - ul[0] = (u_long)((u_int64_t)*llp >> 32) & 0xffffffff; - ul[1] = (u_long)((u_int64_t)*llp) & 0xffffffff; - if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE) + ul[0] = (u_int32_t)((u_int64_t)*llp >> 32) & 0xffffffff; + ul[1] = (u_int32_t)((u_int64_t)*llp) & 0xffffffff; + if (XDR_PUTLONG(xdrs, (xdrlong_t *)&ul[0]) == FALSE) return (FALSE); - return (XDR_PUTLONG(xdrs, (long *)&ul[1])); + return (XDR_PUTLONG(xdrs, (xdrlong_t *)&ul[1])); case XDR_DECODE: - if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE) + if (XDR_GETLONG(xdrs, (xdrlong_t *)&ul[0]) == FALSE) return (FALSE); - if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE) + if (XDR_GETLONG(xdrs, (xdrlong_t *)&ul[1]) == FALSE) return (FALSE); *llp = (int64_t) (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1])); @@ -803,19 +820,19 @@ xdr_u_int64_t(xdrs, ullp) XDR *xdrs; u_int64_t *ullp; { - u_long ul[2]; + u_int32_t ul[2]; switch (xdrs->x_op) { case XDR_ENCODE: - ul[0] = (u_long)(*ullp >> 32) & 0xffffffff; - ul[1] = (u_long)(*ullp) & 0xffffffff; - if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE) + ul[0] = (u_int32_t)(*ullp >> 32) & 0xffffffff; + ul[1] = (u_int32_t)(*ullp) & 0xffffffff; + if (XDR_PUTLONG(xdrs, (xdrlong_t *)&ul[0]) == FALSE) return (FALSE); - return (XDR_PUTLONG(xdrs, (long *)&ul[1])); + return (XDR_PUTLONG(xdrs, (xdrlong_t *)&ul[1])); case XDR_DECODE: - if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE) + if (XDR_GETLONG(xdrs, (xdrlong_t *)&ul[0]) == FALSE) return (FALSE); - if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE) + if (XDR_GETLONG(xdrs, (xdrlong_t *)&ul[1]) == FALSE) return (FALSE); *ullp = (u_int64_t) (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1])); @@ -836,7 +853,6 @@ xdr_hyper(xdrs, llp) XDR *xdrs; longlong_t *llp; { - /* * Don't bother open-coding this; it's a fair amount of code. Just * call xdr_int64_t(). @@ -853,7 +869,6 @@ xdr_u_hyper(xdrs, ullp) XDR *xdrs; u_longlong_t *ullp; { - /* * Don't bother open-coding this; it's a fair amount of code. Just * call xdr_u_int64_t(). @@ -870,7 +885,6 @@ xdr_longlong_t(xdrs, llp) XDR *xdrs; longlong_t *llp; { - /* * Don't bother open-coding this; it's a fair amount of code. Just * call xdr_int64_t(). diff --git a/rpc.subproj/xdr.h b/rpc.subproj/xdr.h index 24da1af..9492ccf 100644 --- a/rpc.subproj/xdr.h +++ b/rpc.subproj/xdr.h @@ -121,10 +121,17 @@ enum xdr_op { typedef struct __rpc_xdr { enum xdr_op x_op; /* operation; fast additional param */ const struct xdr_ops { +#ifdef __LP64__ + /* get an int from underlying stream */ + bool_t (*x_getlong)(struct __rpc_xdr *, int *); + /* put an int to " */ + bool_t (*x_putlong)(struct __rpc_xdr *, const int *); +#else /* get a long from underlying stream */ bool_t (*x_getlong)(struct __rpc_xdr *, long *); /* put a long to " */ bool_t (*x_putlong)(struct __rpc_xdr *, const long *); +#endif /* get some bytes from " */ bool_t (*x_getbytes)(struct __rpc_xdr *, char *, unsigned int); /* put some bytes to " */ @@ -181,25 +188,48 @@ typedef bool_t (*xdrproc_t)(XDR *, ...); #define xdr_putlong(xdrs, longp) \ (*(xdrs)->x_ops->x_putlong)(xdrs, longp) + +#ifdef __LP64__ static __inline int xdr_getint32(XDR *xdrs, int32_t *ip) { - long l; + int32_t l; if (!xdr_getlong(xdrs, &l)) return (FALSE); - *ip = (int32_t)l; + *ip = l; return (TRUE); } static __inline int xdr_putint32(XDR *xdrs, int32_t *ip) { - long l; + int32_t l; - l = (long)*ip; + l = *ip; return xdr_putlong(xdrs, &l); } +#else +static __inline int +xdr_getint32(XDR *xdrs, int32_t *ip) +{ + int32_t l; + + if (!xdr_getlong(xdrs, (long *)&l)) + return (FALSE); + *ip = l; + return (TRUE); +} + +static __inline int +xdr_putint32(XDR *xdrs, int32_t *ip) +{ + int32_t l; + + l = *ip; + return xdr_putlong(xdrs, (long *)&l); +} +#endif #define XDR_GETINT32(xdrs, int32p) xdr_getint32(xdrs, int32p) #define XDR_PUTINT32(xdrs, int32p) xdr_putint32(xdrs, int32p) @@ -287,12 +317,21 @@ struct xdr_discrim { #define IXDR_GET_U_INT32(buf) ((u_int32_t)IXDR_GET_INT32(buf)) #define IXDR_PUT_U_INT32(buf, v) IXDR_PUT_INT32((buf), ((int32_t)(v))) +#ifdef __LP64__ +#define IXDR_GET_LONG(buf) (ntohl((u_int32_t)*(buf)++)) +#define IXDR_PUT_LONG(buf, v) (*(buf)++ = htonl((u_int32_t)v)) +#else #define IXDR_GET_LONG(buf) ((long)ntohl((u_int32_t)*(buf)++)) #define IXDR_PUT_LONG(buf, v) (*(buf)++ =(int32_t)htonl((u_int32_t)v)) +#endif #define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf)) #define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf)) +#ifdef __LP64__ +#define IXDR_GET_U_LONG(buf) ((unsigned int)IXDR_GET_LONG(buf)) +#else #define IXDR_GET_U_LONG(buf) ((unsigned long)IXDR_GET_LONG(buf)) +#endif #define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf)) #define IXDR_GET_U_SHORT(buf) ((unsigned short)IXDR_GET_LONG(buf)) @@ -309,8 +348,13 @@ __BEGIN_DECLS extern bool_t xdr_void(void); extern bool_t xdr_int(XDR *, int *); extern bool_t xdr_u_int(XDR *, unsigned int *); +#ifdef __LP64__ +extern bool_t xdr_long(XDR *, int *); +extern bool_t xdr_u_long(XDR *, unsigned int *); +#else extern bool_t xdr_long(XDR *, long *); extern bool_t xdr_u_long(XDR *, unsigned long *); +#endif extern bool_t xdr_short(XDR *, short *); extern bool_t xdr_u_short(XDR *, unsigned short *); extern bool_t xdr_int16_t(XDR *, int16_t *); diff --git a/rpc.subproj/xdr_mem.c b/rpc.subproj/xdr_mem.c index ed2a65a..fc4dc82 100644 --- a/rpc.subproj/xdr_mem.c +++ b/rpc.subproj/xdr_mem.c @@ -71,6 +71,7 @@ static char *sccsid = "@(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC"; */ #include +#include #include @@ -79,11 +80,17 @@ static char *sccsid = "@(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC"; #include #include +#ifdef __LP64__ +#define xdrlong_t int +#else +#define xdrlong_t long +#endif + static void xdrmem_destroy(XDR *); -static bool_t xdrmem_getlong_aligned(XDR *, long *); -static bool_t xdrmem_putlong_aligned(XDR *, const long *); -static bool_t xdrmem_getlong_unaligned(XDR *, long *); -static bool_t xdrmem_putlong_unaligned(XDR *, const long *); +static bool_t xdrmem_getlong_aligned(XDR *, xdrlong_t *); +static bool_t xdrmem_putlong_aligned(XDR *, const xdrlong_t *); +static bool_t xdrmem_getlong_unaligned(XDR *, xdrlong_t *); +static bool_t xdrmem_putlong_unaligned(XDR *, const xdrlong_t *); static bool_t xdrmem_getbytes(XDR *, char *, u_int); static bool_t xdrmem_putbytes(XDR *, const char *, u_int); /* XXX: w/64-bit pointers, u_int not enough! */ @@ -125,7 +132,6 @@ xdrmem_create(xdrs, addr, size, op) u_int size; enum xdr_op op; { - xdrs->x_op = op; xdrs->x_ops = ((unsigned long)addr & (sizeof(int32_t) - 1)) ? &xdrmem_ops_unaligned : &xdrmem_ops_aligned; @@ -138,15 +144,13 @@ static void xdrmem_destroy(xdrs) XDR *xdrs; { - } static bool_t xdrmem_getlong_aligned(xdrs, lp) XDR *xdrs; - long *lp; + xdrlong_t *lp; { - if (xdrs->x_handy < sizeof(int32_t)) return (FALSE); xdrs->x_handy -= sizeof(int32_t); @@ -158,9 +162,8 @@ xdrmem_getlong_aligned(xdrs, lp) static bool_t xdrmem_putlong_aligned(xdrs, lp) XDR *xdrs; - const long *lp; + const xdrlong_t *lp; { - if (xdrs->x_handy < sizeof(int32_t)) return (FALSE); xdrs->x_handy -= sizeof(int32_t); @@ -172,7 +175,7 @@ xdrmem_putlong_aligned(xdrs, lp) static bool_t xdrmem_getlong_unaligned(xdrs, lp) XDR *xdrs; - long *lp; + xdrlong_t *lp; { u_int32_t l; @@ -188,7 +191,7 @@ xdrmem_getlong_unaligned(xdrs, lp) static bool_t xdrmem_putlong_unaligned(xdrs, lp) XDR *xdrs; - const long *lp; + const xdrlong_t *lp; { u_int32_t l; @@ -207,7 +210,6 @@ xdrmem_getbytes(xdrs, addr, len) char *addr; u_int len; { - if (xdrs->x_handy < len) return (FALSE); xdrs->x_handy -= len; @@ -222,7 +224,6 @@ xdrmem_putbytes(xdrs, addr, len) const char *addr; u_int len; { - if (xdrs->x_handy < len) return (FALSE); xdrs->x_handy -= len; @@ -235,9 +236,16 @@ static u_int xdrmem_getpos(xdrs) XDR *xdrs; { + ptrdiff_t delta; + u_int val; - /* XXX w/64-bit pointers, u_int not enough! */ - return (u_int)((u_long)xdrs->x_private - (u_long)xdrs->x_base); + delta = xdrs->x_private - (void *)(xdrs->x_base); +#ifdef __LP64__ + if (delta > UINT32_MAX) return -1; +#endif + + val = delta; + return val; } static bool_t @@ -245,13 +253,18 @@ xdrmem_setpos(xdrs, pos) XDR *xdrs; u_int pos; { + ptrdiff_t delta; char *newaddr = xdrs->x_base + pos; char *lastaddr = (char *)xdrs->x_private + xdrs->x_handy; if (newaddr > lastaddr) return (FALSE); xdrs->x_private = newaddr; - xdrs->x_handy = (u_int)(lastaddr - newaddr); /* XXX sizeof(u_int) UINT32_MAX) return (FALSE); +#endif + xdrs->x_handy = delta; return (TRUE); } @@ -276,6 +289,5 @@ xdrmem_inline_unaligned(xdrs, len) XDR *xdrs; u_int len; { - return (0); } diff --git a/rpc.subproj/xdr_rec.c b/rpc.subproj/xdr_rec.c index 844c327..77fffec 100644 --- a/rpc.subproj/xdr_rec.c +++ b/rpc.subproj/xdr_rec.c @@ -71,7 +71,7 @@ static char *sccsid = "@(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC"; * and the tcp transport level. A record is composed on one or more * record fragments. A record fragment is a thirty-two bit header followed * by n bytes of data, where n is contained in the header. The header - * is represented as a htonl(u_long). Thegh order bit encodes + * is in network byte order. Thegh order bit encodes * whether or not the fragment is the last fragment of the record * (1 => fragment is last, 0 => more fragments to follow. * The other 31 bits encode the byte length of the fragment. @@ -85,6 +85,7 @@ static char *sccsid = "@(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC"; #include #include #include +#include #include #include @@ -92,8 +93,14 @@ static char *sccsid = "@(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC"; #include #include +#ifdef __LP64__ +static bool_t xdrrec_getlong(XDR *, int *); +static bool_t xdrrec_putlong(XDR *, const int *); +#else static bool_t xdrrec_getlong(XDR *, long *); static bool_t xdrrec_putlong(XDR *, const long *); +#endif + static bool_t xdrrec_getbytes(XDR *, char *, u_int); static bool_t xdrrec_putbytes(XDR *, const char *, u_int); @@ -102,6 +109,8 @@ static bool_t xdrrec_setpos(XDR *, u_int); static int32_t *xdrrec_inline(XDR *, u_int); static void xdrrec_destroy(XDR *); +bool_t __xdrrec_getrec(XDR *, enum xprt_stat *, bool_t); + static const struct xdr_ops xdrrec_ops = { xdrrec_getlong, xdrrec_putlong, @@ -116,7 +125,7 @@ static const struct xdr_ops xdrrec_ops = { /* * A record is composed of one or more record fragments. * A record fragment is a four-byte header followed by zero to - * 2**32-1 bytes. The header is treated as a long unsigned and is + * 2**32-1 bytes. The header is treated as an unsigned 32-bit integer and is * encode/decoded to the network via htonl/ntohl. The low order 31 bits * are a byte count of the fragment. The highest order bit is a boolean: * 1 => this fragment is the last fragment of the record, @@ -129,7 +138,7 @@ static const struct xdr_ops xdrrec_ops = { #define LAST_FRAG ((u_int32_t)(1 << 31)) typedef struct rec_strm { - char *tcp_handle; + void *tcp_handle; /* * out-goung bits */ @@ -143,11 +152,11 @@ typedef struct rec_strm { * in-coming bits */ int (*readit)(void *, void *, int); - u_long in_size; /* fixed size of the input buffer */ + size_t in_size; /* fixed size of the input buffer */ char *in_base; char *in_finger; /* location of next byte to be had */ char *in_boundry; /* can read up to this location */ - long fbtbc; /* fragment bytes to be consumed */ + int fbtbc; /* fragment bytes to be consumed */ bool_t last_frag; u_int sendsize; u_int recvsize; @@ -167,7 +176,7 @@ static bool_t flush_out(RECSTREAM *, bool_t); static bool_t fill_input_buf(RECSTREAM *); static bool_t get_input_bytes(RECSTREAM *, char *, int); static bool_t set_input_fragment(RECSTREAM *); -static bool_t skip_input_bytes(RECSTREAM *, long); +static bool_t skip_input_bytes(RECSTREAM *, int); static bool_t realloc_stream(RECSTREAM *, int); @@ -251,48 +260,58 @@ xdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit) static bool_t xdrrec_getlong(xdrs, lp) XDR *xdrs; +#ifdef __LP64__ + int *lp; +#else long *lp; +#endif { RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); int32_t *buflp = (int32_t *)(void *)(rstrm->in_finger); int32_t mylong; /* first try the inline, fast case */ - if ((rstrm->fbtbc >= sizeof(int32_t)) && - (((long)rstrm->in_boundry - (long)buflp) >= sizeof(int32_t))) { - *lp = (long)ntohl((u_int32_t)(*buflp)); + if ((rstrm->fbtbc >= sizeof(int32_t)) && ((rstrm->in_boundry - (char *)buflp) >= sizeof(int32_t))) + { + *lp = ntohl(*buflp); rstrm->fbtbc -= sizeof(int32_t); rstrm->in_finger += sizeof(int32_t); - } else { - if (! xdrrec_getbytes(xdrs, (char *)(void *)&mylong, - sizeof(int32_t))) - return (FALSE); - *lp = (long)ntohl((u_int32_t)mylong); } + else + { + if (! xdrrec_getbytes(xdrs, (char *)(void *)&mylong, sizeof(int32_t))) return (FALSE); + *lp = ntohl(mylong); + } + return (TRUE); } static bool_t xdrrec_putlong(xdrs, lp) XDR *xdrs; +#ifdef __LP64__ + const int *lp; +#else const long *lp; +#endif { RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); int32_t *dest_lp = ((int32_t *)(void *)(rstrm->out_finger)); - if ((rstrm->out_finger += sizeof(int32_t)) > rstrm->out_boundry) { + if ((rstrm->out_finger += sizeof(int32_t)) > rstrm->out_boundry) + { /* * this case should almost never happen so the code is * inefficient */ rstrm->out_finger -= sizeof(int32_t); rstrm->frag_sent = TRUE; - if (! flush_out(rstrm, FALSE)) - return (FALSE); + if (! flush_out(rstrm, FALSE)) return (FALSE); dest_lp = ((int32_t *)(void *)(rstrm->out_finger)); rstrm->out_finger += sizeof(int32_t); } - *dest_lp = (int32_t)htonl((u_int32_t)(*lp)); + + *dest_lp = htonl(*lp); return (TRUE); } @@ -334,8 +353,7 @@ xdrrec_putbytes(xdrs, addr, len) size_t current; while (len > 0) { - current = (size_t)((u_long)rstrm->out_boundry - - (u_long)rstrm->out_finger); + current = (size_t)(rstrm->out_boundry - rstrm->out_finger); current = (len < current) ? len : current; memmove(rstrm->out_finger, addr, current); rstrm->out_finger += current; @@ -356,8 +374,13 @@ xdrrec_getpos(xdrs) { RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; off_t pos; + int hfd; + + /* tcp_handle is in actual fact just a file descriptor */ + hfd = 0; + memcpy(&hfd, rstrm->tcp_handle, sizeof(hfd)); - pos = lseek((int)(u_long)rstrm->tcp_handle, (off_t)0, 1); + pos = lseek(hfd, 0, 1); if (pos != -1) switch (xdrs->x_op) { @@ -533,17 +556,15 @@ xdrrec_endofrecord(xdrs, sendnow) bool_t sendnow; { RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); - u_long len; /* fragment length */ + unsigned int len; /* fragment length */ if (sendnow || rstrm->frag_sent || - ((u_long)rstrm->out_finger + sizeof(u_int32_t) >= - (u_long)rstrm->out_boundry)) { + (rstrm->out_finger + sizeof(u_int32_t) >= rstrm->out_boundry)) { rstrm->frag_sent = FALSE; return (flush_out(rstrm, TRUE)); } - len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->frag_header) - - sizeof(u_int32_t); - *(rstrm->frag_header) = htonl((u_int32_t)len | LAST_FRAG); + len = rstrm->out_finger - (char *)(rstrm->frag_header) - sizeof(u_int32_t); + *(rstrm->frag_header) = htonl(len | LAST_FRAG); rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_finger; rstrm->out_finger += sizeof(u_int32_t); return (TRUE); @@ -653,14 +674,11 @@ flush_out(rstrm, eor) bool_t eor; { u_int32_t eormask = (eor == TRUE) ? LAST_FRAG : 0; - u_int32_t len = (u_int32_t)((u_long)(rstrm->out_finger) - - (u_long)(rstrm->frag_header) - sizeof(u_int32_t)); + u_int32_t len = rstrm->out_finger - (char *)(rstrm->frag_header) - sizeof(u_int32_t); *(rstrm->frag_header) = htonl(len | eormask); - len = (u_int32_t)((u_long)(rstrm->out_finger) - - (u_long)(rstrm->out_base)); - if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len) - != (int)len) + len = rstrm->out_finger - rstrm->out_base; + if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, len) != len) return (FALSE); rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_base; rstrm->out_finger = (char *)rstrm->out_base + sizeof(u_int32_t); @@ -679,9 +697,9 @@ fill_input_buf(rstrm) return FALSE; where = rstrm->in_base; - i = (u_int32_t)((u_long)rstrm->in_boundry % BYTES_PER_XDR_UNIT); + i = (size_t)(rstrm->in_boundry) % BYTES_PER_XDR_UNIT; where += i; - len = (u_int32_t)(rstrm->in_size - i); + len = rstrm->in_size - i; if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1) return (FALSE); rstrm->in_finger = where; @@ -707,8 +725,7 @@ get_input_bytes(rstrm, addr, len) } while (len > 0) { - current = (size_t)((long)rstrm->in_boundry - - (long)rstrm->in_finger); + current = (size_t)(rstrm->in_boundry - rstrm->in_finger); if (current == 0) { if (! fill_input_buf(rstrm)) return (FALSE); @@ -752,19 +769,18 @@ set_input_fragment(rstrm) static bool_t /* consumes input bytes; knows nothing about records! */ skip_input_bytes(rstrm, cnt) RECSTREAM *rstrm; - long cnt; + int cnt; { u_int32_t current; while (cnt > 0) { - current = (size_t)((long)rstrm->in_boundry - - (long)rstrm->in_finger); + current = (size_t)(rstrm->in_boundry - rstrm->in_finger); if (current == 0) { if (! fill_input_buf(rstrm)) return (FALSE); continue; } - current = (u_int32_t)((cnt < current) ? cnt : current); + current = (cnt < current) ? cnt : current; rstrm->in_finger += current; cnt -= current; } @@ -789,7 +805,7 @@ realloc_stream(rstrm, size) RECSTREAM *rstrm; int size; { - long diff; + int diff; char *buf; if (size > rstrm->recvsize) { diff --git a/rpc.subproj/xdr_sizeof.c b/rpc.subproj/xdr_sizeof.c index a96c1e8..318a5b8 100644 --- a/rpc.subproj/xdr_sizeof.c +++ b/rpc.subproj/xdr_sizeof.c @@ -70,7 +70,11 @@ static bool_t x_putlong(xdrs, longp) XDR *xdrs; +#ifdef __LP64__ + int *longp; +#else long *longp; +#endif { xdrs->x_handy += BYTES_PER_XDR_UNIT; return (TRUE); @@ -109,7 +113,7 @@ x_inline(xdrs, len) XDR *xdrs; u_int len; { - long llen; + size_t llen; if (len == 0) { return (NULL); @@ -120,7 +124,7 @@ x_inline(xdrs, len) llen = len; - if (llen < xdrs->x_base) { + if (llen < (size_t)xdrs->x_base) { /* x_private was already allocated */ xdrs->x_handy += llen; return ((int32_t *) xdrs->x_private); @@ -158,7 +162,11 @@ x_destroy(xdrs) return; } +#ifdef __LP64__ +unsigned int +#else unsigned long +#endif xdr_sizeof(func, data) xdrproc_t func; void *data; @@ -167,7 +175,11 @@ xdr_sizeof(func, data) struct xdr_ops ops; bool_t stat; /* to stop ANSI-C compiler from complaining */ +#ifdef __LP64__ + typedef bool_t (* dummyfunc1)(XDR *, int *); +#else typedef bool_t (* dummyfunc1)(XDR *, long *); +#endif typedef bool_t (* dummyfunc2)(XDR *, caddr_t, u_int); ops.x_putlong = x_putlong; diff --git a/rpc.subproj/xdr_stdio.c b/rpc.subproj/xdr_stdio.c index ec955bc..2bdc4af 100644 --- a/rpc.subproj/xdr_stdio.c +++ b/rpc.subproj/xdr_stdio.c @@ -76,8 +76,13 @@ static char *sccsid = "@(#)xdr_stdio.c 2.1 88/07/29 4.0 RPCSRC"; #include static void xdrstdio_destroy(XDR *); +#ifdef __LP64__ +static bool_t xdrstdio_getlong(XDR *, int *); +static bool_t xdrstdio_putlong(XDR *, const int *); +#else static bool_t xdrstdio_getlong(XDR *, long *); static bool_t xdrstdio_putlong(XDR *, const long *); +#endif static bool_t xdrstdio_getbytes(XDR *, char *, u_int); static bool_t xdrstdio_putbytes(XDR *, const char *, u_int); static u_int xdrstdio_getpos(XDR *); @@ -109,7 +114,6 @@ xdrstdio_create(xdrs, file, op) FILE *file; enum xdr_op op; { - xdrs->x_op = op; xdrs->x_ops = &xdrstdio_ops; xdrs->x_private = file; @@ -126,31 +130,38 @@ xdrstdio_destroy(xdrs) XDR *xdrs; { (void)fflush((FILE *)xdrs->x_private); - /* XXX: should we close the file ?? */ + /* XXX: should we close the file ?? */ } static bool_t xdrstdio_getlong(xdrs, lp) XDR *xdrs; +#ifdef __LP64__ + int *lp; +#else long *lp; +#endif { u_int32_t temp; if (fread(&temp, sizeof(int32_t), 1, (FILE *)xdrs->x_private) != 1) return (FALSE); - *lp = (long)ntohl(temp); + *lp = ntohl(temp); return (TRUE); } static bool_t xdrstdio_putlong(xdrs, lp) XDR *xdrs; +#ifdef __LP64__ + const int *lp; +#else const long *lp; +#endif { - int32_t mycopy = htonl((u_int32_t)*lp); + int32_t mycopy = htonl(*lp); - if (fwrite(&mycopy, sizeof(int32_t), 1, (FILE *)xdrs->x_private) != 1) - return (FALSE); + if (fwrite(&mycopy, sizeof(int32_t), 1, (FILE *)xdrs->x_private) != 1) return (FALSE); return (TRUE); } @@ -160,9 +171,9 @@ xdrstdio_getbytes(xdrs, addr, len) char *addr; u_int len; { + size_t flen = len; - if ((len != 0) && (fread(addr, (size_t)len, 1, (FILE *)xdrs->x_private) != 1)) - return (FALSE); + if ((len != 0) && (fread(addr, flen, 1, (FILE *)xdrs->x_private) != 1)) return (FALSE); return (TRUE); } @@ -172,29 +183,38 @@ xdrstdio_putbytes(xdrs, addr, len) const char *addr; u_int len; { + size_t flen = len; - if ((len != 0) && (fwrite(addr, (size_t)len, 1, - (FILE *)xdrs->x_private) != 1)) - return (FALSE); + if ((len != 0) && (fwrite(addr, flen, 1, (FILE *)xdrs->x_private) != 1)) return (FALSE); return (TRUE); } +/* This only works if file offsets are <= UINT32_MAX */ static u_int xdrstdio_getpos(xdrs) XDR *xdrs; { + long offset; + u_int val; - return ((u_int) ftell((FILE *)xdrs->x_private)); + offset = ftell((FILE *)xdrs->x_private); +#ifdef __LP64__ + if (offset > UINT32_MAX) return -1; +#endif + val = offset; + return val; } +/* This only works if file offsets are <= UINT32_MAX */ static bool_t xdrstdio_setpos(xdrs, pos) XDR *xdrs; u_int pos; { + long offset; - return ((fseek((FILE *)xdrs->x_private, (long)pos, 0) < 0) ? - FALSE : TRUE); + offset = pos; + return ((fseek((FILE *)xdrs->x_private, offset, 0) < 0) ? FALSE : TRUE); } /* ARGSUSED */ diff --git a/util.subproj/Makefile.postamble b/util.subproj/Makefile.postamble index d5e61ec..d1c33e5 100644 --- a/util.subproj/Makefile.postamble +++ b/util.subproj/Makefile.postamble @@ -119,3 +119,4 @@ install-man-page: $(LN) -f "$(DSTROOT)/usr/share/man/man3/rcmd.3" "$(DSTROOT)/usr/share/man/man3/ruserok.3" mkdir -p "$(DSTROOT)/usr/share/man/man5" install -c -m 644 hosts.equiv.5 "$(DSTROOT)/usr/share/man/man5" + $(LN) -f "$(DSTROOT)/usr/share/man/man5//hosts.equiv.5" "$(DSTROOT)/usr/share/man/man5/.rhosts.5" diff --git a/util.subproj/Makefile.preamble b/util.subproj/Makefile.preamble index 7b61caa..1d8f0c6 100644 --- a/util.subproj/Makefile.preamble +++ b/util.subproj/Makefile.preamble @@ -1,5 +1,6 @@ AFTER_POSTINSTALL += install-man-page OTHER_CFLAGS = \ + -D__DARWIN_NON_CANCELABLE=1 \ -DINET6=1 # for building 64-bit diff --git a/util.subproj/hosts.equiv.5 b/util.subproj/hosts.equiv.5 index c96e48f..b11dc76 100755 --- a/util.subproj/hosts.equiv.5 +++ b/util.subproj/hosts.equiv.5 @@ -167,7 +167,6 @@ Per-user trusted host-user pairs list .Xr rcmd 3 , .Xr ruserok 3 , .Xr netgroup 5 -.Re .Sh HISTORY The .Nm .rhosts diff --git a/util.subproj/putpwpasswd.c b/util.subproj/putpwpasswd.c index 976ef2f..99894a4 100644 --- a/util.subproj/putpwpasswd.c +++ b/util.subproj/putpwpasswd.c @@ -21,117 +21,9 @@ * * @APPLE_LICENSE_HEADER_END@ */ -/* - * putpwpasswd() - * Copyright (C) 1989 by NeXT, Inc. - * - * Changes a user's password entry. Works only for NetInfo. - * - * NOTE: This is not done in lookupd because we need to know - * the identity of the user and there is currently no way to - * get that information through a Mach message. Privileged users - * get privileged sockets and do not need to supply a old password - * if they are changing their password on the master server for their - * account entry. Unprivileged users get unprivileged sockets and must - * supply the old password. - */ -#include -#include -#include -#include -#include -#include - -static const ni_name NAME_USERS = "users"; -static const ni_name NAME_PASSWD = "passwd"; - -static int -changeit( - void *ni, - ni_id *id, - char *login, - char *old_passwd, - char *new_passwd - ) -{ - ni_proplist pl; - ni_index i; - ni_index prop_index; - ni_property prop; - ni_status stat; - - ni_setabort(ni, TRUE); - ni_needwrite(ni, TRUE); - ni_setuser(ni, login); - ni_setpassword(ni, old_passwd); - - if (ni_read(ni, id, &pl) != NI_OK) { - return (0); - } - prop_index = NI_INDEX_NULL; - for (i = 0; i < pl.nipl_len; i++) { - if (ni_name_match(pl.nipl_val[i].nip_name, NAME_PASSWD)) { - prop_index = i; - break; - } - } - if (prop_index == NI_INDEX_NULL) { - prop.nip_name = NAME_PASSWD; - prop.nip_val.ninl_len = 1; - prop.nip_val.ninl_val = &new_passwd; - stat = ni_createprop(ni, id, prop, NI_INDEX_NULL); - } else { - if (pl.nipl_val[i].nip_val.ninl_len == 0) { - stat = ni_createname(ni, id, prop_index, - new_passwd, 0); - } else { - stat = ni_writename(ni, id, prop_index, 0, - new_passwd); - } - } - ni_proplist_free(&pl); - return (stat == NI_OK); -} int -putpwpasswd( - char *login, - char *old_passwd, /* cleartext */ - char *new_passwd /* encrypted */ - ) +putpwpasswd(char *login, char *old_passwd, char *new_passwd) { - char *dir; - void *ni; - void *newni; - ni_id id; - ni_status stat; - int changed; - - stat = ni_open(NULL, ".", &ni); - if (stat != NI_OK) { - return (0); - } - - dir = malloc(1 + strlen(NAME_USERS) + 1 + strlen(login) + 1); - sprintf(dir, "/%s/%s", NAME_USERS, login); - - changed = 0; - for (;;) { - stat = ni_pathsearch(ni, &id, dir); - if (stat == NI_OK) { - changed = changeit(ni, &id, login, old_passwd, - new_passwd); - break; - } - stat = ni_open(ni, "..", &newni); - if (stat != NI_OK) { - break; - } - ni_free(ni); - ni = newni; - } - free(dir); - ni_free(ni); - return (changed); -} - + return 0; +} diff --git a/util.subproj/pwcache.c b/util.subproj/pwcache.c index 53e79f3..ce31e7a 100644 --- a/util.subproj/pwcache.c +++ b/util.subproj/pwcache.c @@ -21,6 +21,14 @@ * * @APPLE_LICENSE_HEADER_END@ */ +/* + * Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved + * + * Copyright (c) 1980, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * @(#)fstab.c 8.1 (Berkeley) 6/4/93 + */ #include @@ -30,6 +38,7 @@ #include #include #include +#include #define NCACHE 64 /* power of 2 */ #define MASK (NCACHE - 1) /* bits to store with */ @@ -41,7 +50,7 @@ user_from_uid(uid, nouser) { static struct ncache { uid_t uid; - char name[UT_NAMESIZE + 1]; + char name[_UTX_USERSIZE + 1]; } *c_uid[NCACHE]; static int pwopen; static char nbuf[15]; /* 32 bits == 10 digits */ @@ -67,8 +76,8 @@ err: goto err; } (*cp)->uid = uid; - (void)strncpy((*cp)->name, pw->pw_name, UT_NAMESIZE); - (*cp)->name[UT_NAMESIZE] = '\0'; + (void)strncpy((*cp)->name, pw->pw_name, _UTX_USERSIZE); + (*cp)->name[_UTX_USERSIZE] = '\0'; } return ((*cp)->name); } @@ -80,7 +89,7 @@ group_from_gid(gid, nogroup) { static struct ncache { gid_t gid; - char name[UT_NAMESIZE + 1]; + char name[_UTX_USERSIZE + 1]; } *c_gid[NCACHE]; static int gropen; static char nbuf[15]; /* 32 bits == 10 digits */ @@ -106,8 +115,8 @@ err: goto err; } (*cp)->gid = gid; - (void)strncpy((*cp)->name, gr->gr_name, UT_NAMESIZE); - (*cp)->name[UT_NAMESIZE] = '\0'; + (void)strncpy((*cp)->name, gr->gr_name, _UTX_USERSIZE); + (*cp)->name[_UTX_USERSIZE] = '\0'; } return ((*cp)->name); } diff --git a/util.subproj/rcmd.c b/util.subproj/rcmd.c index 8472938..02c497b 100644 --- a/util.subproj/rcmd.c +++ b/util.subproj/rcmd.c @@ -66,9 +66,7 @@ static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94"; #include #include -#include #include -#include #include #include @@ -79,6 +77,7 @@ static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94"; #include #include #include +#include #ifdef YP #include #include @@ -234,7 +233,7 @@ rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af) } else { char num[8]; int s2 = rresvport_af(&lport, ai->ai_family), s3; - int len = ai->ai_addrlen; + unsigned int len = ai->ai_addrlen; int nfds; if (s2 < 0) @@ -404,6 +403,9 @@ rresvport_af(alport, family) int __check_rhosts_file = 1; char *__rcmd_errstr; +/* Guess at the size of a password buffer for getpwnam_r (see lookup.subproj/lu_group.c) */ +#define MAXPWBUF (MAXLOGNAME + 1 + _PASSWORD_LEN + 1 + MAXPATHLEN + 1 + MAXPATHLEN + 1 + 4098) + /* * AF independent extension of iruserok. * @@ -418,13 +420,14 @@ iruserok_sa(ra, rlen, superuser, ruser, luser) { register char *cp; struct stat sbuf; - struct passwd *pwd; + struct passwd p, *pwd; FILE *hostf; uid_t uid; - int first; + int first, status; char pbuf[MAXPATHLEN]; const struct sockaddr *raddr; struct sockaddr_storage ss; + char pwbuf[MAXPWBUF]; /* avoid alignment issue */ if (rlen > sizeof(ss)) @@ -444,8 +447,14 @@ again: } if (first == 1 && (__check_rhosts_file || superuser)) { first = 0; - if ((pwd = getpwnam(luser)) == NULL) - return (-1); + + memset(&p, 0, sizeof(struct passwd)); + memset(pwbuf, 0, sizeof(pwbuf)); + pwd = NULL; + + status = getpwnam_r(luser, &p, pwbuf, MAXPWBUF, &pwd); + if (status != 0) return -1; + (void)strcpy(pbuf, pwd->pw_dir); (void)strcat(pbuf, "/.rhosts"); -- 2.45.2