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.
30 #include <netinfo/ni.h>
31 #include <rpc/pmap_clnt.h>
32 #include <rpc/pmap_prot.h>
38 #define NI_TIMEOUT_SHORT 5 /* 5 second timeout for transactions */
39 #define NI_TIMEOUT_LONG 60 /* 60 second timeout for writes */
40 #define NI_TRIES 5 /* number of retries per timeout (udp only) */
41 #define NI_SLEEPTIME 4 /* 4 second sleeptime, in case of errors */
42 #define NI_MAXSLEEPTIME 64 /* 64 second max sleep time */
43 #define NI_MAXCONNTRIES 2 /* Try to form a connection twice before sleeping */
45 /* Hack for determining if an IP address is a broadcast address. -GRS */
46 /* Note that addr is network byte order (big endian) - BKM */
48 #define IS_BROADCASTADDR(addr) (((unsigned char *) &addr)[0] == 0xFF)
50 #ifndef INADDR_LOOPBACK
51 #define INADDR_LOOPBACK (u_long)0x7f000001
53 #define debug(msg) syslog(LOG_ERR, msg)
55 #define clnt_debug(ni, msg) /* do nothing */
57 typedef struct ni_private
{
58 int naddrs
; /* number of addresses */
59 struct in_addr
*addrs
; /* addresses of servers - network byte order */
60 int whichwrite
; /* which one of the above is the master */
61 ni_name
*tags
; /* tags of servers */
62 int pid
; /* pid, to detect forks */
63 int tsock
; /* tcp socket */
64 int tport
; /* tcp local port name - host byte order */
65 CLIENT
*tc
; /* tcp client */
66 long tv_sec
; /* timeout for this call */
67 long rtv_sec
; /* read timeout - 0 if default */
68 long wtv_sec
; /* write timeout - 0 if default */
69 int abort
; /* abort on timeout? */
70 int needwrite
; /* need to lock writes? */
71 int uid
; /* user id */
72 ni_name passwd
; /* password */
75 #define NIP(ni) ((ni_private *)(ni))
77 static const ni_name NAME_NAME
= "name";
78 static const ni_name NAME_SERVES
= "serves";
79 static const ni_name NAME_MACHINES
= "machines";
80 static const ni_name NAME_IP_ADDRESS
= "ip_address";
81 static const ni_name NAME_MASTER
= "master";
82 static const ni_name NAME_USERS
= "users";
83 static const ni_name NAME_UID
= "uid";
85 typedef struct getreg_stuff
{
86 nibind_getregister_res res
;
91 static int socket_open(struct sockaddr_in
*raddr
, int, int, int, int, int);
95 * Keep track of our port, in case somebody closes our socket
103 struct sockaddr_in sin
;
106 sinlen
= sizeof(sin
);
107 if (getsockname(sock
, (struct sockaddr
*)&sin
, &sinlen
) == 0) {
108 if (sin
.sin_port
== 0) {
109 (void)bind(sock
, (struct sockaddr
*)&sin
, sizeof(sin
));
110 sinlen
= sizeof(sin
);
111 (void)getsockname(sock
, (struct sockaddr
*)&sin
,
114 return (ntohs(sin
.sin_port
));
121 * Is the NetInfo binder running?
129 struct sockaddr_in sin
;
132 sock
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
136 sin
.sin_family
= AF_INET
;
137 sin
.sin_port
= htons(PMAPPORT
);
138 sin
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
139 bzero(sin
.sin_zero
, sizeof(sin
.sin_zero
));
140 res
= connect(sock
, (struct sockaddr
*)&sin
, sizeof(sin
));
145 sin
.sin_port
= htons(pmap_getport(&sin
, NIBIND_PROG
, NIBIND_VERS
,
147 if (sin
.sin_port
== 0) {
150 sock
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
154 res
= connect(sock
, (struct sockaddr
*)&sin
, sizeof(sin
));
165 if (ni
->passwd
!= NULL
&& ni
->tc
!= NULL
) {
166 auth_destroy(ni
->tc
->cl_auth
);
167 ni
->tc
->cl_auth
= authunix_create(ni
->passwd
, ni
->uid
, 0, 0,
180 tv
->tv_sec
= sec
/ tries
;
181 tv
->tv_usec
= ((sec
% tries
) * 1000000) / tries
;
195 ni
->tv_sec
= timeout
;
196 if (ni
->tc
!= NULL
) {
197 clnt_control(ni
->tc
, CLSET_TIMEOUT
, &tv
);
203 * Connect to a given address/tag
210 struct sockaddr_in sin
;
215 nibind_getregister_res res
;
217 bzero(&sin
, sizeof(sin
));
219 sin
.sin_family
= AF_INET
;
220 sin
.sin_addr
= ni
->addrs
[0];
221 ni_settimeout(ni
, ni
->rtv_sec
== 0 ? NI_TIMEOUT_SHORT
: ni
->rtv_sec
);
222 fixtimeout(&tv
, ni
->tv_sec
, NI_TRIES
);
223 sock
= socket_open(&sin
, NIBIND_PROG
, NIBIND_VERS
, ni
->tv_sec
,
224 NI_TRIES
, IPPROTO_UDP
);
228 cl
= clntudp_create(&sin
, NIBIND_PROG
, NIBIND_VERS
, tv
,
234 tv
.tv_sec
= ni
->rtv_sec
== 0 ? NI_TIMEOUT_SHORT
: ni
->rtv_sec
;
236 stat
= clnt_call(cl
, NIBIND_GETREGISTER
, xdr_ni_name
, &ni
->tags
[0],
237 xdr_nibind_getregister_res
, &res
, tv
);
240 if (stat
!= RPC_SUCCESS
|| res
.status
!= NI_OK
) {
245 * Found the address, now connect to it.
247 sin
.sin_port
= htons(res
.nibind_getregister_res_u
.addrs
.tcp_port
);
248 sock
= socket_open(&sin
, NI_PROG
, NI_VERS
, ni
->tv_sec
, NI_TRIES
,
253 cl
= clnttcp_create(&sin
, NI_PROG
, NI_VERS
, &sock
, 0, 0);
258 clnt_control(cl
, CLSET_TIMEOUT
, &tv
);
261 ni
->tport
= getmyport(sock
);
263 (void) fcntl(ni
->tsock
, F_SETFD
, 1);
274 ((ni_private
*)ni
)->abort
= abort
;
284 ((ni_private
*)ni
)->wtv_sec
= timeout
;
294 ((ni_private
*)ni
)->rtv_sec
= timeout
;
304 ((ni_private
*)ni
)->needwrite
= needwrite
;
313 char buf
[1024]; /* XXX */
314 int i
, len
, ifreq_size
, offset
, sockaddr_size
, size
;
316 struct sockaddr_in
*sin
;
317 unsigned long n_addr
;
319 sock
= socket(AF_INET
, SOCK_DGRAM
, 0);
321 if (sock
< 0) return (htonl(IN_CLASSA_NET
));
323 ifc
.ifc_len
= sizeof(buf
);
326 if (ioctl(sock
, SIOCGIFCONF
, (char *)&ifc
) < 0)
329 return (htonl(IN_CLASSA_NET
));
332 ifreq_size
= sizeof(struct ifreq
);
333 sockaddr_size
= sizeof(struct sockaddr
);
336 len
= ifc
.ifc_len
/ ifreq_size
;
337 for (i
= 0; i
< len
; i
++)
339 ifr
= (struct ifreq
*)(ifc
.ifc_buf
+ offset
);
341 offset
+= sockaddr_size
;
343 size
= ifr
->ifr_addr
.sa_len
;
344 if (size
> sockaddr_size
) offset
+= (size
- sockaddr_size
);
346 if (ifr
->ifr_addr
.sa_family
!= AF_INET
) continue;
347 if (ioctl(sock
, SIOCGIFFLAGS
, (char *)ifr
) < 0) continue;
349 sin
= (struct sockaddr_in
*)&ifr
->ifr_addr
;
350 if ((ifr
->ifr_flags
& IFF_UP
) &&
351 !(ifr
->ifr_flags
& IFF_LOOPBACK
) &&
352 (sin
->sin_addr
.s_addr
!= 0))
354 ioctl(sock
, SIOCGIFNETMASK
, (char *)ifr
);
355 n_addr
= ((struct sockaddr_in
*)&(ifr
->ifr_addr
))->sin_addr
.s_addr
;
362 return (htonl(IN_CLASSA_NET
));
371 char buf
[1024]; /* XXX */
372 int i
, len
, ifreq_size
, offset
, sockaddr_size
, size
;
375 sock
= socket(AF_INET
, SOCK_DGRAM
, 0);
379 return (htonl(INADDR_LOOPBACK
));
382 ifc
.ifc_len
= sizeof(buf
);
385 if (ioctl(sock
, SIOCGIFCONF
, (char *)&ifc
) < 0)
388 return (htonl(INADDR_LOOPBACK
));
391 ifreq_size
= sizeof(struct ifreq
);
392 sockaddr_size
= sizeof(struct sockaddr
);
395 len
= ifc
.ifc_len
/ ifreq_size
;
396 for (i
= 0; i
< len
; i
++)
398 ifr
= (struct ifreq
*)(ifc
.ifc_buf
+ offset
);
400 offset
+= sockaddr_size
;
402 size
= ifr
->ifr_addr
.sa_len
;
403 if (size
> sockaddr_size
) offset
+= (size
- sockaddr_size
);
405 if (ifr
->ifr_addr
.sa_family
!= AF_INET
) continue;
406 if (ioctl(sock
, SIOCGIFFLAGS
, ifr
) < 0) continue;
408 if ((ifr
->ifr_flags
& IFF_UP
) && (!(ifr
->ifr_flags
& IFF_LOOPBACK
)))
411 return (((struct sockaddr_in
*)&(ifr
->ifr_addr
))->sin_addr
.s_addr
);
416 return (htonl(INADDR_LOOPBACK
));
421 * Returns a client handle to the NetInfo server, if it's running
424 connectlocal(ni_private
*ni
)
428 if (!nibind_up(ni
)) {
432 ni
->addrs
= (struct in_addr
*)malloc(sizeof(struct in_addr
));
433 ni
->addrs
[0].s_addr
= htonl(INADDR_LOOPBACK
);
434 ni
->tags
= (ni_name
*)malloc(sizeof(ni_name
));
435 ni
->tags
[0] = ni_name_dup("local");
437 while (!connectit(ni
)) {
439 syslog(LOG_ERR
, "NetInfo timeout connecting to local domain, sleeping");
446 syslog(LOG_ERR
, "NetInfo connection to local domain waking");
453 * Destroy the client handle
464 if (sock
>= 0 && getmyport(sock
) != port
) {
466 * Somebody else has the descriptor open. Do not close it,
472 auth_destroy(cl
->cl_auth
);
477 * It's ours and we can close it
485 * Reinitialize everything
492 if (ni
->tc
!= NULL
) {
493 clnt_kill(ni
->tc
, ni
->tsock
, ni
->tport
);
503 * Switch to a new server
511 struct in_addr tmp_addr
;
518 tmp_addr
= ni
->addrs
[0];
519 tmp_tag
= ni
->tags
[0];
521 ni
->addrs
[0] = ni
->addrs
[which
];
522 ni
->tags
[0] = ni
->tags
[which
];
524 ni
->addrs
[which
] = tmp_addr
;
525 ni
->tags
[which
] = tmp_tag
;
527 if (ni
->whichwrite
== 0) {
528 ni
->whichwrite
= which
;
530 else if (ni
->whichwrite
== which
) {
537 * Swap two servers' positions
546 struct in_addr tmp_addr
;
549 tmp_addr
= ni
->addrs
[a
];
550 tmp_tag
= ni
->tags
[a
];
552 ni
->addrs
[a
] = ni
->addrs
[b
];
553 ni
->tags
[a
] = ni
->tags
[b
];
555 ni
->addrs
[b
] = tmp_addr
;
556 ni
->tags
[b
] = tmp_tag
;
558 if (ni
->whichwrite
== a
) {
561 else if (ni
->whichwrite
== b
) {
568 * Callback routine for multi_call
569 * XXX: should save returned port numbers
574 struct sockaddr_in
*sin
,
578 getreg_stuff
*stuff
= (getreg_stuff
*)vstuff
;
580 if (stuff
->res
.status
!= NI_OK
) {
583 ni_switch(stuff
->ni
, which
);
595 int sleeptime
= NI_SLEEPTIME
;
599 unsigned long myaddr
;
600 unsigned long mynetmask
;
601 unsigned long mynetwork
;
604 if (ni
->naddrs
== 1) {
611 * re-order the servers so that:
612 * servers on the local host are at the start of the list, then
613 * servers on the local network are next, then
614 * all other servers are next
617 myaddr
= sys_address();
618 mynetmask
= sys_netmask();
619 mynetwork
= myaddr
& mynetmask
;
622 * move local servers to the head of the list
625 for (i
= nlocal
; i
< ni
->naddrs
; i
++) {
626 if ((ni
->addrs
[i
].s_addr
== myaddr
) ||
627 (ni
->addrs
[i
].s_addr
== htonl(INADDR_LOOPBACK
)))
629 ni_swap(ni
, nlocal
, i
);
635 * move servers on this network to follow local servers
638 for (i
= nnetwork
; i
< ni
->naddrs
; i
++) {
639 if (((ni
->addrs
[i
].s_addr
& mynetmask
) == mynetwork
) ||
640 IS_BROADCASTADDR(ni
->addrs
[i
].s_addr
))
642 ni_swap(ni
, nnetwork
, i
);
650 * call local servers first
653 for (i
= 0; i
< nlocal
; i
++) {
654 syslog(LOG_DEBUG
, "NetInfo connect call to: %s/%s (local %d)",
655 inet_ntoa(ni
->addrs
[i
]), ni
->tags
[i
], i
);
657 stat
= multi_call(nlocal
, ni
->addrs
,
658 NIBIND_PROG
, NIBIND_VERS
, NIBIND_GETREGISTER
,
659 xdr_ni_name
, ni
->tags
,
661 xdr_nibind_getregister_res
,
664 if (stat
== RPC_SUCCESS
) {
670 * call local servers and this network's servers
672 if (nnetwork
> nlocal
) {
673 for (i
= 0; i
< nnetwork
; i
++) {
674 syslog(LOG_DEBUG
, "NetInfo connect call to: %s/%s (network %d)",
675 inet_ntoa(ni
->addrs
[i
]), ni
->tags
[i
], i
);
677 stat
= multi_call(nnetwork
, ni
->addrs
,
678 NIBIND_PROG
, NIBIND_VERS
, NIBIND_GETREGISTER
,
679 xdr_ni_name
, ni
->tags
,
681 xdr_nibind_getregister_res
,
684 if (stat
== RPC_SUCCESS
) {
692 for (i
= 0; i
< ni
->naddrs
; i
++) {
693 syslog(LOG_DEBUG
, "NetInfo connect call to: %s/%s (world %d)",
694 inet_ntoa(ni
->addrs
[i
]), ni
->tags
[i
], i
);
696 stat
= multi_call(ni
->naddrs
,
697 ni
->addrs
, NIBIND_PROG
, NIBIND_VERS
,
699 xdr_ni_name
, ni
->tags
,
701 xdr_nibind_getregister_res
,
703 ni
->rtv_sec
== 0 ? NI_TIMEOUT_SHORT
: ni
->rtv_sec
);
704 if (stat
== RPC_SUCCESS
) {
712 if (ni
->whichwrite
>= 0) {
714 "NetInfo connect timeout (domain with master %s/%s), sleeping",
715 inet_ntoa(ni
->addrs
[ni
->whichwrite
]), ni
->tags
[ni
->whichwrite
]);
718 syslog(LOG_ERR
, "NetInfo connect timeout (domain with server %s/%s), sleeping",
719 inet_ntoa(ni
->addrs
[0]), ni
->tags
[0]);
724 if (sleeptime
< NI_MAXSLEEPTIME
) {
725 sleeptime
*= 2; /* backoff */
729 syslog(LOG_INFO
, "NetInfo connected to %s/%s", inet_ntoa(ni
->addrs
[0]), ni
->tags
[0]);
732 syslog(LOG_ERR
, "NetInfo connected to %s/%s", inet_ntoa(ni
->addrs
[0]), ni
->tags
[0]);
739 * Confirm that our tcp socket is still valid
747 if (ni
->tsock
!= -1) {
748 if (getmyport(ni
->tsock
) == ni
->tport
) {
752 * Somebody closed our socket. Do not close it, it could
753 * be owned by somebody else now.
755 auth_destroy(ni
->tc
->cl_auth
);
756 clnt_destroy(ni
->tc
);
759 if (!needwrite
&& !rebind(ni
) && ni
->abort
) {
762 return (connectit(ni
));
782 if (ni
->naddrs
== 1) {
784 * One server - must be the master
789 needwrite
= ni
->needwrite
;
791 if (ni_root(ni
, &root
) != NI_OK
) {
792 ni
->needwrite
= needwrite
;
795 if (ni_lookupprop(ni
, &root
, NAME_MASTER
, &nl
) != NI_OK
) {
796 ni
->needwrite
= needwrite
;
799 if (nl
.ninl_len
== 0) {
800 ni
->needwrite
= needwrite
;
803 sep
= index(nl
.ninl_val
[0], '/');
805 ni
->needwrite
= needwrite
;
809 master
= nl
.ninl_val
[0];
810 if (ni_lookup(ni
, &root
, NAME_NAME
, NAME_MACHINES
, &idl
) != NI_OK
) {
811 ni
->needwrite
= needwrite
;
812 ni_namelist_free(&nl
);
815 if (idl
.niil_len
< 1) {
816 ni
->needwrite
= needwrite
;
819 id
.nii_object
= idl
.niil_val
[0];
820 ni_idlist_free(&idl
);
821 if (ni_lookup(ni
, &id
, NAME_NAME
, master
, &idl
) != NI_OK
) {
822 ni_namelist_free(&nl
);
823 ni
->needwrite
= needwrite
;
826 ni_namelist_free(&nl
);
827 if (idl
.niil_len
< 1) {
828 ni
->needwrite
= needwrite
;
831 id
.nii_object
= idl
.niil_val
[0];
832 ni_idlist_free(&idl
);
833 if (ni_lookupprop(ni
, &id
, NAME_IP_ADDRESS
, &nl
) != NI_OK
) {
836 for (i
= 0; i
< nl
.ninl_len
; i
++) {
837 addr
.s_addr
= inet_addr(nl
.ninl_val
[i
]);
838 for (j
= 0; j
< ni
->naddrs
; j
++) {
839 if (addr
.s_addr
== ni
->addrs
[j
].s_addr
) {
841 ni_namelist_free(&nl
);
842 ni
->needwrite
= needwrite
;
847 ni
->needwrite
= needwrite
;
848 ni_namelist_free(&nl
);
867 if (getpid() != ni
->pid
) {
870 if (needwrite
|| ni
->needwrite
) {
871 if (ni
->whichwrite
>= 0) {
872 ni_switch(ni
, ni
->whichwrite
);
874 if (!setmaster(ni
)) {
877 ni_switch(ni
, ni
->whichwrite
);
880 ni_settimeout(ni
, (ni
->rtv_sec
== 0 ?
881 NI_TIMEOUT_SHORT
: ni
->rtv_sec
));
884 ni_settimeout(ni
, (ni
->wtv_sec
== 0 ?
885 NI_TIMEOUT_LONG
: ni
->wtv_sec
));
888 ni_settimeout(ni
, (ni
->rtv_sec
== 0 ?
889 NI_TIMEOUT_SHORT
: ni
->rtv_sec
));
893 * Try more than once, in case server closed connection.
895 for (i
= 0; i
< NI_MAXCONNTRIES
; i
++) {
896 if (!confirm_tcp(ni
, needwrite
)) {
899 if ((resp
= (*stub
)(args
, ni
->tc
)) != NULL
) {
901 syslog(LOG_ERR
, "NetInfo connected to %s/%s",
902 inet_ntoa(ni
->addrs
[0]), ni
->tags
[0]);
906 clnt_geterr(ni
->tc
, &err
);
907 if (err
.re_status
!= RPC_CANTRECV
) {
910 if (i
+ 1 < NI_MAXCONNTRIES
) {
912 * Server closed connection. Reinit and try
918 if (err
.re_status
== RPC_PROCUNAVAIL
) {
921 if (needwrite
|| ni
->abort
) {
923 * We time out for writes or if it is explicitly
930 "NetInfo connection failed for server %s/%s",
931 inet_ntoa(ni
->addrs
[0]), ni
->tags
[0]);
935 if (ni
->tc
!= NULL
) {
936 if (!(sleeptime
== 0 &&
937 err
.re_status
== RPC_TIMEDOUT
)) {
939 * Do not print message on
940 * first timeout. It is likely
941 * we will find another server soon.
942 * Let's not needlessly alarm the
945 syslog(LOG_ERR
, "%s on connection to %s/%s",
946 clnt_sperror(ni
->tc
,"NetInfo connection timeout"),
947 inet_ntoa(ni
->addrs
[0]), ni
->tags
[0]);
951 /* first attempt failed */
952 syslog(LOG_ERR
, "%s on initial connection to %s/%s",
953 clnt_sperror(ni
->tc
,"NetInfo connection timeout"),
954 inet_ntoa(ni
->addrs
[0]), ni
->tags
[0]);
958 "NetInfo connection failed for server %s/%s",
959 inet_ntoa(ni
->addrs
[0]), ni
->tags
[0]);
965 if (sleeptime
< NI_MAXSLEEPTIME
) {
966 sleeptime
*= 2; /* backoff */
970 * Do not sleep on the first timeout.
971 * It is likely we will find another server quickly.
973 sleeptime
= NI_SLEEPTIME
;
981 #define RCALLIT(a, b, c) callit((ni_private *)(a), (void *(*)())(b), \
985 #define WCALLIT(a, b, c) callit((ni_private *)(a), (void *(*)())(b), \
1001 ni
->whichwrite
= -1;
1013 ni
= (ni_private
*)malloc(sizeof(*ni
));
1015 ni
->whichwrite
= -1;
1020 ni
->tv_sec
= NI_TIMEOUT_SHORT
;
1027 return ((void *)ni
);
1039 dupni
= (ni_private
*)ni_alloc();
1042 dupni
->naddrs
= NIP(ni
)->naddrs
;
1043 dupni
->whichwrite
= NIP(ni
)->whichwrite
;
1044 if (dupni
->naddrs
> 0) {
1045 dupni
->addrs
= ((struct in_addr
*)
1046 malloc(NIP(ni
)->naddrs
* sizeof(struct in_addr
)));
1047 bcopy(NIP(ni
)->addrs
, dupni
->addrs
,
1048 NIP(ni
)->naddrs
* sizeof(struct in_addr
));
1049 dupni
->tags
= ((ni_name
*)
1050 malloc(NIP(ni
)->naddrs
* sizeof(ni_name
)));
1051 for (i
= 0; i
< NIP(ni
)->naddrs
; i
++) {
1052 dupni
->tags
[i
] = ni_name_dup(NIP(ni
)->tags
[i
]);
1055 if (NIP(ni
)->passwd
!= NULL
) {
1056 dupni
->passwd
= ni_name_dup(NIP(ni
)->passwd
);
1058 return ((void *)dupni
);
1069 int len
= strlen(domain
);
1072 sep
= index(domtag
, '/');
1076 if (strncmp(domain
, domtag
, len
) == 0 &&
1077 domtag
[len
] == '/') {
1078 *tag
= ni_name_dup(sep
+ 1);
1090 ni_private
*target_ni
1095 struct in_addr addr
;
1098 id
.nii_object
= ido
;
1099 if (ni_lookupprop(ni
, &id
, NAME_IP_ADDRESS
, &nl
) != NI_OK
) {
1102 if (nl
.ninl_len
== 0) {
1106 if (target_ni
->naddrs
== 0) {
1108 (struct in_addr
*)malloc(nl
.ninl_len
* sizeof(struct in_addr
));
1110 (ni_name
*)malloc(nl
.ninl_len
* sizeof(ni_name
));
1113 (struct in_addr
*)realloc(target_ni
->addrs
,
1114 ((target_ni
->naddrs
+ nl
.ninl_len
) * sizeof(struct in_addr
)));
1116 (ni_name
*)realloc(target_ni
->tags
,
1117 ((target_ni
->naddrs
+ nl
.ninl_len
) * sizeof(ni_name
)));
1120 for (i
=0; i
<nl
.ninl_len
; i
++) {
1121 addr
.s_addr
= inet_addr(nl
.ninl_val
[i
]);
1122 target_ni
->addrs
[target_ni
->naddrs
] = addr
;
1123 target_ni
->tags
[target_ni
->naddrs
] = ni_name_dup(tag
);
1124 target_ni
->naddrs
++;
1127 ni_namelist_free(&nl
);
1136 ni_private
*target_ni
1142 ni_entrylist entries
;
1147 if (ni_root(ni
, &id
) != NI_OK
) {
1151 if (ni_lookup(ni
, &id
, NAME_NAME
, NAME_MACHINES
, &ids
) != NI_OK
) {
1155 id
.nii_object
= ids
.niil_val
[0];
1156 ni_idlist_free(&ids
);
1158 if (ni_list(ni
, &id
, NAME_SERVES
, &entries
) != NI_OK
) {
1162 for (i
= 0; i
< entries
.niel_len
; i
++) {
1163 if (entries
.niel_val
[i
].names
!= NULL
) {
1164 nl
= *entries
.niel_val
[i
].names
;
1165 for (j
= 0; j
< nl
.ninl_len
; j
++) {
1166 if (match(dom
, nl
.ninl_val
[j
], &tag
)) {
1168 entries
.niel_val
[i
].id
,
1180 ni_entrylist_free(&entries
);
1181 return (target_ni
->naddrs
> 0);
1191 ni_private
*target_ni
1197 if (ni_root(ni
, &id
) != NI_OK
) {
1200 if (ni_lookup(ni
, &id
, NAME_NAME
, NAME_MACHINES
, &ids
) != NI_OK
) {
1203 id
.nii_object
= ids
.niil_val
[0];
1204 ni_idlist_free(&ids
);
1206 if (ni_lookup(ni
, &id
, NAME_NAME
, hname
, &ids
) != NI_OK
) {
1209 id
.nii_object
= ids
.niil_val
[0];
1210 ni_idlist_free(&ids
);
1211 if (!addaddr(ni
, id
.nii_object
, tag
, target_ni
)) {
1220 getparent(ni_private
*oldni
, ni_private
**newni
)
1222 ni_rparent_res
*resp
;
1227 struct in_addr raddr
;
1234 * First, find our parent, any parent
1237 resp
= RCALLIT(oldni
, _ni_rparent_2
, NULL
);
1241 if (resp
->status
!= NI_NORESPONSE
) {
1245 syslog(LOG_ERR
, "NetInfo timeout finding server for parent of %s/%s, sleeping",
1246 inet_ntoa(oldni
->addrs
[0]), oldni
->tags
[0]);
1249 sleep(NI_SLEEPTIME
);
1252 raddr
.s_addr
= htonl(resp
->ni_rparent_res_u
.binding
.addr
);
1254 syslog(LOG_ERR
, "NetInfo %s/%s found parent %s/%s",
1255 inet_ntoa(oldni
->addrs
[0]), oldni
->tags
[0],
1256 inet_ntoa(raddr
), resp
->ni_rparent_res_u
.binding
.tag
);
1258 if (resp
->status
!= NI_OK
) {
1259 return (resp
->status
);
1265 ni
->addrs
= (struct in_addr
*)malloc(sizeof(struct in_addr
));
1266 ni
->addrs
[0].s_addr
=htonl(resp
->ni_rparent_res_u
.binding
.addr
);
1267 ni
->tags
= (ni_name
*)malloc(sizeof(ni_name
));
1268 ni
->tags
[0] = ni_name_dup(resp
->ni_rparent_res_u
.binding
.tag
);
1270 xdr_free(xdr_ni_rparent_res
, resp
);
1276 if (get_daddr(dupni
, ".", ni
)) {
1279 * Now make sure returned parent is head of
1282 for (i
= 0; i
< ni
->naddrs
; i
++) {
1283 if (ni
->addrs
[i
].s_addr
==
1284 dupni
->addrs
[0].s_addr
) {
1292 * Reuse dupni client info
1294 ni
->tsock
= dupni
->tsock
;
1295 ni
->tport
= dupni
->tport
;
1303 * If returned parent wasn't in list, it's a rogue.
1304 * Log an error and drop the connection.
1307 syslog(LOG_ERR
, "Rogue NetInfo server detected: %s/%s",
1308 inet_ntoa(dupni
->addrs
[0]), dupni
->tags
[0]);
1327 struct sockaddr_in
*sin
,
1334 NIP(ni
)->naddrs
= 1;
1335 NIP(ni
)->addrs
= (struct in_addr
*
1336 )malloc(sizeof(struct in_addr
));
1337 NIP(ni
)->addrs
[0] = sin
->sin_addr
;
1338 NIP(ni
)->tags
= (ni_name
*)malloc(sizeof(ni_name
));
1339 NIP(ni
)->tags
[0] = ni_name_dup(tag
);
1347 struct sockaddr_in
*addr
,
1352 if (!confirm_tcp(ni
, 0)) {
1355 *tag
= ni_name_dup(NIP(ni
)->tags
[0]);
1356 addr
->sin_addr
= NIP(ni
)->addrs
[0];
1357 addr
->sin_port
= htons(NIP(ni
)->tport
);
1358 addr
->sin_family
= AF_INET
;
1359 bzero(addr
->sin_zero
, sizeof(addr
->sin_zero
));
1372 ni_name sep
, addr
, tag
;
1373 struct sockaddr_in sin
;
1376 if (oldni
== NULL
) {
1378 if (!connectlocal(ni
)) {
1382 if (strcmp(domain
, "..") == 0) {
1384 status
= getparent((ni_private
*)oldni
, &ni
);
1386 if (status
!= NI_OK
) {
1389 } else if ((sep
= index(domain
, '@')) != NULL
) {
1391 tag
= strncpy((char *)malloc(sep
-domain
+1), domain
, sep
-domain
);
1392 tag
[sep
-domain
] = '\0';
1393 addr
= strcpy ((char *)malloc(strlen(sep
+1)), sep
+1);
1394 sin
.sin_addr
.s_addr
= inet_addr(addr
);
1395 if (sin
.sin_addr
.s_addr
== INADDR_NONE
) {
1396 he
= gethostbyname(addr
);
1402 bcopy(he
->h_addr_list
[0], &sin
.sin_addr
.s_addr
, he
->h_length
);
1404 ni
= ni_connect(&sin
, tag
);
1407 } else if (strcmp(domain
, ".") != 0) {
1409 * nothing else makes sense
1415 if (strcmp(domain
, "..") == 0) {
1416 status
= getparent((ni_private
*)oldni
, &ni
);
1417 if (status
!= NI_OK
) {
1420 } else if ((sep
= index(domain
, '@')) != NULL
) {
1421 tag
= strncpy((char *)malloc(sep
-domain
+1), domain
, sep
-domain
);
1422 tag
[sep
-domain
] = '\0';
1423 addr
= strcpy ((char *)malloc(strlen(sep
+1)), sep
+1);
1424 sin
.sin_addr
.s_addr
= inet_addr(addr
);
1425 if (sin
.sin_addr
.s_addr
== INADDR_NONE
) {
1426 he
= gethostbyname(addr
);
1432 bcopy(he
->h_addr_list
[0], &sin
.sin_addr
.s_addr
, he
->h_length
);
1434 ni
= ni_connect(&sin
, tag
);
1441 if (!get_daddr(oldni
, (ni_name
)domain
, ni
)) {
1447 return ((void *)ni
);
1458 if (NIP(ni
)->tc
!= NULL
) {
1459 clnt_kill(NIP(ni
)->tc
, NIP(ni
)->tsock
, NIP(ni
)->tport
);
1461 if (NIP(ni
)->naddrs
> 0) {
1462 free(NIP(ni
)->addrs
);
1463 for (i
= 0; i
< NIP(ni
)->naddrs
; i
++) {
1464 ni_name_free(&NIP(ni
)->tags
[i
]);
1466 free(NIP(ni
)->tags
);
1468 if (NIP(ni
)->passwd
!= NULL
) {
1469 ni_name_free(&NIP(ni
)->passwd
);
1476 * The rest of these are just wrappers that end up doing
1477 * RPC calls to the local NetInfo server.
1487 if ((resp
= (ni_proplist
*)RCALLIT(ni
, _ni_statistics_2
, NULL
))
1504 if ((resp
= RCALLIT(ni
, _ni_root_2
, id
)) == NULL
) {
1505 clnt_debug(ni
, "_ni_root");
1508 if (resp
->status
== NI_OK
) {
1509 *id
= resp
->ni_id_res_u
.id
;
1511 return (resp
->status
);
1523 if ((resp
= RCALLIT(ni
, _ni_self_2
, id
)) == NULL
) {
1524 clnt_debug(ni
, "_ni_self");
1527 if (resp
->status
== NI_OK
) {
1528 *id
= resp
->ni_id_res_u
.id
;
1530 return (resp
->status
);
1538 ni_index
*parent_id_p
1541 ni_parent_res
*resp
;
1543 if ((resp
= RCALLIT(ni
, _ni_parent_2
, id
)) == NULL
) {
1544 clnt_debug(ni
, "_ni_parent");
1547 if (resp
->status
== NI_OK
) {
1548 *parent_id_p
= resp
->ni_parent_res_u
.stuff
.object_id
;
1549 *id
= resp
->ni_parent_res_u
.stuff
.self_id
;
1551 return (resp
->status
);
1562 ni_children_res
*resp
;
1564 if ((resp
= RCALLIT(ni
, _ni_children_2
, id
)) == NULL
) {
1565 clnt_debug(ni
, "_ni_children");
1568 if (resp
->status
== NI_OK
) {
1569 *children
= resp
->ni_children_res_u
.stuff
.children
;
1570 *id
= resp
->ni_children_res_u
.stuff
.self_id
;
1572 return (resp
->status
);
1585 ni_create_args args
;
1586 ni_create_res
*resp
;
1588 args
.id
= *parent_id
;
1591 args
.target_id
= NULL
;
1592 if ((resp
= WCALLIT(ni
, _ni_create_2
, &args
)) == NULL
) {
1593 clnt_debug(ni
, "_ni_create");
1596 if (resp
->status
== NI_OK
) {
1597 *child_id_p
= resp
->ni_create_res_u
.stuff
.id
;
1598 *parent_id
= resp
->ni_create_res_u
.stuff
.self_id
;
1600 return (resp
->status
);
1612 ni_destroy_args args
;
1614 args
.parent_id
= *parent_id
;
1615 args
.self_id
= self_id
;
1616 if ((resp
= WCALLIT(ni
, _ni_destroy_2
, &args
)) == NULL
) {
1617 clnt_debug(ni
, "_ni_destroy");
1620 if (resp
->status
== NI_OK
) {
1621 *parent_id
= resp
->ni_id_res_u
.id
;
1623 return (resp
->status
);
1634 ni_proplist_stuff args
;
1639 if ((resp
= WCALLIT(ni
, _ni_write_2
, &args
)) == NULL
) {
1640 clnt_debug(ni
, "_ni_write");
1643 if (resp
->status
== NI_OK
) {
1644 *self_id
= resp
->ni_id_res_u
.id
;
1646 return (resp
->status
);
1657 ni_proplist_res
*resp
;
1659 if ((resp
= RCALLIT(ni
, _ni_read_2
, self_id
)) == NULL
) {
1660 clnt_debug(ni
, "_ni_read");
1663 if (resp
->status
== NI_OK
) {
1664 *self_id
= resp
->ni_proplist_res_u
.stuff
.id
;
1665 *pl
= resp
->ni_proplist_res_u
.stuff
.props
;
1667 return (resp
->status
);
1675 ni_name_const pname
,
1680 ni_lookup_res
*resp
;
1681 ni_lookup_args args
;
1684 args
.key
= (ni_name
)pname
;
1685 args
.value
= (ni_name
)pval
;
1686 if ((resp
= RCALLIT(ni
, _ni_lookup_2
, &args
)) == NULL
) {
1687 clnt_debug(ni
, "_ni_lookup");
1690 if (resp
->status
== NI_OK
) {
1691 *hits
= resp
->ni_lookup_res_u
.stuff
.idlist
;
1692 *id
= resp
->ni_lookup_res_u
.stuff
.self_id
;
1694 return (resp
->status
);
1702 ni_name_const pname
,
1707 ni_proplist_res
*resp
;
1708 ni_lookup_args args
;
1711 args
.key
= (ni_name
)pname
;
1712 args
.value
= (ni_name
)pval
;
1713 if ((resp
= RCALLIT(ni
, _ni_lookupread_2
, &args
)) == NULL
) {
1714 clnt_debug(ni
, "_ni_lookupread");
1717 if (resp
->status
== NI_OK
) {
1718 *props
= resp
->ni_proplist_res_u
.stuff
.props
;
1719 *id
= resp
->ni_proplist_res_u
.stuff
.id
;
1721 return (resp
->status
);
1729 ni_name_const pname
,
1730 ni_entrylist
*entries
1737 args
.name
= (ni_name
)pname
;
1738 if ((resp
= RCALLIT(ni
, _ni_list_2
, &args
)) == NULL
) {
1739 clnt_debug(ni
, "_ni_list");
1742 if (resp
->status
== NI_OK
) {
1743 *entries
= resp
->ni_list_res_u
.stuff
.entries
;
1744 *id
= resp
->ni_list_res_u
.stuff
.self_id
;
1746 return (resp
->status
);
1754 ni_proplist_list
*entries
1757 ni_listall_res
*resp
;
1759 if ((resp
= RCALLIT(ni
, _ni_listall_2
, id
)) == NULL
) {
1760 clnt_debug(ni
, "_ni_listall");
1763 if (resp
->status
== NI_OK
) {
1764 *entries
= resp
->ni_listall_res_u
.stuff
.entries
;
1765 *id
= resp
->ni_listall_res_u
.stuff
.self_id
;
1767 return (resp
->status
);
1776 ni_namelist
*propval_p
1779 ni_namelist_res
*resp
;
1783 args
.prop_index
= which
;
1784 if ((resp
= RCALLIT(ni
, _ni_readprop_2
, &args
)) == NULL
) {
1785 clnt_debug(ni
, "_ni_readprop");
1788 if (resp
->status
== NI_OK
) {
1789 *propval_p
= resp
->ni_namelist_res_u
.stuff
.values
;
1790 *id
= resp
->ni_namelist_res_u
.stuff
.self_id
;
1792 return (resp
->status
);
1805 ni_writeprop_args args
;
1808 args
.prop_index
= which
;
1809 args
.values
= propval
;
1810 if ((resp
= WCALLIT(ni
, _ni_writeprop_2
, &args
)) == NULL
) {
1811 clnt_debug(ni
, "_ni_writeprop");
1814 if (resp
->status
== NI_OK
) {
1815 *id
= resp
->ni_id_res_u
.id
;
1817 return (resp
->status
);
1825 ni_namelist
*propnames
1828 ni_namelist_res
*resp
;
1830 if ((resp
= RCALLIT(ni
, _ni_listprops_2
, id
)) == NULL
) {
1831 clnt_debug(ni
, "_ni_listprops");
1834 if (resp
->status
== NI_OK
) {
1835 *propnames
= resp
->ni_namelist_res_u
.stuff
.values
;
1836 *id
= resp
->ni_namelist_res_u
.stuff
.self_id
;
1838 return (resp
->status
);
1851 ni_createprop_args args
;
1856 if ((resp
= WCALLIT(ni
, _ni_createprop_2
, &args
)) == NULL
) {
1857 clnt_debug(ni
, "_ni_createprop");
1860 if (resp
->status
== NI_OK
) {
1861 *id
= resp
->ni_id_res_u
.id
;
1863 return (resp
->status
);
1878 args
.prop_index
= which
;
1879 if ((resp
= WCALLIT(ni
, _ni_destroyprop_2
, &args
)) == NULL
) {
1880 clnt_debug(ni
, "_ni_destroyprop");
1883 if (resp
->status
== NI_OK
) {
1884 *id
= resp
->ni_id_res_u
.id
;
1886 return (resp
->status
);
1894 ni_index prop_index
,
1899 ni_propname_args args
;
1902 args
.prop_index
= prop_index
;
1903 args
.name
= (ni_name
)name
;
1904 if ((resp
= WCALLIT(ni
, _ni_renameprop_2
, &args
)) == NULL
) {
1905 clnt_debug(ni
, "_ni_renameprop");
1908 if (resp
->status
== NI_OK
) {
1909 *id
= resp
->ni_id_res_u
.id
;
1911 return (resp
->status
);
1919 ni_index prop_index
,
1925 ni_createname_args args
;
1928 args
.prop_index
= prop_index
;
1929 args
.name
= (ni_name
)name
;
1931 if ((resp
= WCALLIT(ni
, _ni_createname_2
, &args
)) == NULL
) {
1932 clnt_debug(ni
, "_ni_createname");
1935 if (resp
->status
== NI_OK
) {
1936 *id
= resp
->ni_id_res_u
.id
;
1938 return (resp
->status
);
1946 ni_index prop_index
,
1951 ni_nameindex_args args
;
1954 args
.prop_index
= prop_index
;
1955 args
.name_index
= name_index
;
1956 if ((resp
= WCALLIT(ni
, _ni_destroyname_2
, &args
)) == NULL
) {
1957 clnt_debug(ni
, "_ni_destroyname");
1960 if (resp
->status
== NI_OK
) {
1961 *id
= resp
->ni_id_res_u
.id
;
1963 return (resp
->status
);
1971 ni_index prop_index
,
1972 ni_index name_index
,
1977 ni_writename_args args
;
1980 args
.prop_index
= prop_index
;
1981 args
.name_index
= name_index
;
1982 args
.name
= (ni_name
)name
;
1983 if ((resp
= WCALLIT(ni
, _ni_writename_2
, &args
)) == NULL
) {
1984 clnt_debug(ni
, "_ni_writename");
1987 if (resp
->status
== NI_OK
) {
1988 *id
= resp
->ni_id_res_u
.id
;
1990 return (resp
->status
);
1998 ni_index prop_index
,
1999 ni_index name_index
,
2003 ni_readname_res
*resp
;
2004 ni_nameindex_args args
;
2007 args
.prop_index
= prop_index
;
2008 args
.name_index
= name_index
;
2009 if ((resp
= RCALLIT(ni
, _ni_readname_2
, &args
)) == NULL
) {
2010 clnt_debug(ni
, "_ni_readname");
2013 if (resp
->status
== NI_OK
) {
2014 *id
= resp
->ni_readname_res_u
.stuff
.id
;
2015 *name
= resp
->ni_readname_res_u
.stuff
.name
;
2017 return (resp
->status
);
2028 if ((resp
= (ni_status
*)RCALLIT(ni
, _ni_resync_2
, NULL
)) == NULL
) {
2047 NIP(ni
)->uid
= getuid();
2048 return (ni_setpassword(ni
, NULL
));
2051 if (ni_root(ni
, &id
) != NI_OK
) {
2054 if (ni_lookup(ni
, &id
, NAME_NAME
, NAME_USERS
, &ids
) != NI_OK
) {
2057 id
.nii_object
= ids
.niil_val
[0];
2058 ni_idlist_free(&ids
);
2060 if (ni_lookup(ni
, &id
, NAME_NAME
, user
, &ids
) != NI_OK
) {
2063 id
.nii_object
= ids
.niil_val
[0];
2064 ni_idlist_free(&ids
);
2065 if (ni_lookupprop(ni
, &id
, NAME_UID
, &nl
) != NI_OK
) {
2068 if (nl
.ninl_len
== 0) {
2071 for (p
= nl
.ninl_val
[0]; *p
; p
++) {
2073 ni_namelist_free(&nl
);
2077 NIP(ni
)->uid
= atoi(nl
.ninl_val
[0]);
2078 if (NIP(ni
)->passwd
== NULL
) {
2079 NIP(ni
)->passwd
= ni_name_dup("");
2081 createauth(NIP(ni
));
2089 ni_name_const passwd
2094 if (NIP(ni
)->passwd
!= NULL
) {
2095 ni_name_free(&NIP(ni
)->passwd
);
2097 if (passwd
== NULL
) {
2098 NIP(ni
)->passwd
= NULL
;
2099 if (NIP(ni
)->tc
!= NULL
) {
2100 auth_destroy(NIP(ni
)->tc
->cl_auth
);
2101 NIP(ni
)->tc
->cl_auth
= authnone_create();
2105 NIP(ni
)->passwd
= ni_name_dup(passwd
);
2107 * Our trivial encryption scheme
2109 for (p
= NIP(ni
)->passwd
; *p
; p
++) {
2112 createauth(NIP(ni
));
2117 extern int bindresvport(int, struct sockaddr_in
*);
2122 * The procedure pmap_getport_to below is derived
2123 * from Sun Microsystems RPC source code. As such the following
2124 * statement applies to it.:
2126 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
2127 * unrestricted use provided that this legend is included on all tape
2128 * media and as a part of the software program in whole or part. Users
2129 * may copy or modify Sun RPC without charge, but are not authorized
2130 * to license or distribute it to anyone else except as part of a product or
2131 * program developed by the user.
2133 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
2134 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
2135 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
2137 * Sun RPC is provided with no support and without any obligation on the
2138 * part of Sun Microsystems, Inc. to assist in its use, correction,
2139 * modification or enhancement.
2141 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
2142 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
2143 * OR ANY PART THEREOF.
2145 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
2146 * or profits or other special, indirect and consequential damages, even if
2147 * Sun has been advised of the possibility of such damages.
2149 * Sun Microsystems, Inc.
2150 * 2550 Garcia Avenue
2151 * Mountain View, California 94043
2154 * Client interface to pmap rpc service.
2156 * Find the mapped port for program,version.
2157 * Calls the pmap service remotely to do the lookup.
2158 * Returns 0 if no map exists.
2161 pmap_getport_to(address
, program
, version
, protocol
, timeout_secs
, ntries
)
2162 struct sockaddr_in
*address
;
2171 register CLIENT
*client
;
2173 struct timeval timeout
;
2175 sock
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
2179 address
->sin_port
= htons(PMAPPORT
);
2180 timeout
.tv_usec
= ((timeout_secs
% ntries
) * 1000000) / ntries
;
2181 timeout
.tv_sec
= (timeout_secs
/ ntries
);
2182 client
= clntudp_bufcreate(address
, PMAPPROG
,
2183 PMAPVERS
, timeout
, &sock
, RPCSMALLMSGSIZE
, RPCSMALLMSGSIZE
);
2184 if (client
!= (CLIENT
*)NULL
) {
2185 parms
.pm_prog
= program
;
2186 parms
.pm_vers
= version
;
2187 parms
.pm_prot
= protocol
;
2188 parms
.pm_port
= 0; /* not needed or used */
2189 timeout
.tv_usec
= 0;
2190 timeout
.tv_sec
= timeout_secs
;
2191 if (CLNT_CALL(client
, PMAPPROC_GETPORT
, xdr_pmap
, &parms
,
2192 xdr_u_short
, &port
, timeout
) != RPC_SUCCESS
){
2193 rpc_createerr
.cf_stat
= RPC_PMAPFAILURE
;
2194 clnt_geterr(client
, &rpc_createerr
.cf_error
);
2196 } else if (port
== 0) {
2197 rpc_createerr
.cf_stat
= RPC_PROGNOTREGISTERED
;
2200 if (client
!= NULL
) {
2201 clnt_destroy(client
);
2204 address
->sin_port
= 0;
2210 * Open a socket, but do not use the default portmap timeout
2214 struct sockaddr_in
*raddr
,
2225 * If no port number given ask the pmap for one
2227 if (raddr
->sin_port
== 0) {
2229 if ((port
= pmap_getport_to(raddr
, prog
, vers
,
2230 IPPROTO_UDP
, timeout
,
2234 raddr
->sin_port
= htons(port
);
2237 sock
= socket(AF_INET
, proto
== IPPROTO_UDP
? SOCK_DGRAM
: SOCK_STREAM
,
2242 (void)bindresvport(sock
, (struct sockaddr_in
*)0);
2243 if (proto
== IPPROTO_TCP
) {
2244 if (connect(sock
, (struct sockaddr
*)raddr
,
2245 sizeof(*raddr
)) < 0) {