xref: /netbsd/usr.sbin/rpcbind/check_bound.c (revision bf9ec67e)
1 /*	$NetBSD: check_bound.c,v 1.2 2000/06/22 08:09:26 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 		free(na);
97 		return (TRUE);
98 	}
99 
100 	ans = bind(fd, (struct sockaddr *)na->buf, na->len);
101 
102 	close(fd);
103 	free(na);
104 
105 	return (ans == 0 ? FALSE : TRUE);
106 }
107 
108 int
109 add_bndlist(struct netconfig *nconf, struct netbuf *baddr)
110 {
111 	struct fdlist *fdl;
112 	struct netconfig *newnconf;
113 
114 	newnconf = getnetconfigent(nconf->nc_netid);
115 	if (newnconf == NULL)
116 		return (-1);
117 	fdl = (struct fdlist *)malloc((u_int)sizeof (struct fdlist));
118 	if (fdl == NULL) {
119 		freenetconfigent(newnconf);
120 		syslog(LOG_ERR, "no memory!");
121 		return (-1);
122 	}
123 	fdl->nconf = newnconf;
124 	fdl->next = NULL;
125 	if (fdhead == NULL) {
126 		fdhead = fdl;
127 		fdtail = fdl;
128 	} else {
129 		fdtail->next = fdl;
130 		fdtail = fdl;
131 	}
132 	/* XXX no bound checking for now */
133 	fdl->check_binding = FALSE;
134 
135 	return 0;
136 }
137 
138 bool_t
139 is_bound(char *netid, char *uaddr)
140 {
141 	struct fdlist *fdl;
142 
143 	for (fdl = fdhead; fdl; fdl = fdl->next)
144 		if (strcmp(fdl->nconf->nc_netid, netid) == 0)
145 			break;
146 	if (fdl == NULL)
147 		return (TRUE);
148 	return (check_bound(fdl, uaddr));
149 }
150 
151 /*
152  * Returns NULL if there was some system error.
153  * Returns "" if the address was not bound, i.e the server crashed.
154  * Returns the merged address otherwise.
155  */
156 char *
157 mergeaddr(SVCXPRT *xprt, char *netid, char *uaddr, char *saddr)
158 {
159 	struct fdlist *fdl;
160 	char *c_uaddr, *s_uaddr, *m_uaddr, *allocated_uaddr = NULL;
161 
162 	for (fdl = fdhead; fdl; fdl = fdl->next)
163 		if (strcmp(fdl->nconf->nc_netid, netid) == 0)
164 			break;
165 	if (fdl == NULL)
166 		return (NULL);
167 	if (check_bound(fdl, uaddr) == FALSE)
168 		/* that server died */
169 		return (nullstring);
170 	/*
171 	 * If saddr is not NULL, the remote client may have included the
172 	 * address by which it contacted us.  Use that for the "client" uaddr,
173 	 * otherwise use the info from the SVCXPRT.
174 	 */
175 	if (saddr != NULL) {
176 		c_uaddr = saddr;
177 	} else {
178 		c_uaddr = taddr2uaddr(fdl->nconf, svc_getrpccaller(xprt));
179 		if (c_uaddr == NULL) {
180 			syslog(LOG_ERR, "taddr2uaddr failed for %s",
181 				fdl->nconf->nc_netid);
182 			return (NULL);
183 		}
184 		allocated_uaddr = c_uaddr;
185 	}
186 
187 #ifdef ND_DEBUG
188 	if (debugging) {
189 		if (saddr == NULL) {
190 			fprintf(stderr, "mergeaddr: client uaddr = %s\n",
191 			    c_uaddr);
192 		} else {
193 			fprintf(stderr, "mergeaddr: contact uaddr = %s\n",
194 			    c_uaddr);
195 		}
196 	}
197 #endif
198 	s_uaddr = uaddr;
199 	/*
200 	 * This is all we should need for IP 4 and 6
201 	 */
202 	m_uaddr = addrmerge(svc_getrpccaller(xprt), s_uaddr, c_uaddr, netid);
203 #ifdef ND_DEBUG
204 	if (debugging)
205 		fprintf(stderr, "mergeaddr: uaddr = %s, merged uaddr = %s\n",
206 				uaddr, m_uaddr);
207 #endif
208 	if (allocated_uaddr != NULL)
209 		free(allocated_uaddr);
210 	return (m_uaddr);
211 }
212 
213 /*
214  * Returns a netconf structure from its internal list.  This
215  * structure should not be freed.
216  */
217 struct netconfig *
218 rpcbind_get_conf(char *netid)
219 {
220 	struct fdlist *fdl;
221 
222 	for (fdl = fdhead; fdl; fdl = fdl->next)
223 		if (strcmp(fdl->nconf->nc_netid, netid) == 0)
224 			break;
225 	if (fdl == NULL)
226 		return (NULL);
227 	return (fdl->nconf);
228 }
229