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