xref: /netbsd-src/usr.sbin/rpcbind/check_bound.c (revision 946379e7b37692fc43f68eb0d1c10daa0a7f3b6c)
1 /*	$NetBSD: check_bound.c,v 1.6 2015/11/08 16:36:28 christos 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 #ifdef RPCBIND_RUMP
61 #include <rump/rump.h>
62 #include <rump/rump_syscalls.h>
63 #endif
64 
65 #include "rpcbind.h"
66 
67 struct fdlist {
68 	int fd;
69 	struct netconfig *nconf;
70 	struct fdlist *next;
71 	int check_binding;
72 };
73 
74 static struct fdlist *fdhead;	/* Link list of the check fd's */
75 static struct fdlist *fdtail;
76 static const char emptystring[] = "";
77 
78 static bool_t check_bound(struct fdlist *, const char *uaddr);
79 
80 /*
81  * Returns 1 if the given address is bound for the given addr & transport
82  * For all error cases, we assume that the address is bound
83  * Returns 0 for success.
84  */
85 static bool_t
86 check_bound(struct fdlist *fdl, const char *uaddr)
87 {
88 	int fd;
89 	struct netbuf *na;
90 	int ans;
91 
92 	if (fdl->check_binding == FALSE)
93 		return (TRUE);
94 
95 	na = uaddr2taddr(fdl->nconf, uaddr);
96 	if (!na)
97 		return (TRUE); /* punt, should never happen */
98 
99 	fd = __rpc_nconf2fd(fdl->nconf);
100 	if (fd < 0) {
101 		free(na);
102 		return (TRUE);
103 	}
104 
105 	ans = bind(fd, (struct sockaddr *)na->buf, na->len);
106 
107 #ifdef RPCBIND_RUMP
108 	rump_sys_close(fd);
109 #else
110 	close(fd);
111 #endif
112 	free(na);
113 
114 	return (ans == 0 ? FALSE : TRUE);
115 }
116 
117 int
118 add_bndlist(struct netconfig *nconf, struct netbuf *baddr)
119 {
120 	struct fdlist *fdl;
121 	struct netconfig *newnconf;
122 
123 	newnconf = getnetconfigent(nconf->nc_netid);
124 	if (newnconf == NULL)
125 		return (-1);
126 	fdl = (struct fdlist *)malloc((u_int)sizeof (struct fdlist));
127 	if (fdl == NULL) {
128 		freenetconfigent(newnconf);
129 		syslog(LOG_ERR, "no memory!");
130 		return (-1);
131 	}
132 	fdl->nconf = newnconf;
133 	fdl->next = NULL;
134 	if (fdhead == NULL) {
135 		fdhead = fdl;
136 		fdtail = fdl;
137 	} else {
138 		fdtail->next = fdl;
139 		fdtail = fdl;
140 	}
141 	/* XXX no bound checking for now */
142 	fdl->check_binding = FALSE;
143 
144 	return 0;
145 }
146 
147 bool_t
148 is_bound(const char *netid, const char *uaddr)
149 {
150 	struct fdlist *fdl;
151 
152 	for (fdl = fdhead; fdl; fdl = fdl->next)
153 		if (strcmp(fdl->nconf->nc_netid, netid) == 0)
154 			break;
155 	if (fdl == NULL)
156 		return (TRUE);
157 	return (check_bound(fdl, uaddr));
158 }
159 
160 /*
161  * Returns NULL if there was some system error.
162  * Returns "" if the address was not bound, i.e the server crashed.
163  * Returns the merged address otherwise.
164  */
165 char *
166 mergeaddr(SVCXPRT *xprt, char *netid, char *uaddr, char *saddr)
167 {
168 	struct fdlist *fdl;
169 	char *c_uaddr, *s_uaddr, *m_uaddr, *allocated_uaddr = NULL;
170 
171 	for (fdl = fdhead; fdl; fdl = fdl->next)
172 		if (strcmp(fdl->nconf->nc_netid, netid) == 0)
173 			break;
174 	if (fdl == NULL)
175 		return (NULL);
176 	if (check_bound(fdl, uaddr) == FALSE)
177 		/* that server died */
178 		return strdup(emptystring);
179 	/*
180 	 * If saddr is not NULL, the remote client may have included the
181 	 * address by which it contacted us.  Use that for the "client" uaddr,
182 	 * otherwise use the info from the SVCXPRT.
183 	 */
184 	if (saddr != NULL) {
185 		c_uaddr = saddr;
186 	} else {
187 		c_uaddr = taddr2uaddr(fdl->nconf, svc_getrpccaller(xprt));
188 		if (c_uaddr == NULL) {
189 			syslog(LOG_ERR, "taddr2uaddr failed for %s",
190 				fdl->nconf->nc_netid);
191 			return (NULL);
192 		}
193 		allocated_uaddr = c_uaddr;
194 	}
195 
196 #ifdef RPCBIND_DEBUG
197 	if (debugging) {
198 		if (saddr == NULL) {
199 			fprintf(stderr, "mergeaddr: client uaddr = %s\n",
200 			    c_uaddr);
201 		} else {
202 			fprintf(stderr, "mergeaddr: contact uaddr = %s\n",
203 			    c_uaddr);
204 		}
205 	}
206 #endif
207 	s_uaddr = uaddr;
208 	/*
209 	 * This is all we should need for IP 4 and 6
210 	 */
211 	m_uaddr = addrmerge(svc_getrpccaller(xprt), s_uaddr, c_uaddr, netid);
212 #ifdef RPCBIND_DEBUG
213 	if (debugging)
214 		fprintf(stderr, "mergeaddr: uaddr = %s, merged uaddr = %s\n",
215 				uaddr, m_uaddr);
216 #endif
217 	if (allocated_uaddr != NULL)
218 		free(allocated_uaddr);
219 	return (m_uaddr);
220 }
221 
222 /*
223  * Returns a netconf structure from its internal list.  This
224  * structure should not be freed.
225  */
226 struct netconfig *
227 rpcbind_get_conf(const char *netid)
228 {
229 	struct fdlist *fdl;
230 
231 	for (fdl = fdhead; fdl; fdl = fdl->next)
232 		if (strcmp(fdl->nconf->nc_netid, netid) == 0)
233 			break;
234 	if (fdl == NULL)
235 		return (NULL);
236 	return (fdl->nconf);
237 }
238