From c29f2fccbf0d388644e29ea3e98c38a343688bd2 Mon Sep 17 00:00:00 2001 From: Apple Date: Thu, 10 Mar 2005 17:44:25 +0000 Subject: [PATCH] Libinfo-221.tar.gz --- Makefile | 5 +- Makefile.preamble | 4 + PB.project | 1 + dns.subproj/Makefile.preamble | 4 + dns.subproj/gethnamaddr.c | 10 +- dns.subproj/getnetnamadr.c | 4 +- dns.subproj/inet.h | 20 +- dns.subproj/nameser8_compat.h | 14 +- dns.subproj/portability.h | 12 +- dns.subproj/res_data.c | 26 +- dns.subproj/res_debug.c | 7 +- dns.subproj/resolv8_compat.h | 60 +- gen.subproj/Makefile.preamble | 4 + gen.subproj/ether_addr.c | 14 +- gen.subproj/fstab.c | 12 - gen.subproj/gethostbyname.3 | 2 +- gen.subproj/getifaddrs.3 | 18 +- gen.subproj/getnetent.3 | 2 +- gen.subproj/ifaddrs.h | 2 +- gen.subproj/inet6_option_space.3 | 315 +--- gen.subproj/inet6_rthdr_space.3 | 168 +- gen.subproj/initgroups.c | 19 +- lookup.subproj/Makefile.preamble | 4 + lookup.subproj/getaddrinfo.3 | 671 +++---- lookup.subproj/getaddrinfo.c | 158 +- lookup.subproj/getnameinfo.3 | 414 ++--- lookup.subproj/lu_bootp.c | 6 +- lookup.subproj/lu_group.c | 258 ++- lookup.subproj/lu_host.c | 133 +- lookup.subproj/lu_host_async.c | 6 +- lookup.subproj/lu_netgroup.c | 57 +- lookup.subproj/lu_network.c | 2 +- lookup.subproj/lu_user.c | 13 +- lookup.subproj/lu_utils.c | 69 +- lookup.subproj/netdb.h | 92 +- lookup.subproj/netdb_async.h | 3 + lookup.subproj/netgr.h | 14 +- mdns.subproj/DNSServiceDiscovery.c | 18 +- mdns.subproj/DNSServiceDiscovery.h | 23 +- mdns.subproj/DNSServiceDiscoveryDefines.h | 1 + mdns.subproj/DNSServiceDiscoveryRequest.defs | 3 +- mdns.subproj/Makefile | 2 +- mdns.subproj/Makefile.preamble | 4 + mdns.subproj/dns_sd.h | 1252 +++++++++---- mdns.subproj/dnssd_clientlib.c | 361 ++++ mdns.subproj/dnssd_clientstub.c | 1090 ++++++----- mdns.subproj/dnssd_ipc.c | 207 ++- mdns.subproj/dnssd_ipc.h | 197 +- membership.subproj/Makefile | 48 + membership.subproj/Makefile.postamble | 0 membership.subproj/Makefile.preamble | 17 + membership.subproj/PB.project | 36 + membership.subproj/memberd.defs | 66 + membership.subproj/memberd_defines.h | 53 + membership.subproj/membership.c | 452 +++++ membership.subproj/membership.h | 44 + membership.subproj/membershipPriv.h | 43 + membership.subproj/ntsid.h | 37 + netinfo.subproj/Makefile.postamble | 2 - netinfo.subproj/Makefile.preamble | 4 + netinfo.subproj/clib.h | 2 +- netinfo.subproj/ni_glue.c | 1708 +++++++++--------- netinfo.subproj/ni_pwdomain.c | 8 +- netinfo.subproj/sys_interfaces.c | 8 +- netinfo.subproj/sys_interfaces.h | 8 +- nis.subproj/Makefile.preamble | 4 + nis.subproj/yp_prot.h | 96 +- nis.subproj/ypclnt.3 | 2 +- nis.subproj/ypclnt.h | 4 +- nis.subproj/ypinternal.h | 8 +- rpc.subproj/Makefile | 4 +- rpc.subproj/Makefile.preamble | 4 + rpc.subproj/PB.project | 3 + rpc.subproj/auth.h | 27 +- rpc.subproj/auth_unix.h | 6 +- rpc.subproj/clnt.h | 74 +- rpc.subproj/pmap_clnt.c | 8 +- rpc.subproj/pmap_clnt.h | 16 +- rpc.subproj/pmap_getmaps.c | 6 +- rpc.subproj/pmap_getport.c | 6 +- rpc.subproj/pmap_prot.h | 24 +- rpc.subproj/pmap_rmt.c | 7 +- rpc.subproj/pmap_rmt.h | 8 +- rpc.subproj/pmap_wakeup.c | 31 + rpc.subproj/pmap_wakeup.h | 6 + rpc.subproj/rpc_msg.h | 24 +- rpc.subproj/svc.h | 52 +- rpc.subproj/svc_tcp.c | 7 +- rpc.subproj/svc_udp.c | 8 +- rpc.subproj/types.h | 15 +- rpc.subproj/xdr.c | 460 ++++- rpc.subproj/xdr.h | 244 ++- rpc.subproj/xdr_array.c | 69 +- rpc.subproj/xdr_float.c | 99 +- rpc.subproj/xdr_mem.c | 205 ++- rpc.subproj/xdr_rec.c | 501 +++-- rpc.subproj/xdr_reference.c | 46 +- rpc.subproj/xdr_sizeof.c | 194 ++ rpc.subproj/xdr_stdio.c | 81 +- util.subproj/Makefile | 2 +- util.subproj/Makefile.preamble | 4 + util.subproj/PB.project | 2 +- util.subproj/glob.c | 897 --------- util.subproj/pwcache.c | 12 - 104 files changed, 6701 insertions(+), 4882 deletions(-) create mode 100755 mdns.subproj/dnssd_clientlib.c create mode 100644 membership.subproj/Makefile create mode 100644 membership.subproj/Makefile.postamble create mode 100644 membership.subproj/Makefile.preamble create mode 100644 membership.subproj/PB.project create mode 100644 membership.subproj/memberd.defs create mode 100644 membership.subproj/memberd_defines.h create mode 100644 membership.subproj/membership.c create mode 100644 membership.subproj/membership.h create mode 100644 membership.subproj/membershipPriv.h create mode 100644 membership.subproj/ntsid.h create mode 100644 rpc.subproj/pmap_wakeup.c create mode 100644 rpc.subproj/pmap_wakeup.h create mode 100644 rpc.subproj/xdr_sizeof.c delete mode 100644 util.subproj/glob.c diff --git a/Makefile b/Makefile index cbb3bca..6739fad 100644 --- a/Makefile +++ b/Makefile @@ -12,8 +12,9 @@ NAME = info PROJECTVERSION = 2.8 PROJECT_TYPE = Library -SUBPROJECTS = dns.subproj gen.subproj lookup.subproj netinfo.subproj\ - nis.subproj rpc.subproj util.subproj mdns.subproj +SUBPROJECTS = dns.subproj gen.subproj lookup.subproj membership.subproj\ + netinfo.subproj nis.subproj rpc.subproj util.subproj\ + mdns.subproj OTHERSRCS = Makefile.preamble Makefile Makefile.postamble diff --git a/Makefile.preamble b/Makefile.preamble index 4e19fe6..606002d 100644 --- a/Makefile.preamble +++ b/Makefile.preamble @@ -2,3 +2,7 @@ LIBRARY_STYLE = STATIC STRIP_ON_INSTALL = NO BEFORE_INSTALL += debug profile override LINK_SUBPROJECTS = NO + +# for building 64-bit +# Libinfo need to build with gcc-3.5 and 3-way fat +export CCOMPILER = /usr/bin/gcc-3.5 diff --git a/PB.project b/PB.project index bda4330..34ca56b 100644 --- a/PB.project +++ b/PB.project @@ -10,6 +10,7 @@ dns.subproj, gen.subproj, lookup.subproj, + membership.subproj, netinfo.subproj, nis.subproj, rpc.subproj, diff --git a/dns.subproj/Makefile.preamble b/dns.subproj/Makefile.preamble index 4b5a0be..c775255 100644 --- a/dns.subproj/Makefile.preamble +++ b/dns.subproj/Makefile.preamble @@ -22,3 +22,7 @@ ARPA_HEADER_DIR_SUFFIX = /arpa ARPA_HEADERS = inet.h ARPA_SYMLINKED_HEADERS = nameser8_compat.h AFTER_INSTALLHDRS += arpa_headers + +# for building 64-bit +# Libinfo need to build with gcc-3.5 and 3-way fat +NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER) diff --git a/dns.subproj/gethnamaddr.c b/dns.subproj/gethnamaddr.c index 9dff96b..b95f26f 100644 --- a/dns.subproj/gethnamaddr.c +++ b/dns.subproj/gethnamaddr.c @@ -78,7 +78,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93"; -static char rcsid[] = "$Id: gethnamaddr.c,v 1.8 2003/07/03 21:56:17 majka Exp $"; +static char rcsid[] = "$Id: gethnamaddr.c,v 1.9 2004/10/07 17:33:33 majka Exp $"; #endif /* LIBC_SCCS and not lint */ #include @@ -526,13 +526,15 @@ gethostbyname_ipv4(name) } struct hostent * -gethostbyaddr(addr, len, type) - const char *addr; - int len, type; +gethostbyaddr(vaddr, len, type) + const void *vaddr; + socklen_t len; + int type; { int n; querybuf buf; register struct hostent *hp; + const char* addr = (const char *)vaddr; char qbuf[MAXDNAME+1]; #ifdef SUNSECURITY register struct hostent *rhp; diff --git a/dns.subproj/getnetnamadr.c b/dns.subproj/getnetnamadr.c index cd05dcc..bd62e06 100644 --- a/dns.subproj/getnetnamadr.c +++ b/dns.subproj/getnetnamadr.c @@ -64,7 +64,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)getnetbyaddr.c 8.1 (Berkeley) 6/4/93"; static char sccsid_[] = "from getnetnamadr.c 1.4 (Coimbra) 93/06/03"; -static char rcsid[] = "$Id: getnetnamadr.c,v 1.4 2003/02/18 17:29:23 majka Exp $"; +static char rcsid[] = "$Id: getnetnamadr.c,v 1.5 2004/10/07 17:33:33 majka Exp $"; #endif /* LIBC_SCCS and not lint */ #include @@ -232,7 +232,7 @@ static char *net_aliases[MAXALIASES], *netbuf = NULL; struct netent * getnetbyaddr(net, net_type) - register long net; + register uint32_t net; register int net_type; { unsigned int netbr[4]; diff --git a/dns.subproj/inet.h b/dns.subproj/inet.h index 53f3f6a..6091ed9 100644 --- a/dns.subproj/inet.h +++ b/dns.subproj/inet.h @@ -78,7 +78,7 @@ /* * @(#)inet.h 8.1 (Berkeley) 6/2/93 - * $Id: inet.h,v 1.4 2003/05/20 23:00:27 majka Exp $ + * $Id: inet.h,v 1.7 2004/10/28 21:58:13 emoy Exp $ */ #ifndef _INET_H_ @@ -86,6 +86,10 @@ /* External definitions for functions in inet(3) */ +#include /* uint32_t uint16_t */ +#include /* htonl() and family if !_POSIX_C_SOURCE */ +#include /* htonl() and family if _POSIX_C_SOURCE */ +#include /* in_addr */ #include #if (!defined(BSD)) || (BSD < 199306) # include @@ -96,22 +100,24 @@ __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); +int inet_pton(int, const char *, void *); +#ifndef _POSIX_C_SOURCE int ascii2addr(int, const char *, void *); char *addr2ascii(int, const void *, int, char *); -in_addr_t inet_addr(const char *); int inet_aton(const char *, struct in_addr *); in_addr_t inet_lnaof(struct in_addr); struct in_addr inet_makeaddr(in_addr_t, in_addr_t); in_addr_t inet_netof(struct in_addr); in_addr_t inet_network(const char *); -char *inet_ntoa(struct in_addr); -int inet_pton(int, const char *, void *); -const char *inet_ntop(int, const void *, char *, size_t); 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); -u_int inet_nsap_addr(const char *, u_char *, int maxlen); -char *inet_nsap_ntoa(int, const u_char *, char *ascii); +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 */ __END_DECLS diff --git a/dns.subproj/nameser8_compat.h b/dns.subproj/nameser8_compat.h index daf88cd..809ec6b 100644 --- a/dns.subproj/nameser8_compat.h +++ b/dns.subproj/nameser8_compat.h @@ -78,7 +78,7 @@ /* * @(#)nameser.h 8.1 (Berkeley) 6/2/93 - * $Id: nameser8_compat.h,v 1.2 2003/02/18 17:29:24 majka Exp $ + * $Id: nameser8_compat.h,v 1.3 2004/10/28 21:58:13 emoy Exp $ */ #ifndef _NAMESER_H_ @@ -320,8 +320,8 @@ struct rrec { char *r_data; /* pointer to data */ }; -extern u_int16_t _getshort __P((const u_char *)); -extern u_int32_t _getlong __P((const u_char *)); +extern u_int16_t _getshort __P((const unsigned char *)); +extern u_int32_t _getlong __P((const unsigned char *)); /* * Inline versions of get/put short/long. Pointer is advanced. @@ -330,7 +330,7 @@ extern u_int32_t _getlong __P((const u_char *)); * portable or it can be elegant but rarely both. */ #define GETSHORT(s, cp) { \ - register u_char *t_cp = (u_char *)(cp); \ + register unsigned char *t_cp = (unsigned char *)(cp); \ (s) = ((u_int16_t)t_cp[0] << 8) \ | ((u_int16_t)t_cp[1]) \ ; \ @@ -338,7 +338,7 @@ extern u_int32_t _getlong __P((const u_char *)); } #define GETLONG(l, cp) { \ - register u_char *t_cp = (u_char *)(cp); \ + register unsigned char *t_cp = (unsigned char *)(cp); \ (l) = ((u_int32_t)t_cp[0] << 24) \ | ((u_int32_t)t_cp[1] << 16) \ | ((u_int32_t)t_cp[2] << 8) \ @@ -349,7 +349,7 @@ extern u_int32_t _getlong __P((const u_char *)); #define PUTSHORT(s, cp) { \ register u_int16_t t_s = (u_int16_t)(s); \ - register u_char *t_cp = (u_char *)(cp); \ + register unsigned char *t_cp = (unsigned char *)(cp); \ *t_cp++ = t_s >> 8; \ *t_cp = t_s; \ (cp) += INT16SZ; \ @@ -357,7 +357,7 @@ extern u_int32_t _getlong __P((const u_char *)); #define PUTLONG(l, cp) { \ register u_int32_t t_l = (u_int32_t)(l); \ - register u_char *t_cp = (u_char *)(cp); \ + register unsigned char *t_cp = (unsigned char *)(cp); \ *t_cp++ = t_l >> 24; \ *t_cp++ = t_l >> 16; \ *t_cp++ = t_l >> 8; \ diff --git a/dns.subproj/portability.h b/dns.subproj/portability.h index 55ed578..58ab529 100644 --- a/dns.subproj/portability.h +++ b/dns.subproj/portability.h @@ -24,7 +24,7 @@ /* portability.h - include or define things that aren't present on all systems * vixie@decwrl 26dec92 [new] * - * $Id: portability.h,v 1.2 1999/10/14 21:56:45 wsanchez Exp $ + * $Id: portability.h,v 1.3 2004/10/28 21:58:14 emoy Exp $ */ /* @@ -290,11 +290,11 @@ extern long pathconf __P((const char *path, int name)); #ifndef UINT_MAX # ifdef __STDC__ -# define UINT_MAX 4294967295u /* max value of an "u_int" */ +# define UINT_MAX 4294967295u /* max value of an "unsigned int" */ # else -# define UINT_MAX ((unsigned)4294967295) /* max value of an "u_int" */ +# define UINT_MAX ((unsigned)4294967295) /* max value of an "unsigned int" */ # endif -# define ULONG_MAX UINT_MAX /* max decimal value of a "u_long" */ +# define ULONG_MAX UINT_MAX /* max decimal value of a "unsigned long" */ #endif #ifndef INT_MAX @@ -414,8 +414,8 @@ extern int bcmp(); #if !defined(ntohl) && !defined(htonl) && defined(BSD) && (BSD <= 43) /* if these aren't null macros in netinet/in.h, extern them here. */ -extern u_short htons(), ntohs(); -extern u_long htonl(), ntohl(); +extern unsigned short htons(), ntohs(); +extern unsigned long htonl(), ntohl(); #endif #if defined(USE_POSIX) && !defined(sun) && !defined(__sgi) \ diff --git a/dns.subproj/res_data.c b/dns.subproj/res_data.c index 4bc8ba3..4f19602 100644 --- a/dns.subproj/res_data.c +++ b/dns.subproj/res_data.c @@ -28,19 +28,15 @@ #if defined(__APPLE__) -#include -#include -#include -#include -#include -#include - -/* From res_init.c */ - -struct __res_state _res = {0}; - -/* From getnetent.c */ - +/* + * _res is declared to be the same siae as struct __res_9_state + * This allows both the BIND-8 library in libSystem (this one) + * and the new BIND-9 library in libresolv to share the same + * structure. We ues the __res_9_state's _pad variable to store + * a version number when _res have been initialized by the BIND-9 + * library, and take precautions to make them work together. + */ +#define RES_9_STATE_SIZE 512 +char _res[RES_9_STATE_SIZE] = {0}; int _net_stayopen = 0; - -#endif /* NeXT */ +#endif diff --git a/dns.subproj/res_debug.c b/dns.subproj/res_debug.c index 6455fdb..ba2cfb4 100644 --- a/dns.subproj/res_debug.c +++ b/dns.subproj/res_debug.c @@ -78,7 +78,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93"; -static char rcsid[] = "$Id: res_debug.c,v 1.4 2003/02/18 17:29:24 majka Exp $"; +static char rcsid[] = "$Id: res_debug.c,v 1.5 2004/06/11 23:16:00 majka Exp $"; #endif /* LIBC_SCCS and not lint */ #include @@ -476,7 +476,8 @@ __p_rr(cp, msg, file) const u_char *cp, *msg; FILE *file; { - int type, class, dlen, n, c; + int type, class, n, c; + long dlen; struct in_addr inaddr; const u_char *cp1, *cp2; u_int32_t tmpttl, t; @@ -703,7 +704,7 @@ __p_rr(cp, msg, file) putc('\n', file); #endif if (cp - cp1 != dlen) { - fprintf(file, ";; packet size error (found %d, dlen was %d)\n", + fprintf(file, ";; packet size error (found %ld, dlen was %ld)\n", cp - cp1, dlen); cp = NULL; } diff --git a/dns.subproj/resolv8_compat.h b/dns.subproj/resolv8_compat.h index 3b47927..c33fe77 100644 --- a/dns.subproj/resolv8_compat.h +++ b/dns.subproj/resolv8_compat.h @@ -78,7 +78,7 @@ /* * @(#)resolv.h 8.1 (Berkeley) 6/2/93 - * $Id: resolv8_compat.h,v 1.2 2003/02/18 17:29:25 majka Exp $ + * $Id: resolv8_compat.h,v 1.3 2004/10/28 21:58:14 emoy Exp $ */ #ifndef _RESOLV_H_ @@ -128,15 +128,15 @@ struct __res_state { int retrans; /* retransmition time interval */ int retry; /* number of times to retransmit */ - u_long options; /* option flags - see below. */ + unsigned long options; /* option flags - see below. */ int nscount; /* number of name servers */ struct sockaddr_in nsaddr_list[MAXNS]; /* address of name server */ #define nsaddr nsaddr_list[0] /* for backward compatibility */ - u_short id; /* current packet id */ + unsigned short id; /* current packet id */ char *dnsrch[MAXDNSRCH+1]; /* components of domain to search */ char defdname[MAXDNAME]; /* default domain */ - u_long pfcode; /* RES_PRF_ flags - see below. */ + unsigned long pfcode; /* RES_PRF_ flags - see below. */ unsigned ndots:4; /* threshold for initial abs. query */ unsigned nsort:4; /* number of elements in sort_list[] */ char unused[3]; @@ -190,16 +190,16 @@ typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error } res_sendhookact; typedef res_sendhookact (*res_send_qhook)__P((struct sockaddr_in * const *ns, - const u_char **query, + const unsigned char **query, int *querylen, - u_char *ans, + unsigned char *ans, int anssiz, int *resplen)); typedef res_sendhookact (*res_send_rhook)__P((const struct sockaddr_in *ns, - const u_char *query, + const unsigned char *query, int querylen, - u_char *ans, + unsigned char *ans, int anssiz, int *resplen)); @@ -225,39 +225,39 @@ extern struct __res_state _res; #define res_nameinquery __res_nameinquery #define res_queriesmatch __res_queriesmatch __BEGIN_DECLS -int __dn_skipname __P((const u_char *, const u_char *)); +int __dn_skipname __P((const unsigned char *, const unsigned char *)); void __fp_resstat __P((struct __res_state *, FILE *)); -void __fp_query __P((const u_char *, FILE *)); -void __fp_nquery __P((const u_char *, int, FILE *)); +void __fp_query __P((const unsigned char *, FILE *)); +void __fp_nquery __P((const unsigned char *, int, FILE *)); char *__hostalias __P((const char *)); -void __putlong __P((u_int32_t, u_char *)); -void __putshort __P((u_int16_t, u_char *)); +void __putlong __P((u_int32_t, unsigned char *)); +void __putshort __P((u_int16_t, unsigned char *)); char *__p_time __P((u_int32_t)); -void __p_query __P((const u_char *)); -const u_char *__p_cdnname __P((const u_char *, const u_char *, int, FILE *)); -const u_char *__p_cdname __P((const u_char *, const u_char *, FILE *)); -const u_char *__p_fqname __P((const u_char *, const u_char *, FILE *)); -const u_char *__p_rr __P((const u_char *, const u_char *, FILE *)); +void __p_query __P((const unsigned char *)); +const unsigned char *__p_cdnname __P((const unsigned char *, const unsigned char *, int, FILE *)); +const unsigned char *__p_cdname __P((const unsigned char *, const unsigned char *, FILE *)); +const unsigned char *__p_fqname __P((const unsigned char *, const unsigned char *, FILE *)); +const unsigned char *__p_rr __P((const unsigned char *, const unsigned char *, FILE *)); const char *__p_type __P((int)); const char *__p_class __P((int)); -const char *__p_option __P((u_long option)); -int dn_comp __P((const char *, u_char *, int, u_char **, u_char **)); -int dn_expand __P((const u_char *, const u_char *, const u_char *, +const char *__p_option __P((unsigned long option)); +int dn_comp __P((const char *, unsigned char *, int, unsigned char **, unsigned char **)); +int dn_expand __P((const unsigned char *, const unsigned char *, const unsigned char *, char *, int)); int res_init __P((void)); u_int16_t res_randomid __P((void)); -int res_query __P((const char *, int, int, u_char *, int)); -int res_search __P((const char *, int, int, u_char *, int)); +int res_query __P((const char *, int, int, unsigned char *, int)); +int res_search __P((const char *, int, int, unsigned char *, int)); int res_querydomain __P((const char *, const char *, int, int, - u_char *, int)); -int res_mkquery __P((int, const char *, int, int, const u_char *, int, - const u_char *, u_char *, int)); -int res_send __P((const u_char *, int, u_char *, int)); + unsigned char *, int)); +int res_mkquery __P((int, const char *, int, int, const unsigned char *, int, + const unsigned char *, unsigned char *, int)); +int res_send __P((const unsigned char *, int, unsigned char *, int)); int res_isourserver __P((const struct sockaddr_in *)); int res_nameinquery __P((const char *, int, int, - const u_char *, const u_char *)); -int res_queriesmatch __P((const u_char *, const u_char *, - const u_char *, const u_char *)); + const unsigned char *, const unsigned char *)); +int res_queriesmatch __P((const unsigned char *, const unsigned char *, + const unsigned char *, const unsigned char *)); __END_DECLS #endif /* !_RESOLV_H_ */ diff --git a/gen.subproj/Makefile.preamble b/gen.subproj/Makefile.preamble index 97b5bb5..baa75c4 100644 --- a/gen.subproj/Makefile.preamble +++ b/gen.subproj/Makefile.preamble @@ -31,3 +31,7 @@ OTHER_CFLAGS = \ -Dgetfsspec=_old_getfsspec \ -Dinitgroups=_old_initgroups \ -I../lookup.subproj + +# for building 64-bit +# Libinfo need to build with gcc-3.5 and 3-way fat +NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER) diff --git a/gen.subproj/ether_addr.c b/gen.subproj/ether_addr.c index 9f91737..b6b726c 100644 --- a/gen.subproj/ether_addr.c +++ b/gen.subproj/ether_addr.c @@ -54,7 +54,7 @@ static const char ethers[] = "/etc/ethers"; * Returns zero if successful, non-zero otherwise. */ int ether_line(s, e, hostname) - char *s; /* the string to be parsed */ + const char *s; /* the string to be parsed */ struct ether_addr *e; /* ethernet address struct to be filled in */ char *hostname; /* hosts name to be set */ { @@ -97,7 +97,7 @@ ether_ntoa(e) */ struct ether_addr * ether_aton(s) - char *s; + const char *s; { static struct ether_addr *ep; register int i; @@ -121,9 +121,8 @@ ether_aton(s) * Given a host's name, this routine returns its 48 bit ethernet address. * Returns zero if successful, non-zero otherwise. */ -/* XXX need to override in netinfo */ -int ether_hostton(host, e) - char *host; /* function input */ +int _old_ether_hostton(host, e) + const char *host; /* function input */ struct ether_addr *e; /* function output */ { char currenthost[256]; @@ -156,10 +155,9 @@ int ether_hostton(host, e) * Given a 48 bit ethernet address, this routine return its host name. * Returns zero if successful, non-zero otherwise. */ -/* XXX need to override in netinfo */ -int ether_ntohost(host, e) +int _old_ether_ntohost(host, e) char *host; /* function output */ - struct ether_addr *e; /* function input */ + const struct ether_addr *e; /* function input */ { struct ether_addr currente; char buf[512]; diff --git a/gen.subproj/fstab.c b/gen.subproj/fstab.c index 121da79..5ccc4b1 100644 --- a/gen.subproj/fstab.c +++ b/gen.subproj/fstab.c @@ -21,18 +21,6 @@ * * @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. - * - * The NEXTSTEP Software License Agreement specifies the terms - * and conditions for redistribution. - * - * @(#)fstab.c 8.1 (Berkeley) 6/4/93 - */ - #include #include diff --git a/gen.subproj/gethostbyname.3 b/gen.subproj/gethostbyname.3 index ca14ce8..779383e 100644 --- a/gen.subproj/gethostbyname.3 +++ b/gen.subproj/gethostbyname.3 @@ -55,7 +55,7 @@ .Ft struct hostent * .Fn gethostbyname2 "const char *name" "int af" .Ft struct hostent * -.Fn gethostbyaddr "const char *addr" "int len" "int type" +.Fn gethostbyaddr "const char *addr" "socklen_t len" "int type" .Ft struct hostent * .Fn gethostent void .Ft void diff --git a/gen.subproj/getifaddrs.3 b/gen.subproj/getifaddrs.3 index 7409e90..6709032 100644 --- a/gen.subproj/getifaddrs.3 +++ b/gen.subproj/getifaddrs.3 @@ -55,7 +55,6 @@ structure contains at least the following entries: u_int ifa_flags; /* Interface flags */ struct sockaddr *ifa_addr; /* Interface address */ struct sockaddr *ifa_netmask; /* Interface netmask */ - struct sockaddr *ifa_broadaddr; /* Interface broadcast address */ struct sockaddr *ifa_dstaddr; /* P2P interface destination */ void *ifa_data; /* Address specific data */ .Ed @@ -96,17 +95,16 @@ field references the netmask associated with if one is set, otherwise it is NULL. .Pp The -.Li ifa_broadaddr -field, -which should only be referenced for non-P2P interfaces, -references the broadcast address associated with -.Li ifa_addr , -if one exists, otherwise it is NULL. -.Pp -The .Li ifa_dstaddr field references the destination address on a P2P interface, -if one exists, otherwise it is NULL. +if one exists, otherwise it contains the broadcast address. +.Pp +Note that as a convenience, +.Li ifa_broadaddr +is defined by a compiler +.Li #define +directive to be the same as +.Li ifa_dstaddr . .Pp The .Li ifa_data diff --git a/gen.subproj/getnetent.3 b/gen.subproj/getnetent.3 index d53c5c9..18bbd70 100644 --- a/gen.subproj/getnetent.3 +++ b/gen.subproj/getnetent.3 @@ -51,7 +51,7 @@ .Ft struct netent * .Fn getnetbyname "const char *name" .Ft struct netent * -.Fn getnetbyaddr "unsigned long net" "int type" +.Fn getnetbyaddr "uint32_t net" "int type" .Ft void .Fn setnetent "int stayopen" .Ft void diff --git a/gen.subproj/ifaddrs.h b/gen.subproj/ifaddrs.h index cf32dae..e264596 100644 --- a/gen.subproj/ifaddrs.h +++ b/gen.subproj/ifaddrs.h @@ -31,7 +31,7 @@ struct ifaddrs { struct ifaddrs *ifa_next; char *ifa_name; - u_int ifa_flags; + unsigned int ifa_flags; struct sockaddr *ifa_addr; struct sockaddr *ifa_netmask; struct sockaddr *ifa_dstaddr; diff --git a/gen.subproj/inet6_option_space.3 b/gen.subproj/inet6_option_space.3 index c5b6cc9..0d6ba0a 100644 --- a/gen.subproj/inet6_option_space.3 +++ b/gen.subproj/inet6_option_space.3 @@ -29,7 +29,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: inet6_option_space.3,v 1.2 2002/03/19 17:20:07 majka Exp $ +.\" $Id: inet6_option_space.3,v 1.3 2005/01/19 00:30:03 majka Exp $ .\" $FreeBSD: src/lib/libc/net/inet6_option_space.3,v 1.1.2.5 2001/08/17 15:42:38 ru Exp $ .\" .Dd December 10, 1999 @@ -73,318 +73,8 @@ The function prototypes for these functions are all in the .Aq Li netinet/in.h header. -.\" -.Ss inet6_option_space -.Fn inet6_option_space -returns the number of bytes required to hold an option when it is stored as -ancillary data, including the -.Li cmsghdr -structure at the beginning, -and any padding at the end -(to make its size a multiple of 8 bytes). -The argument is the size of the structure defining the option, -which must include any pad bytes at the beginning -(the value -.Li y -in the alignment term -.Dq Li "xn + y" ) , -the type byte, the length byte, and the option data. -.Pp -Note: If multiple options are stored in a single ancillary data -object, which is the recommended technique, this function -overestimates the amount of space required by the size of -.Li N-1 -.Li cmsghdr -structures, -where -.Li N -is the number of options to be stored in the object. -This is of little consequence, since it is assumed that most -Hop-by-Hop option headers and Destination option headers carry only -one option -(appendix B of [RFC-2460]). -.\" -.Ss inet6_option_init -.Fn inet6_option_init -is called once per ancillary data object that will -contain either Hop-by-Hop or Destination options. -It returns -.Li 0 -on success or -.Li -1 -on an error. -.Pp -.Fa bp -is a pointer to previously allocated space that will contain the -ancillary data object. -It must be large enough to contain all the -individual options to be added by later calls to -.Fn inet6_option_append -and -.Fn inet6_option_alloc . -.Pp -.Fa cmsgp -is a pointer to a pointer to a -.Li cmsghdr -structure. -.Fa *cmsgp -is initialized by this function to point to the -.Li cmsghdr -structure constructed by this function in the buffer pointed to by -.Fa bp . -.Pp -.Fa type -is either -.Dv IPV6_HOPOPTS -or -.Dv IPV6_DSTOPTS . -This -.Fa type -is stored in the -.Li cmsg_type -member of the -.Li cmsghdr -structure pointed to by -.Fa *cmsgp . -.\" -.Ss inet6_option_append -This function appends a Hop-by-Hop option or a Destination option -into an ancillary data object that has been initialized by -.Fn inet6_option_init . -This function returns -.Li 0 -if it succeeds or -.Li -1 -on an error. -.Pp -.Fa cmsg -is a pointer to the -.Li cmsghdr -structure that must have been -initialized by -.Fn inet6_option_init . -.Pp -.Fa typep -is a pointer to the 8-bit option type. -It is assumed that this -field is immediately followed by the 8-bit option data length field, -which is then followed immediately by the option data. -The caller -initializes these three fields -(the type-length-value, or TLV) -before calling this function. -.Pp -The option type must have a value from -.Li 2 -to -.Li 255 , -inclusive. -.Li ( 0 -and -.Li 1 -are reserved for the -.Li Pad1 -and -.Li PadN -options, respectively.) -.Pp -The option data length must have a value between -.Li 0 -and -.Li 255 , -inclusive, and is the length of the option data that follows. -.Pp -.Fa multx -is the value -.Li x -in the alignment term -.Dq Li xn + y . -It must have a value of -.Li 1 , -.Li 2 , -.Li 4 , -or -.Li 8 . -.Pp -.Fa plusy -is the value -.Li y -in the alignment term -.Dq Li xn + y . -It must have a value between -.Li 0 -and -.Li 7 , -inclusive. -.\" -.Ss inet6_option_alloc -This function appends a Hop-by-Hop option or a Destination option -into an ancillary data object that has been initialized by -.Fn inet6_option_init . -This function returns a pointer to the 8-bit -option type field that starts the option on success, or -.Dv NULL -on an error. -.Pp -The difference between this function and -.Fn inet6_option_append -is that the latter copies the contents of a previously built option into -the ancillary data object while the current function returns a -pointer to the space in the data object where the option's TLV must -then be built by the caller. -.Pp -.Fa cmsg -is a pointer to the -.Li cmsghdr -structure that must have been -initialized by -.Fn inet6_option_init . -.Pp -.Fa datalen -is the value of the option data length byte for this option. -This value is required as an argument to allow the function to -determine if padding must be appended at the end of the option. -(The -.Fn inet6_option_append -function does not need a data length argument -since the option data length must already be stored by the caller.) -.Pp -.Fa multx -is the value -.Li x -in the alignment term -.Dq Li xn + y . -It must have a value of -.Li 1 , -.Li 2 , -.Li 4 , -or -.Li 8 . -.Pp -.Fa plusy -is the value -.Li y -in the alignment term -.Dq Li xn + y . -It must have a value between -.Li 0 -and -.Li 7 , -inclusive. -.\" -.Ss inet6_option_next -This function processes the next Hop-by-Hop option or Destination -option in an ancillary data object. -If another option remains to be -processed, the return value of the function is -.Li 0 -and -.Fa *tptrp -points to -the 8-bit option type field -(which is followed by the 8-bit option -data length, followed by the option data). -If no more options remain -to be processed, the return value is -.Li -1 -and -.Fa *tptrp -is -.Dv NULL . -If an error occurs, the return value is -.Li -1 -and -.Fa *tptrp -is not -.Dv NULL . -.Pp -.Fa cmsg -is a pointer to -.Li cmsghdr -structure of which -.Li cmsg_level -equals -.Dv IPPROTO_IPV6 -and -.Li cmsg_type -equals either -.Dv IPV6_HOPOPTS -or -.Dv IPV6_DSTOPTS . -.Pp -.Fa tptrp -is a pointer to a pointer to an 8-bit byte and -.Fa *tptrp -is used -by the function to remember its place in the ancillary data object -each time the function is called. -The first time this function is -called for a given ancillary data object, -.Fa *tptrp -must be set to -.Dv NULL . .Pp -Each time this function returns success, -.Fa *tptrp -points to the 8-bit -option type field for the next option to be processed. -.\" -.Ss inet6_option_find -This function is similar to the previously described -.Fn inet6_option_next -function, except this function lets the caller -specify the option type to be searched for, instead of always -returning the next option in the ancillary data object. -.Fa cmsg -is a -pointer to -.Li cmsghdr -structure of which -.Li cmsg_level -equals -.Dv IPPROTO_IPV6 -and -.Li cmsg_type -equals either -.Dv IPV6_HOPOPTS -or -.Dv IPV6_DSTOPTS . -.Pp -.Fa tptrp -is a pointer to a pointer to an 8-bit byte and -.Fa *tptrp -is used -by the function to remember its place in the ancillary data object -each time the function is called. -The first time this function is -called for a given ancillary data object, -.Fa *tptrp -must be set to -.Dv NULL . -.Pa -This function starts searching for an option of the specified type -beginning after the value of -.Fa *tptrp . -If an option of the specified -type is located, this function returns -.Li 0 -and -.Fa *tptrp -points to the 8- -bit option type field for the option of the specified type. -If an -option of the specified type is not located, the return value is -.Li -1 -and -.Fa *tptrp -is -.Dv NULL . -If an error occurs, the return value is -.Li -1 -and -.Fa *tptrp -is not -.Dv NULL . +The full description of these functions is available in RFC2292. .\" .Sh DIAGNOSTICS .Fn inet6_option_init @@ -442,4 +132,3 @@ are documented in (RFC2292). .\" .Sh BUGS -The text was shamelessly copied from RFC2292. diff --git a/gen.subproj/inet6_rthdr_space.3 b/gen.subproj/inet6_rthdr_space.3 index 3ca3581..58cae2c 100644 --- a/gen.subproj/inet6_rthdr_space.3 +++ b/gen.subproj/inet6_rthdr_space.3 @@ -29,7 +29,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: inet6_rthdr_space.3,v 1.2 2002/03/19 17:20:07 majka Exp $ +.\" $Id: inet6_rthdr_space.3,v 1.3 2005/01/19 00:30:03 majka Exp $ .\" $FreeBSD: src/lib/libc/net/inet6_rthdr_space.3,v 1.1.2.5 2001/08/17 15:42:38 ru Exp $ .\" .Dd December 10, 1999 @@ -99,172 +99,8 @@ fetch one flag from a Routing header The function prototypes for these functions are all in the .Aq Li netinet/in.h header. -.\" -.Ss inet6_rthdr_space -This function returns the number of bytes required to hold a Routing -header of the specified -.Fa type -containing the specified number of -.Fa segments -(addresses). -For an IPv6 Type 0 Routing header, the number -of segments must be between 1 and 23, inclusive. The return value -includes the size of the cmsghdr structure that precedes the Routing -header, and any required padding. -.Pp -If the return value is 0, then either the type of the Routing header -is not supported by this implementation or the number of segments is -invalid for this type of Routing header. -.Pp -Note: This function returns the size but does not allocate the space -required for the ancillary data. -This allows an application to -allocate a larger buffer, if other ancillary data objects are -desired, since all the ancillary data objects must be specified to -.Xr sendmsg 2 -as a single -.Li msg_control -buffer. -.\" -.Ss inet6_rthdr_init -This function initializes the buffer pointed to by -.Fa bp -to contain a -.Li cmsghdr -structure followed by a Routing header of the specified -.Fa type . -The -.Li cmsg_len -member of the -.Li cmsghdr -structure is initialized to the -size of the structure plus the amount of space required by the -Routing header. -The -.Li cmsg_level -and -.Li cmsg_type -members are also initialized as required. -.Pp -The caller must allocate the buffer and its size can be determined by -calling -.Fn inet6_rthdr_space . -.Pp -Upon success the return value is the pointer to the -.Li cmsghdr -structure, and this is then used as the first argument to the next -two functions. -Upon an error the return value is -.Dv NULL . -.\" -.Ss inet6_rthdr_add -This function adds the address pointed to by -.Fa addr -to the end of the -Routing header being constructed and sets the type of this hop to the -value of -.Fa flags . -For an IPv6 Type 0 Routing header, -.Fa flags -must be -either -.Dv IPV6_RTHDR_LOOSE -or -.Dv IPV6_RTHDR_STRICT . -.Pp -If successful, the -.Li cmsg_len -member of the -.Li cmsghdr -structure is -updated to account for the new address in the Routing header and the -return value of the function is 0. -Upon an error the return value of -the function is -1. -.\" -.Ss inet6_rthdr_lasthop -This function specifies the Strict/Loose flag for the final hop of a -Routing header. -For an IPv6 Type 0 Routing header, -.Fa flags -must be either -.Dv IPV6_RTHDR_LOOSE -or -.Dv IPV6_RTHDR_STRICT . -.Pp -The return value of the function is 0 upon success, or -1 upon an error. -.Pp -Notice that a Routing header specifying -.Li N -intermediate nodes requires -.Li N+1 -Strict/Loose flags. -This requires -.Li N -calls to -.Fn inet6_rthdr_add -followed by one call to -.Fn inet6_rthdr_lasthop . -.\" -.Ss inet6_rthdr_reverse -This function is not yet implemented. -When implemented, this should behave as follows. -.Pp -This function takes a Routing header that was received as ancillary -data -(pointed to by the first argument, -.Fa in ) -and writes a new Routing -header that sends datagrams along the reverse of that route. -Both -arguments are allowed to point to the same buffer -(that is, the reversal can occur in place). -.Pp -The return value of the function is 0 on success, or -1 upon an -error. -.\" -.Ss inet6_rthdr_segments -This function returns the number of segments -(addresses) -contained in -the Routing header described by -.Fa cmsg . -On success the return value is -between 1 and 23, inclusive. -The return value of the function is -1 upon an error. -.\" -.Ss inet6_rthdr_getaddr -This function returns a pointer to the IPv6 address specified by -.Fa index -(which must have a value between 1 and the value returned by -.Fn inet6_rthdr_segments ) -in the Routing header described by -.Fa cmsg . -An -application should first call -.Fn inet6_rthdr_segments -to obtain the number of segments in the Routing header. -.Pp -Upon an error the return value of the function is -.Dv NULL . -.\" -.Ss inet6_rthdr_getflags -This function returns the flags value specified by -.Fa index -(which must -have a value between 0 and the value returned by -.Fn inet6_rthdr_segments ) -in the Routing header described by -.Fa cmsg . -For an IPv6 Type 0 Routing header the return value will be either -.Dv IPV6_RTHDR_LOOSE -or -.Dv IPV6_RTHDR_STRICT . -.Pp -Upon an error the return value of the function is -1. .Pp -Note: Addresses are indexed starting at 1, and flags starting at 0, -to maintain consistency with the terminology and figures in RFC2460. +The full description of these functions is available in RFC2292. .\" .Sh DIAGNOSTICS .Fn inet6_rthdr_space diff --git a/gen.subproj/initgroups.c b/gen.subproj/initgroups.c index cf7fabf..0ca077a 100644 --- a/gen.subproj/initgroups.c +++ b/gen.subproj/initgroups.c @@ -59,10 +59,12 @@ static char sccsid[] = "@(#)initgroups.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include +#include #include #include #include +#include int initgroups(uname, agroup) @@ -70,14 +72,19 @@ initgroups(uname, agroup) int agroup; { int groups[NGROUPS], ngroups; + struct passwd *pw; + /* get the UID for this user */ + if ((pw = getpwnam(uname)) == NULL) + return(-1); + + /* fetch the initial (advisory) group list */ ngroups = NGROUPS; - if (getgrouplist(uname, agroup, groups, &ngroups) < 0) - warnx("%s is in too many groups, using first %d", - uname, ngroups); - if (setgroups(ngroups, groups) < 0) { - warn("setgroups"); + getgrouplist(uname, agroup, groups, &ngroups); + if (ngroups == 0) + return(-1); + + if (syscall(SYS_initgroups, ngroups, groups, pw->pw_uid) < 0) return (-1); - } return (0); } diff --git a/lookup.subproj/Makefile.preamble b/lookup.subproj/Makefile.preamble index 365735b..0f382d0 100644 --- a/lookup.subproj/Makefile.preamble +++ b/lookup.subproj/Makefile.preamble @@ -10,3 +10,7 @@ PRIVATE_HEADER_DIR = /usr/local/include ASYNC_HEADER_DIR_SUFFIX = / NETINFO_HEADER_DIR_SUFFIX = /netinfo AFTER_POSTINSTALL += install-man-page + +# for building 64-bit +# Libinfo need to build with gcc-3.5 and 3-way fat +NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER) diff --git a/lookup.subproj/getaddrinfo.3 b/lookup.subproj/getaddrinfo.3 index 19b1b79..5ab76fb 100644 --- a/lookup.subproj/getaddrinfo.3 +++ b/lookup.subproj/getaddrinfo.3 @@ -1,215 +1,154 @@ -.\" $FreeBSD: src/lib/libc/net/getaddrinfo.3,v 1.2.2.8 2001/08/17 15:42:38 ru Exp $ -.\" $KAME: getaddrinfo.3,v 1.22 2000/08/09 21:16:17 itojun Exp $ +.\" $NetBSD: getaddrinfo.3,v 1.39 2005/01/11 06:01:41 itojun Exp $ +.\" $KAME: getaddrinfo.3,v 1.36 2005/01/05 03:23:05 itojun Exp $ +.\" $OpenBSD: getaddrinfo.3,v 1.35 2004/12/21 03:40:31 jaredy Exp $ .\" -.\" Copyright (c) 1983, 1987, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. +.\" Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2000, 2001 Internet Software Consortium. .\" -.\" 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. +.\" 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. .\" -.\" 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. +.\" 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. .\" -.\" From: @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95 -.\" -.Dd May 25, 1995 +.Dd December 20, 2004 .Dt GETADDRINFO 3 .Os -.\" .Sh NAME .Nm getaddrinfo , -.Nm freeaddrinfo , -.Nm gai_strerror -.Nd nodename-to-address translation in protocol-independent manner -.\" -.Sh LIBRARY -.Lb libc +.Nm freeaddrinfo +.Nd socket address structure to host and service name .Sh SYNOPSIS .Fd #include .Fd #include .Fd #include .Ft int -.Fn getaddrinfo "const char *nodename" "const char *servname" \ -"const struct addrinfo *hints" "struct addrinfo **res" +.Fn getaddrinfo "const char *hostname" "const char *servname" \ + "const struct addrinfo *hints" "struct addrinfo **res" .Ft void .Fn freeaddrinfo "struct addrinfo *ai" -.Ft "const char *" -.Fn gai_strerror "int ecode" -.\" .Sh DESCRIPTION The .Fn getaddrinfo -function is defined for protocol-independent nodename-to-address translation. -It performs the functionality of +function is used to get a list of +.Tn IP +addresses and port numbers for host +.Fa hostname +and service +.Fa servname . +It is a replacement for and provides more flexibility than the .Xr gethostbyname 3 and -.Xr getservbyname 3 , -but in a more sophisticated manner. -.Pp -The -.Li addrinfo -structure is defined as a result of including the -.Aq Pa netdb.h -header: -.Bd -literal -offset -struct addrinfo { - int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */ - int ai_family; /* PF_xxx */ - int ai_socktype; /* SOCK_xxx */ - int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ - size_t ai_addrlen; /* length of ai_addr */ - char *ai_canonname; /* canonical name for nodename */ - struct sockaddr *ai_addr; /* binary address */ - struct addrinfo *ai_next; /* next structure in linked list */ -}; -.Ed +.Xr getservbyname 3 +functions. .Pp The -.Fa nodename -and -.Fa servname -arguments are pointers to null-terminated strings or -.Dv NULL . -One or both of these two arguments must be a -.Pf non Dv -NULL -pointer. -In the normal client scenario, both the -.Fa nodename +.Fa hostname and .Fa servname -are specified. -In the normal server scenario, only the +arguments are either pointers to NUL-terminated strings or the null pointer. +An acceptable value for +.Fa hostname +is either a valid host name or a numeric host address string consisting +of a dotted decimal IPv4 address or an IPv6 address. +The .Fa servname -is specified. -A -.Pf non Dv -NULL -.Fa nodename -string can be either a node name or a numeric host address string -(i.e., a dotted-decimal IPv4 address or an IPv6 hex address). -A -.Pf non Dv -NULL +is either a decimal port number or a service name listed in +.Xr services 5 . +At least one of +.Fa hostname +and .Fa servname -string can be either a service name or a decimal port number. +must be non-null. .Pp -The caller can optionally pass an -.Li addrinfo -structure, pointed to by the third argument, -to provide hints concerning the type of socket that the caller supports. -In this .Fa hints -structure all members other than -.Fa ai_flags , -.Fa ai_family , -.Fa ai_socktype , -and -.Fa ai_protocol -must be zero or a -.Dv NULL -pointer. -A value of -.Dv PF_UNSPEC -for +is an optional pointer to a +.Li struct addrinfo , +as defined by +.Aq Pa netdb.h : +.Bd -literal +struct addrinfo { + int ai_flags; /* input flags */ + int ai_family; /* protocol family for socket */ + int ai_socktype; /* socket type */ + int ai_protocol; /* protocol for socket */ + socklen_t ai_addrlen; /* length of socket-address */ + struct sockaddr *ai_addr; /* socket-address for socket */ + char *ai_canonname; /* canonical name for service location */ + struct addrinfo *ai_next; /* pointer to next in list */ +}; +.Ed +.Pp +This structure can be used to provide hints concerning the type of socket +that the caller supports or wishes to use. +The caller can supply the following structure elements in +.Fa hints : +.Bl -tag -width "ai_socktypeXX" +.It Fa ai_family +The protocol family that should be used. +When .Fa ai_family -means the caller will accept any protocol family. -A value of 0 for +is set to +.Dv PF_UNSPEC , +it means the caller will accept any protocol family supported by the +operating system. +.It Fa ai_socktype +Denotes the type of socket that is wanted: +.Dv SOCK_STREAM , +.Dv SOCK_DGRAM , +or +.Dv SOCK_RAW . +When .Fa ai_socktype -means the caller will accept any socket type. -A value of 0 for +is zero the caller will accept any socket type. +.It Fa ai_protocol +Indicates which transport protocol is desired, +.Dv IPPROTO_UDP +or +.Dv IPPROTO_TCP . +If .Fa ai_protocol -means the caller will accept any protocol. -For example, if the caller handles only TCP and not UDP, then the -.Fa ai_socktype -member of the hints structure should be set to -.Dv SOCK_STREAM -when -.Fn getaddrinfo -is called. -If the caller handles only IPv4 and not IPv6, then the -.Fa ai_family -member of the -.Fa hints -structure should be set to -.Dv PF_INET -when -.Fn getaddrinfo -is called. -If the third argument to +is zero the caller will accept any protocol. +.It Fa ai_flags +.Fa ai_flags +is formed by +.Tn OR Ns 'ing +the following values: +.Bl -tag -width "AI_CANONNAMEXX" +.It Dv AI_CANONNAME +If the +.Dv AI_CANONNAME +bit is set, a successful call to .Fn getaddrinfo -is a -.Dv NULL -pointer, this is the same as if the caller had filled in an -.Li addrinfo -structure initialized to zero with -.Fa ai_family -set to -.Dv PF_UNSPEC . -.Pp -Upon successful return a pointer to a linked list of one or more -.Li addrinfo -structures is returned through the final argument. -The caller can process each -.Li addrinfo -structure in this list by following the -.Fa ai_next -pointer, until a -.Dv NULL -pointer is encountered. -In each returned -.Li addrinfo -structure the three members -.Fa ai_family , -.Fa ai_socktype , -and -.Fa ai_protocol -are the corresponding arguments for a call to the -.Fn socket -function. -In each +will return a NUL-terminated string containing the canonical name +of the specified hostname in the +.Fa ai_canonname +element of the first .Li addrinfo -structure the -.Fa ai_addr -member points to a filled-in socket address structure whose length is -specified by the -.Fa ai_addrlen -member. -.Pp +structure returned. +.It Dv AI_NUMERICHOST +If the +.Dv AI_NUMERICHOST +bit is set, it indicates that +.Fa hostname +should be treated as a numeric string defining an IPv4 or IPv6 address +and no name resolution should be attempted. +.It Dv AI_PASSIVE If the .Dv AI_PASSIVE -bit is set in the -.Fa ai_flags -member of the -.Fa hints -structure, then the caller plans to use the returned socket address -structure in a call to -.Fn bind . +bit is set it indicates that the returned socket address structure +is intended for use in a call to +.Xr bind 2 . In this case, if the -.Fa nodename -argument is a -.Dv NULL -pointer, then the IP address portion of the socket -address structure will be set to +.Fa hostname +argument is the null pointer, then the IP address portion of the +socket address structure will be set to .Dv INADDR_ANY for an IPv4 address or .Dv IN6ADDR_ANY_INIT @@ -217,169 +156,92 @@ for an IPv6 address. .Pp If the .Dv AI_PASSIVE -bit is not set in the -.Fa ai_flags -member of the -.Fa hints -structure, then the returned socket address structure will be ready for a -call to -.Fn connect -(for a connection-oriented protocol) -or either -.Fn connect , -.Fn sendto , +bit is not set, the returned socket address structure will be ready +for use in a call to +.Xr connect 2 +for a connection-oriented protocol or +.Xr connect 2 , +.Xr sendto 2 , or -.Fn sendmsg -(for a connectionless protocol). -In this case, if the -.Fa nodename -argument is a -.Dv NULL -pointer, then the IP address portion of the -socket address structure will be set to the loopback address. +.Xr sendmsg 2 +if a connectionless protocol was chosen. +The +.Tn IP +address portion of the socket address structure will be set to the +loopback address if +.Fa hostname +is the null pointer and +.Dv AI_PASSIVE +is not set. +.El +.El .Pp -If the -.Dv AI_CANONNAME -bit is set in the -.Fa ai_flags -member of the -.Fa hints -structure, then upon successful return the -.Fa ai_canonname -member of the first +All other elements of the .Li addrinfo -structure in the linked list will point to a null-terminated string -containing the canonical name of the specified -.Fa nodename . -.Pp -If the -.Dv AI_NUMERICHOST -bit is set in the -.Fa ai_flags -member of the +structure passed via .Fa hints -structure, then a -.Pf non Dv -NULL -.Fa nodename -string must be a numeric host address string. -Otherwise an error of -.Dv EAI_NONAME -is returned. -This flag prevents any type of name resolution service (e.g., the DNS) -from being called. +must be zero or the null pointer. .Pp -The arguments to -.Fn getaddrinfo -must be sufficiently consistent and unambiguous. -Here are some problem cases you may encounter: -.Bl -bullet -.It -.Fn getaddrinfo -will fail if the members in the +If .Fa hints -structure are not consistent. -For example, for internet address families, -.Fn getaddrinfo -will fail if you specify -.Dv SOCK_STREAM -to -.Fa ai_socktype -while you specify -.Dv IPPROTO_UDP -to -.Fa ai_protocol . -.It -If you specify a -.Fa servname -which is defined only for certain -.Fa ai_socktype , -.Fn getaddrinfo -will fail because the arguments are not consistent. -For example, -.Fn getaddrinfo -will return an error if you ask for -.Dq Li tftp -service on -.Dv SOCK_STREAM . -.It -For internet address families, if you specify -.Fa servname -while you set -.Fa ai_socktype -to -.Dv SOCK_RAW , +is the null pointer, .Fn getaddrinfo -will fail, because service names are not defined for the internet -.Dv SOCK_RAW -space. -.It -If you specify numeric -.Fa servname , -while leaving -.Fa ai_socktype -and -.Fa ai_protocol -unspecified, -.Fn getaddrinfo -will fail. -This is because the numeric -.Fa servname -does not identify any socket type, and -.Fn getaddrinfo -is not allowed to glob the argument in such case. -.El +behaves as if the caller provided a +.Li struct addrinfo +with +.Fa ai_family +set to +.Dv PF_UNSPEC +and all other elements set to zero or +.Dv NULL . .Pp -All of the information returned by -.Fn getaddrinfo -is dynamically allocated: -the +After a successful call to +.Fn getaddrinfo , +.Fa *res +is a pointer to a linked list of one or more .Li addrinfo -structures, the socket address structures, and canonical node name -strings pointed to by the addrinfo structures. -To return this information to the system the function -.Fn freeaddrinfo -is called. -The -.Fa addrinfo -structure pointed to by the -.Fa ai argument -is freed, along with any dynamic storage pointed to by the structure. -This operation is repeated until a -.Dv NULL +structures. +The list can be traversed by following the .Fa ai_next -pointer is encountered. +pointer in each +.Li addrinfo +structure until a null pointer is encountered. +The three members +.Fa ai_family, +.Fa ai_socktype, +and +.Fa ai_protocol +in each returned +.Li addrinfo +structure are suitable for a call to +.Xr socket 2 . +For each +.Li addrinfo +structure in the list, the +.Fa ai_addr +member points to a filled-in socket address structure of length +.Fa ai_addrlen . .Pp -To aid applications in printing error messages based on the -.Dv EAI_xxx -codes returned by -.Fn getaddrinfo , -.Fn gai_strerror -is defined. -The argument is one of the -.Dv EAI_xxx -values defined earlier and the return value points to a string describing -the error. -If the argument is not one of the -.Dv EAI_xxx -values, the function still returns a pointer to a string whose contents -indicate an unknown error. -.\" -.Sh EXTENSIONS -This implementation supports numeric IPv6 address notation with the -experimental scope identifier. -By appending a percent sign and scope identifier to the address, you -can specify the value of the +This implementation of +.Fn getaddrinfo +allows numeric IPv6 address notation with scope identifier, +as documented in chapter 11 of draft-ietf-ipv6-scoping-arch-02.txt. +By appending the percent character and scope identifier to addresses, +one can fill the .Li sin6_scope_id -field of the socket address. -This makes management of scoped address easier, +field for addresses. +This would make management of scoped addresses easier and allows cut-and-paste input of scoped addresses. .Pp -At the moment the code supports only link-local addresses in this format. -The scope identifier is hardcoded to name of hardware interface associated -with the link, -(such as -.Li ne0 ) . -For example, +At this moment the code supports only link-local addresses with the format. +The scope identifier is hardcoded to the name of the hardware interface +associated +with the link +.Po +such as +.Li ne0 +.Pc . +An example is .Dq Li fe80::1%ne0 , which means .Do @@ -389,25 +251,49 @@ on the link associated with the interface .Dc . .Pp -This implementation is still very experimental and non-standard. The current implementation assumes a one-to-one relationship between -interfaces and links, which is not necessarily true according to the -specification. -.\" +the interface and link, which is not necessarily true from the specification. +.Pp +All of the information returned by +.Fn getaddrinfo +is dynamically allocated: the +.Li addrinfo +structures themselves as well as the socket address structures and +the canonical host name strings included in the +.Li addrinfo +structures. +.Pp +Memory allocated for the dynamically allocated structures created by +a successful call to +.Fn getaddrinfo +is released by the +.Fn freeaddrinfo +function. +The +.Fa ai +pointer should be a +.Li addrinfo +structure created by a call to +.Fn getaddrinfo . +.Sh RETURN VALUES +.Fn getaddrinfo +returns zero on success or one of the error codes listed in +.Xr gai_strerror 3 +if an error occurs. .Sh EXAMPLES The following code tries to connect to .Dq Li www.kame.net service -.Dq Li http . -via stream socket. -It loops through all the addresses available, regardless of the address family. +.Dq Li http +via a stream socket. +It loops through all the addresses available, regardless of address family. If the destination resolves to an IPv4 address, it will use an .Dv AF_INET socket. Similarly, if it resolves to IPv6, an .Dv AF_INET6 socket is used. -Observe that there is no hardcoded reference to particular address family. +Observe that there is no hardcoded reference to a particular address family. The code works even if .Fn getaddrinfo returns addresses that are not IPv4/v6. @@ -426,8 +312,6 @@ if (error) { /*NOTREACHED*/ } s = -1; -cause = "no addresses"; -errno = EADDRNOTAVAIL; for (res = res0; res; res = res->ai_next) { s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); @@ -446,7 +330,7 @@ for (res = res0; res; res = res->ai_next) { break; /* okay we got one */ } if (s < 0) { - err(1, cause); + err(1, "%s", cause); /*NOTREACHED*/ } freeaddrinfo(res0); @@ -485,106 +369,50 @@ for (res = res0; res && nsock < MAXSOCK; res = res->ai_next) { close(s[nsock]); continue; } - - if (listen(s[nsock], SOMAXCONN) < 0) { - cause = "listen"; - close(s[nsock]); - continue; - } + (void) listen(s[nsock], 5); nsock++; } if (nsock == 0) { - err(1, cause); + err(1, "%s", cause); /*NOTREACHED*/ } freeaddrinfo(res0); .Ed -.\" -.Sh FILES -.Bl -tag -width /etc/resolv.conf -compact -.It Pa /etc/hosts -.It Pa /etc/host.conf -.It Pa /etc/resolv.conf -.El -.\" -.Sh DIAGNOSTICS -Error return status from -.Fn getaddrinfo -is zero on success and non-zero on errors. -Non-zero error codes are defined in -.Aq Pa netdb.h , -and as follows: -.Pp -.Bl -tag -width EAI_ADDRFAMILY -compact -.It Dv EAI_ADDRFAMILY -Address family for -.Fa nodename -not supported. -.It Dv EAI_AGAIN -Temporary failure in name resolution. -.It Dv EAI_BADFLAGS -Invalid value for -.Fa ai_flags . -.It Dv EAI_FAIL -Non-recoverable failure in name resolution. -.It Dv EAI_FAMILY -.Fa ai_family -not supported. -.It Dv EAI_MEMORY -Memory allocation failure. -.It Dv EAI_NODATA -No address associated with -.Fa nodename . -.It Dv EAI_NONAME -.Fa nodename -nor -.Fa servname -provided, or not known. -.It Dv EAI_SERVICE -.Fa servname -not supported for -.Fa ai_socktype . -.It Dv EAI_SOCKTYPE -.Fa ai_socktype -not supported. -.It Dv EAI_SYSTEM -System error returned in -.Va errno . -.El -.Pp -If called with an appropriate argument, -.Fn gai_strerror -returns a pointer to a string describing the given error code. -If the argument is not one of the -.Dv EAI_xxx -values, the function still returns a pointer to a string whose contents -indicate an unknown error. -.\" .Sh SEE ALSO +.Xr bind 2 , +.Xr connect 2 , +.Xr send 2 , +.Xr socket 2 , +.Xr gai_strerror 3 , .Xr gethostbyname 3 , .Xr getnameinfo 3 , .Xr getservbyname 3 , +.Xr resolver 3 , .Xr hosts 5 , +.Xr resolv.conf 5 , .Xr services 5 , .Xr hostname 7 , .Xr named 8 -.Pp .Rs .%A R. Gilligan .%A S. Thomson .%A J. Bound +.%A J. McCann .%A W. Stevens .%T Basic Socket Interface Extensions for IPv6 -.%R RFC2553 -.%D March 1999 +.%R RFC 3493 +.%D February 2003 .Re .Rs -.%A Tatsuya Jinmei -.%A Atsushi Onoe -.%T "An Extension of Format for IPv6 Scoped Addresses" +.%A S. Deering +.%A B. Haberman +.%A T. Jinmei +.%A E. Nordmark +.%A B. Zill +.%T "IPv6 Scoped Address Architecture" .%R internet draft -.%N draft-ietf-ipngwg-scopedaddr-format-02.txt +.%N draft-ietf-ipv6-scoping-arch-02.txt .%O work in progress material .Re .Rs @@ -593,20 +421,15 @@ indicate an unknown error. .%B "Proceedings of the freenix track: 2000 USENIX annual technical conference" .%D June 2000 .Re -.\" -.Sh HISTORY -The implementation first appeared in WIDE Hydrangea IPv6 protocol stack kit. -.\" .Sh STANDARDS The .Fn getaddrinfo -function is defined in -.St -p1003.1g-2000 , -and documented in -.Dq Basic Socket Interface Extensions for IPv6 -(RFC2553). -.\" +function is defined by the +.St -p1003.1g-2000 +draft specification and documented in +.Dv "RFC 3493" , +.Dq Basic Socket Interface Extensions for IPv6 . .Sh BUGS -The current implementation is not thread-safe. -.Pp -The text was shamelessly copied from RFC2553. +The implementation of +.Fn getaddrinfo +is not thread-safe. diff --git a/lookup.subproj/getaddrinfo.c b/lookup.subproj/getaddrinfo.c index 852ff1f..d23a37c 100644 --- a/lookup.subproj/getaddrinfo.c +++ b/lookup.subproj/getaddrinfo.c @@ -465,7 +465,7 @@ gai_lookupd_process_dictionary(XDR *inxdr) static int gai_make_query(const char *nodename, const char *servname, const struct addrinfo *hints, char *buf, uint32_t *len) { - int32_t numerichost, family, proto, socktype, canonname, passive; + int32_t numerichost, family, proto, socktype, canonname, passive, parallel; uint32_t na; XDR outxdr; char str[64], *cname; @@ -476,6 +476,7 @@ gai_make_query(const char *nodename, const char *servname, const struct addrinfo socktype = SOCK_UNSPEC; canonname = 0; passive = 0; + parallel = 0; cname = NULL; if (hints != NULL) @@ -483,7 +484,8 @@ gai_make_query(const char *nodename, const char *servname, const struct addrinfo 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) == 1) passive = 1; + if (hints->ai_flags & AI_PASSIVE) passive = 1; + if (hints->ai_flags & AI_PARALLEL) parallel = 1; proto = hints->ai_protocol; if (hints->ai_socktype == SOCK_DGRAM) @@ -509,9 +511,10 @@ gai_make_query(const char *nodename, const char *servname, const struct addrinfo 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, &na)) + if (!xdr_int(&outxdr, (int32_t *)&na)) { xdr_destroy(&outxdr); return EAI_SYSTEM; @@ -583,6 +586,15 @@ gai_make_query(const char *nodename, const char *servname, const struct addrinfo } } + if (parallel != 0) + { + if (encode_kv(&outxdr, "parallel", "1") != 0) + { + xdr_destroy(&outxdr); + return EAI_SYSTEM; + } + } + if (numerichost != 0) { if (encode_kv(&outxdr, "numerichost", "1") != 0) @@ -812,7 +824,7 @@ gai_lookupd(const char *nodename, const char *servname, const struct addrinfo *h xdrmem_create(&inxdr, rbuf, rlen, XDR_DECODE); - if (!xdr_int(&inxdr, &n)) + if (!xdr_int(&inxdr, (int32_t *)&n)) { xdr_destroy(&inxdr); return EAI_SYSTEM; @@ -862,7 +874,7 @@ gai_checkhints(const struct addrinfo *hints) } int -getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res) +getaddrinfo(const char * __restrict nodename, const char * __restrict servname, const struct addrinfo * __restrict hints, struct addrinfo ** __restrict res) { int32_t status, nodenull, servnull; @@ -944,7 +956,7 @@ gai_extract_data(char *buf, uint32_t len, struct addrinfo **res) xdrmem_create(&xdr, buf, len, XDR_DECODE); - if (!xdr_int(&xdr, &n)) + if (!xdr_int(&xdr, (int32_t *)&n)) { xdr_destroy(&xdr); return EAI_SYSTEM; @@ -1016,8 +1028,8 @@ getaddrinfo_async_handle_reply(void *msg) if (status != KERN_SUCCESS) { if (status == MIG_REPLY_MISMATCH) return 0; - if (callback != NULL) callback(EAI_SYSTEM, NULL, context); - return EAI_SYSTEM; + if (callback != NULL) callback(EAI_NODATA, NULL, context); + return EAI_NODATA; } status = gai_extract_data(buf, len, &res); @@ -1065,50 +1077,45 @@ getaddrinfo_async_handle_reply(void *msg) static int gni_lookupd_process_dictionary(XDR *inxdr, char **host, char **serv) { - int32_t i, nkeys, nvals; - char *key, *val; + int32_t i, j, nkeys, nvals, status; + char *key, **vals; if ((host == NULL) || (serv == NULL)) return EAI_SYSTEM; + if (!xdr_int(inxdr, &nkeys)) return EAI_SYSTEM; + *host = NULL; + *serv = NULL; + for (i = 0; i < nkeys; i++) { key = NULL; - val = NULL; - - if (!xdr_string(inxdr, &key, LONG_STRING_LENGTH)) return EAI_SYSTEM; - if (!xdr_int(inxdr, &nvals)) - { - free(key); - return EAI_SYSTEM; - } + vals = NULL; + nvals = 0; + + status = _lu_xdr_attribute(inxdr, &key, &vals, (uint32_t *)&nvals); + if (status < 0) return EAI_SYSTEM; - if (nvals != 1) - { - free(key); - return EAI_SYSTEM; - } - - if (!xdr_string(inxdr, &val, LONG_STRING_LENGTH)) + if (nvals == 0) { free(key); - return EAI_SYSTEM; + continue; } - if (!strcmp(key, "name")) + if ((*host == NULL) && (!strcmp("name", key))) { - *host = val; - val = NULL; + *host = vals[0]; + for (j = 1; j < nvals; j++) free(vals[j]); } - else if (!strcmp(key, "service")) + else if ((*serv == NULL) && (!strcmp(key, "service"))) { - *serv = val; - val = NULL; + *serv = vals[0]; + for (j = 1; j < nvals; j++) free(vals[j]); } if (key != NULL) free(key); - if (val != NULL) free(val); + free(vals); } return 0; @@ -1120,7 +1127,7 @@ gni_make_query(const struct sockaddr *sa, size_t salen, int wanthost, int wantse 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; + uint32_t a4, ifnum, offset, na, proto, fqdn, numerichost, numericserv, name_req, isll, issl; struct sockaddr_in6 *s6; if (sa == NULL) return EAI_FAIL; @@ -1131,6 +1138,8 @@ gni_make_query(const struct sockaddr *sa, size_t salen, int wanthost, int wantse numerichost = 0; numericserv = 0; name_req = 0; + isll = 0; + issl = 0; offset = INET_NTOP_AF_INET_OFFSET; key = "ip_address"; @@ -1165,7 +1174,11 @@ gni_make_query(const struct sockaddr *sa, size_t salen, int wanthost, int wantse default: if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr)) { - flags |= NI_NUMERICHOST; + isll = 1; + } + else if (IN6_IS_ADDR_SITELOCAL(&s6->sin6_addr)) + { + issl = 1; } else if (IN6_IS_ADDR_MULTICAST(&s6->sin6_addr)) { @@ -1174,6 +1187,17 @@ gni_make_query(const struct sockaddr *sa, size_t salen, int wanthost, int wantse break; } + if ((isll != 0) || (issl != 0)) + { + ifnum = 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; + + s6->sin6_addr.__u6_addr.__u6_addr16[1] = 0; + s6->sin6_scope_id = ifnum; + if ((ifnum != 0) && (flags & NI_NUMERICHOST)) flags |= NI_WITHSCOPEID; + } + offset = INET_NTOP_AF_INET6_OFFSET; key = "ipv6_address"; port = s6->sin6_port; @@ -1220,7 +1244,7 @@ gni_make_query(const struct sockaddr *sa, size_t salen, int wanthost, int wantse xdrmem_create(&outxdr, buf, *len, XDR_ENCODE); - if (!xdr_int(&outxdr, &na)) + if (!xdr_int(&outxdr, (int32_t *)&na)) { xdr_destroy(&outxdr); return EAI_SYSTEM; @@ -1310,12 +1334,13 @@ gni_make_query(const struct sockaddr *sa, size_t salen, int wanthost, int wantse } int -getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) +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; - int wanth, wants; + uint32_t ifnum; + int wanth, wants, isll, issl; XDR inxdr; - char qbuf[LU_QBUF_SIZE]; + char qbuf[LU_QBUF_SIZE], ifname[IF_NAMESIZE]; char *rbuf, *hval, *sval; mach_port_t server_port; kern_return_t status; @@ -1325,10 +1350,34 @@ getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostl /* Check input */ if (sa == NULL) return EAI_FAIL; - /* V4 mapped and compat addresses are converted to plain V4 */ + isll = 0; + issl = 0; + ifnum = 0; + if (sa->sa_family == AF_INET6) { s6 = (struct sockaddr_in6 *)sa; + + 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 + * 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)) + { + ifnum = 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; + + s6->sin6_addr.__u6_addr.__u6_addr16[1] = 0; + s6->sin6_scope_id = ifnum; + } + + /* 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)); @@ -1342,7 +1391,7 @@ getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostl return i; } } - + wanth = 0; if ((host != NULL) && (hostlen != 0)) wanth = 1; @@ -1360,6 +1409,16 @@ getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostl 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 (((isll != 0) || (issl != 0)) && (ifnum != 0)) + { + /* append interface name */ + if (if_indextoname(ifnum, ifname) != NULL) + { + strcat(host, "%"); + strcat(host, ifname); + } + } + if (wants == 0) return 0; } @@ -1399,7 +1458,7 @@ getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostl qlen = LU_QBUF_SIZE; i = gni_make_query(sa, salen, wanth, wants, flags, qbuf, &qlen); - if (i != 0) return EAI_SYSTEM; + if (i != 0) return i; qlen /= BYTES_PER_XDR_UNIT; @@ -1412,7 +1471,7 @@ getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostl xdrmem_create(&inxdr, rbuf, rlen, XDR_DECODE); - if (!xdr_int(&inxdr, &n)) + if (!xdr_int(&inxdr, (int32_t *)&n)) { xdr_destroy(&inxdr); return EAI_SYSTEM; @@ -1478,7 +1537,7 @@ getnameinfo_async_start(mach_port_t *p, const struct sockaddr *sa, size_t salen, qlen = LU_QBUF_SIZE; i = gni_make_query(sa, salen, 1, 1, flags, qbuf, &qlen); - if (i != 0) return EAI_SYSTEM; + if (i != 0) return i; qlen /= BYTES_PER_XDR_UNIT; @@ -1496,6 +1555,7 @@ gni_extract_data(char *buf, uint32_t len, char **host, char **serv) { XDR xdr; uint32_t n; + int i; *host = NULL; *serv = NULL; @@ -1505,7 +1565,7 @@ gni_extract_data(char *buf, uint32_t len, char **host, char **serv) xdrmem_create(&xdr, buf, len, XDR_DECODE); - if (!xdr_int(&xdr, &n)) + if (!xdr_int(&xdr, (int32_t *)&n)) { xdr_destroy(&xdr); return EAI_SYSTEM; @@ -1517,7 +1577,9 @@ gni_extract_data(char *buf, uint32_t len, char **host, char **serv) return EAI_NONAME; } - return gni_lookupd_process_dictionary(&xdr, host, serv); + i = gni_lookupd_process_dictionary(&xdr, host, serv); + xdr_destroy(&xdr); + return i; } int32_t @@ -1558,8 +1620,8 @@ getnameinfo_async_handle_reply(void *msg) if (status != KERN_SUCCESS) { if (status == MIG_REPLY_MISMATCH) return 0; - if (callback != NULL) callback(EAI_SYSTEM, NULL, NULL, context); - return EAI_SYSTEM; + if (callback != NULL) callback(EAI_NONAME, NULL, NULL, context); + return EAI_NONAME; } hval = NULL; diff --git a/lookup.subproj/getnameinfo.3 b/lookup.subproj/getnameinfo.3 index ce36d8a..9220959 100644 --- a/lookup.subproj/getnameinfo.3 +++ b/lookup.subproj/getnameinfo.3 @@ -1,311 +1,269 @@ -.\" $FreeBSD: src/lib/libc/net/getnameinfo.3,v 1.2.2.7 2001/08/17 15:42:38 ru Exp $ -.\" $KAME: getnameinfo.3,v 1.17 2000/08/09 21:16:17 itojun Exp $ +.\" $NetBSD: getnameinfo.3,v 1.34 2005/01/12 14:44:11 wiz Exp $ +.\" $KAME: getnameinfo.3,v 1.37 2005/01/05 03:23:05 itojun Exp $ +.\" $OpenBSD: getnameinfo.3,v 1.36 2004/12/21 09:48:20 jmc Exp $ .\" -.\" Copyright (c) 1983, 1987, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. +.\" Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2000, 2001 Internet Software Consortium. .\" -.\" 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. +.\" 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. .\" -.\" 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. +.\" 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. .\" -.\" From: @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95 -.\" -.Dd May 25, 1995 +.Dd December 20, 2004 .Dt GETNAMEINFO 3 .Os -.\" .Sh NAME .Nm getnameinfo -.Nd address-to-nodename translation in protocol-independent manner -.\" -.Sh LIBRARY -.Lb libc +.Nd socket address structure to hostname and service name .Sh SYNOPSIS -.Fd #include -.Fd #include -.Fd #include +.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" -.\" +.Fn getnameinfo "const struct sockaddr *sa" "socklen_t salen" "char *host" \ + "size_t hostlen" "char *serv" "size_t servlen" "int flags" .Sh DESCRIPTION The .Fn getnameinfo -function is defined for protocol-independent address-to-nodename translation. -Its functionality is a reverse conversion of -.Xr getaddrinfo 3 , -and implements similar functionality with +function is used to convert a +.Li sockaddr +structure to a pair of host name and service strings. +It is a replacement for and provides more flexibility than the .Xr gethostbyaddr 3 and .Xr getservbyport 3 -in more sophisticated manner. -.Pp -This function looks up an IP address and port number provided by the -caller in the DNS and system-specific database, and returns text -strings for both in buffers provided by the caller. -The function indicates successful completion by a zero return value; -a non-zero return value indicates failure. +functions and is the converse of the +.Xr getaddrinfo 3 +function. .Pp -The first argument, -.Fa sa , -points to either a -.Li sockaddr_in -structure (for IPv4) or a -.Li sockaddr_in6 -structure (for IPv6) that holds the IP address and port number. The -.Fa salen -argument gives the length of the +.Li sockaddr +structure +.Fa sa +should point to either a .Li sockaddr_in or .Li sockaddr_in6 -structure. +structure (for IPv4 or IPv6 respectively) that is +.Fa salen +bytes long. .Pp -The function returns the nodename associated with the IP address in -the buffer pointed to by the +The host and service names associated with +.Fa sa +are stored in .Fa host -argument. -The caller provides the size of this buffer via the +and +.Fa serv +which have length parameters .Fa hostlen -argument. -The service name associated with the port number is returned in the buffer -pointed to by -.Fa serv , -and the -.Fa servlen -argument gives the length of this buffer. -The caller specifies not to return either string by providing a zero -value for the +and +.Fa servlen . +The maximum value for .Fa hostlen -or +is +.Dv NI_MAXHOST +and the maximum value for .Fa servlen -arguments. -Otherwise, the caller must provide buffers large enough to hold the -nodename and the service name, including the terminating null characters. -.Pp -Unfortunately most systems do not provide constants that specify the -maximum size of either a fully-qualified domain name or a service name. -Therefore to aid the application in allocating buffers for these two -returned strings the following constants are defined in -.Aq Pa netdb.h : -.Bd -literal -offset -#define NI_MAXHOST 1025 -#define NI_MAXSERV 32 -.Ed -.Pp -The first value is actually defined as the constant -.Dv MAXDNAME -in recent versions of BIND's -.Aq Pa arpa/nameser.h -header -(older versions of BIND define this constant to be 256) -and the second is a guess based on the services listed in the current -Assigned Numbers RFC. -.Pp -The final argument is a -.Fa flag -that changes the default actions of this function. -By default the fully-qualified domain name (FQDN) for the host is -looked up in the DNS and returned. -If the flag bit -.Dv NI_NOFQDN -is set, only the nodename portion of the FQDN is returned for local hosts. -.Pp -If the -.Fa flag -bit -.Dv NI_NUMERICHOST -is set, or if the host's name cannot be located in the DNS, -the numeric form of the host's address is returned instead of its name -(e.g., by calling -.Fn inet_ntop -instead of -.Fn getnodebyaddr ) . -If the -.Fa flag -bit -.Dv NI_NAMEREQD -is set, an error is returned if the host's name cannot be located in the DNS. -.Pp -If the flag bit -.Dv NI_NUMERICSERV -is set, the numeric form of the service address is returned -(e.g., its port number) -instead of its name. -The two -.Dv NI_NUMERICxxx -flags are required to support the -.Fl n -flag that many commands provide. +is +.Dv NI_MAXSERV , +as defined by +.Aq Pa netdb.h . +If a length parameter is zero, no string will be stored. +Otherwise, enough space must be provided to store the +host name or service string plus a byte for the NUL terminator. .Pp -A fifth flag bit, -.Dv NI_DGRAM , -specifies that the service is a datagram service, and causes -.Fn getservbyport +The +.Fa flags +argument is formed by +.Sy OR Ns 'ing +the following values: +.Bl -tag -width "NI_NUMERICHOSTXX" +.It Dv NI_NOFQDN +A fully qualified domain name is not required for local hosts. +The local part of the fully qualified domain name is returned instead. +.It Dv NI_NUMERICHOST +Return the address in numeric form, as if calling +.Xr inet_ntop 3 , +instead of a host name. +.It Dv NI_NAMEREQD +A name is required. +If the host name cannot be found in DNS and this flag is set, +a non-zero error code is returned. +If the host name is not found and the flag is not set, the +address is returned in numeric form. +.It NI_NUMERICSERV +The service name is returned as a digit string representing the port number. +.It NI_DGRAM +Specifies that the service being looked up is a datagram +service, and causes +.Xr getservbyport 3 to be called with a second argument of .Dq udp instead of its default of .Dq tcp . -This is required for the few ports (512-514) -that have different services for UDP and TCP. +This is required for the few ports (512\-514) that have different services +for +.Tn UDP +and +.Tn TCP . +.El .Pp -These -.Dv NI_xxx -flags are defined in -.Aq Pa netdb.h . -.\" -.Sh EXTENSION -The implementation allows experimental numeric IPv6 address notation with -scope identifier. -IPv6 link-local address will appear as string like -.Dq Li fe80::1%ne0 , -if -.Dv NI_WITHSCOPEID -bit is enabled in -.Ar flags -argument. +This implementation allows numeric IPv6 address notation with scope identifier, +as documented in chapter 11 of draft-ietf-ipv6-scoping-arch-02.txt. +IPv6 link-local address will appear as a string like +.Dq Li fe80::1%ne0 . Refer to .Xr getaddrinfo 3 -for the notation. -.\" +for more information. +.Sh RETURN VALUES +.Fn getnameinfo +returns zero on success or one of the error codes listed in +.Xr gai_strerror 3 +if an error occurs. .Sh EXAMPLES -The following code tries to get numeric hostname, and service name, -for given socket address. -Observe that there is no hardcoded reference to particular address family. +The following code tries to get a numeric host name, and service name, +for a given socket address. +Observe that there is no hardcoded reference to a particular address family. .Bd -literal -offset indent struct sockaddr *sa; /* input */ char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; -if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), sbuf, +if (getnameinfo(sa, sa-\*[Gt]sa_len, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) { errx(1, "could not get numeric hostname"); /*NOTREACHED*/ } -printf("host=%s, serv=%s\\n", hbuf, sbuf); +printf("host=%s, serv=%s\en", hbuf, sbuf); .Ed .Pp -The following version checks if the socket address has reverse address mapping. +The following version checks if the socket address has a reverse address mapping: .Bd -literal -offset indent struct sockaddr *sa; /* input */ char hbuf[NI_MAXHOST]; -if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0, +if (getnameinfo(sa, sa-\*[Gt]sa_len, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD)) { errx(1, "could not resolve hostname"); /*NOTREACHED*/ } -printf("host=%s\\n", hbuf); +printf("host=%s\en", hbuf); .Ed -.\" -.Sh FILES -.Bl -tag -width /etc/resolv.conf -compact -.It Pa /etc/hosts -.It Pa /etc/host.conf -.It Pa /etc/resolv.conf -.El -.\" -.Sh DIAGNOSTICS -The function indicates successful completion by a zero return value; -a non-zero return value indicates failure. -Error codes are as below: -.Bl -tag -width Er -.It Bq Er EAI_AGAIN -The name could not be resolved at this time. -Future attempts may succeed. -.It Bq Er EAI_BADFLAGS -The flags had an invalid value. -.It Bq Er EAI_FAIL -A non-recoverable error occurred. -.It Bq Er EAI_FAMILY -The address family was not recognized or the address length was invalid -for the specified family. -.It Bq Er EAI_MEMORY -There was a memory allocation failure. -.It Bq Er EAI_NONAME -The name does not resolve for the supplied parameters. -.Dv NI_NAMEREQD -is set and the host's name cannot be located, -or both nodename and servname were null. -.It Bq Er EAI_SYSTEM -A system error occurred. -The error code can be found in errno. -.El -.\" .Sh SEE ALSO +.Xr gai_strerror 3 , .Xr getaddrinfo 3 , .Xr gethostbyaddr 3 , .Xr getservbyport 3 , +.Xr inet_ntop 3 , +.Xr resolver 3 , .Xr hosts 5 , +.Xr resolv.conf 5 , .Xr services 5 , .Xr hostname 7 , .Xr named 8 -.Pp .Rs .%A R. Gilligan .%A S. Thomson .%A J. Bound .%A W. Stevens .%T Basic Socket Interface Extensions for IPv6 -.%R RFC2553 +.%R RFC 2553 .%D March 1999 .Re .Rs -.%A Tatsuya Jinmei -.%A Atsushi Onoe -.%T "An Extension of Format for IPv6 Scoped Addresses" +.%A S. Deering +.%A B. Haberman +.%A T. Jinmei +.%A E. Nordmark +.%A B. Zill +.%T "IPv6 Scoped Address Architecture" .%R internet draft -.%N draft-ietf-ipngwg-scopedaddr-format-02.txt +.%N draft-ietf-ipv6-scoping-arch-02.txt .%O work in progress material .Re .Rs .%A Craig Metz .%T Protocol Independence Using the Sockets API -.%B "Proceedings of the freenix track: 2000 USENIX annual technical conference" +.%B "Proceedings of the FREENIX track: 2000 USENIX annual technical conference" .%D June 2000 .Re -.\" -.Sh HISTORY -The implementation first appeared in WIDE Hydrangea IPv6 protocol stack kit. -.\" .Sh STANDARDS The -.Fn getaddrinfo -function is defined in -.St -p1003.1g-2000 , -and documented in -.Dq Basic Socket Interface Extensions for IPv6 -(RFC2553). -.\" -.Sh BUGS -The current implementation is not thread-safe. +.Fn getnameinfo +function is defined by the +.St -p1003.1g-2000 +draft specification and documented in +.Sy "RFC 2553" , +.Dq Basic Socket Interface Extensions for IPv6 . +.Sh CAVEATS +.Fn getnameinfo +can return both numeric and FQDN forms of the address specified in +.Fa sa . +There is no return value that indicates whether the string returned in +.Fa host +is a result of binary to numeric-text translation (like +.Xr inet_ntop 3 ) , +or is the result of a DNS reverse lookup. +Because of this, malicious parties could set up a PTR record as follows: +.Bd -literal -offset indent +1.0.0.127.in-addr.arpa. IN PTR 10.1.1.1 +.Ed .Pp -The text was shamelessly copied from RFC2553. +and trick the caller of +.Fn getnameinfo +into believing that +.Fa sa +is +.Li 10.1.1.1 +when it is actually +.Li 127.0.0.1 . .Pp -The type of the 2nd argument should be -.Li socklen_t -for RFC2553 conformance. -The current code is based on pre-RFC2553 specification. +To prevent such attacks, the use of +.Dv NI_NAMEREQD +is recommended when the result of +.Fn getnameinfo +is used for access control purposes: +.Bd -literal -offset indent +struct sockaddr *sa; +socklen_t salen; +char addr[NI_MAXHOST]; +struct addrinfo hints, *res; +int error; + +error = getnameinfo(sa, salen, addr, sizeof(addr), + NULL, 0, NI_NAMEREQD); +if (error == 0) { + memset(\*[Am]hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_DGRAM; /*dummy*/ + hints.ai_flags = AI_NUMERICHOST; + if (getaddrinfo(addr, "0", \*[Am]hints, \*[Am]res) == 0) { + /* malicious PTR record */ + freeaddrinfo(res); + printf("bogus PTR record\en"); + return -1; + } + /* addr is FQDN as a result of PTR lookup */ +} else { + /* addr is numeric string */ + error = getnameinfo(sa, salen, addr, sizeof(addr), + NULL, 0, NI_NUMERICHOST); +} +.Ed +.Sh BUGS +The implementation of +.Fn getnameinfo +is not thread-safe. +.\".Pp +.\".Ox +.\"intentionally uses a different +.\".Dv NI_MAXHOST +.\"value from what +.\".Tn "RFC 2553" +.\"suggests, to avoid buffer length handling mistakes. diff --git a/lookup.subproj/lu_bootp.c b/lookup.subproj/lu_bootp.c index c37df56..8f96c94 100644 --- a/lookup.subproj/lu_bootp.c +++ b/lookup.subproj/lu_bootp.c @@ -43,8 +43,6 @@ #include "lookup.h" #include "lu_utils.h" -extern struct ether_addr *ether_aton(char *); - static pthread_mutex_t _bootp_lock = PTHREAD_MUTEX_INITIALIZER; struct bootpent @@ -166,7 +164,7 @@ lu_bootp_getbyether(struct ether_addr *enaddr, char **name, } datalen *= BYTES_PER_XDR_UNIT; - if ((lookup_buf == NULL) || (datalen == 0)) return NULL; + if ((lookup_buf == NULL) || (datalen == 0)) return 0; xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE); @@ -226,7 +224,7 @@ lu_bootp_getbyip(struct ether_addr *enaddr, char **name, } datalen *= BYTES_PER_XDR_UNIT; - if ((lookup_buf == NULL) || (datalen == 0)) return NULL; + if ((lookup_buf == NULL) || (datalen == 0)) return 0; xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE); diff --git a/lookup.subproj/lu_group.c b/lookup.subproj/lu_group.c index adf3fe9..ae18310 100644 --- a/lookup.subproj/lu_group.c +++ b/lookup.subproj/lu_group.c @@ -34,10 +34,13 @@ #include #include #include +#include #include #include #include #include +#include +#include #include "_lu_types.h" #include "lookup.h" @@ -55,6 +58,14 @@ static unsigned int _group_cache_ttl = DEFAULT_GROUP_CACHE_TTL; static pthread_mutex_t _group_lock = PTHREAD_MUTEX_INITIALIZER; +/* + * 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); + #define GR_GET_NAME 1 #define GR_GET_GID 2 #define GR_GET_ENT 3 @@ -220,8 +231,8 @@ copy_group_r(struct group *in, struct group *out, char *buffer, int buflen) /* Calculate size of input */ hsize = 0; - if (in->gr_name != NULL) hsize += strlen(in->gr_name); - if (in->gr_passwd != NULL) hsize += strlen(in->gr_passwd); + if (in->gr_name != NULL) hsize += (strlen(in->gr_name) + 1); + if (in->gr_passwd != NULL) hsize += (strlen(in->gr_passwd) + 1); /* NULL pointer at end of list */ hsize += sizeof(char *); @@ -232,7 +243,7 @@ copy_group_r(struct group *in, struct group *out, char *buffer, int buflen) for (len = 0; in->gr_mem[len] != NULL; len++) { hsize += sizeof(char *); - hsize += strlen(in->gr_mem[len]); + hsize += (strlen(in->gr_mem[len]) + 1); } } @@ -557,24 +568,59 @@ lu_getgrnam(const char *name) return g; } +/* + * add a group to a list + * + * if dupok is non-zero, it's OK to add a duplicate entry + * if dupok is zero, we only add the gid if it is new + * (*listcount) is incremented if the gid was added + * 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) +{ + int i, n, addit, status; + + if (laststatus != 0) return laststatus; + + status = 0; + addit = 1; + n = *listcount; + + if (dupok == 0) + { + for (i = 0; (i < n) && (addit == 1); i++) + { + if (list[i] == gid) addit = 0; + } + } + + if (addit == 0) return 0; + if (n >= max) return -1; + + list[n] = gid; + *listcount = n + 1; + return 0; +} + int -_old_getgrouplist(const char *uname, int agroup, int *groups, int *grpcnt) +_old_getgrouplist(const char *uname, int basegid, int *groups, int *grpcnt) { struct group *grp; - int i, ngroups; - int ret, maxgroups; + int i, status, maxgroups; - ret = 0; - ngroups = 0; + status = 0; maxgroups = *grpcnt; + *grpcnt = 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. */ - groups[ngroups++] = agroup; - if (maxgroups > 1) groups[ngroups++] = agroup; + status = _add_group(basegid, groups, grpcnt, maxgroups, 0, status); + status = _add_group(basegid, groups, grpcnt, maxgroups, 1, status); /* * Scan the group file to find additional groups. @@ -583,26 +629,86 @@ _old_getgrouplist(const char *uname, int agroup, int *groups, int *grpcnt) while ((grp = getgrent())) { - if (grp->gr_gid == (gid_t)agroup) continue; + if (grp->gr_gid == (gid_t)basegid) continue; for (i = 0; grp->gr_mem[i]; i++) { if (!strcmp(grp->gr_mem[i], uname)) { - if (ngroups >= maxgroups) - { - ret = -1; - break; - } - - groups[ngroups++] = grp->gr_gid; + status = _add_group(grp->gr_gid, groups, grpcnt, maxgroups, 0, status); break; } } } endgrent(); - *grpcnt = ngroups; - return ret; + return status; +} + +static int +_mbr_running() +{ + kern_return_t status; + + 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; +} + +/* + * Guess at the size of a password buffer for getpwnam_r + * pw_name can be MAXLOGNAME + 1 256 - sys/param.h + * pw_passwd can be _PASSWORD_LEN + 1 129 - pwd.h + * pw_dir can be MAXPATHLEN + 1 1025 - sys/syslimits.h + * pw_shell can be MAXPATHLEN + 1025 - sys/syslimits.h + * We allow pw_class and pw_gecos to take a maximum of 4098 bytes (there's no limit on these). + * This adds to 6533 bytes (until one of the constants changes) + */ +#define MAXPWBUF (MAXLOGNAME + 1 + _PASSWORD_LEN + 1 + MAXPATHLEN + 1 + MAXPATHLEN + 1 + 4098) +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; + int pwstatus; + GIDArray gids; + int status, maxgroups; + + 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; + + maxgroups = *grpcnt; + *grpcnt = 0; + + 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; + + 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; + + count = 0; + kstatus = _mbr_GetGroups(mbr_port, p.pw_uid, &count, gids); + if (kstatus != KERN_SUCCESS) return status; + + for (i = 0; (i < count) && (status == 0); i++) + { + status = _add_group(gids[i], groups, grpcnt, maxgroups, 0, status); + } + + return status; } static int @@ -614,54 +720,49 @@ lu_getgrouplist(const char *name, int basegid, int *groups, int *grpcnt, int dup static int proc = -1; char *lookup_buf; char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT]; - int ngroups; - int a_group; - int i, j, count; + int gid; + int i, count; + int status, maxgroups; - if (groups == NULL) return -1; - if (*grpcnt == 0) return -1; + status = 0; - ngroups = 0; - groups[ngroups++] = basegid; - if (*grpcnt == 1) return 0; + if (name == NULL) return status; + if (groups == NULL) return status; + if (grpcnt == NULL) return status; + + maxgroups = *grpcnt; + *grpcnt = 0; - if (dupbase != 0) - { - /* getgrouplist duplicates the primary group! */ - groups[ngroups++] = basegid; - if (*grpcnt == 2) return 0; - } + 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 (proc < 0) { - if (_lookup_link(_lu_port, "initgroups", &proc) != KERN_SUCCESS) - { - return -1; - } + if (_lookup_link(_lu_port, "initgroups", &proc) != KERN_SUCCESS) return status; } xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE); if (!xdr__lu_string(&outxdr, (_lu_string *)&name)) { xdr_destroy(&outxdr); - return -1; + return status; } 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) + if (_lookup_all(_lu_port, proc, (unit *)namebuf, xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, &lookup_buf, &datalen) != KERN_SUCCESS) { xdr_destroy(&outxdr); - return -1; + return status; } xdr_destroy(&outxdr); datalen *= BYTES_PER_XDR_UNIT; - if ((lookup_buf == NULL) || (datalen == 0)) return NULL; + if ((lookup_buf == NULL) || (datalen == 0)) return 0; xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE); @@ -669,55 +770,41 @@ lu_getgrouplist(const char *name, int basegid, int *groups, int *grpcnt, int dup { xdr_destroy(&inxdr); vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); - return -1; + return status; } - for (i = 0; i < count; i++) + for (i = 0; (i < count) && (status == 0); i++) { - if (!xdr_int(&inxdr, &a_group)) break; - - j = 0; - if (dupbase != 0) j = 1; - for (; j < ngroups; j++) - { - if (groups[j] == a_group) break; - } - - if (j >= ngroups) - { - groups[ngroups++] = a_group; - if (ngroups == *grpcnt) break; - } + if (!xdr_int(&inxdr, &gid)) break; + status = _add_group(gid, groups, grpcnt, maxgroups, 0, status); } xdr_destroy(&inxdr); vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); - *grpcnt = ngroups; - return 0; + return status; } -int -getgrouplist(const char *uname, int agroup, int *groups, int *grpcnt) +static int +getgrouplist_internal(const char *name, int basegid, int *groups, int *grpcnt, int dupbase) { + if (_mbr_running()) + { + return mbr_getgrouplist(name, basegid, groups, grpcnt, dupbase); + } + if (_lu_running()) { - return lu_getgrouplist(uname, agroup, groups, grpcnt, 1); + return lu_getgrouplist(name, basegid, groups, grpcnt, dupbase); } - - return _old_getgrouplist(uname, agroup, groups, grpcnt); + + return _old_getgrouplist(name, basegid, groups, grpcnt); } -static int -lu_initgroups(const char *name, int basegid) +int +getgrouplist(const char *uname, int agroup, int *groups, int *grpcnt) { - int status, ngroups, groups[NGROUPS]; - - ngroups = NGROUPS; - status = lu_getgrouplist(name, basegid, groups, &ngroups, 0); - if (status < 0) return status; - - return setgroups(ngroups, groups); + return getgrouplist_internal(uname, agroup, groups, grpcnt, 1); } static void @@ -914,23 +1001,14 @@ getgr_r(const char *name, gid_t gid, int source, struct group *grp, char *buffer int initgroups(const char *name, int basegid) { - int res; + int status, ngroups, groups[NGROUPS]; - if (name == NULL) return -1; + ngroups = NGROUPS; - if (_lu_running()) - { - if ((res = lu_initgroups(name, basegid))) - { - res = _old_initgroups(name, basegid); - } - } - else - { - res = _old_initgroups(name, basegid); - } + status = getgrouplist_internal(name, basegid, groups, &ngroups, 0); + if (status < 0) return status; - return (res); + return setgroups(ngroups, groups); } struct group * diff --git a/lookup.subproj/lu_host.c b/lookup.subproj/lu_host.c index b99826f..962c434 100644 --- a/lookup.subproj/lu_host.c +++ b/lookup.subproj/lu_host.c @@ -34,7 +34,10 @@ #include #include #include +#include #include +#include +#include #include "_lu_types.h" #include "lookup.h" @@ -62,8 +65,6 @@ static unsigned int _host_byaddr_cache_index = 0; static pthread_mutex_t _host_lock = PTHREAD_MUTEX_INITIALIZER; -extern struct hostent *_res_gethostbyaddr(); -extern struct hostent *_res_gethostbyname(); extern struct hostent *_old_gethostbyaddr(); extern struct hostent *_old_gethostbyname(); extern struct hostent *_old_gethostent(); @@ -71,6 +72,9 @@ extern void _old_sethostent(); extern void _old_endhostent(); extern void _old_sethostfile(); +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); @@ -665,7 +669,7 @@ lu_gethostbyaddr(const char *addr, int want, int *err) if (_lookup_all(_lu_port, proc, (unit *)address, len / BYTES_PER_XDR_UNIT, &lookup_buf, &datalen) != KERN_SUCCESS) { - *err = NO_RECOVERY; + *err = HOST_NOT_FOUND; return NULL; } @@ -750,7 +754,7 @@ lu_gethostbyname(const char *name, int want, int *err) if (_lookup_all(_lu_port, proc, (unit *)namebuf, xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, &lookup_buf, &datalen) != KERN_SUCCESS) { xdr_destroy(&outxdr); - *err = NO_RECOVERY; + *err = HOST_NOT_FOUND; return NULL; } @@ -831,7 +835,7 @@ lu_gethostent(int want, int *err) if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS) { lu_endhostent(); - *err = NO_RECOVERY; + *err = HOST_NOT_FOUND; return NULL; } @@ -908,8 +912,7 @@ gethostbyaddrerrno(const char *addr, int len, int type, int *err) else { pthread_mutex_lock(&_host_lock); - res = copy_host(_res_gethostbyaddr(addr, len, type)); - if (res == NULL) res = copy_host(_old_gethostbyaddr(addr, len, type)); + res = copy_host(_old_gethostbyaddr(addr, len, type)); *err = h_errno; pthread_mutex_unlock(&_host_lock); } @@ -920,7 +923,7 @@ gethostbyaddrerrno(const char *addr, int len, int type, int *err) } struct hostent * -gethostbyaddr(const char *addr, int len, int type) +gethostbyaddr(const void *addr, socklen_t len, int type) { struct hostent *res; struct lu_thread_info *tdata; @@ -1010,8 +1013,7 @@ gethostbynameerrno(const char *name, int *err) else { pthread_mutex_lock(&_host_lock); - res = copy_host(_res_gethostbyname(name)); - if (res == NULL) res = copy_host(_old_gethostbyname(name)); + res = copy_host(_old_gethostbyname(name)); *err = h_errno; pthread_mutex_unlock(&_host_lock); } @@ -1069,7 +1071,6 @@ gethostbyname2(const char *name, int af) if (res == NULL) { errno = EAFNOSUPPORT; - h_errno = NETDB_INTERNAL; return NULL; } @@ -1356,8 +1357,7 @@ getipnodebyname(const char *name, int af, int flags, int *err) else { pthread_mutex_lock(&_host_lock); - res = copy_host(_res_gethostbyname(name)); - if (res == NULL) res = copy_host(_old_gethostbyname(name)); + res = copy_host(_old_gethostbyname(name)); *err = h_errno; pthread_mutex_unlock(&_host_lock); } @@ -1372,3 +1372,110 @@ getipnodebyname(const char *name, int af, int flags, int *err) return res; } + +/* + * 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) +{ + unsigned int i, n, j, x[6]; + ni_proplist *q, **r; + char *s; + + 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; + } + + for (i = 0; i < 6; i++) e->ether_addr_octet[i] = x[i]; + + for (i = 0; i < n; i++) + { + ni_proplist_free(r[i]); + free(r[i]); + } + + free(r); + return 0; +} + +/* + * 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) +{ + unsigned int i, n, len, x[6]; + ni_proplist *q, **r; + char str[256]; + + if (host == NULL) return -1; + if (e == NULL) 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; +} + +int +ether_hostton(const char *host, struct ether_addr *e) +{ + if (_lu_running()) return lu_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); + return _old_ether_ntohost(host, e); +} diff --git a/lookup.subproj/lu_host_async.c b/lookup.subproj/lu_host_async.c index 1367eef..bdf6796 100644 --- a/lookup.subproj/lu_host_async.c +++ b/lookup.subproj/lu_host_async.c @@ -374,7 +374,7 @@ _gethostbyaddr_async_start(const char *addr, int len, int type, a_request_callou if (len != sizeof(struct in_addr)) { *error = NO_RECOVERY; - return NULL; + return MACH_PORT_NULL; } v4addr = malloc(len); @@ -400,7 +400,7 @@ _gethostbyaddr_async_start(const char *addr, int len, int type, a_request_callou if (len != sizeof(struct in6_addr)) { *error = NO_RECOVERY; - return NULL; + return MACH_PORT_NULL; } v6addr = malloc(len); @@ -784,7 +784,7 @@ _gethostbyname_async_start(const char *name, int want, int *error, a_request_cal free(request->request.data); free(request); *error = NO_RECOVERY; - mp = NULL; + mp = MACH_PORT_NULL; } xdr_destroy(&outxdr); diff --git a/lookup.subproj/lu_netgroup.c b/lookup.subproj/lu_netgroup.c index 5a32b0b..1badf48 100644 --- a/lookup.subproj/lu_netgroup.c +++ b/lookup.subproj/lu_netgroup.c @@ -40,8 +40,15 @@ #define FIX(x) ((x == NULL) ? NULL : (_lu_string *)&(x)) +struct lu_netgrent +{ + char *ng_host; + char *ng_user; + char *ng_domain; +}; + static void -free_netgroup_data(struct netgrent *ng) +free_netgroup_data(struct lu_netgrent *ng) { if (ng == NULL) return; @@ -51,7 +58,7 @@ free_netgroup_data(struct netgrent *ng) } static void -free_netgroup(struct netgrent *ng) +free_netgroup(struct lu_netgrent *ng) { if (ng == NULL) return; free_netgroup_data(ng); @@ -69,7 +76,7 @@ free_lu_thread_info_netgroup(void *x) if (tdata->lu_entry != NULL) { - free_netgroup((struct netgrent *)tdata->lu_entry); + free_netgroup((struct lu_netgrent *)tdata->lu_entry); tdata->lu_entry = NULL; } @@ -78,11 +85,11 @@ free_lu_thread_info_netgroup(void *x) free(tdata); } -static struct netgrent * +static struct lu_netgrent * extract_netgroup(XDR *xdr) { char *h, *u, *d; - struct netgrent *ng; + struct lu_netgrent *ng; if (xdr == NULL) return NULL; @@ -108,7 +115,7 @@ extract_netgroup(XDR *xdr) return NULL; } - ng = (struct netgrent *)calloc(1, sizeof(struct netgrent)); + ng = (struct lu_netgrent *)calloc(1, sizeof(struct lu_netgrent)); ng->ng_host = h; ng->ng_user = u; @@ -118,14 +125,14 @@ extract_netgroup(XDR *xdr) } #ifdef NOTDEF -static struct netgrent * -copy_netgroup(struct netgrent *in) +static struct lu_netgrent * +copy_netgroup(struct lu_netgrent *in) { - struct netgrent *ng; + struct lu_netgrent *ng; if (in == NULL) return NULL; - ng = (struct group *)calloc(1, sizeof(struct netgrent)); + 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); @@ -136,12 +143,12 @@ copy_netgroup(struct netgrent *in) #endif static void -recycle_netgroup(struct lu_thread_info *tdata, struct netgrent *in) +recycle_netgroup(struct lu_thread_info *tdata, struct lu_netgrent *in) { - struct netgrent *ng; + struct lu_netgrent *ng; if (tdata == NULL) return; - ng = (struct netgrent *)tdata->lu_entry; + ng = (struct lu_netgrent *)tdata->lu_entry; if (in == NULL) { @@ -210,7 +217,7 @@ lu_innetgr(const char *group, const char *host, const char *user, } datalen *= BYTES_PER_XDR_UNIT; - if ((lookup_buf == NULL) || (datalen == 0)) return NULL; + if ((lookup_buf == NULL) || (datalen == 0)) return 0; xdrmem_create(&xdr, lookup_buf, datalen, XDR_DECODE); if (!xdr_int(&xdr, &res)) @@ -223,7 +230,7 @@ lu_innetgr(const char *group, const char *host, const char *user, xdr_destroy(&xdr); vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen); - return res; + return 1; } static void @@ -256,7 +263,7 @@ lu_setnetgrent(const char *name) tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info)); _lu_data_set_key(_lu_data_key_netgroup, tdata); } - + lu_endnetgrent(); if (proc < 0) @@ -299,10 +306,10 @@ lu_setnetgrent(const char *name) } -struct netgrent * +static struct lu_netgrent * lu_getnetgrent(void) { - struct netgrent *ng; + struct lu_netgrent *ng; struct lu_thread_info *tdata; tdata = _lu_data_create_key(_lu_data_key_netgroup, free_lu_thread_info_netgroup); @@ -334,10 +341,10 @@ innetgr(const char *group, const char *host, const char *user, return 0; } -struct netgrent * -getnetgrent(void) +int +getnetgrent(char **host, char **user, char **domain) { - struct netgrent *res = NULL; + struct lu_netgrent *res = NULL; struct lu_thread_info *tdata; tdata = _lu_data_create_key(_lu_data_key_netgroup, free_lu_thread_info_netgroup); @@ -351,7 +358,13 @@ getnetgrent(void) if (_lu_running()) res = lu_getnetgrent(); recycle_netgroup(tdata, res); - return (struct netgrent *)tdata->lu_entry; + if (res == NULL) return 0; + + if (host != NULL) *host = res->ng_host; + if (user != NULL) *user = res->ng_user; + if (domain != NULL) *domain = res->ng_domain; + + return 1; } void diff --git a/lookup.subproj/lu_network.c b/lookup.subproj/lu_network.c index e603b9b..db1ba65 100644 --- a/lookup.subproj/lu_network.c +++ b/lookup.subproj/lu_network.c @@ -486,7 +486,7 @@ getnet(const char *name, long addr, int type, int source) } struct netent * -getnetbyaddr(long addr, int type) +getnetbyaddr(uint32_t addr, int type) { return getnet(NULL, addr, type, N_GET_ADDR); } diff --git a/lookup.subproj/lu_user.c b/lookup.subproj/lu_user.c index 2535b36..e7f92af 100644 --- a/lookup.subproj/lu_user.c +++ b/lookup.subproj/lu_user.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include "_lu_types.h" @@ -237,12 +238,12 @@ copy_user_r(struct passwd *in, struct passwd *out, char *buffer, int buflen) /* Calculate size of input */ hsize = 0; - if (in->pw_name != NULL) hsize += strlen(in->pw_name); - if (in->pw_passwd != NULL) hsize += strlen(in->pw_passwd); - if (in->pw_class != NULL) hsize += strlen(in->pw_class); - if (in->pw_gecos != NULL) hsize += strlen(in->pw_gecos); - if (in->pw_dir != NULL) hsize += strlen(in->pw_dir); - if (in->pw_shell != NULL) hsize += strlen(in->pw_shell); + if (in->pw_name != NULL) hsize += (strlen(in->pw_name) + 1); + if (in->pw_passwd != NULL) hsize += (strlen(in->pw_passwd) + 1); + if (in->pw_class != NULL) hsize += (strlen(in->pw_class) + 1); + if (in->pw_gecos != NULL) hsize += (strlen(in->pw_gecos) + 1); + if (in->pw_dir != NULL) hsize += (strlen(in->pw_dir) + 1); + if (in->pw_shell != NULL) hsize += (strlen(in->pw_shell) + 1); /* Check buffer space */ if (hsize > buflen) return -1; diff --git a/lookup.subproj/lu_utils.c b/lookup.subproj/lu_utils.c index d98e380..3362147 100644 --- a/lookup.subproj/lu_utils.c +++ b/lookup.subproj/lu_utils.c @@ -41,7 +41,7 @@ #define LU_MESSAGE_SEND_ID 4241776 #define LU_MESSAGE_REPLY_ID 4241876 -static pthread_key_t _info_key = NULL; +static pthread_key_t _info_key = 0; static pthread_once_t _info_key_initialized = PTHREAD_ONCE_INIT; struct _lu_data_s @@ -112,9 +112,9 @@ _lu_async_send(_lu_async_request_t *r) 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); + 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; - + if (status == MACH_SEND_INVALID_REPLY) { mach_port_mod_refs(mach_task_self(), r->reply_port, MACH_PORT_RIGHT_RECEIVE, -1); @@ -204,6 +204,7 @@ lu_async_receive(mach_port_t p, char **buf, uint32_t *len) kern_return_t status; uint32_t size; _lu_async_request_t *req; + boolean_t msgh_simple; size = sizeof(_lu_reply_msg_t); @@ -219,6 +220,8 @@ lu_async_receive(mach_port_t p, char **buf, uint32_t *len) return status; } + msgh_simple = !(r->head.msgh_bits & MACH_MSGH_BITS_COMPLEX); + req = _lu_worklist_remove(r->head.msgh_local_port); if (req == NULL) { @@ -226,6 +229,14 @@ lu_async_receive(mach_port_t p, char **buf, uint32_t *len) return KERN_FAILURE; } + if (msgh_simple && ((mig_reply_error_t *) r)->RetCode != KERN_SUCCESS) + { + _lu_free_request(req); + status = ((mig_reply_error_t *) r)->RetCode; + free(r); + return status; + } + *buf = r->reply_data.address; *len = r->reply_data.size; @@ -273,7 +284,7 @@ _lu_create_request(uint32_t proc, const char *buf, uint32_t len, void *callback, _lu_async_request_t *r; kern_return_t status; - if (_lu_port == NULL) return NULL; + if (_lu_port == MACH_PORT_NULL) return NULL; r = (_lu_async_request_t *)calloc(1, sizeof(_lu_async_request_t)); if (r == NULL) return NULL; @@ -350,6 +361,7 @@ lu_async_handle_reply(void *msg, char **buf, uint32_t *len, void **callback, voi _lu_async_request_t *req; kern_return_t status; uint32_t retry; + boolean_t msgh_simple; if (msg == NULL) return -1; r = (_lu_reply_msg_t *)msg; @@ -375,15 +387,23 @@ lu_async_handle_reply(void *msg, char **buf, uint32_t *len, void **callback, voi 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; - *buf = r->reply_data.address; - *len = r->reply_data.size; *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; } @@ -403,8 +423,7 @@ _lookupd_xdr_dictionary(XDR *inxdr) l->ni_proplist_val = NULL; if (nkeys > 0) { - i = nkeys * sizeof(ni_property); - l->ni_proplist_val = (ni_property *)calloc(1, i); + l->ni_proplist_val = (ni_property *)calloc(nkeys, sizeof(ni_property)); } for (i = 0; i < nkeys; i++) @@ -417,20 +436,19 @@ _lookupd_xdr_dictionary(XDR *inxdr) } 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) { - j = nvals * sizeof(ni_name); - l->ni_proplist_val[i].nip_val.ni_namelist_val = (ni_name *)calloc(1, j); + l->ni_proplist_val[i].nip_val.ni_namelist_val = (ni_name *)calloc(nvals, sizeof(ni_name)); } - + for (j = 0; j < nvals; j++) { val = NULL; @@ -463,7 +481,7 @@ lookupd_query(ni_proplist *l, ni_proplist ***out) if (l == NULL) return 0; if (out == NULL) return 0; - if (_lu_port == NULL) return 0; + if (_lu_port == MACH_PORT_NULL) return 0; status = _lookup_link(_lu_port, "query", &proc); if (status != KERN_SUCCESS) return 0; @@ -482,13 +500,12 @@ lookupd_query(ni_proplist *l, ni_proplist ***out) for (i = 0; i < l->ni_proplist_len; i++) { p = &(l->ni_proplist_val[i]); - s = NULL; + s = p->nip_name; if (!xdr_string(&outxdr, &s, _LU_MAXLUSTRLEN)) { xdr_destroy(&outxdr); return 0; } - p->nip_name = s; if (!xdr_int(&outxdr, &(p->nip_val.ni_namelist_len))) { @@ -498,21 +515,20 @@ lookupd_query(ni_proplist *l, ni_proplist ***out) for (j = 0; j < p->nip_val.ni_namelist_len; j++) { - s = NULL; + s = p->nip_val.ni_namelist_val[j]; if (!xdr_string(&outxdr, &s, _LU_MAXLUSTRLEN)) { xdr_destroy(&outxdr); return 0; } - p->nip_val.ni_namelist_val[j] = s; } } listbuf = NULL; datalen = 0; - n = xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT; - status = _lookup_all(_lu_port, proc, (unit *)databuf, n, &listbuf, &datalen); + n = xdr_getpos(&outxdr); + status = _lookup_all(_lu_port, proc, (void *)databuf, n, &listbuf, &datalen); if (status != KERN_SUCCESS) { xdr_destroy(&outxdr); @@ -520,12 +536,7 @@ lookupd_query(ni_proplist *l, ni_proplist ***out) } xdr_destroy(&outxdr); - -#ifdef NOTDEF -/* NOTDEF because OOL buffers are counted in bytes with untyped IPC */ datalen *= BYTES_PER_XDR_UNIT; -#endif - xdrmem_create(&inxdr, listbuf, datalen, XDR_DECODE); if (!xdr_int(&inxdr, &n)) @@ -550,7 +561,7 @@ lookupd_query(ni_proplist *l, ni_proplist ***out) xdr_destroy(&inxdr); vm_deallocate(mach_task_self(), (vm_address_t)listbuf, datalen); - + return n; } @@ -587,7 +598,7 @@ lookupd_make_query(char *cat, char *fmt, ...) } va_start(ap, fmt); - for (f = fmt; *f != NULL; f++) + for (f = fmt; (*f) != '\0'; f++) { arg = va_arg(ap, char *); if (*f == 'k') @@ -696,7 +707,7 @@ _lu_data_free(void *x) t = (struct _lu_data_s *)x; for (i = 0; i < t->icount; i++) - { + { if ((t->idata[i] != NULL) && (t->idata_destructor[i] != NULL)) { (*(t->idata_destructor[i]))(t->idata[i]); diff --git a/lookup.subproj/netdb.h b/lookup.subproj/netdb.h index c0811c4..916842e 100644 --- a/lookup.subproj/netdb.h +++ b/lookup.subproj/netdb.h @@ -81,9 +81,19 @@ #ifndef _NETDB_H_ #define _NETDB_H_ -#include -#include -#include +#include +#include <_types.h> +#include /* IPPORT_RESERVED */ + +#ifndef _SIZE_T +#define _SIZE_T +typedef __darwin_size_t size_t; +#endif + +#ifndef _SOCKLEN_T +#define _SOCKLEN_T +typedef __darwin_socklen_t socklen_t; +#endif #define _PATH_HEQUIV "/etc/hosts.equiv" #define _PATH_HOSTS "/etc/hosts" @@ -93,6 +103,10 @@ extern int h_errno; +#ifndef IPPORT_RESERVED +#define IPPORT_RESERVED __DARWIN_IPPORT_RESERVED +#endif + /* * Structures returned by network data base library. All addresses are * supplied in host order, and returned in network order (suitable for @@ -104,7 +118,9 @@ struct hostent { int h_addrtype; /* host address type */ int h_length; /* length of address */ char **h_addr_list; /* list of addresses from name server */ +#ifndef _POSIX_C_SOURCE #define h_addr h_addr_list[0] /* address, for backward compatiblity */ +#endif /* !_POSIX_C_SOURCE */ }; /* @@ -115,7 +131,7 @@ struct netent { char *n_name; /* official name of net */ char **n_aliases; /* alias list */ int n_addrtype; /* net address type */ - unsigned long n_net; /* network # */ + uint32_t n_net; /* network # */ }; struct servent { @@ -136,48 +152,60 @@ struct addrinfo { int ai_family; /* PF_xxx */ int ai_socktype; /* SOCK_xxx */ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ - size_t ai_addrlen; /* length of ai_addr */ + socklen_t ai_addrlen; /* length of ai_addr */ char *ai_canonname; /* canonical name for hostname */ struct sockaddr *ai_addr; /* binary address */ struct addrinfo *ai_next; /* next structure in linked list */ }; +#ifndef _POSIX_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 */ /* * Error return codes from gethostbyname() and gethostbyaddr() * (left in extern int h_errno). */ - +#ifndef _POSIX_C_SOURCE #define NETDB_INTERNAL -1 /* see errno */ #define NETDB_SUCCESS 0 /* no problem */ +#endif /* !_POSIX_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 #define NO_ADDRESS NO_DATA /* no address, look for MX record */ - +#endif /* !_POSIX_C_SOURCE */ /* * Error return codes from getaddrinfo() */ +#ifndef _POSIX_C_SOURCE #define EAI_ADDRFAMILY 1 /* address family for hostname not supported */ +#endif /* !_POSIX_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 #define EAI_NODATA 7 /* no address associated with hostname */ +#endif /* !_POSIX_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 #define EAI_BADHINTS 12 #define EAI_PROTOCOL 13 #define EAI_MAX 14 +#else /* _POSIX_C_SOURCE */ +#define EAI_OVERFLOW 14 /* An argument buffer overflowed */ +#endif /* !_POSIX_C_SOURCE */ /* * Flag values for getaddrinfo() @@ -186,21 +214,27 @@ struct rpcent { #define AI_CANONNAME 0x00000002 /* fill ai_canonname */ #define AI_NUMERICHOST 0x00000004 /* prevent name resolution */ /* valid flags for addrinfo */ +#ifndef _POSIX_C_SOURCE #define AI_MASK (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST) - +#endif /* !_POSIX_C_SOURCE */ #define AI_ALL 0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */ +#ifndef _POSIX_C_SOURCE #define AI_V4MAPPED_CFG 0x00000200 /* accept IPv4-mapped if kernel supports */ +#endif /* !_POSIX_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 #define AI_DEFAULT (AI_V4MAPPED_CFG | AI_ADDRCONFIG) +#endif /* !_POSIX_C_SOURCE */ /* * Constants for getnameinfo() */ +#ifndef _POSIX_C_SOURCE #define NI_MAXHOST 1025 #define NI_MAXSERV 32 - +#endif /* !_POSIX_C_SOURCE */ /* * Flag values for getnameinfo() */ @@ -209,26 +243,33 @@ struct rpcent { #define NI_NAMEREQD 0x00000004 #define NI_NUMERICSERV 0x00000008 #define NI_DGRAM 0x00000010 +#ifndef _POSIX_C_SOURCE #define NI_WITHSCOPEID 0x00000020 /* * Scope delimit character */ #define SCOPE_DELIMITER '%' +#endif /* !_POSIX_C_SOURCE */ __BEGIN_DECLS void endhostent(void); void endnetent(void); void endprotoent(void); void endservent(void); -void freehostent(struct hostent *); -struct hostent *gethostbyaddr(const char *, int, int); + +void freeaddrinfo(struct addrinfo *); +const char *gai_strerror(int); +int getaddrinfo(const char * __restrict, const char * __restrict, + const struct addrinfo * __restrict, + struct addrinfo ** __restrict); +struct hostent *gethostbyaddr(const void *, socklen_t, int); struct hostent *gethostbyname(const char *); -struct hostent *gethostbyname2(const char *, int); struct hostent *gethostent(void); -struct hostent *getipnodebyaddr(const void *, size_t, int, int *); -struct hostent *getipnodebyname(const char *, int, int, int *); -struct netent *getnetbyaddr(long, int); +int getnameinfo(const struct sockaddr * __restrict, socklen_t, + char * __restrict, socklen_t, char * __restrict, + socklen_t, int); +struct netent *getnetbyaddr(uint32_t, int); struct netent *getnetbyname(const char *); struct netent *getnetent(void); struct protoent *getprotobyname(const char *); @@ -237,24 +278,25 @@ struct protoent *getprotoent(void); struct servent *getservbyname(const char *, const char *); struct servent *getservbyport(int, const char *); struct servent *getservent(void); +void sethostent(int); +/* void sethostfile(const char *); */ +void setnetent(int); +void setprotoent(int); +void setservent(int); +#ifndef _POSIX_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); struct rpcent *getrpcbynumber(long number); 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 *); -void sethostent(int); -/* void sethostfile(const char *); */ -void setnetent(int); -void setprotoent(int); -void setservent(int); -const char *gai_strerror(int); -void freeaddrinfo(struct addrinfo *); -int getaddrinfo(const char *, const char *, const struct addrinfo *, struct addrinfo **); -int getnameinfo(const struct sockaddr *, socklen_t, char *, size_t, char *, size_t, int); +#endif /* !_POSIX_C_SOURCE */ __END_DECLS #endif /* !_NETDB_H_ */ diff --git a/lookup.subproj/netdb_async.h b/lookup.subproj/netdb_async.h index da6ed9d..6b72111 100644 --- a/lookup.subproj/netdb_async.h +++ b/lookup.subproj/netdb_async.h @@ -34,6 +34,9 @@ #define getipnodebyaddr_async_handle_reply getipnodebyaddr_async_handleReply #define getipnodebyname_async_handle_reply getipnodebyname_async_handleReply +/* SPI for parallel / fast getaddrinfo */ +#define AI_PARALLEL 0x00000008 + __BEGIN_DECLS /* diff --git a/lookup.subproj/netgr.h b/lookup.subproj/netgr.h index f2b1917..a1a4cda 100644 --- a/lookup.subproj/netgr.h +++ b/lookup.subproj/netgr.h @@ -29,19 +29,13 @@ #ifndef _NETGR_H_ #define _NETGR_H_ -struct netgrent { - char *ng_host; - char *ng_user; - char *ng_domain; -}; - #include __BEGIN_DECLS -int innetgr __P((const char *,const char *,const char *,const char *)); -void setnetgrent __P((const char *)); -struct netgrent *getnetgrent __P((void)); -void endnetgrent __P((void)); +int innetgr(const char * name, const char *host, const char *user, const char *domain); +int getnetgrent(char **host, char **user, char **domain); +void endnetgrent(void); +void setnetgrent(const char *netgroup); __END_DECLS #endif /* !_NETGR_H_ */ diff --git a/mdns.subproj/DNSServiceDiscovery.c b/mdns.subproj/DNSServiceDiscovery.c index 9ebc96a..a311769 100644 --- a/mdns.subproj/DNSServiceDiscovery.c +++ b/mdns.subproj/DNSServiceDiscovery.c @@ -32,7 +32,7 @@ #include -extern struct rpc_subsystem internal_DNSServiceDiscoveryReply_subsystem; +extern struct mig_subsystem internal_DNSServiceDiscoveryReply_subsystem; extern boolean_t DNSServiceDiscoveryReply_server( mach_msg_header_t *InHeadP, @@ -63,7 +63,7 @@ kern_return_t DNSServiceRegistrationCreate_rpc DNSCString name, DNSCString regtype, DNSCString domain, - int port, + IPPort port, DNSCString txtRecord ); @@ -270,7 +270,9 @@ dns_service_discovery_ref DNSServiceRegistrationCreate kern_return_t result; dns_service_discovery_ref return_t; struct a_requests *request; - + IPPort IpPort; + char *portptr = (char *)&port; + if (!serverPort) { return NULL; } @@ -300,7 +302,15 @@ dns_service_discovery_ref DNSServiceRegistrationCreate request->context = context; request->callout.regCallback = callBack; - result = DNSServiceRegistrationCreate_rpc(serverPort, clientPort, (char *)name, (char *)regtype, (char *)domain, port, (char *)txtRecord); + // 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)); diff --git a/mdns.subproj/DNSServiceDiscovery.h b/mdns.subproj/DNSServiceDiscovery.h index 3cd32f1..2539467 100644 --- a/mdns.subproj/DNSServiceDiscovery.h +++ b/mdns.subproj/DNSServiceDiscovery.h @@ -31,6 +31,8 @@ #include +#include + __BEGIN_DECLS /* Opaque internal data type */ @@ -109,7 +111,7 @@ dns_service_discovery_ref DNSServiceRegistrationCreate const char *txtRecord, DNSServiceRegistrationReply callBack, void *context -); +) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED; /***************************************************************************/ /* DNS Domain Enumeration */ @@ -151,7 +153,7 @@ 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 */ @@ -186,7 +188,7 @@ dns_service_discovery_ref DNSServiceBrowserCreate const char *domain, DNSServiceBrowserReply callBack, void *context -); +) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED; /***************************************************************************/ /* Resolver requests */ @@ -219,7 +221,7 @@ dns_service_discovery_ref DNSServiceResolverResolve const char *domain, DNSServiceResolverReply callBack, void *context -); +) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED; /***************************************************************************/ /* Mach port accessor and deallocation */ @@ -234,7 +236,7 @@ dns_service_discovery_ref DNSServiceResolverResolve specified or some other error occurred which prevented the resolution from being started. */ -mach_port_t DNSServiceDiscoveryMachPort(dns_service_discovery_ref dnsServiceDiscovery); +mach_port_t DNSServiceDiscoveryMachPort(dns_service_discovery_ref dnsServiceDiscovery) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED; /*! @function DNSServiceDiscoveryDeallocate @@ -242,7 +244,7 @@ mach_port_t DNSServiceDiscoveryMachPort(dns_service_discovery_ref dnsServiceDisc @param dnsServiceDiscovery A dns_service_discovery_ref as returned from a creation or enumeration call @result void */ -void DNSServiceDiscoveryDeallocate(dns_service_discovery_ref dnsServiceDiscovery); +void DNSServiceDiscoveryDeallocate(dns_service_discovery_ref dnsServiceDiscovery) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED; /***************************************************************************/ /* Registration updating */ @@ -258,7 +260,8 @@ void DNSServiceDiscoveryDeallocate(dns_service_discovery_ref dnsServiceDiscovery @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); +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 @@ -270,7 +273,8 @@ DNSRecordReference DNSServiceRegistrationAddRecord(dns_service_discovery_ref dns @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); +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 @@ -279,7 +283,8 @@ DNSServiceRegistrationReplyErrorType DNSServiceRegistrationUpdateRecord(dns_serv @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); +DNSServiceRegistrationReplyErrorType DNSServiceRegistrationRemoveRecord(dns_service_discovery_ref ref, DNSRecordReference reference) +AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER_BUT_DEPRECATED; __END_DECLS diff --git a/mdns.subproj/DNSServiceDiscoveryDefines.h b/mdns.subproj/DNSServiceDiscoveryDefines.h index b0525e1..9f021d9 100644 --- a/mdns.subproj/DNSServiceDiscoveryDefines.h +++ b/mdns.subproj/DNSServiceDiscoveryDefines.h @@ -31,6 +31,7 @@ typedef char DNSCString[1024]; typedef char sockaddr_t[128]; typedef const char * record_data_t; +typedef struct { char bytes[4]; } IPPort; #endif /* __DNS_SERVICE_DISCOVERY_DEFINES_H */ diff --git a/mdns.subproj/DNSServiceDiscoveryRequest.defs b/mdns.subproj/DNSServiceDiscoveryRequest.defs index 29495f8..d14917a 100644 --- a/mdns.subproj/DNSServiceDiscoveryRequest.defs +++ b/mdns.subproj/DNSServiceDiscoveryRequest.defs @@ -33,6 +33,7 @@ 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; @@ -52,7 +53,7 @@ simpleroutine DNSServiceRegistrationCreate_rpc( in name: DNSCString; in regtype: DNSCString; in domain: DNSCString; - in port: int; + in port: IPPort; in txtRecord: DNSCString); diff --git a/mdns.subproj/Makefile b/mdns.subproj/Makefile index 18a40c0..cda015f 100644 --- a/mdns.subproj/Makefile +++ b/mdns.subproj/Makefile @@ -14,7 +14,7 @@ PROJECT_TYPE = Component HFILES = DNSServiceDiscoveryDefines.h DNSServiceDiscovery.h dns_sd.h dnssd_ipc.h -CFILES = DNSServiceDiscovery.c dnssd_clientstub.c dnssd_ipc.c +CFILES = DNSServiceDiscovery.c dnssd_clientstub.c dnssd_ipc.c dnssd_clientlib.c OTHERSRCS = Makefile.preamble Makefile Makefile.postamble\ DNSServiceDiscoveryReply.defs DNSServiceDiscoveryRequest.defs diff --git a/mdns.subproj/Makefile.preamble b/mdns.subproj/Makefile.preamble index cde6a14..c3ae97e 100644 --- a/mdns.subproj/Makefile.preamble +++ b/mdns.subproj/Makefile.preamble @@ -154,3 +154,7 @@ AFTER_INSTALLHDRS += mdns_hdrs PRIVATE_HEADER_DIR = /AppleInternal/Developer/Headers MDNS_HEADER_DIR_SUFFIX = /DNSServiceDiscovery + +# for building 64-bit +# Libinfo need to build with gcc-3.5 and 3-way fat +NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER) diff --git a/mdns.subproj/dns_sd.h b/mdns.subproj/dns_sd.h index 4768588..a7411a3 100644 --- a/mdns.subproj/dns_sd.h +++ b/mdns.subproj/dns_sd.h @@ -1,33 +1,58 @@ /* - * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2003-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.2 (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 + * + * 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 OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * + * 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 -#include +#elif defined(__sun__) +#include +#elif defined(_WIN32) +#include +#define _UNUSED +#define bzero(a, b) memset(a, 0, b) +typedef UINT8 uint8_t; +typedef INT8 int8_t; +typedef UINT16 uint16_t; +typedef INT16 int16_t; +typedef UINT32 uint32_t; +typedef INT32 int32_t; +#else #include -#include - +#endif /* DNSServiceRef, DNSRecordRef * @@ -42,45 +67,136 @@ typedef struct _DNSRecordRef_t *DNSRecordRef; /* General flags used in functions defined below */ enum { - kDNSServiceFlagsMoreComing = 1, - kDNSServiceFlagsFinished = 0, /* i.e. bit not set */ - /* MoreComing indicates to a Browse callback that another result is - * queued. Applications should not update their UI to display browse - * results when the MoreComing flag is set, instead deferring the update - * until the callback's flag is Finished. */ - - kDNSServiceFlagsAdd = 2, - kDNSServiceFlagsDefault = 4, - kDNSServiceFlagsRemove = 0, /* i.e. bit not set */ - /* Flags for domain enumeration and browse reply callbacks. + 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" + * conjuction with "Add". An enumeration callback with the "Add" + * flag NOT set indicates a "Remove", i.e. the domain is no longer + * valid. */ - kDNSServiceFlagsNoAutoRename = 8, - kDNSServiceFlagsAutoRename = 0, /* i.e. bit not set */ + kDNSServiceFlagsNoAutoRename = 0x8, /* Flag for specifying renaming behavior on name conflict when registering - * non-shared records. NoAutorename is only valid if a name is explicitly - * specified when registering a service (ie the default name is not used.) + * 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 = 16, - kDNSServiceFlagsUnique = 32, + kDNSServiceFlagsShared = 0x10, + kDNSServiceFlagsUnique = 0x20, /* Flag for registering individual records on a connected - * DNSServiceRef. Shared indicates that there may be multiple records + * 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 = 64, - kDNSServiceFlagsRegistrationDomains = 128 + 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 { @@ -97,16 +213,105 @@ enum kDNSServiceErr_AlreadyRegistered = -65547, kDNSServiceErr_NameConflict = -65548, kDNSServiceErr_Invalid = -65549, + kDNSServiceErr_Firewall = -65550, kDNSServiceErr_Incompatible = -65551, /* client library incompatible with daemon */ - kDNSServiceErr_BadinterfaceIndex = -65552 + 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; @@ -122,11 +327,11 @@ typedef int32_t DNSServiceErrorType; /* DNSServiceRefSockFD() * * Access underlying Unix domain socket for an initialized DNSServiceRef. - * The DNS Service Discovery implmementation uses this socket to communicate between + * 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 + * 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. @@ -135,17 +340,18 @@ typedef int32_t DNSServiceErrorType; * socket buffer. * * sdRef: A DNSServiceRef initialized by any of the DNSService calls. - * - * return value: The DNSServiceRef's underlying socket descriptor, or -1 on + * + * return value: The DNSServiceRef's underlying socket descriptor, or -1 on * error. */ - -int DNSServiceRefSockFD(DNSServiceRef sdRef); + +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 + * 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 @@ -160,111 +366,121 @@ int DNSServiceRefSockFD(DNSServiceRef sdRef); * an error code indicating the specific failure that occurred. */ -DNSServiceErrorType DNSServiceProcessResult(DNSServiceRef sdRef); +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. + * 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'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 + * 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 + * 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 + * 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 DNSServiceRefDeallocate(DNSServiceRef sdRef); +void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef); /********************************************************************************************* - * + * * Domain Enumeration * *********************************************************************************************/ /* DNSServiceEnumerateDomains() - * + * * Asynchronously enumerate domains available for browsing and registration. - * Currently, the only domain returned is "local.", but other domains will be returned in future. * * 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: - * 1 (MoreComing) - * 2 (Add/Remove) - * 4 (Add Default) + * 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.) + * 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 + * 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 (*DNSServiceDomainEnumReply) +typedef void (DNSSD_API *DNSServiceDomainEnumReply) ( DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, - const char *replyDomain, - void *context + const char *replyDomain, + void *context ); - + + /* DNSServiceEnumerateDomains() Parameters: * * - * sdRef: A pointer to an uninitialized sdRef. May be passed to - * DNSServiceRefDeallocate() to cancel the enumeration. + * 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: - * 0 (BrowseDomains) to enumerate domains recommended for browsing. - * 32 (RegistrationDomains) to enumerate domains recommended for registration. + * 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. - * - * callBack: The function to be called when a domain is found or the call asynchronously + * 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 + * 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 + * 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 DNSServiceEnumerateDomains + +DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains ( DNSServiceRef *sdRef, DNSServiceFlags flags, @@ -273,27 +489,28 @@ DNSServiceErrorType DNSServiceEnumerateDomains 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 + * errorCode: Will be kDNSServiceErr_NoError on success, otherwise will * indicate the failure that occurred (including name conflicts, if the - * kDNSServiceFlagsNoAutoRenameOnConflict flag was passed to 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 + * 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. @@ -305,87 +522,89 @@ DNSServiceErrorType DNSServiceEnumerateDomains * context: The context pointer that was passed to the callout. * */ - -typedef void (*DNSServiceRegisterReply) + +typedef void (DNSSD_API *DNSServiceRegisterReply) ( DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode, - const char *name, - const char *regtype, - const char *domain, - void *context + const char *name, + const char *regtype, + const char *domain, + void *context ); - + + /* DNSServiceRegister() Parameters: * - * sdRef: A pointer to an uninitialized sdRef. If this call succeeds, the reference - * may be passed to - * DNSServiceRefDeallocate() to deregister the service. - * + * 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. Pass -1 to register a service only on the local - * machine (service will not be visible to remote hosts.) + * 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 + * 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 + * 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 + * 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 + * 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 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. + * 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. + * txtRecord: The txt record rdata. May be NULL. Note that a non-NULL txtRecord + * MUST be a properly formatted DNS TXT record, i.e. * ... * * callBack: The function to be called when the registration completes or asynchronously - * fails. The client MAY pass NULL for the callback - The client will NOT be notified + * 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 + * 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 + * 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 + * 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 DNSServiceRegister +DNSServiceErrorType DNSSD_API DNSServiceRegister ( DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *name, /* may be NULL */ - const char *regtype, + const char *regtype, const char *domain, /* may be NULL */ const char *host, /* may be NULL */ uint16_t port, @@ -394,39 +613,40 @@ DNSServiceErrorType DNSServiceRegister 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 + * 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 + * + * 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. TXT, SRV, etc), as defined in nameser.h. + * 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. + * 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 DNSServiceAddRecord +DNSServiceErrorType DNSSD_API DNSServiceAddRecord ( DNSServiceRef sdRef, DNSRecordRef *RecordRef, @@ -437,6 +657,7 @@ DNSServiceErrorType DNSServiceAddRecord uint32_t ttl ); + /* DNSServiceUpdateRecord * * Update a registered resource record. The record must either be: @@ -465,7 +686,7 @@ DNSServiceErrorType DNSServiceAddRecord * error code indicating the error that occurred. */ -DNSServiceErrorType DNSServiceUpdateRecord +DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord ( DNSServiceRef sdRef, DNSRecordRef RecordRef, /* may be NULL */ @@ -475,9 +696,10 @@ DNSServiceErrorType DNSServiceUpdateRecord uint32_t ttl ); + /* DNSServiceRemoveRecord * - * Remove a record previously added to a service record set via DNSServiceAddRecord(), or deregister + * Remove a record previously added to a service record set via DNSServiceAddRecord(), or deregister * an record registered individually via DNSServiceRegisterRecord(). * * Parameters: @@ -487,16 +709,16 @@ DNSServiceErrorType DNSServiceUpdateRecord * DNSServiceCreateConnection() (if the record being removed was registered via * DNSServiceRegisterRecord()). * - * recordRef: A DNSRecordRef initialized by a successful call to DNSServiceAddRecord() + * 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 DNSServiceRemoveRecord +DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord ( DNSServiceRef sdRef, DNSRecordRef RecordRef, @@ -510,7 +732,6 @@ DNSServiceErrorType DNSServiceRemoveRecord * *********************************************************************************************/ - /* Browse for instances of a service. * * @@ -518,88 +739,102 @@ DNSServiceErrorType DNSServiceRemoveRecord * * sdRef: The DNSServiceRef initialized by DNSServiceBrowse(). * - * flags: Possible values are MoreComing and Add/Remove. See flag definitions - * for details. + * 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. + * be passed to DNSServiceResolve() when resolving the service. * - * errorCode: Will be kDNSServiceErr_NoError (0) on success, otherwise will + * 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 service name discovered. + * 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, as passed in to DNSServiceBrowse(). + * 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 on which the service was discovered (if the application did not - * specify a domain in DNSServicBrowse(), this indicates the domain on which the - * service was discovered.) + * 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 (*DNSServiceBrowseReply) +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 + const char *serviceName, + const char *regtype, + const char *replyDomain, + void *context ); - + + /* DNSServiceBrowse() Parameters: * - * sdRef: A pointer to an uninitialized sdRef. May be passed to - * DNSServiceRefDeallocate() to terminate the browse. + * 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. Pass -1 to only browse for services provided on the local host. + * 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 + * 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 + * 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 + * 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 + * 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 + * 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 DNSServiceBrowse +DNSServiceErrorType DNSSD_API DNSServiceBrowse ( DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, - const char *regtype, + 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 + * 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 @@ -615,89 +850,93 @@ DNSServiceErrorType DNSServiceBrowse * * flags: Currently unused, reserved for future use. * - * interfaceIndex: The interface on which the service was resolved. + * interfaceIndex: The interface on which the service was resolved. * - * errorCode: Will be kDNSServiceErr_NoError (0) on success, otherwise will + * 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 ... - * (Any literal dots (".") are escaped with a backslash ("\."), and literal - * backslashes are escaped with a second backslash ("\\"), e.g. a web server - * named "Dr. Pepper" would have the fullname "Dr\.\032Pepper._http._tcp.local."). - * This is the appropriate format to pass to standard system DNS APIs such as - * res_query(), or to the special-purpose functions included in this API that - * take fullname parameters. - * - * hosttarget: The target hostname of the machine providing the service. This name can + * (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 number on which connections are accepted for this service. + * 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 (*DNSServiceResolveReply) +typedef void (DNSSD_API *DNSServiceResolveReply) ( DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, - const char *fullname, + const char *fullname, const char *hosttarget, uint16_t port, uint16_t txtLen, const char *txtRecord, - void *context + void *context ); - + + /* DNSServiceResolve() Parameters * - * sdRef: A pointer to an uninitialized sdRef. May be passed to - * DNSServiceRefDeallocate() to terminate the resolve. + * 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. The client should - * pass the interface on which the servicename was discovered, i.e. - * the interfaceIndex passed to the DNSServiceBrowseReply callback, - * or 0 to resolve the named service on all available interfaces. + * 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 servicename to be resolved. + * name: The name of the service instance to be resolved, as reported to the + * DNSServiceBrowseReply() callback. * - * regtype: The service type being resolved followed by the protocol, separated by a - * dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp". + * regtype: The type of the service instance to be resolved, as reported to the + * DNSServiceBrowseReply() callback. * - * domain: The domain on which the service is registered, i.e. the domain passed - * 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 + * 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 + * 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 + * 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 DNSServiceResolve +DNSServiceErrorType DNSSD_API DNSServiceResolve ( DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, - const char *name, - const char *regtype, - const char *domain, + const char *name, + const char *regtype, + const char *domain, DNSServiceResolveReply callBack, void *context /* may be NULL */ ); @@ -709,57 +948,6 @@ DNSServiceErrorType DNSServiceResolve * *********************************************************************************************/ -/* DNS Naming Conventions: - * - * The following functions refer to resource records by their full domain name, unlike the above - * functions which divide the name into servicename/regtype/domain fields. In the above functions, - * a dot (".") is considered to be a literal dot in the servicename field (e.g. "Dr. Pepper") and - * a label separator in the regtype ("_ftp._tcp") or domain ("apple.com") fields. Literal dots in - * the domain field would be escaped with a backslash, and literal backslashes would be escaped with - * a second backslash (this is generally not an issue, as domain names on the Internet today almost - * never use characters other than letters, digits, or hyphens, and the dots are label separators.) - * Furthermore, this is transparent to the caller, so long as the fields are passed between functions - * without manipulation. However, the following, special-purpose calls use a single, full domain name. - * As such, all dots are considered to be label separators, unless escaped, and all backslashes are - * considered to be escape characters, unless preceded by a second backslash. For example, the name - * "Dr. Smith \ Dr. Johnson" could be passed literally as a service name parameter in the above calls, - * but in the special purpose call, the dots and backslash would have to be escaped - * (e.g. "Dr\. Smith \\ Dr\. Johnson._ftp._tcp.apple.com" for an ftp service on the apple.com domain.) - */ - -/* 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 kDNSServiceDiscoveryMaxDomainName (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". Any literal dots or backslashes - * must be escaped. - * - * return value: Returns 0 on success, -1 on error. - * - */ - -int DNSServiceConstructFullName - ( - char *fullName, - const char *service, /* may be NULL */ - const char *regtype, - const char *domain - ); - /* DNSServiceCreateConnection() * * Create a connection to the daemon allowing efficient registration of @@ -777,12 +965,12 @@ int DNSServiceConstructFullName * case the DNSServiceRef is not initialized). */ -DNSServiceErrorType DNSServiceCreateConnection(DNSServiceRef *sdRef); +DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef); /* DNSServiceRegisterRecord * - * Register an individual resource record on a connected DNSServiceRef. + * 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. @@ -792,82 +980,80 @@ DNSServiceErrorType DNSServiceCreateConnection(DNSServiceRef *sdRef); * * 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 + * 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 (*DNSServiceRegisterRecordReply) + + typedef void (DNSSD_API *DNSServiceRegisterRecordReply) ( DNSServiceRef sdRef, DNSRecordRef RecordRef, DNSServiceFlags flags, DNSServiceErrorType errorCode, - void *context + void *context ); - -/* DNSServiceRegisterRecord() Parameters: + +/* DNSServiceRegisterRecord() Parameters: * * sdRef: A DNSServiceRef initialized by DNSServiceCreateConnection(). * - * RecordRef: A pointer to an uninitialized DNSRecordRef. Upon succesfull completion of this + * 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 + * (To deregister ALL records registered on a single connected DNSServiceRef * and deallocate each of their corresponding DNSServiceRecordRefs, call * DNSServiceRefDealloocate()). * - * flags: Possible values are Shared/Unique (see flag type definitions for details). - * + * 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. - * Passing -1 causes the record to only be visible on the local host. + * 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. PTR, SRV, etc), as defined - * in nameser.h. + * rrtype: The numerical type of the resource record (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc) * - * rrclass: The class of the resource record, as defined in nameser.h (usually 1 for the - * Internet class). + * 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. + * 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 + * 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 + * 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 + * 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 DNSServiceRegisterRecord +DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord ( DNSServiceRef sdRef, DNSRecordRef *RecordRef, DNSServiceFlags flags, uint32_t interfaceIndex, - const char *fullname, + const char *fullname, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, @@ -886,21 +1072,24 @@ DNSServiceErrorType DNSServiceRegisterRecord * DNSServiceQueryRecordReply() Callback Parameters: * * sdRef: The DNSServiceRef initialized by DNSServiceQueryRecord(). - * - * flags: Possible values are Finished/MoreComing. * - * interfaceIndex: The interface on which the query was resolved (the index for a given + * 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: 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. PTR, SRV, etc) as defined in nameser.h. + * rrtype: The resource record's type (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc) * - * rrclass: The class of the resource record, as defined in nameser.h (usually 1). + * rrclass: The class of the resource record (usually kDNSServiceClass_IN). * * rdlen: The length, in bytes, of the resource record rdata. * @@ -912,93 +1101,104 @@ DNSServiceErrorType DNSServiceRegisterRecord * */ -typedef void (*DNSServiceQueryRecordReply) +typedef void (DNSSD_API *DNSServiceQueryRecordReply) ( DNSServiceRef DNSServiceRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, - const char *fullname, + const char *fullname, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata, uint32_t ttl, - void *context + void *context ); + /* DNSServiceQueryRecord() Parameters: * - * sdRef: A pointer to an uninitialized DNSServiceRef. + * 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. * - * flags: Currently unused, reserved for future use. - * * 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. Passing -1 causes the name to be queried for only on the - * local host. + * 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. PTR, SRV, etc) - * as defined in nameser.h. + * 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, as defined in nameser.h - * (usually 1 for the Internet class). + * 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 + * 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 + * 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 + * 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 DNSServiceQueryRecord + +DNSServiceErrorType DNSSD_API DNSServiceQueryRecord ( DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, - const char *fullname, + 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 + * 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. PTR, SRV, etc) as defined in nameser.h. + * rrtype: The resource record's type (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc) * - * rrclass: The class of the resource record, as defined in nameser.h (usually 1). + * 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 DNSServiceReconfirmRecord + +void DNSSD_API DNSServiceReconfirmRecord ( DNSServiceFlags flags, uint32_t interfaceIndex, - const char *fullname, + const char *fullname, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, @@ -1006,5 +1206,439 @@ void DNSServiceReconfirmRecord ); -#endif // _DNS_SD_H +/********************************************************************************************* + * + * General Utility Functions + * + *********************************************************************************************/ + +/* DNSServiceConstructFullName() + * + * Concatenate a three-part domain name (as returned by the above callbacks) into a + * properly-escaped full domain name. Note that callbacks in the above functions ALREADY ESCAPE + * strings where necessary. + * + * Parameters: + * + * fullName: A pointer to a buffer that where the resulting full domain name is to be written. + * The buffer must be kDNSServiceMaxDomainName (1005) bytes in length to + * accommodate the longest legal domain name without buffer overrun. + * + * service: The service name - any dots or slashes must NOT be escaped. + * May be NULL (to construct a PTR record name, e.g. + * "_ftp._tcp.apple.com"). + * + * regtype: The service type followed by the protocol, separated by a dot + * (e.g. "_ftp._tcp"). + * + * domain: The domain name, e.g. "apple.com.". Literal dots or backslashes, + * if any, must be escaped, e.g. "1st\. Floor.apple.com." + * + * return value: Returns 0 on success, -1 on error. + * + */ + +int DNSSD_API DNSServiceConstructFullName + ( + char *fullName, + const char *service, /* may be NULL */ + const char *regtype, + const char *domain + ); + + +/********************************************************************************************* + * + * TXT Record Construction Functions + * + *********************************************************************************************/ + +/* + * A typical calling sequence for TXT record construction is something like: + * + * Client allocates storage for TXTRecord data (e.g. declare buffer on the stack) + * TXTRecordCreate(); + * TXTRecordSetValue(); + * TXTRecordSetValue(); + * TXTRecordSetValue(); + * ... + * DNSServiceRegister( ... TXTRecordGetLength(), TXTRecordGetBytesPtr() ... ); + * TXTRecordDeallocate(); + * Explicitly deallocate storage for TXTRecord data (if not allocated on the stack) + */ + + +/* TXTRecordRef + * + * Opaque internal data type. + * Note: Represents a DNS-SD TXT record. + */ + +typedef struct _TXTRecordRef_t { char privatedata[16]; } TXTRecordRef; + + +/* TXTRecordCreate() + * + * Creates a new empty TXTRecordRef referencing the specified storage. + * + * If the buffer parameter is NULL, or the specified storage size is not + * large enough to hold a key subsequently added using TXTRecordSetValue(), + * then additional memory will be added as needed using malloc(). + * + * On some platforms, when memory is low, malloc() may fail. In this + * case, TXTRecordSetValue() will return kDNSServiceErr_NoMemory, and this + * error condition will need to be handled as appropriate by the caller. + * + * You can avoid the need to handle this error condition if you ensure + * that the storage you initially provide is large enough to hold all + * the key/value pairs that are to be added to the record. + * The caller can precompute the exact length required for all of the + * key/value pairs to be added, or simply provide a fixed-sized buffer + * known in advance to be large enough. + * A no-value (key-only) key requires (1 + key length) bytes. + * A key with empty value requires (1 + key length + 1) bytes. + * A key with non-empty value requires (1 + key length + 1 + value length). + * For most applications, DNS-SD TXT records are generally + * less than 100 bytes, so in most cases a simple fixed-sized + * 256-byte buffer will be more than sufficient. + * Recommended size limits for DNS-SD TXT Records are discussed in + * + * + * Note: When passing parameters to and from these TXT record APIs, + * the key name does not include the '=' character. The '=' character + * is the separator between the key and value in the on-the-wire + * packet format; it is not part of either the key or the value. + * + * txtRecord: A pointer to an uninitialized TXTRecordRef. + * + * bufferLen: The size of the storage provided in the "buffer" parameter. + * + * buffer: The storage used to hold the TXTRecord data. + * This storage must remain valid for as long as + * the TXTRecordRef. + */ + +void DNSSD_API TXTRecordCreate + ( + TXTRecordRef *txtRecord, + uint16_t bufferLen, + void *buffer + ); + + +/* TXTRecordDeallocate() + * + * Releases any resources allocated in the course of preparing a TXT Record + * using TXTRecordCreate()/TXTRecordSetValue()/TXTRecordRemoveValue(). + * Ownership of the buffer provided in TXTRecordCreate() returns to the client. + * + * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate(). + * + */ + +void DNSSD_API TXTRecordDeallocate + ( + TXTRecordRef *txtRecord + ); + + +/* TXTRecordSetValue() + * + * Adds a key (optionally with value) to a TXTRecordRef. If the "key" already + * exists in the TXTRecordRef, then the current value will be replaced with + * the new value. + * Keys may exist in four states with respect to a given TXT record: + * - Absent (key does not appear at all) + * - Present with no value ("key" appears alone) + * - Present with empty value ("key=" appears in TXT record) + * - Present with non-empty value ("key=value" appears in TXT record) + * For more details refer to "Data Syntax for DNS-SD TXT Records" in + * + * + * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate(). + * + * key: A null-terminated string which only contains printable ASCII + * values (0x20-0x7E), excluding '=' (0x3D). Keys should be + * 8 characters or less (not counting the terminating null). + * + * valueSize: The size of the value. + * + * value: Any binary value. For values that represent + * textual data, UTF-8 is STRONGLY recommended. + * For values that represent textual data, valueSize + * should NOT include the terminating null (if any) + * at the end of the string. + * If NULL, then "key" will be added with no value. + * If non-NULL but valueSize is zero, then "key=" will be + * added with empty value. + * + * return value: Returns kDNSServiceErr_NoError on success. + * Returns kDNSServiceErr_Invalid if the "key" string contains + * illegal characters. + * Returns kDNSServiceErr_NoMemory if adding this key would + * exceed the available storage. + */ + +DNSServiceErrorType DNSSD_API TXTRecordSetValue + ( + TXTRecordRef *txtRecord, + const char *key, + uint8_t valueSize, /* may be zero */ + const void *value /* may be NULL */ + ); + + +/* TXTRecordRemoveValue() + * + * Removes a key from a TXTRecordRef. The "key" must be an + * ASCII string which exists in the TXTRecordRef. + * + * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate(). + * + * key: A key name which exists in the TXTRecordRef. + * + * return value: Returns kDNSServiceErr_NoError on success. + * Returns kDNSServiceErr_NoSuchKey if the "key" does not + * exist in the TXTRecordRef. + * + */ + +DNSServiceErrorType DNSSD_API TXTRecordRemoveValue + ( + TXTRecordRef *txtRecord, + const char *key + ); + + +/* TXTRecordGetLength() + * + * Allows you to determine the length of the raw bytes within a TXTRecordRef. + * + * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate(). + * + * return value: Returns the size of the raw bytes inside a TXTRecordRef + * which you can pass directly to DNSServiceRegister() or + * to DNSServiceUpdateRecord(). + * Returns 0 if the TXTRecordRef is empty. + * + */ + +uint16_t DNSSD_API TXTRecordGetLength + ( + const TXTRecordRef *txtRecord + ); + + +/* TXTRecordGetBytesPtr() + * + * Allows you to retrieve a pointer to the raw bytes within a TXTRecordRef. + * + * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate(). + * + * return value: Returns a pointer to the raw bytes inside the TXTRecordRef + * which you can pass directly to DNSServiceRegister() or + * to DNSServiceUpdateRecord(). + * + */ + +const void * DNSSD_API TXTRecordGetBytesPtr + ( + const TXTRecordRef *txtRecord + ); + + +/********************************************************************************************* + * + * TXT Record Parsing Functions + * + *********************************************************************************************/ + +/* + * A typical calling sequence for TXT record parsing is something like: + * + * Receive TXT record data in DNSServiceResolve() callback + * if (TXTRecordContainsKey(txtLen, txtRecord, "key")) then do something + * val1ptr = TXTRecordGetValuePtr(txtLen, txtRecord, "key1", &len1); + * val2ptr = TXTRecordGetValuePtr(txtLen, txtRecord, "key2", &len2); + * ... + * bcopy(val1ptr, myval1, len1); + * bcopy(val2ptr, myval2, len2); + * ... + * return; + * + * If you wish to retain the values after return from the DNSServiceResolve() + * callback, then you need to copy the data to your own storage using bcopy() + * or similar, as shown in the example above. + * + * If for some reason you need to parse a TXT record you built yourself + * using the TXT record construction functions above, then you can do + * that using TXTRecordGetLength and TXTRecordGetBytesPtr calls: + * TXTRecordGetValue(TXTRecordGetLength(x), TXTRecordGetBytesPtr(x), key, &len); + * + * Most applications only fetch keys they know about from a TXT record and + * ignore the rest. + * However, some debugging tools wish to fetch and display all keys. + * To do that, use the TXTRecordGetCount() and TXTRecordGetItemAtIndex() calls. + */ + +/* TXTRecordContainsKey() + * + * Allows you to determine if a given TXT Record contains a specified key. + * + * txtLen: The size of the received TXT Record. + * + * txtRecord: Pointer to the received TXT Record bytes. + * + * key: A null-terminated ASCII string containing the key name. + * + * return value: Returns 1 if the TXT Record contains the specified key. + * Otherwise, it returns 0. + * + */ + +int DNSSD_API TXTRecordContainsKey + ( + uint16_t txtLen, + const void *txtRecord, + const char *key + ); + + +/* TXTRecordGetValuePtr() + * + * Allows you to retrieve the value for a given key from a TXT Record. + * + * txtLen: The size of the received TXT Record + * + * txtRecord: Pointer to the received TXT Record bytes. + * + * key: A null-terminated ASCII string containing the key name. + * + * valueLen: On output, will be set to the size of the "value" data. + * + * return value: Returns NULL if the key does not exist in this TXT record, + * or exists with no value (to differentiate between + * these two cases use TXTRecordContainsKey()). + * Returns pointer to location within TXT Record bytes + * if the key exists with empty or non-empty value. + * For empty value, valueLen will be zero. + * For non-empty value, valueLen will be length of value data. + */ + +const void * DNSSD_API TXTRecordGetValuePtr + ( + uint16_t txtLen, + const void *txtRecord, + const char *key, + uint8_t *valueLen + ); + + +/* TXTRecordGetCount() + * + * Returns the number of keys stored in the TXT Record. The count + * can be used with TXTRecordGetItemAtIndex() to iterate through the keys. + * + * txtLen: The size of the received TXT Record. + * + * txtRecord: Pointer to the received TXT Record bytes. + * + * return value: Returns the total number of keys in the TXT Record. + * + */ + +uint16_t DNSSD_API TXTRecordGetCount + ( + uint16_t txtLen, + const void *txtRecord + ); + + +/* TXTRecordGetItemAtIndex() + * + * Allows you to retrieve a key name and value pointer, given an index into + * a TXT Record. Legal index values range from zero to TXTRecordGetCount()-1. + * It's also possible to iterate through keys in a TXT record by simply + * calling TXTRecordGetItemAtIndex() repeatedly, beginning with index zero + * and increasing until TXTRecordGetItemAtIndex() returns kDNSServiceErr_Invalid. + * + * On return: + * For keys with no value, *value is set to NULL and *valueLen is zero. + * For keys with empty value, *value is non-NULL and *valueLen is zero. + * For keys with non-empty value, *value is non-NULL and *valueLen is non-zero. + * + * txtLen: The size of the received TXT Record. + * + * txtRecord: Pointer to the received TXT Record bytes. + * + * index: An index into the TXT Record. + * + * keyBufLen: The size of the string buffer being supplied. + * + * key: A string buffer used to store the key name. + * On return, the buffer contains a null-terminated C string + * giving the key name. DNS-SD TXT keys are usually + * 8 characters or less. To hold the maximum possible + * key name, the buffer should be 256 bytes long. + * + * valueLen: On output, will be set to the size of the "value" data. + * + * value: On output, *value is set to point to location within TXT + * Record bytes that holds the value data. + * + * return value: Returns kDNSServiceErr_NoError on success. + * Returns kDNSServiceErr_NoMemory if keyBufLen is too short. + * Returns kDNSServiceErr_Invalid if index is greater than + * TXTRecordGetCount()-1. + */ + +DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex + ( + uint16_t txtLen, + const void *txtRecord, + uint16_t index, + uint16_t keyBufLen, + char *key, + uint8_t *valueLen, + const void **value + ); + +#ifdef __APPLE_API_PRIVATE + +/* + * Mac OS X specific functionality + * 3rd party clients of this API should not depend on future support or availability of this routine + */ + +/* DNSServiceSetDefaultDomainForUser() + * + * Set the default domain for the caller's UID. Future browse and registration + * calls by this user that do not specify an explicit domain will browse and + * register in this wide-area domain in addition to .local. In addition, this + * domain will be returned as a Browse domain via domain enumeration calls. + * + * + * Parameters: + * + * flags: Pass kDNSServiceFlagsAdd to add a domain for a user. Call without + * this flag set to clear a previously added domain. + * + * domain: The domain to be used for the caller's UID. + * + * return value: Returns kDNSServiceErr_NoError on succeses, otherwise returns + * an error code indicating the error that occurred + */ + +DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser + ( + DNSServiceFlags flags, + const char *domain + ); + +#endif //__APPLE_API_PRIVATE + +#ifdef __cplusplus + } +#endif +#endif /* _DNS_SD_H */ diff --git a/mdns.subproj/dnssd_clientlib.c b/mdns.subproj/dnssd_clientlib.c new file mode 100755 index 0000000..d3c36ad --- /dev/null +++ b/mdns.subproj/dnssd_clientlib.c @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: dnssd_clientlib.c,v $ +Revision 1.3 2004/09/16 23:45:23 majka +Integrated 3775315 and 3765280. + +Revision 1.2.16.1 2004/09/02 19:43:41 ksekar +: Sync dns-sd client files between Libinfo and +mDNSResponder projects + +Revision 1.7 2004/06/26 03:16:34 shersche +clean up warning messages on Win32 platform + +Submitted by: herscher + +Revision 1.6 2004/06/12 01:09:45 cheshire +To be callable from the broadest range of clients on Windows (e.g. Visual Basic, C#, etc.) +API routines have to be declared as "__stdcall", instead of the C default, "__cdecl" + +Revision 1.5 2004/05/25 18:29:33 cheshire +Move DNSServiceConstructFullName() from dnssd_clientstub.c to dnssd_clientlib.c, +so that it's also accessible to dnssd_clientshim.c (single address space) clients. + +Revision 1.4 2004/05/25 17:08:55 cheshire +Fix compiler warning (doesn't make sense for function return type to be const) + +Revision 1.3 2004/05/21 21:41:35 cheshire +Add TXT record building and parsing APIs + +Revision 1.2 2004/05/20 22:22:21 cheshire +Enable code that was bracketed by "#if 0" + +Revision 1.1 2004/03/12 21:30:29 cheshire +Build a System-Context Shared Library from mDNSCore, for the benefit of developers +like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code. + + */ + +#include +#include + +#include "dns_sd.h" + +#if MDNS_BUILDINGSHAREDLIBRARY || MDNS_BUILDINGSTUBLIBRARY +#pragma export on +#endif + +#if defined(_WIN32) +// disable warning "conversion from to uint16_t" +#pragma warning(disable:4244) +#endif + +/********************************************************************************************* + * + * Supporting Functions + * + *********************************************************************************************/ + +#define mdnsIsDigit(X) ((X) >= '0' && (X) <= '9') + +static int DomainEndsInDot(const char *dom) + { + while (dom[0] && dom[1]) + { + if (dom[0] == '\\') // advance past escaped byte sequence + { + if (mdnsIsDigit(dom[1]) && mdnsIsDigit(dom[2]) && mdnsIsDigit(dom[3])) + dom += 4; // If "\ddd" then skip four + else dom += 2; // else if "\x" then skip two + } + else dom++; // else goto next character + } + return (dom[0] == '.'); + } + +static uint8_t *InternalTXTRecordSearch + ( + uint16_t txtLen, + const void *txtRecord, + const char *key, + unsigned long *keylen + ) + { + uint8_t *p = (uint8_t*)txtRecord; + uint8_t *e = p + txtLen; + *keylen = (unsigned long) strlen(key); + while (pbuffer = buffer; + txtRec->buflen = buffer ? bufferLen : (uint16_t)0; + txtRec->datalen = 0; + txtRec->malloced = 0; + } + +void TXTRecordDeallocate(TXTRecordRef *txtRecord) + { + if (txtRec->malloced) free(txtRec->buffer); + } + +DNSServiceErrorType TXTRecordSetValue + ( + TXTRecordRef *txtRecord, + const char *key, + uint8_t valueSize, + const void *value + ) + { + uint8_t *start, *p; + const char *k; + unsigned long keysize, keyvalsize; + + for (k = key; *k; k++) if (*k < 0x20 || *k > 0x7E || *k == '=') return(kDNSServiceErr_Invalid); + keysize = (unsigned long)(k - key); + keyvalsize = 1 + keysize + (value ? (1 + valueSize) : 0); + if (keysize < 1 || keyvalsize > 255) return(kDNSServiceErr_Invalid); + (void)TXTRecordRemoveValue(txtRecord, key); + if (txtRec->datalen + keyvalsize > txtRec->buflen) + { + unsigned char *newbuf; + unsigned long newlen = txtRec->datalen + keyvalsize; + if (newlen > 0xFFFF) return(kDNSServiceErr_Invalid); + newbuf = malloc((size_t)newlen); + if (!newbuf) return(kDNSServiceErr_NoMemory); + memcpy(newbuf, txtRec->buffer, txtRec->datalen); + if (txtRec->malloced) free(txtRec->buffer); + txtRec->buffer = newbuf; + txtRec->buflen = (uint16_t)(newlen); + txtRec->malloced = 1; + } + start = txtRec->buffer + txtRec->datalen; + p = start + 1; + memcpy(p, key, keysize); + p += keysize; + if (value) + { + *p++ = '='; + memcpy(p, value, valueSize); + p += valueSize; + } + *start = (uint8_t)(p - start - 1); + txtRec->datalen += p - start; + return(kDNSServiceErr_NoError); + } + +DNSServiceErrorType TXTRecordRemoveValue + ( + TXTRecordRef *txtRecord, + const char *key + ) + { + unsigned long keylen, itemlen, remainder; + uint8_t *item = InternalTXTRecordSearch(txtRec->datalen, txtRec->buffer, key, &keylen); + if (!item) return(kDNSServiceErr_NoSuchKey); + itemlen = (unsigned long)(1 + item[0]); + remainder = (unsigned long)((txtRec->buffer + txtRec->datalen) - (item + itemlen)); + // Use memmove because memcpy behaviour is undefined for overlapping regions + memmove(item, item + itemlen, remainder); + txtRec->datalen -= itemlen; + return(kDNSServiceErr_NoError); + } + +uint16_t TXTRecordGetLength (const TXTRecordRef *txtRecord) { return(txtRec->datalen); } +const void * TXTRecordGetBytesPtr(const TXTRecordRef *txtRecord) { return(txtRec->buffer); } + +/********************************************************************************************* + * + * TXT Record Parsing Functions + * + *********************************************************************************************/ + +int TXTRecordContainsKey + ( + uint16_t txtLen, + const void *txtRecord, + const char *key + ) + { + unsigned long keylen; + return (InternalTXTRecordSearch(txtLen, txtRecord, key, &keylen) ? 1 : 0); + } + +const void * TXTRecordGetValuePtr + ( + uint16_t txtLen, + const void *txtRecord, + const char *key, + uint8_t *valueLen + ) + { + unsigned long keylen; + uint8_t *item = InternalTXTRecordSearch(txtLen, txtRecord, key, &keylen); + if (!item || item[0] <= keylen) return(NULL); // If key not found, or found with no value, return NULL + *valueLen = (uint8_t)(item[0] - (keylen + 1)); + return (item + 1 + keylen + 1); + } + +uint16_t TXTRecordGetCount + ( + uint16_t txtLen, + const void *txtRecord + ) + { + uint16_t count = 0; + uint8_t *p = (uint8_t*)txtRecord; + uint8_t *e = p + txtLen; + while (pe) ? (uint16_t)0 : count); + } + +DNSServiceErrorType TXTRecordGetItemAtIndex + ( + uint16_t txtLen, + const void *txtRecord, + uint16_t index, + uint16_t keyBufLen, + char *key, + uint8_t *valueLen, + const void **value + ) + { + uint16_t count = 0; + uint8_t *p = (uint8_t*)txtRecord; + uint8_t *e = p + txtLen; + while (p= keyBufLen) return(kDNSServiceErr_NoMemory); + memcpy(key, x, len); + key[len] = 0; + if (x+len Socket-based APIs aren't endian-safe + +Revision 1.16 2004/09/17 20:19:00 majka +Integrated 3804522 + +Revision 1.15.2.1 2004/09/17 20:15:30 ksekar +*** empty log message *** + +Revision 1.15 2004/09/16 23:45:24 majka +Integrated 3775315 and 3765280. + +Revision 1.14.4.1 2004/09/02 19:43:41 ksekar +: Sync dns-sd client files between Libinfo and +mDNSResponder projects + +Revision 1.28 2004/08/11 17:10:04 cheshire +Fix signed/unsigned warnings + +Revision 1.27 2004/08/11 00:54:16 cheshire +Change "hdr->op.request_op" to just "hdr->op" + +Revision 1.26 2004/07/26 06:07:27 shersche +fix bugs when using an error socket to communicate with the daemon + +Revision 1.25 2004/07/26 05:54:02 shersche +DNSServiceProcessResult() returns NoError if socket read returns EWOULDBLOCK + +Revision 1.24 2004/07/20 06:46:21 shersche + fix endless loop in my_read() if recv returns 0 +Bug #: 3730123 + +Revision 1.23 2004/06/29 00:48:38 cheshire +Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; +use an explicit while() loop instead. + +Revision 1.22 2004/06/26 03:16:34 shersche +clean up warning messages on Win32 platform + +Submitted by: herscher + +Revision 1.21 2004/06/18 04:53:56 rpantos +Use platform layer for socket types. Introduce USE_TCP_LOOPBACK. Remove dependency on mDNSClientAPI.h. + +Revision 1.20 2004/06/12 00:50:22 cheshire +Changes for Windows compatibility + +Revision 1.19 2004/05/25 18:29:33 cheshire +Move DNSServiceConstructFullName() from dnssd_clientstub.c to dnssd_clientlib.c, +so that it's also accessible to dnssd_clientshim.c (single address space) clients. + +Revision 1.18 2004/05/18 23:51:27 cheshire +Tidy up all checkin comments to use consistent "" format for bug numbers + +Revision 1.17 2004/05/06 18:42:58 ksekar +General dns_sd.h API cleanup, including the following radars: +: Remove flags with zero value +: Passing in NULL causes a crash. + +Revision 1.16 2004/03/12 22:00:37 cheshire +Added: #include + +Revision 1.15 2004/01/20 18:36:29 ksekar +Propagated Libinfo fix for : SU: +DNSServiceUpdateRecord() doesn't allow you to update the TXT record +into TOT mDNSResponder. + +Revision 1.14 2004/01/19 22:39:17 cheshire +Don't use "MSG_WAITALL"; it makes send() return "Invalid argument" on Linux; +use an explicit while() loop instead. (In any case, this should only make a difference +with non-blocking sockets, which we don't use on the client side right now.) + +Revision 1.13 2004/01/19 21:46:52 cheshire +Fix compiler warning + +Revision 1.12 2003/12/23 20:46:47 ksekar +: sync dnssd files between libinfo & mDNSResponder + +Revision 1.11 2003/12/08 21:11:42 rpantos +Changes necessary to support mDNSResponder on Linux. + +Revision 1.10 2003/10/13 23:50:53 ksekar +Updated dns_sd clientstub files to bring copies in synch with +top-of-tree Libinfo: A memory leak in dnssd_clientstub.c is fixed, +and comments in dns_sd.h are improved. + +Revision 1.9 2003/08/15 21:30:39 cheshire +Bring up to date with LibInfo version + +Revision 1.8 2003/08/13 23:54:52 ksekar +Bringing dnssd_clientstub.c up to date with Libinfo, per radar 3376640 + +Revision 1.7 2003/08/12 19:56:25 cheshire +Update to APSL 2.0 + */ -#include "dnssd_ipc.h" #include +#include +#if defined(_WIN32) +#include +#include +#define sockaddr_mdns sockaddr_in +#define AF_MDNS AF_INET +#else #include +#include +#define sockaddr_mdns sockaddr_un +#define AF_MDNS AF_LOCAL +#endif + +#include "dnssd_ipc.h" + +#if defined(_WIN32) +// disable warning: "'type cast' : from data pointer 'void *' to +// function pointer" +#pragma warning(disable:4055) + +// disable warning: "nonstandard extension, function/data pointer +// conversion in expression" +#pragma warning(disable:4152) +#define sleep(X) Sleep((X) * 1000) + +static int g_initWinsock = 0; +#endif #define CTL_PATH_PREFIX "/tmp/dnssd_clippath." @@ -31,101 +187,337 @@ // last 3 digits of the time (in seconds) and n is the 6-digit microsecond time // general utility functions -static DNSServiceRef connect_to_server(void); -DNSServiceErrorType deliver_request(void *msg, DNSServiceRef sdr, int reuse_sd); -static ipc_msg_hdr *create_hdr(int op, int *len, char **data_start, int reuse_socket); -static int my_read(int sd, char *buf, int len); -static int my_write(int sd, char *buf, int len); -static int domain_ends_in_dot(const char *dom); -// server response handlers -static void handle_query_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *msg); -static void handle_browse_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data); -static void handle_regservice_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data); -static void handle_regrecord_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data); -static void handle_enumeration_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data); -static void handle_resolve_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data); - typedef struct _DNSServiceRef_t { - int sockfd; // connected socket between client and daemon - int op; // request/reply_op_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; + } _DNSServiceRef_t; typedef struct _DNSRecordRef_t { void *app_context; DNSServiceRegisterRecordReply app_callback; DNSRecordRef recref; - int record_index; // index is unique to the ServiceDiscoveryRef + uint32_t record_index; // index is unique to the ServiceDiscoveryRef DNSServiceRef sdr; } _DNSRecordRef_t; - // exported functions -int DNSServiceRefSockFD(DNSServiceRef sdRef) +// 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; + 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 < 10) + 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 sdRef->sockfd; + 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 DNSServiceProcessResult(DNSServiceRef sdRef) +DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef) { ipc_msg_hdr hdr; char *data; - if (!sdRef || sdRef->sockfd < 0 || !sdRef->process_reply) + if (!sdRef || sdRef->sockfd < 0 || !sdRef->process_reply) return kDNSServiceErr_BadReference; - if (my_read(sdRef->sockfd, (void *)&hdr, sizeof(hdr)) < 0) - return kDNSServiceErr_Unknown; + 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) + if (my_read(sdRef->sockfd, data, hdr.datalen) < 0) return kDNSServiceErr_Unknown; sdRef->process_reply(sdRef, &hdr, data); free(data); return kDNSServiceErr_NoError; } - -void DNSServiceRefDeallocate(DNSServiceRef sdRef) +void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef) { if (!sdRef) return; - if (sdRef->sockfd > 0) close(sdRef->sockfd); + 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 DNSServiceResolve +DNSServiceErrorType DNSSD_API DNSServiceResolve ( DNSServiceRef *sdRef, - const DNSServiceFlags flags, - const uint32_t interfaceIndex, + DNSServiceFlags flags, + uint32_t interfaceIndex, const char *name, const char *regtype, const char *domain, - const DNSServiceResolveReply callBack, + DNSServiceResolveReply callBack, void *context ) { char *msg = NULL, *ptr; - int len; + 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); @@ -142,7 +534,7 @@ DNSServiceErrorType DNSServiceResolve 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); @@ -156,7 +548,7 @@ DNSServiceErrorType DNSServiceResolve sdr->app_callback = callBack; sdr->app_context = context; *sdRef = sdr; - + return err; error: @@ -164,53 +556,52 @@ error: if (*sdRef) { free(*sdRef); *sdRef = NULL; } return kDNSServiceErr_Unknown; } - - -static void handle_resolve_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) + +static void handle_query_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) { DNSServiceFlags flags; - char fullname[kDNSServiceMaxDomainName]; - char target[kDNSServiceMaxDomainName]; - uint16_t port, txtlen; - uint32_t ifi; - DNSServiceErrorType err; - char *txtrecord; - - (void)hdr; //unused - + 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); - ifi = get_long(&data); - err = get_error_code(&data); - get_string(&data, fullname, kDNSServiceMaxDomainName); - get_string(&data, target, kDNSServiceMaxDomainName); - port = get_short(&data); - txtlen = get_short(&data); - txtrecord = get_rdata(&data, txtlen); - - ((DNSServiceResolveReply)sdr->app_callback)(sdr, flags, ifi, err, fullname, target, port, txtlen, txtrecord, sdr->app_context); - } - - + 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 DNSServiceQueryRecord +DNSServiceErrorType DNSSD_API DNSServiceQueryRecord ( DNSServiceRef *sdRef, - const DNSServiceFlags flags, - const uint32_t interfaceIndex, + DNSServiceFlags flags, + uint32_t interfaceIndex, const char *name, - const uint16_t rrtype, - const uint16_t rrclass, - const DNSServiceQueryRecordReply callBack, + uint16_t rrtype, + uint16_t rrclass, + DNSServiceQueryRecordReply callBack, void *context ) { char *msg = NULL, *ptr; - int len; + size_t len; ipc_msg_hdr *hdr; DNSServiceRef sdr; DNSServiceErrorType err; - + if (!sdRef) return kDNSServiceErr_BadParam; *sdRef = NULL; @@ -254,45 +645,39 @@ error: return kDNSServiceErr_Unknown; } - -static void handle_query_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) +static void handle_browse_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) { - DNSServiceFlags flags; - uint32_t interfaceIndex, ttl; - DNSServiceErrorType errorCode; - char name[256]; - uint16_t rrtype, rrclass, rdlen; - char *rdata; - (void)hdr;//Unused + 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); - (get_string(&data, name, 256) < 0); - rrtype = get_short(&data); - rrclass = get_short(&data); - rdlen = get_short(&data); - rdata = get_rdata(&data, rdlen); - ttl = get_long(&data); - if (!rdata) return; - ((DNSServiceQueryRecordReply)sdr->app_callback)(sdr, flags, interfaceIndex, errorCode, name, rrtype, rrclass, - rdlen, rdata, ttl, sdr->app_context); - return; + 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 DNSServiceBrowse +DNSServiceErrorType DNSSD_API DNSServiceBrowse ( DNSServiceRef *sdRef, - const DNSServiceFlags flags, - const uint32_t interfaceIndex, + DNSServiceFlags flags, + uint32_t interfaceIndex, const char *regtype, const char *domain, - const DNSServiceBrowseReply callBack, + DNSServiceBrowseReply callBack, void *context ) { char *msg = NULL, *ptr; - int len; + size_t len; ipc_msg_hdr *hdr; DNSServiceRef sdr; DNSServiceErrorType err; @@ -336,48 +721,71 @@ error: 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_browse_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) +static void handle_regservice_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) { - DNSServiceFlags flags; - uint32_t interfaceIndex; - DNSServiceErrorType errorCode; - char replyName[256], replyType[256], replyDomain[256]; + 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); - get_string(&data, replyName, 256); - get_string(&data, replyType, 256); - get_string(&data, replyDomain, 256); - ((DNSServiceBrowseReply)sdr->app_callback)(sdr, flags, interfaceIndex, errorCode, replyName, replyType, replyDomain, sdr->app_context); + 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 DNSServiceRegister +DNSServiceErrorType DNSSD_API DNSServiceRegister ( DNSServiceRef *sdRef, - const DNSServiceFlags flags, - const uint32_t interfaceIndex, - const char *name, - const char *regtype, - const char *domain, - const char *host, - const uint16_t port, - const uint16_t txtLen, - const void *txtRecord, - const DNSServiceRegisterReply callBack, - void *context + 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; - int len; + 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; @@ -386,8 +794,8 @@ DNSServiceErrorType DNSServiceRegister if (!regtype) return kDNSServiceErr_BadParam; if (!domain) domain = ""; if (!host) host = ""; - if (!txtRecord) (char *)txtRecord = ""; - + if (!txtRecord) txtRecord = (void*)""; + // auto-name must also have auto-rename if (!name[0] && (flags & kDNSServiceFlagsNoAutoRename)) return kDNSServiceErr_BadParam; @@ -411,7 +819,8 @@ DNSServiceErrorType DNSServiceRegister put_string(regtype, &ptr); put_string(domain, &ptr); put_string(host, &ptr); - put_short(port, &ptr); + *ptr++ = port.b[0]; + *ptr++ = port.b[1]; put_short(txtLen, &ptr); put_rdata(txtLen, txtRecord, &ptr); @@ -423,7 +832,7 @@ DNSServiceErrorType DNSServiceRegister DNSServiceRefDeallocate(sdr); return err; } - + sdr->op = reg_service_request; sdr->process_reply = callBack ? handle_regservice_response : NULL; sdr->app_callback = callBack; @@ -431,51 +840,52 @@ DNSServiceErrorType DNSServiceRegister *sdRef = sdr; return err; - + error: if (msg) free(msg); if (*sdRef) { free(*sdRef); *sdRef = NULL; } return kDNSServiceErr_Unknown; } - -static void handle_regservice_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) +static void handle_enumeration_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) { DNSServiceFlags flags; uint32_t interfaceIndex; - DNSServiceErrorType errorCode; - char name[256], regtype[256], domain[256]; + DNSServiceErrorType err; + char domain[kDNSServiceMaxDomainName]; + int str_error = 0; (void)hdr;//Unused flags = get_flags(&data); interfaceIndex = get_long(&data); - errorCode = get_error_code(&data); - get_string(&data, name, 256); - get_string(&data, regtype, 256); - get_string(&data, domain, 256); - ((DNSServiceRegisterReply)sdr->app_callback)(sdr, flags, errorCode, name, regtype, domain, sdr->app_context); + 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 DNSServiceEnumerateDomains +DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains ( DNSServiceRef *sdRef, - const DNSServiceFlags flags, - const uint32_t interfaceIndex, - const DNSServiceDomainEnumReply callBack, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceDomainEnumReply callBack, void *context ) { char *msg = NULL, *ptr; - int len; + 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(DNSServiceFlags); len += sizeof(uint32_t); hdr = create_hdr(enumeration_request, &len, &ptr, 1); @@ -507,24 +917,26 @@ error: return kDNSServiceErr_Unknown; } - -static void handle_enumeration_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) +static void handle_regrecord_response(DNSServiceRef sdr, ipc_msg_hdr *hdr, char *data) { DNSServiceFlags flags; uint32_t interfaceIndex; - DNSServiceErrorType err; - char domain[256]; - (void)hdr;//Unused + 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); - err = get_error_code(&data); - get_string(&data, domain, 256); - ((DNSServiceDomainEnumReply)sdr->app_callback)(sdr, flags, interfaceIndex, err, domain, sdr->app_context); - } + errorCode = get_error_code(&data); + rref->app_callback(rref->sdr, rref, flags, errorCode, rref->app_context); + } -DNSServiceErrorType DNSServiceCreateConnection(DNSServiceRef *sdRef) +DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef) { if (!sdRef) return kDNSServiceErr_BadParam; *sdRef = connect_to_server(); @@ -535,54 +947,36 @@ DNSServiceErrorType DNSServiceCreateConnection(DNSServiceRef *sdRef) return 0; } - - -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 DNSServiceRegisterRecord +DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord ( - const DNSServiceRef sdRef, - DNSRecordRef *RecordRef, - const DNSServiceFlags flags, - const uint32_t interfaceIndex, + DNSServiceRef sdRef, + DNSRecordRef *RecordRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, const char *fullname, - const uint16_t rrtype, - const uint16_t rrclass, - const uint16_t rdlen, + uint16_t rrtype, + uint16_t rrclass, + uint16_t rdlen, const void *rdata, - const uint32_t ttl, - const DNSServiceRegisterRecordReply callBack, + uint32_t ttl, + DNSServiceRegisterRecordReply callBack, void *context ) { char *msg = NULL, *ptr; - int len; + size_t len; ipc_msg_hdr *hdr = NULL; DNSServiceRef tmp = NULL; DNSRecordRef rref = NULL; - - if (!sdRef || sdRef->op != connection || sdRef->sockfd < 0) + 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 = sizeof(DNSServiceFlags); len += 2 * sizeof(uint32_t); // interfaceIndex, ttl len += 3 * sizeof(uint16_t); // rrtype, rrclass, rdlen len += strlen(fullname) + 1; @@ -608,8 +1002,8 @@ DNSServiceErrorType DNSServiceRegisterRecord rref->sdr = sdRef; *RecordRef = rref; hdr->client_context.context = rref; - hdr->reg_index = rref->record_index; - + hdr->reg_index = rref->record_index; + return deliver_request(msg, sdRef, 0); error: @@ -620,26 +1014,26 @@ error: } //sdRef returned by DNSServiceRegister() -DNSServiceErrorType DNSServiceAddRecord +DNSServiceErrorType DNSSD_API DNSServiceAddRecord ( - const DNSServiceRef sdRef, + DNSServiceRef sdRef, DNSRecordRef *RecordRef, - const DNSServiceFlags flags, - const uint16_t rrtype, - const uint16_t rdlen, + DNSServiceFlags flags, + uint16_t rrtype, + uint16_t rdlen, const void *rdata, - const uint32_t ttl + uint32_t ttl ) { ipc_msg_hdr *hdr; - int len = 0; + size_t len = 0; char *ptr; DNSRecordRef rref; - if (!sdRef || (sdRef->op != reg_service_request) || !RecordRef) + 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); @@ -661,7 +1055,7 @@ DNSServiceErrorType DNSServiceAddRecord rref->sdr = sdRef; *RecordRef = rref; hdr->client_context.context = rref; - hdr->reg_index = rref->record_index; + hdr->reg_index = rref->record_index; return deliver_request((char *)hdr, sdRef, 0); error: @@ -670,26 +1064,24 @@ error: if (*RecordRef) *RecordRef = NULL; return kDNSServiceErr_Unknown; } - //DNSRecordRef returned by DNSServiceRegisterRecord or DNSServiceAddRecord -DNSServiceErrorType DNSServiceUpdateRecord +DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord ( - const DNSServiceRef sdRef, + DNSServiceRef sdRef, DNSRecordRef RecordRef, - const DNSServiceFlags flags, - const uint16_t rdlen, + DNSServiceFlags flags, + uint16_t rdlen, const void *rdata, - const uint32_t ttl + uint32_t ttl ) { ipc_msg_hdr *hdr; - int len = 0; + size_t len = 0; char *ptr; - if (!sdRef) - return kDNSServiceErr_BadReference; - + if (!sdRef) return kDNSServiceErr_BadReference; + len += sizeof(uint16_t); len += rdlen; len += sizeof(uint32_t); @@ -704,24 +1096,22 @@ DNSServiceErrorType DNSServiceUpdateRecord put_long(ttl, &ptr); return deliver_request((char *)hdr, sdRef, 0); } - - -DNSServiceErrorType DNSServiceRemoveRecord +DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord ( - const DNSServiceRef sdRef, - const DNSRecordRef RecordRef, - const DNSServiceFlags flags + DNSServiceRef sdRef, + DNSRecordRef RecordRef, + DNSServiceFlags flags ) { ipc_msg_hdr *hdr; - int len = 0; + size_t len = 0; char *ptr; DNSServiceErrorType err; - if (!sdRef || !RecordRef || !sdRef->max_index) + 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; @@ -732,20 +1122,19 @@ DNSServiceErrorType DNSServiceRemoveRecord return err; } - -void DNSServiceReconfirmRecord +void DNSSD_API DNSServiceReconfirmRecord ( - const DNSServiceFlags flags, - const uint32_t interfaceIndex, + DNSServiceFlags flags, + uint32_t interfaceIndex, const char *fullname, - const uint16_t rrtype, - const uint16_t rrclass, - const uint16_t rdlen, + uint16_t rrtype, + uint16_t rrclass, + uint16_t rdlen, const void *rdata ) { char *ptr; - int len; + size_t len; ipc_msg_hdr *hdr; DNSServiceRef tmp; @@ -766,224 +1155,9 @@ void DNSServiceReconfirmRecord put_short(rrclass, &ptr); put_short(rdlen, &ptr); put_rdata(rdlen, rdata, &ptr); - my_write(tmp->sockfd, (char *)hdr, len); + ConvertHeaderBytes(hdr); + my_write(tmp->sockfd, (char *)hdr, (int) len); + free(hdr); DNSServiceRefDeallocate(tmp); } - - -int DNSServiceConstructFullName - ( - char *fullName, - const char *service, /* may be NULL */ - const char *regtype, - const char *domain - ) - { - int len; - u_char c; - char *fn = fullName; - const char *s = service; - const char *r = regtype; - const char *d = domain; - - if (service) - { - while(*s) - { - c = *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 = (u_char)('0' + (c % 10)); - } - *fn++ = c; - } - *fn++ = '.'; - } - if (!regtype) return -1; - len = strlen(regtype); - if (domain_ends_in_dot(regtype)) len--; - if (len < 4) return -1; // regtype must end in _udp or _tcp - if (strncmp((regtype + len - 4), "_tcp", 4) && strncmp((regtype + len - 4), "_udp", 4)) return -1; - while(*r) - *fn++ = *r++; - if (!domain_ends_in_dot(regtype)) *fn++ = '.'; - - if (!domain) return -1; - len = strlen(domain); - if (!len) return -1; - while(*d) - *fn++ = *d++; - if (!domain_ends_in_dot(domain)) *fn++ = '.'; - *fn = '\0'; - return 0; - } - -static int domain_ends_in_dot(const char *dom) - { - while(*dom && *(dom + 1)) - { - if (*dom == '\\') // advance past escaped byte sequence - { - if (*(dom + 1) >= '0' && *(dom + 1) <= '9') dom += 4; - else dom += 2; - } - else dom++; // else read one character - } - return (*dom == '.'); - } - - - - // return a connected service ref (deallocate with DNSServiceRefDeallocate) -static DNSServiceRef connect_to_server(void) - { - struct sockaddr_un saddr; - DNSServiceRef sdr; - - sdr = malloc(sizeof(_DNSServiceRef_t)); - if (!sdr) return NULL; - - if ((sdr->sockfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) - { - free(sdr); - return NULL; - } - - saddr.sun_family = AF_LOCAL; - strcpy(saddr.sun_path, MDNS_UDS_SERVERPATH); - if (connect(sdr->sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) - { - free(sdr); - return NULL; - } - return sdr; - } - - - - -int my_write(int sd, char *buf, int len) - { - if (send(sd, buf, len, MSG_WAITALL) != len) return -1; - return 0; - } - - -// read len bytes. return 0 on success, -1 on error -int my_read(int sd, char *buf, int len) - { - if (recv(sd, buf, len, MSG_WAITALL) != len) return -1; - return 0; - } - - -DNSServiceErrorType deliver_request(void *msg, DNSServiceRef sdr, int reuse_sd) - { - ipc_msg_hdr *hdr = msg; - mode_t mask; - struct sockaddr_un caddr, daddr; // (client and daemon address structs) - char *path = NULL; - int listenfd = -1, errsd = -1, len; - DNSServiceErrorType err = kDNSServiceErr_Unknown; - - if (!hdr || sdr->sockfd < 0) return kDNSServiceErr_Unknown; - - if (!reuse_sd) - { - // setup temporary error socket - if ((listenfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) - goto cleanup; - - bzero(&caddr, sizeof(caddr)); - caddr.sun_family = AF_LOCAL; - caddr.sun_len = sizeof(struct sockaddr_un); - path = (char *)msg + sizeof(ipc_msg_hdr); - strcpy(caddr.sun_path, path); - mask = umask(0); - if (bind(listenfd, (struct sockaddr *)&caddr, sizeof(caddr)) < 0) - { - umask(mask); - goto cleanup; - } - umask(mask); - listen(listenfd, 1); - } - - if (my_write(sdr->sockfd, msg, hdr->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; - } - - len = recv(errsd, &err, sizeof(err), MSG_WAITALL); - if (len != sizeof(err)) - { - err = kDNSServiceErr_Unknown; - } -cleanup: - if (!reuse_sd && listenfd > 0) close(listenfd); - if (!reuse_sd && errsd > 0) close(errsd); - if (!reuse_sd && path) unlink(path); - if (msg) free(msg); - return err; - } - - - -/* 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(int op, int *len, char **data_start, int reuse_socket) - { - char *msg = NULL; - ipc_msg_hdr *hdr; - int datalen; - char ctrl_path[256]; - struct timeval time; - - if (!reuse_socket) - { - if (gettimeofday(&time, NULL) < 0) return NULL; - sprintf(ctrl_path, "%s%d-%.3x-%.6u", CTL_PATH_PREFIX, (int)getpid(), - time.tv_sec & 0xFFF, time.tv_usec); - - *len += strlen(ctrl_path) + 1; - } - - - datalen = *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.request_op = op; - if (reuse_socket) hdr->flags |= IPC_FLAGS_REUSE_SOCKET; - *data_start = msg + sizeof(ipc_msg_hdr); - if (!reuse_socket) put_string(ctrl_path, data_start); - return hdr; - } diff --git a/mdns.subproj/dnssd_ipc.c b/mdns.subproj/dnssd_ipc.c index 1906659..0854ada 100644 --- a/mdns.subproj/dnssd_ipc.c +++ b/mdns.subproj/dnssd_ipc.c @@ -2,129 +2,128 @@ * Copyright (c) 2003 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.2 (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 + * + * 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 OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * + * 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@ - */ - -#include "dnssd_ipc.h" + Change History (most recent first): -void put_flags(const DNSServiceFlags flags, char **ptr) - { - memcpy(*ptr, &flags, sizeof(DNSServiceFlags)); - *ptr += sizeof(flags); - } +$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 -DNSServiceFlags get_flags(char **ptr) - { - DNSServiceFlags flags; - - flags = *(DNSServiceFlags *)*ptr; - *ptr += sizeof(DNSServiceFlags); - return flags; - } +Revision 1.9.4.1 2004/09/20 21:54:33 ksekar + Socket-based APIs aren't endian-safe -void put_long(const uint32_t l, char **ptr) - { - - *(uint32_t *)(*ptr) = l; - *ptr += sizeof(uint32_t); - } - -uint32_t get_long(char **ptr) - { - uint32_t l; - - l = *(uint32_t *)(*ptr); - *ptr += sizeof(uint32_t); - return l; - } - -void put_error_code(const DNSServiceErrorType error, char **ptr) - { - memcpy(*ptr, &error, sizeof(error)); - *ptr += sizeof(DNSServiceErrorType); - } - -DNSServiceErrorType get_error_code(char **ptr) - { - DNSServiceErrorType error; - - error = *(DNSServiceErrorType *)(*ptr); - *ptr += sizeof(DNSServiceErrorType); - return error; - } - -void put_short(const uint16_t s, char **ptr) - { - *(uint16_t *)(*ptr) = s; - *ptr += sizeof(uint16_t); - } +Revision 1.9 2004/09/16 23:45:24 majka +Integrated 3775315 and 3765280. -uint16_t get_short(char **ptr) - { - uint16_t s; +Revision 1.8.4.1 2004/09/02 19:43:41 ksekar +: Sync dns-sd client files between Libinfo and +mDNSResponder projects - s = *(uint16_t *)(*ptr); - *ptr += sizeof(uint16_t); - return s; - } +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 -int put_string(const char *str, char **ptr) - { - if (!str) str = ""; - strcpy(*ptr, str); - *ptr += strlen(str) + 1; - return 0; - } - -// !!!KRS we don't properly handle the case where the string is longer than the buffer!!! -int get_string(char **ptr, char *buffer, int buflen) - { - int overrun; - - overrun = (int)strlen(*ptr) < buflen ? 0 : -1; - strncpy(buffer, *ptr, buflen - 1); - buffer[buflen - 1] = '\0'; - *ptr += strlen(buffer) + 1; - return overrun; - } +Revision 1.9 2004/05/18 23:51:27 cheshire +Tidy up all checkin comments to use consistent "" format for bug numbers -void put_rdata(const int rdlen, const char *rdata, char **ptr) - { - memcpy(*ptr, rdata, rdlen); - *ptr += rdlen; - } +Revision 1.8 2003/11/05 22:44:57 ksekar +: No bounds checking when reading data from client +Reviewed by: Stuart Cheshire -char *get_rdata(char **ptr, int rdlen) - { - char *rd; - - rd = *ptr; - *ptr += rdlen; - return rd; - } +Revision 1.7 2003/08/12 19:56:25 cheshire +Update to APSL 2.0 + */ +#include "dnssd_ipc.h" +void put_long(const uint32_t l, char **ptr) + { + (*ptr)[0] = (char)((l >> 24) & 0xFF); + (*ptr)[1] = (char)((l >> 16) & 0xFF); + (*ptr)[2] = (char)((l >> 8) & 0xFF); + (*ptr)[3] = (char)((l ) & 0xFF); + *ptr += sizeof(uint32_t); + } +uint32_t get_long(char **ptr) + { + uint8_t *p = (uint8_t*) *ptr; + *ptr += sizeof(uint32_t); + return((uint32_t) ((uint32_t)p[0] << 24 | (uint32_t)p[1] << 16 | (uint32_t)p[2] << 8 | p[3])); + } + +void put_short(uint16_t s, char **ptr) + { + (*ptr)[0] = (char)((s >> 8) & 0xFF); + (*ptr)[1] = (char)((s ) & 0xFF); + *ptr += sizeof(uint16_t); + } +uint16_t get_short(char **ptr) + { + uint8_t *p = (uint8_t*) *ptr; + *ptr += sizeof(uint16_t); + return((uint16_t) ((uint16_t)p[0] << 8 | p[1])); + } +int put_string(const char *str, char **ptr) + { + if (!str) str = ""; + strcpy(*ptr, str); + *ptr += strlen(str) + 1; + return 0; + } +int get_string(char **ptr, char *buffer, int buflen) + { + int overrun = (int)strlen(*ptr) < buflen ? 0 : -1; + strncpy(buffer, *ptr, buflen - 1); + buffer[buflen - 1] = '\0'; + *ptr += strlen(buffer) + 1; + return overrun; + } +void put_rdata(const int rdlen, const char *rdata, char **ptr) + { + memcpy(*ptr, rdata, rdlen); + *ptr += rdlen; + } +char *get_rdata(char **ptr, int rdlen) + { + char *rd = *ptr; + *ptr += rdlen; + return rd; + } + +void ConvertHeaderBytes(ipc_msg_hdr *hdr) + { + hdr->version = htonl(hdr->version); + hdr->datalen = htonl(hdr->datalen); + hdr->flags = htonl(hdr->flags); + hdr->op = htonl(hdr->op ); + hdr->reg_index = htonl(hdr->reg_index); + } diff --git a/mdns.subproj/dnssd_ipc.h b/mdns.subproj/dnssd_ipc.h index 09e8149..ccdcd25 100644 --- a/mdns.subproj/dnssd_ipc.h +++ b/mdns.subproj/dnssd_ipc.h @@ -2,45 +2,135 @@ * Copyright (c) 2003 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.2 (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 + * + * 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 OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * * @APPLE_LICENSE_HEADER_END@ - */ + Change History (most recent first): + +$Log: dnssd_ipc.h,v $ +Revision 1.9 2004/09/22 20:05:38 majka +Integrated +3725573 - Need Error Codes for handling Lighthouse setup failure on NAT +3805822 - Socket-based APIs aren't endian-safe +3806739 - DNSServiceSetDefaultDomainForUser header comments incorrect + +Revision 1.8.2.1 2004/09/20 21:54:33 ksekar + Socket-based APIs aren't endian-safe + +Revision 1.8 2004/09/17 20:19:01 majka +Integrated 3804522 + +Revision 1.7.2.1 2004/09/17 20:15:30 ksekar +*** empty log message *** + +Revision 1.7 2004/09/16 23:45:24 majka +Integrated 3775315 and 3765280. + +Revision 1.6.4.1 2004/09/02 19:43:41 ksekar +: Sync dns-sd client files between Libinfo and +mDNSResponder projects + +Revision 1.11 2004/08/10 06:24:56 cheshire +Use types with precisely defined sizes for 'op' and 'reg_index', for better +compatibility if the daemon and the client stub are built using different compilers + +Revision 1.10 2004/07/07 17:39:25 shersche +Change MDNS_SERVERPORT from 5533 to 5354. +Revision 1.9 2004/06/25 00:26:27 rpantos +Changes to fix the Posix build on Solaris. + +Revision 1.8 2004/06/18 04:56:51 rpantos +Add layer for platform code + +Revision 1.7 2004/06/12 01:08:14 cheshire +Changes for Windows compatibility + +Revision 1.6 2003/08/12 19:56:25 cheshire +Update to APSL 2.0 + + */ #ifndef DNSSD_IPC_H #define DNSSD_IPC_H #include "dns_sd.h" -#include -#include -#include -#include -#include -#include -#include -#define UDSDEBUG // verbose debug output + +// +// Common cross platform services +// +#if defined(WIN32) +# include +# define dnssd_InvalidSocket INVALID_SOCKET +# define dnssd_EWOULDBLOCK WSAEWOULDBLOCK +# define dnssd_EINTR WSAEINTR +# define MSG_WAITALL 0 +# define dnssd_sock_t SOCKET +# define dnssd_sockbuf_t +# define dnssd_close(sock) closesocket(sock) +# define dnssd_errno() WSAGetLastError() +# define ssize_t int +# define getpid _getpid +#else +# include +# include +# include +# include +# include +# include +# include +# include +# include +# define dnssd_InvalidSocket -1 +# define dnssd_EWOULDBLOCK EWOULDBLOCK +# define dnssd_EINTR EINTR +# define dnssd_EPIPE EPIPE +# define dnssd_sock_t int +# define dnssd_close(sock) close(sock) +# define dnssd_errno() errno +#endif + +#if defined(USE_TCP_LOOPBACK) +# define AF_DNSSD AF_INET +# define MDNS_TCP_SERVERADDR "127.0.0.1" +# define MDNS_TCP_SERVERPORT 5354 +# define LISTENQ 5 +# define dnssd_sockaddr_t struct sockaddr_in +#else +# define AF_DNSSD AF_LOCAL +# define MDNS_UDS_SERVERPATH "/var/run/mDNSResponder" +# define LISTENQ 100 + // longest legal control path length +# define MAX_CTLPATH 256 +# define dnssd_sockaddr_t struct sockaddr_un +#endif + + +//#define UDSDEBUG // verbose debug output + +// Compatibility workaround +#ifndef AF_LOCAL +#define AF_LOCAL AF_UNIX +#endif // General UDS constants -#define MDNS_UDS_SERVERPATH "/var/run/mDNSResponder" -#define LISTENQ 100 -#define TXT_RECORD_INDEX -1 // record index for default text record -#define MAX_CTLPATH 256 // longest legal control path length +#define TXT_RECORD_INDEX ((uint32_t)(-1)) // record index for default text record // IPC data encoding constants and types #define VERSION 1 @@ -48,7 +138,6 @@ #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() @@ -61,7 +150,8 @@ typedef enum query_request, reconfirm_record_request, add_record_request, - update_record_request + update_record_request, + setdomain_request } request_op_t; typedef enum @@ -74,10 +164,8 @@ typedef enum 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 @@ -95,62 +183,43 @@ typedef union uint32_t ptr64[2]; } client_context_t; - typedef struct ipc_msg_hdr_struct { uint32_t version; uint32_t datalen; uint32_t flags; - union - { - request_op_t request_op; - reply_op_t reply_op; - } op; + 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 - int reg_index; // identifier for a record registered via DNSServiceRegisterRecord() on a + 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; - - - + } 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. +// 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_flags(const DNSServiceFlags flags, char **ptr); -DNSServiceFlags get_flags(char **ptr); - void put_long(const uint32_t l, char **ptr); uint32_t get_long(char **ptr); -void put_error_code(const DNSServiceErrorType, char **ptr); -DNSServiceErrorType get_error_code(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 - +char *get_rdata(char **ptr, int rdlen); // return value is rdata pointed to by *ptr - // rdata is not copied from buffer. -void put_short(uint16_t s, char **ptr); -uint16_t get_short(char **ptr); - - +void ConvertHeaderBytes(ipc_msg_hdr *hdr); #endif // DNSSD_IPC_H - - - - - - - - - - - diff --git a/membership.subproj/Makefile b/membership.subproj/Makefile new file mode 100644 index 0000000..2544a39 --- /dev/null +++ b/membership.subproj/Makefile @@ -0,0 +1,48 @@ +# +# Generated by the NeXT 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 = membership + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Component + +HFILES = membership.h membershipPriv.h memberd_defines.h ntsid.h + +CFILES = membership.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble memberd.defs + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = subproj.make +NEXTSTEP_INSTALLDIR = /Local/Developer/System +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + +PUBLIC_HEADERS = membership.h ntsid.h + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/membership.subproj/Makefile.postamble b/membership.subproj/Makefile.postamble new file mode 100644 index 0000000..e69de29 diff --git a/membership.subproj/Makefile.preamble b/membership.subproj/Makefile.preamble new file mode 100644 index 0000000..6d8c68a --- /dev/null +++ b/membership.subproj/Makefile.preamble @@ -0,0 +1,17 @@ +OTHER_PRIVATE_HEADERS = membershipPriv.h + +# Additional flags (MiG generated files) +DEFSFILES = memberd.defs +OTHER_OFILES = memberdUser.o + +# private headers +INTERNAL_HDRS = memberd.defs memberd.h + +BEFORE_INSTALLHDRS += $(SFILE_DIR) $(INTERNAL_HDRS) +# AFTER_INSTALLHDRS += mdns_hdrs +PRIVATE_HEADER_DIR = /usr/local/include + + +# for building 64-bit +# Libinfo need to build with gcc-3.5 and 3-way fat +NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER) diff --git a/membership.subproj/PB.project b/membership.subproj/PB.project new file mode 100644 index 0000000..9fafc15 --- /dev/null +++ b/membership.subproj/PB.project @@ -0,0 +1,36 @@ +{ + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + H_FILES = ( + membership.h, + membershipPriv.h, + memberd_defines.h, + ntsid.h + ); + OTHER_LINKED = (membership.c); + OTHER_SOURCES = ( + Makefile.preamble, + Makefile, + Makefile.postamble, + memberd.defs + ); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (membership.h, ntsid.h); + }; + LANGUAGE = English; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /Local/Developer/System; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = lookup; + PROJECTTYPE = Component; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/membership.subproj/memberd.defs b/membership.subproj/memberd.defs new file mode 100644 index 0000000..9f98bac --- /dev/null +++ b/membership.subproj/memberd.defs @@ -0,0 +1,66 @@ +/* + * 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@ + */ + + +subsystem memberd 8000; + +serverprefix Server; + +#include +import "memberd_defines.h"; + +type kauth_identity_extlookup = struct [50] of integer_t; +type guid_t = struct [4] of uint32_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); + +routine _mbr_GetStats( + server: mach_port_t; + out stats: StatBlock); + +routine _mbr_ClearStats( server: mach_port_t ); + +routine _mbr_MapName( + server: mach_port_t; + in isUser: uint8_t; + in name: string; + out guid: guid_t ); + +routine _mbr_GetGroups( + server: mach_port_t; + in uid: uint32_t; + out numGroups: uint32_t; + out gids: GIDArray ); + +routine _mbr_ClearCache( server: mach_port_t ); + +routine _mbr_DumpState( + server: mach_port_t; + in logOnly: uint8_t ); diff --git a/membership.subproj/memberd_defines.h b/membership.subproj/memberd_defines.h new file mode 100644 index 0000000..6fbb468 --- /dev/null +++ b/membership.subproj/memberd_defines.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef USER_API_DEFINES +#define USER_API_DEFINES +#import +#import + +typedef struct kauth_identity_extlookup kauth_identity_extlookup; +typedef char* string; + +typedef struct StatBlock +{ + uint32_t fTotalUpTime; + uint32_t fTotalCallsHandled; + uint32_t fAverageuSecPerCall; + uint32_t fCacheHits; + uint32_t fCacheMisses; + uint32_t fTotalRecordLookups; + uint32_t fNumFailedRecordLookups; + uint32_t fAverageuSecPerRecordLookup; + uint32_t fTotalMembershipSearches; + uint32_t fAverageuSecPerMembershipSearch; + uint32_t fTotalLegacySearches; + uint32_t fAverageuSecPerLegacySearch; + uint32_t fTotalGUIDMemberSearches; + uint32_t fAverageuSecPerGUIDMemberSearch; + uint32_t fTotalNestedMemberSearches; + uint32_t fAverageuSecPerNestedMemberSearch; +} StatBlock; + +typedef uint32_t GIDArray[16]; + +#endif \ No newline at end of file diff --git a/membership.subproj/membership.c b/membership.subproj/membership.c new file mode 100644 index 0000000..223aeef --- /dev/null +++ b/membership.subproj/membership.c @@ -0,0 +1,452 @@ +/* + * 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@ + */ + +#include "membership.h" +#include "membershipPriv.h" +#include "memberd.h" + +#include +#include +#include +#include + +static mach_port_t GetServerPort() +{ + kern_return_t result; + static mach_port_t bsPort = 0; + static mach_port_t fServerPort = 0; + + if (bsPort == 0) + { + result = task_get_bootstrap_port( mach_task_self(), &bsPort ); + result = bootstrap_look_up( bsPort, "com.apple.memberd", &fServerPort ); + +// if the port lookup failed, the rpc will fail and we will return EIO +// if (result != MACH_MSG_SUCCESS) +// { +// printf("Got error %d on lookup (is memberd running?)\n", result); +// } + } + + return fServerPort; +} + +int mbr_uid_to_uuid(uid_t id, uuid_t uu) +{ + struct kauth_identity_extlookup request; + int result = 0; + + request.el_flags = KAUTH_EXTLOOKUP_VALID_UID | KAUTH_EXTLOOKUP_WANT_UGUID; + request.el_uid = id; + result = _mbr_DoMembershipCall(GetServerPort(), &request); + if (result != KERN_SUCCESS) + return EIO; + + if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_UGUID) != 0) + memcpy(uu, &request.el_uguid, sizeof(guid_t)); + else + result = ENOENT; + + return result; +} + +int mbr_gid_to_uuid(gid_t id, uuid_t uu) +{ + struct kauth_identity_extlookup request; + kern_return_t result; + int error = 0; + + request.el_flags = KAUTH_EXTLOOKUP_VALID_GID | KAUTH_EXTLOOKUP_WANT_GGUID; + request.el_gid = id; + result = _mbr_DoMembershipCall(GetServerPort(), &request); + if (result != KERN_SUCCESS) + return EIO; + + if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GGUID) != 0) + memcpy(uu, &request.el_gguid, sizeof(guid_t)); + else + error = ENOENT; + + return error; +} + +int mbr_uuid_to_id( const uuid_t uu, uid_t* id, int* id_type) +{ + struct kauth_identity_extlookup request; + kern_return_t result; + int error = 0; + + 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); + if (result != KERN_SUCCESS) + return EIO; + + if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_UID) != 0) + { + *id = request.el_uid; + *id_type = ID_TYPE_UID; + } + else if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GID) != 0) + { + *id = request.el_gid; + *id_type = ID_TYPE_GID; + } + else + error = ENOENT; + + return error; +} + +int mbr_sid_to_uuid(const nt_sid_t* sid, uuid_t uu) +{ + struct kauth_identity_extlookup request; + kern_return_t result; + int error = 0; + + 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); + if (result != KERN_SUCCESS) + return EIO; + + if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GGUID) != 0) + memcpy(uu, &request.el_gguid, sizeof(guid_t)); + else + error = ENOENT; + + return error; +} + +int mbr_uuid_to_sid(const uuid_t uu, nt_sid_t* sid) +{ + struct kauth_identity_extlookup request; + kern_return_t result; + int error = 0; + + request.el_flags = KAUTH_EXTLOOKUP_VALID_GGUID | KAUTH_EXTLOOKUP_WANT_GSID; + memcpy(&request.el_gguid, uu, sizeof(guid_t)); + result = _mbr_DoMembershipCall(GetServerPort(), &request); + if (result != KERN_SUCCESS) + return EIO; + + if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GSID) != 0) + memcpy(sid, &request.el_gsid, sizeof(nt_sid_t)); + else + error = ENOENT; + + return error; +} + +int mbr_check_membership(uuid_t user, uuid_t group, int* ismember) +{ + struct kauth_identity_extlookup request; + kern_return_t result; + int error = 0; + + 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); + if (result != KERN_SUCCESS) + return EIO; + + if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) != 0) + { + *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0); + } + else + error = ENOENT; + + return error; +} + +int mbr_check_membership_by_id(uuid_t user, gid_t group, int* ismember) +{ + struct kauth_identity_extlookup request; + kern_return_t result; + int error = 0; + + 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); + if (result != KERN_SUCCESS) + return EIO; + + if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) != 0) + { + *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0); + } + else + error = ENOENT; + + return error; +} + +int mbr_reset_cache() +{ + kern_return_t result; + result = _mbr_ClearCache(GetServerPort()); + if (result != KERN_SUCCESS) + return EIO; + return 0; +} + +int mbr_user_name_to_uuid(const char* name, uuid_t uu) +{ + kern_return_t result; + + if (strlen(name) > 255) + return EINVAL; + + result = _mbr_MapName(GetServerPort(), 1, (char*)name, (guid_t*)uu); + + if (result == KERN_FAILURE) + return ENOENT; + else if (result != KERN_SUCCESS) + return EIO; + + return 0; +} + +int mbr_group_name_to_uuid(const char* name, uuid_t uu) +{ + kern_return_t result; + + if (strlen(name) > 255) + return EINVAL; + + result = _mbr_MapName(GetServerPort(), 0, (char*)name, (guid_t*)uu); + + if (result == KERN_FAILURE) + return ENOENT; + else if (result != KERN_SUCCESS) + return EIO; + + return 0; +} + +int mbr_check_service_membership(const uuid_t user, const char* servicename, int* ismember) +{ + char* prefix = "com.apple.access_"; + char* all_services = "com.apple.access_all_services"; + char groupName[256]; + uuid_t group_uu; + int result; + + if (strlen(servicename) > 255 - strlen(prefix)) + return EINVAL; + + // start by checking "all services" + result = mbr_group_name_to_uuid(all_services, group_uu); + + if (result == ENOENT) + { + // all_services group didn't exist, check individual group + memcpy(groupName, prefix, strlen(prefix)); + strcpy(groupName + strlen(prefix), servicename); + result = mbr_group_name_to_uuid(groupName, group_uu); + } + + if (result == 0) + result = mbr_check_membership(user, group_uu, ismember); + + return result; +} + +static char* ConvertBytesToDecimal(char* buffer, unsigned long long value) +{ + char* temp; + buffer[24] = '\0'; + buffer[23] = '0'; + + if (value == 0) + return &buffer[23]; + + temp = &buffer[24]; + while (value != 0) + { + temp--; + *temp = '0' + (value % 10); + value /= 10; + } + + return temp; +} + +int mbr_sid_to_string(const nt_sid_t* sid, char* string) +{ + char* current = string; + long long temp = 0; + int i; + char tempBuffer[25]; + + if (sid->sid_authcount > NTSID_MAX_AUTHORITIES) + return EINVAL; + + memcpy(((char*)&temp)+2, sid->sid_authority, 6); + + current[0] = 'S'; + current[1] = '-'; + current += 2; + strcpy(current, ConvertBytesToDecimal(tempBuffer, sid->sid_kind)); + current = current + strlen(current); + *current = '-'; + current++; + strcpy(current, ConvertBytesToDecimal(tempBuffer, temp)); + + for(i=0; i < sid->sid_authcount; i++) + { + current = current + strlen(current); + *current = '-'; + current++; + strcpy(current, ConvertBytesToDecimal(tempBuffer, sid->sid_authorities[i])); + } + + return 0; +} + +int mbr_string_to_sid(const char* string, nt_sid_t* sid) +{ + char* current = string+2; + int count = 0; + long long temp; + + memset(sid, 0, sizeof(nt_sid_t)); + if (string[0] != 'S' || string[1] != '-') return EINVAL; + + sid->sid_kind = strtol(current, ¤t, 10); + if (*current == '\0') return EINVAL; + current++; + temp = strtoll(current, ¤t, 10); + memcpy(sid->sid_authority, ((char*)&temp)+2, 6); + while (*current != '\0' && count < NTSID_MAX_AUTHORITIES) + { + current++; + sid->sid_authorities[count] = strtol(current, ¤t, 10); + count++; + } + + if (*current != '\0') + return EINVAL; + + sid->sid_authcount = count; + + return 0; +} + +static void ConvertBytesToHex(char** string, char** data, int numBytes) +{ + int i; + + for (i=0; i < numBytes; i++) + { + unsigned char hi = ((**data) >> 4) & 0xf; + unsigned char low = (**data) & 0xf; + if (hi < 10) + **string = '0' + hi; + else + **string = 'A' + hi - 10; + + (*string)++; + + if (low < 10) + **string = '0' + low; + else + **string = 'A' + low - 10; + + (*string)++; + (*data)++; + } +} + +int mbr_uuid_to_string(const uuid_t uu, char* string) +{ + char* guid = (char*)uu; + char* strPtr = string; + ConvertBytesToHex(&strPtr, &guid, 4); + *strPtr = '-'; strPtr++; + ConvertBytesToHex(&strPtr, &guid, 2); + *strPtr = '-'; strPtr++; + ConvertBytesToHex(&strPtr, &guid, 2); + *strPtr = '-'; strPtr++; + ConvertBytesToHex(&strPtr, &guid, 2); + *strPtr = '-'; strPtr++; + ConvertBytesToHex(&strPtr, &guid, 6); + *strPtr = '\0'; + + return 0; +} + +int mbr_string_to_uuid(const char* string, uuid_t uu) +{ + short dataIndex = 0; + int isFirstNibble = 1; + + if (strlen(string) > MBR_UU_STRING_SIZE) + return EINVAL; + + while (*string != '\0' && dataIndex < 16) + { + char nibble; + + if (*string >= '0' && *string <= '9') + nibble = *string - '0'; + else if (*string >= 'A' && *string <= 'F') + nibble = *string - 'A' + 10; + else if (*string >= 'a' && *string <= 'f') + nibble = *string - 'a' + 10; + else + { + if (*string != '-') + return EINVAL; + string++; + continue; + } + + if (isFirstNibble) + { + uu[dataIndex] = nibble << 4; + isFirstNibble = 0; + } + else + { + uu[dataIndex] |= nibble; + dataIndex++; + isFirstNibble = 1; + } + + string++; + } + + if (dataIndex != 16) + return EINVAL; + + return 0; +} + diff --git a/membership.subproj/membership.h b/membership.subproj/membership.h new file mode 100644 index 0000000..9a0aef0 --- /dev/null +++ b/membership.subproj/membership.h @@ -0,0 +1,44 @@ +/* + * 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 _MEMBERSHIP_H_ +#define _MEMBERSHIP_H_ + +#include +#include + +#define ID_TYPE_UID 0 +#define ID_TYPE_GID 1 + +__BEGIN_DECLS + +int mbr_uid_to_uuid(uid_t id, uuid_t uu); +int mbr_gid_to_uuid(gid_t id, uuid_t uu); +int mbr_uuid_to_id( const uuid_t uu, uid_t* id, int* id_type); +int mbr_sid_to_uuid( const nt_sid_t* sid, uuid_t uu); +int mbr_uuid_to_sid( const uuid_t uu, nt_sid_t* sid); + +int mbr_check_membership(uuid_t user, uuid_t group, int* ismember); + +__END_DECLS + +#endif /* !_MEMBERSHIP_H_ */ diff --git a/membership.subproj/membershipPriv.h b/membership.subproj/membershipPriv.h new file mode 100644 index 0000000..580b8db --- /dev/null +++ b/membership.subproj/membershipPriv.h @@ -0,0 +1,43 @@ +/* + * 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 _MEMBERSHIPPRIV_H_ +#define _MEMBERSHIPPRIV_H_ + +#include +#include + +int mbr_reset_cache(); +int mbr_user_name_to_uuid(const char* name, uuid_t uu); +int mbr_group_name_to_uuid(const char* name, uuid_t uu); +int mbr_check_membership_by_id(uuid_t user, gid_t group, int* ismember); +int mbr_check_service_membership(const uuid_t user, const char* servicename, int* ismember); + +#define MBR_UU_STRING_SIZE 37 +#define MBR_MAX_SID_STRING_SIZE 200 + +int mbr_uuid_to_string(const uuid_t uu, char* string); +int mbr_string_to_uuid(const char* string, uuid_t uu); +int mbr_sid_to_string(const nt_sid_t* sid, char* string); +int mbr_string_to_sid(const char* string, nt_sid_t* sid); + +#endif /* !_MEMBERSHIPPRIV_H_ */ diff --git a/membership.subproj/ntsid.h b/membership.subproj/ntsid.h new file mode 100644 index 0000000..5fe28bd --- /dev/null +++ b/membership.subproj/ntsid.h @@ -0,0 +1,37 @@ +/* + * 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 _NTSID_H_ +#define _NTSID_H_ + +#include + +#define NTSID_MAX_AUTHORITIES 16 + +typedef struct { + u_int8_t sid_kind; + u_int8_t sid_authcount; + u_int8_t sid_authority[6]; + u_int32_t sid_authorities[NTSID_MAX_AUTHORITIES]; +} nt_sid_t __attribute__ ((packed)); + +#endif /* !_NTSID_H_ */ diff --git a/netinfo.subproj/Makefile.postamble b/netinfo.subproj/Makefile.postamble index d8a74f5..0c5d83e 100644 --- a/netinfo.subproj/Makefile.postamble +++ b/netinfo.subproj/Makefile.postamble @@ -2,8 +2,6 @@ MAN3DIR=/usr/share/man/man3 MAN5DIR=/usr/share/man/man5 install-netinfo-man: - install -m 755 -o root -g wheel -d $(DSTROOT)$(MAN3DIR) - install -m 644 -o root -g wheel -c netinfo.3 "$(DSTROOT)$(MAN3DIR)" install -m 755 -o root -g wheel -d $(DSTROOT)$(MAN5DIR) install -m 644 -o root -g wheel -c netinfo.5 "$(DSTROOT)$(MAN5DIR)" diff --git a/netinfo.subproj/Makefile.preamble b/netinfo.subproj/Makefile.preamble index e90b6f4..8637aab 100644 --- a/netinfo.subproj/Makefile.preamble +++ b/netinfo.subproj/Makefile.preamble @@ -5,3 +5,7 @@ AFTER_POSTINSTALL += install-netinfo-man OTHER_PRIVATE_HEADERS = $(NETINFO_HEADERS) BEFORE_INSTALLHEADERS += $(NETINFO_HEADERS) PRIVATE_HEADER_DIR = /usr/local/include/netinfo + +# for building 64-bit +# Libinfo need to build with gcc-3.5 and 3-way fat +NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER) diff --git a/netinfo.subproj/clib.h b/netinfo.subproj/clib.h index d284ec5..c9db33b 100644 --- a/netinfo.subproj/clib.h +++ b/netinfo.subproj/clib.h @@ -27,7 +27,7 @@ */ enum clnt_stat multi_call(unsigned, - struct in_addr *, u_long, u_long, u_long, + struct in_addr *, unsigned long, unsigned long, unsigned long, xdrproc_t, void *, unsigned, xdrproc_t, void *, int (*)(), int); diff --git a/netinfo.subproj/ni_glue.c b/netinfo.subproj/ni_glue.c index 31969e5..43c146d 100644 --- a/netinfo.subproj/ni_glue.c +++ b/netinfo.subproj/ni_glue.c @@ -3,11 +3,11 @@ * * @APPLE_LICENSE_HEADER_START@ * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of + * 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 + * 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. * @@ -15,7 +15,7 @@ * 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 + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * @@ -42,9 +42,9 @@ #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_TRIES 5 /* number of retries per timeout (udp only) */ #define NI_SLEEPTIME 4 /* 4 second sleeptime, in case of errors */ -#define NI_MAXSLEEPTIME 64 /* 64 second max sleep time */ +#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 */ @@ -57,9 +57,10 @@ #endif #define debug(msg) syslog(LOG_ERR, msg) -#define clnt_debug(ni, msg) /* do nothing */ +#define clnt_debug(ni, msg) /* do nothing */ -typedef struct ni_private { +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 */ @@ -79,6 +80,9 @@ typedef struct 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"; @@ -93,56 +97,47 @@ 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. + * Keep track of our port, in case somebody closes our socket on us. */ static int -getmyport( - int sock - ) +getmyport(int sock) { struct sockaddr_in sin; int sinlen; - sinlen = sizeof(sin); - if (getsockname(sock, (struct sockaddr *)&sin, &sinlen) == 0) { - if (sin.sin_port == 0) { - (void)bind(sock, (struct sockaddr *)&sin, sizeof(sin)); - sinlen = sizeof(sin); - (void)getsockname(sock, (struct sockaddr *)&sin, - &sinlen); - } - return (ntohs(sin.sin_port)); + 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 (-1); + + return ntohs(sin.sin_port); } static void -createauth( - ni_private *ni - ) +createauth(ni_private *ni) { - if (ni->passwd != NULL && ni->tc != NULL) { + 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); + ni->tc->cl_auth = authunix_create(ni->passwd, ni->uid, 0, 0, NULL); } } static void -fixtimeout( - struct timeval *tv, - long sec, - int tries - ) +fixtimeout(struct timeval *tv, long sec, int tries) { tv->tv_sec = sec / tries; tv->tv_usec = ((sec % tries) * 1000000) / tries; @@ -150,19 +145,14 @@ fixtimeout( static void -ni_settimeout( - ni_private *ni, - int timeout - ) +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, &tv); - } + if (ni->tc != NULL) clnt_control(ni->tc, CLSET_TIMEOUT, (char *)&tv); } @@ -173,44 +163,52 @@ static int connectit(ni_private *ni) { struct sockaddr_in sin; - int sock; + 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")) { - interface_list_t *ilist; + 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); + } - ilist = sys_interfaces(); - if (sys_is_my_address(ilist, &ni->addrs[0])) + 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); } - sys_interfaces_release(ilist); } /* - * 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 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) { @@ -218,82 +216,78 @@ connectit(ni_private *ni) 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); + if (sock < 0) return 0; cl = clntudp_create(&sin, NIBIND_PROG, NIBIND_VERS, tv, &sock); if (cl == NULL) { close(sock); - return (0); + 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, xdr_ni_name, &ni->tags[0], xdr_nibind_getregister_res, &res, tv); + 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); - + 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); + if (sock < 0) return 0; cl = clnttcp_create(&sin, NI_PROG, NI_VERS, &sock, 0, 0); if (cl == NULL) { close(sock); - return (0); + return 0; } - clnt_control(cl, CLSET_TIMEOUT, &tv); + 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); + return 1; } void -ni_setabort( - void *ni, - int abort - ) +ni_setabort(void *ni, int abort) { + if (ni == NULL) return; + ((ni_private *)ni)->abort = abort; } void -ni_setwritetimeout( - void *ni, - int timeout - ) +ni_setwritetimeout(void *ni, int timeout) { + if (ni == NULL) return; + ((ni_private *)ni)->wtv_sec = timeout; } void -ni_setreadtimeout( - void *ni, - int timeout - ) +ni_setreadtimeout(void *ni, int timeout) { + if (ni == NULL) return; + ((ni_private *)ni)->rtv_sec = timeout; } void -ni_needwrite( - void *ni, - int needwrite - ) +ni_needwrite(void *ni, int needwrite) { + if (ni == NULL) return; + ((ni_private *)ni)->needwrite = needwrite; } @@ -313,24 +307,21 @@ connectlocal(ni_private *ni) ni->tags[0] = ni_name_dup("local"); ni->whichwrite = 0; - while (!connectit(ni)) + while (connectit(ni) == 0) { - if (!printed) + if (printed == 0) { syslog(LOG_ERR, "NetInfo timeout connecting to local domain, sleeping"); - printed++; + printed = 1; } sleep(NI_SLEEPTIME); /* wait forever */ } - if (printed) - { - syslog(LOG_ERR, "NetInfo connection to local domain waking"); - } + if (printed != 0) syslog(LOG_INFO, "NetInfo connection to local domain waking"); - return (1); + return 1; } @@ -338,31 +329,26 @@ connectlocal(ni_private *ni) * Destroy the client handle */ static void -clnt_kill( - CLIENT *cl, - int sock, - int port - ) +clnt_kill(CLIENT *cl, int sock, int port) { int save = 0; + int p; - if (sock >= 0 && getmyport(sock) != port) { - /* - * Somebody else has the descriptor open. Do not close it, - * it's not ours. - */ - save++; + p = getmyport(sock); + + if ((sock >= 0) && (p != -1) && (p != port)) + { + /* Somebody has the reused the socket. */ + save = 1; } - if (cl != NULL) { - auth_destroy(cl->cl_auth); + + if (cl != NULL) + { + if (cl->cl_auth != NULL) auth_destroy(cl->cl_auth); clnt_destroy(cl); } - if (!save) { - /* - * It's ours and we can close it - */ - (void)close(sock); - } + + if (save == 0) close(sock); } @@ -370,14 +356,16 @@ clnt_kill( * Reinitialize everything */ static void -reinit( - ni_private *ni - ) +reinit(ni_private *ni) { - if (ni->tc != NULL) { + 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(); @@ -388,33 +376,26 @@ reinit( * Switch to a new server */ static void -ni_switch( - ni_private *ni, - ni_index which - ) +ni_switch(ni_private *ni, ni_index which) { struct in_addr tmp_addr; ni_name tmp_tag; - if (which == 0) { - return; - } + 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; - } + if (ni->whichwrite == 0) ni->whichwrite = which; + else if (ni->whichwrite == which) ni->whichwrite = 0; } @@ -422,11 +403,7 @@ ni_switch( * Swap two servers' positions */ static void -ni_swap( - ni_private *ni, - ni_index a, - ni_index b - ) +ni_swap(ni_private *ni, ni_index a, ni_index b) { struct in_addr tmp_addr; ni_name tmp_tag; @@ -438,37 +415,79 @@ ni_swap( 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; - } + 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 - ) +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); - } + + 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); + return TRUE; } @@ -479,48 +498,45 @@ static void shuffle(ni_private *ni) { int *shuffle; - int i, j; - int rfd; + 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--) { - unsigned int rEnt; - long rVal; - int tEnt; - + for (i = 0, j = ni->naddrs; j > 0; i++, j--) + { /* get a random number */ - if ((rfd < 0) || - (read(rfd, &rVal, sizeof(rVal)) != sizeof(rVal))) { + if ((rfd < 0) || (read(rfd, &rv, sizeof(rv)) != sizeof(rv))) + { /* if we could not read from /dev/random */ - static int initialized = 0; - if (!initialized) + if (initialized == 0) { srandom(gethostid() ^ time(NULL)); - initialized++; + initialized = 1; } - rVal = random(); + rv = random(); } - rEnt = (unsigned int)rVal % j; /* pick one of the remaining entries */ - tEnt = shuffle[rEnt]; /* grab the random entry */ - shuffle[rEnt] = shuffle[j-1]; /* the last entry moves to the random slot */ - shuffle[j-1] = tEnt; /* the last slot gets the random entry */ - ni_swap(ni, rEnt, j-1); /* and swap the actual NI addresses */ + 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) (void)close(rfd); + if (rfd > 0) close(rfd); return; } static int -rebind( - ni_private *ni - ) +rebind(ni_private *ni) { enum clnt_stat stat; getreg_stuff stuff; @@ -531,9 +547,10 @@ rebind( interface_list_t *ilist; int i; - if (ni->naddrs == 1) { + if (ni->naddrs == 1) + { ni->whichwrite = 0; - return (1); + return 1; } /* @@ -544,7 +561,7 @@ rebind( * all other servers are next */ - ilist = sys_interfaces(); + ilist = _libinfo_ni_sys_interfaces(); /* * shuffle addresses @@ -555,8 +572,9 @@ rebind( * move local servers to the head of the list */ nlocal = 0; - for (i = nlocal; i < ni->naddrs; i++) { - if (sys_is_my_address(ilist, &ni->addrs[i])) + for (i = nlocal; i < ni->naddrs; i++) + { + if (_libinfo_ni_sys_is_my_address(ilist, &ni->addrs[i])) { ni_swap(ni, nlocal, i); nlocal++; @@ -567,105 +585,86 @@ rebind( * move servers on this network to follow local servers */ nnetwork = nlocal; - for (i = nnetwork; i < ni->naddrs; i++) { - if (sys_is_my_network(ilist, &ni->addrs[i]) || - IS_BROADCASTADDR(ni->addrs[i].s_addr)) + 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++; } } - sys_interfaces_release(ilist); + _libinfo_ni_sys_interfaces_release(ilist); stuff.ni = ni; - for (;;) { + 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, - xdr_ni_name, ni->tags, - sizeof(ni_name), - xdr_nibind_getregister_res, - &stuff, eachresult, - NI_TIMEOUT_SHORT); - if (stat == RPC_SUCCESS) { - break; + 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, - xdr_ni_name, ni->tags, - sizeof(ni_name), - xdr_nibind_getregister_res, - &stuff, eachresult, - NI_TIMEOUT_SHORT); - if (stat == RPC_SUCCESS) { - break; + 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, - xdr_ni_name, ni->tags, - sizeof(ni_name), - xdr_nibind_getregister_res, - &stuff, eachresult, - ni->rtv_sec == 0 ? NI_TIMEOUT_SHORT : ni->rtv_sec); - if (stat == RPC_SUCCESS) { - break; + 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) { - if (ni->whichwrite >= 0) { - syslog(LOG_ERR, - "NetInfo connect timeout (domain with master %s/%s), sleeping", - inet_ntoa(ni->addrs[ni->whichwrite]), ni->tags[ni->whichwrite]); + 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_ERR, "NetInfo connect timeout (domain with server %s/%s), sleeping", - inet_ntoa(ni->addrs[0]), ni->tags[0]); + else + { + syslog(LOG_WARNING, "NetInfo connect timeout (domain with server %s/%s), sleeping", inet_ntoa(ni->addrs[0]), ni->tags[0]); } - printed++; + + printed = 1; } + sleep(sleeptime); - if (sleeptime < NI_MAXSLEEPTIME) { - sleeptime *= 2; /* backoff */ + if (sleeptime < NI_MAXSLEEPTIME) + { + /* backoff */ + sleeptime *= 2; } } syslog(LOG_INFO, "NetInfo connected to %s/%s", inet_ntoa(ni->addrs[0]), ni->tags[0]); - if (printed) { - syslog(LOG_ERR, "NetInfo connected to %s/%s", inet_ntoa(ni->addrs[0]), ni->tags[0]); - } - return (1); + return 1; } @@ -673,18 +672,27 @@ rebind( * Confirm that our tcp socket is still valid */ static int -confirm_tcp( - ni_private *ni, - int needwrite - ) +confirm_tcp(ni_private *ni, int needwrite) { - if (ni->tsock != -1) { - if (getmyport(ni->tsock) == ni->tport) { - return (1); + 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 closed our socket. Do not close it, it could - * be owned by somebody else now. + * Somebody has reused our socket. */ if (ni->tc != NULL) { @@ -693,17 +701,15 @@ confirm_tcp( ni->tc = NULL; } } - if (!needwrite && !rebind(ni) && ni->abort) { - return (0); - } - return (connectit(ni)); + + if ((needwrite == 0) && (rebind(ni) == 0) && (ni->abort != 0)) return 0; + + return connectit(ni); } static int -setmaster( - ni_private *ni - ) +setmaster(ni_private *ni) { ni_id root; ni_namelist nl; @@ -716,88 +722,104 @@ setmaster( struct in_addr addr; int needwrite; - if (ni->naddrs == 1) { - /* - * One server - must be the master - */ + if (ni->naddrs == 1) + { + /* One server - must be the master */ ni->whichwrite = 0; - return (1); + return 1; } + needwrite = ni->needwrite; ni->needwrite = 0; - if (ni_root(ni, &root) != NI_OK) { + if (ni_root(ni, &root) != NI_OK) + { ni->needwrite = needwrite; - return (0); + return 0; } + NI_INIT(&nl); - if (ni_lookupprop(ni, &root, NAME_MASTER, &nl) != NI_OK) { + if (ni_lookupprop(ni, &root, NAME_MASTER, &nl) != NI_OK) + { ni->needwrite = needwrite; - return (0); + return 0; } - if (nl.ninl_len == 0) { + + if (nl.ninl_len == 0) + { ni->needwrite = needwrite; - return (0); + return 0; } + sep = index(nl.ninl_val[0], '/'); - if (sep == NULL) { + if (sep == NULL) + { ni->needwrite = needwrite; - return (0); + return 0; } + *sep++ = 0; master = nl.ninl_val[0]; + NI_INIT(&idl); - if (ni_lookup(ni, &root, NAME_NAME, NAME_MACHINES, &idl) != NI_OK) { + if (ni_lookup(ni, &root, NAME_NAME, NAME_MACHINES, &idl) != NI_OK) + { ni->needwrite = needwrite; ni_namelist_free(&nl); - return (0); + return 0; } - if (idl.niil_len < 1) { + + if (idl.niil_len < 1) + { ni->needwrite = needwrite; - return (0); + 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) { + if (ni_lookup(ni, &id, NAME_NAME, master, &idl) != NI_OK) + { ni_namelist_free(&nl); ni->needwrite = needwrite; - return (0); + return 0; } + ni_namelist_free(&nl); - if (idl.niil_len < 1) { + if (idl.niil_len < 1) + { ni->needwrite = needwrite; - return (0); + 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++) { + 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) { + 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); + return 1; } } } + ni->needwrite = needwrite; ni_namelist_free(&nl); - return (0); + return 0; } static void * -callit( - ni_private *ni, - void *(*stub)(), - void *args, - int needwrite - ) +callit(ni_private *ni, void *(*stub)(), void *args, int needwrite) { void *resp; struct rpc_err err; @@ -805,78 +827,83 @@ callit( int sleeptime = 0; int printed = 0; - if (getpid() != ni->pid) { - reinit(ni); - } - if (needwrite || ni->needwrite) { - if (ni->whichwrite >= 0) { + if (getpid() != ni->pid) reinit(ni); + + if (needwrite || ni->needwrite) + { + if (ni->whichwrite >= 0) + { ni_switch(ni, ni->whichwrite); - } else { - if (!setmaster(ni)) { - return (NULL); - } + } + else + { + if (setmaster(ni) == 0) return NULL; ni_switch(ni, ni->whichwrite); } - if (!needwrite) { - ni_settimeout(ni, (ni->rtv_sec == 0 ? - NI_TIMEOUT_SHORT : ni->rtv_sec)); + + 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)); + 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 (;;) { + + 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) { - syslog(LOG_ERR, "NetInfo connected to %s/%s", - inet_ntoa(ni->addrs[0]), ni->tags[0]); - } - return (resp); + 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. - */ + + 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) { + + 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 (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) { - if (ni->tc != NULL) { - if (!(sleeptime == 0 && - err.re_status == RPC_TIMEDOUT)) { + + 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 @@ -884,71 +911,60 @@ callit( * 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++; + 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 { + else + { /* first attempt failed */ - syslog(LOG_ERR, "%s on initial connection to %s/%s", - clnt_sperror(ni->tc,"NetInfo connection timeout"), - inet_ntoa(ni->addrs[0]), ni->tags[0]); + 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++; + } + else + { + syslog(LOG_ERR, "NetInfo connection failed for server %s/%s", inet_ntoa(ni->addrs[0]), ni->tags[0]); + printed = 1; } } - if (sleeptime > 0) { + + if (sleeptime > 0) + { sleep(sleeptime); - if (sleeptime < NI_MAXSLEEPTIME) { - sleeptime *= 2; /* backoff */ - } - } else { + /* 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); - (void)rebind(ni); + rebind(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 void -ni_clear( - ni_private *ni - ) +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; + 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_alloc(void) { ni_private *ni; @@ -966,61 +982,55 @@ ni_alloc( ni->passwd = NULL; ni->uid = getuid(); ni->needwrite = 0; - return ((void *)ni); + return (void *)ni; } void * -_ni_dup( - void *ni - ) +_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++) { + 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); + + 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 - ) +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] == '/') { + if (sep == NULL) return 0; + + if ((strncmp(domain, domtag, len) == 0) && (domtag[len] == '/')) + { *tag = ni_name_dup(sep + 1); - return (1); + return 1; } - return (0); + + return 0; } @@ -1070,10 +1080,17 @@ addaddr(void *ni, ni_index ido, ni_name tag, ni_private *target_ni) 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); - if (ni_lookupprop(ni, &id, NAME_IP_ADDRESS, &nl) != NI_OK) return 0; + + status = ni_lookupprop(ni, &id, NAME_IP_ADDRESS, &nl); + if (status != NI_OK) return 0; if (nl.ni_namelist_len == 0) return 0; @@ -1111,7 +1128,9 @@ get_daddr(ni_private *ni, ni_name dom, ni_private *target_ni) 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, ".")) { @@ -1128,15 +1147,18 @@ get_daddr(ni_private *ni, ni_name dom, ni_private *target_ni) { 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; @@ -1176,6 +1198,9 @@ getparent(ni_private *oldni, ni_private **newni) int printed = 0; int inlist = 0; + if (oldni == NULL) return 0; + if (newni == NULL) return 0; + while (found == 0) { /* @@ -1187,11 +1212,10 @@ getparent(ni_private *oldni, ni_private **newni) if (resp == NULL) return NI_FAILED; if (resp->status != NI_NORESPONSE) break; - if (!printed) + if (printed != 0) { - syslog(LOG_ERR, "NetInfo timeout finding server for parent of %s/%s, sleeping", - inet_ntoa(oldni->addrs[0]), oldni->tags[0]); - printed++; + 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); @@ -1200,13 +1224,11 @@ getparent(ni_private *oldni, ni_private **newni) if (printed) { raddr.s_addr = htonl(resp->ni_rparent_res_u.binding.addr); - - syslog(LOG_ERR, "NetInfo %s/%s found parent %s/%s", - inet_ntoa(oldni->addrs[0]), oldni->tags[0], - inet_ntoa(raddr), resp->ni_rparent_res_u.binding.tag); + + 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); + if (resp->status != NI_OK) return resp->status; ni = ni_alloc(); *ni = *oldni; @@ -1216,9 +1238,9 @@ getparent(ni_private *oldni, ni_private **newni) 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(xdr_ni_rparent_res, resp); - + + xdr_free((xdrproc_t)xdr_ni_rparent_res, (void *)resp); + dupni = ni; ni = ni_alloc(); *ni = *dupni; @@ -1263,8 +1285,7 @@ getparent(ni_private *oldni, ni_private **newni) */ if (inlist == 0) { - syslog(LOG_ERR, "Rogue NetInfo server detected: %s/%s", - inet_ntoa(dupni->addrs[0]), dupni->tags[0]); + syslog(LOG_ERR, "Rogue NetInfo server detected: %s/%s", inet_ntoa(dupni->addrs[0]), dupni->tags[0]); reinit(ni); } @@ -1284,41 +1305,39 @@ getparent(ni_private *oldni, ni_private **newni) void * -ni_connect( - struct sockaddr_in *sin, - const char *tag - ) +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 = (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); + return ni; } ni_status -ni_addrtag( - void *ni, - struct sockaddr_in *addr, - ni_name *tag - ) +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; - 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); + + return NI_OK; } @@ -1336,9 +1355,12 @@ ni_new(void *oldni, const char *domain) sep = index(domain, '@'); if (sep != NULL) { - tag = strncpy((char *)malloc(sep - domain + 1), domain, sep - domain); + tag = strncpy((char *)malloc(sep - domain + 1), domain, sep - domain); tag[sep - domain] = '\0'; - addr = strcpy ((char *)malloc(strlen(sep + 1)), sep + 1); + + addr = NULL; + asprintf(&addr, "%s", sep + 1); + sin.sin_addr.s_addr = inet_addr(addr); if (sin.sin_addr.s_addr == INADDR_NONE) { @@ -1396,7 +1418,7 @@ ni_new(void *oldni, const char *domain) ni = ni_alloc(); *ni = *NIP(oldni); ni_clear(ni); - if (!get_daddr(oldni, (ni_name)domain, ni)) + if (get_daddr(oldni, (ni_name)domain, ni) == 0) { ni_free(ni); return NULL; @@ -1407,25 +1429,23 @@ ni_new(void *oldni, const char *domain) void -ni_free( - void *ni - ) +ni_free(void *ni) { ni_index i; - if (NIP(ni)->tc != NULL) { - clnt_kill(NIP(ni)->tc, NIP(ni)->tsock, NIP(ni)->tport); - } - if (NIP(ni)->naddrs > 0) { - free(NIP(ni)->addrs); - for (i = 0; i < NIP(ni)->naddrs; i++) { - ni_name_free(&NIP(ni)->tags[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); - } + + if (NIP(ni)->passwd != NULL) ni_name_free(&NIP(ni)->passwd); + free(ni); } @@ -1435,658 +1455,735 @@ ni_free( * RPC calls to the local NetInfo server. */ ni_status -ni_statistics( - void *ni, - ni_proplist *pl - ) +ni_statistics(void *ni, ni_proplist *pl) { ni_proplist *resp; - if ((resp = (ni_proplist *)RCALLIT(ni, _ni_statistics_2, NULL)) - == NULL) { - return (NI_FAILED); + 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); + return NI_OK; } ni_status -ni_root( - void *ni, - ni_id *id - ) +ni_root(void *ni, ni_id *id) { ni_id_res *resp; - if ((resp = RCALLIT(ni, _ni_root_2, id)) == NULL) { + 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); + return NI_FAILED; } - if (resp->status == NI_OK) { - *id = resp->ni_id_res_u.id; - } - return (resp->status); + + 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_self(void *ni, ni_id *id) { ni_id_res *resp; - if ((resp = RCALLIT(ni, _ni_self_2, id)) == NULL) { + 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 NI_FAILED; } - return (resp->status); + + 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(void *ni, ni_id *id, ni_index *parent_id_p) { ni_parent_res *resp; - if ((resp = RCALLIT(ni, _ni_parent_2, id)) == NULL) { + 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); + return NI_FAILED; } - if (resp->status == NI_OK) { + + 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); + + return resp->status; } ni_status -ni_children( - void *ni, - ni_id *id, - ni_idlist *children - ) +ni_children(void *ni, ni_id *id, ni_idlist *children) { ni_children_res *resp; - if ((resp = RCALLIT(ni, _ni_children_2, id)) == NULL) { + 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); + return NI_FAILED; } - if (resp->status == NI_OK) { + + 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); + + 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(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; - if ((resp = WCALLIT(ni, _ni_create_2, &args)) == NULL) { + + resp = WCALLIT(ni, _ni_create_2, &args); + if (resp == NULL) + { clnt_debug(ni, "_ni_create"); - return (NI_FAILED); + return NI_FAILED; } - if (resp->status == NI_OK) { + + 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); + + return resp->status; } ni_status -ni_destroy( - void *ni, - ni_id *parent_id, - ni_id self_id - ) +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; - if ((resp = WCALLIT(ni, _ni_destroy_2, &args)) == NULL) { + + resp = WCALLIT(ni, _ni_destroy_2, &args); + if (resp == NULL) + { clnt_debug(ni, "_ni_destroy"); - return (NI_FAILED); + return NI_FAILED; } - if (resp->status == NI_OK) { - *parent_id = resp->ni_id_res_u.id; - } - return (resp->status); + + 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_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; - if ((resp = WCALLIT(ni, _ni_write_2, &args)) == NULL) { + + 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 NI_FAILED; } - return (resp->status); + + 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_read(void *ni, ni_id *self_id, ni_proplist *pl) { ni_proplist_res *resp; - if ((resp = RCALLIT(ni, _ni_read_2, self_id)) == NULL) { + 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); + return NI_FAILED; } - if (resp->status == NI_OK) { + + 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); + + 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(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; - if ((resp = RCALLIT(ni, _ni_lookup_2, &args)) == NULL) { + + resp = RCALLIT(ni, _ni_lookup_2, &args); + if (resp == NULL) + { clnt_debug(ni, "_ni_lookup"); - return (NI_FAILED); + return NI_FAILED; } - if (resp->status == NI_OK) { + + 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); + + return resp->status; } ni_status -ni_lookupread( - void *ni, - ni_id *id, - ni_name_const pname, - ni_name_const pval, - ni_proplist *props - ) +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; - if ((resp = RCALLIT(ni, _ni_lookupread_2, &args)) == NULL) { + + resp = RCALLIT(ni, _ni_lookupread_2, &args); + if (resp == NULL) + { clnt_debug(ni, "_ni_lookupread"); - return (NI_FAILED); + return NI_FAILED; } - if (resp->status == NI_OK) { + + if (resp->status == NI_OK) + { *props = resp->ni_proplist_res_u.stuff.props; *id = resp->ni_proplist_res_u.stuff.id; } - return (resp->status); + + return resp->status; } ni_status -ni_list( - void *ni, - ni_id *id, - ni_name_const pname, - ni_entrylist *entries - ) +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; - if ((resp = RCALLIT(ni, _ni_list_2, &args)) == NULL) { + + resp = RCALLIT(ni, _ni_list_2, &args); + if (resp == NULL) + { clnt_debug(ni, "_ni_list"); - return (NI_FAILED); + return NI_FAILED; } - if (resp->status == NI_OK) { + + 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); + + return resp->status; } ni_status -ni_listall( - void *ni, - ni_id *id, - ni_proplist_list *entries - ) +ni_listall(void *ni, ni_id *id, ni_proplist_list *entries) { ni_listall_res *resp; - if ((resp = RCALLIT(ni, _ni_listall_2, id)) == NULL) { + 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); + return NI_FAILED; } - if (resp->status == NI_OK) { + + 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); + + return resp->status; } ni_status -ni_readprop( - void *ni, - ni_id *id, - ni_index which, - ni_namelist *propval_p - ) +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; - if ((resp = RCALLIT(ni, _ni_readprop_2, &args)) == NULL) { + + resp = RCALLIT(ni, _ni_readprop_2, &args); + if (resp == NULL) + { clnt_debug(ni, "_ni_readprop"); - return (NI_FAILED); + return NI_FAILED; } - if (resp->status == NI_OK) { + + 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); + + return resp->status; } ni_status -ni_writeprop( - void *ni, - ni_id *id, - ni_index which, - ni_namelist propval - ) +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; - if ((resp = WCALLIT(ni, _ni_writeprop_2, &args)) == NULL) { + + 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 NI_FAILED; } - return (resp->status); + + 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_listprops(void *ni, ni_id *id, ni_namelist *propnames) { ni_namelist_res *resp; - if ((resp = RCALLIT(ni, _ni_listprops_2, id)) == NULL) { + 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); + return NI_FAILED; } - if (resp->status == NI_OK) { + + 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); + + return resp->status; } - + ni_status -ni_createprop( - void *ni, - ni_id *id, - ni_property prop, - ni_index where - ) +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; - if ((resp = WCALLIT(ni, _ni_createprop_2, &args)) == NULL) { + + resp = WCALLIT(ni, _ni_createprop_2, &args); + if (resp == NULL) + { clnt_debug(ni, "_ni_createprop"); - return (NI_FAILED); + return NI_FAILED; } - if (resp->status == NI_OK) { - *id = resp->ni_id_res_u.id; - } - return (resp->status); + + 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_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; - if ((resp = WCALLIT(ni, _ni_destroyprop_2, &args)) == NULL) { + + 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 NI_FAILED; } - return (resp->status); + + 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_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; - if ((resp = WCALLIT(ni, _ni_renameprop_2, &args)) == NULL) { + + resp = WCALLIT(ni, _ni_renameprop_2, &args); + if (resp == NULL) + { clnt_debug(ni, "_ni_renameprop"); - return (NI_FAILED); + return NI_FAILED; } - if (resp->status == NI_OK) { - *id = resp->ni_id_res_u.id; - } - return (resp->status); + + 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_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; - if ((resp = WCALLIT(ni, _ni_createname_2, &args)) == NULL) { + + 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 NI_FAILED; } - return (resp->status); + + 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_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; - if ((resp = WCALLIT(ni, _ni_destroyname_2, &args)) == NULL) { + + 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 NI_FAILED; } - return (resp->status); + + 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_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; - if ((resp = WCALLIT(ni, _ni_writename_2, &args)) == NULL) { + + resp = WCALLIT(ni, _ni_writename_2, &args); + if (resp == NULL) + { clnt_debug(ni, "_ni_writename"); - return (NI_FAILED); + return NI_FAILED; } - if (resp->status == NI_OK) { - *id = resp->ni_id_res_u.id; - } - return (resp->status); + + 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(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; - if ((resp = RCALLIT(ni, _ni_readname_2, &args)) == NULL) { + + resp = RCALLIT(ni, _ni_readname_2, &args); + if (resp == NULL) + { clnt_debug(ni, "_ni_readname"); - return (NI_FAILED); + return NI_FAILED; } - if (resp->status == NI_OK) { + + if (resp->status == NI_OK) + { *id = resp->ni_readname_res_u.stuff.id; *name = resp->ni_readname_res_u.stuff.name; } - return (resp->status); + + return resp->status; } ni_status -ni_resync( - void *ni - ) +ni_resync(void *ni) { ni_status *resp; - if ((resp = (ni_status *)RCALLIT(ni, _ni_resync_2, NULL)) == NULL) { - return (NI_FAILED); + 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); + + return *resp; } ni_status -ni_setuser( - void *ni, - ni_name_const user - ) +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) { + if (user == NULL) + { NIP(ni)->uid = getuid(); - return (ni_setpassword(ni, NULL)); + return ni_setpassword(ni, NULL); } - if (ni_root(ni, &id) != NI_OK) { - return(NI_NOUSER); - } + status = ni_root(ni, &id); + if (status != NI_OK) return NI_NOUSER; + NI_INIT(&ids); - if (ni_lookup(ni, &id, NAME_NAME, NAME_USERS, &ids) != NI_OK) { - return (NI_NOUSER); - } + 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); - if (ni_lookup(ni, &id, NAME_NAME, user, &ids) != NI_OK) { - return (NI_NOUSER); - } + 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); - if (ni_lookupprop(ni, &id, NAME_UID, &nl) != NI_OK) { - return (NI_NOUSER); - } - if (nl.ninl_len == 0) { - return (NI_NOUSER); - } - for (p = nl.ninl_val[0]; *p; p++) { - if (!isdigit(*p)) { + 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); + return NI_NOUSER; } } + NIP(ni)->uid = atoi(nl.ninl_val[0]); - if (NIP(ni)->passwd == NULL) { - NIP(ni)->passwd = ni_name_dup(""); - } + if (NIP(ni)->passwd == NULL) NIP(ni)->passwd = ni_name_dup(""); + createauth(NIP(ni)); - return (NI_OK); + return NI_OK; } ni_status -ni_setpassword( - void *ni, - ni_name_const passwd - ) +ni_setpassword(void *ni, ni_name_const passwd) { char *p; - if (NIP(ni)->passwd != NULL) { - ni_name_free(&NIP(ni)->passwd); - } - if (passwd == NULL) { + 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) { + if (NIP(ni)->tc != NULL) + { auth_destroy(NIP(ni)->tc->cl_auth); NIP(ni)->tc->cl_auth = authnone_create(); } - return (NI_OK); + return NI_OK; } + NIP(ni)->passwd = ni_name_dup(passwd); - /* - * Our trivial encryption scheme - */ - for (p = NIP(ni)->passwd; *p; p++) { - *p = ~(*p); - } + + /* Our trivial encryption scheme */ + for (p = NIP(ni)->passwd; *p; p++) *p = ~(*p); createauth(NIP(ni)); - return (NI_OK); + return NI_OK; } -extern int bindresvport(int, struct sockaddr_in *); - - /* - * NeXT note: * The procedure pmap_getport_to below is derived - * from Sun Microsystems RPC source code. As such the following + * 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 + * 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. @@ -2109,7 +2206,7 @@ extern int bindresvport(int, struct sockaddr_in *); * * Sun Microsystems, Inc. * 2550 Garcia Avenue - * Mountain View, California 94043 + * Mountain View, California 94043 */ /* * Client interface to pmap rpc service. @@ -2132,38 +2229,41 @@ pmap_getport_to(address, program, version, protocol, timeout_secs, ntries) register CLIENT *client; struct pmap parms; struct timeval timeout; - + sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (sock < 0) { - return (0); - } + 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 != (CLIENT *)NULL) { + + 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 */ + parms.pm_port = 0; /* not needed or used */ timeout.tv_usec = 0; timeout.tv_sec = timeout_secs; - if (CLNT_CALL(client, PMAPPROC_GETPORT, xdr_pmap, &parms, - xdr_u_short, &port, timeout) != RPC_SUCCESS){ + + 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) { + } + else if (port == 0) + { rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; } } - if (client != NULL) { - clnt_destroy(client); - } - (void)close(sock); + + if (client != NULL) clnt_destroy(client); + + close(sock); address->sin_port = 0; - return (port); + return port; } @@ -2171,59 +2271,55 @@ pmap_getport_to(address, program, version, protocol, timeout_secs, ntries) * 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 - ) +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) { - u_short port; - if ((port = pmap_getport_to(raddr, prog, vers, - IPPROTO_UDP, timeout, - ntries)) == 0) { - return (-1); - } + 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 (-1 == bindresvport(sock, NULL) && errno == EADDRNOTAVAIL) { + 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 (-1 == bind(sock, &bindsin, sizeof(bindsin))) { + 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__); - (void)close(sock); + 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) { + + if (proto == IPPROTO_TCP) + { + if (connect(sock, (struct sockaddr *)raddr, sizeof(*raddr)) < 0) + { syslog(LOG_DEBUG, "Libinfo[%s():%d] connect(): %m", __func__, __LINE__); - (void)close(sock); - return (-1); + close(sock); + return -1; } } - return (sock); + + return sock; } diff --git a/netinfo.subproj/ni_pwdomain.c b/netinfo.subproj/ni_pwdomain.c index 9d9c541..e6e1a23 100644 --- a/netinfo.subproj/ni_pwdomain.c +++ b/netinfo.subproj/ni_pwdomain.c @@ -149,9 +149,9 @@ ni_domainof(void *ni, void *parent) return dom; } - ilist = sys_interfaces(); + ilist = _libinfo_ni_sys_interfaces(); if (ilist == NULL) return ni_name_dup(NAME_UNKNOWN); - if (sys_is_my_address(ilist, &(addr.sin_addr))) + if (_libinfo_ni_sys_is_my_address(ilist, &(addr.sin_addr))) { /* Try all my non-loopback interfaces */ for (i = 0; i < ilist->count; i++) @@ -163,12 +163,12 @@ ni_domainof(void *ni, void *parent) if (dom != NULL) { ni_name_free(&tag); - sys_interfaces_release(ilist); + _libinfo_ni_sys_interfaces_release(ilist); return dom; } } } - sys_interfaces_release(ilist); + _libinfo_ni_sys_interfaces_release(ilist); dom = malloc(strlen(tag) + 256); sprintf(dom, "%s@%s", tag, inet_ntoa(addr.sin_addr.s_addr)); diff --git a/netinfo.subproj/sys_interfaces.c b/netinfo.subproj/sys_interfaces.c index 682da1a..ff78452 100644 --- a/netinfo.subproj/sys_interfaces.c +++ b/netinfo.subproj/sys_interfaces.c @@ -29,7 +29,7 @@ #include "sys_interfaces.h" __private_extern__ interface_list_t * -sys_interfaces(void) +_libinfo_ni_sys_interfaces(void) { interface_list_t *my_interfaces = NULL; interface_t *iface; @@ -73,7 +73,7 @@ sys_interfaces(void) } __private_extern__ void -sys_interfaces_release(interface_list_t *l) +_libinfo_ni_sys_interfaces_release(interface_list_t *l) { int i; @@ -89,7 +89,7 @@ sys_interfaces_release(interface_list_t *l) } __private_extern__ int -sys_is_my_address(interface_list_t *l, struct in_addr *a) +_libinfo_ni_sys_is_my_address(interface_list_t *l, struct in_addr *a) { int i; @@ -103,7 +103,7 @@ sys_is_my_address(interface_list_t *l, struct in_addr *a) } __private_extern__ int -sys_is_my_network(interface_list_t *l, struct in_addr *a) +_libinfo_ni_sys_is_my_network(interface_list_t *l, struct in_addr *a) { int i; diff --git a/netinfo.subproj/sys_interfaces.h b/netinfo.subproj/sys_interfaces.h index 03d4d52..8064075 100644 --- a/netinfo.subproj/sys_interfaces.h +++ b/netinfo.subproj/sys_interfaces.h @@ -46,9 +46,9 @@ typedef struct interface_t *interface; } interface_list_t; -interface_list_t *sys_interfaces(void); -void sys_interfaces_release(interface_list_t *l); -int sys_is_my_address(interface_list_t *l, struct in_addr *a); -int sys_is_my_network(interface_list_t *l, struct in_addr *a); +interface_list_t *_libinfo_ni_sys_interfaces(void); +void _libinfo_ni_sys_interfaces_release(interface_list_t *l); +int _libinfo_ni_sys_is_my_address(interface_list_t *l, struct in_addr *a); +int _libinfo_ni_sys_is_my_network(interface_list_t *l, struct in_addr *a); #endif /* __SYS_INTERFACES__ */ diff --git a/nis.subproj/Makefile.preamble b/nis.subproj/Makefile.preamble index 5001fae..a5e57b4 100644 --- a/nis.subproj/Makefile.preamble +++ b/nis.subproj/Makefile.preamble @@ -1,2 +1,6 @@ AFTER_POSTINSTALL += install-nis-man PUBLIC_HEADER_DIR_SUFFIX = /rpcsvc + +# for building 64-bit +# Libinfo need to build with gcc-3.5 and 3-way fat +NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER) diff --git a/nis.subproj/yp_prot.h b/nis.subproj/yp_prot.h index 1be2a2e..531017c 100644 --- a/nis.subproj/yp_prot.h +++ b/nis.subproj/yp_prot.h @@ -91,19 +91,19 @@ */ #ifndef BOOL_DEFINED -typedef u_int bool; +typedef unsigned int bool; #define BOOL_DEFINED #endif /* Program and version symbols, magic numbers */ -#define YPPROG ((u_long)100004) -#define YPVERS ((u_long)2) -#define YPVERS_ORIG ((u_long)1) -#define YPMAXRECORD ((u_long)1024) -#define YPMAXDOMAIN ((u_long)64) -#define YPMAXMAP ((u_long)64) -#define YPMAXPEER ((u_long)256) +#define YPPROG ((unsigned long)100004) +#define YPVERS ((unsigned long)2) +#define YPVERS_ORIG ((unsigned long)1) +#define YPMAXRECORD ((unsigned long)1024) +#define YPMAXDOMAIN ((unsigned long)64) +#define YPMAXMAP ((unsigned long)64) +#define YPMAXPEER ((unsigned long)256) /* * I don't know if anything of sun's depends on this, or if they @@ -123,7 +123,7 @@ typedef struct { struct ypmap_parms { const char *domain; const char *map; - u_long ordernum; + unsigned long ordernum; char *owner; }; @@ -140,9 +140,9 @@ struct ypreq_nokey { struct ypreq_xfr { struct ypmap_parms map_parms; - u_long transid; - u_long proto; - u_short port; + unsigned long transid; + unsigned long proto; + unsigned short port; }; #define ypxfr_domain map_parms.domain #define ypxfr_map map_parms.map @@ -150,24 +150,24 @@ struct ypreq_xfr { #define ypxfr_owner map_parms.owner struct ypresp_val { - u_long status; + unsigned long status; datum valdat; }; struct ypresp_key_val { - u_long status; + unsigned long status; datum keydat; datum valdat; }; struct ypresp_master { - u_long status; + unsigned long status; char *master; }; struct ypresp_order { - u_long status; - u_long ordernum; + unsigned long status; + unsigned long ordernum; }; struct ypresp_all { @@ -183,23 +183,23 @@ struct ypmaplist { }; struct ypresp_maplist { - u_long status; + unsigned long status; struct ypmaplist *list; }; /* ypserv procedure numbers */ -#define YPPROC_NULL ((u_long)0) -#define YPPROC_DOMAIN ((u_long)1) -#define YPPROC_DOMAIN_NONACK ((u_long)2) -#define YPPROC_MATCH ((u_long)3) -#define YPPROC_FIRST ((u_long)4) -#define YPPROC_NEXT ((u_long)5) -#define YPPROC_XFR ((u_long)6) -#define YPPROC_CLEAR ((u_long)7) -#define YPPROC_ALL ((u_long)8) -#define YPPROC_MASTER ((u_long)9) -#define YPPROC_ORDER ((u_long)10) -#define YPPROC_MAPLIST ((u_long)11) +#define YPPROC_NULL ((unsigned long)0) +#define YPPROC_DOMAIN ((unsigned long)1) +#define YPPROC_DOMAIN_NONACK ((unsigned long)2) +#define YPPROC_MATCH ((unsigned long)3) +#define YPPROC_FIRST ((unsigned long)4) +#define YPPROC_NEXT ((unsigned long)5) +#define YPPROC_XFR ((unsigned long)6) +#define YPPROC_CLEAR ((unsigned long)7) +#define YPPROC_ALL ((unsigned long)8) +#define YPPROC_MASTER ((unsigned long)9) +#define YPPROC_ORDER ((unsigned long)10) +#define YPPROC_MAPLIST ((unsigned long)11) /* ypserv procedure return status values */ #define YP_TRUE ((long)1) /* general purpose success code */ @@ -230,10 +230,10 @@ struct dom_binding { struct dom_binding *dom_pnext; char dom_domain[YPMAXDOMAIN + 1]; struct sockaddr_in dom_server_addr; - u_short dom_server_port; + unsigned short dom_server_port; int dom_socket; CLIENT *dom_client; - u_short dom_local_port; + unsigned short dom_local_port; long dom_vers; }; @@ -251,14 +251,14 @@ struct dom_binding { * used by ypset. */ -#define YPBINDPROG ((u_long)100007) -#define YPBINDVERS ((u_long)2) -#define YPBINDVERS_ORIG ((u_long)1) +#define YPBINDPROG ((unsigned long)100007) +#define YPBINDVERS ((unsigned long)2) +#define YPBINDVERS_ORIG ((unsigned long)1) /* ypbind procedure numbers */ -#define YPBINDPROC_NULL ((u_long)0) -#define YPBINDPROC_DOMAIN ((u_long)1) -#define YPBINDPROC_SETDOM ((u_long)2) +#define YPBINDPROC_NULL ((unsigned long)0) +#define YPBINDPROC_DOMAIN ((unsigned long)1) +#define YPBINDPROC_SETDOM ((unsigned long)2) /* error code in ypbind_resp.ypbind_status */ enum ypbind_resptype { @@ -269,13 +269,13 @@ enum ypbind_resptype { /* network order, of course */ struct ypbind_binding { struct in_addr ypbind_binding_addr; - u_short ypbind_binding_port; + unsigned short ypbind_binding_port; }; struct ypbind_resp { enum ypbind_resptype ypbind_status; union { - u_long ypbind_error; + unsigned long ypbind_error; struct ypbind_binding ypbind_bindinfo; } ypbind_respbody; }; @@ -291,7 +291,7 @@ struct ypbind_resp { struct ypbind_setdom { char ypsetdom_domain[YPMAXDOMAIN + 1]; struct ypbind_binding ypsetdom_binding; - u_short ypsetdom_vers; + unsigned short ypsetdom_vers; }; #define ypsetdom_addr ypsetdom_binding.ypbind_binding_addr #define ypsetdom_port ypsetdom_binding.ypbind_binding_port @@ -308,16 +308,16 @@ struct ypbind_setdom { * This protocol is not implimented, naturally, because this YP * implimentation only does the client side. */ -#define YPPUSHVERS ((u_long)1) -#define YPPUSHVERS_ORIG ((u_long)1) +#define YPPUSHVERS ((unsigned long)1) +#define YPPUSHVERS_ORIG ((unsigned long)1) /* yppush procedure numbers */ -#define YPPUSHPROC_NULL ((u_long)0) -#define YPPUSHPROC_XFRRESP ((u_long)1) +#define YPPUSHPROC_NULL ((unsigned long)0) +#define YPPUSHPROC_XFRRESP ((unsigned long)1) struct yppushresp_xfr { - u_long transid; - u_long status; + unsigned long transid; + unsigned long status; }; /* yppush status value in yppushresp_xfr.status */ @@ -354,7 +354,7 @@ bool_t xdr_ypresp_val __P((XDR *, struct ypresp_val *)); bool_t xdr_ypbind_setdom __P((XDR *, struct ypbind_setdom *)); bool_t xdr_ypresp_key_val __P((XDR *, struct ypresp_key_val *)); bool_t xdr_ypresp_all __P((XDR *, struct ypresp_all *)); -bool_t xdr_ypresp_all_seq __P((XDR *, u_long *)); +bool_t xdr_ypresp_all_seq __P((XDR *, unsigned long *)); bool_t xdr_ypresp_master __P((XDR *, struct ypresp_master *)); bool_t xdr_ypmaplist_str __P((XDR *, char *)); bool_t xdr_ypmaplist __P((XDR *, struct ypmaplist *)); diff --git a/nis.subproj/ypclnt.3 b/nis.subproj/ypclnt.3 index 6f1651f..0d8951e 100644 --- a/nis.subproj/ypclnt.3 +++ b/nis.subproj/ypclnt.3 @@ -156,7 +156,7 @@ is returned and control given back to the user code. The .Nm ypclnt suite provides the following functionality: -.Bl -tag -width Fn yp_match +.Bl -tag -width ".Fn yperr_string" .It Fn yp_match Provides the value associated with the given key. .It Fn yp_first diff --git a/nis.subproj/ypclnt.h b/nis.subproj/ypclnt.h index c09e8b1..bb4fb87 100644 --- a/nis.subproj/ypclnt.h +++ b/nis.subproj/ypclnt.h @@ -55,6 +55,8 @@ #ifndef _RPCSVC_YPCLNT_H_ #define _RPCSVC_YPCLNT_H_ +#include + #define YPERR_BADARGS 1 /* args to function are bad */ #define YPERR_RPC 2 /* RPC failure */ #define YPERR_DOMAIN 3 /* can't bind to a server for domain */ @@ -82,7 +84,7 @@ struct ypall_callback { /* return non-0 to stop getting called */ - int (*foreach) __P((u_long, char *, int, char *, int, void *)); + int (*foreach) __P((unsigned long, char *, int, char *, int, void *)); char *data; /* opaque pointer for use of callback fn */ }; diff --git a/nis.subproj/ypinternal.h b/nis.subproj/ypinternal.h index da7451a..848c572 100644 --- a/nis.subproj/ypinternal.h +++ b/nis.subproj/ypinternal.h @@ -62,10 +62,10 @@ struct dom_binding { struct dom_binding *dom_pnext; char dom_domain[YPMAXDOMAIN + 1]; struct sockaddr_in dom_server_addr; - u_short dom_server_port; + unsigned short dom_server_port; int dom_socket; CLIENT *dom_client; - u_short dom_local_port; + unsigned short dom_local_port; long dom_vers; }; @@ -82,9 +82,9 @@ int _yp_check __P((char **)); #ifdef YPMATCHCACHE static bool_t ypmatch_add __P((const char *, const char *, - u_int, char *, u_int)); + unsigned int, char *, unsigned int)); static bool_t ypmatch_find __P((const char *, const char *, - u_int, char **, u_int *)); + unsigned int, char **, unsigned int *)); static struct ypmatch_ent { struct ypmatch_ent *next; diff --git a/rpc.subproj/Makefile b/rpc.subproj/Makefile index 4bf2c53..1139cb3 100644 --- a/rpc.subproj/Makefile +++ b/rpc.subproj/Makefile @@ -13,7 +13,7 @@ PROJECTVERSION = 2.8 PROJECT_TYPE = Component HFILES = auth.h auth_unix.h clnt.h pmap_clnt.h pmap_prot.h pmap_rmt.h\ - rpc.h rpc_msg.h svc.h svc_auth.h types.h xdr.h + rpc.h rpc_msg.h svc.h svc_auth.h types.h xdr.h pmap_wakeup.h CFILES = auth_none.c auth_unix.c authunix_prot.c bindresvport.c\ clnt_generic.c clnt_perror.c clnt_raw.c clnt_simple.c\ @@ -23,7 +23,7 @@ CFILES = auth_none.c auth_unix.c authunix_prot.c bindresvport.c\ rpc_prot.c svc.c svc_auth.c svc_auth_unix.c svc_raw.c\ svc_run.c svc_simple.c svc_tcp.c getrpcent.c svc_udp.c xdr.c\ xdr_array.c xdr_float.c xdr_mem.c xdr_rec.c xdr_reference.c\ - xdr_stdio.c getrpcport.c + xdr_sizeof.c xdr_stdio.c getrpcport.c pmap_wakeup.c OTHERSRCS = Makefile.preamble Makefile diff --git a/rpc.subproj/Makefile.preamble b/rpc.subproj/Makefile.preamble index 1d84ceb..83c6f72 100644 --- a/rpc.subproj/Makefile.preamble +++ b/rpc.subproj/Makefile.preamble @@ -6,3 +6,7 @@ OTHER_CFLAGS = \ -Dgetrpcbynumber=_old_getrpcbynumber PUBLIC_HEADER_DIR_SUFFIX = /rpc + +# for building 64-bit +# Libinfo need to build with gcc-3.5 and 3-way fat +NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER) diff --git a/rpc.subproj/PB.project b/rpc.subproj/PB.project index 859704b..f7685fe 100644 --- a/rpc.subproj/PB.project +++ b/rpc.subproj/PB.project @@ -8,6 +8,7 @@ pmap_clnt.h, pmap_prot.h, pmap_rmt.h, + pmap_wakeup.h, rpc.h, rpc_msg.h, svc.h, @@ -33,6 +34,7 @@ pmap_prot.c, pmap_prot2.c, pmap_rmt.c, + pmap_wakeup.c, rpc_callmsg.c, rpc_commondata.c, rpc_dtablesize.c, @@ -52,6 +54,7 @@ xdr_mem.c, xdr_rec.c, xdr_reference.c, + xdr_sizeof.c, xdr_stdio.c, getrpcport.c ); diff --git a/rpc.subproj/auth.h b/rpc.subproj/auth.h index bc5f843..4c3b528 100644 --- a/rpc.subproj/auth.h +++ b/rpc.subproj/auth.h @@ -51,7 +51,7 @@ * * from: @(#)auth.h 1.17 88/02/08 SMI * from: @(#)auth.h 2.3 88/08/07 4.0 RPCSRC - * $Id: auth.h,v 1.2 1999/10/14 21:56:52 wsanchez Exp $ + * $Id: auth.h,v 1.4 2004/11/25 19:41:19 emoy Exp $ */ /* @@ -91,7 +91,7 @@ enum auth_stat { AUTH_FAILED=7 /* some unknown reason */ }; -typedef u_long u_int32; /* 32-bit unsigned integers */ +typedef unsigned long u_int32; /* 32-bit unsigned integers */ union des_block { struct { @@ -111,7 +111,7 @@ __END_DECLS struct opaque_auth { enum_t oa_flavor; /* flavor of auth */ caddr_t oa_base; /* address of more auth stuff */ - u_int oa_length; /* not to exceed MAX_AUTH_BYTES */ + unsigned int oa_length; /* not to exceed MAX_AUTH_BYTES */ }; @@ -123,11 +123,20 @@ typedef struct { struct opaque_auth ah_verf; union des_block ah_key; struct auth_ops { - void (*ah_nextverf)(); - int (*ah_marshal)(); /* nextverf & serialize */ - int (*ah_validate)(); /* validate varifier */ - int (*ah_refresh)(); /* refresh credentials */ - void (*ah_destroy)(); /* destroy this structure */ +#ifdef __cplusplus + void (*ah_nextverf)(...); + int (*ah_marshal)(...); /* nextverf & serialize */ + int (*ah_validate)(...); /* validate varifier */ + int (*ah_refresh)(...); /* refresh credentials */ + void (*ah_destroy)(...); /* destroy this structure */ +#else + /* DO NOT REMOVE THE COMMENTED OUT ...: fixincludes needs to see them */ + void (*ah_nextverf)(/*...*/); + int (*ah_marshal)(/*...*/); /* nextverf & serialize */ + int (*ah_validate)(/*...*/); /* validate varifier */ + int (*ah_refresh)(/*...*/); /* refresh credentials */ + void (*ah_destroy)(/*...*/); /* destroy this structure */ +#endif } *ah_ops; caddr_t ah_private; } AUTH; @@ -187,7 +196,7 @@ __BEGIN_DECLS extern AUTH *authunix_create __P((char *, int, int, int, int *)); extern AUTH *authunix_create_default __P((void)); extern AUTH *authnone_create __P((void)); -extern AUTH *authdes_create __P((char *, u_int, +extern AUTH *authdes_create __P((char *, unsigned int, struct sockaddr_in *, des_block *)); __END_DECLS diff --git a/rpc.subproj/auth_unix.h b/rpc.subproj/auth_unix.h index a26f59a..8870544 100644 --- a/rpc.subproj/auth_unix.h +++ b/rpc.subproj/auth_unix.h @@ -51,7 +51,7 @@ * * from: @(#)auth_unix.h 1.8 88/02/08 SMI * from: @(#)auth_unix.h 2.2 88/07/29 4.0 RPCSRC - * $Id: auth_unix.h,v 1.3 2001/01/17 19:05:42 majka Exp $ + * $Id: auth_unix.h,v 1.4 2004/10/28 21:58:21 emoy Exp $ */ /* @@ -78,11 +78,11 @@ * Unix style credentials. */ struct authunix_parms { - u_long aup_time; + unsigned long aup_time; char *aup_machname; int aup_uid; int aup_gid; - u_int aup_len; + unsigned int aup_len; int *aup_gids; }; diff --git a/rpc.subproj/clnt.h b/rpc.subproj/clnt.h index ba38098..4aeca14 100644 --- a/rpc.subproj/clnt.h +++ b/rpc.subproj/clnt.h @@ -51,7 +51,7 @@ * * from: @(#)clnt.h 1.31 88/02/08 SMI * from: @(#)clnt.h 2.1 88/07/29 4.0 RPCSRC - * $Id: clnt.h,v 1.3 2003/07/03 21:56:21 majka Exp $ + * $Id: clnt.h,v 1.4 2004/10/28 21:58:22 emoy Exp $ */ /* @@ -123,8 +123,8 @@ struct rpc_err { int RE_errno; /* realated system error */ enum auth_stat RE_why; /* why the auth error occurred */ struct { - u_long low; /* lowest verion supported */ - u_long high; /* highest verion supported */ + unsigned long low; /* lowest verion supported */ + unsigned long high; /* highest verion supported */ } RE_vers; struct { /* maybe meaningful if RPC_FAILED */ long s1; @@ -148,7 +148,7 @@ struct CLIENT { AUTH *cl_auth; /* authenticator */ struct clnt_ops { - enum clnt_stat (*cl_call)(CLIENT *, u_long, xdrproc_t, void *, xdrproc_t, void *, struct timeval); /* call remote procedure */ + enum clnt_stat (*cl_call)(CLIENT *, unsigned long, xdrproc_t, void *, xdrproc_t, void *, struct timeval); /* call remote procedure */ void (*cl_abort)(void); /* abort a call */ void (*cl_geterr)(CLIENT *, struct rpc_err *); /* get specific error code */ bool_t (*cl_freeres)(CLIENT *, xdrproc_t, void *); /* frees results */ @@ -169,7 +169,7 @@ struct CLIENT * enum clnt_stat * CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout) * CLIENT *rh; - * u_long proc; + * unsigned long proc; * xdrproc_t xargs; * caddr_t argsp; * xdrproc_t xres; @@ -212,7 +212,7 @@ struct CLIENT * bool_t * CLNT_CONTROL(cl, request, info) * CLIENT *cl; - * u_int request; + * unsigned int request; * char *info; */ #define CLNT_CONTROL(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in)) @@ -245,16 +245,16 @@ struct CLIENT * and network administration. */ -#define RPCTEST_PROGRAM ((u_long)1) -#define RPCTEST_VERSION ((u_long)1) -#define RPCTEST_NULL_PROC ((u_long)2) -#define RPCTEST_NULL_BATCH_PROC ((u_long)3) +#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) /* * By convention, procedure 0 takes null arguments and returns them */ -#define NULLPROC ((u_long)0) +#define NULLPROC ((unsigned long)0) /* * Below are the client handle creation routines for the various @@ -266,11 +266,11 @@ struct CLIENT * Memory based rpc (for speed check and testing) * CLIENT * * clntraw_create(prog, vers) - * u_long prog; - * u_long vers; + * unsigned long prog; + * unsigned long vers; */ __BEGIN_DECLS -extern CLIENT *clntraw_create __P((u_long, u_long)); +extern CLIENT *clntraw_create __P((unsigned long, unsigned long)); __END_DECLS @@ -279,12 +279,12 @@ __END_DECLS * CLIENT * * clnt_create(host, prog, vers, prot); * char *host; -- hostname - * u_long prog; -- program number - * u_long vers; -- version number + * unsigned long prog; -- program number + * unsigned long vers; -- version number * char *prot; -- protocol */ __BEGIN_DECLS -extern CLIENT *clnt_create __P((char *, u_long, u_long, char *)); +extern CLIENT *clnt_create __P((char *, unsigned long, unsigned long, char *)); __END_DECLS @@ -293,19 +293,19 @@ __END_DECLS * CLIENT * * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) * struct sockaddr_in *raddr; - * u_long prog; - * u_long version; + * unsigned long prog; + * unsigned long version; * register int *sockp; - * u_int sendsz; - * u_int recvsz; + * unsigned int sendsz; + * unsigned int recvsz; */ __BEGIN_DECLS extern CLIENT *clnttcp_create __P((struct sockaddr_in *, - u_long, - u_long, + unsigned long, + unsigned long, int *, - u_int, - u_int)); + unsigned int, + unsigned int)); __END_DECLS @@ -314,8 +314,8 @@ __END_DECLS * CLIENT * * clntudp_create(raddr, program, version, wait, sockp) * struct sockaddr_in *raddr; - * u_long program; - * u_long version; + * unsigned long program; + * unsigned long version; * struct timeval wait; * int *sockp; * @@ -323,26 +323,26 @@ __END_DECLS * CLIENT * * clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz) * struct sockaddr_in *raddr; - * u_long program; - * u_long version; + * unsigned long program; + * unsigned long version; * struct timeval wait; * int *sockp; - * u_int sendsz; - * u_int recvsz; + * unsigned int sendsz; + * unsigned int recvsz; */ __BEGIN_DECLS extern CLIENT *clntudp_create __P((struct sockaddr_in *, - u_long, - u_long, + unsigned long, + unsigned long, struct timeval, int *)); extern CLIENT *clntudp_bufcreate __P((struct sockaddr_in *, - u_long, - u_long, + unsigned long, + unsigned long, struct timeval, int *, - u_int, - u_int)); + unsigned int, + unsigned int)); __END_DECLS diff --git a/rpc.subproj/pmap_clnt.c b/rpc.subproj/pmap_clnt.c index 087e4a8..0a89232 100644 --- a/rpc.subproj/pmap_clnt.c +++ b/rpc.subproj/pmap_clnt.c @@ -53,7 +53,7 @@ #if defined(LIBC_SCCS) && !defined(lint) /*static char *sccsid = "from: @(#)pmap_clnt.c 1.37 87/08/11 Copyr 1984 Sun Micro";*/ /*static char *sccsid = "from: @(#)pmap_clnt.c 2.2 88/08/01 4.0 RPCSRC";*/ -static char *rcsid = "$Id: pmap_clnt.c,v 1.4 2002/02/19 20:36:23 epeyton Exp $"; +static char *rcsid = "$Id: pmap_clnt.c,v 1.5 2004/12/19 22:45:44 zarzycki Exp $"; #endif /* @@ -74,6 +74,8 @@ static char *rcsid = "$Id: pmap_clnt.c,v 1.4 2002/02/19 20:36:23 epeyton Exp $"; #include #include +#include "pmap_wakeup.h" + static struct timeval timeout = { 5, 0 }; static struct timeval tottimeout = { 60, 0 }; @@ -97,6 +99,8 @@ pmap_set(program, version, protocol, port) struct pmap parms; bool_t rslt; + pmap_wakeup(); + memset(&myaddress, 0, sizeof(struct sockaddr_in)); myaddress.sin_family = AF_INET; myaddress.sin_addr.s_addr = htonl(INADDR_LOOPBACK); @@ -134,6 +138,8 @@ pmap_unset(program, version) struct pmap parms; bool_t rslt; + pmap_wakeup(); + memset(&myaddress, 0, sizeof(struct sockaddr_in)); myaddress.sin_family = AF_INET; myaddress.sin_addr.s_addr = htonl(INADDR_LOOPBACK); diff --git a/rpc.subproj/pmap_clnt.h b/rpc.subproj/pmap_clnt.h index 16e7fed..f89b81e 100644 --- a/rpc.subproj/pmap_clnt.h +++ b/rpc.subproj/pmap_clnt.h @@ -51,7 +51,7 @@ * * from: @(#)pmap_clnt.h 1.11 88/02/08 SMI * from: @(#)pmap_clnt.h 2.1 88/07/29 4.0 RPCSRC - * $Id: pmap_clnt.h,v 1.2 1999/10/14 21:56:53 wsanchez Exp $ + * $Id: pmap_clnt.h,v 1.3 2004/10/28 21:58:22 emoy Exp $ */ /* @@ -88,20 +88,20 @@ #include __BEGIN_DECLS -extern bool_t pmap_set __P((u_long, u_long, int, int)); -extern bool_t pmap_unset __P((u_long, u_long)); +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 *, - u_long, u_long, u_long, + unsigned long, unsigned long, unsigned long, xdrproc_t, caddr_t, xdrproc_t, caddr_t, - struct timeval, u_long *)); -extern enum clnt_stat clnt_broadcast __P((u_long, u_long, u_long, + 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 (*)())); -extern u_short pmap_getport __P((struct sockaddr_in *, - u_long, u_long, u_int)); +extern unsigned short pmap_getport __P((struct sockaddr_in *, + unsigned long, unsigned long, unsigned int)); __END_DECLS #endif /* !_RPC_PMAPCLNT_H */ diff --git a/rpc.subproj/pmap_getmaps.c b/rpc.subproj/pmap_getmaps.c index 2d8b341..98eeedd 100644 --- a/rpc.subproj/pmap_getmaps.c +++ b/rpc.subproj/pmap_getmaps.c @@ -53,7 +53,7 @@ #if defined(LIBC_SCCS) && !defined(lint) /*static char *sccsid = "from: @(#)pmap_getmaps.c 1.10 87/08/11 Copyr 1984 Sun Micro";*/ /*static char *sccsid = "from: @(#)pmap_getmaps.c 2.2 88/08/01 4.0 RPCSRC";*/ -static char *rcsid = "$Id: pmap_getmaps.c,v 1.3 2002/02/19 20:36:24 epeyton Exp $"; +static char *rcsid = "$Id: pmap_getmaps.c,v 1.4 2004/12/19 22:45:44 zarzycki Exp $"; #endif /* @@ -77,6 +77,8 @@ static char *rcsid = "$Id: pmap_getmaps.c,v 1.3 2002/02/19 20:36:24 epeyton Exp #define NAMELEN 255 #define MAX_BROADCAST_SIZE 1400 +#include "pmap_wakeup.h" + extern int errno; /* @@ -92,6 +94,8 @@ pmap_getmaps(address) struct timeval minutetimeout; register CLIENT *client; + pmap_wakeup(); + minutetimeout.tv_sec = 60; minutetimeout.tv_usec = 0; address->sin_port = htons(PMAPPORT); diff --git a/rpc.subproj/pmap_getport.c b/rpc.subproj/pmap_getport.c index 2e78d39..2c33f72 100644 --- a/rpc.subproj/pmap_getport.c +++ b/rpc.subproj/pmap_getport.c @@ -53,7 +53,7 @@ #if defined(LIBC_SCCS) && !defined(lint) /*static char *sccsid = "from: @(#)pmap_getport.c 1.9 87/08/11 Copyr 1984 Sun Micro";*/ /*static char *sccsid = "from: @(#)pmap_getport.c 2.2 88/08/01 4.0 RPCSRC";*/ -static char *rcsid = "$Id: pmap_getport.c,v 1.3 2002/02/19 20:36:24 epeyton Exp $"; +static char *rcsid = "$Id: pmap_getport.c,v 1.4 2004/12/19 22:45:44 zarzycki Exp $"; #endif /* @@ -70,6 +70,8 @@ static char *rcsid = "$Id: pmap_getport.c,v 1.3 2002/02/19 20:36:24 epeyton Exp #include #include +#include "pmap_wakeup.h" + static struct timeval timeout = { 5, 0 }; static struct timeval tottimeout = { 60, 0 }; @@ -90,6 +92,8 @@ pmap_getport(address, program, version, protocol) register CLIENT *client; struct pmap parms; + pmap_wakeup(); + address->sin_port = htons(PMAPPORT); client = clntudp_bufcreate(address, PMAPPROG, PMAPVERS, timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); diff --git a/rpc.subproj/pmap_prot.h b/rpc.subproj/pmap_prot.h index 1565f5e..a51ce23 100644 --- a/rpc.subproj/pmap_prot.h +++ b/rpc.subproj/pmap_prot.h @@ -51,7 +51,7 @@ * * from: @(#)pmap_prot.h 1.14 88/02/08 SMI * from: @(#)pmap_prot.h 2.1 88/07/29 4.0 RPCSRC - * $Id: pmap_prot.h,v 1.2 1999/10/14 21:56:53 wsanchez Exp $ + * $Id: pmap_prot.h,v 1.3 2004/10/28 21:58:22 emoy Exp $ */ /* @@ -95,17 +95,17 @@ #define _RPC_PMAPPROT_H #include -#define PMAPPORT ((u_short)111) -#define PMAPPROG ((u_long)100000) -#define PMAPVERS ((u_long)2) -#define PMAPVERS_PROTO ((u_long)2) -#define PMAPVERS_ORIG ((u_long)1) -#define PMAPPROC_NULL ((u_long)0) -#define PMAPPROC_SET ((u_long)1) -#define PMAPPROC_UNSET ((u_long)2) -#define PMAPPROC_GETPORT ((u_long)3) -#define PMAPPROC_DUMP ((u_long)4) -#define PMAPPROC_CALLIT ((u_long)5) +#define PMAPPORT ((unsigned short)111) +#define PMAPPROG ((unsigned long)100000) +#define PMAPVERS ((unsigned long)2) +#define PMAPVERS_PROTO ((unsigned long)2) +#define PMAPVERS_ORIG ((unsigned long)1) +#define PMAPPROC_NULL ((unsigned long)0) +#define PMAPPROC_SET ((unsigned long)1) +#define PMAPPROC_UNSET ((unsigned long)2) +#define PMAPPROC_GETPORT ((unsigned long)3) +#define PMAPPROC_DUMP ((unsigned long)4) +#define PMAPPROC_CALLIT ((unsigned long)5) struct pmap { long unsigned pm_prog; diff --git a/rpc.subproj/pmap_rmt.c b/rpc.subproj/pmap_rmt.c index f478bbc..a91b2a2 100644 --- a/rpc.subproj/pmap_rmt.c +++ b/rpc.subproj/pmap_rmt.c @@ -53,7 +53,7 @@ #if defined(LIBC_SCCS) && !defined(lint) /*static char *sccsid = "from: @(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro";*/ /*static char *sccsid = "from: @(#)pmap_rmt.c 2.2 88/08/01 4.0 RPCSRC";*/ -static char *rcsid = "$Id: pmap_rmt.c,v 1.5 2003/06/05 21:43:28 majka Exp $"; +static char *rcsid = "$Id: pmap_rmt.c,v 1.6 2004/12/19 22:45:44 zarzycki Exp $"; #endif /* @@ -79,7 +79,8 @@ static char *rcsid = "$Id: pmap_rmt.c,v 1.5 2003/06/05 21:43:28 majka Exp $"; #include #define MAX_BROADCAST_SIZE 1400 -extern int errno; +#include "pmap_wakeup.h" + static struct timeval timeout = { 3, 0 }; @@ -105,6 +106,8 @@ pmap_rmtcall(addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout, port_pt struct rmtcallres r; enum clnt_stat stat; + pmap_wakeup(); + addr->sin_port = htons(PMAPPORT); client = clntudp_create(addr, PMAPPROG, PMAPVERS, timeout, &socket); if (client != (CLIENT *)NULL) { diff --git a/rpc.subproj/pmap_rmt.h b/rpc.subproj/pmap_rmt.h index a6782a5..a768d46 100644 --- a/rpc.subproj/pmap_rmt.h +++ b/rpc.subproj/pmap_rmt.h @@ -51,7 +51,7 @@ * * from: @(#)pmap_rmt.h 1.2 88/02/08 SMI * from: @(#)pmap_rmt.h 2.1 88/07/29 4.0 RPCSRC - * $Id: pmap_rmt.h,v 1.2 1999/10/14 21:56:53 wsanchez Exp $ + * $Id: pmap_rmt.h,v 1.3 2004/10/28 21:58:23 emoy Exp $ */ /* @@ -66,14 +66,14 @@ #include struct rmtcallargs { - u_long prog, vers, proc, arglen; + unsigned long prog, vers, proc, arglen; caddr_t args_ptr; xdrproc_t xdr_args; }; struct rmtcallres { - u_long *port_ptr; - u_long resultslen; + unsigned long *port_ptr; + unsigned long resultslen; caddr_t results_ptr; xdrproc_t xdr_results; }; diff --git a/rpc.subproj/pmap_wakeup.c b/rpc.subproj/pmap_wakeup.c new file mode 100644 index 0000000..4d302e6 --- /dev/null +++ b/rpc.subproj/pmap_wakeup.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include + +#include "pmap_wakeup.h" + +void pmap_wakeup(void) +{ + struct sockaddr_un sun; + int fd; + char b; + + memset(&sun, 0, sizeof(sun)); + + sun.sun_family = AF_UNIX; + strcpy(sun.sun_path, "/var/run/portmap.socket"); + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) + return; + + if (connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) { + close(fd); + return; + } + + read(fd, &b, sizeof(b)); + close(fd); +} diff --git a/rpc.subproj/pmap_wakeup.h b/rpc.subproj/pmap_wakeup.h new file mode 100644 index 0000000..b5dda38 --- /dev/null +++ b/rpc.subproj/pmap_wakeup.h @@ -0,0 +1,6 @@ +#ifndef __PMAP_WAKEUP_H__ +#define __PMAP_WAKEUP_H__ + +void pmap_wakeup(void); + +#endif diff --git a/rpc.subproj/rpc_msg.h b/rpc.subproj/rpc_msg.h index 53373d0..6f5611b 100644 --- a/rpc.subproj/rpc_msg.h +++ b/rpc.subproj/rpc_msg.h @@ -51,7 +51,7 @@ * * from: @(#)rpc_msg.h 1.7 86/07/16 SMI * from: @(#)rpc_msg.h 2.1 88/07/29 4.0 RPCSRC - * $Id: rpc_msg.h,v 1.2 1999/10/14 21:56:54 wsanchez Exp $ + * $Id: rpc_msg.h,v 1.3 2004/10/28 21:58:24 emoy Exp $ */ /* @@ -64,8 +64,8 @@ #ifndef _RPC_RPCMSG_H #define _RPC_RPCMSG_H -#define RPC_MSG_VERSION ((u_long) 2) -#define RPC_SERVICE_PORT ((u_short) 2048) +#define RPC_MSG_VERSION ((unsigned long) 2) +#define RPC_SERVICE_PORT ((unsigned short) 2048) /* * Bottom up definition of an rpc message. @@ -111,8 +111,8 @@ struct accepted_reply { enum accept_stat ar_stat; union { struct { - u_long low; - u_long high; + unsigned long low; + unsigned long high; } AR_versions; struct { caddr_t where; @@ -131,8 +131,8 @@ struct rejected_reply { enum reject_stat rj_stat; union { struct { - u_long low; - u_long high; + unsigned long low; + unsigned long high; } RJ_versions; enum auth_stat RJ_why; /* why authentication did not work */ } ru; @@ -157,10 +157,10 @@ struct reply_body { * Body of an rpc request call. */ struct call_body { - u_long cb_rpcvers; /* must be equal to two */ - u_long cb_prog; - u_long cb_vers; - u_long cb_proc; + unsigned long cb_rpcvers; /* must be equal to two */ + unsigned long cb_prog; + unsigned long cb_vers; + unsigned long cb_proc; struct opaque_auth cb_cred; struct opaque_auth cb_verf; /* protocol specific - provided by client */ }; @@ -169,7 +169,7 @@ struct call_body { * The rpc message */ struct rpc_msg { - u_long rm_xid; + unsigned long rm_xid; enum msg_type rm_direction; union { struct call_body RM_cmb; diff --git a/rpc.subproj/svc.h b/rpc.subproj/svc.h index 8a3004e..55df0fd 100644 --- a/rpc.subproj/svc.h +++ b/rpc.subproj/svc.h @@ -51,7 +51,7 @@ * * from: @(#)svc.h 1.20 88/02/08 SMI * from: @(#)svc.h 2.2 88/07/29 4.0 RPCSRC - * $Id: svc.h,v 1.2 1999/10/14 21:56:54 wsanchez Exp $ + * $Id: svc.h,v 1.4 2004/11/25 19:41:19 emoy Exp $ */ /* @@ -97,14 +97,24 @@ enum xprt_stat { */ typedef struct { int xp_sock; - u_short xp_port; /* associated port number */ + unsigned short xp_port; /* associated port number */ struct xp_ops { - bool_t (*xp_recv)(); /* receive incomming requests */ - enum xprt_stat (*xp_stat)(); /* get transport status */ - bool_t (*xp_getargs)(); /* get arguments */ - bool_t (*xp_reply)(); /* send reply */ - bool_t (*xp_freeargs)();/* free mem allocated for args */ - void (*xp_destroy)(); /* destroy this struct */ +#ifdef __cplusplus + bool_t (*xp_recv)(...); /* receive incomming requests */ + enum xprt_stat (*xp_stat)(...); /* get transport status */ + bool_t (*xp_getargs)(...); /* get arguments */ + bool_t (*xp_reply)(...); /* send reply */ + bool_t (*xp_freeargs)(...);/* free mem allocated for args */ + void (*xp_destroy)(...); /* destroy this struct */ +#else + /* DO NOT REMOVE THE COMMENTED OUT ...: fixincludes needs to see them */ + bool_t (*xp_recv)(/*...*/); /* receive incomming requests */ + enum xprt_stat (*xp_stat)(/*...*/); /* get transport status */ + bool_t (*xp_getargs)(/*...*/); /* get arguments */ + bool_t (*xp_reply)(/*...*/); /* send reply */ + bool_t (*xp_freeargs)(/*...*/);/* free mem allocated for args */ + void (*xp_destroy)(/*...*/); /* destroy this struct */ +#endif } *xp_ops; int xp_addrlen; /* length of remote address */ struct sockaddr_in xp_raddr; /* remote address */ @@ -161,9 +171,9 @@ typedef struct { * Service request */ struct svc_req { - u_long rq_prog; /* service program number */ - u_long rq_vers; /* service protocol version */ - u_long rq_proc; /* the desired procedure */ + unsigned long rq_prog; /* service program number */ + unsigned long rq_vers; /* service protocol version */ + unsigned long rq_proc; /* the desired procedure */ struct opaque_auth rq_cred; /* raw creds from the wire */ caddr_t rq_clntcred; /* read only cooked cred */ SVCXPRT *rq_xprt; /* associated transport */ @@ -175,24 +185,24 @@ struct svc_req { * * svc_register(xprt, prog, vers, dispatch, protocol) * SVCXPRT *xprt; - * u_long prog; - * u_long vers; - * void (*dispatch)(); + * unsigned long prog; + * unsigned long vers; + * void (*dispatch)(...); // fixincludes needs the ..., even in a comment * int protocol; like TCP or UDP, zero means do not register */ __BEGIN_DECLS -extern bool_t svc_register __P((SVCXPRT *, u_long, u_long, void (*)(), int)); +extern bool_t svc_register __P((SVCXPRT *, unsigned long, unsigned long, void (*)(), int)); __END_DECLS /* * Service un-registration * * svc_unregister(prog, vers) - * u_long prog; - * u_long vers; + * unsigned long prog; + * unsigned long vers; */ __BEGIN_DECLS -extern void svc_unregister __P((u_long, u_long)); +extern void svc_unregister __P((unsigned long, unsigned long)); __END_DECLS /* @@ -249,7 +259,7 @@ extern bool_t svc_sendreply __P((SVCXPRT *, xdrproc_t, char *)); extern void svcerr_decode __P((SVCXPRT *)); extern void svcerr_weakauth __P((SVCXPRT *)); extern void svcerr_noproc __P((SVCXPRT *)); -extern void svcerr_progvers __P((SVCXPRT *, u_long, u_long)); +extern void svcerr_progvers __P((SVCXPRT *, unsigned long, unsigned long)); extern void svcerr_auth __P((SVCXPRT *, enum auth_stat)); extern void svcerr_noprog __P((SVCXPRT *)); extern void svcerr_systemerr __P((SVCXPRT *)); @@ -311,7 +321,7 @@ __END_DECLS */ __BEGIN_DECLS extern SVCXPRT *svcudp_create __P((int)); -extern SVCXPRT *svcudp_bufcreate __P((int, u_int, u_int)); +extern SVCXPRT *svcudp_bufcreate __P((int, unsigned int, unsigned int)); __END_DECLS @@ -319,7 +329,7 @@ __END_DECLS * Tcp based rpc. */ __BEGIN_DECLS -extern SVCXPRT *svctcp_create __P((int, u_int, u_int)); +extern SVCXPRT *svctcp_create __P((int, unsigned int, unsigned int)); __END_DECLS #endif /* !_RPC_SVC_H */ diff --git a/rpc.subproj/svc_tcp.c b/rpc.subproj/svc_tcp.c index 52d0c69..59303fe 100644 --- a/rpc.subproj/svc_tcp.c +++ b/rpc.subproj/svc_tcp.c @@ -53,7 +53,7 @@ #if defined(LIBC_SCCS) && !defined(lint) /*static char *sccsid = "from: @(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/ /*static char *sccsid = "from: @(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC";*/ -static char *rcsid = "$Id: svc_tcp.c,v 1.5 2003/06/23 17:24:59 majka Exp $"; +static char *rcsid = "$Id: svc_tcp.c,v 1.6 2004/06/11 16:28:07 majka Exp $"; #endif /* @@ -348,11 +348,6 @@ readtcp(xprt, buf, len) { ready = TRUE; } - else - { - svc_getreqset(&readfds); - } - } while (!ready); if ((len = read(sock, buf, len)) > 0) return len; diff --git a/rpc.subproj/svc_udp.c b/rpc.subproj/svc_udp.c index 5d799b8..5f836b4 100644 --- a/rpc.subproj/svc_udp.c +++ b/rpc.subproj/svc_udp.c @@ -53,7 +53,7 @@ #if defined(LIBC_SCCS) && !defined(lint) /*static char *sccsid = "from: @(#)svc_udp.c 1.24 87/08/11 Copyr 1984 Sun Micro";*/ /*static char *sccsid = "from: @(#)svc_udp.c 2.2 88/07/29 4.0 RPCSRC";*/ -static char *rcsid = "$Id: svc_udp.c,v 1.3 2002/02/19 20:36:25 epeyton Exp $"; +static char *rcsid = "$Id: svc_udp.c,v 1.5 2004/10/13 00:24:07 jkh Exp $"; #endif /* @@ -70,6 +70,7 @@ static char *rcsid = "$Id: svc_udp.c,v 1.3 2002/02/19 20:36:25 epeyton Exp $"; #include #include #include +#include #include extern int bindresvport(); @@ -192,6 +193,9 @@ svcudp_stat(xprt) return (XPRT_IDLE); } +static int cache_get(); +static void cache_set(); + static bool_t svcudp_recv(xprt, msg) register SVCXPRT *xprt; @@ -202,7 +206,6 @@ svcudp_recv(xprt, msg) register int rlen; char *reply; u_long replylen; - static int cache_get(); again: xprt->xp_addrlen = sizeof(struct sockaddr_in); @@ -236,7 +239,6 @@ svcudp_reply(xprt, msg) register XDR *xdrs = &(su->su_xdrs); register int slen; register bool_t stat = FALSE; - static void cache_set(); xdrs->x_op = XDR_ENCODE; XDR_SETPOS(xdrs, 0); diff --git a/rpc.subproj/types.h b/rpc.subproj/types.h index 79f7ede..33ae11c 100644 --- a/rpc.subproj/types.h +++ b/rpc.subproj/types.h @@ -51,7 +51,7 @@ * * from: @(#)types.h 1.18 87/07/24 SMI * from: @(#)types.h 2.3 88/08/15 4.0 RPCSRC - * $Id: types.h,v 1.3 2002/07/27 18:24:28 majka Exp $ + * $Id: types.h,v 1.4 2003/10/16 22:15:15 majka Exp $ */ /* @@ -70,9 +70,18 @@ #ifndef TRUE # define TRUE (1) #endif + #ifndef NULL -# define NULL 0 -#endif +#ifdef __GNUG__ +#define NULL __null +#else /* ! __GNUG__ */ +#ifndef __cplusplus +#define NULL ((void *)0) +#else /* __cplusplus */ +#define NULL 0 +#endif /* ! __cplusplus */ +#endif /* __GNUG__ */ +#endif /* ! NULL */ #define mem_alloc(bsize) calloc(1, bsize) #define mem_free(ptr, bsize) free(ptr) diff --git a/rpc.subproj/xdr.c b/rpc.subproj/xdr.c index 6423726..d9b60a5 100644 --- a/rpc.subproj/xdr.c +++ b/rpc.subproj/xdr.c @@ -21,6 +21,9 @@ * * @APPLE_LICENSE_HEADER_END@ */ + +/* $NetBSD: xdr.c,v 1.22 2000/07/06 03:10:35 christos Exp $ */ + /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape @@ -28,33 +31,33 @@ * 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 */ #if defined(LIBC_SCCS) && !defined(lint) -/*static char *sccsid = "from: @(#)xdr.c 1.35 87/08/12";*/ -/*static char *sccsid = "from: @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC";*/ -static char *rcsid = "$Id: xdr.c,v 1.4 2003/06/23 17:24:59 majka Exp $"; +static char *sccsid = "@(#)xdr.c 1.35 87/08/12"; +static char *sccsid = "@(#)xdr.c 2.1 88/07/29 4.0 RPCSRC"; #endif +#include /* * xdr.c, Generic XDR routines implementation. @@ -66,6 +69,7 @@ static char *rcsid = "$Id: xdr.c,v 1.4 2003/06/23 17:24:59 majka Exp $"; * xdr. */ +#include #include #include #include @@ -73,6 +77,9 @@ static char *rcsid = "$Id: xdr.c,v 1.4 2003/06/23 17:24:59 majka Exp $"; #include #include +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" */ @@ -83,7 +90,7 @@ static char *rcsid = "$Id: xdr.c,v 1.4 2003/06/23 17:24:59 majka Exp $"; /* * for unit alignment */ -static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 }; +static const char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 }; /* * Free a data structure using XDR @@ -92,11 +99,7 @@ static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 }; void xdr_free(proc, objp) xdrproc_t proc; -#if defined(__APPLE__) void *objp; -#else - char *objp; -#endif /* !NeXT */ { XDR x; @@ -108,14 +111,13 @@ xdr_free(proc, objp) * XDR nothing */ bool_t -xdr_void(/* xdrs, addr */) - /* XDR *xdrs; */ - /* caddr_t addr; */ +xdr_void(void) { return (TRUE); } + /* * XDR integers */ @@ -124,17 +126,26 @@ xdr_int(xdrs, ip) XDR *xdrs; int *ip; { + long l; -#ifdef lint - (void) (xdr_short(xdrs, (short *)ip)); - return (xdr_long(xdrs, (long *)ip)); -#else - if (sizeof (int) == sizeof (long)) { - return (xdr_long(xdrs, (long *)ip)); - } else { - return (xdr_short(xdrs, (short *)ip)); + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (long) *ip; + return (XDR_PUTLONG(xdrs, &l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, &l)) { + return (FALSE); + } + *ip = (int) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); } -#endif + /* NOTREACHED */ + return (FALSE); } /* @@ -145,38 +156,47 @@ xdr_u_int(xdrs, up) XDR *xdrs; u_int *up; { + u_long l; -#ifdef lint - (void) (xdr_short(xdrs, (short *)up)); - return (xdr_u_long(xdrs, (u_long *)up)); -#else - if (sizeof (u_int) == sizeof (u_long)) { - return (xdr_u_long(xdrs, (u_long *)up)); - } else { - return (xdr_short(xdrs, (short *)up)); + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (u_long) *up; + return (XDR_PUTLONG(xdrs, (long *)&l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, (long *)&l)) { + return (FALSE); + } + *up = (u_int) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); } -#endif + /* NOTREACHED */ + return (FALSE); } + /* * XDR long integers * same as xdr_u_long - open coded to save a proc call! */ bool_t xdr_long(xdrs, lp) - register XDR *xdrs; + XDR *xdrs; long *lp; { - - if (xdrs->x_op == XDR_ENCODE) + switch (xdrs->x_op) { + case XDR_ENCODE: return (XDR_PUTLONG(xdrs, lp)); - - if (xdrs->x_op == XDR_DECODE) + case XDR_DECODE: return (XDR_GETLONG(xdrs, lp)); - - if (xdrs->x_op == XDR_FREE) + case XDR_FREE: return (TRUE); - + } + /* NOTREACHED */ return (FALSE); } @@ -186,25 +206,91 @@ xdr_long(xdrs, lp) */ bool_t xdr_u_long(xdrs, ulp) - register XDR *xdrs; + XDR *xdrs; u_long *ulp; { - - if (xdrs->x_op == XDR_DECODE) - return (XDR_GETLONG(xdrs, (long *)ulp)); - if (xdrs->x_op == XDR_ENCODE) + switch (xdrs->x_op) { + case XDR_ENCODE: return (XDR_PUTLONG(xdrs, (long *)ulp)); - if (xdrs->x_op == XDR_FREE) + case XDR_DECODE: + return (XDR_GETLONG(xdrs, (long *)ulp)); + case XDR_FREE: + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} + + +/* + * XDR 32-bit integers + * same as xdr_u_int32_t - open coded to save a proc call! + */ +bool_t +xdr_int32_t(xdrs, int32_p) + XDR *xdrs; + int32_t *int32_p; +{ + long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (long) *int32_p; + return (XDR_PUTLONG(xdrs, &l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, &l)) { + return (FALSE); + } + *int32_p = (int32_t) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} + +/* + * XDR unsigned 32-bit integers + * same as xdr_int32_t - open coded to save a proc call! + */ +bool_t +xdr_u_int32_t(xdrs, u_int32_p) + XDR *xdrs; + u_int32_t *u_int32_p; +{ + u_long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (u_long) *u_int32_p; + return (XDR_PUTLONG(xdrs, (long *)&l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, (long *)&l)) { + return (FALSE); + } + *u_int32_p = (u_int32_t) l; + return (TRUE); + + case XDR_FREE: return (TRUE); + } + /* NOTREACHED */ return (FALSE); } + /* * XDR short integers */ bool_t xdr_short(xdrs, sp) - register XDR *xdrs; + XDR *xdrs; short *sp; { long l; @@ -225,6 +311,7 @@ xdr_short(xdrs, sp) case XDR_FREE: return (TRUE); } + /* NOTREACHED */ return (FALSE); } @@ -233,7 +320,7 @@ xdr_short(xdrs, sp) */ bool_t xdr_u_short(xdrs, usp) - register XDR *xdrs; + XDR *xdrs; u_short *usp; { u_long l; @@ -242,18 +329,80 @@ xdr_u_short(xdrs, usp) case XDR_ENCODE: l = (u_long) *usp; + return (XDR_PUTLONG(xdrs, (long *)&l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, (long *)&l)) { + return (FALSE); + } + *usp = (u_short) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} + + +/* + * XDR 16-bit integers + */ +bool_t +xdr_int16_t(xdrs, int16_p) + XDR *xdrs; + int16_t *int16_p; +{ + long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (long) *int16_p; return (XDR_PUTLONG(xdrs, &l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &l)) { return (FALSE); } - *usp = (u_short) l; + *int16_p = (int16_t) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} + +/* + * XDR unsigned 16-bit integers + */ +bool_t +xdr_u_int16_t(xdrs, u_int16_p) + XDR *xdrs; + u_int16_t *u_int16_p; +{ + u_long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (u_long) *u_int16_p; + return (XDR_PUTLONG(xdrs, (long *)&l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, (long *)&l)) { + return (FALSE); + } + *u_int16_p = (u_int16_t) l; return (TRUE); case XDR_FREE: return (TRUE); } + /* NOTREACHED */ return (FALSE); } @@ -299,7 +448,7 @@ xdr_u_char(xdrs, cp) */ bool_t xdr_bool(xdrs, bp) - register XDR *xdrs; + XDR *xdrs; bool_t *bp; { long lb; @@ -320,6 +469,7 @@ xdr_bool(xdrs, bp) case XDR_FREE: return (TRUE); } + /* NOTREACHED */ return (FALSE); } @@ -331,23 +481,20 @@ xdr_enum(xdrs, ep) XDR *xdrs; enum_t *ep; { -#ifndef lint enum sizecheck { SIZEVAL }; /* used to find the size of an enum */ /* * enums are treated as ints */ - if (sizeof (enum sizecheck) == sizeof (long)) { - return (xdr_long(xdrs, (long *)ep)); - } else if (sizeof (enum sizecheck) == sizeof (short)) { - return (xdr_short(xdrs, (short *)ep)); + /* LINTED */ if (sizeof (enum sizecheck) == sizeof (long)) { + return (xdr_long(xdrs, (long *)(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)) { + return (xdr_short(xdrs, (short *)(void *)ep)); } else { return (FALSE); } -#else - (void) (xdr_short(xdrs, (short *)ep)); - return (xdr_long(xdrs, (long *)ep)); -#endif } /* @@ -357,12 +504,12 @@ xdr_enum(xdrs, ep) */ bool_t xdr_opaque(xdrs, cp, cnt) - register XDR *xdrs; + XDR *xdrs; caddr_t cp; - register u_int cnt; + u_int cnt; { - register u_int rndup; - static char crud[BYTES_PER_XDR_UNIT]; + u_int rndup; + static int crud[BYTES_PER_XDR_UNIT]; /* * if no data we are done @@ -383,7 +530,7 @@ xdr_opaque(xdrs, cp, cnt) } if (rndup == 0) return (TRUE); - return (XDR_GETBYTES(xdrs, crud, rndup)); + return (XDR_GETBYTES(xdrs, (caddr_t)(void *)crud, rndup)); } if (xdrs->x_op == XDR_ENCODE) { @@ -409,13 +556,13 @@ xdr_opaque(xdrs, cp, cnt) */ bool_t xdr_bytes(xdrs, cpp, sizep, maxsize) - register XDR *xdrs; + XDR *xdrs; char **cpp; - register u_int *sizep; + u_int *sizep; u_int maxsize; { - register char *sp = *cpp; /* sp is the actual string pointer */ - register u_int nodesize; + char *sp = *cpp; /* sp is the actual string pointer */ + u_int nodesize; /* * first deal with the length since xdr bytes are counted @@ -438,13 +585,13 @@ xdr_bytes(xdrs, cpp, sizep, maxsize) return (TRUE); } if (sp == NULL) { - *cpp = sp = (char *)mem_alloc(nodesize); + *cpp = sp = mem_alloc(nodesize); } if (sp == NULL) { - (void) fprintf(stderr, "xdr_bytes: out of memory\n"); + warnx("xdr_bytes: out of memory"); return (FALSE); } - /* fall into ... */ + /* FALLTHROUGH */ case XDR_ENCODE: return (xdr_opaque(xdrs, sp, nodesize)); @@ -456,6 +603,7 @@ xdr_bytes(xdrs, cpp, sizep, maxsize) } return (TRUE); } + /* NOTREACHED */ return (FALSE); } @@ -484,13 +632,13 @@ xdr_netobj(xdrs, np) */ bool_t xdr_union(xdrs, dscmp, unp, choices, dfault) - register XDR *xdrs; + XDR *xdrs; enum_t *dscmp; /* enum to decide which arm to work on */ char *unp; /* the union itself */ - struct xdr_discrim *choices; /* [value, xdr proc] for each arm */ + const struct xdr_discrim *choices; /* [value, xdr proc] for each arm */ xdrproc_t dfault; /* default xdr routine */ { - register enum_t dscm; + enum_t dscm; /* * we deal with the discriminator; it's an enum @@ -506,14 +654,14 @@ xdr_union(xdrs, dscmp, unp, choices, dfault) */ for (; choices->proc != NULL_xdrproc_t; choices++) { if (choices->value == dscm) - return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED)); + return ((*(choices->proc))(xdrs, unp)); } /* * no match - execute the default xdr routine if there is one */ return ((dfault == NULL_xdrproc_t) ? FALSE : - (*dfault)(xdrs, unp, LASTUNSIGNED)); + (*dfault)(xdrs, unp)); } @@ -533,11 +681,11 @@ xdr_union(xdrs, dscmp, unp, choices, dfault) */ bool_t xdr_string(xdrs, cpp, maxsize) - register XDR *xdrs; + XDR *xdrs; char **cpp; u_int maxsize; { - register char *sp = *cpp; /* sp is the actual string pointer */ + char *sp = *cpp; /* sp is the actual string pointer */ u_int size; u_int nodesize; @@ -549,11 +697,12 @@ xdr_string(xdrs, cpp, maxsize) if (sp == NULL) { return(TRUE); /* already free */ } - /* fall through... */ + /* FALLTHROUGH */ case XDR_ENCODE: size = strlen(sp); break; - default: break; + case XDR_DECODE: + break; } if (! xdr_u_int(xdrs, &size)) { return (FALSE); @@ -573,13 +722,13 @@ xdr_string(xdrs, cpp, maxsize) return (TRUE); } if (sp == NULL) - *cpp = sp = (char *)mem_alloc(nodesize); + *cpp = sp = mem_alloc(nodesize); if (sp == NULL) { - (void) fprintf(stderr, "xdr_string: out of memory\n"); + warnx("xdr_string: out of memory"); return (FALSE); } sp[size] = 0; - /* fall into ... */ + /* FALLTHROUGH */ case XDR_ENCODE: return (xdr_opaque(xdrs, sp, size)); @@ -589,6 +738,7 @@ xdr_string(xdrs, cpp, maxsize) *cpp = NULL; return (TRUE); } + /* NOTREACHED */ return (FALSE); } @@ -601,8 +751,146 @@ xdr_wrapstring(xdrs, cpp) XDR *xdrs; char **cpp; { - if (xdr_string(xdrs, cpp, LASTUNSIGNED)) { + return xdr_string(xdrs, cpp, LASTUNSIGNED); +} + +/* + * NOTE: xdr_hyper(), xdr_u_hyper(), xdr_longlong_t(), and xdr_u_longlong_t() + * are in the "non-portable" section because they require that a `long long' + * be a 64-bit type. + * + * --thorpej@netbsd.org, November 30, 1999 + */ + +/* + * XDR 64-bit integers + */ +bool_t +xdr_int64_t(xdrs, llp) + XDR *xdrs; + int64_t *llp; +{ + u_long 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) + return (FALSE); + return (XDR_PUTLONG(xdrs, (long *)&ul[1])); + case XDR_DECODE: + if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE) + return (FALSE); + if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE) + return (FALSE); + *llp = (int64_t) + (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1])); + return (TRUE); + case XDR_FREE: + return (TRUE); + } + /* NOTREACHED */ + return (FALSE); +} + + +/* + * XDR unsigned 64-bit integers + */ +bool_t +xdr_u_int64_t(xdrs, ullp) + XDR *xdrs; + u_int64_t *ullp; +{ + u_long 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) + return (FALSE); + return (XDR_PUTLONG(xdrs, (long *)&ul[1])); + case XDR_DECODE: + if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE) + return (FALSE); + if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE) + return (FALSE); + *ullp = (u_int64_t) + (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1])); + return (TRUE); + case XDR_FREE: return (TRUE); } + /* NOTREACHED */ return (FALSE); } + + +/* + * XDR hypers + */ +bool_t +xdr_hyper(xdrs, llp) + XDR *xdrs; + longlong_t *llp; +{ + + /* + * Don't bother open-coding this; it's a fair amount of code. Just + * call xdr_int64_t(). + */ + return (xdr_int64_t(xdrs, (int64_t *)llp)); +} + + +/* + * XDR unsigned hypers + */ +bool_t +xdr_u_hyper(xdrs, ullp) + XDR *xdrs; + u_longlong_t *ullp; +{ + + /* + * Don't bother open-coding this; it's a fair amount of code. Just + * call xdr_u_int64_t(). + */ + return (xdr_u_int64_t(xdrs, (u_int64_t *)ullp)); +} + + +/* + * XDR longlong_t's + */ +bool_t +xdr_longlong_t(xdrs, llp) + XDR *xdrs; + longlong_t *llp; +{ + + /* + * Don't bother open-coding this; it's a fair amount of code. Just + * call xdr_int64_t(). + */ + return (xdr_int64_t(xdrs, (int64_t *)llp)); +} + + +/* + * XDR u_longlong_t's + */ +bool_t +xdr_u_longlong_t(xdrs, ullp) + XDR *xdrs; + u_longlong_t *ullp; +{ + + /* + * Don't bother open-coding this; it's a fair amount of code. Just + * call xdr_u_int64_t(). + */ + return (xdr_u_int64_t(xdrs, (u_int64_t *)ullp)); +} diff --git a/rpc.subproj/xdr.h b/rpc.subproj/xdr.h index a395710..24da1af 100644 --- a/rpc.subproj/xdr.h +++ b/rpc.subproj/xdr.h @@ -28,30 +28,30 @@ * 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 + * WARRANTIES OF DESIGN, MERCHANTABILITY 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 * * from: @(#)xdr.h 1.19 87/04/22 SMI * from: @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC - * $Id: xdr.h,v 1.3 2003/06/23 17:24:59 majka Exp $ + * $FreeBSD: src/include/rpc/xdr.h,v 1.23 2003/03/07 13:19:40 nectar Exp $ */ /* @@ -112,6 +112,39 @@ enum xdr_op { #define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \ * BYTES_PER_XDR_UNIT) +/* + * The XDR handle. + * Contains operation which is being applied to the stream, + * an operations vector for the particular implementation (e.g. see xdr_mem.c), + * and two private fields for the use of the particular implementation. + */ +typedef struct __rpc_xdr { + enum xdr_op x_op; /* operation; fast additional param */ + const struct xdr_ops { + /* 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 *); + /* get some bytes from " */ + bool_t (*x_getbytes)(struct __rpc_xdr *, char *, unsigned int); + /* put some bytes to " */ + bool_t (*x_putbytes)(struct __rpc_xdr *, const char *, unsigned int); + /* returns bytes off from beginning */ + unsigned int (*x_getpostn)(struct __rpc_xdr *); + /* lets you reposition the stream */ + bool_t (*x_setpostn)(struct __rpc_xdr *, unsigned int); + /* buf quick ptr to buffered data */ + int32_t *(*x_inline)(struct __rpc_xdr *, unsigned int); + /* free privates of this xdr_stream */ + void (*x_destroy)(struct __rpc_xdr *); + bool_t (*x_control)(struct __rpc_xdr *, int, void *); + } *x_ops; + char * x_public; /* users' data */ + void * x_private; /* pointer to private data */ + char * x_base; /* private used for position info */ + unsigned int x_handy; /* extra private word */ +} XDR; + /* * A xdrproc_t exists for each data type which is to be encoded or decoded. * @@ -119,42 +152,24 @@ enum xdr_op { * The opaque pointer generally points to a structure of the data type * to be decoded. If this pointer is 0, then the type routines should * allocate dynamic storage of the appropriate size and return it. - * bool_t (*xdrproc_t)(XDR *, caddr_t *); */ -typedef bool_t (*xdrproc_t)(); - +#ifdef _KERNEL +typedef bool_t (*xdrproc_t)(XDR *, void *, unsigned int); +#else /* - * The XDR handle. - * Contains operation which is being applied to the stream, - * an operations vector for the paticular implementation (e.g. see xdr_mem.c), - * and two private fields for the use of the particular impelementation. + * XXX can't actually prototype it, because some take three args!!! */ -typedef struct __rpc_xdr { - enum xdr_op x_op; /* operation; fast additional param */ - struct xdr_ops { - bool_t (*x_getlong)(struct __rpc_xdr *, long *); - bool_t (*x_putlong)(struct __rpc_xdr *, long *); - bool_t (*x_getbytes)(struct __rpc_xdr *, caddr_t, u_int); - bool_t (*x_putbytes)(struct __rpc_xdr *, caddr_t, u_int); - u_int (*x_getpostn)(struct __rpc_xdr *); - bool_t (*x_setpostn)(struct __rpc_xdr *, u_int); - long *(*x_inline)(struct __rpc_xdr *, u_int); - void (*x_destroy)(struct __rpc_xdr *); - } *x_ops; - caddr_t x_public; /* users' data */ - caddr_t x_private; /* pointer to private data */ - caddr_t x_base; /* private used for position info */ - int x_handy; /* extra private word */ -} XDR; +typedef bool_t (*xdrproc_t)(XDR *, ...); +#endif /* * Operations defined on a XDR handle * * XDR *xdrs; * long *longp; - * caddr_t addr; - * u_int len; - * u_int pos; + * char * addr; + * unsigned int len; + * unsigned int pos; */ #define XDR_GETLONG(xdrs, longp) \ (*(xdrs)->x_ops->x_getlong)(xdrs, longp) @@ -166,6 +181,29 @@ typedef struct __rpc_xdr { #define xdr_putlong(xdrs, longp) \ (*(xdrs)->x_ops->x_putlong)(xdrs, longp) +static __inline int +xdr_getint32(XDR *xdrs, int32_t *ip) +{ + long l; + + if (!xdr_getlong(xdrs, &l)) + return (FALSE); + *ip = (int32_t)l; + return (TRUE); +} + +static __inline int +xdr_putint32(XDR *xdrs, int32_t *ip) +{ + long l; + + l = (long)*ip; + return xdr_putlong(xdrs, &l); +} + +#define XDR_GETINT32(xdrs, int32p) xdr_getint32(xdrs, int32p) +#define XDR_PUTINT32(xdrs, int32p) xdr_putint32(xdrs, int32p) + #define XDR_GETBYTES(xdrs, addr, len) \ (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) #define xdr_getbytes(xdrs, addr, len) \ @@ -191,21 +229,32 @@ typedef struct __rpc_xdr { #define xdr_inline(xdrs, len) \ (*(xdrs)->x_ops->x_inline)(xdrs, len) -#define XDR_DESTROY(xdrs) \ - if (xdrs) \ - if ((xdrs)->x_ops) \ - if ((xdrs)->x_ops->x_destroy) \ - (*(xdrs)->x_ops->x_destroy)(xdrs) -#define xdr_destroy(xdrs) \ - if (xdrs) \ - if ((xdrs)->x_ops) \ - if ((xdrs)->x_ops->x_destroy) \ - (*(xdrs)->x_ops->x_destroy)(xdrs) +#define XDR_DESTROY(xdrs) \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs) +#define xdr_destroy(xdrs) \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs) + +#define XDR_CONTROL(xdrs, req, op) \ + if ((xdrs)->x_ops->x_control) \ + (*(xdrs)->x_ops->x_control)(xdrs, req, op) +#define xdr_control(xdrs, req, op) XDR_CONTROL(xdrs, req, op) + +/* + * Solaris strips the '_t' from these types -- not sure why. + * But, let's be compatible. + */ +#define xdr_rpcvers(xdrs, versp) xdr_u_int32(xdrs, versp) +#define xdr_rpcprog(xdrs, progp) xdr_u_int32(xdrs, progp) +#define xdr_rpcproc(xdrs, procp) xdr_u_int32(xdrs, procp) +#define xdr_rpcprot(xdrs, protp) xdr_u_int32(xdrs, protp) +#define xdr_rpcport(xdrs, portp) xdr_u_int32(xdrs, portp) /* * Support struct for discriminated unions. * You create an array of xdrdiscrim structures, terminated with - * a entry with a null procedure pointer. The xdr_union routine gets + * an entry with a null procedure pointer. The xdr_union routine gets * the discriminant value and then searches the array of structures * for a matching value. If a match is found the associated xdr routine * is called to handle that part of the union. If there is @@ -219,7 +268,7 @@ struct xdr_discrim { }; /* - * In-line routines for fast encode/decode of primitve data types. + * In-line routines for fast encode/decode of primitive data types. * Caveat emptor: these use single memory cycles to get the * data from the underlying buffer, and will fail to operate * properly if the data is not aligned. The standard way to use these @@ -233,61 +282,77 @@ struct xdr_discrim { * N.B. and frozen for all time: each data type here uses 4 bytes * of external representation. */ -#define IXDR_GET_LONG(buf) ((long)ntohl((u_long)*(buf)++)) -#define IXDR_PUT_LONG(buf, v) (*(buf)++ = (long)htonl((u_long)v)) +#define IXDR_GET_INT32(buf) ((int32_t)ntohl((u_int32_t)*(buf)++)) +#define IXDR_PUT_INT32(buf, v) (*(buf)++ =(int32_t)htonl((u_int32_t)v)) +#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))) + +#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)) #define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf)) #define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf)) -#define IXDR_GET_U_LONG(buf) ((u_long)IXDR_GET_LONG(buf)) +#define IXDR_GET_U_LONG(buf) ((unsigned long)IXDR_GET_LONG(buf)) #define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf)) -#define IXDR_GET_U_SHORT(buf) ((u_short)IXDR_GET_LONG(buf)) +#define IXDR_GET_U_SHORT(buf) ((unsigned short)IXDR_GET_LONG(buf)) -#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) -#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) -#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) -#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) -#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG((buf), (v)) +#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG((buf), (v)) +#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG((buf), (v)) +#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG((buf), (v)) +#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG((buf), (v)) /* * These are the "generic" xdr routines. */ __BEGIN_DECLS -extern bool_t xdr_void __P((void)); -extern bool_t xdr_int __P((XDR *, int *)); -extern bool_t xdr_u_int __P((XDR *, u_int *)); -extern bool_t xdr_long __P((XDR *, long *)); -extern bool_t xdr_u_long __P((XDR *, u_long *)); -extern bool_t xdr_short __P((XDR *, short *)); -extern bool_t xdr_u_short __P((XDR *, u_short *)); -extern bool_t xdr_bool __P((XDR *, bool_t *)); -extern bool_t xdr_enum __P((XDR *, enum_t *)); -extern bool_t xdr_array __P((XDR *, char **, u_int *, u_int, u_int, xdrproc_t)); -extern bool_t xdr_bytes __P((XDR *, char **, u_int *, u_int)); -extern bool_t xdr_opaque __P((XDR *, caddr_t, u_int)); -extern bool_t xdr_string __P((XDR *, char **, u_int)); -extern bool_t xdr_union __P((XDR *, enum_t *, char *, struct xdr_discrim *, xdrproc_t)); -extern bool_t xdr_char __P((XDR *, char *)); -extern bool_t xdr_u_char __P((XDR *, u_char *)); -extern bool_t xdr_vector __P((XDR *, char *, u_int, u_int, xdrproc_t)); -extern bool_t xdr_float __P((XDR *, float *)); -extern bool_t xdr_double __P((XDR *, double *)); -extern bool_t xdr_reference __P((XDR *, caddr_t *, u_int, xdrproc_t)); -extern bool_t xdr_pointer __P((XDR *, caddr_t *, u_int, xdrproc_t)); -extern bool_t xdr_wrapstring __P((XDR *, char **)); -extern void xdr_free __P((xdrproc_t, void *)); +extern bool_t xdr_void(void); +extern bool_t xdr_int(XDR *, int *); +extern bool_t xdr_u_int(XDR *, unsigned int *); +extern bool_t xdr_long(XDR *, long *); +extern bool_t xdr_u_long(XDR *, unsigned long *); +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 *); +extern bool_t xdr_u_int16_t(XDR *, u_int16_t *); +extern bool_t xdr_int32_t(XDR *, int32_t *); +extern bool_t xdr_u_int32_t(XDR *, u_int32_t *); +extern bool_t xdr_int64_t(XDR *, int64_t *); +extern bool_t xdr_u_int64_t(XDR *, u_int64_t *); +extern bool_t xdr_bool(XDR *, bool_t *); +extern bool_t xdr_enum(XDR *, enum_t *); +extern bool_t xdr_array(XDR *, char **, unsigned int *, unsigned int, unsigned int, xdrproc_t); +extern bool_t xdr_bytes(XDR *, char **, unsigned int *, unsigned int); +extern bool_t xdr_opaque(XDR *, char *, unsigned int); +extern bool_t xdr_string(XDR *, char **, unsigned int); +extern bool_t xdr_union(XDR *, enum_t *, char *, const struct xdr_discrim *, xdrproc_t); +extern bool_t xdr_char(XDR *, char *); +extern bool_t xdr_u_char(XDR *, unsigned char *); +extern bool_t xdr_vector(XDR *, char *, unsigned int, unsigned int, xdrproc_t); +extern bool_t xdr_float(XDR *, float *); +extern bool_t xdr_double(XDR *, double *); +extern bool_t xdr_quadruple(XDR *, long double *); +extern bool_t xdr_reference(XDR *, char **, unsigned int, xdrproc_t); +extern bool_t xdr_pointer(XDR *, char **, unsigned int, xdrproc_t); +extern bool_t xdr_wrapstring(XDR *, char **); +extern void xdr_free(xdrproc_t, void *); +extern bool_t xdr_hyper(XDR *, quad_t *); +extern bool_t xdr_u_hyper(XDR *, u_quad_t *); +extern bool_t xdr_longlong_t(XDR *, quad_t *); +extern bool_t xdr_u_longlong_t(XDR *, u_quad_t *); __END_DECLS /* * Common opaque bytes objects used by many rpc protocols; * declared here due to commonality. */ -#define MAX_NETOBJ_SZ 1024 +#define MAX_NETOBJ_SZ 1024 struct netobj { - u_int n_len; + unsigned int n_len; char *n_bytes; }; typedef struct netobj netobj; -extern bool_t xdr_netobj(); +extern bool_t xdr_netobj(XDR *, struct netobj *); /* * These are the public routines for the various implementations of @@ -295,24 +360,27 @@ extern bool_t xdr_netobj(); */ __BEGIN_DECLS /* XDR using memory buffers */ -extern void xdrmem_create __P((XDR *, void *, u_int, enum xdr_op)); +extern void xdrmem_create(XDR *, char *, unsigned int, enum xdr_op); -#ifdef _STDIO_H_ /* XDR using stdio library */ -extern void xdrstdio_create __P((XDR *, FILE *, enum xdr_op)); +#ifdef _STDIO_H_ +extern void xdrstdio_create(XDR *, FILE *, enum xdr_op); #endif /* XDR pseudo records for tcp */ -extern void xdrrec_create __P((XDR *, u_int, u_int, char *, int (*)(), int (*)())); +extern void xdrrec_create(XDR *, unsigned int, unsigned int, void *, + int (*)(void *, void *, int), + int (*)(void *, void *, int)); /* make end of xdr record */ -extern bool_t xdrrec_endofrecord __P((XDR *, int)); +extern bool_t xdrrec_endofrecord(XDR *, int); /* move to beginning of next record */ -extern bool_t xdrrec_skiprecord __P((XDR *)); +extern bool_t xdrrec_skiprecord(XDR *); /* true if no more input */ -extern bool_t xdrrec_eof __P((XDR *)); +extern bool_t xdrrec_eof(XDR *); +extern unsigned int xdrrec_readbytes(XDR *, caddr_t, unsigned int); __END_DECLS #endif /* !_RPC_XDR_H */ diff --git a/rpc.subproj/xdr_array.c b/rpc.subproj/xdr_array.c index 734f3b0..7b82e3e 100644 --- a/rpc.subproj/xdr_array.c +++ b/rpc.subproj/xdr_array.c @@ -21,6 +21,9 @@ * * @APPLE_LICENSE_HEADER_END@ */ + +/* $NetBSD: xdr_array.c,v 1.12 2000/01/22 22:19:18 mycroft Exp $ */ + /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape @@ -28,33 +31,33 @@ * 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 */ #if defined(LIBC_SCCS) && !defined(lint) -/*static char *sccsid = "from: @(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro";*/ -/*static char *sccsid = "from: @(#)xdr_array.c 2.1 88/07/29 4.0 RPCSRC";*/ -static char *rcsid = "$Id: xdr_array.c,v 1.4 2003/06/23 17:24:59 majka Exp $"; +static char *sccsid = "@(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro"; +static char *sccsid = "@(#)xdr_array.c 2.1 88/07/29 4.0 RPCSRC"; #endif +#include /* * xdr_array.c, Generic XDR routines impelmentation. @@ -65,15 +68,15 @@ static char *rcsid = "$Id: xdr_array.c,v 1.4 2003/06/23 17:24:59 majka Exp $"; * arrays. See xdr.h for more info on the interface to xdr. */ +#include +#include #include #include #include + #include #include -#define LASTUNSIGNED ((u_int)0-1) - - /* * XDR an array of arbitrary elements * *addrp is a pointer to the array, *sizep is the number of elements. @@ -83,25 +86,26 @@ static char *rcsid = "$Id: xdr_array.c,v 1.4 2003/06/23 17:24:59 majka Exp $"; */ bool_t xdr_array(xdrs, addrp, sizep, maxsize, elsize, elproc) - register XDR *xdrs; + XDR *xdrs; caddr_t *addrp; /* array pointer */ u_int *sizep; /* number of elements */ u_int maxsize; /* max numberof elements */ u_int elsize; /* size in bytes of each element */ xdrproc_t elproc; /* xdr routine to handle each element */ { - register u_int i; - register caddr_t target = *addrp; - register u_int c; /* the actual element count */ - register bool_t stat = TRUE; - register u_int nodesize; + u_int i; + caddr_t target = *addrp; + u_int c; /* the actual element count */ + bool_t stat = TRUE; + u_int nodesize; /* like strings, arrays are really counted arrays */ - if (! xdr_u_int(xdrs, sizep)) { + if (!xdr_u_int(xdrs, sizep)) { return (FALSE); } c = *sizep; - if ((c > maxsize) && (xdrs->x_op != XDR_FREE)) { + if ((c > maxsize || UINT_MAX/elsize < c) && + (xdrs->x_op != XDR_FREE)) { return (FALSE); } nodesize = c * elsize; @@ -117,24 +121,24 @@ xdr_array(xdrs, addrp, sizep, maxsize, elsize, elproc) return (TRUE); *addrp = target = mem_alloc(nodesize); if (target == NULL) { - (void) fprintf(stderr, - "xdr_array: out of memory\n"); + warnx("xdr_array: out of memory"); return (FALSE); } - bzero(target, nodesize); + memset(target, 0, nodesize); break; case XDR_FREE: return (TRUE); - default: break; + case XDR_ENCODE: + break; } /* * now we xdr each element of array */ for (i = 0; (i < c) && stat; i++) { - stat = (*elproc)(xdrs, target, LASTUNSIGNED); + stat = (*elproc)(xdrs, target); target += elsize; } @@ -160,22 +164,21 @@ xdr_array(xdrs, addrp, sizep, maxsize, elsize, elproc) */ bool_t xdr_vector(xdrs, basep, nelem, elemsize, xdr_elem) - register XDR *xdrs; - register char *basep; - register u_int nelem; - register u_int elemsize; - register xdrproc_t xdr_elem; + XDR *xdrs; + char *basep; + u_int nelem; + u_int elemsize; + xdrproc_t xdr_elem; { - register u_int i; - register char *elptr; + u_int i; + char *elptr; elptr = basep; for (i = 0; i < nelem; i++) { - if (! (*xdr_elem)(xdrs, elptr, LASTUNSIGNED)) { + if (!(*xdr_elem)(xdrs, elptr)) { return(FALSE); } elptr += elemsize; } return(TRUE); } - diff --git a/rpc.subproj/xdr_float.c b/rpc.subproj/xdr_float.c index 775022a..1ef6f04 100644 --- a/rpc.subproj/xdr_float.c +++ b/rpc.subproj/xdr_float.c @@ -21,6 +21,9 @@ * * @APPLE_LICENSE_HEADER_END@ */ + +/* $NetBSD: xdr_float.c,v 1.23 2000/07/17 04:59:51 matt Exp $ */ + /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape @@ -28,36 +31,36 @@ * 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 */ #if defined(LIBC_SCCS) && !defined(lint) -/*static char *sccsid = "from: @(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro";*/ -/*static char *sccsid = "from: @(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC";*/ -static char *rcsid = "$Id: xdr_float.c,v 1.2 1999/10/14 21:56:55 wsanchez Exp $"; +static char *sccsid = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro"; +static char *sccsid = "@(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC"; #endif +#include /* - * xdr_float.c, Generic XDR routines impelmentation. + * xdr_float.c, Generic XDR routines implementation. * * Copyright (C) 1984, Sun Microsystems, Inc. * @@ -66,22 +69,25 @@ static char *rcsid = "$Id: xdr_float.c,v 1.2 1999/10/14 21:56:55 wsanchez Exp $" * xdr. */ -#include #include #include + +#include + #include #include /* * NB: Not portable. - * This routine works on Suns (Sky / 68000's), i386's, MIPS, NS32k and Vaxen. + * This routine works on machines with IEEE754 FP and Vaxen. */ -#if defined(mc68000)||defined(sparc)||defined(i386)||defined(mips)||defined(ns32k)||defined(__APPLE__) +#if 1 /* Used to be long list of architectures */ +#include #define IEEEFP #endif -#ifdef vax +#if defined(__vax__) /* What IEEE single precision floating point looks like on a Vax */ struct ieee_single { @@ -114,8 +120,8 @@ static struct sgl_limits { bool_t xdr_float(xdrs, fp) - register XDR *xdrs; - register float *fp; + XDR *xdrs; + float *fp; { #ifndef IEEEFP struct ieee_single is; @@ -126,8 +132,8 @@ xdr_float(xdrs, fp) switch (xdrs->x_op) { case XDR_ENCODE: -#ifdef IEEEFP - return (XDR_PUTLONG(xdrs, (long *)fp)); +#ifdef IEEEFP + return (XDR_PUTINT32(xdrs, (int32_t *)fp)); #else vs = *((struct vax_single *)fp); for (i = 0, lim = sgl_limits; @@ -144,15 +150,15 @@ xdr_float(xdrs, fp) is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2; shipit: is.sign = vs.sign; - return (XDR_PUTLONG(xdrs, (long *)&is)); + return (XDR_PUTINT32(xdrs, (int32_t *)&is)); #endif case XDR_DECODE: #ifdef IEEEFP - return (XDR_GETLONG(xdrs, (long *)fp)); + return (XDR_GETINT32(xdrs, (int32_t *)fp)); #else vsp = (struct vax_single *)fp; - if (!XDR_GETLONG(xdrs, (long *)&is)) + if (!XDR_GETINT32(xdrs, (int32_t *)&is)) return (FALSE); for (i = 0, lim = sgl_limits; i < sizeof(sgl_limits)/sizeof(struct sgl_limits); @@ -174,14 +180,11 @@ xdr_float(xdrs, fp) case XDR_FREE: return (TRUE); } + /* NOTREACHED */ return (FALSE); } -/* - * This routine works on Suns (Sky / 68000's), i386's, MIPS and Vaxen. - */ - -#ifdef vax +#if defined(__vax__) /* What IEEE double precision floating point looks like on a Vax */ struct ieee_double { unsigned int mantissa1 : 20; @@ -219,14 +222,17 @@ static struct dbl_limits { bool_t xdr_double(xdrs, dp) - register XDR *xdrs; + XDR *xdrs; double *dp; { - register long *lp; -#ifndef IEEEFP +#ifdef IEEEFP + int32_t *i32p; + bool_t rv; +#else + int32_t *lp; struct ieee_double id; struct vax_double vd; - register struct dbl_limits *lim; + struct dbl_limits *lim; int i; #endif @@ -234,12 +240,19 @@ xdr_double(xdrs, dp) case XDR_ENCODE: #ifdef IEEEFP - lp = (long *)dp; + i32p = (int32_t *)(void *)dp; #if BYTE_ORDER == BIG_ENDIAN - return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp)); + rv = XDR_PUTINT32(xdrs, i32p); + if (!rv) + return (rv); + rv = XDR_PUTINT32(xdrs, i32p+1); #else - return (XDR_PUTLONG(xdrs, lp+1) && XDR_PUTLONG(xdrs, lp)); + rv = XDR_PUTINT32(xdrs, i32p+1); + if (!rv) + return (rv); + rv = XDR_PUTINT32(xdrs, i32p); #endif + return (rv); #else vd = *((struct vax_double *)dp); for (i = 0, lim = dbl_limits; @@ -261,21 +274,28 @@ xdr_double(xdrs, dp) ((vd.mantissa4 >> 3) & MASK(13)); shipit: id.sign = vd.sign; - lp = (long *)&id; - return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp)); + lp = (int32_t *)&id; + return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp)); #endif case XDR_DECODE: #ifdef IEEEFP - lp = (long *)dp; + i32p = (int32_t *)(void *)dp; #if BYTE_ORDER == BIG_ENDIAN - return (XDR_GETLONG(xdrs, lp++) && XDR_GETLONG(xdrs, lp)); + rv = XDR_GETINT32(xdrs, i32p); + if (!rv) + return (rv); + rv = XDR_GETINT32(xdrs, i32p+1); #else - return (XDR_GETLONG(xdrs, lp+1) && XDR_GETLONG(xdrs, lp)); + rv = XDR_GETINT32(xdrs, i32p+1); + if (!rv) + return (rv); + rv = XDR_GETINT32(xdrs, i32p); #endif + return (rv); #else - lp = (long *)&id; - if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(xdrs, lp)) + lp = (int32_t *)&id; + if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(xdrs, lp)) return (FALSE); for (i = 0, lim = dbl_limits; i < sizeof(dbl_limits)/sizeof(struct dbl_limits); @@ -302,5 +322,6 @@ xdr_double(xdrs, dp) case XDR_FREE: return (TRUE); } + /* NOTREACHED */ return (FALSE); } diff --git a/rpc.subproj/xdr_mem.c b/rpc.subproj/xdr_mem.c index 5f6d68c..ed2a65a 100644 --- a/rpc.subproj/xdr_mem.c +++ b/rpc.subproj/xdr_mem.c @@ -21,6 +21,9 @@ * * @APPLE_LICENSE_HEADER_END@ */ + +/* $NetBSD: xdr_mem.c,v 1.15 2000/01/22 22:19:18 mycroft Exp $ */ + /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape @@ -28,33 +31,33 @@ * 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 */ #if defined(LIBC_SCCS) && !defined(lint) -/*static char *sccsid = "from: @(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/ -/*static char *sccsid = "from: @(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC";*/ -static char *rcsid = "$Id: xdr_mem.c,v 1.5 2003/06/23 17:24:59 majka Exp $"; +static char *sccsid = "@(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro"; +static char *sccsid = "@(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC"; #endif +#include /* * xdr_mem.h, XDR implementation using memory buffers. @@ -67,144 +70,212 @@ static char *rcsid = "$Id: xdr_mem.c,v 1.5 2003/06/23 17:24:59 majka Exp $"; * */ +#include + +#include #include + #include #include -#include -static bool_t xdrmem_getlong(); -static bool_t xdrmem_putlong(); -static bool_t xdrmem_getbytes(); -static bool_t xdrmem_putbytes(); -static u_int xdrmem_getpos(); -static bool_t xdrmem_setpos(); -static long * xdrmem_inline(); -static void xdrmem_destroy(); - -static struct xdr_ops xdrmem_ops = { - xdrmem_getlong, - xdrmem_putlong, +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_getbytes(XDR *, char *, u_int); +static bool_t xdrmem_putbytes(XDR *, const char *, u_int); +/* XXX: w/64-bit pointers, u_int not enough! */ +static u_int xdrmem_getpos(XDR *); +static bool_t xdrmem_setpos(XDR *, u_int); +static int32_t *xdrmem_inline_aligned(XDR *, u_int); +static int32_t *xdrmem_inline_unaligned(XDR *, u_int); + +static const struct xdr_ops xdrmem_ops_aligned = { + xdrmem_getlong_aligned, + xdrmem_putlong_aligned, + xdrmem_getbytes, + xdrmem_putbytes, + xdrmem_getpos, + xdrmem_setpos, + xdrmem_inline_aligned, + xdrmem_destroy +}; + +static const struct xdr_ops xdrmem_ops_unaligned = { + xdrmem_getlong_unaligned, + xdrmem_putlong_unaligned, xdrmem_getbytes, xdrmem_putbytes, xdrmem_getpos, xdrmem_setpos, - xdrmem_inline, + xdrmem_inline_unaligned, xdrmem_destroy }; /* * The procedure xdrmem_create initializes a stream descriptor for a - * memory buffer. + * memory buffer. */ void xdrmem_create(xdrs, addr, size, op) - register XDR *xdrs; -#if defined(__APPLE__) - void *addr; -#else - caddr_t addr; -#endif + XDR *xdrs; + char *addr; u_int size; enum xdr_op op; { xdrs->x_op = op; - xdrs->x_ops = &xdrmem_ops; + xdrs->x_ops = ((unsigned long)addr & (sizeof(int32_t) - 1)) + ? &xdrmem_ops_unaligned : &xdrmem_ops_aligned; xdrs->x_private = xdrs->x_base = addr; xdrs->x_handy = size; } +/*ARGSUSED*/ static void -xdrmem_destroy(XDR *xdrs) +xdrmem_destroy(xdrs) + XDR *xdrs; { + } static bool_t -xdrmem_getlong(xdrs, lp) - register XDR *xdrs; +xdrmem_getlong_aligned(xdrs, lp) + XDR *xdrs; long *lp; { - if ((xdrs->x_handy -= sizeof(long)) < 0) + + if (xdrs->x_handy < sizeof(int32_t)) + return (FALSE); + xdrs->x_handy -= sizeof(int32_t); + *lp = ntohl(*(u_int32_t *)xdrs->x_private); + xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t); + return (TRUE); +} + +static bool_t +xdrmem_putlong_aligned(xdrs, lp) + XDR *xdrs; + const long *lp; +{ + + if (xdrs->x_handy < sizeof(int32_t)) return (FALSE); - *lp = (long)ntohl((u_long)(*((long *)(xdrs->x_private)))); - xdrs->x_private += sizeof(long); + xdrs->x_handy -= sizeof(int32_t); + *(u_int32_t *)xdrs->x_private = htonl((u_int32_t)*lp); + xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t); return (TRUE); } static bool_t -xdrmem_putlong(xdrs, lp) - register XDR *xdrs; +xdrmem_getlong_unaligned(xdrs, lp) + XDR *xdrs; long *lp; { - if ((xdrs->x_handy -= sizeof(long)) < 0) + u_int32_t l; + + if (xdrs->x_handy < sizeof(int32_t)) return (FALSE); - *(long *)xdrs->x_private = (long)htonl((u_long)(*lp)); - xdrs->x_private += sizeof(long); + xdrs->x_handy -= sizeof(int32_t); + memmove(&l, xdrs->x_private, sizeof(int32_t)); + *lp = ntohl(l); + xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t); + return (TRUE); +} + +static bool_t +xdrmem_putlong_unaligned(xdrs, lp) + XDR *xdrs; + const long *lp; +{ + u_int32_t l; + + if (xdrs->x_handy < sizeof(int32_t)) + return (FALSE); + xdrs->x_handy -= sizeof(int32_t); + l = htonl((u_int32_t)*lp); + memmove(xdrs->x_private, &l, sizeof(int32_t)); + xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t); return (TRUE); } static bool_t xdrmem_getbytes(xdrs, addr, len) - register XDR *xdrs; - caddr_t addr; - register u_int len; + XDR *xdrs; + char *addr; + u_int len; { - if ((xdrs->x_handy -= len) < 0) + if (xdrs->x_handy < len) return (FALSE); - bcopy(xdrs->x_private, addr, len); - xdrs->x_private += len; + xdrs->x_handy -= len; + memmove(addr, xdrs->x_private, len); + xdrs->x_private = (char *)xdrs->x_private + len; return (TRUE); } static bool_t xdrmem_putbytes(xdrs, addr, len) - register XDR *xdrs; - caddr_t addr; - register u_int len; + XDR *xdrs; + const char *addr; + u_int len; { - if ((xdrs->x_handy -= len) < 0) + if (xdrs->x_handy < len) return (FALSE); - bcopy(addr, xdrs->x_private, len); - xdrs->x_private += len; + xdrs->x_handy -= len; + memmove(xdrs->x_private, addr, len); + xdrs->x_private = (char *)xdrs->x_private + len; return (TRUE); } static u_int xdrmem_getpos(xdrs) - register XDR *xdrs; + XDR *xdrs; { - return ((u_int)xdrs->x_private - (u_int)xdrs->x_base); + + /* XXX w/64-bit pointers, u_int not enough! */ + return (u_int)((u_long)xdrs->x_private - (u_long)xdrs->x_base); } static bool_t xdrmem_setpos(xdrs, pos) - register XDR *xdrs; + XDR *xdrs; u_int pos; { - register caddr_t newaddr = xdrs->x_base + pos; - register caddr_t lastaddr = xdrs->x_private + xdrs->x_handy; + char *newaddr = xdrs->x_base + pos; + char *lastaddr = (char *)xdrs->x_private + xdrs->x_handy; - if ((long)newaddr > (long)lastaddr) + if (newaddr > lastaddr) return (FALSE); xdrs->x_private = newaddr; - xdrs->x_handy = (int)lastaddr - (int)newaddr; + xdrs->x_handy = (u_int)(lastaddr - newaddr); /* XXX sizeof(u_int) x_handy >= len) { xdrs->x_handy -= len; - buf = (long *) xdrs->x_private; - xdrs->x_private += len; + buf = (int32_t *)xdrs->x_private; + xdrs->x_private = (char *)xdrs->x_private + len; } return (buf); } + +/* ARGSUSED */ +static int32_t * +xdrmem_inline_unaligned(xdrs, len) + XDR *xdrs; + u_int len; +{ + + return (0); +} diff --git a/rpc.subproj/xdr_rec.c b/rpc.subproj/xdr_rec.c index ce01f1c..844c327 100644 --- a/rpc.subproj/xdr_rec.c +++ b/rpc.subproj/xdr_rec.c @@ -21,6 +21,9 @@ * * @APPLE_LICENSE_HEADER_END@ */ + +/* $NetBSD: xdr_rec.c,v 1.18 2000/07/06 03:10:35 christos Exp $ */ + /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape @@ -28,32 +31,34 @@ * 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 */ + +#include #if defined(LIBC_SCCS) && !defined(lint) -/*static char *sccsid = "from: @(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/ -/*static char *sccsid = "from: @(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC";*/ -static char *rcsid = "$Id: xdr_rec.c,v 1.4 2003/06/23 17:24:59 majka Exp $"; +static char *sccsid = "@(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro"; +static char *sccsid = "@(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC"; #endif +#include /* * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking" @@ -72,30 +77,32 @@ static char *rcsid = "$Id: xdr_rec.c,v 1.4 2003/06/23 17:24:59 majka Exp $"; * The other 31 bits encode the byte length of the fragment. */ +#include + +#include + +#include #include #include #include -#include + #include #include -#include +#include +#include +#include + +static bool_t xdrrec_getlong(XDR *, long *); +static bool_t xdrrec_putlong(XDR *, const long *); +static bool_t xdrrec_getbytes(XDR *, char *, u_int); -static u_int fix_buf_size(); -static bool_t flush_out(); -static bool_t get_input_bytes(); -static bool_t set_input_fragment(); -static bool_t skip_input_bytes(); - -static bool_t xdrrec_getlong(); -static bool_t xdrrec_putlong(); -static bool_t xdrrec_getbytes(); -static bool_t xdrrec_putbytes(); -static u_int xdrrec_getpos(); -static bool_t xdrrec_setpos(); -static long * xdrrec_inline(); -static void xdrrec_destroy(); - -static struct xdr_ops xdrrec_ops = { +static bool_t xdrrec_putbytes(XDR *, const char *, u_int); +static u_int xdrrec_getpos(XDR *); +static bool_t xdrrec_setpos(XDR *, u_int); +static int32_t *xdrrec_inline(XDR *, u_int); +static void xdrrec_destroy(XDR *); + +static const struct xdr_ops xdrrec_ops = { xdrrec_getlong, xdrrec_putlong, xdrrec_getbytes, @@ -108,7 +115,7 @@ static struct xdr_ops xdrrec_ops = { /* * A record is composed of one or more record fragments. - * A record fragment is a two-byte header followed by zero to + * 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 * 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: @@ -119,34 +126,50 @@ static struct xdr_ops xdrrec_ops = { * meet the needs of xdr and rpc based on tcp. */ -#define LAST_FRAG ((u_long)(1 << 31)) +#define LAST_FRAG ((u_int32_t)(1 << 31)) typedef struct rec_strm { - caddr_t tcp_handle; - caddr_t the_buffer; + char *tcp_handle; /* * out-goung bits */ - int (*writeit)(); - caddr_t out_base; /* output buffer (points to frag header) */ - caddr_t out_finger; /* next output position */ - caddr_t out_boundry; /* data cannot up to this address */ - u_long *frag_header; /* beginning of curren fragment */ + int (*writeit)(void *, void *, int); + char *out_base; /* output buffer (points to frag header) */ + char *out_finger; /* next output position */ + char *out_boundry; /* data cannot up to this address */ + u_int32_t *frag_header; /* beginning of curren fragment */ bool_t frag_sent; /* true if buffer sent in middle of record */ /* * in-coming bits */ - int (*readit)(); + int (*readit)(void *, void *, int); u_long in_size; /* fixed size of the input buffer */ - caddr_t in_base; - caddr_t in_finger; /* location of next byte to be had */ - caddr_t in_boundry; /* can read up to this location */ + 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 */ bool_t last_frag; u_int sendsize; u_int recvsize; + + bool_t nonblock; + bool_t in_haveheader; + u_int32_t in_header; + char *in_hdrp; + int in_hdrlen; + int in_reclen; + int in_received; + int in_maxrec; } RECSTREAM; +static u_int fix_buf_size(u_int); +static bool_t flush_out(RECSTREAM *, bool_t); +static bool_t fill_input_buf(RECSTREAM *); +static bool_t get_input_bytes(RECSTREAM *, char *, int); +static bool_t set_input_fragment(RECSTREAM *); +static bool_t skip_input_bytes(RECSTREAM *, long); +static bool_t realloc_stream(RECSTREAM *, int); + /* * Create an xdr handle for xdrrec @@ -159,49 +182,51 @@ typedef struct rec_strm { */ void xdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit) - register XDR *xdrs; - register u_int sendsize; - register u_int recvsize; - caddr_t tcp_handle; - int (*readit)(); /* like read, but pass it a tcp_handle, not sock */ - int (*writeit)(); /* like write, but pass it a tcp_handle, not sock */ + XDR *xdrs; + u_int sendsize; + u_int recvsize; + void *tcp_handle; + /* like read, but pass it a tcp_handle, not sock */ + int (*readit)(void *, void *, int); + /* like write, but pass it a tcp_handle, not sock */ + int (*writeit)(void *, void *, int); { - register RECSTREAM *rstrm = - (RECSTREAM *)mem_alloc(sizeof(RECSTREAM)); + RECSTREAM *rstrm = mem_alloc(sizeof(RECSTREAM)); if (rstrm == NULL) { - (void)fprintf(stderr, "xdrrec_create: out of memory\n"); + warnx("xdrrec_create: out of memory"); /* * This is bad. Should rework xdrrec_create to * return a handle, and in this case return NULL */ return; } - /* - * adjust sizes and allocate buffer quad byte aligned - */ rstrm->sendsize = sendsize = fix_buf_size(sendsize); + rstrm->out_base = mem_alloc(rstrm->sendsize); + if (rstrm->out_base == NULL) { + warnx("xdrrec_create: out of memory"); + mem_free(rstrm, sizeof(RECSTREAM)); + return; + } rstrm->recvsize = recvsize = fix_buf_size(recvsize); - rstrm->the_buffer = mem_alloc(sendsize + recvsize + BYTES_PER_XDR_UNIT); - if (rstrm->the_buffer == NULL) { - (void)fprintf(stderr, "xdrrec_create: out of memory\n"); + rstrm->in_base = mem_alloc(recvsize); + if (rstrm->in_base == NULL) { + warnx("xdrrec_create: out of memory"); + mem_free(rstrm->out_base, sendsize); + mem_free(rstrm, sizeof(RECSTREAM)); return; } - for (rstrm->out_base = rstrm->the_buffer; - (u_int)rstrm->out_base % BYTES_PER_XDR_UNIT != 0; - rstrm->out_base++); - rstrm->in_base = rstrm->out_base + sendsize; /* * now the rest ... */ xdrs->x_ops = &xdrrec_ops; - xdrs->x_private = (caddr_t)rstrm; + xdrs->x_private = rstrm; rstrm->tcp_handle = tcp_handle; rstrm->readit = readit; rstrm->writeit = writeit; rstrm->out_finger = rstrm->out_boundry = rstrm->out_base; - rstrm->frag_header = (u_long *)rstrm->out_base; - rstrm->out_finger += sizeof(u_long); + rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_base; + rstrm->out_finger += sizeof(u_int32_t); rstrm->out_boundry += sendsize; rstrm->frag_sent = FALSE; rstrm->in_size = recvsize; @@ -209,6 +234,12 @@ xdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit) rstrm->in_finger = (rstrm->in_boundry += recvsize); rstrm->fbtbc = 0; rstrm->last_frag = TRUE; + rstrm->in_haveheader = FALSE; + rstrm->in_hdrlen = 0; + rstrm->in_hdrp = (char *)(void *)&rstrm->in_header; + rstrm->nonblock = FALSE; + rstrm->in_reclen = 0; + rstrm->in_received = 0; } @@ -222,20 +253,21 @@ xdrrec_getlong(xdrs, lp) XDR *xdrs; long *lp; { - register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); - register long *buflp = (long *)(rstrm->in_finger); - long mylong; + 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(long)) && - (((int)rstrm->in_boundry - (int)buflp) >= sizeof(long))) { - *lp = (long)ntohl((u_long)(*buflp)); - rstrm->fbtbc -= sizeof(long); - rstrm->in_finger += sizeof(long); + if ((rstrm->fbtbc >= sizeof(int32_t)) && + (((long)rstrm->in_boundry - (long)buflp) >= sizeof(int32_t))) { + *lp = (long)ntohl((u_int32_t)(*buflp)); + rstrm->fbtbc -= sizeof(int32_t); + rstrm->in_finger += sizeof(int32_t); } else { - if (! xdrrec_getbytes(xdrs, (caddr_t)&mylong, sizeof(long))) + if (! xdrrec_getbytes(xdrs, (char *)(void *)&mylong, + sizeof(int32_t))) return (FALSE); - *lp = (long)ntohl((u_long)mylong); + *lp = (long)ntohl((u_int32_t)mylong); } return (TRUE); } @@ -243,38 +275,38 @@ xdrrec_getlong(xdrs, lp) static bool_t xdrrec_putlong(xdrs, lp) XDR *xdrs; - long *lp; + const long *lp; { - register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); - register long *dest_lp = ((long *)(rstrm->out_finger)); + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + int32_t *dest_lp = ((int32_t *)(void *)(rstrm->out_finger)); - if ((rstrm->out_finger += sizeof(long)) > 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(long); + rstrm->out_finger -= sizeof(int32_t); rstrm->frag_sent = TRUE; if (! flush_out(rstrm, FALSE)) return (FALSE); - dest_lp = ((long *)(rstrm->out_finger)); - rstrm->out_finger += sizeof(long); + dest_lp = ((int32_t *)(void *)(rstrm->out_finger)); + rstrm->out_finger += sizeof(int32_t); } - *dest_lp = (long)htonl((u_long)(*lp)); + *dest_lp = (int32_t)htonl((u_int32_t)(*lp)); return (TRUE); } static bool_t /* must manage buffers, fragments, and records */ xdrrec_getbytes(xdrs, addr, len) XDR *xdrs; - register caddr_t addr; - register u_int len; + char *addr; + u_int len; { - register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); - register int current; + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + int current; while (len > 0) { - current = rstrm->fbtbc; + current = (int)rstrm->fbtbc; if (current == 0) { if (rstrm->last_frag) return (FALSE); @@ -295,16 +327,17 @@ xdrrec_getbytes(xdrs, addr, len) static bool_t xdrrec_putbytes(xdrs, addr, len) XDR *xdrs; - register caddr_t addr; - register u_int len; + const char *addr; + u_int len; { - register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); - register int current; + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + size_t current; while (len > 0) { - current = (u_int)rstrm->out_boundry - (u_int)rstrm->out_finger; + current = (size_t)((u_long)rstrm->out_boundry - + (u_long)rstrm->out_finger); current = (len < current) ? len : current; - bcopy(addr, rstrm->out_finger, current); + memmove(rstrm->out_finger, addr, current); rstrm->out_finger += current; addr += current; len -= current; @@ -319,12 +352,12 @@ xdrrec_putbytes(xdrs, addr, len) static u_int xdrrec_getpos(xdrs) - register XDR *xdrs; + XDR *xdrs; { - register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; - register long pos; + RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; + off_t pos; - pos = lseek((int)rstrm->tcp_handle, 0, 1); + pos = lseek((int)(u_long)rstrm->tcp_handle, (off_t)0, 1); if (pos != -1) switch (xdrs->x_op) { @@ -337,7 +370,7 @@ xdrrec_getpos(xdrs) break; default: - pos = (u_int) -1; + pos = (off_t) -1; break; } return ((u_int) pos); @@ -345,20 +378,20 @@ xdrrec_getpos(xdrs) static bool_t xdrrec_setpos(xdrs, pos) - register XDR *xdrs; + XDR *xdrs; u_int pos; { - register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; + RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; u_int currpos = xdrrec_getpos(xdrs); int delta = currpos - pos; - caddr_t newpos; + char *newpos; if ((int)currpos != -1) switch (xdrs->x_op) { case XDR_ENCODE: newpos = rstrm->out_finger - delta; - if ((newpos > (caddr_t)(rstrm->frag_header)) && + if ((newpos > (char *)(void *)(rstrm->frag_header)) && (newpos < rstrm->out_boundry)) { rstrm->out_finger = newpos; return (TRUE); @@ -375,24 +408,26 @@ xdrrec_setpos(xdrs, pos) return (TRUE); } break; - default: break; + + case XDR_FREE: + break; } return (FALSE); } -static long * +static int32_t * xdrrec_inline(xdrs, len) - register XDR *xdrs; - int len; + XDR *xdrs; + u_int len; { - register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; - long * buf = NULL; + RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; + int32_t *buf = NULL; switch (xdrs->x_op) { case XDR_ENCODE: if ((rstrm->out_finger + len) <= rstrm->out_boundry) { - buf = (long *) rstrm->out_finger; + buf = (int32_t *)(void *)rstrm->out_finger; rstrm->out_finger += len; } break; @@ -400,25 +435,27 @@ xdrrec_inline(xdrs, len) case XDR_DECODE: if ((len <= rstrm->fbtbc) && ((rstrm->in_finger + len) <= rstrm->in_boundry)) { - buf = (long *) rstrm->in_finger; + buf = (int32_t *)(void *)rstrm->in_finger; rstrm->fbtbc -= len; rstrm->in_finger += len; } break; - default: break; + + case XDR_FREE: + break; } return (buf); } static void xdrrec_destroy(xdrs) - register XDR *xdrs; + XDR *xdrs; { - register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; + RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; - mem_free(rstrm->the_buffer, - rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT); - mem_free((caddr_t)rstrm, sizeof(RECSTREAM)); + mem_free(rstrm->out_base, rstrm->sendsize); + mem_free(rstrm->in_base, rstrm->recvsize); + mem_free(rstrm, sizeof(RECSTREAM)); } @@ -434,7 +471,21 @@ bool_t xdrrec_skiprecord(xdrs) XDR *xdrs; { - register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + enum xprt_stat xstat; + + if (rstrm->nonblock) { + if (__xdrrec_getrec(xdrs, &xstat, FALSE)) { + rstrm->fbtbc = 0; + return TRUE; + } + if (rstrm->in_finger == rstrm->in_boundry && + xstat == XPRT_MOREREQS) { + rstrm->fbtbc = 0; + return TRUE; + } + return FALSE; + } while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) { if (! skip_input_bytes(rstrm, rstrm->fbtbc)) @@ -448,15 +499,15 @@ xdrrec_skiprecord(xdrs) } /* - * Look ahead fuction. - * Returns TRUE iff there is no more input in the buffer + * Look ahead function. + * Returns TRUE iff there is no more input in the buffer * after consuming the rest of the current record. */ bool_t xdrrec_eof(xdrs) XDR *xdrs; { - register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) { if (! skip_input_bytes(rstrm, rstrm->fbtbc)) @@ -481,58 +532,156 @@ xdrrec_endofrecord(xdrs, sendnow) XDR *xdrs; bool_t sendnow; { - register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); - register u_long len; /* fragment length */ + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + u_long len; /* fragment length */ if (sendnow || rstrm->frag_sent || - ((u_long)rstrm->out_finger + sizeof(u_long) >= + ((u_long)rstrm->out_finger + sizeof(u_int32_t) >= (u_long)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_long); - *(rstrm->frag_header) = htonl((u_long)len | LAST_FRAG); - rstrm->frag_header = (u_long *)rstrm->out_finger; - rstrm->out_finger += sizeof(u_long); + sizeof(u_int32_t); + *(rstrm->frag_header) = htonl((u_int32_t)len | LAST_FRAG); + rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_finger; + rstrm->out_finger += sizeof(u_int32_t); return (TRUE); } +/* + * Fill the stream buffer with a record for a non-blocking connection. + * Return true if a record is available in the buffer, false if not. + */ +bool_t +__xdrrec_getrec(xdrs, statp, expectdata) + XDR *xdrs; + enum xprt_stat *statp; + bool_t expectdata; +{ + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + ssize_t n; + int fraglen; + + if (!rstrm->in_haveheader) { + n = rstrm->readit(rstrm->tcp_handle, rstrm->in_hdrp, + (int)sizeof (rstrm->in_header) - rstrm->in_hdrlen); + if (n == 0) { + *statp = expectdata ? XPRT_DIED : XPRT_IDLE; + return FALSE; + } + if (n < 0) { + *statp = XPRT_DIED; + return FALSE; + } + rstrm->in_hdrp += n; + rstrm->in_hdrlen += n; + if (rstrm->in_hdrlen < sizeof (rstrm->in_header)) { + *statp = XPRT_MOREREQS; + return FALSE; + } + rstrm->in_header = ntohl(rstrm->in_header); + fraglen = (int)(rstrm->in_header & ~LAST_FRAG); + if (fraglen == 0 || fraglen > rstrm->in_maxrec || + (rstrm->in_reclen + fraglen) > rstrm->in_maxrec) { + *statp = XPRT_DIED; + return FALSE; + } + rstrm->in_reclen += fraglen; + if (rstrm->in_reclen > rstrm->recvsize) + realloc_stream(rstrm, rstrm->in_reclen); + if (rstrm->in_header & LAST_FRAG) { + rstrm->in_header &= ~LAST_FRAG; + rstrm->last_frag = TRUE; + } + } + + n = rstrm->readit(rstrm->tcp_handle, + rstrm->in_base + rstrm->in_received, + (rstrm->in_reclen - rstrm->in_received)); + + if (n < 0) { + *statp = XPRT_DIED; + return FALSE; + } + + if (n == 0) { + *statp = expectdata ? XPRT_DIED : XPRT_IDLE; + return FALSE; + } + + rstrm->in_received += n; + + if (rstrm->in_received == rstrm->in_reclen) { + rstrm->in_haveheader = FALSE; + rstrm->in_hdrp = (char *)(void *)&rstrm->in_header; + rstrm->in_hdrlen = 0; + if (rstrm->last_frag) { + rstrm->fbtbc = rstrm->in_reclen; + rstrm->in_boundry = rstrm->in_base + rstrm->in_reclen; + rstrm->in_finger = rstrm->in_base; + rstrm->in_reclen = rstrm->in_received = 0; + *statp = XPRT_MOREREQS; + return TRUE; + } + } + + *statp = XPRT_MOREREQS; + return FALSE; +} + +bool_t +__xdrrec_setnonblock(xdrs, maxrec) + XDR *xdrs; + int maxrec; +{ + RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + + rstrm->nonblock = TRUE; + if (maxrec == 0) + maxrec = rstrm->recvsize; + rstrm->in_maxrec = maxrec; + return TRUE; +} /* * Internal useful routines */ static bool_t flush_out(rstrm, eor) - register RECSTREAM *rstrm; + RECSTREAM *rstrm; bool_t eor; { - register u_long eormask = (eor == TRUE) ? LAST_FRAG : 0; - register u_long len = (u_long)(rstrm->out_finger) - - (u_long)(rstrm->frag_header) - sizeof(u_long); + 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)); *(rstrm->frag_header) = htonl(len | eormask); - len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->out_base); + 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) return (FALSE); - rstrm->frag_header = (u_long *)rstrm->out_base; - rstrm->out_finger = (caddr_t)rstrm->out_base + sizeof(u_long); + rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_base; + rstrm->out_finger = (char *)rstrm->out_base + sizeof(u_int32_t); return (TRUE); } static bool_t /* knows nothing about records! Only about input buffers */ fill_input_buf(rstrm) - register RECSTREAM *rstrm; + RECSTREAM *rstrm; { - register caddr_t where; - u_int i; - register int len; + char *where; + u_int32_t i; + int len; + + if (rstrm->nonblock) + return FALSE; where = rstrm->in_base; - i = (u_int)rstrm->in_boundry % BYTES_PER_XDR_UNIT; + i = (u_int32_t)((u_long)rstrm->in_boundry % BYTES_PER_XDR_UNIT); where += i; - len = rstrm->in_size - i; + len = (u_int32_t)(rstrm->in_size - i); if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1) return (FALSE); rstrm->in_finger = where; @@ -543,21 +692,30 @@ fill_input_buf(rstrm) static bool_t /* knows nothing about records! Only about input buffers */ get_input_bytes(rstrm, addr, len) - register RECSTREAM *rstrm; - register caddr_t addr; - register int len; + RECSTREAM *rstrm; + char *addr; + int len; { - register int current; + size_t current; + + if (rstrm->nonblock) { + if (len > (int)(rstrm->in_boundry - rstrm->in_finger)) + return FALSE; + memcpy(addr, rstrm->in_finger, (size_t)len); + rstrm->in_finger += len; + return TRUE; + } while (len > 0) { - current = (int)rstrm->in_boundry - (int)rstrm->in_finger; + current = (size_t)((long)rstrm->in_boundry - + (long)rstrm->in_finger); if (current == 0) { if (! fill_input_buf(rstrm)) return (FALSE); continue; } current = (len < current) ? len : current; - bcopy(rstrm->in_finger, addr, current); + memmove(addr, rstrm->in_finger, current); rstrm->in_finger += current; addr += current; len -= current; @@ -567,33 +725,46 @@ get_input_bytes(rstrm, addr, len) static bool_t /* next two bytes of the input stream are treated as a header */ set_input_fragment(rstrm) - register RECSTREAM *rstrm; + RECSTREAM *rstrm; { - u_long header; + u_int32_t header; - if (! get_input_bytes(rstrm, (caddr_t)&header, sizeof(header))) + if (rstrm->nonblock) + return FALSE; + if (! get_input_bytes(rstrm, (char *)(void *)&header, sizeof(header))) return (FALSE); - header = (long)ntohl(header); + header = ntohl(header); rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE; + /* + * Sanity check. Try not to accept wildly incorrect + * record sizes. Unfortunately, the only record size + * we can positively identify as being 'wildly incorrect' + * is zero. Ridiculously large record sizes may look wrong, + * but we don't have any way to be certain that they aren't + * what the client actually intended to send us. + */ + if (header == 0) + return(FALSE); rstrm->fbtbc = header & (~LAST_FRAG); return (TRUE); } static bool_t /* consumes input bytes; knows nothing about records! */ skip_input_bytes(rstrm, cnt) - register RECSTREAM *rstrm; + RECSTREAM *rstrm; long cnt; { - register int current; + u_int32_t current; while (cnt > 0) { - current = (int)rstrm->in_boundry - (int)rstrm->in_finger; + current = (size_t)((long)rstrm->in_boundry - + (long)rstrm->in_finger); if (current == 0) { if (! fill_input_buf(rstrm)) return (FALSE); continue; } - current = (cnt < current) ? cnt : current; + current = (u_int32_t)((cnt < current) ? cnt : current); rstrm->in_finger += current; cnt -= current; } @@ -602,10 +773,36 @@ skip_input_bytes(rstrm, cnt) static u_int fix_buf_size(s) - register u_int s; + u_int s; { if (s < 100) s = 4000; return (RNDUP(s)); } + +/* + * Reallocate the input buffer for a non-block stream. + */ +static bool_t +realloc_stream(rstrm, size) + RECSTREAM *rstrm; + int size; +{ + long diff; + char *buf; + + if (size > rstrm->recvsize) { + buf = realloc(rstrm->in_base, (size_t)size); + if (buf == NULL) + return FALSE; + diff = buf - rstrm->in_base; + rstrm->in_finger += diff; + rstrm->in_base = buf; + rstrm->in_boundry = buf + size; + rstrm->recvsize = size; + rstrm->in_size = size; + } + + return TRUE; +} diff --git a/rpc.subproj/xdr_reference.c b/rpc.subproj/xdr_reference.c index 0821987..2708c81 100644 --- a/rpc.subproj/xdr_reference.c +++ b/rpc.subproj/xdr_reference.c @@ -21,6 +21,9 @@ * * @APPLE_LICENSE_HEADER_END@ */ + +/* $NetBSD: xdr_reference.c,v 1.13 2000/01/22 22:19:18 mycroft Exp $ */ + /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape @@ -28,33 +31,35 @@ * 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 */ +#include #if defined(LIBC_SCCS) && !defined(lint) -/*static char *sccsid = "from: @(#)xdr_reference.c 1.11 87/08/11 SMI";*/ -/*static char *sccsid = "from: @(#)xdr_reference.c 2.1 88/07/29 4.0 RPCSRC";*/ -static char *rcsid = "$Id: xdr_reference.c,v 1.4 2003/06/23 17:24:59 majka Exp $"; +static char *sccsid = "@(#)xdr_reference.c 1.11 87/08/11 SMI"; +static char *sccsid = "@(#)xdr_reference.c 2.1 88/07/29 4.0 RPCSRC"; +static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr_reference.c,v 1.11 2002/03/22 21:53:26 obrien Exp $"; #endif +#include /* * xdr_reference.c, Generic XDR routines impelmentation. @@ -65,14 +70,14 @@ static char *rcsid = "$Id: xdr_reference.c,v 1.4 2003/06/23 17:24:59 majka Exp $ * "pointers". See xdr.h for more info on the interface to xdr. */ +#include #include #include #include + #include #include -#define LASTUNSIGNED ((u_int)0-1) - /* * XDR an indirect pointer * xdr_reference is for recursively translating a structure that is @@ -84,13 +89,13 @@ static char *rcsid = "$Id: xdr_reference.c,v 1.4 2003/06/23 17:24:59 majka Exp $ */ bool_t xdr_reference(xdrs, pp, size, proc) - register XDR *xdrs; + XDR *xdrs; caddr_t *pp; /* the pointer to work on */ u_int size; /* size of the object pointed to */ xdrproc_t proc; /* xdr routine to handle the object */ { - register caddr_t loc = *pp; - register bool_t stat; + caddr_t loc = *pp; + bool_t stat; if (loc == NULL) switch (xdrs->x_op) { @@ -100,16 +105,17 @@ xdr_reference(xdrs, pp, size, proc) case XDR_DECODE: *pp = loc = (caddr_t) mem_alloc(size); if (loc == NULL) { - (void) fprintf(stderr, - "xdr_reference: out of memory\n"); + warnx("xdr_reference: out of memory"); return (FALSE); } - bzero(loc, (int)size); + memset(loc, 0, size); break; - default: break; - } - stat = (*proc)(xdrs, loc, LASTUNSIGNED); + case XDR_ENCODE: + break; + } + + stat = (*proc)(xdrs, loc); if (xdrs->x_op == XDR_FREE) { mem_free(loc, size); @@ -140,7 +146,7 @@ xdr_reference(xdrs, pp, size, proc) */ bool_t xdr_pointer(xdrs,objpp,obj_size,xdr_obj) - register XDR *xdrs; + XDR *xdrs; char **objpp; u_int obj_size; xdrproc_t xdr_obj; diff --git a/rpc.subproj/xdr_sizeof.c b/rpc.subproj/xdr_sizeof.c new file mode 100644 index 0000000..a96c1e8 --- /dev/null +++ b/rpc.subproj/xdr_sizeof.c @@ -0,0 +1,194 @@ +/* + * 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@ + */ + +/* + * 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 + */ +/* + * xdr_sizeof.c + * + * Copyright 1990 Sun Microsystems, Inc. + * + * General purpose routine to see how much space something will use + * when serialized using XDR. + */ + +#include + +#include +#include +#include +#include + +/* ARGSUSED */ +static bool_t +x_putlong(xdrs, longp) + XDR *xdrs; + long *longp; +{ + xdrs->x_handy += BYTES_PER_XDR_UNIT; + return (TRUE); +} + +/* ARGSUSED */ +static bool_t +x_putbytes(xdrs, bp, len) + XDR *xdrs; + char *bp; + u_int len; +{ + xdrs->x_handy += len; + return (TRUE); +} + +static u_int +x_getpostn(xdrs) + XDR *xdrs; +{ + return (xdrs->x_handy); +} + +/* ARGSUSED */ +static bool_t +x_setpostn(xdrs, pos) + XDR *xdrs; + u_int pos; +{ + /* This is not allowed */ + return (FALSE); +} + +static int32_t * +x_inline(xdrs, len) + XDR *xdrs; + u_int len; +{ + long llen; + + if (len == 0) { + return (NULL); + } + if (xdrs->x_op != XDR_ENCODE) { + return (NULL); + } + + llen = len; + + if (llen < xdrs->x_base) { + /* x_private was already allocated */ + xdrs->x_handy += llen; + return ((int32_t *) xdrs->x_private); + } else { + /* Free the earlier space and allocate new area */ + if (xdrs->x_private) + free(xdrs->x_private); + if ((xdrs->x_private = (caddr_t) malloc(len)) == NULL) { + xdrs->x_base = 0; + return (NULL); + } + xdrs->x_base = (caddr_t)llen; + xdrs->x_handy += llen; + return ((int32_t *) xdrs->x_private); + } +} + +static int +harmless() +{ + /* Always return FALSE/NULL, as the case may be */ + return (0); +} + +static void +x_destroy(xdrs) + XDR *xdrs; +{ + xdrs->x_handy = 0; + xdrs->x_base = 0; + if (xdrs->x_private) { + free(xdrs->x_private); + xdrs->x_private = NULL; + } + return; +} + +unsigned long +xdr_sizeof(func, data) + xdrproc_t func; + void *data; +{ + XDR x; + struct xdr_ops ops; + bool_t stat; + /* to stop ANSI-C compiler from complaining */ + typedef bool_t (* dummyfunc1)(XDR *, long *); + typedef bool_t (* dummyfunc2)(XDR *, caddr_t, u_int); + + ops.x_putlong = x_putlong; + ops.x_putbytes = x_putbytes; + ops.x_inline = x_inline; + ops.x_getpostn = x_getpostn; + ops.x_setpostn = x_setpostn; + ops.x_destroy = x_destroy; + + /* the other harmless ones */ + ops.x_getlong = (dummyfunc1) harmless; + ops.x_getbytes = (dummyfunc2) harmless; + + x.x_op = XDR_ENCODE; + x.x_ops = &ops; + x.x_handy = 0; + x.x_private = (caddr_t) NULL; + x.x_base = (caddr_t) 0; + + stat = func(&x, data); + if (x.x_private) + free(x.x_private); + return (stat == TRUE ? (unsigned) x.x_handy: 0); +} diff --git a/rpc.subproj/xdr_stdio.c b/rpc.subproj/xdr_stdio.c index d4c6b49..ec955bc 100644 --- a/rpc.subproj/xdr_stdio.c +++ b/rpc.subproj/xdr_stdio.c @@ -21,6 +21,9 @@ * * @APPLE_LICENSE_HEADER_END@ */ + +/* $NetBSD: xdr_stdio.c,v 1.14 2000/01/22 22:19:19 mycroft Exp $ */ + /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape @@ -28,33 +31,33 @@ * 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 */ #if defined(LIBC_SCCS) && !defined(lint) -/*static char *sccsid = "from: @(#)xdr_stdio.c 1.16 87/08/11 Copyr 1984 Sun Micro";*/ -/*static char *sccsid = "from: @(#)xdr_stdio.c 2.1 88/07/29 4.0 RPCSRC";*/ -static char *rcsid = "$Id: xdr_stdio.c,v 1.2 1999/10/14 21:56:55 wsanchez Exp $"; +static char *sccsid = "@(#)xdr_stdio.c 1.16 87/08/11 Copyr 1984 Sun Micro"; +static char *sccsid = "@(#)xdr_stdio.c 2.1 88/07/29 4.0 RPCSRC"; #endif +#include /* * xdr_stdio.c, XDR implementation on standard i/o file. @@ -66,23 +69,25 @@ static char *rcsid = "$Id: xdr_stdio.c,v 1.2 1999/10/14 21:56:55 wsanchez Exp $" * from the stream. */ -#include #include + +#include +#include #include -static bool_t xdrstdio_getlong(); -static bool_t xdrstdio_putlong(); -static bool_t xdrstdio_getbytes(); -static bool_t xdrstdio_putbytes(); -static u_int xdrstdio_getpos(); -static bool_t xdrstdio_setpos(); -static long * xdrstdio_inline(); -static void xdrstdio_destroy(); +static void xdrstdio_destroy(XDR *); +static bool_t xdrstdio_getlong(XDR *, long *); +static bool_t xdrstdio_putlong(XDR *, const long *); +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 *); +static bool_t xdrstdio_setpos(XDR *, u_int); +static int32_t *xdrstdio_inline(XDR *, u_int); /* * Ops vector for stdio type XDR */ -static struct xdr_ops xdrstdio_ops = { +static const struct xdr_ops xdrstdio_ops = { xdrstdio_getlong, /* deseraialize a long int */ xdrstdio_putlong, /* seraialize a long int */ xdrstdio_getbytes, /* deserialize counted bytes */ @@ -100,14 +105,14 @@ static struct xdr_ops xdrstdio_ops = { */ void xdrstdio_create(xdrs, file, op) - register XDR *xdrs; + XDR *xdrs; FILE *file; enum xdr_op op; { xdrs->x_op = op; xdrs->x_ops = &xdrstdio_ops; - xdrs->x_private = (caddr_t)file; + xdrs->x_private = file; xdrs->x_handy = 0; xdrs->x_base = 0; } @@ -118,37 +123,33 @@ xdrstdio_create(xdrs, file, op) */ static void xdrstdio_destroy(xdrs) - register XDR *xdrs; + XDR *xdrs; { (void)fflush((FILE *)xdrs->x_private); - /* xx should we close the file ?? */ -}; + /* XXX: should we close the file ?? */ +} static bool_t xdrstdio_getlong(xdrs, lp) XDR *xdrs; - register long *lp; + long *lp; { + u_int32_t temp; - if (fread((caddr_t)lp, sizeof(long), 1, (FILE *)xdrs->x_private) != 1) + if (fread(&temp, sizeof(int32_t), 1, (FILE *)xdrs->x_private) != 1) return (FALSE); -#ifndef mc68000 - *lp = ntohl(*lp); -#endif + *lp = (long)ntohl(temp); return (TRUE); } static bool_t xdrstdio_putlong(xdrs, lp) XDR *xdrs; - long *lp; + const long *lp; { + int32_t mycopy = htonl((u_int32_t)*lp); -#ifndef mc68000 - long mycopy = htonl(*lp); - lp = &mycopy; -#endif - if (fwrite((caddr_t)lp, sizeof(long), 1, (FILE *)xdrs->x_private) != 1) + if (fwrite(&mycopy, sizeof(int32_t), 1, (FILE *)xdrs->x_private) != 1) return (FALSE); return (TRUE); } @@ -156,11 +157,11 @@ xdrstdio_putlong(xdrs, lp) static bool_t xdrstdio_getbytes(xdrs, addr, len) XDR *xdrs; - caddr_t addr; + char *addr; u_int len; { - if ((len != 0) && (fread(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1)) + if ((len != 0) && (fread(addr, (size_t)len, 1, (FILE *)xdrs->x_private) != 1)) return (FALSE); return (TRUE); } @@ -168,11 +169,12 @@ xdrstdio_getbytes(xdrs, addr, len) static bool_t xdrstdio_putbytes(xdrs, addr, len) XDR *xdrs; - caddr_t addr; + const char *addr; u_int len; { - if ((len != 0) && (fwrite(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1)) + if ((len != 0) && (fwrite(addr, (size_t)len, 1, + (FILE *)xdrs->x_private) != 1)) return (FALSE); return (TRUE); } @@ -195,7 +197,8 @@ xdrstdio_setpos(xdrs, pos) FALSE : TRUE); } -static long * +/* ARGSUSED */ +static int32_t * xdrstdio_inline(xdrs, len) XDR *xdrs; u_int len; diff --git a/util.subproj/Makefile b/util.subproj/Makefile index f3bb751..fed6205 100644 --- a/util.subproj/Makefile +++ b/util.subproj/Makefile @@ -12,7 +12,7 @@ NAME = util PROJECTVERSION = 2.8 PROJECT_TYPE = Component -CFILES = glob.c hton.c putpwpasswd.c pwcache.c rcmd.c\ +CFILES = hton.c putpwpasswd.c pwcache.c rcmd.c\ rcmdsh.c OTHERSRCS = Makefile Makefile.preamble Makefile.postamble rcmd.3 hosts.equiv.5 diff --git a/util.subproj/Makefile.preamble b/util.subproj/Makefile.preamble index 4a51a2c..7b61caa 100644 --- a/util.subproj/Makefile.preamble +++ b/util.subproj/Makefile.preamble @@ -1,3 +1,7 @@ AFTER_POSTINSTALL += install-man-page OTHER_CFLAGS = \ -DINET6=1 + +# for building 64-bit +# Libinfo need to build with gcc-3.5 and 3-way fat +NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER) diff --git a/util.subproj/PB.project b/util.subproj/PB.project index 90b1556..af7392b 100644 --- a/util.subproj/PB.project +++ b/util.subproj/PB.project @@ -1,7 +1,7 @@ { DYNAMIC_CODE_GEN = YES; FILESTABLE = { - OTHER_LINKED = (glob.c, hton.c, putpwpasswd.c, pwcache.c, rcmd.c, rcmdsh.c); + OTHER_LINKED = (hton.c, putpwpasswd.c, pwcache.c, rcmd.c, rcmdsh.c); OTHER_SOURCES = (Makefile, Makefile.preamble, Makefile.postamble, rcmd.3, hosts.equiv.5); }; LANGUAGE = English; diff --git a/util.subproj/glob.c b/util.subproj/glob.c deleted file mode 100644 index b27c283..0000000 --- a/util.subproj/glob.c +++ /dev/null @@ -1,897 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved - * - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Guido van Rossum. - * - * The NEXTSTEP Software License Agreement specifies the terms - * and conditions for redistribution. - * - * @(#)glob.c 8.3 (Berkeley) 10/13/93 - */ - -/* - * glob(3) -- a superset of the one defined in POSIX 1003.2. - * - * The [!...] convention to negate a range is supported (SysV, Posix, ksh). - * - * Optional extra services, controlled by flags not defined by POSIX: - * - * GLOB_QUOTE: - * Escaping convention: \ inhibits any special meaning the following - * character might have (except \ at end of string is retained). - * GLOB_MAGCHAR: - * Set in gl_flags if pattern contained a globbing character. - * GLOB_NOMAGIC: - * Same as GLOB_NOCHECK, but it will only append pattern if it did - * not contain any magic characters. [Used in csh style globbing] - * GLOB_ALTDIRFUNC: - * Use alternately specified directory access functions. - * GLOB_TILDE: - * expand ~user/foo to the /home/dir/of/user/foo - * GLOB_BRACE: - * expand {1,2}{a,b} to 1a 1b 2a 2b - * gl_matchc: - * Number of matches in the current invocation of glob. - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DOLLAR '$' -#define DOT '.' -#define EOS '\0' -#define LBRACKET '[' -#define NOT '!' -#define QUESTION '?' -#define QUOTE '\\' -#define RANGE '-' -#define RBRACKET ']' -#define SEP '/' -#define STAR '*' -#define TILDE '~' -#define UNDERSCORE '_' -#define LBRACE '{' -#define RBRACE '}' -#define SLASH '/' -#define COMMA ',' - -#ifndef DEBUG - -#define M_QUOTE 0x8000 -#define M_PROTECT 0x4000 -#define M_MASK 0xffff -#define M_ASCII 0x00ff - -typedef u_short Char; - -#else - -#define M_QUOTE 0x80 -#define M_PROTECT 0x40 -#define M_MASK 0xff -#define M_ASCII 0x7f - -typedef char Char; - -#endif - - -#define CHAR(c) ((Char)((c)&M_ASCII)) -#define META(c) ((Char)((c)|M_QUOTE)) -#define M_ALL META('*') -#define M_END META(']') -#define M_NOT META('!') -#define M_ONE META('?') -#define M_RNG META('-') -#define M_SET META('[') -#define ismeta(c) (((c)&M_QUOTE) != 0) - - -static int compare __P((const void *, const void *)); -static int g_Ctoc __P((const Char *, char *, u_int)); -static int g_lstat __P((Char *, struct stat *, glob_t *)); -static DIR *g_opendir __P((Char *, glob_t *)); -static Char *g_strchr __P((Char *, int)); -#ifdef notdef -static Char *g_strcat __P((Char *, const Char *)); -#endif -static int g_stat __P((Char *, struct stat *, glob_t *)); -static int glob0 __P((const Char *, glob_t *, int *)); -static int glob1 __P((Char *, glob_t *, int *)); -static int glob2 __P((Char *, Char *, Char *, Char *, glob_t *, int *)); -static int glob3 __P((Char *, Char *, Char *, Char *, Char *, glob_t *, int *)); -static int globextend __P((const Char *, glob_t *, int *)); -static const Char * - globtilde __P((const Char *, Char *, size_t, glob_t *)); -static int globexp1 __P((const Char *, glob_t *, int *)); -static int globexp2 __P((const Char *, const Char *, glob_t *, int *, int *)); -static int match __P((Char *, Char *, Char *)); -#ifdef DEBUG -static void qprintf __P((const char *, Char *)); -#endif - -int -glob(pattern, flags, errfunc, pglob) - const char *pattern; - int flags, (*errfunc) __P((const char *, int)); - glob_t *pglob; -{ - const u_char *patnext; - int c, limit; - Char *bufnext, *bufend, patbuf[MAXPATHLEN]; - - patnext = (u_char *) pattern; - if (!(flags & GLOB_APPEND)) { - pglob->gl_pathc = 0; - pglob->gl_pathv = NULL; - if (!(flags & GLOB_DOOFFS)) - pglob->gl_offs = 0; - } -#if !defined(GLOB_MAXPATH) -#define GLOB_MAXPATH 0x1000 -#endif - if (flags & GLOB_MAXPATH) - limit = pglob->gl_matchc; - else - limit = 0; - pglob->gl_flags = flags & ~GLOB_MAGCHAR; - pglob->gl_errfunc = errfunc; - pglob->gl_matchc = 0; - - bufnext = patbuf; - bufend = bufnext + MAXPATHLEN - 1; - if (flags & GLOB_QUOTE) { - /* Protect the quoted characters. */ - while (bufnext < bufend && (c = *patnext++) != EOS) - if (c == QUOTE) { - if ((c = *patnext++) == EOS) { - c = QUOTE; - --patnext; - } - *bufnext++ = c | M_PROTECT; - } - else - *bufnext++ = c; - } - else - while (bufnext < bufend && (c = *patnext++) != EOS) - *bufnext++ = c; - *bufnext = EOS; - - if (flags & GLOB_BRACE) - return globexp1(patbuf, pglob, &limit); - else - return glob0(patbuf, pglob, &limit); -} - -/* - * Expand recursively a glob {} pattern. When there is no more expansion - * invoke the standard globbing routine to glob the rest of the magic - * characters - */ -static int -globexp1(pattern, pglob, limit) - const Char *pattern; - glob_t *pglob; - int *limit; -{ - const Char* ptr = pattern; - int rv; - - /* Protect a single {}, for find(1), like csh */ - if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) - return glob0(pattern, pglob, limit); - - while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL) - if (!globexp2(ptr, pattern, pglob, &rv, limit)) - return rv; - - return glob0(pattern, pglob, limit); -} - - -/* - * Recursive brace globbing helper. Tries to expand a single brace. - * If it succeeds then it invokes globexp1 with the new pattern. - * If it fails then it tries to glob the rest of the pattern and returns. - */ -static int -globexp2(ptr, pattern, pglob, rv, limit) - const Char *ptr, *pattern; - glob_t *pglob; - int *rv, *limit; -{ - int i; - Char *lm, *ls; - const Char *pe, *pm, *pl; - Char patbuf[MAXPATHLEN]; - - /* copy part up to the brace */ - for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) - continue; - *lm = EOS; - ls = lm; - - /* Find the balanced brace */ - for (i = 0, pe = ++ptr; *pe; pe++) - if (*pe == LBRACKET) { - /* Ignore everything between [] */ - for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++) - continue; - if (*pe == EOS) { - /* - * We could not find a matching RBRACKET. - * Ignore and just look for RBRACE - */ - pe = pm; - } - } - else if (*pe == LBRACE) - i++; - else if (*pe == RBRACE) { - if (i == 0) - break; - i--; - } - - /* Non matching braces; just glob the pattern */ - if (i != 0 || *pe == EOS) { - *rv = glob0(patbuf, pglob, limit); - return 0; - } - - for (i = 0, pl = pm = ptr; pm <= pe; pm++) - switch (*pm) { - case LBRACKET: - /* Ignore everything between [] */ - for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++) - continue; - if (*pm == EOS) { - /* - * We could not find a matching RBRACKET. - * Ignore and just look for RBRACE - */ - pm = pl; - } - break; - - case LBRACE: - i++; - break; - - case RBRACE: - if (i) { - i--; - break; - } - /* FALLTHROUGH */ - case COMMA: - if (i && *pm == COMMA) - break; - else { - /* Append the current string */ - for (lm = ls; (pl < pm); *lm++ = *pl++) - continue; - /* - * Append the rest of the pattern after the - * closing brace - */ - for (pl = pe + 1; (*lm++ = *pl++) != EOS;) - continue; - - /* Expand the current pattern */ -#ifdef DEBUG - qprintf("globexp2:", patbuf); -#endif - *rv = globexp1(patbuf, pglob, limit); - - /* move after the comma, to the next string */ - pl = pm + 1; - } - break; - - default: - break; - } - *rv = 0; - return 0; -} - - - -/* - * expand tilde from the passwd file. - */ -static const Char * -globtilde(pattern, patbuf, patbuf_len, pglob) - const Char *pattern; - Char *patbuf; - size_t patbuf_len; - glob_t *pglob; -{ - struct passwd *pwd; - char *h; - const Char *p; - Char *b, *eb; - - if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE)) - return pattern; - - /* - * Copy up to the end of the string or / - */ - eb = &patbuf[patbuf_len - 1]; - for (p = pattern + 1, h = (char *) patbuf; - h < (char *)eb && *p && *p != SLASH; *h++ = *p++) - continue; - - *h = EOS; - - if (((char *) patbuf)[0] == EOS) { - /* - * handle a plain ~ or ~/ by expanding $HOME first (iff - * we're not running setuid or setgid) and then trying - * the password file - */ - if ( -#if 0 -#ifndef __NETBSD_SYSCALLS - issetugid() != 0 || -#endif -#endif - (h = getenv("HOME")) == NULL) { - if (((h = getlogin()) != NULL && - (pwd = getpwnam(h)) != NULL) || - (pwd = getpwuid(getuid())) != NULL) - h = pwd->pw_dir; - else - return pattern; - } - } - else { - /* - * Expand a ~user - */ - if ((pwd = getpwnam((char*) patbuf)) == NULL) - return pattern; - else - h = pwd->pw_dir; - } - - /* Copy the home directory */ - for (b = patbuf; b < eb && *h; *b++ = *h++) - continue; - - /* Append the rest of the pattern */ - while (b < eb && (*b++ = *p++) != EOS) - continue; - *b = EOS; - - return patbuf; -} - - -/* - * The main glob() routine: compiles the pattern (optionally processing - * quotes), calls glob1() to do the real pattern matching, and finally - * sorts the list (unless unsorted operation is requested). Returns 0 - * if things went well, nonzero if errors occurred. It is not an error - * to find no matches. - */ -static int -glob0(pattern, pglob, limit) - const Char *pattern; - glob_t *pglob; - int *limit; -{ - const Char *qpatnext; - int c, err, oldpathc; - Char *bufnext, patbuf[MAXPATHLEN]; - - qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob); - oldpathc = pglob->gl_pathc; - bufnext = patbuf; - - /* We don't need to check for buffer overflow any more. */ - while ((c = *qpatnext++) != EOS) { - switch (c) { - case LBRACKET: - c = *qpatnext; - if (c == NOT) - ++qpatnext; - if (*qpatnext == EOS || - g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) { - *bufnext++ = LBRACKET; - if (c == NOT) - --qpatnext; - break; - } - *bufnext++ = M_SET; - if (c == NOT) - *bufnext++ = M_NOT; - c = *qpatnext++; - do { - *bufnext++ = CHAR(c); - if (*qpatnext == RANGE && - (c = qpatnext[1]) != RBRACKET) { - *bufnext++ = M_RNG; - *bufnext++ = CHAR(c); - qpatnext += 2; - } - } while ((c = *qpatnext++) != RBRACKET); - pglob->gl_flags |= GLOB_MAGCHAR; - *bufnext++ = M_END; - break; - case QUESTION: - pglob->gl_flags |= GLOB_MAGCHAR; - *bufnext++ = M_ONE; - break; - case STAR: - pglob->gl_flags |= GLOB_MAGCHAR; - /* collapse adjacent stars to one, - * to avoid exponential behavior - */ - if (bufnext == patbuf || bufnext[-1] != M_ALL) - *bufnext++ = M_ALL; - break; - default: - *bufnext++ = CHAR(c); - break; - } - } - *bufnext = EOS; -#ifdef DEBUG - qprintf("glob0:", patbuf); -#endif - - if ((err = glob1(patbuf, pglob, limit)) != 0) - return(err); - - /* - * If there was no match we are going to append the pattern - * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified - * and the pattern did not contain any magic characters - * GLOB_NOMAGIC is there just for compatibility with csh. - */ - if (pglob->gl_pathc == oldpathc && - ((pglob->gl_flags & GLOB_NOCHECK) || - ((pglob->gl_flags & GLOB_NOMAGIC) && - !(pglob->gl_flags & GLOB_MAGCHAR)))) - return(globextend(pattern, pglob, limit)); - else if (!(pglob->gl_flags & GLOB_NOSORT)) - qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, - pglob->gl_pathc - oldpathc, sizeof(char *), compare); - return(0); -} - -static int -compare(p, q) - const void *p, *q; -{ - return(strcmp(*(char **)p, *(char **)q)); -} - -static int -glob1(pattern, pglob, limit) - Char *pattern; - glob_t *pglob; - int *limit; -{ - Char pathbuf[MAXPATHLEN]; - - /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ - if (*pattern == EOS) - return(0); - return(glob2(pathbuf, pathbuf, pathbuf + MAXPATHLEN - 1, - pattern, pglob, limit)); -} - -/* - * The functions glob2 and glob3 are mutually recursive; there is one level - * of recursion for each segment in the pattern that contains one or more - * meta characters. - */ -static int -glob2(pathbuf, pathend, pathend_last, pattern, pglob, limit) - Char *pathbuf, *pathend, *pathend_last, *pattern; - glob_t *pglob; - int *limit; -{ - struct stat sb; - Char *p, *q; - int anymeta; - - /* - * Loop over pattern segments until end of pattern or until - * segment with meta character found. - */ - for (anymeta = 0;;) { - if (*pattern == EOS) { /* End of pattern? */ - *pathend = EOS; - if (g_lstat(pathbuf, &sb, pglob)) - return(0); - - if (((pglob->gl_flags & GLOB_MARK) && - pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) - || (S_ISLNK(sb.st_mode) && - (g_stat(pathbuf, &sb, pglob) == 0) && - S_ISDIR(sb.st_mode)))) { - if (pathend + 1 > pathend_last) - return (1); - *pathend++ = SEP; - *pathend = EOS; - } - ++pglob->gl_matchc; - return(globextend(pathbuf, pglob, limit)); - } - - /* Find end of next segment, copy tentatively to pathend. */ - q = pathend; - p = pattern; - while (*p != EOS && *p != SEP) { - if (ismeta(*p)) - anymeta = 1; - if (q + 1 > pathend_last) - return (1); - *q++ = *p++; - } - - if (!anymeta) { /* No expansion, do next segment. */ - pathend = q; - pattern = p; - while (*pattern == SEP) { - if (pathend + 1 > pathend_last) - return (1); - *pathend++ = *pattern++; - } - } else /* Need expansion, recurse. */ - return(glob3(pathbuf, pathend, pathend_last, pattern, p, - pglob, limit)); - } - /* NOTREACHED */ -} - -static int -glob3(pathbuf, pathend, pathend_last, pattern, restpattern, pglob, limit) - Char *pathbuf, *pathend, *pathend_last, *pattern, *restpattern; - glob_t *pglob; - int *limit; -{ - register struct dirent *dp; - DIR *dirp; - int err; - char buf[MAXPATHLEN]; - - /* - * The readdirfunc declaration can't be prototyped, because it is - * assigned, below, to two functions which are prototyped in glob.h - * and dirent.h as taking pointers to differently typed opaque - * structures. - */ - struct dirent *(*readdirfunc)(); - - if (pathend > pathend_last) - return (1); - *pathend = EOS; - errno = 0; - - if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { - /* TODO: don't call for ENOENT or ENOTDIR? */ - if (pglob->gl_errfunc) { - if (g_Ctoc(pathbuf, buf, sizeof(buf))) - return (GLOB_ABEND); - if (pglob->gl_errfunc(buf, errno) || - pglob->gl_flags & GLOB_ERR) - return (GLOB_ABEND); - } - return(0); - } - - err = 0; - - /* Search directory for matching names. */ - if (pglob->gl_flags & GLOB_ALTDIRFUNC) - readdirfunc = pglob->gl_readdir; - else - readdirfunc = readdir; - while ((dp = (*readdirfunc)(dirp))) { - register u_char *sc; - register Char *dc; - - /* Initial DOT must be matched literally. */ - if (dp->d_name[0] == DOT && *pattern != DOT) - continue; - dc = pathend; - sc = (u_char *) dp->d_name; - while (dc < pathend_last && (*dc++ = *sc++) != EOS) - ; - if (!match(pathend, pattern, restpattern)) { - *pathend = EOS; - continue; - } - err = glob2(pathbuf, --dc, pathend_last, restpattern, - pglob, limit); - if (err) - break; - } - - if (pglob->gl_flags & GLOB_ALTDIRFUNC) - (*pglob->gl_closedir)(dirp); - else - closedir(dirp); - return(err); -} - - -/* - * Extend the gl_pathv member of a glob_t structure to accomodate a new item, - * add the new item, and update gl_pathc. - * - * This assumes the BSD realloc, which only copies the block when its size - * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic - * behavior. - * - * Return 0 if new item added, error code if memory couldn't be allocated. - * - * Invariant of the glob_t structure: - * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and - * gl_pathv points to (gl_offs + gl_pathc + 1) items. - */ -static int -globextend(path, pglob, limit) - const Char *path; - glob_t *pglob; - int *limit; -{ - register char **pathv; - register int i; - u_int newsize, len; - char *copy; - const Char *p; - - if (*limit && pglob->gl_pathc > *limit) -#if !defined(GLOB_LIMIT) -#define GLOB_LIMIT (-3) -#endif - return (GLOB_LIMIT); - - newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); - pathv = pglob->gl_pathv ? - realloc((char *)pglob->gl_pathv, newsize) : - malloc(newsize); - if (pathv == NULL) { - if (pglob->gl_pathv) { - free(pglob->gl_pathv); - pglob->gl_pathv = NULL; - } - return(GLOB_NOSPACE); - } - - if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { - /* first time around -- clear initial gl_offs items */ - pathv += pglob->gl_offs; - for (i = pglob->gl_offs; --i >= 0; ) - *--pathv = NULL; - } - pglob->gl_pathv = pathv; - - for (p = path; *p++;) - continue; - len = (size_t)(p - path); - if ((copy = malloc(len)) != NULL) { - if (g_Ctoc(path, copy, len)) { - free(copy); - return (GLOB_NOSPACE); - } - pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; - } - pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; - return(copy == NULL ? GLOB_NOSPACE : 0); -} - -/* - * pattern matching function for filenames. Each occurrence of the * - * pattern causes a recursion level. - */ -static int -match(name, pat, patend) - register Char *name, *pat, *patend; -{ - int ok, negate_range; - Char c, k; - - while (pat < patend) { - c = *pat++; - switch (c & M_MASK) { - case M_ALL: - if (pat == patend) - return(1); - do - if (match(name, pat, patend)) - return(1); - while (*name++ != EOS); - return(0); - case M_ONE: - if (*name++ == EOS) - return(0); - break; - case M_SET: - ok = 0; - if ((k = *name++) == EOS) - return(0); - if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) - ++pat; - while (((c = *pat++) & M_MASK) != M_END) - if ((*pat & M_MASK) == M_RNG) { - if (c <= k && k <= pat[1]) - ok = 1; - pat += 2; - } else if (c == k) - ok = 1; - if (ok == negate_range) - return(0); - break; - default: - if (*name++ != c) - return(0); - break; - } - } - return(*name == EOS); -} - -/* Free allocated data belonging to a glob_t structure. */ -void -globfree(pglob) - glob_t *pglob; -{ - register int i; - register char **pp; - - if (pglob->gl_pathv != NULL) { - pp = pglob->gl_pathv + pglob->gl_offs; - for (i = pglob->gl_pathc; i--; ++pp) - if (*pp) - free(*pp); - free(pglob->gl_pathv); - pglob->gl_pathv = NULL; - } -} - -static DIR * -g_opendir(str, pglob) - register Char *str; - glob_t *pglob; -{ - char buf[MAXPATHLEN]; - - if (!*str) - strcpy(buf, "."); - else { - if (g_Ctoc(str, buf, sizeof(buf))) - return (NULL); - } - - if (pglob->gl_flags & GLOB_ALTDIRFUNC) - return((*pglob->gl_opendir)(buf)); - - return(opendir(buf)); -} - -static int -g_lstat(fn, sb, pglob) - register Char *fn; - struct stat *sb; - glob_t *pglob; -{ - char buf[MAXPATHLEN]; - - if (g_Ctoc(fn, buf, sizeof(buf))) { - errno = ENAMETOOLONG; - return (-1); - } - if (pglob->gl_flags & GLOB_ALTDIRFUNC) - return((*pglob->gl_lstat)(buf, sb)); - return(lstat(buf, sb)); -} - -static int -g_stat(fn, sb, pglob) - register Char *fn; - struct stat *sb; - glob_t *pglob; -{ - char buf[MAXPATHLEN]; - - if (g_Ctoc(fn, buf, sizeof(buf))) { - errno = ENAMETOOLONG; - return (-1); - } - if (pglob->gl_flags & GLOB_ALTDIRFUNC) - return((*pglob->gl_stat)(buf, sb)); - return(stat(buf, sb)); -} - -static Char * -g_strchr(str, ch) - Char *str; - int ch; -{ - do { - if (*str == ch) - return (str); - } while (*str++); - return (NULL); -} - -static int -g_Ctoc(str, buf, len) - const Char *str; - char *buf; - u_int len; -{ - - while (len--) { - if ((*buf++ = *str++) == '\0') - return (0); - } - return (1); -} - -#ifdef DEBUG -static void -qprintf(str, s) - const char *str; - register Char *s; -{ - register Char *p; - - (void)printf("%s:\n", str); - for (p = s; *p; p++) - (void)printf("%c", CHAR(*p)); - (void)printf("\n"); - for (p = s; *p; p++) - (void)printf("%c", *p & M_PROTECT ? '"' : ' '); - (void)printf("\n"); - for (p = s; *p; p++) - (void)printf("%c", ismeta(*p) ? '_' : ' '); - (void)printf("\n"); -} -#endif diff --git a/util.subproj/pwcache.c b/util.subproj/pwcache.c index 0d9b517..53e79f3 100644 --- a/util.subproj/pwcache.c +++ b/util.subproj/pwcache.c @@ -21,18 +21,6 @@ * * @APPLE_LICENSE_HEADER_END@ */ -/* - * Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved - * - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * The NEXTSTEP Software License Agreement specifies the terms - * and conditions for redistribution. - * - * @(#)pwcache.c 8.1 (Berkeley) 6/4/93 - */ - #include -- 2.45.2