174462Salfred/*	$NetBSD: check_bound.c,v 1.2 2000/06/22 08:09:26 fvdl Exp $	*/
274462Salfred/*	$FreeBSD$ */
374462Salfred
474462Salfred/*
574462Salfred * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
674462Salfred * unrestricted use provided that this legend is included on all tape
774462Salfred * media and as a part of the software program in whole or part.  Users
874462Salfred * may copy or modify Sun RPC without charge, but are not authorized
974462Salfred * to license or distribute it to anyone else except as part of a product or
1074462Salfred * program developed by the user.
1174462Salfred *
1274462Salfred * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
1374462Salfred * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
1474462Salfred * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
1574462Salfred *
1674462Salfred * Sun RPC is provided with no support and without any obligation on the
1774462Salfred * part of Sun Microsystems, Inc. to assist in its use, correction,
1874462Salfred * modification or enhancement.
1974462Salfred *
2074462Salfred * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
2174462Salfred * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
2274462Salfred * OR ANY PART THEREOF.
2374462Salfred *
2474462Salfred * In no event will Sun Microsystems, Inc. be liable for any lost revenue
2574462Salfred * or profits or other special, indirect and consequential damages, even if
2674462Salfred * Sun has been advised of the possibility of such damages.
2774462Salfred *
2874462Salfred * Sun Microsystems, Inc.
2974462Salfred * 2550 Garcia Avenue
3074462Salfred * Mountain View, California  94043
3174462Salfred */
3274462Salfred/*
3374462Salfred * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
3474462Salfred */
3574462Salfred
3674462Salfred/* #ident	"@(#)check_bound.c	1.15	93/07/05 SMI" */
3774462Salfred
3874462Salfred#if 0
3974462Salfred#ifndef lint
4074462Salfredstatic	char sccsid[] = "@(#)check_bound.c 1.11 89/04/21 Copyr 1989 Sun Micro";
4174462Salfred#endif
4274462Salfred#endif
4374462Salfred
4474462Salfred/*
4574462Salfred * check_bound.c
4674462Salfred * Checks to see whether the program is still bound to the
47228990Suqs * claimed address and returns the universal merged address
4874462Salfred *
4974462Salfred */
5074462Salfred
5174462Salfred#include <sys/types.h>
5274462Salfred#include <sys/socket.h>
5374462Salfred#include <rpc/rpc.h>
54296994Sasomers#include <rpc/svc_dg.h>
5574462Salfred#include <stdio.h>
5674462Salfred#include <netconfig.h>
5774462Salfred#include <syslog.h>
5874462Salfred#include <string.h>
5974462Salfred#include <unistd.h>
6074462Salfred#include <stdlib.h>
6174462Salfred
6274462Salfred#include "rpcbind.h"
6374462Salfred
6474462Salfredstruct fdlist {
6574462Salfred	int fd;
6674462Salfred	struct netconfig *nconf;
6774462Salfred	struct fdlist *next;
6874462Salfred	int check_binding;
6974462Salfred};
7074462Salfred
7174462Salfredstatic struct fdlist *fdhead;	/* Link list of the check fd's */
7274462Salfredstatic struct fdlist *fdtail;
7374462Salfredstatic char *nullstring = "";
7474462Salfred
75173412Skevlostatic bool_t check_bound(struct fdlist *, char *uaddr);
7674462Salfred
7774462Salfred/*
7874462Salfred * Returns 1 if the given address is bound for the given addr & transport
7974462Salfred * For all error cases, we assume that the address is bound
8074462Salfred * Returns 0 for success.
8174462Salfred */
8274462Salfredstatic bool_t
8374462Salfredcheck_bound(struct fdlist *fdl, char *uaddr)
8474462Salfred{
8574462Salfred	int fd;
8674462Salfred	struct netbuf *na;
8774462Salfred	int ans;
8874462Salfred
8974462Salfred	if (fdl->check_binding == FALSE)
9074462Salfred		return (TRUE);
9174462Salfred
9274462Salfred	na = uaddr2taddr(fdl->nconf, uaddr);
9374462Salfred	if (!na)
9474462Salfred		return (TRUE); /* punt, should never happen */
9574462Salfred
9674462Salfred	fd = __rpc_nconf2fd(fdl->nconf);
9774462Salfred	if (fd < 0) {
9879722Siedowse		free(na->buf);
9974462Salfred		free(na);
10074462Salfred		return (TRUE);
10174462Salfred	}
10274462Salfred
10374462Salfred	ans = bind(fd, (struct sockaddr *)na->buf, na->len);
10474462Salfred
10574462Salfred	close(fd);
10679722Siedowse	free(na->buf);
10774462Salfred	free(na);
10874462Salfred
10974462Salfred	return (ans == 0 ? FALSE : TRUE);
11074462Salfred}
11174462Salfred
11274462Salfredint
113104592Salfredadd_bndlist(struct netconfig *nconf, struct netbuf *baddr __unused)
11474462Salfred{
11574462Salfred	struct fdlist *fdl;
11674462Salfred	struct netconfig *newnconf;
11774462Salfred
11874462Salfred	newnconf = getnetconfigent(nconf->nc_netid);
11974462Salfred	if (newnconf == NULL)
12074462Salfred		return (-1);
12196788Sjmallett	fdl = malloc(sizeof (struct fdlist));
12274462Salfred	if (fdl == NULL) {
12374462Salfred		freenetconfigent(newnconf);
12474462Salfred		syslog(LOG_ERR, "no memory!");
12574462Salfred		return (-1);
12674462Salfred	}
12774462Salfred	fdl->nconf = newnconf;
12874462Salfred	fdl->next = NULL;
12974462Salfred	if (fdhead == NULL) {
13074462Salfred		fdhead = fdl;
13174462Salfred		fdtail = fdl;
13274462Salfred	} else {
13374462Salfred		fdtail->next = fdl;
13474462Salfred		fdtail = fdl;
13574462Salfred	}
13674462Salfred	/* XXX no bound checking for now */
13774462Salfred	fdl->check_binding = FALSE;
13874462Salfred
13974462Salfred	return 0;
14074462Salfred}
14174462Salfred
14274462Salfredbool_t
14374462Salfredis_bound(char *netid, char *uaddr)
14474462Salfred{
14574462Salfred	struct fdlist *fdl;
14674462Salfred
14774462Salfred	for (fdl = fdhead; fdl; fdl = fdl->next)
14874462Salfred		if (strcmp(fdl->nconf->nc_netid, netid) == 0)
14974462Salfred			break;
15074462Salfred	if (fdl == NULL)
15174462Salfred		return (TRUE);
15274462Salfred	return (check_bound(fdl, uaddr));
15374462Salfred}
15474462Salfred
15574462Salfred/*
15674462Salfred * Returns NULL if there was some system error.
15774462Salfred * Returns "" if the address was not bound, i.e the server crashed.
15874462Salfred * Returns the merged address otherwise.
15974462Salfred */
16074462Salfredchar *
16174462Salfredmergeaddr(SVCXPRT *xprt, char *netid, char *uaddr, char *saddr)
16274462Salfred{
16374462Salfred	struct fdlist *fdl;
164296994Sasomers	struct svc_dg_data *dg_data;
16574462Salfred	char *c_uaddr, *s_uaddr, *m_uaddr, *allocated_uaddr = NULL;
16674462Salfred
16774462Salfred	for (fdl = fdhead; fdl; fdl = fdl->next)
16874462Salfred		if (strcmp(fdl->nconf->nc_netid, netid) == 0)
16974462Salfred			break;
17074462Salfred	if (fdl == NULL)
17174462Salfred		return (NULL);
17274462Salfred	if (check_bound(fdl, uaddr) == FALSE)
17374462Salfred		/* that server died */
17474462Salfred		return (nullstring);
17574462Salfred	/*
176296994Sasomers	 * Try to determine the local address on which the client contacted us,
177296994Sasomers	 * so we can send a reply from the same address.  If it's unknown, then
178296994Sasomers	 * try to determine which address the client used, and pick a nearby
179296994Sasomers	 * local address.
180296994Sasomers	 *
18174462Salfred	 * If saddr is not NULL, the remote client may have included the
18274462Salfred	 * address by which it contacted us.  Use that for the "client" uaddr,
18374462Salfred	 * otherwise use the info from the SVCXPRT.
18474462Salfred	 */
185296994Sasomers	dg_data = (struct svc_dg_data*)xprt->xp_p2;
186296994Sasomers	if (dg_data != NULL && dg_data->su_srcaddr.buf != NULL) {
187296994Sasomers		c_uaddr = taddr2uaddr(fdl->nconf, &dg_data->su_srcaddr);
188296994Sasomers		allocated_uaddr = c_uaddr;
189296994Sasomers	}
190296994Sasomers	else if (saddr != NULL) {
19174462Salfred		c_uaddr = saddr;
19274462Salfred	} else {
19374462Salfred		c_uaddr = taddr2uaddr(fdl->nconf, svc_getrpccaller(xprt));
19474462Salfred		allocated_uaddr = c_uaddr;
19574462Salfred	}
196296994Sasomers	if (c_uaddr == NULL) {
197296994Sasomers		syslog(LOG_ERR, "taddr2uaddr failed for %s",
198296994Sasomers			fdl->nconf->nc_netid);
199296994Sasomers		return (NULL);
200296994Sasomers	}
20174462Salfred
20274462Salfred#ifdef ND_DEBUG
20374462Salfred	if (debugging) {
20474462Salfred		if (saddr == NULL) {
20574462Salfred			fprintf(stderr, "mergeaddr: client uaddr = %s\n",
20674462Salfred			    c_uaddr);
20774462Salfred		} else {
20874462Salfred			fprintf(stderr, "mergeaddr: contact uaddr = %s\n",
20974462Salfred			    c_uaddr);
21074462Salfred		}
21174462Salfred	}
21274462Salfred#endif
21374462Salfred	s_uaddr = uaddr;
21474462Salfred	/*
21574462Salfred	 * This is all we should need for IP 4 and 6
21674462Salfred	 */
21774462Salfred	m_uaddr = addrmerge(svc_getrpccaller(xprt), s_uaddr, c_uaddr, netid);
21874462Salfred#ifdef ND_DEBUG
21974462Salfred	if (debugging)
22074462Salfred		fprintf(stderr, "mergeaddr: uaddr = %s, merged uaddr = %s\n",
22174462Salfred				uaddr, m_uaddr);
22274462Salfred#endif
223301644Sngie	free(allocated_uaddr);
22474462Salfred	return (m_uaddr);
22574462Salfred}
22674462Salfred
22774462Salfred/*
22874462Salfred * Returns a netconf structure from its internal list.  This
22974462Salfred * structure should not be freed.
23074462Salfred */
23174462Salfredstruct netconfig *
232296994Sasomersrpcbind_get_conf(const char *netid)
23374462Salfred{
23474462Salfred	struct fdlist *fdl;
23574462Salfred
23674462Salfred	for (fdl = fdhead; fdl; fdl = fdl->next)
23774462Salfred		if (strcmp(fdl->nconf->nc_netid, netid) == 0)
23874462Salfred			break;
23974462Salfred	if (fdl == NULL)
24074462Salfred		return (NULL);
24174462Salfred	return (fdl->nconf);
24274462Salfred}
243