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