2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
25 * Glues the library routines to the stub routines
26 * Copyright (C) 1989 by NeXT, Inc.
31 #include <netinfo/ni.h>
32 #include <rpc/pmap_clnt.h>
33 #include <rpc/pmap_prot.h>
39 #include "sys_interfaces.h"
41 #define LOCAL_PORT 1033
43 #define NI_TIMEOUT_SHORT 5 /* 5 second timeout for transactions */
44 #define NI_TIMEOUT_LONG 60 /* 60 second timeout for writes */
45 #define NI_TRIES 5 /* number of retries per timeout (udp only) */
46 #define NI_SLEEPTIME 4 /* 4 second sleeptime, in case of errors */
47 #define NI_MAXSLEEPTIME 16 /* 16 second max sleep time */
48 #define NI_MAXCONNTRIES 2 /* Try to form a connection twice before sleeping */
50 /* Hack for determining if an IP address is a broadcast address. -GRS */
51 /* Note that addr is network byte order (big endian) - BKM */
53 #define IS_BROADCASTADDR(addr) (((unsigned char *) &addr)[0] == 0xFF)
55 #ifndef INADDR_LOOPBACK
56 #define INADDR_LOOPBACK (u_long)0x7f000001
58 #define debug(msg) syslog(LOG_ERR, msg)
60 #define clnt_debug(ni, msg) /* do nothing */
62 typedef struct ni_private
64 int naddrs
; /* number of addresses */
65 struct in_addr
*addrs
; /* addresses of servers - network byte order */
66 int whichwrite
; /* which one of the above is the master */
67 ni_name
*tags
; /* tags of servers */
68 int pid
; /* pid, to detect forks */
69 int tsock
; /* tcp socket */
70 int tport
; /* tcp local port name - host byte order */
71 CLIENT
*tc
; /* tcp client */
72 long tv_sec
; /* timeout for this call */
73 long rtv_sec
; /* read timeout - 0 if default */
74 long wtv_sec
; /* write timeout - 0 if default */
75 int abort
; /* abort on timeout? */
76 int needwrite
; /* need to lock writes? */
77 int uid
; /* user id */
78 ni_name passwd
; /* password */
81 #define NIP(ni) ((ni_private *)(ni))
83 #define RCALLIT(a, b, c) callit((ni_private *)(a), (void *(*)())(b), (void *)c, 0)
84 #define WCALLIT(a, b, c) callit((ni_private *)(a), (void *(*)())(b), (void *)c, 1)
86 static const ni_name NAME_NAME
= "name";
87 static const ni_name NAME_SERVES
= "serves";
88 static const ni_name NAME_MACHINES
= "machines";
89 static const ni_name NAME_IP_ADDRESS
= "ip_address";
90 static const ni_name NAME_MASTER
= "master";
91 static const ni_name NAME_USERS
= "users";
92 static const ni_name NAME_UID
= "uid";
94 static const ni_name NAME_DOMAIN_SERVERS
= "domain_servers";
96 typedef struct getreg_stuff
{
97 nibind_getregister_res res
;
101 static int socket_open(struct sockaddr_in
*raddr
, int, int, int, int, int);
102 extern int bindresvport(int, struct sockaddr_in
*);
105 * Keep track of our port, in case somebody closes our socket on us.
110 struct sockaddr_in sin
;
113 sinlen
= sizeof(struct sockaddr_in
);
114 if (getsockname(sock
, (struct sockaddr
*)&sin
, &sinlen
) != 0) return -1;
116 if (sin
.sin_port
== 0)
118 if (bind(sock
, (struct sockaddr
*)&sin
, sizeof(struct sockaddr_in
)) != 0) return -1;
120 sinlen
= sizeof(struct sockaddr_in
);
121 if (getsockname(sock
, (struct sockaddr
*)&sin
, &sinlen
) != 0) return -1;
124 return ntohs(sin
.sin_port
);
129 createauth(ni_private
*ni
)
131 if (ni
->passwd
!= NULL
&& ni
->tc
!= NULL
)
133 auth_destroy(ni
->tc
->cl_auth
);
134 ni
->tc
->cl_auth
= authunix_create(ni
->passwd
, ni
->uid
, 0, 0, NULL
);
140 fixtimeout(struct timeval
*tv
, long sec
, int tries
)
142 tv
->tv_sec
= sec
/ tries
;
143 tv
->tv_usec
= ((sec
% tries
) * 1000000) / tries
;
148 ni_settimeout(ni_private
*ni
, int timeout
)
154 ni
->tv_sec
= timeout
;
155 if (ni
->tc
!= NULL
) clnt_control(ni
->tc
, CLSET_TIMEOUT
, (char *)&tv
);
160 * Connect to a given address/tag
163 connectit(ni_private
*ni
)
165 struct sockaddr_in sin
;
170 nibind_getregister_res res
;
171 interface_list_t
*ilist
;
174 bzero(&sin
, sizeof(sin
));
176 sin
.sin_family
= AF_INET
;
178 tv
.tv_sec
= ni
->rtv_sec
== 0 ? NI_TIMEOUT_SHORT
: ni
->rtv_sec
;
181 ni_settimeout(ni
, tv
.tv_sec
);
182 fixtimeout(&tv
, ni
->tv_sec
, NI_TRIES
);
185 * If connecting to local domain, try using the "well-known" port first.
189 if (!strcmp(ni
->tags
[0], "local"))
191 if (ni
->addrs
[0].s_addr
== htonl(INADDR_LOOPBACK
))
197 ilist
= _libinfo_ni_sys_interfaces();
198 if (_libinfo_ni_sys_is_my_address(ilist
, &ni
->addrs
[0])) islocal
= 1;
199 _libinfo_ni_sys_interfaces_release(ilist
);
204 sin
.sin_port
= htons(LOCAL_PORT
);
205 sin
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
206 sock
= socket_open(&sin
, NI_PROG
, NI_VERS
, ni
->tv_sec
, NI_TRIES
, IPPROTO_TCP
);
211 * 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.
216 sin
.sin_addr
= ni
->addrs
[0];
218 sock
= socket_open(&sin
, NIBIND_PROG
, NIBIND_VERS
, ni
->tv_sec
, NI_TRIES
, IPPROTO_UDP
);
219 if (sock
< 0) return 0;
221 cl
= clntudp_create(&sin
, NIBIND_PROG
, NIBIND_VERS
, tv
, &sock
);
228 tv
.tv_sec
= ni
->rtv_sec
== 0 ? NI_TIMEOUT_SHORT
: ni
->rtv_sec
;
231 stat
= clnt_call(cl
, NIBIND_GETREGISTER
, (xdrproc_t
)xdr_ni_name
, (char *)&ni
->tags
[0], (xdrproc_t
)xdr_nibind_getregister_res
, (char *)&res
, tv
);
234 if (stat
!= RPC_SUCCESS
|| res
.status
!= NI_OK
) return 0;
236 sin
.sin_port
= htons(res
.nibind_getregister_res_u
.addrs
.tcp_port
);
237 sock
= socket_open(&sin
, NI_PROG
, NI_VERS
, ni
->tv_sec
, NI_TRIES
, IPPROTO_TCP
);
240 if (sock
< 0) return 0;
242 cl
= clnttcp_create(&sin
, NI_PROG
, NI_VERS
, &sock
, 0, 0);
249 clnt_control(cl
, CLSET_TIMEOUT
, (char *)&tv
);
252 ni
->tport
= getmyport(sock
);
254 fcntl(ni
->tsock
, F_SETFD
, 1);
260 ni_setabort(void *ni
, int abort
)
262 if (ni
== NULL
) return;
264 ((ni_private
*)ni
)->abort
= abort
;
269 ni_setwritetimeout(void *ni
, int timeout
)
271 if (ni
== NULL
) return;
273 ((ni_private
*)ni
)->wtv_sec
= timeout
;
278 ni_setreadtimeout(void *ni
, int timeout
)
280 if (ni
== NULL
) return;
282 ((ni_private
*)ni
)->rtv_sec
= timeout
;
287 ni_needwrite(void *ni
, int needwrite
)
289 if (ni
== NULL
) return;
291 ((ni_private
*)ni
)->needwrite
= needwrite
;
296 * Returns a client handle to the NetInfo server, if it's running
299 connectlocal(ni_private
*ni
)
304 ni
->addrs
= (struct in_addr
*)malloc(sizeof(struct in_addr
));
305 ni
->addrs
[0].s_addr
= htonl(INADDR_LOOPBACK
);
306 ni
->tags
= (ni_name
*)malloc(sizeof(ni_name
));
307 ni
->tags
[0] = ni_name_dup("local");
310 while (connectit(ni
) == 0)
314 syslog(LOG_ERR
, "NetInfo timeout connecting to local domain, sleeping");
322 if (printed
!= 0) syslog(LOG_INFO
, "NetInfo connection to local domain waking");
329 * Destroy the client handle
332 clnt_kill(CLIENT
*cl
, int sock
, int port
)
339 if ((sock
>= 0) && (p
!= -1) && (p
!= port
))
341 /* Somebody has the reused the socket. */
347 if (cl
->cl_auth
!= NULL
) auth_destroy(cl
->cl_auth
);
351 if (save
== 0) close(sock
);
356 * Reinitialize everything
359 reinit(ni_private
*ni
)
361 if (ni
== NULL
) return;
365 clnt_kill(ni
->tc
, ni
->tsock
, ni
->tport
);
376 * Switch to a new server
379 ni_switch(ni_private
*ni
, ni_index which
)
381 struct in_addr tmp_addr
;
384 if (ni
== NULL
) return;
385 if (which
== 0) return;
388 tmp_addr
= ni
->addrs
[0];
389 tmp_tag
= ni
->tags
[0];
391 ni
->addrs
[0] = ni
->addrs
[which
];
392 ni
->tags
[0] = ni
->tags
[which
];
394 ni
->addrs
[which
] = tmp_addr
;
395 ni
->tags
[which
] = tmp_tag
;
397 if (ni
->whichwrite
== 0) ni
->whichwrite
= which
;
398 else if (ni
->whichwrite
== which
) ni
->whichwrite
= 0;
403 * Swap two servers' positions
406 ni_swap(ni_private
*ni
, ni_index a
, ni_index b
)
408 struct in_addr tmp_addr
;
413 tmp_addr
= ni
->addrs
[a
];
414 tmp_tag
= ni
->tags
[a
];
416 ni
->addrs
[a
] = ni
->addrs
[b
];
417 ni
->tags
[a
] = ni
->tags
[b
];
419 ni
->addrs
[b
] = tmp_addr
;
420 ni
->tags
[b
] = tmp_tag
;
422 if (ni
->whichwrite
== a
) ni
->whichwrite
= b
;
423 else if (ni
->whichwrite
== b
) ni
->whichwrite
= a
;
427 ni_ping(unsigned short port
, struct in_addr addr
)
429 struct sockaddr_in sin
;
432 struct timeval timeout
, retry
;
435 memset(&sin
, 0, sizeof(struct sockaddr_in
));
437 sin
.sin_family
= AF_INET
;
441 timeout
.tv_sec
= NI_TIMEOUT_SHORT
;
447 sock
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
448 if (sock
< 0) return NI_FAILED
;
450 cl
= clntudp_create(&sin
, NI_PROG
, NI_VERS
, timeout
, &sock
);
457 clnt_control(cl
, CLSET_RETRY_TIMEOUT
, (char *)&retry
);
459 stat
= clnt_call(cl
, _NI_PING
, (xdrproc_t
)xdr_void
, (char *)NULL
, (xdrproc_t
)xdr_void
, (char *)NULL
, timeout
);
463 if (stat
!= RPC_SUCCESS
) return NI_FAILED
;
469 * Callback routine for multi_call
470 * XXX: should save returned port numbers
473 eachresult(void *vstuff
, struct sockaddr_in
*sin
, int which
)
476 getreg_stuff
*stuff
= (getreg_stuff
*)vstuff
;
478 if (stuff
->res
.status
!= NI_OK
) return FALSE
;
481 * Actually talk to server (netinfod) to make sure it is alive
482 * before switching. If we got this far, nibindd gave us a
483 * port number for an address and tag. We connect to that
484 * port and do a ni_root() query before accepting the server.
486 status
= ni_ping(htons(stuff
->res
.nibind_getregister_res_u
.addrs
.udp_port
), stuff
->ni
->addrs
[which
]);
487 if (status
!= NI_OK
) return FALSE
;
489 ni_switch(stuff
->ni
, which
);
498 shuffle(ni_private
*ni
)
501 int i
, j
, rfd
, rv
, te
;
503 static int initialized
= 0;
505 if (ni
== NULL
) return;
506 if (ni
->naddrs
<= 1) return;
508 rfd
= open("/dev/random", O_RDONLY
, 0);
509 shuffle
= (int *)malloc(ni
->naddrs
* sizeof(int));
510 for (i
= 0; i
< ni
->naddrs
; i
++) shuffle
[i
] = i
;
511 for (i
= 0, j
= ni
->naddrs
; j
> 0; i
++, j
--)
513 /* get a random number */
514 if ((rfd
< 0) || (read(rfd
, &rv
, sizeof(rv
)) != sizeof(rv
)))
516 /* if we could not read from /dev/random */
517 if (initialized
== 0)
519 srandom(gethostid() ^ time(NULL
));
525 re
= (unsigned int)rv
% j
; /* pick one of the remaining entries */
526 te
= shuffle
[re
]; /* grab the random entry */
527 shuffle
[re
] = shuffle
[j
-1]; /* the last entry moves to the random slot */
528 shuffle
[j
-1] = te
; /* the last slot gets the random entry */
529 ni_swap(ni
, re
, j
-1); /* and swap the actual NI addresses */
533 if (rfd
> 0) close(rfd
);
539 rebind(ni_private
*ni
)
543 int sleeptime
= NI_SLEEPTIME
;
547 interface_list_t
*ilist
;
558 * re-order the servers so that:
559 * servers on the local host are at the start of the list, then
560 * servers on the local network are next, then
561 * all other servers are next
564 ilist
= _libinfo_ni_sys_interfaces();
572 * move local servers to the head of the list
575 for (i
= nlocal
; i
< ni
->naddrs
; i
++)
577 if (_libinfo_ni_sys_is_my_address(ilist
, &ni
->addrs
[i
]))
579 ni_swap(ni
, nlocal
, i
);
585 * move servers on this network to follow local servers
588 for (i
= nnetwork
; i
< ni
->naddrs
; i
++)
590 if (_libinfo_ni_sys_is_my_network(ilist
, &ni
->addrs
[i
]) || IS_BROADCASTADDR(ni
->addrs
[i
].s_addr
))
592 ni_swap(ni
, nnetwork
, i
);
597 _libinfo_ni_sys_interfaces_release(ilist
);
603 * call local servers first
607 for (i
= 0; i
< nlocal
; i
++)
609 syslog(LOG_DEBUG
, "NetInfo connect call to: %s/%s (local %d)", inet_ntoa(ni
->addrs
[i
]), ni
->tags
[i
], i
);
612 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
);
613 if (stat
== RPC_SUCCESS
) break;
617 * call local servers and this network's servers
619 if (nnetwork
> nlocal
)
621 for (i
= 0; i
< nnetwork
; i
++)
623 syslog(LOG_DEBUG
, "NetInfo connect call to: %s/%s (network %d)", inet_ntoa(ni
->addrs
[i
]), ni
->tags
[i
], i
);
626 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
);
627 if (stat
== RPC_SUCCESS
) break;
633 for (i
= 0; i
< ni
->naddrs
; i
++)
635 syslog(LOG_DEBUG
, "NetInfo connect call to: %s/%s (world %d)", inet_ntoa(ni
->addrs
[i
]), ni
->tags
[i
], i
);
637 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
);
638 if (stat
== RPC_SUCCESS
) break;
640 if (ni
->abort
) return 0;
644 if (ni
->whichwrite
>= 0)
647 "NetInfo connect timeout (domain with master %s/%s), sleeping", inet_ntoa(ni
->addrs
[ni
->whichwrite
]), ni
->tags
[ni
->whichwrite
]);
651 syslog(LOG_WARNING
, "NetInfo connect timeout (domain with server %s/%s), sleeping", inet_ntoa(ni
->addrs
[0]), ni
->tags
[0]);
658 if (sleeptime
< NI_MAXSLEEPTIME
)
665 syslog(LOG_INFO
, "NetInfo connected to %s/%s", inet_ntoa(ni
->addrs
[0]), ni
->tags
[0]);
672 * Confirm that our tcp socket is still valid
675 confirm_tcp(ni_private
*ni
, int needwrite
)
681 p
= getmyport(ni
->tsock
);
682 if ((p
!= -1) && (p
== ni
->tport
))
690 /* Socket has died. Close it so it doesn't become a zombie. */
695 * Somebody has reused our socket.
699 if (ni
->tc
->cl_auth
!= NULL
) auth_destroy(ni
->tc
->cl_auth
);
700 clnt_destroy(ni
->tc
);
705 if ((needwrite
== 0) && (rebind(ni
) == 0) && (ni
->abort
!= 0)) return 0;
707 return connectit(ni
);
712 setmaster(ni_private
*ni
)
727 /* One server - must be the master */
732 needwrite
= ni
->needwrite
;
734 if (ni_root(ni
, &root
) != NI_OK
)
736 ni
->needwrite
= needwrite
;
741 if (ni_lookupprop(ni
, &root
, NAME_MASTER
, &nl
) != NI_OK
)
743 ni
->needwrite
= needwrite
;
747 if (nl
.ninl_len
== 0)
749 ni
->needwrite
= needwrite
;
753 sep
= index(nl
.ninl_val
[0], '/');
756 ni
->needwrite
= needwrite
;
761 master
= nl
.ninl_val
[0];
764 if (ni_lookup(ni
, &root
, NAME_NAME
, NAME_MACHINES
, &idl
) != NI_OK
)
766 ni
->needwrite
= needwrite
;
767 ni_namelist_free(&nl
);
771 if (idl
.niil_len
< 1)
773 ni
->needwrite
= needwrite
;
777 id
.nii_object
= idl
.niil_val
[0];
778 ni_idlist_free(&idl
);
781 if (ni_lookup(ni
, &id
, NAME_NAME
, master
, &idl
) != NI_OK
)
783 ni_namelist_free(&nl
);
784 ni
->needwrite
= needwrite
;
788 ni_namelist_free(&nl
);
789 if (idl
.niil_len
< 1)
791 ni
->needwrite
= needwrite
;
795 id
.nii_object
= idl
.niil_val
[0];
796 ni_idlist_free(&idl
);
798 if (ni_lookupprop(ni
, &id
, NAME_IP_ADDRESS
, &nl
) != NI_OK
) return 0;
800 for (i
= 0; i
< nl
.ninl_len
; i
++)
802 addr
.s_addr
= inet_addr(nl
.ninl_val
[i
]);
803 for (j
= 0; j
< ni
->naddrs
; j
++)
805 if (addr
.s_addr
== ni
->addrs
[j
].s_addr
)
808 ni_namelist_free(&nl
);
809 ni
->needwrite
= needwrite
;
815 ni
->needwrite
= needwrite
;
816 ni_namelist_free(&nl
);
822 callit(ni_private
*ni
, void *(*stub
)(), void *args
, int needwrite
)
830 if (getpid() != ni
->pid
) reinit(ni
);
832 if (needwrite
|| ni
->needwrite
)
834 if (ni
->whichwrite
>= 0)
836 ni_switch(ni
, ni
->whichwrite
);
840 if (setmaster(ni
) == 0) return NULL
;
841 ni_switch(ni
, ni
->whichwrite
);
846 ni_settimeout(ni
, (ni
->rtv_sec
== 0 ? NI_TIMEOUT_SHORT
: ni
->rtv_sec
));
851 ni_settimeout(ni
, (ni
->wtv_sec
== 0 ? NI_TIMEOUT_LONG
: ni
->wtv_sec
));
856 ni_settimeout(ni
, (ni
->rtv_sec
== 0 ? NI_TIMEOUT_SHORT
: ni
->rtv_sec
));
862 * Try more than once, in case server closed connection.
864 for (i
= 0; i
< NI_MAXCONNTRIES
; i
++)
866 if (!confirm_tcp(ni
, needwrite
)) break;
868 if ((resp
= (*stub
)(args
, ni
->tc
)) != NULL
)
870 if (printed
!= 0) syslog(LOG_INFO
, "NetInfo connected to %s/%s", inet_ntoa(ni
->addrs
[0]), ni
->tags
[0]);
876 clnt_geterr(ni
->tc
, &err
);
877 if (err
.re_status
!= RPC_CANTRECV
) break;
880 if ((i
+ 1) < NI_MAXCONNTRIES
)
882 /* Server closed connection. Reinit and try again. */
887 if (err
.re_status
== RPC_PROCUNAVAIL
) return NULL
;
889 if (needwrite
|| ni
->abort
)
892 * We time out for writes or if it is explicitly
895 if (ni
->abort
) reinit(ni
);
897 syslog(LOG_ERR
, "NetInfo connection failed for server %s/%s", inet_ntoa(ni
->addrs
[0]), ni
->tags
[0]);
905 if ((sleeptime
!= 0) || (err
.re_status
!= RPC_TIMEDOUT
))
908 * Do not print message on
909 * first timeout. It is likely
910 * we will find another server soon.
911 * Let's not needlessly alarm the
914 syslog(LOG_ERR
, "%s on connection to %s/%s", clnt_sperror(ni
->tc
,"NetInfo connection timeout"), inet_ntoa(ni
->addrs
[0]), ni
->tags
[0]);
919 /* first attempt failed */
920 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]);
925 syslog(LOG_ERR
, "NetInfo connection failed for server %s/%s", inet_ntoa(ni
->addrs
[0]), ni
->tags
[0]);
934 if (sleeptime
< NI_MAXSLEEPTIME
) sleeptime
*= 2;
939 * Do not sleep on the first timeout.
940 * It is likely we will find another server quickly.
942 sleeptime
= NI_SLEEPTIME
;
952 ni_clear(ni_private
*ni
)
971 ni
= (ni_private
*)malloc(sizeof(*ni
));
978 ni
->tv_sec
= NI_TIMEOUT_SHORT
;
995 if (ni
== NULL
) return NULL
;
997 dupni
= (ni_private
*)ni_alloc();
1000 dupni
->naddrs
= NIP(ni
)->naddrs
;
1001 dupni
->whichwrite
= NIP(ni
)->whichwrite
;
1002 if (dupni
->naddrs
> 0)
1004 dupni
->addrs
= ((struct in_addr
*) malloc(NIP(ni
)->naddrs
* sizeof(struct in_addr
)));
1005 bcopy(NIP(ni
)->addrs
, dupni
->addrs
, NIP(ni
)->naddrs
* sizeof(struct in_addr
));
1006 dupni
->tags
= ((ni_name
*) malloc(NIP(ni
)->naddrs
* sizeof(ni_name
)));
1007 for (i
= 0; i
< NIP(ni
)->naddrs
; i
++)
1009 dupni
->tags
[i
] = ni_name_dup(NIP(ni
)->tags
[i
]);
1013 if (NIP(ni
)->passwd
!= NULL
) dupni
->passwd
= ni_name_dup(NIP(ni
)->passwd
);
1014 return (void *)dupni
;
1019 match(ni_name domain
, ni_name domtag
, ni_name
*tag
)
1021 int len
= strlen(domain
);
1024 sep
= index(domtag
, '/');
1025 if (sep
== NULL
) return 0;
1027 if ((strncmp(domain
, domtag
, len
) == 0) && (domtag
[len
] == '/'))
1029 *tag
= ni_name_dup(sep
+ 1);
1038 add_addr_tag(ni_private
*ni
, ni_name addrtag
)
1040 struct in_addr addr
;
1044 slash
= strchr(addrtag
, '/');
1045 if (slash
== NULL
) return;
1048 if (tag
[0] == '\0') return;
1052 if (inet_aton(addrtag
, &addr
) == 0) return;
1054 if (ni
->naddrs
== 0)
1056 ni
->addrs
= (struct in_addr
*)calloc(1, sizeof(struct in_addr
));
1057 if (ni
->addrs
== NULL
) return;
1059 ni
->tags
= (ni_name
*)calloc(1, sizeof(ni_name
));
1060 if (ni
->tags
== NULL
) return;
1064 ni
->addrs
= (struct in_addr
*)realloc(ni
->addrs
, ((ni
->naddrs
+ 1) * sizeof(struct in_addr
)));
1065 if (ni
->addrs
== NULL
) return;
1067 ni
->tags
= (ni_name
*)realloc(ni
->tags
, ((ni
->naddrs
+ 1) * sizeof(ni_name
)));
1068 if (ni
->tags
== NULL
) return;
1071 ni
->addrs
[ni
->naddrs
] = addr
;
1072 ni
->tags
[ni
->naddrs
] = ni_name_dup(tag
);
1077 addaddr(void *ni
, ni_index ido
, ni_name tag
, ni_private
*target_ni
)
1081 struct in_addr addr
;
1085 if (ni
== NULL
) return 0;
1086 if (tag
== NULL
) return 0;
1087 if (target_ni
== NULL
) return 0;
1089 id
.nii_object
= ido
;
1092 status
= ni_lookupprop(ni
, &id
, NAME_IP_ADDRESS
, &nl
);
1093 if (status
!= NI_OK
) return 0;
1095 if (nl
.ni_namelist_len
== 0) return 0;
1097 if (target_ni
->naddrs
== 0)
1099 target_ni
->addrs
= (struct in_addr
*)malloc(nl
.ni_namelist_len
* sizeof(struct in_addr
));
1100 target_ni
->tags
= (ni_name
*)malloc(nl
.ni_namelist_len
* sizeof(ni_name
));
1104 target_ni
->addrs
= (struct in_addr
*)realloc(target_ni
->addrs
, ((target_ni
->naddrs
+ nl
.ni_namelist_len
) * sizeof(struct in_addr
)));
1105 target_ni
->tags
= (ni_name
*)realloc(target_ni
->tags
, ((target_ni
->naddrs
+ nl
.ni_namelist_len
) * sizeof(ni_name
)));
1108 for (i
= 0; i
< nl
.ni_namelist_len
; i
++)
1110 addr
.s_addr
= inet_addr(nl
.ni_namelist_val
[i
]);
1111 target_ni
->addrs
[target_ni
->naddrs
] = addr
;
1112 target_ni
->tags
[target_ni
->naddrs
] = ni_name_dup(tag
);
1113 target_ni
->naddrs
++;
1116 ni_namelist_free(&nl
);
1121 get_daddr(ni_private
*ni
, ni_name dom
, ni_private
*target_ni
)
1125 ni_entrylist entries
;
1131 if (ni
== NULL
) return 0;
1132 if (dom
== NULL
) return 0;
1133 if (target_ni
== NULL
) return 0;
1135 if (!strcmp(dom
, "."))
1137 /* check for server list */
1139 if (ni_statistics(ni
, &pl
) == NI_OK
)
1141 i
= ni_proplist_match(pl
, NAME_DOMAIN_SERVERS
, NULL
);
1142 if (i
!= NI_INDEX_NULL
)
1144 if (pl
.ni_proplist_val
[i
].nip_val
.ni_namelist_len
> 0)
1146 for (j
= 0; j
< pl
.ni_proplist_val
[i
].nip_val
.ni_namelist_len
; j
++)
1148 add_addr_tag(target_ni
, pl
.ni_proplist_val
[i
].nip_val
.ni_namelist_val
[j
]);
1151 ni_proplist_free(&pl
);
1156 ni_proplist_free(&pl
);
1160 if (ni_root(ni
, &nid
) != NI_OK
) return 0;
1163 if (ni_lookup(ni
, &nid
, NAME_NAME
, NAME_MACHINES
, &ids
) != NI_OK
) return 0;
1165 nid
.nii_object
= ids
.niil_val
[0];
1166 ni_idlist_free(&ids
);
1169 if (ni_list(ni
, &nid
, NAME_SERVES
, &entries
) != NI_OK
) return 0;
1171 for (i
= 0; i
< entries
.niel_len
; i
++)
1173 if (entries
.niel_val
[i
].names
== NULL
) continue;
1175 for (j
= 0; j
< entries
.niel_val
[i
].names
->ni_namelist_len
; j
++)
1177 if (match(dom
, entries
.niel_val
[i
].names
->ni_namelist_val
[j
], &tag
))
1179 addaddr(ni
, entries
.niel_val
[i
].id
, tag
, target_ni
);
1185 ni_entrylist_free(&entries
);
1186 return (target_ni
->naddrs
> 0);
1190 getparent(ni_private
*oldni
, ni_private
**newni
)
1192 ni_rparent_res
*resp
;
1193 ni_private
*ni
= NULL
;
1197 struct in_addr raddr
;
1201 if (oldni
== NULL
) return 0;
1202 if (newni
== NULL
) return 0;
1207 * First, find our parent, any parent
1211 resp
= RCALLIT(oldni
, _ni_rparent_2
, NULL
);
1212 if (resp
== NULL
) return NI_FAILED
;
1213 if (resp
->status
!= NI_NORESPONSE
) break;
1217 syslog(LOG_WARNING
, "NetInfo timeout finding server for parent of %s/%s, sleeping", inet_ntoa(oldni
->addrs
[0]), oldni
->tags
[0]);
1221 sleep(NI_SLEEPTIME
);
1226 raddr
.s_addr
= htonl(resp
->ni_rparent_res_u
.binding
.addr
);
1228 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
);
1231 if (resp
->status
!= NI_OK
) return resp
->status
;
1237 ni
->addrs
= (struct in_addr
*)malloc(sizeof(struct in_addr
));
1238 ni
->addrs
[0].s_addr
=htonl(resp
->ni_rparent_res_u
.binding
.addr
);
1239 ni
->tags
= (ni_name
*)malloc(sizeof(ni_name
));
1240 ni
->tags
[0] = ni_name_dup(resp
->ni_rparent_res_u
.binding
.tag
);
1242 xdr_free((xdrproc_t
)xdr_ni_rparent_res
, (void *)resp
);
1248 if (get_daddr(dupni
, ".", ni
) == 0)
1250 if (oldni
->abort
== 1)
1259 * Make sure returned parent is head of list
1261 for (i
= 0; i
< ni
->naddrs
; i
++)
1263 if (ni
->addrs
[i
].s_addr
== dupni
->addrs
[0].s_addr
)
1272 * Reuse dupni client info
1274 ni
->tsock
= dupni
->tsock
;
1275 ni
->tport
= dupni
->tport
;
1283 * If returned parent wasn't in list, it's a rogue.
1284 * Log an error and drop the connection.
1288 syslog(LOG_ERR
, "Rogue NetInfo server detected: %s/%s", inet_ntoa(dupni
->addrs
[0]), dupni
->tags
[0]);
1302 if (ni
!= NULL
) ni_free(ni
);
1308 ni_connect(struct sockaddr_in
*sin
, const char *tag
)
1312 if (sin
== NULL
) return NULL
;
1313 if (tag
== NULL
) return NULL
;
1316 NIP(ni
)->naddrs
= 1;
1317 NIP(ni
)->addrs
= (struct in_addr
*)malloc(sizeof(struct in_addr
));
1318 NIP(ni
)->addrs
[0] = sin
->sin_addr
;
1319 NIP(ni
)->tags
= (ni_name
*)malloc(sizeof(ni_name
));
1320 NIP(ni
)->tags
[0] = ni_name_dup(tag
);
1326 ni_addrtag(void *ni
, struct sockaddr_in
*addr
, ni_name
*tag
)
1328 if (ni
== NULL
) return NI_FAILED
;
1329 if (addr
== NULL
) return NI_FAILED
;
1330 if (tag
== NULL
) return NI_FAILED
;
1332 if (!confirm_tcp(ni
, 0)) return NI_FAILED
;
1334 *tag
= ni_name_dup(NIP(ni
)->tags
[0]);
1335 addr
->sin_addr
= NIP(ni
)->addrs
[0];
1336 addr
->sin_port
= htons(NIP(ni
)->tport
);
1337 addr
->sin_family
= AF_INET
;
1338 bzero(addr
->sin_zero
, sizeof(addr
->sin_zero
));
1345 ni_new(void *oldni
, const char *domain
)
1349 ni_name sep
, addr
, tag
;
1350 struct sockaddr_in sin
;
1353 if (domain
== NULL
) return NULL
;
1355 sep
= index(domain
, '@');
1358 tag
= strncpy((char *)malloc(sep
- domain
+ 1), domain
, sep
- domain
);
1359 tag
[sep
- domain
] = '\0';
1362 asprintf(&addr
, "%s", sep
+ 1);
1364 sin
.sin_addr
.s_addr
= inet_addr(addr
);
1365 if (sin
.sin_addr
.s_addr
== INADDR_NONE
)
1367 he
= gethostbyname(addr
);
1375 bcopy(he
->h_addr_list
[0], &sin
.sin_addr
.s_addr
, he
->h_length
);
1378 ni
= ni_connect(&sin
, tag
);
1390 if (connectlocal(ni
) == 0)
1396 if (strcmp(domain
, ".") == 0) return (void *)ni
;
1398 if (strcmp(domain
, "..") == 0)
1401 status
= getparent((ni_private
*)oldni
, &ni
);
1403 if (status
!= NI_OK
) return NULL
;
1411 if (strcmp(domain
, "..") == 0)
1413 status
= getparent((ni_private
*)oldni
, &ni
);
1414 if (status
!= NI_OK
) return NULL
;
1421 if (get_daddr(oldni
, (ni_name
)domain
, ni
) == 0)
1436 if (ni
== NULL
) return;
1438 if (NIP(ni
)->tc
!= NULL
) clnt_kill(NIP(ni
)->tc
, NIP(ni
)->tsock
, NIP(ni
)->tport
);
1440 if (NIP(ni
)->naddrs
> 0)
1442 for (i
= 0; i
< NIP(ni
)->naddrs
; i
++) ni_name_free(&NIP(ni
)->tags
[i
]);
1443 free(NIP(ni
)->tags
);
1444 free(NIP(ni
)->addrs
);
1447 if (NIP(ni
)->passwd
!= NULL
) ni_name_free(&NIP(ni
)->passwd
);
1454 * The rest of these are just wrappers that end up doing
1455 * RPC calls to the local NetInfo server.
1458 ni_statistics(void *ni
, ni_proplist
*pl
)
1462 if (ni
== NULL
) return NI_FAILED
;
1463 if (pl
== NULL
) return NI_FAILED
;
1465 resp
= (ni_proplist
*)RCALLIT(ni
, _ni_statistics_2
, NULL
);
1468 clnt_debug(ni
, "_ni_statistics");
1478 ni_root(void *ni
, ni_id
*id
)
1482 if (ni
== NULL
) return NI_FAILED
;
1483 if (id
== NULL
) return NI_FAILED
;
1485 resp
= RCALLIT(ni
, _ni_root_2
, id
);
1488 clnt_debug(ni
, "_ni_root");
1492 if (resp
->status
== NI_OK
) *id
= resp
->ni_id_res_u
.id
;
1494 return resp
->status
;
1499 ni_self(void *ni
, ni_id
*id
)
1503 if (ni
== NULL
) return NI_FAILED
;
1504 if (id
== NULL
) return NI_FAILED
;
1506 resp
= RCALLIT(ni
, _ni_self_2
, id
);
1509 clnt_debug(ni
, "_ni_self");
1513 if (resp
->status
== NI_OK
) *id
= resp
->ni_id_res_u
.id
;
1515 return resp
->status
;
1520 ni_parent(void *ni
, ni_id
*id
, ni_index
*parent_id_p
)
1522 ni_parent_res
*resp
;
1524 if (ni
== NULL
) return NI_FAILED
;
1525 if (id
== NULL
) return NI_FAILED
;
1526 if (parent_id_p
== NULL
) return NI_FAILED
;
1528 resp
= RCALLIT(ni
, _ni_parent_2
, id
);
1531 clnt_debug(ni
, "_ni_parent");
1535 if (resp
->status
== NI_OK
)
1537 *parent_id_p
= resp
->ni_parent_res_u
.stuff
.object_id
;
1538 *id
= resp
->ni_parent_res_u
.stuff
.self_id
;
1541 return resp
->status
;
1546 ni_children(void *ni
, ni_id
*id
, ni_idlist
*children
)
1548 ni_children_res
*resp
;
1550 if (ni
== NULL
) return NI_FAILED
;
1551 if (id
== NULL
) return NI_FAILED
;
1552 if (children
== NULL
) return NI_FAILED
;
1554 resp
= RCALLIT(ni
, _ni_children_2
, id
);
1557 clnt_debug(ni
, "_ni_children");
1561 if (resp
->status
== NI_OK
)
1563 *children
= resp
->ni_children_res_u
.stuff
.children
;
1564 *id
= resp
->ni_children_res_u
.stuff
.self_id
;
1567 return resp
->status
;
1572 ni_create(void *ni
, ni_id
*parent_id
, ni_proplist pl
, ni_id
*child_id_p
, ni_index where
)
1574 ni_create_args args
;
1575 ni_create_res
*resp
;
1577 if (ni
== NULL
) return NI_FAILED
;
1578 if (parent_id
== NULL
) return NI_FAILED
;
1579 if (child_id_p
== NULL
) return NI_FAILED
;
1581 args
.id
= *parent_id
;
1584 args
.target_id
= NULL
;
1586 resp
= WCALLIT(ni
, _ni_create_2
, &args
);
1589 clnt_debug(ni
, "_ni_create");
1593 if (resp
->status
== NI_OK
)
1595 *child_id_p
= resp
->ni_create_res_u
.stuff
.id
;
1596 *parent_id
= resp
->ni_create_res_u
.stuff
.self_id
;
1599 return resp
->status
;
1604 ni_destroy(void *ni
, ni_id
*parent_id
, ni_id self_id
)
1607 ni_destroy_args args
;
1609 if (ni
== NULL
) return NI_FAILED
;
1610 if (parent_id
== NULL
) return NI_FAILED
;
1612 args
.parent_id
= *parent_id
;
1613 args
.self_id
= self_id
;
1615 resp
= WCALLIT(ni
, _ni_destroy_2
, &args
);
1618 clnt_debug(ni
, "_ni_destroy");
1622 if (resp
->status
== NI_OK
) *parent_id
= resp
->ni_id_res_u
.id
;
1624 return resp
->status
;
1629 ni_write(void *ni
, ni_id
*self_id
, ni_proplist pl
)
1631 ni_proplist_stuff args
;
1634 if (ni
== NULL
) return NI_FAILED
;
1635 if (self_id
== NULL
) return NI_FAILED
;
1640 resp
= WCALLIT(ni
, _ni_write_2
, &args
);
1643 clnt_debug(ni
, "_ni_write");
1647 if (resp
->status
== NI_OK
) *self_id
= resp
->ni_id_res_u
.id
;
1649 return resp
->status
;
1654 ni_read(void *ni
, ni_id
*self_id
, ni_proplist
*pl
)
1656 ni_proplist_res
*resp
;
1658 if (ni
== NULL
) return NI_FAILED
;
1659 if (self_id
== NULL
) return NI_FAILED
;
1660 if (pl
== NULL
) return NI_FAILED
;
1662 resp
= RCALLIT(ni
, _ni_read_2
, self_id
);
1665 clnt_debug(ni
, "_ni_read");
1669 if (resp
->status
== NI_OK
)
1671 *self_id
= resp
->ni_proplist_res_u
.stuff
.id
;
1672 *pl
= resp
->ni_proplist_res_u
.stuff
.props
;
1675 return resp
->status
;
1680 ni_lookup(void *ni
, ni_id
*id
, ni_name_const pname
, ni_name_const pval
, ni_idlist
*hits
)
1682 ni_lookup_res
*resp
;
1683 ni_lookup_args args
;
1685 if (ni
== NULL
) return NI_FAILED
;
1686 if (id
== NULL
) return NI_FAILED
;
1687 if (pname
== NULL
) return NI_FAILED
;
1688 /* pval may be NULL */
1689 if (hits
== NULL
) return NI_FAILED
;
1692 args
.key
= (ni_name
)pname
;
1693 args
.value
= (ni_name
)pval
;
1695 resp
= RCALLIT(ni
, _ni_lookup_2
, &args
);
1698 clnt_debug(ni
, "_ni_lookup");
1702 if (resp
->status
== NI_OK
)
1704 *hits
= resp
->ni_lookup_res_u
.stuff
.idlist
;
1705 *id
= resp
->ni_lookup_res_u
.stuff
.self_id
;
1708 return resp
->status
;
1713 ni_lookupread(void *ni
, ni_id
*id
, ni_name_const pname
, ni_name_const pval
, ni_proplist
*props
)
1715 ni_proplist_res
*resp
;
1716 ni_lookup_args args
;
1718 if (ni
== NULL
) return NI_FAILED
;
1719 if (id
== NULL
) return NI_FAILED
;
1720 if (pname
== NULL
) return NI_FAILED
;
1721 /* pval may be NULL*/
1722 if (props
== NULL
) return NI_FAILED
;
1725 args
.key
= (ni_name
)pname
;
1726 args
.value
= (ni_name
)pval
;
1728 resp
= RCALLIT(ni
, _ni_lookupread_2
, &args
);
1731 clnt_debug(ni
, "_ni_lookupread");
1735 if (resp
->status
== NI_OK
)
1737 *props
= resp
->ni_proplist_res_u
.stuff
.props
;
1738 *id
= resp
->ni_proplist_res_u
.stuff
.id
;
1741 return resp
->status
;
1746 ni_list(void *ni
, ni_id
*id
, ni_name_const pname
, ni_entrylist
*entries
)
1751 if (ni
== NULL
) return NI_FAILED
;
1752 if (id
== NULL
) return NI_FAILED
;
1753 if (pname
== NULL
) return NI_FAILED
;
1754 if (entries
== NULL
) return NI_FAILED
;
1757 args
.name
= (ni_name
)pname
;
1759 resp
= RCALLIT(ni
, _ni_list_2
, &args
);
1762 clnt_debug(ni
, "_ni_list");
1766 if (resp
->status
== NI_OK
)
1768 *entries
= resp
->ni_list_res_u
.stuff
.entries
;
1769 *id
= resp
->ni_list_res_u
.stuff
.self_id
;
1772 return resp
->status
;
1777 ni_listall(void *ni
, ni_id
*id
, ni_proplist_list
*entries
)
1779 ni_listall_res
*resp
;
1781 if (ni
== NULL
) return NI_FAILED
;
1782 if (id
== NULL
) return NI_FAILED
;
1783 if (entries
== NULL
) return NI_FAILED
;
1785 resp
= RCALLIT(ni
, _ni_listall_2
, id
);
1788 clnt_debug(ni
, "_ni_listall");
1792 if (resp
->status
== NI_OK
)
1794 *entries
= resp
->ni_listall_res_u
.stuff
.entries
;
1795 *id
= resp
->ni_listall_res_u
.stuff
.self_id
;
1798 return resp
->status
;
1803 ni_readprop(void *ni
, ni_id
*id
, ni_index which
, ni_namelist
*propval_p
)
1805 ni_namelist_res
*resp
;
1808 if (ni
== NULL
) return NI_FAILED
;
1809 if (id
== NULL
) return NI_FAILED
;
1810 if (propval_p
== NULL
) return NI_FAILED
;
1813 args
.prop_index
= which
;
1815 resp
= RCALLIT(ni
, _ni_readprop_2
, &args
);
1818 clnt_debug(ni
, "_ni_readprop");
1822 if (resp
->status
== NI_OK
)
1824 *propval_p
= resp
->ni_namelist_res_u
.stuff
.values
;
1825 *id
= resp
->ni_namelist_res_u
.stuff
.self_id
;
1828 return resp
->status
;
1833 ni_writeprop(void *ni
, ni_id
*id
, ni_index which
, ni_namelist propval
)
1836 ni_writeprop_args args
;
1838 if (ni
== NULL
) return NI_FAILED
;
1839 if (id
== NULL
) return NI_FAILED
;
1842 args
.prop_index
= which
;
1843 args
.values
= propval
;
1845 resp
= WCALLIT(ni
, _ni_writeprop_2
, &args
);
1848 clnt_debug(ni
, "_ni_writeprop");
1852 if (resp
->status
== NI_OK
) *id
= resp
->ni_id_res_u
.id
;
1854 return resp
->status
;
1859 ni_listprops(void *ni
, ni_id
*id
, ni_namelist
*propnames
)
1861 ni_namelist_res
*resp
;
1863 if (ni
== NULL
) return NI_FAILED
;
1864 if (id
== NULL
) return NI_FAILED
;
1865 if (propnames
== NULL
) return NI_FAILED
;
1867 resp
= RCALLIT(ni
, _ni_listprops_2
, id
);
1870 clnt_debug(ni
, "_ni_listprops");
1874 if (resp
->status
== NI_OK
)
1876 *propnames
= resp
->ni_namelist_res_u
.stuff
.values
;
1877 *id
= resp
->ni_namelist_res_u
.stuff
.self_id
;
1880 return resp
->status
;
1885 ni_createprop(void *ni
, ni_id
*id
, ni_property prop
, ni_index where
)
1888 ni_createprop_args args
;
1890 if (ni
== NULL
) return NI_FAILED
;
1891 if (id
== NULL
) return NI_FAILED
;
1897 resp
= WCALLIT(ni
, _ni_createprop_2
, &args
);
1900 clnt_debug(ni
, "_ni_createprop");
1904 if (resp
->status
== NI_OK
) *id
= resp
->ni_id_res_u
.id
;
1906 return resp
->status
;
1911 ni_destroyprop(void *ni
, ni_id
*id
, ni_index which
)
1916 if (ni
== NULL
) return NI_FAILED
;
1917 if (id
== NULL
) return NI_FAILED
;
1920 args
.prop_index
= which
;
1922 resp
= WCALLIT(ni
, _ni_destroyprop_2
, &args
);
1925 clnt_debug(ni
, "_ni_destroyprop");
1929 if (resp
->status
== NI_OK
) *id
= resp
->ni_id_res_u
.id
;
1931 return resp
->status
;
1936 ni_renameprop(void *ni
, ni_id
*id
, ni_index prop_index
, ni_name_const name
)
1939 ni_propname_args args
;
1941 if (ni
== NULL
) return NI_FAILED
;
1942 if (id
== NULL
) return NI_FAILED
;
1943 if (name
== NULL
) return NI_FAILED
;
1946 args
.prop_index
= prop_index
;
1947 args
.name
= (ni_name
)name
;
1949 resp
= WCALLIT(ni
, _ni_renameprop_2
, &args
);
1952 clnt_debug(ni
, "_ni_renameprop");
1956 if (resp
->status
== NI_OK
) *id
= resp
->ni_id_res_u
.id
;
1958 return resp
->status
;
1963 ni_createname(void *ni
, ni_id
*id
, ni_index prop_index
, ni_name_const name
, ni_index where
)
1966 ni_createname_args args
;
1968 if (ni
== NULL
) return NI_FAILED
;
1969 if (id
== NULL
) return NI_FAILED
;
1970 if (name
== NULL
) return NI_FAILED
;
1973 args
.prop_index
= prop_index
;
1974 args
.name
= (ni_name
)name
;
1977 resp
= WCALLIT(ni
, _ni_createname_2
, &args
);
1980 clnt_debug(ni
, "_ni_createname");
1984 if (resp
->status
== NI_OK
) *id
= resp
->ni_id_res_u
.id
;
1986 return resp
->status
;
1991 ni_destroyname(void *ni
, ni_id
*id
, ni_index prop_index
, ni_index name_index
)
1994 ni_nameindex_args args
;
1996 if (ni
== NULL
) return NI_FAILED
;
1997 if (id
== NULL
) return NI_FAILED
;
2000 args
.prop_index
= prop_index
;
2001 args
.name_index
= name_index
;
2003 resp
= WCALLIT(ni
, _ni_destroyname_2
, &args
);
2006 clnt_debug(ni
, "_ni_destroyname");
2010 if (resp
->status
== NI_OK
) *id
= resp
->ni_id_res_u
.id
;
2012 return resp
->status
;
2017 ni_writename(void *ni
, ni_id
*id
, ni_index prop_index
, ni_index name_index
, ni_name_const name
)
2020 ni_writename_args args
;
2022 if (ni
== NULL
) return NI_FAILED
;
2023 if (id
== NULL
) return NI_FAILED
;
2024 if (name
== NULL
) return NI_FAILED
;
2027 args
.prop_index
= prop_index
;
2028 args
.name_index
= name_index
;
2029 args
.name
= (ni_name
)name
;
2031 resp
= WCALLIT(ni
, _ni_writename_2
, &args
);
2034 clnt_debug(ni
, "_ni_writename");
2038 if (resp
->status
== NI_OK
) *id
= resp
->ni_id_res_u
.id
;
2040 return resp
->status
;
2045 ni_readname(void *ni
, ni_id
*id
, ni_index prop_index
, ni_index name_index
, ni_name
*name
)
2047 ni_readname_res
*resp
;
2048 ni_nameindex_args args
;
2050 if (ni
== NULL
) return NI_FAILED
;
2051 if (id
== NULL
) return NI_FAILED
;
2052 if (name
== NULL
) return NI_FAILED
;
2055 args
.prop_index
= prop_index
;
2056 args
.name_index
= name_index
;
2058 resp
= RCALLIT(ni
, _ni_readname_2
, &args
);
2061 clnt_debug(ni
, "_ni_readname");
2065 if (resp
->status
== NI_OK
)
2067 *id
= resp
->ni_readname_res_u
.stuff
.id
;
2068 *name
= resp
->ni_readname_res_u
.stuff
.name
;
2071 return resp
->status
;
2080 if (ni
== NULL
) return NI_FAILED
;
2082 resp
= (ni_status
*)RCALLIT(ni
, _ni_resync_2
, NULL
);
2085 clnt_debug(ni
, "_ni_resync");
2094 ni_setuser(void *ni
, ni_name_const user
)
2102 if (ni
== NULL
) return NI_FAILED
;
2106 NIP(ni
)->uid
= getuid();
2107 return ni_setpassword(ni
, NULL
);
2110 status
= ni_root(ni
, &id
);
2111 if (status
!= NI_OK
) return NI_NOUSER
;
2114 status
= ni_lookup(ni
, &id
, NAME_NAME
, NAME_USERS
, &ids
);
2115 if (status
!= NI_OK
) return NI_NOUSER
;
2117 id
.nii_object
= ids
.niil_val
[0];
2118 ni_idlist_free(&ids
);
2121 status
= ni_lookup(ni
, &id
, NAME_NAME
, user
, &ids
);
2122 if (status
!= NI_OK
) return NI_NOUSER
;
2124 id
.nii_object
= ids
.niil_val
[0];
2125 ni_idlist_free(&ids
);
2128 status
= ni_lookupprop(ni
, &id
, NAME_UID
, &nl
);
2129 if (status
!= NI_OK
) return NI_NOUSER
;
2131 if (nl
.ninl_len
== 0) return NI_NOUSER
;
2133 for (p
= nl
.ninl_val
[0]; *p
; p
++)
2135 if (isdigit(*p
) == 0)
2137 ni_namelist_free(&nl
);
2142 NIP(ni
)->uid
= atoi(nl
.ninl_val
[0]);
2143 if (NIP(ni
)->passwd
== NULL
) NIP(ni
)->passwd
= ni_name_dup("");
2145 createauth(NIP(ni
));
2151 ni_setpassword(void *ni
, ni_name_const passwd
)
2155 if (ni
== NULL
) return NI_FAILED
;
2157 if (NIP(ni
)->passwd
!= NULL
) ni_name_free(&NIP(ni
)->passwd
);
2161 NIP(ni
)->passwd
= NULL
;
2162 if (NIP(ni
)->tc
!= NULL
)
2164 auth_destroy(NIP(ni
)->tc
->cl_auth
);
2165 NIP(ni
)->tc
->cl_auth
= authnone_create();
2170 NIP(ni
)->passwd
= ni_name_dup(passwd
);
2172 /* Our trivial encryption scheme */
2173 for (p
= NIP(ni
)->passwd
; *p
; p
++) *p
= ~(*p
);
2174 createauth(NIP(ni
));
2180 * The procedure pmap_getport_to below is derived
2181 * from Sun Microsystems RPC source code. As such the following
2182 * statement applies to it.:
2184 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
2185 * unrestricted use provided that this legend is included on all tape
2186 * media and as a part of the software program in whole or part. Users
2187 * may copy or modify Sun RPC without charge, but are not authorized
2188 * to license or distribute it to anyone else except as part of a product or
2189 * program developed by the user.
2191 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
2192 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
2193 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
2195 * Sun RPC is provided with no support and without any obligation on the
2196 * part of Sun Microsystems, Inc. to assist in its use, correction,
2197 * modification or enhancement.
2199 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
2200 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
2201 * OR ANY PART THEREOF.
2203 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
2204 * or profits or other special, indirect and consequential damages, even if
2205 * Sun has been advised of the possibility of such damages.
2207 * Sun Microsystems, Inc.
2208 * 2550 Garcia Avenue
2209 * Mountain View, California 94043
2212 * Client interface to pmap rpc service.
2214 * Find the mapped port for program,version.
2215 * Calls the pmap service remotely to do the lookup.
2216 * Returns 0 if no map exists.
2219 pmap_getport_to(address
, program
, version
, protocol
, timeout_secs
, ntries
)
2220 struct sockaddr_in
*address
;
2229 register CLIENT
*client
;
2231 struct timeval timeout
;
2233 sock
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
2234 if (sock
< 0) return 0;
2236 address
->sin_port
= htons(PMAPPORT
);
2237 timeout
.tv_usec
= ((timeout_secs
% ntries
) * 1000000) / ntries
;
2238 timeout
.tv_sec
= (timeout_secs
/ ntries
);
2240 client
= clntudp_bufcreate(address
, PMAPPROG
, PMAPVERS
, timeout
, &sock
, RPCSMALLMSGSIZE
, RPCSMALLMSGSIZE
);
2243 parms
.pm_prog
= program
;
2244 parms
.pm_vers
= version
;
2245 parms
.pm_prot
= protocol
;
2246 parms
.pm_port
= 0; /* not needed or used */
2247 timeout
.tv_usec
= 0;
2248 timeout
.tv_sec
= timeout_secs
;
2250 if (CLNT_CALL(client
, PMAPPROC_GETPORT
, (xdrproc_t
)xdr_pmap
, (char *)&parms
, (xdrproc_t
)xdr_u_short
, (char *)&port
, timeout
) != RPC_SUCCESS
)
2252 rpc_createerr
.cf_stat
= RPC_PMAPFAILURE
;
2253 clnt_geterr(client
, &rpc_createerr
.cf_error
);
2258 rpc_createerr
.cf_stat
= RPC_PROGNOTREGISTERED
;
2262 if (client
!= NULL
) clnt_destroy(client
);
2265 address
->sin_port
= 0;
2271 * Open a socket, but do not use the default portmap timeout
2274 socket_open(struct sockaddr_in
*raddr
, int prog
, int vers
, int timeout
, int ntries
, int proto
)
2276 struct sockaddr_in bindsin
;
2281 memset(&bindsin
, 0, sizeof(bindsin
));
2284 * If no port number given ask the pmap for one
2286 if (raddr
->sin_port
== 0)
2288 port
= pmap_getport_to(raddr
, prog
, vers
, IPPROTO_UDP
, timeout
, ntries
);
2289 if (port
== 0) return -1;
2291 raddr
->sin_port
= htons(port
);
2294 sock
= socket(AF_INET
, proto
== IPPROTO_UDP
? SOCK_DGRAM
: SOCK_STREAM
, proto
);
2295 if (sock
< 0) return -1;
2297 if ((bindresvport(sock
, NULL
) < 0) && (errno
== EADDRNOTAVAIL
))
2299 /* XXX - we're hitting this case way too often under load */
2300 /* fail gracefully: some address is better than none most of the time */
2301 syslog(LOG_DEBUG
, "Libinfo[%s():%d] bindresvport(): %m", __func__
, __LINE__
);
2302 if (bind(sock
, (struct sockaddr
*)&bindsin
, sizeof(bindsin
)) < 0)
2304 /* The system is really sad now if it can't give me any address... */
2305 syslog(LOG_DEBUG
, "Libinfo[%s():%d] bind(): %m", __func__
, __LINE__
);
2311 setsockopt(sock
, SOL_SOCKET
, SO_REUSEPORT
, &reuse
, sizeof(int));
2312 setsockopt(sock
, SOL_SOCKET
, SO_REUSEADDR
, &reuse
, sizeof(int));
2314 if (proto
== IPPROTO_TCP
)
2316 if (connect(sock
, (struct sockaddr
*)raddr
, sizeof(*raddr
)) < 0)
2318 syslog(LOG_DEBUG
, "Libinfo[%s():%d] connect(): %m", __func__
, __LINE__
);