xref: /netbsd-src/usr.sbin/rpcbind/check_bound.c (revision 4472dbe5e3bd91ef2540bada7a7ca7384627ff9b)
1 /*	$NetBSD: check_bound.c,v 1.1 2000/06/02 23:15:41 fvdl Exp $	*/
2 
3 /*
4  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5  * unrestricted use provided that this legend is included on all tape
6  * media and as a part of the software program in whole or part.  Users
7  * may copy or modify Sun RPC without charge, but are not authorized
8  * to license or distribute it to anyone else except as part of a product or
9  * program developed by the user.
10  *
11  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
12  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
14  *
15  * Sun RPC is provided with no support and without any obligation on the
16  * part of Sun Microsystems, Inc. to assist in its use, correction,
17  * modification or enhancement.
18  *
19  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21  * OR ANY PART THEREOF.
22  *
23  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24  * or profits or other special, indirect and consequential damages, even if
25  * Sun has been advised of the possibility of such damages.
26  *
27  * Sun Microsystems, Inc.
28  * 2550 Garcia Avenue
29  * Mountain View, California  94043
30  */
31 /*
32  * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
33  */
34 
35 /* #ident	"@(#)check_bound.c	1.15	93/07/05 SMI" */
36 
37 #if 0
38 #ifndef lint
39 static	char sccsid[] = "@(#)check_bound.c 1.11 89/04/21 Copyr 1989 Sun Micro";
40 #endif
41 #endif
42 
43 /*
44  * check_bound.c
45  * Checks to see whether the program is still bound to the
46  * claimed address and returns the univeral merged address
47  *
48  */
49 
50 #include <sys/types.h>
51 #include <sys/socket.h>
52 #include <rpc/rpc.h>
53 #include <stdio.h>
54 #include <netconfig.h>
55 #include <syslog.h>
56 #include <string.h>
57 #include <unistd.h>
58 #include <stdlib.h>
59 
60 #include "rpcbind.h"
61 
62 struct fdlist {
63 	int fd;
64 	struct netconfig *nconf;
65 	struct fdlist *next;
66 	int check_binding;
67 };
68 
69 static struct fdlist *fdhead;	/* Link list of the check fd's */
70 static struct fdlist *fdtail;
71 static char *nullstring = "";
72 
73 static bool_t check_bound __P((struct fdlist *, char *uaddr));
74 
75 /*
76  * Returns 1 if the given address is bound for the given addr & transport
77  * For all error cases, we assume that the address is bound
78  * Returns 0 for success.
79  */
80 static bool_t
81 check_bound(struct fdlist *fdl, char *uaddr)
82 {
83 	int fd;
84 	struct netbuf *na;
85 	int ans;
86 
87 	if (fdl->check_binding == FALSE)
88 		return (TRUE);
89 
90 	na = uaddr2taddr(fdl->nconf, uaddr);
91 	if (!na)
92 		return (TRUE); /* punt, should never happen */
93 
94 	fd = __rpc_nconf2fd(fdl->nconf);
95 	if (fd < 0)
96 		return (TRUE);
97 
98 	ans = bind(fd, (struct sockaddr *)na->buf, na->len);
99 
100 	close(fd);
101 
102 	return (ans == 0 ? FALSE : TRUE);
103 }
104 
105 int
106 add_bndlist(struct netconfig *nconf, struct netbuf *baddr)
107 {
108 	struct fdlist *fdl;
109 	struct netconfig *newnconf;
110 
111 	newnconf = getnetconfigent(nconf->nc_netid);
112 	if (newnconf == NULL)
113 		return (-1);
114 	fdl = (struct fdlist *)malloc((u_int)sizeof (struct fdlist));
115 	if (fdl == NULL) {
116 		freenetconfigent(newnconf);
117 		syslog(LOG_ERR, "no memory!");
118 		return (-1);
119 	}
120 	fdl->nconf = newnconf;
121 	fdl->next = NULL;
122 	if (fdhead == NULL) {
123 		fdhead = fdl;
124 		fdtail = fdl;
125 	} else {
126 		fdtail->next = fdl;
127 		fdtail = fdl;
128 	}
129 	/* XXX no bound checking for now */
130 	fdl->check_binding = FALSE;
131 
132 	return 0;
133 }
134 
135 bool_t
136 is_bound(char *netid, char *uaddr)
137 {
138 	struct fdlist *fdl;
139 
140 	for (fdl = fdhead; fdl; fdl = fdl->next)
141 		if (strcmp(fdl->nconf->nc_netid, netid) == 0)
142 			break;
143 	if (fdl == NULL)
144 		return (TRUE);
145 	return (check_bound(fdl, uaddr));
146 }
147 
148 /*
149  * Returns NULL if there was some system error.
150  * Returns "" if the address was not bound, i.e the server crashed.
151  * Returns the merged address otherwise.
152  */
153 char *
154 mergeaddr(SVCXPRT *xprt, char *netid, char *uaddr, char *saddr)
155 {
156 	struct fdlist *fdl;
157 	char *c_uaddr, *s_uaddr, *m_uaddr;
158 
159 	for (fdl = fdhead; fdl; fdl = fdl->next)
160 		if (strcmp(fdl->nconf->nc_netid, netid) == 0)
161 			break;
162 	if (fdl == NULL)
163 		return (NULL);
164 	if (check_bound(fdl, uaddr) == FALSE)
165 		/* that server died */
166 		return (nullstring);
167 	/*
168 	 * If saddr is not NULL, the remote client may have included the
169 	 * address by which it contacted us.  Use that for the "client" uaddr,
170 	 * otherwise use the info from the SVCXPRT.
171 	 */
172 	if (saddr != NULL) {
173 		c_uaddr = saddr;
174 	} else {
175 		c_uaddr = taddr2uaddr(fdl->nconf, svc_getrpccaller(xprt));
176 		if (c_uaddr == NULL) {
177 			syslog(LOG_ERR, "taddr2uaddr failed for %s",
178 				fdl->nconf->nc_netid);
179 			return (NULL);
180 		}
181 	}
182 
183 #ifdef ND_DEBUG
184 	if (debugging) {
185 		if (saddr == NULL) {
186 			fprintf(stderr, "mergeaddr: client uaddr = %s\n",
187 			    c_uaddr);
188 		} else {
189 			fprintf(stderr, "mergeaddr: contact uaddr = %s\n",
190 			    c_uaddr);
191 		}
192 	}
193 #endif
194 	s_uaddr = uaddr;
195 	/*
196 	 * This is all we should need for IP 4 and 6
197 	 */
198 	m_uaddr = addrmerge(svc_getrpccaller(xprt), s_uaddr, c_uaddr, netid);
199 #ifdef ND_DEBUG
200 	if (debugging)
201 		fprintf(stderr, "mergeaddr: uaddr = %s, merged uaddr = %s\n",
202 				uaddr, m_uaddr);
203 #endif
204 	return (m_uaddr);
205 }
206 
207 /*
208  * Returns a netconf structure from its internal list.  This
209  * structure should not be freed.
210  */
211 struct netconfig *
212 rpcbind_get_conf(char *netid)
213 {
214 	struct fdlist *fdl;
215 
216 	for (fdl = fdhead; fdl; fdl = fdl->next)
217 		if (strcmp(fdl->nconf->nc_netid, netid) == 0)
218 			break;
219 	if (fdl == NULL)
220 		return (NULL);
221 	return (fdl->nconf);
222 }
223