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
netinfo.subproj,
nis.subproj,
rpc.subproj,
- util.subproj,
- mdns.subproj
+ util.subproj
);
};
LANGUAGE = English;
OTHER_CFLAGS = \
+ -D__DARWIN_NON_CANCELABLE=1 \
-Dsethostent=_res_sethostent \
-Dgethostent=_res_gethostent \
-Dendhostent=_res_endhostent \
"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;
extern int h_errno;
-extern int _lu_running(void);
-
#ifdef DEBUG
static void
dprintf(msg, num)
return (gethostbyname2(name, AF_INET));
}
+#ifdef NOTDEF
static struct hostent *
gethostbyname_ipv4(name)
const char *name;
}
return (getanswer(&buf, n, name, C_IN, T_A));
}
+#endif
struct hostent *
gethostbyaddr(vaddr, len, type)
/*
* @(#)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_
/* External definitions for functions in inet(3) */
+#include <_types.h>
#include <stdint.h> /* uint32_t uint16_t */
-#include <machine/endian.h> /* htonl() and family if !_POSIX_C_SOURCE */
-#include <sys/_endian.h> /* htonl() and family if _POSIX_C_SOURCE */
+#include <machine/endian.h> /* htonl() and family if (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */
+#include <sys/_endian.h> /* htonl() and family if (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */
#include <netinet/in.h> /* in_addr */
-#include <sys/param.h>
-#if (!defined(BSD)) || (BSD < 199306)
-# include <sys/bitypes.h>
-#else
-# include <sys/types.h>
-#endif
-#include <sys/cdefs.h>
__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 *);
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
#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
* 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) */
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;
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);
# 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 <netinfo/ni.h>
-# 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
#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 &&
}
#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()
{
struct timeval timeout;
fd_set dsmask;
struct sockaddr_in from;
- int fromlen;
+ unsigned int fromlen;
if ((s < 0) || vc) {
if (vc)
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
$(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"
AFTER_POSTINSTALL += install-man-page
OTHER_CFLAGS = \
+ -D__DARWIN_NON_CANCELABLE=1 \
-DINET6=1 \
-Dsetservent=_old_setservent \
-Dgetservent=_old_getservent \
# for building 64-bit
# <rdar://problem/3819761> 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 > $@
Makefile.preamble,
Makefile,
Makefile.postamble,
- ether_addr.3,
getifaddrs.3,
if_indextoname.3,
inet6_rthdr_space.3,
+++ /dev/null
-.so man3/ethers.3
*
* @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 <errno.h>
#include <fstab.h>
return((_gr_fp = fopen(_PATH_GROUP, "r")) ? 1 : 0);
}
-int
+void
setgrent()
{
- return(setgroupent(0));
+ setgroupent(0);
}
int
.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 <netdb.h>
.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 ,
will result in an answer;
for example, a mail-forwarder may be registered for this domain.
.El
+.Sh LEGACY SYNOPSIS
+.Fd #include <netdb.h>
+.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 ,
#include <errno.h>
#include <ifaddrs.h>
+#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
+#include <stdint.h>
#if !defined(AF_LINK)
#define SA_LEN(sa) sizeof(struct sockaddr)
#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
#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;
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];
struct ifreq *ifr;
struct ifreq *lifr;
#endif /* NET_RT_IFLIST */
- int i;
+ int i, status;
size_t len, alen;
char *data;
char *names;
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) {
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];
++icnt;
dcnt += SA_RLEN(sa);
ncnt += sizeof(ifr->ifr_name) + 1;
-
+
ifr = (struct ifreq *)(((char *)sa) + SA_LEN(sa));
}
#endif /* NET_RT_IFLIST */
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);
}
*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);
}
.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 <netdb.h>
+.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 ,
.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 <netdb.h>
+.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 ,
/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2007 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
*
* /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
#include <stdlib.h>
#include <string.h>
#include <pwd.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
#include <unistd.h>
#define forever for (;;)
#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)
return insertString(s, l, (unsigned int)-1);
}
-
static char **
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 */
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;
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];
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)
{
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)
{
}
}
-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] == '#')
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;
+ }
}
.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 <netdb.h>
+.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 ,
.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
.Fd #include <sys/types.h>
.Fd #include <sys/socket.h>
.Fd #include <net/if.h>
-.Ft "unsigned int"
-.Fn if_nametoindex "const char *ifname"
+.Ft 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
#include <stdio.h>
#include <stdint.h>
#include <string.h>
+#include <errno.h>
#include <sys/socket.h>
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);
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--)
else j = 0;
zr[i] = j;
}
-
+
/* find longest run of zeros */
k = -1;
j = 0;
j = zr[i];
}
}
-
+
for(i = 0; i < 8; i++)
{
if (i != k) zr[i] = 0;
}
-
+
len = 0;
for (i = 0; i < 8; i++)
{
/* 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;
}
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <net/if.h>
#include <arpa/nameser.h>
#include <string.h>
#include <stdlib.h>
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;
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
* 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;
* 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;
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) {
*/
const int n = tp - colonp;
int i;
-
+
if (tp == endp)
return (0);
for (i = 1; i <= n; i++) {
#include <err.h>
#include <pwd.h>
+__private_extern__ struct passwd *LI_files_getpwnam(const char *name);
+
+/* this is _old_initgroups */
int
initgroups(uname, agroup)
const char *uname;
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 */
*/
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
#include <printerdb.h>
-#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 *);
--- /dev/null
+/*
+ * 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 <sys/types.h>;
+
+#include <mach/std_types.defs>
+#include <mach/mach_types.defs>
+
+import <DSlibinfoMIG_types.h>;
+
+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
+);
--- /dev/null
+/*
+ * 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 <sys/types.h>;
+
+#include <mach/std_types.defs>
+#include <mach/mach_types.defs>
+
+import <DSlibinfoMIG_types.h>;
+
+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
+);
--- /dev/null
+/*
+ * 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__ */
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
%_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)
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"
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
# <rdar://problem/3819761> Libinfo need to build with gcc-3.5 and 3-way fat
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 = (
--- /dev/null
+.\" 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.
--- /dev/null
+.\" $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 <sys/types.h>
+.Fd #include <sys/socket.h>
+.Fd #include <netdb.h>
+.Pp
+The include files
+.In sys/types.h
+and
+.In sys/socket.h
+are necessary.
+.Sh SEE ALSO
+.Xr getaddrinfo 3 ,
+.Xr getnameinfo 3
.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 <sys/types.h>
.Fd #include <sys/socket.h>
.Fd #include <netdb.h>
-.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
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
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.
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
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
.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.
}
freeaddrinfo(res0);
.Ed
+.Sh LEGACY SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/socket.h>
+.Fd #include <netdb.h>
+.Pp
+The include file
+.In sys/types.h
+is necessary.
.Sh SEE ALSO
.Xr bind 2 ,
.Xr connect 2 ,
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.
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
-#include <errno.h>
#include <stdio.h>
+#include <errno.h>
#include <ctype.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#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;
}
}
-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)
{
}
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;
}
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;
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;
}
/*
- * getaddrinfo support in lookupd
+ * getaddrinfo
+ *
* Input dict may contain the following
*
* name: nodename
*/
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;
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)
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;
}
}
- 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
}
else
{
- return EAI_NODATA;
+ return EAI_NONAME;
}
proto = IPPROTO_UNSPEC;
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;
struct in6_addr a6;
struct addrinfo *a;
+ count = 0;
+ scopeid = 0;
+
numericserv = 0;
if (servname != NULL) numericserv = is_a_number(servname);
{
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;
+ }
}
}
}
{
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++;
}
}
{
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++)
{
{
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;
}
}
- 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))
{
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;
}
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;
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;
}
}
- 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;
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;
}
{
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;
}
*/
/*
- * getnameinfo support in lookupd
+ * getnameinfo support in Directory Service
* Input dict may contain the following
*
* ip_address: node address
*/
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))
{
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)
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)
{
switch (s6->sin6_addr.s6_addr[0])
{
case 0x00:
+ {
if (IN6_IS_ADDR_V4MAPPED(&s6->sin6_addr))
{
}
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;
}
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;
/* 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;
*/
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)
{
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;
if (gni_proc < 0)
{
- status = _lookup_link(server_port, "getnameinfo", &gni_proc);
+ status = LI_DSLookupGetProcedureNumber("getnameinfo", &gni_proc);
if (status != KERN_SUCCESS)
{
errno = ECONNREFUSED;
}
}
- 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;
}
}
- 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;
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;
}
{
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);
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;
}
--- /dev/null
+.\" 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.
--- /dev/null
+.\" 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 <grp.h>
+.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.
--- /dev/null
+.\" 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 .
.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
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
}
printf("host=%s\en", hbuf);
.Ed
+.Sh LEGACY SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/socket.h>
+.Fd #include <netdb.h>
+.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 ,
NULL, 0, NI_NUMERICHOST);
}
.Ed
-.Sh BUGS
-The implementation of
-.Fn getnameinfo
-is not thread-safe.
.\".Pp
.\".Ox
.\"intentionally uses a different
--- /dev/null
+.\" 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.
--- /dev/null
+.\" 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 <sys/types.h>
+.Fd #include <pwd.h>
+.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.
--- /dev/null
+.\" 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 .
--- /dev/null
+/*
+ * 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 <stdint.h>
+#include <sys/cdefs.h>
+
+/*
+ * 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_ */
/*
- * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <mach/mach.h>
#include <stdio.h>
#include <string.h>
-#include <rpc/types.h>
-#include <rpc/xdr.h>
#include <aliasdb.h>
#include <pthread.h>
-
-#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
{
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;
}
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
{
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();
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <rpc/types.h>
-#include <rpc/xdr.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <pthread.h>
-#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;
}
#include <mach/mach.h>
#include <stdio.h>
#include <string.h>
-#include <rpc/types.h>
-#include <rpc/xdr.h>
#include <bootparams.h>
-#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();
}
#include <mach/mach.h>
#include <stdio.h>
#include <string.h>
-#include <rpc/types.h>
-#include <rpc/xdr.h>
#include <fstab.h>
#include <pthread.h>
-
-#include "lookup.h"
-#include "_lu_types.h"
#include "lu_utils.h"
#include "lu_overrides.h"
+#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:
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;
}
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();
}
-
/*
- * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2007 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <stdio.h>
#include <string.h>
#include <ctype.h>
-#include <rpc/types.h>
-#include <rpc/xdr.h>
-#include <grp.h>
#include <pwd.h>
#include <netinet/in.h>
#include <sys/param.h>
#include <pthread.h>
#include <errno.h>
#include <servers/bootstrap.h>
-
-#include "_lu_types.h"
-#include "lookup.h"
+#include <sys/syscall.h>
#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
}
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;
{
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)
{
}
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);
}
/*
* 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.
{
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;
}
/*
* 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)
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:
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;
}
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
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;
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 *
int
setgrent(void)
{
- if (_lu_running()) lu_setgrent();
+ if (_ds_running()) ds_setgrent();
else _old_setgrent();
return 1;
}
void
endgrent(void)
{
- if (_lu_running()) lu_endgrent();
+ if (_ds_running()) ds_endgrent();
else _old_endgrent();
}
#include <ifaddrs.h>
#include <sys/types.h>
#include <netinet/if_ether.h>
-
-#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);
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)
{
{
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;
}
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;
}
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,
*/
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;
}
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);
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);
}
{
if (inet_aton(name, &addr) == 0)
{
- *err = HOST_NOT_FOUND;
+ if (err != NULL) *err = HOST_NOT_FOUND;
return NULL;
}
}
}
- 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;
}
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
return 1;
}
-
+
__private_extern__ int
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)
{
}
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;
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)
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;
}
}
else
{
- *err = NO_RECOVERY;
+ if (err != NULL) *err = NO_RECOVERY;
return NULL;
}
{
if (getifaddrs(&ifa) < 0)
{
- *err = NO_RECOVERY;
+ if (err != NULL) *err = NO_RECOVERY;
return NULL;
}
/* Bail out if there are no interfaces */
if ((if4 == 0) && (if6 == 0))
{
- *err = NO_ADDRESS;
+ if (err != NULL) *err = NO_ADDRESS;
return NULL;
}
}
* 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);
}
#define _LU_HOST_H_
#include <sys/cdefs.h>
+#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);
*/
#include <netdb.h>
-/* async gethostbyXXX function prototypes */
#include <netdb_async.h>
#include <pthread.h>
#include <stdlib.h>
#include <mach/mach.h>
-#include <netinfo/_lu_types.h>
-#include <netinfo/lookup.h>
-#include <rpc/types.h>
-#include <rpc/xdr.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <net/if.h>
-#include <libkern/OSByteOrder.h>
+#include <errno.h>
#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;
}
{
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);
/* 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;
}
}
* 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);
}
* Netgroup lookup
* Copyright (C) 1989 by NeXT, Inc.
*/
-#include <netgr.h>
+#include <netdb.h>
#include <mach/mach.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
-#include <rpc/types.h>
-#include <rpc/xdr.h>
-
-#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;
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();
}
#include <mach/mach.h>
#include <stdio.h>
#include <string.h>
-#include <rpc/types.h>
-#include <rpc/xdr.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
-
-#include "_lu_types.h"
-#include "lookup.h"
#include "lu_utils.h"
static pthread_mutex_t _network_lock = PTHREAD_MUTEX_INITIALIZER;
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;
}
else
{
pthread_mutex_lock(&_network_lock);
+
switch (source)
{
case N_GET_NAME:
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 *
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();
}
#include <sys/types.h>
__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();
#include <mach/mach.h>
#include <stdio.h>
#include <string.h>
-#include <rpc/types.h>
-#include <rpc/xdr.h>
#include <pthread.h>
-
-#include "_lu_types.h"
-#include "lookup.h"
#include "printerdb.h"
#include "lu_utils.h"
-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();
}
#include <mach/mach.h>
#include <stdio.h>
#include <string.h>
-#include <rpc/types.h>
-#include <rpc/xdr.h>
#include <netdb.h>
#include <netinet/in.h>
-
-#include "_lu_types.h"
-#include "lookup.h"
+#include <pthread.h>
#include "lu_utils.h"
extern struct protoent *_old_getprotobynumber();
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:
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 *
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();
}
/*
- * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <mach/mach.h>
#include <stdio.h>
#include <string.h>
+#include <stdint.h>
#include <netinet/in.h>
#include <pthread.h>
-
-#include "_lu_types.h"
-#include "lookup.h"
#include "lu_utils.h"
#include "lu_overrides.h"
#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;
}
else
{
pthread_mutex_lock(&_rpc_lock);
+
switch (source)
{
case RPC_GET_NAME:
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 *
}
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 *
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();
}
#include <mach/mach.h>
#include <stdio.h>
#include <string.h>
-#include <rpc/types.h>
-#include <rpc/xdr.h>
#include <netdb.h>
#include <netinet/in.h>
#include <pthread.h>
-
-#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;
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)
{
{
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)
{
}
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)
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
{
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 *
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();
}
#include <mach/mach.h>
#include <stdio.h>
#include <string.h>
-#include <rpc/types.h>
-#include <rpc/xdr.h>
#include <pwd.h>
#include <netinet/in.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
-
-#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;
#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
}
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))
}
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);
}
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)
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;
}
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
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;
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
/*
- * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* @APPLE_LICENSE_HEADER_END@
*/
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mach/mach.h>
+#include <servers/bootstrap.h>
#include <pthread.h>
-#ifdef DEBUG
+#include <errno.h>
+#include <notify.h>
#include <syslog.h>
+#include <unistd.h>
+#ifdef DEBUG
+#include <asl.h>
#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)
{
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;
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;
}
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;
*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);
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++)
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;
+}
#ifndef _LU_UTILS_H_
#define _LU_UTILS_H_
-#import <netinfo/lookup_types.h>
-#include <netinfo/ni.h>
+#include "DSlibinfoMIG_types.h"
+#include "kvbuf.h"
#include <stdarg.h>
-#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_ */
#ifndef _NETDB_H_
#define _NETDB_H_
-#include <stdint.h>
#include <_types.h>
+#include <stdint.h>
#include <netinet/in.h> /* IPPORT_RESERVED */
#ifndef _SIZE_T
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) */
};
/*
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()
#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()
*/
#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);
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_ */
__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
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);
/*
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
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
*/
/*
+++ /dev/null
-/*
- * 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 <sys/cdefs.h>
-
-__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_ */
+++ /dev/null
-/*
- * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#include "DNSServiceDiscovery.h"
-#include "DNSServiceDiscoveryDefines.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <servers/bootstrap.h>
-#include <mach/mach.h>
-#include <mach/mach_error.h>
-#include <pthread.h>
-
-#include <netinet/in.h>
-
-extern struct 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;
-}
+++ /dev/null
-/*
- * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
-* "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef __DNS_SERVICE_DISCOVERY_H
-#define __DNS_SERVICE_DISCOVERY_H
-
-#include <mach/mach_types.h>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/cdefs.h>
-
-#include <netinet/in.h>
-
-#include <AvailabilityMacros.h>
-
-__BEGIN_DECLS
-
-/* Opaque internal data type */
-typedef struct _dns_service_discovery_t * dns_service_discovery_ref;
-
-/* possible reply flags values */
-
-enum {
- kDNSServiceDiscoveryNoFlags = 0,
- kDNSServiceDiscoveryMoreRepliesImmediately = 1 << 0,
-};
-
-
-/* possible error code values */
-typedef enum
-{
- kDNSServiceDiscoveryWaiting = 1,
- kDNSServiceDiscoveryNoError = 0,
- // mDNS Error codes are in the range
- // FFFE FF00 (-65792) to FFFE FFFF (-65537)
- kDNSServiceDiscoveryUnknownErr = -65537, // 0xFFFE FFFF
- kDNSServiceDiscoveryNoSuchNameErr = -65538,
- kDNSServiceDiscoveryNoMemoryErr = -65539,
- kDNSServiceDiscoveryBadParamErr = -65540,
- kDNSServiceDiscoveryBadReferenceErr = -65541,
- kDNSServiceDiscoveryBadStateErr = -65542,
- kDNSServiceDiscoveryBadFlagsErr = -65543,
- kDNSServiceDiscoveryUnsupportedErr = -65544,
- kDNSServiceDiscoveryNotInitializedErr = -65545,
- kDNSServiceDiscoveryNoCache = -65546,
- kDNSServiceDiscoveryAlreadyRegistered = -65547,
- kDNSServiceDiscoveryNameConflict = -65548,
- kDNSServiceDiscoveryInvalid = -65549,
- kDNSServiceDiscoveryMemFree = -65792 // 0xFFFE FF00
-} DNSServiceRegistrationReplyErrorType;
-
-typedef uint32_t DNSRecordReference;
-
-
-/*!
-@function DNSServiceResolver_handleReply
- @description This function should be called with the Mach message sent
- to the port returned by the call to DNSServiceResolverResolve.
- The reply message will be interpreted and will result in a
- call to the specified callout function.
- @param replyMsg The Mach message.
- */
-void DNSServiceDiscovery_handleReply(void *replyMsg);
-
-/* Service Registration */
-
-typedef void (*DNSServiceRegistrationReply) (
- DNSServiceRegistrationReplyErrorType errorCode,
- void *context
-);
-
-/*!
-@function DNSServiceRegistrationCreate
- @description Register a named service with DNS Service Discovery
- @param name The name of this service instance (e.g. "Steve's Printer")
- @param regtype The service type (e.g. "_printer._tcp." -- see
- RFC 2782 (DNS SRV) and <http://www.iana.org/assignments/port-numbers>)
- @param domain The domain in which to register the service (e.g. "apple.com.")
- @param port The local port on which this service is being offered (in network byte order)
- @param txtRecord Optional protocol-specific additional information
- @param callBack The DNSServiceRegistrationReply function to be called
- @param context A user specified context which will be passed to the callout function.
- @result A dns_registration_t
-*/
-dns_service_discovery_ref DNSServiceRegistrationCreate
-(
- const char *name,
- const char *regtype,
- const char *domain,
- uint16_t port,
- const char *txtRecord,
- DNSServiceRegistrationReply callBack,
- void *context
-) 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 */
+++ /dev/null
-/*
- * Copyright (c) 2001 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#ifndef __DNS_SERVICE_DISCOVERY_DEFINES_H
-#define __DNS_SERVICE_DISCOVERY_DEFINES_H
-
-#include <mach/mach_types.h>
-
-#define DNS_SERVICE_DISCOVERY_SERVER "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 */
-
+++ /dev/null
-/*
- * Copyright (c) 2001 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-subsystem
- DNSServiceDiscoveryReply 7250;
-
-ServerPrefix internal_;
-
-#include <mach/std_types.defs>
-#include <mach/mach_types.defs>
-
-import "DNSServiceDiscoveryDefines.h";
-
-type DNSCString = c_string[*:1024];
-type sockaddr_t = array[128] of char;
-
-simpleroutine DNSServiceDomainEnumerationReply_rpc(
- reply: mach_port_t;
- in resultType: int;
- in replyDomain: DNSCString;
- in flags: int;
- SendTime to: natural_t);
-
-simpleroutine DNSServiceBrowserReply_rpc(
- reply: mach_port_t;
- in resultType: int;
- in replyName: DNSCString;
- in replyType: DNSCString;
- in replyDomain: DNSCString;
- in flags: int;
- SendTime to: natural_t);
-
-
-simpleroutine DNSServiceRegistrationReply_rpc(
- reply: mach_port_t;
- in resultType: int;
- SendTime to: natural_t);
-
-
-simpleroutine DNSServiceResolverReply_rpc(
- reply: mach_port_t;
- in interface: sockaddr_t;
- in address: sockaddr_t;
- in txtRecord: DNSCString;
- in flags: int;
- SendTime to: natural_t);
-
+++ /dev/null
-/*
- * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-subsystem
- DNSServiceDiscoveryRequest 7200;
-
-ServerPrefix provide_;
-
-#include <mach/std_types.defs>
-#include <mach/mach_types.defs>
-
-import "DNSServiceDiscoveryDefines.h";
-
-type DNSCString = c_string[*:1024];
-type record_data = ^ array [] of MACH_MSG_TYPE_BYTE
- ctype: record_data_t;
-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);
-
+++ /dev/null
-#
-# 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
+++ /dev/null
-###############################################################################
-# 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) $@
+++ /dev/null
-###############################################################################
-# Makefile.preamble
-# Copyright 1997, Apple Computer, Inc.
-#
-# Use this makefile for configuring the standard application makefiles
-# associated with ProjectBuilder. It is included before the main makefile.
-# In Makefile.preamble you set attributes for a project, so they are available
-# to the project's makefiles. In contrast, you typically write additional rules or
-# override built-in behavior in the Makefile.postamble.
-#
-# Each directory in a project tree (main project plus subprojects) should
-# have its own Makefile.preamble and Makefile.postamble.
-###############################################################################
-#
-# Before the main makefile is included for this project, you may set:
-#
-# MAKEFILEDIR: Directory in which to find $(MAKEFILE)
-# MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
-
-# Compiler/linker flags added to the defaults: The OTHER_* variables will be
-# inherited by all nested sub-projects, but the LOCAL_ versions of the same
-# variables will not. Put your -I, -D, -U, and -L flags in ProjectBuilder's
-# Build Attributes inspector if at all possible. To override the default flags
-# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble. The
-# variables below are *inputs* to the build process and distinct from the override
-# settings done (less often) in the Makefile.postamble.
-#
-# OTHER_CFLAGS, LOCAL_CFLAGS: additional flags to pass to the compiler
-# Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
-# .cc, .cxx, .C, and .M files. There is no need to respecify the
-# flags in OTHER_MFLAGS, etc.
-# OTHER_MFLAGS, LOCAL_MFLAGS: additional flags for .m files
-# OTHER_CCFLAGS, LOCAL_CCFLAGS: additional flags for .cc, .cxx, and ...C files
-# OTHER_MMFLAGS, LOCAL_MMFLAGS: additional flags for .mm and .M files
-# OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS: additional flags used when
-# precompiling header files
-# OTHER_LDFLAGS, LOCAL_LDFLAGS: additional flags passed to ld and libtool
-# OTHER_PSWFLAGS, LOCAL_PSWFLAGS: additional flags passed to pswrap
-# OTHER_RPCFLAGS, LOCAL_RPCFLAGS: additional flags passed to rpcgen
-# OTHER_YFLAGS, LOCAL_YFLAGS: additional flags passed to yacc
-# OTHER_LFLAGS, LOCAL_LFLAGS: additional flags passed to lex
-
-# These variables provide hooks enabling you to add behavior at almost every
-# stage of the make:
-#
-# BEFORE_PREBUILD: targets to build before installing headers for a subproject
-# AFTER_PREBUILD: targets to build after installing headers for a subproject
-# BEFORE_BUILD_RECURSION: targets to make before building subprojects
-# BEFORE_BUILD: targets to make before a build, but after subprojects
-# AFTER_BUILD: targets to make after a build
-#
-# BEFORE_INSTALL: targets to build before installing the product
-# AFTER_INSTALL: targets to build after installing the product
-# BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
-# AFTER_POSTINSTALL: targts to build after postinstalling every subproject
-#
-# BEFORE_INSTALLHDRS: targets to build before installing headers for a
-# subproject
-# AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
-# BEFORE_INSTALLSRC: targets to build before installing source for a subproject
-# AFTER_INSTALLSRC: targets to build after installing source for a subproject
-#
-# BEFORE_DEPEND: targets to build before building dependencies for a
-# subproject
-# AFTER_DEPEND: targets to build after building dependencies for a
-# subproject
-#
-# AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
-# updated every time the project is built. If NO, the dependency
-# file is only built when the depend target is invoked.
-
-# Framework-related variables:
-# FRAMEWORK_DLL_INSTALLDIR: On Windows platforms, this variable indicates
-# where to put the framework's DLL. This variable defaults to
-# $(INSTALLDIR)/../Executables
-
-# Library-related variables:
-# PUBLIC_HEADER_DIR: Determines where public exported header files
-# should be installed. Do not include $(DSTROOT) in this value --
-# it is prefixed automatically. For library projects you should
-# set this to something like /Developer/Headers/$(NAME). Do not set
-# this variable for framework projects unless you do not want the
-# header files included in the framework.
-# PRIVATE_HEADER_DIR: Determines where private exported header files
-# should be installed. Do not include $(DSTROOT) in this value --
-# it is prefixed automatically.
-# LIBRARY_STYLE: This may be either STATIC or DYNAMIC, and determines
-# whether the libraries produced are statically linked when they
-# are used or if they are dynamically loadable. This defaults to
-# DYNAMIC.
-# LIBRARY_DLL_INSTALLDIR: On Windows platforms, this variable indicates
-# where to put the library's DLL. This variable defaults to
-# $(INSTALLDIR)/../Executables
-#
-# INSTALL_AS_USER: owner of the intalled products (default root)
-# INSTALL_AS_GROUP: group of the installed products (default wheel)
-# INSTALL_PERMISSIONS: permissions of the installed product (default o+rX)
-#
-# OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
-# passed on the command line to recursive invocations of make. Note that
-# the values in OTHER_*FLAGS are inherited by subprojects automatically --
-# you do not have to (and shouldn't) add OTHER_*FLAGS to
-# OTHER_RECURSIVE_VARIABLES.
-
-# Additional headers to export beyond those in the PB.project:
-# OTHER_PUBLIC_HEADERS
-# OTHER_PROJECT_HEADERS
-# OTHER_PRIVATE_HEADERS
-
-# Additional files for the project's product: <<path relative to proj?>>
-# OTHER_RESOURCES: (non-localized) resources for this project
-# OTHER_OFILES: relocatables to be linked into this project
-# OTHER_LIBS: more libraries to link against
-# OTHER_PRODUCT_DEPENDS: other dependencies of this project
-# OTHER_SOURCEFILES: other source files maintained by .pre/postamble
-# OTHER_GARBAGE: additional files to be removed by `make clean'
-
-# Set this to YES if you don't want a final libtool call for a library/framework.
-# BUILD_OFILES_LIST_ONLY
-
-# To include a version string, project source must exist in a directory named
-# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
-# OTHER_GENERATED_OFILES = $(VERS_OFILE)
-
-# This definition will suppress stripping of debug symbols when an executable
-# is installed. By default it is YES.
-# STRIP_ON_INSTALL = NO
-
-# Uncomment to suppress generation of a KeyValueCoding index when installing
-# frameworks (This index is used by WOB and IB to determine keys available
-# for an object). Set to YES by default.
-# PREINDEX_FRAMEWORK = NO
-
-# Change this definition to install projects somewhere other than the
-# standard locations. NEXT_ROOT defaults to "C:/Apple" on Windows systems
-# and "" on other systems.
-DSTROOT = $(HOME)
-
-# Additional flags (MiG generated files)
-OTHER_OFILES = DNSServiceDiscoveryRequestUser.o DNSServiceDiscoveryReplyServer.o
-
-# private headers
-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
-# <rdar://problem/3819761> Libinfo need to build with gcc-3.5 and 3-way fat
-NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER)
+++ /dev/null
-{
- 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";
-}
+++ /dev/null
-/*
- * 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 <sys/types.h>
-#elif defined(__sun__)
-#include <sys/types.h>
-#elif defined(_WIN32)
-#include <windows.h>
-#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 <stdint.h>
-#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. <length byte> <data>
- * <length byte> <data> ...
- *
- * 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 <servicename>.<protocol>.<domain>.
- * (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
- * <http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt>
- *
- * 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
- * <http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt>
- *
- * 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 */
+++ /dev/null
-/*
- * 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
-<rdar://problem/3775315>: 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 <stdlib.h>
-#include <string.h>
-
-#include "dns_sd.h"
-
-#if MDNS_BUILDINGSHAREDLIBRARY || MDNS_BUILDINGSTUBLIBRARY
-#pragma export on
-#endif
-
-#if defined(_WIN32)
-// disable warning "conversion from <data> 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 (p<e)
- {
- uint8_t *x = p;
- p += 1 + p[0];
- if (p <= e && *keylen <= x[0] && !strncmp(key, (char*)x+1, *keylen))
- if (*keylen == x[0] || x[1+*keylen] == '=') return(x);
- }
- return(NULL);
- }
-
-/*********************************************************************************************
- *
- * General Utility Functions
- *
- *********************************************************************************************/
-
-int DNSSD_API DNSServiceConstructFullName
- (
- char *fullName,
- const char *service, /* may be NULL */
- const char *regtype,
- const char *domain
- )
- {
- unsigned long len;
- unsigned char c;
- char *fn = fullName;
- const char *s = service;
- const char *r = regtype;
- const char *d = domain;
-
- if (service)
- {
- while(*s)
- {
- c = (unsigned char)*s++;
- if (c == '.' || (c == '\\')) *fn++ = '\\'; // escape dot and backslash literals
- else if (c <= ' ') // escape non-printable characters
- {
- *fn++ = '\\';
- *fn++ = (char) ('0' + (c / 100));
- *fn++ = (char) ('0' + (c / 10) % 10);
- c = (unsigned char)('0' + (c % 10));
- }
- *fn++ = (char)c;
- }
- *fn++ = '.';
- }
-
- if (!regtype) return -1;
- len = (unsigned long) strlen(regtype);
- if (DomainEndsInDot(regtype)) len--;
- if (len < 6) return -1; // regtype must be at least "x._udp" or "x._tcp"
- if (strncmp((regtype + len - 4), "_tcp", 4) && strncmp((regtype + len - 4), "_udp", 4)) return -1;
- while(*r) *fn++ = *r++;
- if (!DomainEndsInDot(regtype)) *fn++ = '.';
-
- if (!domain || !domain[0]) return -1;
- while(*d) *fn++ = *d++;
- if (!DomainEndsInDot(domain)) *fn++ = '.';
- *fn = '\0';
- return 0;
- }
-
-/*********************************************************************************************
- *
- * TXT Record Construction Functions
- *
- *********************************************************************************************/
-
-typedef struct _TXTRecordRefRealType
- {
- uint8_t *buffer; // Pointer to data
- uint16_t buflen; // Length of buffer
- uint16_t datalen; // Length currently in use
- uint16_t malloced; // Non-zero if buffer was allocated via malloc()
- } TXTRecordRefRealType;
-
-#define txtRec ((TXTRecordRefRealType*)txtRecord)
-
-// The opaque storage defined in the public dns_sd.h header is 16 bytes;
-// make sure we don't exceed that.
-struct dnssd_clientlib_CompileTimeAssertionCheck
- {
- char assert0[(sizeof(TXTRecordRefRealType) <= 16) ? 1 : -1];
- };
-
-void TXTRecordCreate
- (
- TXTRecordRef *txtRecord,
- uint16_t bufferLen,
- void *buffer
- )
- {
- txtRec->buffer = 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 (p<e) { p += 1 + p[0]; count++; }
- return((p>e) ? (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<e && count<index) { p += 1 + p[0]; count++; } // Find requested item
- if (p<e && p + 1 + p[0] <= e) // If valid
- {
- uint8_t *x = p+1;
- unsigned long len = 0;
- e = p + 1 + p[0];
- while (x+len<e && x[len] != '=') len++;
- if (len >= keyBufLen) return(kDNSServiceErr_NoMemory);
- memcpy(key, x, len);
- key[len] = 0;
- if (x+len<e) // If we found '='
- {
- *value = x + len + 1;
- *valueLen = (uint8_t)(p[0] - (len + 1));
- }
- else
- {
- *value = NULL;
- *valueLen = 0;
- }
- return(kDNSServiceErr_NoError);
- }
- return(kDNSServiceErr_Invalid);
- }
+++ /dev/null
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004, Apple Computer, 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.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 AND ITS 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 APPLE OR ITS 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.
-
- Change History (most recent first):
-
-$Log: dnssd_clientstub.c,v $
-Revision 1.20.70.3 2006/05/02 16:17:04 majka
-Make NumTries unsigned.
-
-Revision 1.20.70.2 2006/05/01 21:43:09 majka
-Additional change (make NumTries static) for 4527193
-SUChardLondon Libinfo-222.4.6
-
-Revision 1.20.70.1 2006/05/01 16:10:54 majka
-Libinfo-222_4_5 is equivalent to Chardonnay Libinfo-222.0.5
-
-Revision 1.20.60.1 2006/04/27 21:33:30 majka
-Integrated 4527193
-
-Revision 1.20 2005/02/03 00:39:05 majka
-Integrated 3942900
-
-Revision 1.19.4.1 2005/02/02 00:47:40 ksekar
-<rdar://problem/3942900> dnd-sd shows the wrong port numbers
-
-Revision 1.19 2004/12/23 23:10:59 majka
-*** empty log message ***
-
-Revision 1.18.8.1 2004/12/23 17:32:56 ksekar
-<rdar://problem/3931319> Rendevzous calls leak sockets if mDNSResponder is not running
-
-Revision 1.18 2004/12/14 18:02:00 majka
-*** empty log message ***
-
-Revision 1.17.36.1 2004/12/13 17:22:39 ksekar
-<rdar://problem/3656389> Deprecate the DNSServiceDiscovery.h API in Tiger
-<rdar://problem/3873869> Add kDNSServiceInterfaceForceMulticast to header
-<rdar://problem/3526342> Remove overly-restrictive flag checks
-
-Revision 1.17 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.16.2.1 2004/09/20 21:54:33 ksekar
-<rdar://problem/3805822> 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
-<rdar://problem/3775315>: 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
-<rdar://problem/3730123> 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 "<rdar://problem/xxxxxxx>" format for bug numbers
-
-Revision 1.17 2004/05/06 18:42:58 ksekar
-General dns_sd.h API cleanup, including the following radars:
-<rdar://problem/3592068>: Remove flags with zero value
-<rdar://problem/3479569>: Passing in NULL causes a crash.
-
-Revision 1.16 2004/03/12 22:00:37 cheshire
-Added: #include <sys/socket.h>
-
-Revision 1.15 2004/01/20 18:36:29 ksekar
-Propagated Libinfo fix for <rdar://problem/3483971>: 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
-<rdar://problem/3497428>: 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 <errno.h>
-#include <stdlib.h>
-#if defined(_WIN32)
-#include <winsock2.h>
-#include <windows.h>
-#define sockaddr_mdns sockaddr_in
-#define AF_MDNS AF_INET
-#else
-#include <sys/time.h>
-#include <sys/socket.h>
-#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);
- }
-
+++ /dev/null
-/*
- * 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
-<rdar://problem/3805822> 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
-<rdar://problem/3775315>: 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 "<rdar://problem/xxxxxxx>" format for bug numbers
-
-Revision 1.8 2003/11/05 22:44:57 ksekar
-<rdar://problem/3335230>: 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);
- }
+++ /dev/null
-/*
- * 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
-<rdar://problem/3805822> 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
-<rdar://problem/3775315>: 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 <winsock2.h>
-# 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 <sys/types.h>
-# include <unistd.h>
-# include <sys/un.h>
-# include <string.h>
-# include <stdio.h>
-# include <stdlib.h>
-# include <sys/stat.h>
-# include <sys/socket.h>
-# include <netinet/in.h>
-# 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
--- /dev/null
+#include <../include/DSmemberdMIG.defs>
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
+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) $@
+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
DYNAMIC_CODE_GEN = YES;
FILESTABLE = {
H_FILES = (
- membership.h,
membershipPriv.h,
- memberd_defines.h,
ntsid.h
);
OTHER_LINKED = (membership.c);
Makefile.preamble,
Makefile,
Makefile.postamble,
- memberd.defs
+ DSmemberdMIG.defs
);
PRECOMPILED_HEADERS = ();
PROJECT_HEADERS = ();
--- /dev/null
+.\" 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
--- /dev/null
+.\" 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
--- /dev/null
+.so man3/mbr_uid_to_uuid.3
+++ /dev/null
-/*
- * 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 <mach/std_types.defs>
-#include <mach/mach_types.defs>
-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
-);
+++ /dev/null
-/*
- * 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 <sys/types.h>
-#import <sys/kauth.h>
-
-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
/*
- * Copyright (c) 2004-2007 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004-2007 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include "membership.h"
#include "membershipPriv.h"
-#include "memberd.h"
-
+#include "DSmemberdMIG.h"
+#include "DSmemberdMIG_types.h"
#include <sys/errno.h>
-#include <servers/bootstrap.h>
#include <mach/mach.h>
+#include <servers/bootstrap.h>
#include <stdlib.h>
#include <libkern/OSByteOrder.h>
-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)
{
}
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)
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);
buffer[24] = '\0';
buffer[23] = '0';
- if (value == 0) return &buffer[23];
+ if (value == 0)
+ return &buffer[23];
temp = &buffer[24];
while (value != 0)
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 = '-';
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;
/* 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);
{
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;
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++;
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;
}
return 0;
}
+
#include <uuid/uuid.h>
#include <ntsid.h>
-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_ */
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
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
+++ /dev/null
-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
-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
# <rdar://problem/3819761> Libinfo need to build with gcc-3.5 and 3-way fat
{
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";
+++ /dev/null
-/*
- * 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 *);
+++ /dev/null
-/*
- * 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))
-
+++ /dev/null
-/*
- * 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 <rpc/rpc.h>
-#include <rpc/pmap_prot.h>
-#include <sys/socket.h>
-#include <syslog.h>
-#include <sys/param.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <unistd.h>
-
-#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);
-}
-
-
-
-
+++ /dev/null
-.TH NETINFO 3 "August 29, 1989" "Apple Computer, Inc."
-.SH NAME
-netinfo \- library routines for NetInfo calls
-.SH SYNOPSIS
-\fB#include <netinfo/ni.h>\fR
-.SH DESCRIPTION
-These calls are the programming interface to NetInfo. Typically,
-a handle (of type "void *") is allocated through a call to
-.I ni_new,
-.I ni_open,
-or
-.I ni_connect.
-This handle opens a connection to the given NetInfo domain. Read calls
-may go to either the master or the clone servers, while writes will
-always go to the master server. If the master is unavailable,
-no writes can be performed.
-The handle is then passed to one of several NetInfo routines for database
-operations and then freed using
-.I ni_free.
-Several utility routines are also supplied which operate on NetInfo data
-structures. These routines don't require NetInfo handles.
-.LP
-.SH MACROS
-.PP
-.B NI_INDEX_NULL
-.IP
-A constant which evaluates to the highest unsigned integer. It is useful
-for indicating something which should go at the end of a list, as opposed
-to a smaller value which indicates the precise position at which the insert
-should occur.
-.PP
-\fBNI_INIT\fR(\fIptr\fR)
-.IP
-Initializes a NetInfo data structure. It effectively zeros out the structure
-referred to by
-.I ptr.
-This macro is useful for indicating an empty list or NULL value with one
-of the many NetInfo data structures.
-.SH "DATATYPES AND ASSOCIATED UTILITY ROUTINES"
-.PP
-.B ni_status
-.IP
-The result code of most NetInfo routines.
-.PP
-const char *\fBni_error\fR(ni_status \fIstatus\fR)
-.IP
-Returns the error string associated with the given NetInfo status.
-.PP
-.B ni_index
-.IP
-An index into a NetInfo list.
-.PP
-.B ni_id
-.IP
-NetInfo directories are identified through the
-.I ni_id
-data structure. It records the ID of the directory in the
-.I nii_object
-field and the instance of the directory in the
-.I nii_instance
-field. The instance indicates which version of the directory is being
-operated on and is only relevant for writes. Each time a write is
-performed, the instance is incremented to reflect the new version. If
-the instance given does not match the current instance of the directory,
-the error NI_STALE is returned, indicating a stale ID. All NetInfo
-routines which operate on directories will return the latest value of
-the instance.
-.PP
-.B ni_name
-.IP
-A NetInfo name. It is equivalent to a C string.
-.PP
-ni_name \fBni_name_dup\fR(const ni_name \fIname\fR)
-.IP
-Returns a mallocated copy of a NetInfo name.
-.PP
-void \fBni_name_free\fR(ni_name *\fInamep\fR)
-.IP
-Frees a NetInfo name. The pointer is converted to NULL. A NULL pointer
-will not be freed.
-.PP
-int \fBni_name_match\fR(const ni_name \fIname1\fR, const ni_name \fIname2\fR)
-.IP
-Compares two NetInfo names for equality. Returns non-zero for success,
-zero for failure.
-.PP
-.B ni_namelist
-.IP
-A list of NetInfo names.
-.PP
-ni_namelist \fBni_namelist_dup\fR(const ni_namelist \fInl\fR)
-.IP
-Returns a mallocated duplicate of a NetInfo namelist.
-.PP
-void \fBni_namelist_free\fR(ni_namelist *\fInl\fR)
-.IP
-Frees a NetInfo namelist. The namelist structure is zeroed. Zeroed
-namelists will not be freed.
-.PP
-void \fBni_namelist_insert\fR(ni_namelist *\fInl\fR, const ni_name \fIname\fR, ni_index \fIwhere\fR)
-.IP
-Duplicates and inserts the given name at the given location into the namelist.
-.PP
-void \fBni_namelist_delete\fR(ni_namelist *\fInl\fR, ni_index \fIwhere\fR)
-.IP
-Deletes and frees the name at the given location in the namelist.
-.PP
-ni_index \fBni_namelist_match\fR(const ni_namelist \fInl\fR, const ni_name \fIname\fR)
-.IP
-If the name is in the given namelist, the first index of its occurrence
-is returned. Otherwise, NI_INDEX_NULL is returned indicating failure.
-.PP
-.B ni_property
-.IP
-A NetInfo property. It contains a name and a namelist of associated values.
-.PP
-ni_property \fBni_prop_dup\fR(const ni_property \fIprop\fR)
-.IP
-Returns a mallocated duplicate of the given NetInfo property.
-.PP
-void \fBni_prop_free\fR(ni_property *\fIprop\fR)
-.IP
-Frees and zeros the NetInfo property. Zeroed properties will not be freed
-again.
-.PP
-.B ni_proplist
-.IP
-A list of NetInfo properties.
-.PP
-void \fBni_proplist_insert\fR(ni_proplist *\fIpl\fR, const ni_property \fIprop\fR, ni_index \fIwhere\fR)
-.IP
-Duplicates and inserts the given property at the given location into the given property
-list.
-.PP
-void \fBni_proplist_delete\fR(ni_proplist *\fIpl\fR, ni_index \fIwhere\fR)
-.IP
-Frees and deletes the property at the given location in the property list.
-.PP
-ni_index \fBni_proplist_match\fR(const ni_proplist \fIpl\fR, const ni_name \fIname\fR, const ni_name \fIval\fR)
-.IP
-Returns the location in the property list of the first property with a name
-of
-.I name
-and having value
-.I val.
-NI_INDEX_NULL is returned on failure.
-If NULL is the \fIvalue\fR argument,
-\fBni_proplist_match\fR will match on only the \fIname\fR argument.
-.PP
-ni_proplist \fBni_proplist_dup\fR(const ni_proplist \fIpl\fR)
-.IP
-Returns a mallocated duplicate property list.
-.PP
-void \fBni_proplist_free\fR(ni_proplist *\fIpl\fR)
-.IP
-Frees and zeroes the property list. A zeroed property will not be freed again.
-.PP
-.B ni_idlist
-.IP
-A list of NetInfo indices (usually directory ID's).
-.PP
-void \fBni_idlist_free\fR(ni_idlist *\fIidl\fR)
-.IP
-Frees and zeroes the given ID list. A zeroed ID list will not be freed again.
-.PP
-.B ni_entry
-.IP
-An entry in a NetInfo directory. It contains the ID of the directory and
-a list of values assocated with whatever property was requested in the
-.I ni_list
-routine. The list may be NULL, indicating that there is not associated
-property for this directory.
-.PP
-.B ni_entrylist
-.IP
-A list of NetInfo entries.
-.PP
-void \fBni_entrylist_free\fR(ni_entrylist *\fIentries\fR)
-.IP
-Frees and zeros the given entry list. A zeroed entry list will not be
-freed again.
-.LP
-.SH "ROUTINES"
-.PP
-ni_status \fBni_addrtag\fR(void *\fIhandle\fR, struct sockaddr_in *\fIaddr\fR, ni_name *\fItag\fR)
-.IP
-Returns the address and domain tag associated with the connected
-NetInfo handle.
-.PP
-ni_status \fBni_children\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_idlist *\fIidlist\fR)
-.IP
-Lists the children ID's (subdirectories) of the given directory.
-.PP
-void *\fBni_connect\fR(struct sockaddr_in *\fIaddr\fR, ni_name \fItag\fR)
-.IP
-Returns a NetInfo handle to the NetInfo domain at the given address
-and domain tag. Returns NULL on failure.
-.PP
-ni_status \fBni_create\fR(void *\fIhandle\fR, ni_id *\fIparent\fR, ni_proplist \fIprops\fR, ni_id *\fIchild\fR, ni_index \fIwhere\fR)
-.IP
-Creates a new directory at the given index initialized with the given
-properties.
-.PP
-ni_status \fBni_createname\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_index \fIprop_index\fR, ni_name \fIname\fR, ni_index \fIval_index\fR)
-.IP
-Inserts the name into the value list of the given directory at the property
-indexed by prop_index and value list location val_index.
-.PP
-ni_status \fBni_createprop\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_property \fIprop\fR, ni_index \fIwhere\fR)
-.IP
-Creates a new property at the given index in the given directory.
-.PP
-ni_status \fBni_destroy\fR(void *\fIhandle\fR, ni_id *\fIparent\fR, ni_id \fIchild\fR)
-.IP
-Destroys the directory child in the given parent directory. Both instance
-must be the latest values or the error NI_STALE is returned.
-.PP
-ni_status \fBni_destroyname\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_index \fIprop_index\fR, ni_index \fIval_index\fR)
-.IP
-Destroys a property value in the given directory at the given prop_index and
-value-list val_index.
-.PP
-ni_status \fBni_destroyprop\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_index \fIwhere\fR)
-.IP
-Destroys the property at property index
-.I where
-in the given directory.
-.PP
-ni_status \fBni_fancyopen\fR(void *\fIhandle\fR, ni_name \fIdomain\fR, void **\fIrethandle\fR, ni_fancyopenargs *\fIargs\fR)
-.PP
-.nf
-typedef struct ni_fancyopenargs {
- int rtimeout;
- int wtimeout;
- int abort;
- int needwrite;
-} ni_fancyopenargs;
-.fi
-.IP
-A fancier version of ni_open which allows one to set
-various attributes on the the returned handle. See
-.I ni_setreadtimeout(),
-.I ni_setwritetimeout(),
-.I ni_setabort()
-and
-.I ni_needwrite()
-for descriptions of the fields
-in the ni_fancyopenargs structure. A 0 in the
-rtimeout or wtimeout field indicates the
-default timeout should be used.
-.PP
-void \fBni_free\fR(void *\fIhandle\fR)
-.IP
-Frees a NetInfo handle and closes any associated connections.
-.PP
-ni_status \fBni_list\fR(void *\fIhandle\fR, ni_id *\fIdir\fR , ni_name \fIname\fR, ni_entrylist *\fIentries\fR)
-.IP
-Lists all the subdirectories of the given directory along with any associated
-values they may have for the property
-.I name.
-If a subdirectory doesn't have the property \fIname\fR,
-the entry is still returned but with a NULL property list.
-.PP
-ni_status \fBni_listprops\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_namelist *\fInl\fR)
-.IP
-Returns the list of property names associated with the given directory.
-.PP
-ni_status \fBni_lookup\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_name \fIname\fR, ni_name \fIval\fR, ni_idlist *\fIfound\fR)
-.IP
-Returns a list of subdirectories which satisfy the relation
-.I name
-equals
-.I val.
-.PP
-ni_status \fBni_lookupprop\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_name \fIname\fR, ni_namelist *\fIval\fR)
-.IP
-Returns the values associated with the property named
-.I name
-in the given directory.
-.PP
-ni_status \fBni_lookupread\fR(void *\fIhandle\fR, ni_id *\fIdirid\fR, ni_name \fIpropname\fR, ni_name \fIpropval\fR, ni_proplist *\fIprops\fR)
-.IP
-Looks up the subdirectory given the
-.I (propname, propval\)
-pair
-and returns the subdirectory's properties. This call is equivalent to
-an
-.I ni_lookup()
-followed by an
-.I ni_read().
-.PP
-void \fBni_needwrite\fR(void *\fIhandle\fR, int \fIneedwrite\fR)
-.IP
-Indicates whether subsequent calls will need to write to a
-netinfo server. By default, the flag is off and the netinfo
-library will automatically switch to a server capable of
-writing whenever a write call occurs. However, since writes
-may take some time to reach the clone server, one could read
-stale information from a clone server and then attempt to
-write the master based upon the stale information. Setting
-.I needwrite
-will lock the handle onto the master netinfo server even for
-reads to prevent this from happening.
-.PP
-ni_status \fBni_open\fR(void *\fIrelativeto\fR, ni_name \fIdomain\fR, void **\fIresult\fR)
-.IP
-Opens a connection to the NetInfo domain
-.I domain.
-The returned handle is opened relative to the domain specified in the
-.I relativeto.
-This handle may be passed as NULL, indicating relative to the local
-NetInfo domain. The path may contain "/"s to indicate a multilevel
-search and may also be "." or ".." to indicate the current domain or
-parent domain, respectively.
-.PP
-ni_status \fBni_parent\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_index *\fIparent_id\fR)
-.IP
-Returns the parent ID of the given directory.
-.PP
-ni_status \fBni_pathsearch\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_name \fIpath\fR)
-.IP
-Does a multilevel lookup on a directory, relative to the given directory
-ID. The path may contain "/"s to separative directory components. "="s
-are used to specify relations and both may be escaped using "\\"s. For
-example, to find the directory associated with the superuser, you may
-specify (relative to the root directory) "/name=users/uid=0". Note that
-the equal signs are not mandatory and will default to "name=" if none
-are specified. In the previous example, "/users/uid=0" would accomplish
-the same result.
-.PP
-ni_status \fBni_read\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_proplist *\fIprops\fR)
-.IP
-Reads all of the properties of the given directory.
-.PP
-ni_status \fBni_readname\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_index \fIprop_index\fR, ni_index \fIval_index\fR, ni_name *\fIvalue\fR)
-.IP
-Reads a value from a property in the given directory. The value is indexed
-by property index
-.I prop_index
-and value index
-.I val_index.
-.PP
-ni_status \fBni_readprop\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_index \fIprop_index\fr, ni_namelist *\fInl\fR)
-.IP
-Reads the value-list associated with the given property, indexed by
-.I prop_index.
-.PP
-ni_status \fBni_renameprop\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_index \fIprop_index\fR, ni_name \fInewname\fR)
-.IP
-Renames the property indexed by
-.I prop_index
-to the new name
-.I newname.
-.PP
-ni_status \fBni_resync\fR(void *\fIhandle\fR)
-.IP
-Attempts to resynchronize the clone servers with the master copy of
-the database.
-.PP
-ni_status \fBni_root\fR(void *\fIhandle\fR, ni_id *\fIdir\fR)
-.IP
-Returns the directory ID of the root of the directory tree.
-.PP
-ni_status \fBni_self\fR(void *\fIhandle\fR, ni_id *\fIdir\fR)
-.IP
-Returns the directory ID of the given directory. Simply refreshes the
-instance field to the latest value.
-.PP
-void \fBni_setabort\fR(void *\fIhandle\fR, int \fIshouldabort\fR)
-.IP
-By default, netinfo calls will try forever until an answer
-is returned from a server.
-.I ni_setabort
- allows one to have
-netinfo return failure upon the first timeout or other failure.
-.PP
-ni_status \fBni_setpassword\fR(void *\fIhandle\fR, ni_name \fIpassword\fR)
-.IP
-Sets the password for the session to
-.I password.
-By default, no password is sent.
-.PP
-void \fBni_setreadtimeout\fR(void *\fIhandle\fR, int \fIseconds\fR)
-.IP
-Sets the timeout associated with reads on netinfo. The timeout
-is only a hint and the effective timeout may be longer. Note
-that calls will not abort even if a timeout is set unless the
-abort flag has been set (see
-.I ni_setabort()).
-.PP
-ni_status \fBni_setuser\fr(void *\fIhandle\fR, ni_name \fIusername\fR)
-.IP
-Changes the username associated with the session. By default, the username
-is the one associated with the user-ID that was used during the UNIX login
-process.
-.PP
-void \fBni_setwritetimeout\fR(void *\fIhandle\fR, int \fIseconds\fR)
-.IP
-Sets the timeout associated with writes on netinfo. The timeout
-is only a hint and the effective timeout may be a longer. Note
-that calls will not abort even if a timeout is set unless the
-abort flag has been set (see
-.I ni_setabort()).
-.PP
-ni_status \fBni_statistics\fR(void *\fIhandle\fR, ni_proplist *\fIstatistics\fR)
-.IP
-Returns various statistics from the server.
-.PP
-ni_status \fBni_write\fR(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_proplist \fIprops\fR)
-.IP
-Writes a new property list to the directory.
-.PP
-ni_status \fBni_writename\fr(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_index \fIprop_index\fr, ni_index \fIname_index\fR, ni_name \fIval\fR)
-.IP
-Writes a new property value to the property indexed by
-.I prop_index
-and value indexed by
-.I val_index.
-.PP
-ni_status \fBni_writeprop\fr(void *\fIhandle\fR, ni_id *\fIdir\fR, ni_index \fIprop_index\fR, ni_namelist \fIvalues\fR)
-.IP
-Writes a new value list to the property indexed by
-.I prop_index.
-It is allowable to have more than one property with the same name.
-.IP
+++ /dev/null
-.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)
+++ /dev/null
-/*
- * 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 <rpc/rpc.h>
-#include <netinfo/ni_prot.h>
-#include <netinfo/nibind_prot.h>
-typedef const char *ni_name_const;
-#include <netinfo/ni_util.h>
-
-/*
- * 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__
-
+++ /dev/null
-/*
- * 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 <netinfo/ni.h>
-
-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)");
-}
+++ /dev/null
-/*
- * 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 <libc.h>
-#include <string.h>
-#include <syslog.h>
-#include <netinfo/ni.h>
-#include <rpc/pmap_clnt.h>
-#include <rpc/pmap_prot.h>
-#include <rpc/xdr.h>
-#include <net/if.h>
-#include <ctype.h>
-#include <errno.h>
-#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;
-}
+++ /dev/null
-/*
- * 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 <string.h>
-#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<NI_NAME_MAXLEN>;
-
-
-typedef ni_name ni_namelist<NI_NAMELIST_MAXLEN>;
-
-/*
- * A property
- */
-struct ni_property {
- ni_name nip_name;
- ni_namelist nip_val;
-};
-
-/*
- * A list of properties
- */
-typedef ni_property ni_proplist<NI_PROPLIST_MAXLEN>;
-
-/*
- * A list of IDs (yet another variable-length array)
- */
-typedef ni_index ni_idlist<NI_IDLIST_MAXLEN>;
-
-
-/*
- * 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<NI_IDLIST_MAXLEN>;
-
-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<NI_IDLIST_MAXLEN>;
-
-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;
+++ /dev/null
-/*
- * 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 <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <stdio.h>
-#include <string.h>
-#include <netinfo/ni.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <sys/ioctl.h>
-#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;
-}
--- /dev/null
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+
+#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; }
+++ /dev/null
-/*
- * 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 <stdlib.h>
-#include <netinfo/ni.h>
-#include <string.h>
-#include <ctype.h>
-#include <netdb.h>
-#include <stdio.h>
-#include <arpa/inet.h>
-
-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 <tag>@<address> 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 <tag>@<address> 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> [/[<domainspec>][:[<dirspec>]]]
- * hostspec ::= [[[user][:[password]]]@]hostref
- * hostref ::= <inet_addr> | <hostname>
- * domainspec ::= <abs_domain> | <rel_domain>
- * dirspec ::= <path> | <unsigned_integer>
- */
-
- x = strlen("netinfo://");
-
- if (strncmp(url, "netinfo://", x)) return;
-
- /*
- * Look for <hostspec> 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 <domainspec> 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 <dirspec> part
- * NULL <dirspec> 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;
-}
+++ /dev/null
-/*
- * 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 <netinfo/ni.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <strings.h>
-#include <regex.h>
-#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;
-}
+++ /dev/null
-/*
- * 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 <netinfo/ni.h>
-
-#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> [/[<domainspec>][:[<dirspec>]]]
- * hostspec ::= [[[user][:[password]]]@]hostref
- * hostref ::= <inet_addr> | <hostname>
- * domainspec ::= <abs_domain> | <rel_domain>
- * dirspec ::= <path> | <unsigned_integer>
- */
-ni_status ni_url(char *, void **, ni_id *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif !_NI_UTIL_H_
-
+++ /dev/null
-/*
- * 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 <netinfo/ni_prot.h>
-%#endif
-#else
-%#include <string.h>
-#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<NIBIND_MAXREGS>;
-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;
+++ /dev/null
-/*
- * 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 <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <ifaddrs.h>
-#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;
-}
+++ /dev/null
-/*
- * 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 <sys/types.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <net/if.h>
-
-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__ */
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
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)"
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)"
+
AFTER_POSTINSTALL += install-nis-man
PUBLIC_HEADER_DIR_SUFFIX = /rpcsvc
+OTHER_CFLAGS += -D__DARWIN_NON_CANCELABLE=1
+
# for building 64-bit
# <rdar://problem/3819761> Libinfo need to build with gcc-3.5 and 3-way fat
NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER)
return FALSE;
}
return xdr_pointer(xdrs, (caddr_t *)&objp->next,
- sizeof(struct ypmaplist), xdr_ypmaplist);
+ sizeof(struct ypmaplist), (xdrproc_t)xdr_ypmaplist);
}
return FALSE;
}
return xdr_pointer(xdrs, (caddr_t *)&objp->maps,
- sizeof(struct ypmaplist), xdr_ypmaplist);
+ sizeof(struct ypmaplist), (xdrproc_t)xdr_ypmaplist);
}
--- /dev/null
+.\" Copyright (c) 1992/3 Theo de Raadt <deraadt@fsa.ca>
+.\" 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.
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;
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;
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;
}
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);
#include <rpc/xdr.h>
#include <rpcsvc/yp.h>
#include <rpcsvc/ypclnt.h>
+#include <notify.h>
+#include <pthread.h>
#include "ypinternal.h"
+extern int notify_register_plain(char *, int *);
+
struct dom_binding *_ypbindlist = NULL;
char _yp_domain[MAXHOSTNAMELEN] = { '\0' };
struct dom_binding **ypdb;
{
static int pid = -1;
- char path[MAXPATHLEN];
struct dom_binding *ysd, *ysd2;
struct ypbind_resp ypbr;
struct timeval tv;
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
* 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;
}
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 ||
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)
(*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;
}
struct ypresp_maplist ypml;
struct timeval tv;
int tries = 0, r;
+ static int proto = YP_BIND_UDP;
again:
if (_yp_dobind(indomain, &ysd) != 0)
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);
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 ||
(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;
}
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 ||
(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
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);
.Nm ypprot_err
.Nd Interface to the YP subsystem
.Sh SYNOPSIS
-.Fd #include <sys/types.h>
+.Fd #include <rpc/rpc.h>
.Fd #include <rpcsvc/ypclnt.h>
.Fd #include <rpcsvc/yp_prot.h>
.Ft int
.Xr ypbind 8 ,
.Xr ypserv 8
.Sh AUTHOR
-Theo De Raadt
+Theo De Raadt
\ No newline at end of file
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 *,
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 ||
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) {
#endif
}
out:
- xdr_free(xdr_ypresp_val, (char *) &yprv);
+ xdr_free((xdrproc_t)xdr_ypresp_val, (char *) &yprv);
_yp_unbind(ysd);
return r;
}
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 ||
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)
(*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;
}
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
--- /dev/null
+###############################################################################
+# 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"
+
OTHER_CFLAGS = \
+ -D__DARWIN_NON_CANCELABLE=1 \
-Dsetrpcent=_old_setrpcent \
-Dgetrpcent=_old_getrpcent \
-Dendrpcent=_old_endrpcent \
# for building 64-bit
# <rdar://problem/3819761> Libinfo need to build with gcc-3.5 and 3-way fat
NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER)
+
+AFTER_POSTINSTALL += install-man-page
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 {
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();
if (len > maxgrplist) {
len = maxgrplist;
}
- return (authunix_create(machname, uid, gid, len, gids));
+ return (authunix_create(machname, uid, gid, len, (int *)gids));
}
/*
* 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;
&& 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);
--- /dev/null
+.\" 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 <sys/types.h>
+.Fd include <netinet/in.h>
+.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.
struct sockaddr_in6 *sin6;
int proto, portrange, portlow;
u_int16_t port;
- int salen;
+ u_int32_t salen;
if (sa == NULL) {
salen = sizeof(myaddr);
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)
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
{
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 */
* 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;
* 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
* 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
* 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
* 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
* 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;
*
* 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
*/
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;
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;
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;
}
*/
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));
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;
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 */
/*
*
* 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).
*
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();
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 */
* 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;
/*
* 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;
}
* 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;
/*
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;
/*
* 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));
* 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
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 =
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);
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 */
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;
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);
/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2007 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
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;
/*
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;
* 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)))
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
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;
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);
}
/*
* 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.
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;
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;
--- /dev/null
+.\" 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 <netdb.h>
+.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.
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);
--- /dev/null
+.\" 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 <rpc/rpc.h>
+.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.
#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.
*/
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;
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;
}
/*
*/
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;
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;
}
#include <sys/cdefs.h>
__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 */
#define NAMELEN 255
#define MAX_BROADCAST_SIZE 1400
-#include "pmap_wakeup.h"
-
extern int errno;
/*
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);
#include <sys/socket.h>
#include <net/if.h>
-#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);
+}
+
#include <sys/cdefs.h>
#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)
#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 {
*/
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);
}
#include <arpa/inet.h>
#define MAX_BROADCAST_SIZE 1400
-#include "pmap_wakeup.h"
-
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;
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) {
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;
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);
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 */
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;
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.
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)) {
} /* 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;
#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);
#include <sys/cdefs.h>
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;
};
#include "pmap_wakeup.h"
-void pmap_wakeup(void)
+int pmap_wakeup(void)
{
struct sockaddr_un sun;
int fd;
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;
}
#ifndef __PMAP_WAKEUP_H__
#define __PMAP_WAKEUP_H__
-void pmap_wakeup(void);
+int pmap_wakeup(void);
#endif
--- /dev/null
+.\" 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 <rpc/rpc.h>
+.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.
+
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) {
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);
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);
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);
*/
}
}
}
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);
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) {
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) {
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) {
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);
*/
}
}
#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)
/*
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;
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;
* 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 */
};
* 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;
}
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 } };
/*
}
/* 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
}
/* 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
}
/*
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) {
*/
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;
*/
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;
*/
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;
* 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 */
*
* 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
/*
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 *));
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];
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);
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);
*/
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;
{
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) {
* 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);
}
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)) {
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) {
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);
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) {
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))
#endif
#include <sys/time.h>
+#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 */
--- /dev/null
+.\" @(#)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
#include <rpc/types.h>
#include <rpc/xdr.h>
+#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)
/*
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:
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:
bool_t
xdr_long(xdrs, lp)
XDR *xdrs;
+#ifdef __LP64__
+ int *lp;
+#else
long *lp;
+#endif
{
switch (xdrs->x_op) {
case XDR_ENCODE:
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);
}
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:
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:
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:
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:
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:
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:
XDR *xdrs;
u_char *cp;
{
- u_int u;
+ u_int32_t u;
u = (*cp);
if (!xdr_u_int(xdrs, &u)) {
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)) {
/*
* 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)) {
caddr_t cp;
u_int cnt;
{
- u_int rndup;
+ u_int32_t rndup;
static int crud[BYTES_PER_XDR_UNIT];
/*
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
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
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]));
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]));
XDR *xdrs;
longlong_t *llp;
{
-
/*
* Don't bother open-coding this; it's a fair amount of code. Just
* call xdr_int64_t().
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().
XDR *xdrs;
longlong_t *llp;
{
-
/*
* Don't bother open-coding this; it's a fair amount of code. Just
* call xdr_int64_t().
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 " */
#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)
#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))
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 *);
*/
#include <sys/types.h>
+#include <stddef.h>
#include <netinet/in.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
+#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! */
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;
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);
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);
static bool_t
xdrmem_getlong_unaligned(xdrs, lp)
XDR *xdrs;
- long *lp;
+ xdrlong_t *lp;
{
u_int32_t l;
static bool_t
xdrmem_putlong_unaligned(xdrs, lp)
XDR *xdrs;
- const long *lp;
+ const xdrlong_t *lp;
{
u_int32_t l;
char *addr;
u_int len;
{
-
if (xdrs->x_handy < len)
return (FALSE);
xdrs->x_handy -= len;
const char *addr;
u_int len;
{
-
if (xdrs->x_handy < len)
return (FALSE);
xdrs->x_handy -= len;
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
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) <? sizeof(ptrdiff_t) */
+ delta = lastaddr - newaddr;
+#ifdef __LP64__
+ if (delta > UINT32_MAX) return (FALSE);
+#endif
+ xdrs->x_handy = delta;
return (TRUE);
}
XDR *xdrs;
u_int len;
{
-
return (0);
}
* 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.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/svc.h>
#include <rpc/clnt.h>
+#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);
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,
/*
* 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,
#define LAST_FRAG ((u_int32_t)(1 << 31))
typedef struct rec_strm {
- char *tcp_handle;
+ void *tcp_handle;
/*
* out-goung bits
*/
* 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;
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);
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);
}
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;
{
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) {
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);
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);
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;
}
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);
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;
}
RECSTREAM *rstrm;
int size;
{
- long diff;
+ int diff;
char *buf;
if (size > rstrm->recvsize) {
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);
XDR *xdrs;
u_int len;
{
- long llen;
+ size_t llen;
if (len == 0) {
return (NULL);
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);
return;
}
+#ifdef __LP64__
+unsigned int
+#else
unsigned long
+#endif
xdr_sizeof(func, data)
xdrproc_t func;
void *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;
#include <rpc/xdr.h>
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 *);
FILE *file;
enum xdr_op op;
{
-
xdrs->x_op = op;
xdrs->x_ops = &xdrstdio_ops;
xdrs->x_private = file;
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);
}
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);
}
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 */
$(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"
AFTER_POSTINSTALL += install-man-page
OTHER_CFLAGS = \
+ -D__DARWIN_NON_CANCELABLE=1 \
-DINET6=1
# for building 64-bit
.Xr rcmd 3 ,
.Xr ruserok 3 ,
.Xr netgroup 5
-.Re
.Sh HISTORY
The
.Nm .rhosts
*
* @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 <stdlib.h>
-#include <stdio.h>
-#include <pwd.h>
-#include <ctype.h>
-#include <netinfo/ni.h>
-#include <libc.h>
-
-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;
+}
*
* @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 <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <utmp.h>
+#include <utmpx.h>
#define NCACHE 64 /* power of 2 */
#define MASK (NCACHE - 1) /* bits to store with */
{
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 */
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);
}
{
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 */
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);
}
#include <sys/socket.h>
#include <sys/stat.h>
-#include <netinet/in.h>
#include <arpa/inet.h>
-#include <netinfo/ni_util.h>
#include <signal.h>
#include <fcntl.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
+#include <time.h>
#ifdef YP
#include <rpc/rpc.h>
#include <rpcsvc/yp_prot.h>
} 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)
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.
*
{
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))
}
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");