X-Git-Url: https://git.saurik.com/apple/libinfo.git/blobdiff_plain/708d63e9d2a7d24723abca74fe82e274b687afaf..918ca66e27695feb15a7ff09a350064e1af20e57:/netinfo.subproj/ni_glue.c?ds=sidebyside diff --git a/netinfo.subproj/ni_glue.c b/netinfo.subproj/ni_glue.c index b6129bc..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. * @@ -26,6 +26,7 @@ * Copyright (C) 1989 by NeXT, Inc. */ #include +#include #include #include #include @@ -33,6 +34,7 @@ #include #include #include +#include #include "clib.h" #include "sys_interfaces.h" @@ -40,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 */ @@ -55,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 */ @@ -77,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"; @@ -85,60 +91,53 @@ static const ni_name NAME_MASTER = "master"; static const ni_name NAME_USERS = "users"; static const ni_name NAME_UID = "uid"; +static const ni_name NAME_DOMAIN_SERVERS = "domain_servers"; + typedef struct getreg_stuff { nibind_getregister_res res; ni_private *ni; } getreg_stuff; - static int socket_open(struct sockaddr_in *raddr, int, int, int, int, int); - +extern int bindresvport(int, struct sockaddr_in *); /* - * Keep track of our port, in case somebody closes our socket - * on us. + * 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; @@ -146,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); } @@ -169,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) { @@ -214,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; } @@ -309,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; } @@ -334,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); } @@ -366,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(); @@ -384,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; } @@ -418,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; @@ -434,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; } @@ -475,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; @@ -527,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; } /* @@ -540,7 +561,7 @@ rebind( * all other servers are next */ - ilist = sys_interfaces(); + ilist = _libinfo_ni_sys_interfaces(); /* * shuffle addresses @@ -551,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++; @@ -563,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; } @@ -669,34 +672,44 @@ 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. */ - auth_destroy(ni->tc->cl_auth); - clnt_destroy(ni->tc); - ni->tc = NULL; - } - if (!needwrite && !rebind(ni) && ni->abort) { - return (0); + if (ni->tc != NULL) + { + if (ni->tc->cl_auth != NULL) auth_destroy(ni->tc->cl_auth); + clnt_destroy(ni->tc); + ni->tc = NULL; + } } - 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; @@ -709,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; @@ -798,77 +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; } - clnt_geterr(ni->tc, &err); - if (err.re_status != RPC_CANTRECV) { - break; + + if (ni->tc != NULL) + { + clnt_geterr(ni->tc, &err); + if (err.re_status != RPC_CANTRECV) break; } - if (i + 1 < NI_MAXCONNTRIES) { - /* - * 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 @@ -876,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; @@ -958,245 +982,254 @@ 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; } +static void +add_addr_tag(ni_private *ni, ni_name addrtag) +{ + struct in_addr addr; + ni_name tag; + char *slash; + + slash = strchr(addrtag, '/'); + if (slash == NULL) return; + + tag = slash + 1; + if (tag[0] == '\0') return; + + *slash = '\0'; + + if (inet_aton(addrtag, &addr) == 0) return; + + if (ni->naddrs == 0) + { + ni->addrs = (struct in_addr *)calloc(1, sizeof(struct in_addr)); + if (ni->addrs == NULL) return; + + ni->tags = (ni_name *)calloc(1, sizeof(ni_name)); + if (ni->tags == NULL) return; + } + else + { + ni->addrs = (struct in_addr *)realloc(ni->addrs, ((ni->naddrs + 1) * sizeof(struct in_addr))); + if (ni->addrs == NULL) return; + + ni->tags = (ni_name *)realloc(ni->tags, ((ni->naddrs + 1) * sizeof(ni_name))); + if (ni->tags == NULL) return; + } + + ni->addrs[ni->naddrs] = addr; + ni->tags[ni->naddrs] = ni_name_dup(tag); + ni->naddrs++; +} + static int -addaddr( - void *ni, - ni_index ido, - ni_name tag, - ni_private *target_ni - ) +addaddr(void *ni, ni_index ido, ni_name tag, ni_private *target_ni) { ni_id id; ni_namelist nl; 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); - } - if (nl.ninl_len == 0) { - return(0); - } - if (target_ni->naddrs == 0) { - target_ni->addrs = - (struct in_addr *)malloc(nl.ninl_len * sizeof(struct in_addr)); - target_ni->tags = - (ni_name *)malloc(nl.ninl_len * sizeof(ni_name)); - } else { - target_ni->addrs = - (struct in_addr *)realloc(target_ni->addrs, - ((target_ni->naddrs + nl.ninl_len) * sizeof(struct in_addr))); - target_ni->tags = - (ni_name *)realloc(target_ni->tags, - ((target_ni->naddrs + nl.ninl_len) * sizeof(ni_name))); + status = ni_lookupprop(ni, &id, NAME_IP_ADDRESS, &nl); + if (status != NI_OK) return 0; + + if (nl.ni_namelist_len == 0) return 0; + + if (target_ni->naddrs == 0) + { + target_ni->addrs = (struct in_addr *)malloc(nl.ni_namelist_len * sizeof(struct in_addr)); + target_ni->tags = (ni_name *)malloc(nl.ni_namelist_len * sizeof(ni_name)); + } + else + { + target_ni->addrs = (struct in_addr *)realloc(target_ni->addrs, ((target_ni->naddrs + nl.ni_namelist_len) * sizeof(struct in_addr))); + target_ni->tags = (ni_name *)realloc(target_ni->tags, ((target_ni->naddrs + nl.ni_namelist_len) * sizeof(ni_name))); } - for (i=0; iaddrs[target_ni->naddrs] = addr; target_ni->tags[target_ni->naddrs] = ni_name_dup(tag); target_ni->naddrs++; } ni_namelist_free(&nl); - return (1); + return 1; } - static int -get_daddr( - ni_private *ni, - ni_name dom, - ni_private *target_ni - ) +get_daddr(ni_private *ni, ni_name dom, ni_private *target_ni) { - ni_id id; + ni_id nid; ni_idlist ids; - ni_namelist nl; ni_entrylist entries; + ni_proplist pl; ni_index i; ni_index j; ni_name tag; - if (ni_root(ni, &id) != NI_OK) { - return(0); + if (ni == NULL) return 0; + if (dom == NULL) return 0; + if (target_ni == NULL) return 0; + + if (!strcmp(dom, ".")) + { + /* check for server list */ + NI_INIT(&pl); + if (ni_statistics(ni, &pl) == NI_OK) + { + i = ni_proplist_match(pl, NAME_DOMAIN_SERVERS, NULL); + if (i != NI_INDEX_NULL) + { + if (pl.ni_proplist_val[i].nip_val.ni_namelist_len > 0) + { + for (j = 0; j < pl.ni_proplist_val[i].nip_val.ni_namelist_len; j++) + { + add_addr_tag(target_ni, pl.ni_proplist_val[i].nip_val.ni_namelist_val[j]); + } + + ni_proplist_free(&pl); + return 1; + } + } + + ni_proplist_free(&pl); + } } + if (ni_root(ni, &nid) != NI_OK) return 0; + NI_INIT(&ids); - if (ni_lookup(ni, &id, NAME_NAME, NAME_MACHINES, &ids) != NI_OK) { - return (0); - } + if (ni_lookup(ni, &nid, NAME_NAME, NAME_MACHINES, &ids) != NI_OK) return 0; - id.nii_object = ids.niil_val[0]; + nid.nii_object = ids.niil_val[0]; ni_idlist_free(&ids); NI_INIT(&entries); - if (ni_list(ni, &id, NAME_SERVES, &entries) != NI_OK) { - return (0); - } - - for (i = 0; i < entries.niel_len; i++) { - if (entries.niel_val[i].names != NULL) { - nl = *entries.niel_val[i].names; - for (j = 0; j < nl.ninl_len; j++) { - if (match(dom, nl.ninl_val[j], &tag)) { - if (addaddr(ni, - entries.niel_val[i].id, - tag, - target_ni)) { - ni_name_free(&tag); - break; - } - ni_name_free(&tag); - } + if (ni_list(ni, &nid, NAME_SERVES, &entries) != NI_OK) return 0; + + for (i = 0; i < entries.niel_len; i++) + { + if (entries.niel_val[i].names == NULL) continue; + + for (j = 0; j < entries.niel_val[i].names->ni_namelist_len; j++) + { + if (match(dom, entries.niel_val[i].names->ni_namelist_val[j], &tag)) + { + addaddr(ni, entries.niel_val[i].id, tag, target_ni); + ni_name_free(&tag); } } - } + ni_entrylist_free(&entries); return (target_ni->naddrs > 0); } - -#ifdef notdef -static int -get_haddr( - ni_private *ni, - ni_name hname, - ni_name tag, - ni_private *target_ni - ) -{ - ni_id id; - ni_idlist ids; - - if (ni_root(ni, &id) != NI_OK) { - return(0); - } - NI_INIT(&ids); - if (ni_lookup(ni, &id, NAME_NAME, NAME_MACHINES, &ids) != NI_OK) { - return (0); - } - id.nii_object = ids.niil_val[0]; - ni_idlist_free(&ids); - - NI_INIT(&ids); - if (ni_lookup(ni, &id, NAME_NAME, hname, &ids) != NI_OK) { - return (0); - } - id.nii_object = ids.niil_val[0]; - ni_idlist_free(&ids); - if (!addaddr(ni, id.nii_object, tag, target_ni)) { - return (0); - } - return (1); -} -#endif - - static ni_status getparent(ni_private *oldni, ni_private **newni) { ni_rparent_res *resp; - ni_private *ni; + ni_private *ni = NULL; ni_private *dupni; - int found; + int found = 0; ni_index i; struct in_addr raddr; int printed = 0; int inlist = 0; - found = 0; - while (!found) { + if (oldni == NULL) return 0; + if (newni == NULL) return 0; + + while (found == 0) + { /* * First, find our parent, any parent */ - for (;;) { + for (;;) + { resp = RCALLIT(oldni, _ni_rparent_2, NULL); - if (resp == NULL) { - return (NI_FAILED); - } - if (resp->status != NI_NORESPONSE) { - break; - } - if (!printed) { - syslog(LOG_ERR, "NetInfo timeout finding server for parent of %s/%s, sleeping", - inet_ntoa(oldni->addrs[0]), oldni->tags[0]); - printed++; + if (resp == NULL) return NI_FAILED; + if (resp->status != NI_NORESPONSE) break; + + if (printed != 0) + { + syslog(LOG_WARNING, "NetInfo timeout finding server for parent of %s/%s, sleeping", inet_ntoa(oldni->addrs[0]), oldni->tags[0]); + printed = 1; } + sleep(NI_SLEEPTIME); } - if (printed) { + + if (printed) + { raddr.s_addr = htonl(resp->ni_rparent_res_u.binding.addr); - - syslog(LOG_ERR, "NetInfo %s/%s found parent %s/%s", - inet_ntoa(oldni->addrs[0]), oldni->tags[0], - inet_ntoa(raddr), resp->ni_rparent_res_u.binding.tag); - } - if (resp->status != NI_OK) { - return (resp->status); + + syslog(LOG_INFO, "NetInfo %s/%s found parent %s/%s", inet_ntoa(oldni->addrs[0]), oldni->tags[0], inet_ntoa(raddr), resp->ni_rparent_res_u.binding.tag); } + + if (resp->status != NI_OK) return resp->status; + ni = ni_alloc(); *ni = *oldni; ni_clear(ni); @@ -1205,22 +1238,30 @@ 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; ni_clear(ni); - if (get_daddr(dupni, ".", ni)) { - + if (get_daddr(dupni, ".", ni) == 0) + { + if (oldni->abort == 1) + { + ni_free(dupni); + break; + } + } + else + { /* - * Now make sure returned parent is head of - * list + * Make sure returned parent is head of list */ - for (i = 0; i < ni->naddrs; i++) { - if (ni->addrs[i].s_addr == - dupni->addrs[0].s_addr) { + for (i = 0; i < ni->naddrs; i++) + { + if (ni->addrs[i].s_addr == dupni->addrs[0].s_addr) + { ni_switch(ni, i); inlist++; break; @@ -1236,75 +1277,72 @@ getparent(ni_private *oldni, ni_private **newni) dupni->tsock = -1; dupni->tport = -1; dupni->tc = NULL; - found++; + found = 1; /* * If returned parent wasn't in list, it's a rogue. * Log an error and drop the connection. */ - if (inlist == 0) { - syslog(LOG_ERR, "Rogue NetInfo server detected: %s/%s", - inet_ntoa(dupni->addrs[0]), dupni->tags[0]); + if (inlist == 0) + { + syslog(LOG_ERR, "Rogue NetInfo server detected: %s/%s", inet_ntoa(dupni->addrs[0]), dupni->tags[0]); reinit(ni); } } ni_free(dupni); } - if (found) { + + if (found) + { *newni = ni; - return (NI_OK); - } else { - ni_free(ni); - return (NI_FAILED); + return NI_OK; } + + if (ni != NULL) ni_free(ni); + return NI_FAILED; } 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; } void * -ni_new( - void *oldni, - const char *domain - ) +ni_new(void *oldni, const char *domain) { ni_private *ni; ni_status status; @@ -1312,101 +1350,102 @@ ni_new( struct sockaddr_in sin; struct hostent *he; - if (oldni == NULL) { + if (domain == NULL) return NULL; + + sep = index(domain, '@'); + if (sep != NULL) + { + tag = strncpy((char *)malloc(sep - domain + 1), domain, sep - domain); + tag[sep - domain] = '\0'; + + addr = NULL; + asprintf(&addr, "%s", sep + 1); + + sin.sin_addr.s_addr = inet_addr(addr); + if (sin.sin_addr.s_addr == INADDR_NONE) + { + he = gethostbyname(addr); + if (he == NULL) + { + free(addr); + free(tag); + return NULL; + } + + bcopy(he->h_addr_list[0], &sin.sin_addr.s_addr, he->h_length); + } + + ni = ni_connect(&sin, tag); + free(addr); + free(tag); + + return (void *)ni; + } + + ni = NULL; + + if (oldni == NULL) + { ni = ni_alloc(); - if (!connectlocal(ni)) { + if (connectlocal(ni) == 0) + { free(ni); - return (NULL); + return NULL; } - if (strcmp(domain, "..") == 0) { + + if (strcmp(domain, ".") == 0) return (void *)ni; + + if (strcmp(domain, "..") == 0) + { oldni = ni; status = getparent((ni_private *)oldni, &ni); ni_free(oldni); - if (status != NI_OK) { - return (NULL); - } - } else if ((sep = index(domain, '@')) != NULL) { - free(ni); - tag = strncpy((char *)malloc(sep-domain+1), domain, sep-domain); - tag[sep-domain] = '\0'; - addr = strcpy ((char *)malloc(strlen(sep+1)), sep+1); - sin.sin_addr.s_addr = inet_addr(addr); - if (sin.sin_addr.s_addr == INADDR_NONE) { - he = gethostbyname(addr); - if (he == NULL) { - free(addr); - free(tag); - return (NULL); - } - bcopy(he->h_addr_list[0], &sin.sin_addr.s_addr, he->h_length); - } - ni = ni_connect(&sin, tag); - free(addr); - free(tag); - } else if (strcmp(domain, ".") != 0) { - /* - * nothing else makes sense - */ - free(ni); - return (NULL); - } - } else { - if (strcmp(domain, "..") == 0) { - status = getparent((ni_private *)oldni, &ni); - if (status != NI_OK) { - return (NULL); - } - } else if ((sep = index(domain, '@')) != NULL) { - tag = strncpy((char *)malloc(sep-domain+1), domain, sep-domain); - tag[sep-domain] = '\0'; - addr = strcpy ((char *)malloc(strlen(sep+1)), sep+1); - sin.sin_addr.s_addr = inet_addr(addr); - if (sin.sin_addr.s_addr == INADDR_NONE) { - he = gethostbyname(addr); - if (he == NULL) { - free(addr); - free(tag); - return (NULL); - } - bcopy(he->h_addr_list[0], &sin.sin_addr.s_addr, he->h_length); - } - ni = ni_connect(&sin, tag); - free(addr); - free(tag); - } else { - ni = ni_alloc(); - *ni = *NIP(oldni); - ni_clear(ni); - if (!get_daddr(oldni, (ni_name)domain, ni)) { - ni_free(ni); - ni = NULL; - } + if (status != NI_OK) return NULL; + return (void *)ni; } + + ni_free(ni); + return NULL; + } + + if (strcmp(domain, "..") == 0) + { + status = getparent((ni_private *)oldni, &ni); + if (status != NI_OK) return NULL; + return (void *)ni; } - return ((void *)ni); + + ni = ni_alloc(); + *ni = *NIP(oldni); + ni_clear(ni); + if (get_daddr(oldni, (ni_name)domain, ni) == 0) + { + ni_free(ni); + return NULL; + } + + return (void *)ni; } void -ni_free( - void *ni - ) +ni_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); } @@ -1416,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); - } - 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_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); - } - 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_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); + 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_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); - } - 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_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); + 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_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. @@ -2090,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. @@ -2113,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; } @@ -2152,44 +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); + sock = socket(AF_INET, proto == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM, proto); + if (sock < 0) return -1; + + if ((bindresvport(sock, NULL) < 0) && (errno == EADDRNOTAVAIL)) + { + /* XXX - we're hitting this case way too often under load */ + /* fail gracefully: some address is better than none most of the time */ + syslog(LOG_DEBUG, "Libinfo[%s():%d] bindresvport(): %m", __func__, __LINE__); + if (bind(sock, (struct sockaddr *)&bindsin, sizeof(bindsin)) < 0) + { + /* The system is really sad now if it can't give me any address... */ + syslog(LOG_DEBUG, "Libinfo[%s():%d] bind(): %m", __func__, __LINE__); + close(sock); + return -1; + } } - (void)bindresvport(sock, (struct sockaddr_in *)0); + setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(int)); - if (proto == IPPROTO_TCP) { - if (connect(sock, (struct sockaddr *)raddr, - sizeof(*raddr)) < 0) { - (void)close(sock); - return (-1); + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)); + + if (proto == IPPROTO_TCP) + { + if (connect(sock, (struct sockaddr *)raddr, sizeof(*raddr)) < 0) + { + syslog(LOG_DEBUG, "Libinfo[%s():%d] connect(): %m", __func__, __LINE__); + close(sock); + return -1; } } - return (sock); + + return sock; }