xref: /dragonfly/usr.sbin/rpcbind/check_bound.c (revision 19fe1c42)
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  * $DragonFly$
33  */
34 /*
35  * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
36  */
37 
38 /*
39  * check_bound.c
40  * Checks to see whether the program is still bound to the
41  * claimed address and returns the univeral merged address
42  *
43  */
44 
45 #include <sys/types.h>
46 #include <sys/socket.h>
47 #include <rpc/rpc.h>
48 #include <stdio.h>
49 #include <netconfig.h>
50 #include <syslog.h>
51 #include <string.h>
52 #include <unistd.h>
53 #include <stdlib.h>
54 
55 #include "rpcbind.h"
56 
57 struct fdlist {
58 	int fd;
59 	struct netconfig *nconf;
60 	struct fdlist *next;
61 	int check_binding;
62 };
63 
64 static struct fdlist *fdhead;	/* Link list of the check fd's */
65 static struct fdlist *fdtail;
66 static char *nullstring = "";
67 
68 static bool_t	check_bound(struct fdlist *, char *uaddr);
69 
70 /*
71  * Returns 1 if the given address is bound for the given addr & transport
72  * For all error cases, we assume that the address is bound
73  * Returns 0 for success.
74  */
75 static bool_t
76 check_bound(struct fdlist *fdl, char *uaddr)
77 {
78 	int fd;
79 	struct netbuf *na;
80 	int ans;
81 
82 	if (fdl->check_binding == FALSE)
83 		return (TRUE);
84 
85 	na = uaddr2taddr(fdl->nconf, uaddr);
86 	if (!na)
87 		return (TRUE); /* punt, should never happen */
88 
89 	fd = __rpc_nconf2fd(fdl->nconf);
90 	if (fd < 0) {
91 		free(na->buf);
92 		free(na);
93 		return (TRUE);
94 	}
95 
96 	ans = bind(fd, (struct sockaddr *)na->buf, na->len);
97 
98 	close(fd);
99 	free(na->buf);
100 	free(na);
101 
102 	return (ans == 0 ? FALSE : TRUE);
103 }
104 
105 int
106 add_bndlist(struct netconfig *nconf, struct netbuf *baddr __unused)
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 = malloc(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, *allocated_uaddr = NULL;
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 		allocated_uaddr = c_uaddr;
182 	}
183 
184 #ifdef ND_DEBUG
185 	if (debugging) {
186 		if (saddr == NULL) {
187 			fprintf(stderr, "mergeaddr: client uaddr = %s\n",
188 			    c_uaddr);
189 		} else {
190 			fprintf(stderr, "mergeaddr: contact uaddr = %s\n",
191 			    c_uaddr);
192 		}
193 	}
194 #endif
195 	s_uaddr = uaddr;
196 	/*
197 	 * This is all we should need for IP 4 and 6
198 	 */
199 	m_uaddr = addrmerge(svc_getrpccaller(xprt), s_uaddr, c_uaddr, netid);
200 #ifdef ND_DEBUG
201 	if (debugging)
202 		fprintf(stderr, "mergeaddr: uaddr = %s, merged uaddr = %s\n",
203 				uaddr, m_uaddr);
204 #endif
205 	if (allocated_uaddr != NULL)
206 		free(allocated_uaddr);
207 	return (m_uaddr);
208 }
209 
210 /*
211  * Returns a netconf structure from its internal list.  This
212  * structure should not be freed.
213  */
214 struct netconfig *
215 rpcbind_get_conf(char *netid)
216 {
217 	struct fdlist *fdl;
218 
219 	for (fdl = fdhead; fdl; fdl = fdl->next)
220 		if (strcmp(fdl->nconf->nc_netid, netid) == 0)
221 			break;
222 	if (fdl == NULL)
223 		return (NULL);
224 	return (fdl->nconf);
225 }
226