2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Glues the library routines to the stub routines
27 * Copyright (C) 1989 by NeXT, Inc.
32 #include <netinfo/ni.h>
33 #include <rpc/pmap_clnt.h>
34 #include <rpc/pmap_prot.h>
40 #include "sys_interfaces.h"
42 #define LOCAL_PORT 1033
44 #define NI_TIMEOUT_SHORT 5 /* 5 second timeout for transactions */
45 #define NI_TIMEOUT_LONG 60 /* 60 second timeout for writes */
46 #define NI_TRIES 5 /* number of retries per timeout (udp only) */
47 #define NI_SLEEPTIME 4 /* 4 second sleeptime, in case of errors */
48 #define NI_MAXSLEEPTIME 64 /* 64 second max sleep time */
49 #define NI_MAXCONNTRIES 2 /* Try to form a connection twice before sleeping */
51 /* Hack for determining if an IP address is a broadcast address. -GRS */
52 /* Note that addr is network byte order (big endian) - BKM */
54 #define IS_BROADCASTADDR(addr) (((unsigned char *) &addr)[0] == 0xFF)
56 #ifndef INADDR_LOOPBACK
57 #define INADDR_LOOPBACK (u_long)0x7f000001
59 #define debug(msg) syslog(LOG_ERR, msg)
61 #define clnt_debug(ni, msg) /* do nothing */
63 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 static const ni_name NAME_NAME
= "name";
84 static const ni_name NAME_SERVES
= "serves";
85 static const ni_name NAME_MACHINES
= "machines";
86 static const ni_name NAME_IP_ADDRESS
= "ip_address";
87 static const ni_name NAME_MASTER
= "master";
88 static const ni_name NAME_USERS
= "users";
89 static const ni_name NAME_UID
= "uid";
91 static const ni_name NAME_DOMAIN_SERVERS
= "domain_servers";
93 typedef struct getreg_stuff
{
94 nibind_getregister_res res
;
99 static int socket_open(struct sockaddr_in
*raddr
, int, int, int, int, int);
103 * Keep track of our port, in case somebody closes our socket
111 struct sockaddr_in sin
;
114 sinlen
= sizeof(sin
);
115 if (getsockname(sock
, (struct sockaddr
*)&sin
, &sinlen
) == 0) {
116 if (sin
.sin_port
== 0) {
117 (void)bind(sock
, (struct sockaddr
*)&sin
, sizeof(sin
));
118 sinlen
= sizeof(sin
);
119 (void)getsockname(sock
, (struct sockaddr
*)&sin
,
122 return (ntohs(sin
.sin_port
));
133 if (ni
->passwd
!= NULL
&& ni
->tc
!= NULL
) {
134 auth_destroy(ni
->tc
->cl_auth
);
135 ni
->tc
->cl_auth
= authunix_create(ni
->passwd
, ni
->uid
, 0, 0,
148 tv
->tv_sec
= sec
/ tries
;
149 tv
->tv_usec
= ((sec
% tries
) * 1000000) / tries
;
163 ni
->tv_sec
= timeout
;
164 if (ni
->tc
!= NULL
) {
165 clnt_control(ni
->tc
, CLSET_TIMEOUT
, &tv
);
171 * Connect to a given address/tag
174 connectit(ni_private
*ni
)
176 struct sockaddr_in sin
;
181 nibind_getregister_res res
;
184 bzero(&sin
, sizeof(sin
));
186 sin
.sin_family
= AF_INET
;
188 tv
.tv_sec
= ni
->rtv_sec
== 0 ? NI_TIMEOUT_SHORT
: ni
->rtv_sec
;
191 ni_settimeout(ni
, tv
.tv_sec
);
192 fixtimeout(&tv
, ni
->tv_sec
, NI_TRIES
);
195 * If connecting to local domain, try using the "well-known" port first.
197 if (!strcmp(ni
->tags
[0], "local"))
199 interface_list_t
*ilist
;
201 ilist
= sys_interfaces();
202 if (sys_is_my_address(ilist
, &ni
->addrs
[0]))
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
);
208 sys_interfaces_release(ilist
);
212 * If connecting to a domain other than the local domain,
213 * or if connection to local didn't work with local's well-known port,
214 * then go through portmap & nibindd to find the port and connect.
219 sin
.sin_addr
= ni
->addrs
[0];
221 sock
= socket_open(&sin
, NIBIND_PROG
, NIBIND_VERS
, ni
->tv_sec
, NI_TRIES
, IPPROTO_UDP
);
222 if (sock
< 0) return (0);
224 cl
= clntudp_create(&sin
, NIBIND_PROG
, NIBIND_VERS
, tv
, &sock
);
231 tv
.tv_sec
= ni
->rtv_sec
== 0 ? NI_TIMEOUT_SHORT
: ni
->rtv_sec
;
234 stat
= clnt_call(cl
, NIBIND_GETREGISTER
, xdr_ni_name
, &ni
->tags
[0], xdr_nibind_getregister_res
, &res
, tv
);
237 if (stat
!= RPC_SUCCESS
|| res
.status
!= NI_OK
) return (0);
239 sin
.sin_port
= htons(res
.nibind_getregister_res_u
.addrs
.tcp_port
);
240 sock
= socket_open(&sin
, NI_PROG
, NI_VERS
, ni
->tv_sec
, NI_TRIES
, IPPROTO_TCP
);
243 if (sock
< 0) return (0);
245 cl
= clnttcp_create(&sin
, NI_PROG
, NI_VERS
, &sock
, 0, 0);
252 clnt_control(cl
, CLSET_TIMEOUT
, &tv
);
255 ni
->tport
= getmyport(sock
);
257 fcntl(ni
->tsock
, F_SETFD
, 1);
268 ((ni_private
*)ni
)->abort
= abort
;
278 ((ni_private
*)ni
)->wtv_sec
= timeout
;
288 ((ni_private
*)ni
)->rtv_sec
= timeout
;
298 ((ni_private
*)ni
)->needwrite
= needwrite
;
303 * Returns a client handle to the NetInfo server, if it's running
306 connectlocal(ni_private
*ni
)
311 ni
->addrs
= (struct in_addr
*)malloc(sizeof(struct in_addr
));
312 ni
->addrs
[0].s_addr
= htonl(INADDR_LOOPBACK
);
313 ni
->tags
= (ni_name
*)malloc(sizeof(ni_name
));
314 ni
->tags
[0] = ni_name_dup("local");
317 while (!connectit(ni
))
321 syslog(LOG_ERR
, "NetInfo timeout connecting to local domain, sleeping");
331 syslog(LOG_ERR
, "NetInfo connection to local domain waking");
339 * Destroy the client handle
350 if (sock
>= 0 && getmyport(sock
) != port
) {
352 * Somebody else has the descriptor open. Do not close it,
358 auth_destroy(cl
->cl_auth
);
363 * It's ours and we can close it
371 * Reinitialize everything
378 if (ni
->tc
!= NULL
) {
379 clnt_kill(ni
->tc
, ni
->tsock
, ni
->tport
);
389 * Switch to a new server
397 struct in_addr tmp_addr
;
404 tmp_addr
= ni
->addrs
[0];
405 tmp_tag
= ni
->tags
[0];
407 ni
->addrs
[0] = ni
->addrs
[which
];
408 ni
->tags
[0] = ni
->tags
[which
];
410 ni
->addrs
[which
] = tmp_addr
;
411 ni
->tags
[which
] = tmp_tag
;
413 if (ni
->whichwrite
== 0) {
414 ni
->whichwrite
= which
;
416 else if (ni
->whichwrite
== which
) {
423 * Swap two servers' positions
432 struct in_addr tmp_addr
;
437 tmp_addr
= ni
->addrs
[a
];
438 tmp_tag
= ni
->tags
[a
];
440 ni
->addrs
[a
] = ni
->addrs
[b
];
441 ni
->tags
[a
] = ni
->tags
[b
];
443 ni
->addrs
[b
] = tmp_addr
;
444 ni
->tags
[b
] = tmp_tag
;
446 if (ni
->whichwrite
== a
) {
449 else if (ni
->whichwrite
== b
) {
456 * Callback routine for multi_call
457 * XXX: should save returned port numbers
462 struct sockaddr_in
*sin
,
466 getreg_stuff
*stuff
= (getreg_stuff
*)vstuff
;
468 if (stuff
->res
.status
!= NI_OK
) {
471 ni_switch(stuff
->ni
, which
);
480 shuffle(ni_private
*ni
)
486 if (ni
->naddrs
<= 1) return;
488 rfd
= open("/dev/random", O_RDONLY
, 0);
489 shuffle
= (int *)malloc(ni
->naddrs
* sizeof(int));
490 for (i
= 0; i
< ni
->naddrs
; i
++) shuffle
[i
] = i
;
491 for (i
= 0, j
= ni
->naddrs
; j
> 0; i
++, j
--) {
496 /* get a random number */
498 (read(rfd
, &rVal
, sizeof(rVal
)) != sizeof(rVal
))) {
499 /* if we could not read from /dev/random */
500 static int initialized
= 0;
503 srandom(gethostid() ^ time(NULL
));
509 rEnt
= (unsigned int)rVal
% j
; /* pick one of the remaining entries */
510 tEnt
= shuffle
[rEnt
]; /* grab the random entry */
511 shuffle
[rEnt
] = shuffle
[j
-1]; /* the last entry moves to the random slot */
512 shuffle
[j
-1] = tEnt
; /* the last slot gets the random entry */
513 ni_swap(ni
, rEnt
, j
-1); /* and swap the actual NI addresses */
516 if (rfd
> 0) (void)close(rfd
);
528 int sleeptime
= NI_SLEEPTIME
;
532 interface_list_t
*ilist
;
535 if (ni
->naddrs
== 1) {
542 * re-order the servers so that:
543 * servers on the local host are at the start of the list, then
544 * servers on the local network are next, then
545 * all other servers are next
548 ilist
= sys_interfaces();
556 * move local servers to the head of the list
559 for (i
= nlocal
; i
< ni
->naddrs
; i
++) {
560 if (sys_is_my_address(ilist
, &ni
->addrs
[i
]))
562 ni_swap(ni
, nlocal
, i
);
568 * move servers on this network to follow local servers
571 for (i
= nnetwork
; i
< ni
->naddrs
; i
++) {
572 if (sys_is_my_network(ilist
, &ni
->addrs
[i
]) ||
573 IS_BROADCASTADDR(ni
->addrs
[i
].s_addr
))
575 ni_swap(ni
, nnetwork
, i
);
580 sys_interfaces_release(ilist
);
585 * call local servers first
588 for (i
= 0; i
< nlocal
; i
++) {
589 syslog(LOG_DEBUG
, "NetInfo connect call to: %s/%s (local %d)",
590 inet_ntoa(ni
->addrs
[i
]), ni
->tags
[i
], i
);
592 stat
= multi_call(nlocal
, ni
->addrs
,
593 NIBIND_PROG
, NIBIND_VERS
, NIBIND_GETREGISTER
,
594 xdr_ni_name
, ni
->tags
,
596 xdr_nibind_getregister_res
,
599 if (stat
== RPC_SUCCESS
) {
605 * call local servers and this network's servers
607 if (nnetwork
> nlocal
) {
608 for (i
= 0; i
< nnetwork
; i
++) {
609 syslog(LOG_DEBUG
, "NetInfo connect call to: %s/%s (network %d)",
610 inet_ntoa(ni
->addrs
[i
]), ni
->tags
[i
], i
);
612 stat
= multi_call(nnetwork
, ni
->addrs
,
613 NIBIND_PROG
, NIBIND_VERS
, NIBIND_GETREGISTER
,
614 xdr_ni_name
, ni
->tags
,
616 xdr_nibind_getregister_res
,
619 if (stat
== RPC_SUCCESS
) {
627 for (i
= 0; i
< ni
->naddrs
; i
++) {
628 syslog(LOG_DEBUG
, "NetInfo connect call to: %s/%s (world %d)",
629 inet_ntoa(ni
->addrs
[i
]), ni
->tags
[i
], i
);
631 stat
= multi_call(ni
->naddrs
,
632 ni
->addrs
, NIBIND_PROG
, NIBIND_VERS
,
634 xdr_ni_name
, ni
->tags
,
636 xdr_nibind_getregister_res
,
638 ni
->rtv_sec
== 0 ? NI_TIMEOUT_SHORT
: ni
->rtv_sec
);
639 if (stat
== RPC_SUCCESS
) {
647 if (ni
->whichwrite
>= 0) {
649 "NetInfo connect timeout (domain with master %s/%s), sleeping",
650 inet_ntoa(ni
->addrs
[ni
->whichwrite
]), ni
->tags
[ni
->whichwrite
]);
653 syslog(LOG_ERR
, "NetInfo connect timeout (domain with server %s/%s), sleeping",
654 inet_ntoa(ni
->addrs
[0]), ni
->tags
[0]);
659 if (sleeptime
< NI_MAXSLEEPTIME
) {
660 sleeptime
*= 2; /* backoff */
664 syslog(LOG_INFO
, "NetInfo connected to %s/%s", inet_ntoa(ni
->addrs
[0]), ni
->tags
[0]);
667 syslog(LOG_ERR
, "NetInfo connected to %s/%s", inet_ntoa(ni
->addrs
[0]), ni
->tags
[0]);
674 * Confirm that our tcp socket is still valid
682 if (ni
->tsock
!= -1) {
683 if (getmyport(ni
->tsock
) == ni
->tport
) {
687 * Somebody closed our socket. Do not close it, it could
688 * be owned by somebody else now.
692 if (ni
->tc
->cl_auth
!= NULL
) auth_destroy(ni
->tc
->cl_auth
);
693 clnt_destroy(ni
->tc
);
697 if (!needwrite
&& !rebind(ni
) && ni
->abort
) {
700 return (connectit(ni
));
720 if (ni
->naddrs
== 1) {
722 * One server - must be the master
727 needwrite
= ni
->needwrite
;
729 if (ni_root(ni
, &root
) != NI_OK
) {
730 ni
->needwrite
= needwrite
;
734 if (ni_lookupprop(ni
, &root
, NAME_MASTER
, &nl
) != NI_OK
) {
735 ni
->needwrite
= needwrite
;
738 if (nl
.ninl_len
== 0) {
739 ni
->needwrite
= needwrite
;
742 sep
= index(nl
.ninl_val
[0], '/');
744 ni
->needwrite
= needwrite
;
748 master
= nl
.ninl_val
[0];
750 if (ni_lookup(ni
, &root
, NAME_NAME
, NAME_MACHINES
, &idl
) != NI_OK
) {
751 ni
->needwrite
= needwrite
;
752 ni_namelist_free(&nl
);
755 if (idl
.niil_len
< 1) {
756 ni
->needwrite
= needwrite
;
759 id
.nii_object
= idl
.niil_val
[0];
760 ni_idlist_free(&idl
);
762 if (ni_lookup(ni
, &id
, NAME_NAME
, master
, &idl
) != NI_OK
) {
763 ni_namelist_free(&nl
);
764 ni
->needwrite
= needwrite
;
767 ni_namelist_free(&nl
);
768 if (idl
.niil_len
< 1) {
769 ni
->needwrite
= needwrite
;
772 id
.nii_object
= idl
.niil_val
[0];
773 ni_idlist_free(&idl
);
775 if (ni_lookupprop(ni
, &id
, NAME_IP_ADDRESS
, &nl
) != NI_OK
) {
778 for (i
= 0; i
< nl
.ninl_len
; i
++) {
779 addr
.s_addr
= inet_addr(nl
.ninl_val
[i
]);
780 for (j
= 0; j
< ni
->naddrs
; j
++) {
781 if (addr
.s_addr
== ni
->addrs
[j
].s_addr
) {
783 ni_namelist_free(&nl
);
784 ni
->needwrite
= needwrite
;
789 ni
->needwrite
= needwrite
;
790 ni_namelist_free(&nl
);
809 if (getpid() != ni
->pid
) {
812 if (needwrite
|| ni
->needwrite
) {
813 if (ni
->whichwrite
>= 0) {
814 ni_switch(ni
, ni
->whichwrite
);
816 if (!setmaster(ni
)) {
819 ni_switch(ni
, ni
->whichwrite
);
822 ni_settimeout(ni
, (ni
->rtv_sec
== 0 ?
823 NI_TIMEOUT_SHORT
: ni
->rtv_sec
));
826 ni_settimeout(ni
, (ni
->wtv_sec
== 0 ?
827 NI_TIMEOUT_LONG
: ni
->wtv_sec
));
830 ni_settimeout(ni
, (ni
->rtv_sec
== 0 ?
831 NI_TIMEOUT_SHORT
: ni
->rtv_sec
));
835 * Try more than once, in case server closed connection.
837 for (i
= 0; i
< NI_MAXCONNTRIES
; i
++) {
838 if (!confirm_tcp(ni
, needwrite
)) {
841 if ((resp
= (*stub
)(args
, ni
->tc
)) != NULL
) {
843 syslog(LOG_ERR
, "NetInfo connected to %s/%s",
844 inet_ntoa(ni
->addrs
[0]), ni
->tags
[0]);
850 clnt_geterr(ni
->tc
, &err
);
851 if (err
.re_status
!= RPC_CANTRECV
) break;
853 if (i
+ 1 < NI_MAXCONNTRIES
) {
855 * Server closed connection. Reinit and try
861 if (err
.re_status
== RPC_PROCUNAVAIL
) {
864 if (needwrite
|| ni
->abort
) {
866 * We time out for writes or if it is explicitly
873 "NetInfo connection failed for server %s/%s",
874 inet_ntoa(ni
->addrs
[0]), ni
->tags
[0]);
878 if (ni
->tc
!= NULL
) {
879 if (!(sleeptime
== 0 &&
880 err
.re_status
== RPC_TIMEDOUT
)) {
882 * Do not print message on
883 * first timeout. It is likely
884 * we will find another server soon.
885 * Let's not needlessly alarm the
888 syslog(LOG_ERR
, "%s on connection to %s/%s",
889 clnt_sperror(ni
->tc
,"NetInfo connection timeout"),
890 inet_ntoa(ni
->addrs
[0]), ni
->tags
[0]);
894 /* first attempt failed */
895 syslog(LOG_ERR
, "%s on initial connection to %s/%s",
896 clnt_sperror(ni
->tc
,"NetInfo connection timeout"),
897 inet_ntoa(ni
->addrs
[0]), ni
->tags
[0]);
901 "NetInfo connection failed for server %s/%s",
902 inet_ntoa(ni
->addrs
[0]), ni
->tags
[0]);
908 if (sleeptime
< NI_MAXSLEEPTIME
) {
909 sleeptime
*= 2; /* backoff */
913 * Do not sleep on the first timeout.
914 * It is likely we will find another server quickly.
916 sleeptime
= NI_SLEEPTIME
;
924 #define RCALLIT(a, b, c) callit((ni_private *)(a), (void *(*)())(b), \
928 #define WCALLIT(a, b, c) callit((ni_private *)(a), (void *(*)())(b), \
956 ni
= (ni_private
*)malloc(sizeof(*ni
));
963 ni
->tv_sec
= NI_TIMEOUT_SHORT
;
982 dupni
= (ni_private
*)ni_alloc();
985 dupni
->naddrs
= NIP(ni
)->naddrs
;
986 dupni
->whichwrite
= NIP(ni
)->whichwrite
;
987 if (dupni
->naddrs
> 0) {
988 dupni
->addrs
= ((struct in_addr
*)
989 malloc(NIP(ni
)->naddrs
* sizeof(struct in_addr
)));
990 bcopy(NIP(ni
)->addrs
, dupni
->addrs
,
991 NIP(ni
)->naddrs
* sizeof(struct in_addr
));
992 dupni
->tags
= ((ni_name
*)
993 malloc(NIP(ni
)->naddrs
* sizeof(ni_name
)));
994 for (i
= 0; i
< NIP(ni
)->naddrs
; i
++) {
995 dupni
->tags
[i
] = ni_name_dup(NIP(ni
)->tags
[i
]);
998 if (NIP(ni
)->passwd
!= NULL
) {
999 dupni
->passwd
= ni_name_dup(NIP(ni
)->passwd
);
1001 return ((void *)dupni
);
1012 int len
= strlen(domain
);
1015 sep
= index(domtag
, '/');
1019 if (strncmp(domain
, domtag
, len
) == 0 &&
1020 domtag
[len
] == '/') {
1021 *tag
= ni_name_dup(sep
+ 1);
1029 add_addr_tag(ni_private
*ni
, ni_name addrtag
)
1031 struct in_addr addr
;
1035 slash
= strchr(addrtag
, '/');
1036 if (slash
== NULL
) return;
1039 if (tag
[0] == '\0') return;
1043 if (inet_aton(addrtag
, &addr
) == 0) return;
1045 if (ni
->naddrs
== 0)
1047 ni
->addrs
= (struct in_addr
*)calloc(1, sizeof(struct in_addr
));
1048 if (ni
->addrs
== NULL
) return;
1050 ni
->tags
= (ni_name
*)calloc(1, sizeof(ni_name
));
1051 if (ni
->tags
== NULL
) return;
1055 ni
->addrs
= (struct in_addr
*)realloc(ni
->addrs
, ((ni
->naddrs
+ 1) * sizeof(struct in_addr
)));
1056 if (ni
->addrs
== NULL
) return;
1058 ni
->tags
= (ni_name
*)realloc(ni
->tags
, ((ni
->naddrs
+ 1) * sizeof(ni_name
)));
1059 if (ni
->tags
== NULL
) return;
1062 ni
->addrs
[ni
->naddrs
] = addr
;
1063 ni
->tags
[ni
->naddrs
] = ni_name_dup(tag
);
1068 addaddr(void *ni
, ni_index ido
, ni_name tag
, ni_private
*target_ni
)
1072 struct in_addr addr
;
1075 id
.nii_object
= ido
;
1077 if (ni_lookupprop(ni
, &id
, NAME_IP_ADDRESS
, &nl
) != NI_OK
) return 0;
1079 if (nl
.ni_namelist_len
== 0) return 0;
1081 if (target_ni
->naddrs
== 0)
1083 target_ni
->addrs
= (struct in_addr
*)malloc(nl
.ni_namelist_len
* sizeof(struct in_addr
));
1084 target_ni
->tags
= (ni_name
*)malloc(nl
.ni_namelist_len
* sizeof(ni_name
));
1088 target_ni
->addrs
= (struct in_addr
*)realloc(target_ni
->addrs
, ((target_ni
->naddrs
+ nl
.ni_namelist_len
) * sizeof(struct in_addr
)));
1089 target_ni
->tags
= (ni_name
*)realloc(target_ni
->tags
, ((target_ni
->naddrs
+ nl
.ni_namelist_len
) * sizeof(ni_name
)));
1092 for (i
= 0; i
< nl
.ni_namelist_len
; i
++)
1094 addr
.s_addr
= inet_addr(nl
.ni_namelist_val
[i
]);
1095 target_ni
->addrs
[target_ni
->naddrs
] = addr
;
1096 target_ni
->tags
[target_ni
->naddrs
] = ni_name_dup(tag
);
1097 target_ni
->naddrs
++;
1100 ni_namelist_free(&nl
);
1105 get_daddr(ni_private
*ni
, ni_name dom
, ni_private
*target_ni
)
1109 ni_entrylist entries
;
1115 if (dom
== NULL
) return 0;
1117 if (!strcmp(dom
, "."))
1119 /* check for server list */
1121 if (ni_statistics(ni
, &pl
) == NI_OK
)
1123 i
= ni_proplist_match(pl
, NAME_DOMAIN_SERVERS
, NULL
);
1124 if (i
!= NI_INDEX_NULL
)
1126 if (pl
.ni_proplist_val
[i
].nip_val
.ni_namelist_len
> 0)
1128 for (j
= 0; j
< pl
.ni_proplist_val
[i
].nip_val
.ni_namelist_len
; j
++)
1130 add_addr_tag(target_ni
, pl
.ni_proplist_val
[i
].nip_val
.ni_namelist_val
[j
]);
1132 ni_proplist_free(&pl
);
1136 ni_proplist_free(&pl
);
1140 if (ni_root(ni
, &nid
) != NI_OK
) return 0;
1142 if (ni_lookup(ni
, &nid
, NAME_NAME
, NAME_MACHINES
, &ids
) != NI_OK
) return 0;
1144 nid
.nii_object
= ids
.niil_val
[0];
1145 ni_idlist_free(&ids
);
1148 if (ni_list(ni
, &nid
, NAME_SERVES
, &entries
) != NI_OK
) return 0;
1150 for (i
= 0; i
< entries
.niel_len
; i
++)
1152 if (entries
.niel_val
[i
].names
== NULL
) continue;
1154 for (j
= 0; j
< entries
.niel_val
[i
].names
->ni_namelist_len
; j
++)
1156 if (match(dom
, entries
.niel_val
[i
].names
->ni_namelist_val
[j
], &tag
))
1158 addaddr(ni
, entries
.niel_val
[i
].id
, tag
, target_ni
);
1164 ni_entrylist_free(&entries
);
1165 return (target_ni
->naddrs
> 0);
1169 getparent(ni_private
*oldni
, ni_private
**newni
)
1171 ni_rparent_res
*resp
;
1172 ni_private
*ni
= NULL
;
1176 struct in_addr raddr
;
1183 * First, find our parent, any parent
1187 resp
= RCALLIT(oldni
, _ni_rparent_2
, NULL
);
1188 if (resp
== NULL
) return NI_FAILED
;
1189 if (resp
->status
!= NI_NORESPONSE
) break;
1193 syslog(LOG_ERR
, "NetInfo timeout finding server for parent of %s/%s, sleeping",
1194 inet_ntoa(oldni
->addrs
[0]), oldni
->tags
[0]);
1198 sleep(NI_SLEEPTIME
);
1203 raddr
.s_addr
= htonl(resp
->ni_rparent_res_u
.binding
.addr
);
1205 syslog(LOG_ERR
, "NetInfo %s/%s found parent %s/%s",
1206 inet_ntoa(oldni
->addrs
[0]), oldni
->tags
[0],
1207 inet_ntoa(raddr
), resp
->ni_rparent_res_u
.binding
.tag
);
1210 if (resp
->status
!= NI_OK
) return (resp
->status
);
1216 ni
->addrs
= (struct in_addr
*)malloc(sizeof(struct in_addr
));
1217 ni
->addrs
[0].s_addr
=htonl(resp
->ni_rparent_res_u
.binding
.addr
);
1218 ni
->tags
= (ni_name
*)malloc(sizeof(ni_name
));
1219 ni
->tags
[0] = ni_name_dup(resp
->ni_rparent_res_u
.binding
.tag
);
1221 xdr_free(xdr_ni_rparent_res
, resp
);
1227 if (get_daddr(dupni
, ".", ni
) == 0)
1229 if (oldni
->abort
== 1)
1238 * Make sure returned parent is head of list
1240 for (i
= 0; i
< ni
->naddrs
; i
++)
1242 if (ni
->addrs
[i
].s_addr
== dupni
->addrs
[0].s_addr
)
1251 * Reuse dupni client info
1253 ni
->tsock
= dupni
->tsock
;
1254 ni
->tport
= dupni
->tport
;
1262 * If returned parent wasn't in list, it's a rogue.
1263 * Log an error and drop the connection.
1267 syslog(LOG_ERR
, "Rogue NetInfo server detected: %s/%s",
1268 inet_ntoa(dupni
->addrs
[0]), dupni
->tags
[0]);
1282 if (ni
!= NULL
) ni_free(ni
);
1289 struct sockaddr_in
*sin
,
1296 NIP(ni
)->naddrs
= 1;
1297 NIP(ni
)->addrs
= (struct in_addr
*
1298 )malloc(sizeof(struct in_addr
));
1299 NIP(ni
)->addrs
[0] = sin
->sin_addr
;
1300 NIP(ni
)->tags
= (ni_name
*)malloc(sizeof(ni_name
));
1301 NIP(ni
)->tags
[0] = ni_name_dup(tag
);
1309 struct sockaddr_in
*addr
,
1314 if (!confirm_tcp(ni
, 0)) {
1317 *tag
= ni_name_dup(NIP(ni
)->tags
[0]);
1318 addr
->sin_addr
= NIP(ni
)->addrs
[0];
1319 addr
->sin_port
= htons(NIP(ni
)->tport
);
1320 addr
->sin_family
= AF_INET
;
1321 bzero(addr
->sin_zero
, sizeof(addr
->sin_zero
));
1327 ni_new(void *oldni
, const char *domain
)
1331 ni_name sep
, addr
, tag
;
1332 struct sockaddr_in sin
;
1335 if (domain
== NULL
) return NULL
;
1337 sep
= index(domain
, '@');
1340 tag
= strncpy((char *)malloc(sep
- domain
+ 1), domain
, sep
- domain
);
1341 tag
[sep
- domain
] = '\0';
1342 addr
= strcpy ((char *)malloc(strlen(sep
+ 1)), sep
+ 1);
1343 sin
.sin_addr
.s_addr
= inet_addr(addr
);
1344 if (sin
.sin_addr
.s_addr
== INADDR_NONE
)
1346 he
= gethostbyname(addr
);
1354 bcopy(he
->h_addr_list
[0], &sin
.sin_addr
.s_addr
, he
->h_length
);
1357 ni
= ni_connect(&sin
, tag
);
1369 if (connectlocal(ni
) == 0)
1375 if (strcmp(domain
, ".") == 0) return (void *)ni
;
1377 if (strcmp(domain
, "..") == 0)
1380 status
= getparent((ni_private
*)oldni
, &ni
);
1382 if (status
!= NI_OK
) return NULL
;
1390 if (strcmp(domain
, "..") == 0)
1392 status
= getparent((ni_private
*)oldni
, &ni
);
1393 if (status
!= NI_OK
) return NULL
;
1400 if (!get_daddr(oldni
, (ni_name
)domain
, ni
))
1417 if (NIP(ni
)->tc
!= NULL
) {
1418 clnt_kill(NIP(ni
)->tc
, NIP(ni
)->tsock
, NIP(ni
)->tport
);
1420 if (NIP(ni
)->naddrs
> 0) {
1421 free(NIP(ni
)->addrs
);
1422 for (i
= 0; i
< NIP(ni
)->naddrs
; i
++) {
1423 ni_name_free(&NIP(ni
)->tags
[i
]);
1425 free(NIP(ni
)->tags
);
1427 if (NIP(ni
)->passwd
!= NULL
) {
1428 ni_name_free(&NIP(ni
)->passwd
);
1435 * The rest of these are just wrappers that end up doing
1436 * RPC calls to the local NetInfo server.
1446 if ((resp
= (ni_proplist
*)RCALLIT(ni
, _ni_statistics_2
, NULL
))
1463 if ((resp
= RCALLIT(ni
, _ni_root_2
, id
)) == NULL
) {
1464 clnt_debug(ni
, "_ni_root");
1467 if (resp
->status
== NI_OK
) {
1468 *id
= resp
->ni_id_res_u
.id
;
1470 return (resp
->status
);
1482 if ((resp
= RCALLIT(ni
, _ni_self_2
, id
)) == NULL
) {
1483 clnt_debug(ni
, "_ni_self");
1486 if (resp
->status
== NI_OK
) {
1487 *id
= resp
->ni_id_res_u
.id
;
1489 return (resp
->status
);
1497 ni_index
*parent_id_p
1500 ni_parent_res
*resp
;
1502 if ((resp
= RCALLIT(ni
, _ni_parent_2
, id
)) == NULL
) {
1503 clnt_debug(ni
, "_ni_parent");
1506 if (resp
->status
== NI_OK
) {
1507 *parent_id_p
= resp
->ni_parent_res_u
.stuff
.object_id
;
1508 *id
= resp
->ni_parent_res_u
.stuff
.self_id
;
1510 return (resp
->status
);
1521 ni_children_res
*resp
;
1523 if ((resp
= RCALLIT(ni
, _ni_children_2
, id
)) == NULL
) {
1524 clnt_debug(ni
, "_ni_children");
1527 if (resp
->status
== NI_OK
) {
1528 *children
= resp
->ni_children_res_u
.stuff
.children
;
1529 *id
= resp
->ni_children_res_u
.stuff
.self_id
;
1531 return (resp
->status
);
1544 ni_create_args args
;
1545 ni_create_res
*resp
;
1547 args
.id
= *parent_id
;
1550 args
.target_id
= NULL
;
1551 if ((resp
= WCALLIT(ni
, _ni_create_2
, &args
)) == NULL
) {
1552 clnt_debug(ni
, "_ni_create");
1555 if (resp
->status
== NI_OK
) {
1556 *child_id_p
= resp
->ni_create_res_u
.stuff
.id
;
1557 *parent_id
= resp
->ni_create_res_u
.stuff
.self_id
;
1559 return (resp
->status
);
1571 ni_destroy_args args
;
1573 args
.parent_id
= *parent_id
;
1574 args
.self_id
= self_id
;
1575 if ((resp
= WCALLIT(ni
, _ni_destroy_2
, &args
)) == NULL
) {
1576 clnt_debug(ni
, "_ni_destroy");
1579 if (resp
->status
== NI_OK
) {
1580 *parent_id
= resp
->ni_id_res_u
.id
;
1582 return (resp
->status
);
1593 ni_proplist_stuff args
;
1598 if ((resp
= WCALLIT(ni
, _ni_write_2
, &args
)) == NULL
) {
1599 clnt_debug(ni
, "_ni_write");
1602 if (resp
->status
== NI_OK
) {
1603 *self_id
= resp
->ni_id_res_u
.id
;
1605 return (resp
->status
);
1616 ni_proplist_res
*resp
;
1618 if ((resp
= RCALLIT(ni
, _ni_read_2
, self_id
)) == NULL
) {
1619 clnt_debug(ni
, "_ni_read");
1622 if (resp
->status
== NI_OK
) {
1623 *self_id
= resp
->ni_proplist_res_u
.stuff
.id
;
1624 *pl
= resp
->ni_proplist_res_u
.stuff
.props
;
1626 return (resp
->status
);
1634 ni_name_const pname
,
1639 ni_lookup_res
*resp
;
1640 ni_lookup_args args
;
1643 args
.key
= (ni_name
)pname
;
1644 args
.value
= (ni_name
)pval
;
1645 if ((resp
= RCALLIT(ni
, _ni_lookup_2
, &args
)) == NULL
) {
1646 clnt_debug(ni
, "_ni_lookup");
1649 if (resp
->status
== NI_OK
) {
1650 *hits
= resp
->ni_lookup_res_u
.stuff
.idlist
;
1651 *id
= resp
->ni_lookup_res_u
.stuff
.self_id
;
1653 return (resp
->status
);
1661 ni_name_const pname
,
1666 ni_proplist_res
*resp
;
1667 ni_lookup_args args
;
1670 args
.key
= (ni_name
)pname
;
1671 args
.value
= (ni_name
)pval
;
1672 if ((resp
= RCALLIT(ni
, _ni_lookupread_2
, &args
)) == NULL
) {
1673 clnt_debug(ni
, "_ni_lookupread");
1676 if (resp
->status
== NI_OK
) {
1677 *props
= resp
->ni_proplist_res_u
.stuff
.props
;
1678 *id
= resp
->ni_proplist_res_u
.stuff
.id
;
1680 return (resp
->status
);
1688 ni_name_const pname
,
1689 ni_entrylist
*entries
1696 args
.name
= (ni_name
)pname
;
1697 if ((resp
= RCALLIT(ni
, _ni_list_2
, &args
)) == NULL
) {
1698 clnt_debug(ni
, "_ni_list");
1701 if (resp
->status
== NI_OK
) {
1702 *entries
= resp
->ni_list_res_u
.stuff
.entries
;
1703 *id
= resp
->ni_list_res_u
.stuff
.self_id
;
1705 return (resp
->status
);
1713 ni_proplist_list
*entries
1716 ni_listall_res
*resp
;
1718 if ((resp
= RCALLIT(ni
, _ni_listall_2
, id
)) == NULL
) {
1719 clnt_debug(ni
, "_ni_listall");
1722 if (resp
->status
== NI_OK
) {
1723 *entries
= resp
->ni_listall_res_u
.stuff
.entries
;
1724 *id
= resp
->ni_listall_res_u
.stuff
.self_id
;
1726 return (resp
->status
);
1735 ni_namelist
*propval_p
1738 ni_namelist_res
*resp
;
1742 args
.prop_index
= which
;
1743 if ((resp
= RCALLIT(ni
, _ni_readprop_2
, &args
)) == NULL
) {
1744 clnt_debug(ni
, "_ni_readprop");
1747 if (resp
->status
== NI_OK
) {
1748 *propval_p
= resp
->ni_namelist_res_u
.stuff
.values
;
1749 *id
= resp
->ni_namelist_res_u
.stuff
.self_id
;
1751 return (resp
->status
);
1764 ni_writeprop_args args
;
1767 args
.prop_index
= which
;
1768 args
.values
= propval
;
1769 if ((resp
= WCALLIT(ni
, _ni_writeprop_2
, &args
)) == NULL
) {
1770 clnt_debug(ni
, "_ni_writeprop");
1773 if (resp
->status
== NI_OK
) {
1774 *id
= resp
->ni_id_res_u
.id
;
1776 return (resp
->status
);
1784 ni_namelist
*propnames
1787 ni_namelist_res
*resp
;
1789 if ((resp
= RCALLIT(ni
, _ni_listprops_2
, id
)) == NULL
) {
1790 clnt_debug(ni
, "_ni_listprops");
1793 if (resp
->status
== NI_OK
) {
1794 *propnames
= resp
->ni_namelist_res_u
.stuff
.values
;
1795 *id
= resp
->ni_namelist_res_u
.stuff
.self_id
;
1797 return (resp
->status
);
1810 ni_createprop_args args
;
1815 if ((resp
= WCALLIT(ni
, _ni_createprop_2
, &args
)) == NULL
) {
1816 clnt_debug(ni
, "_ni_createprop");
1819 if (resp
->status
== NI_OK
) {
1820 *id
= resp
->ni_id_res_u
.id
;
1822 return (resp
->status
);
1837 args
.prop_index
= which
;
1838 if ((resp
= WCALLIT(ni
, _ni_destroyprop_2
, &args
)) == NULL
) {
1839 clnt_debug(ni
, "_ni_destroyprop");
1842 if (resp
->status
== NI_OK
) {
1843 *id
= resp
->ni_id_res_u
.id
;
1845 return (resp
->status
);
1853 ni_index prop_index
,
1858 ni_propname_args args
;
1861 args
.prop_index
= prop_index
;
1862 args
.name
= (ni_name
)name
;
1863 if ((resp
= WCALLIT(ni
, _ni_renameprop_2
, &args
)) == NULL
) {
1864 clnt_debug(ni
, "_ni_renameprop");
1867 if (resp
->status
== NI_OK
) {
1868 *id
= resp
->ni_id_res_u
.id
;
1870 return (resp
->status
);
1878 ni_index prop_index
,
1884 ni_createname_args args
;
1887 args
.prop_index
= prop_index
;
1888 args
.name
= (ni_name
)name
;
1890 if ((resp
= WCALLIT(ni
, _ni_createname_2
, &args
)) == NULL
) {
1891 clnt_debug(ni
, "_ni_createname");
1894 if (resp
->status
== NI_OK
) {
1895 *id
= resp
->ni_id_res_u
.id
;
1897 return (resp
->status
);
1905 ni_index prop_index
,
1910 ni_nameindex_args args
;
1913 args
.prop_index
= prop_index
;
1914 args
.name_index
= name_index
;
1915 if ((resp
= WCALLIT(ni
, _ni_destroyname_2
, &args
)) == NULL
) {
1916 clnt_debug(ni
, "_ni_destroyname");
1919 if (resp
->status
== NI_OK
) {
1920 *id
= resp
->ni_id_res_u
.id
;
1922 return (resp
->status
);
1930 ni_index prop_index
,
1931 ni_index name_index
,
1936 ni_writename_args args
;
1939 args
.prop_index
= prop_index
;
1940 args
.name_index
= name_index
;
1941 args
.name
= (ni_name
)name
;
1942 if ((resp
= WCALLIT(ni
, _ni_writename_2
, &args
)) == NULL
) {
1943 clnt_debug(ni
, "_ni_writename");
1946 if (resp
->status
== NI_OK
) {
1947 *id
= resp
->ni_id_res_u
.id
;
1949 return (resp
->status
);
1957 ni_index prop_index
,
1958 ni_index name_index
,
1962 ni_readname_res
*resp
;
1963 ni_nameindex_args args
;
1966 args
.prop_index
= prop_index
;
1967 args
.name_index
= name_index
;
1968 if ((resp
= RCALLIT(ni
, _ni_readname_2
, &args
)) == NULL
) {
1969 clnt_debug(ni
, "_ni_readname");
1972 if (resp
->status
== NI_OK
) {
1973 *id
= resp
->ni_readname_res_u
.stuff
.id
;
1974 *name
= resp
->ni_readname_res_u
.stuff
.name
;
1976 return (resp
->status
);
1987 if ((resp
= (ni_status
*)RCALLIT(ni
, _ni_resync_2
, NULL
)) == NULL
) {
2006 NIP(ni
)->uid
= getuid();
2007 return (ni_setpassword(ni
, NULL
));
2010 if (ni_root(ni
, &id
) != NI_OK
) {
2014 if (ni_lookup(ni
, &id
, NAME_NAME
, NAME_USERS
, &ids
) != NI_OK
) {
2017 id
.nii_object
= ids
.niil_val
[0];
2018 ni_idlist_free(&ids
);
2021 if (ni_lookup(ni
, &id
, NAME_NAME
, user
, &ids
) != NI_OK
) {
2024 id
.nii_object
= ids
.niil_val
[0];
2025 ni_idlist_free(&ids
);
2027 if (ni_lookupprop(ni
, &id
, NAME_UID
, &nl
) != NI_OK
) {
2030 if (nl
.ninl_len
== 0) {
2033 for (p
= nl
.ninl_val
[0]; *p
; p
++) {
2035 ni_namelist_free(&nl
);
2039 NIP(ni
)->uid
= atoi(nl
.ninl_val
[0]);
2040 if (NIP(ni
)->passwd
== NULL
) {
2041 NIP(ni
)->passwd
= ni_name_dup("");
2043 createauth(NIP(ni
));
2051 ni_name_const passwd
2056 if (NIP(ni
)->passwd
!= NULL
) {
2057 ni_name_free(&NIP(ni
)->passwd
);
2059 if (passwd
== NULL
) {
2060 NIP(ni
)->passwd
= NULL
;
2061 if (NIP(ni
)->tc
!= NULL
) {
2062 auth_destroy(NIP(ni
)->tc
->cl_auth
);
2063 NIP(ni
)->tc
->cl_auth
= authnone_create();
2067 NIP(ni
)->passwd
= ni_name_dup(passwd
);
2069 * Our trivial encryption scheme
2071 for (p
= NIP(ni
)->passwd
; *p
; p
++) {
2074 createauth(NIP(ni
));
2079 extern int bindresvport(int, struct sockaddr_in
*);
2084 * The procedure pmap_getport_to below is derived
2085 * from Sun Microsystems RPC source code. As such the following
2086 * statement applies to it.:
2088 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
2089 * unrestricted use provided that this legend is included on all tape
2090 * media and as a part of the software program in whole or part. Users
2091 * may copy or modify Sun RPC without charge, but are not authorized
2092 * to license or distribute it to anyone else except as part of a product or
2093 * program developed by the user.
2095 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
2096 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
2097 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
2099 * Sun RPC is provided with no support and without any obligation on the
2100 * part of Sun Microsystems, Inc. to assist in its use, correction,
2101 * modification or enhancement.
2103 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
2104 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
2105 * OR ANY PART THEREOF.
2107 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
2108 * or profits or other special, indirect and consequential damages, even if
2109 * Sun has been advised of the possibility of such damages.
2111 * Sun Microsystems, Inc.
2112 * 2550 Garcia Avenue
2113 * Mountain View, California 94043
2116 * Client interface to pmap rpc service.
2118 * Find the mapped port for program,version.
2119 * Calls the pmap service remotely to do the lookup.
2120 * Returns 0 if no map exists.
2123 pmap_getport_to(address
, program
, version
, protocol
, timeout_secs
, ntries
)
2124 struct sockaddr_in
*address
;
2133 register CLIENT
*client
;
2135 struct timeval timeout
;
2137 sock
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
2141 address
->sin_port
= htons(PMAPPORT
);
2142 timeout
.tv_usec
= ((timeout_secs
% ntries
) * 1000000) / ntries
;
2143 timeout
.tv_sec
= (timeout_secs
/ ntries
);
2144 client
= clntudp_bufcreate(address
, PMAPPROG
,
2145 PMAPVERS
, timeout
, &sock
, RPCSMALLMSGSIZE
, RPCSMALLMSGSIZE
);
2146 if (client
!= (CLIENT
*)NULL
) {
2147 parms
.pm_prog
= program
;
2148 parms
.pm_vers
= version
;
2149 parms
.pm_prot
= protocol
;
2150 parms
.pm_port
= 0; /* not needed or used */
2151 timeout
.tv_usec
= 0;
2152 timeout
.tv_sec
= timeout_secs
;
2153 if (CLNT_CALL(client
, PMAPPROC_GETPORT
, xdr_pmap
, &parms
,
2154 xdr_u_short
, &port
, timeout
) != RPC_SUCCESS
){
2155 rpc_createerr
.cf_stat
= RPC_PMAPFAILURE
;
2156 clnt_geterr(client
, &rpc_createerr
.cf_error
);
2158 } else if (port
== 0) {
2159 rpc_createerr
.cf_stat
= RPC_PROGNOTREGISTERED
;
2162 if (client
!= NULL
) {
2163 clnt_destroy(client
);
2166 address
->sin_port
= 0;
2172 * Open a socket, but do not use the default portmap timeout
2176 struct sockaddr_in
*raddr
,
2184 struct sockaddr_in bindsin
;
2188 memset(&bindsin
, 0, sizeof(bindsin
));
2191 * If no port number given ask the pmap for one
2193 if (raddr
->sin_port
== 0) {
2195 if ((port
= pmap_getport_to(raddr
, prog
, vers
,
2196 IPPROTO_UDP
, timeout
,
2200 raddr
->sin_port
= htons(port
);
2203 sock
= socket(AF_INET
, proto
== IPPROTO_UDP
? SOCK_DGRAM
: SOCK_STREAM
,
2208 if (-1 == bindresvport(sock
, NULL
) && errno
== EADDRNOTAVAIL
) {
2209 /* XXX - we're hitting this case way too often under load */
2210 /* fail gracefully: some address is better than none most of the time */
2211 syslog(LOG_DEBUG
, "Libinfo[%s():%d] bindresvport(): %m", __func__
, __LINE__
);
2212 if (-1 == bind(sock
, &bindsin
, sizeof(bindsin
))) {
2213 /* The system is really sad now if it can't give me any address... */
2214 syslog(LOG_DEBUG
, "Libinfo[%s():%d] bind(): %m", __func__
, __LINE__
);
2219 setsockopt(sock
, SOL_SOCKET
, SO_REUSEPORT
, &reuse
, sizeof(int));
2220 setsockopt(sock
, SOL_SOCKET
, SO_REUSEADDR
, &reuse
, sizeof(int));
2221 if (proto
== IPPROTO_TCP
) {
2222 if (connect(sock
, (struct sockaddr
*)raddr
,
2223 sizeof(*raddr
)) < 0) {
2224 syslog(LOG_DEBUG
, "Libinfo[%s():%d] connect(): %m", __func__
, __LINE__
);