174462Salfred/* $NetBSD: check_bound.c,v 1.2 2000/06/22 08:09:26 fvdl Exp $ */ 274462Salfred/* $FreeBSD$ */ 374462Salfred 4258564Shrs/*- 5258564Shrs * Copyright (c) 2009, Sun Microsystems, Inc. 6258564Shrs * All rights reserved. 7258564Shrs * 8258564Shrs * Redistribution and use in source and binary forms, with or without 9258564Shrs * modification, are permitted provided that the following conditions are met: 10258564Shrs * - Redistributions of source code must retain the above copyright notice, 11258564Shrs * this list of conditions and the following disclaimer. 12258564Shrs * - Redistributions in binary form must reproduce the above copyright notice, 13258564Shrs * this list of conditions and the following disclaimer in the documentation 14258564Shrs * and/or other materials provided with the distribution. 15258564Shrs * - Neither the name of Sun Microsystems, Inc. nor the names of its 16258564Shrs * contributors may be used to endorse or promote products derived 17258564Shrs * from this software without specific prior written permission. 18258564Shrs * 19258564Shrs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20258564Shrs * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21258564Shrs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22258564Shrs * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23258564Shrs * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24258564Shrs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25258564Shrs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26258564Shrs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27258564Shrs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28258564Shrs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29258564Shrs * POSSIBILITY OF SUCH DAMAGE. 3074462Salfred */ 3174462Salfred/* 3274462Salfred * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. 3374462Salfred */ 3474462Salfred 3574462Salfred/* #ident "@(#)check_bound.c 1.15 93/07/05 SMI" */ 3674462Salfred 3774462Salfred#if 0 3874462Salfred#ifndef lint 3974462Salfredstatic char sccsid[] = "@(#)check_bound.c 1.11 89/04/21 Copyr 1989 Sun Micro"; 4074462Salfred#endif 4174462Salfred#endif 4274462Salfred 4374462Salfred/* 4474462Salfred * check_bound.c 4574462Salfred * Checks to see whether the program is still bound to the 46228990Suqs * claimed address and returns the universal merged address 4774462Salfred * 4874462Salfred */ 4974462Salfred 5074462Salfred#include <sys/types.h> 5174462Salfred#include <sys/socket.h> 5274462Salfred#include <rpc/rpc.h> 53293229Sasomers#include <rpc/svc_dg.h> 5474462Salfred#include <stdio.h> 5574462Salfred#include <netconfig.h> 5674462Salfred#include <syslog.h> 5774462Salfred#include <string.h> 5874462Salfred#include <unistd.h> 5974462Salfred#include <stdlib.h> 6074462Salfred 6174462Salfred#include "rpcbind.h" 6274462Salfred 6374462Salfredstruct fdlist { 6474462Salfred int fd; 6574462Salfred struct netconfig *nconf; 6674462Salfred struct fdlist *next; 6774462Salfred int check_binding; 6874462Salfred}; 6974462Salfred 7074462Salfredstatic struct fdlist *fdhead; /* Link list of the check fd's */ 7174462Salfredstatic struct fdlist *fdtail; 7274462Salfredstatic char *nullstring = ""; 7374462Salfred 74173412Skevlostatic bool_t check_bound(struct fdlist *, char *uaddr); 7574462Salfred 7674462Salfred/* 7774462Salfred * Returns 1 if the given address is bound for the given addr & transport 7874462Salfred * For all error cases, we assume that the address is bound 7974462Salfred * Returns 0 for success. 8074462Salfred */ 8174462Salfredstatic bool_t 8274462Salfredcheck_bound(struct fdlist *fdl, char *uaddr) 8374462Salfred{ 8474462Salfred int fd; 8574462Salfred struct netbuf *na; 8674462Salfred int ans; 8774462Salfred 8874462Salfred if (fdl->check_binding == FALSE) 8974462Salfred return (TRUE); 9074462Salfred 9174462Salfred na = uaddr2taddr(fdl->nconf, uaddr); 9274462Salfred if (!na) 9374462Salfred return (TRUE); /* punt, should never happen */ 9474462Salfred 9574462Salfred fd = __rpc_nconf2fd(fdl->nconf); 9674462Salfred if (fd < 0) { 9779722Siedowse free(na->buf); 9874462Salfred free(na); 9974462Salfred return (TRUE); 10074462Salfred } 10174462Salfred 10274462Salfred ans = bind(fd, (struct sockaddr *)na->buf, na->len); 10374462Salfred 10474462Salfred close(fd); 10579722Siedowse free(na->buf); 10674462Salfred free(na); 10774462Salfred 10874462Salfred return (ans == 0 ? FALSE : TRUE); 10974462Salfred} 11074462Salfred 11174462Salfredint 112104592Salfredadd_bndlist(struct netconfig *nconf, struct netbuf *baddr __unused) 11374462Salfred{ 11474462Salfred struct fdlist *fdl; 11574462Salfred struct netconfig *newnconf; 11674462Salfred 11774462Salfred newnconf = getnetconfigent(nconf->nc_netid); 11874462Salfred if (newnconf == NULL) 11974462Salfred return (-1); 12096788Sjmallett fdl = malloc(sizeof (struct fdlist)); 12174462Salfred if (fdl == NULL) { 12274462Salfred freenetconfigent(newnconf); 12374462Salfred syslog(LOG_ERR, "no memory!"); 12474462Salfred return (-1); 12574462Salfred } 12674462Salfred fdl->nconf = newnconf; 12774462Salfred fdl->next = NULL; 12874462Salfred if (fdhead == NULL) { 12974462Salfred fdhead = fdl; 13074462Salfred fdtail = fdl; 13174462Salfred } else { 13274462Salfred fdtail->next = fdl; 13374462Salfred fdtail = fdl; 13474462Salfred } 13574462Salfred /* XXX no bound checking for now */ 13674462Salfred fdl->check_binding = FALSE; 13774462Salfred 13874462Salfred return 0; 13974462Salfred} 14074462Salfred 14174462Salfredbool_t 14274462Salfredis_bound(char *netid, char *uaddr) 14374462Salfred{ 14474462Salfred struct fdlist *fdl; 14574462Salfred 14674462Salfred for (fdl = fdhead; fdl; fdl = fdl->next) 14774462Salfred if (strcmp(fdl->nconf->nc_netid, netid) == 0) 14874462Salfred break; 14974462Salfred if (fdl == NULL) 15074462Salfred return (TRUE); 15174462Salfred return (check_bound(fdl, uaddr)); 15274462Salfred} 15374462Salfred 15474462Salfred/* 15574462Salfred * Returns NULL if there was some system error. 15674462Salfred * Returns "" if the address was not bound, i.e the server crashed. 15774462Salfred * Returns the merged address otherwise. 15874462Salfred */ 15974462Salfredchar * 16074462Salfredmergeaddr(SVCXPRT *xprt, char *netid, char *uaddr, char *saddr) 16174462Salfred{ 16274462Salfred struct fdlist *fdl; 163293229Sasomers struct svc_dg_data *dg_data; 16474462Salfred char *c_uaddr, *s_uaddr, *m_uaddr, *allocated_uaddr = NULL; 16574462Salfred 16674462Salfred for (fdl = fdhead; fdl; fdl = fdl->next) 16774462Salfred if (strcmp(fdl->nconf->nc_netid, netid) == 0) 16874462Salfred break; 16974462Salfred if (fdl == NULL) 17074462Salfred return (NULL); 17174462Salfred if (check_bound(fdl, uaddr) == FALSE) 17274462Salfred /* that server died */ 17374462Salfred return (nullstring); 17474462Salfred /* 175293229Sasomers * Try to determine the local address on which the client contacted us, 176293229Sasomers * so we can send a reply from the same address. If it's unknown, then 177293229Sasomers * try to determine which address the client used, and pick a nearby 178293229Sasomers * local address. 179293229Sasomers * 18074462Salfred * If saddr is not NULL, the remote client may have included the 18174462Salfred * address by which it contacted us. Use that for the "client" uaddr, 18274462Salfred * otherwise use the info from the SVCXPRT. 18374462Salfred */ 184293229Sasomers dg_data = (struct svc_dg_data*)xprt->xp_p2; 185293229Sasomers if (dg_data != NULL && dg_data->su_srcaddr.buf != NULL) { 186293229Sasomers c_uaddr = taddr2uaddr(fdl->nconf, &dg_data->su_srcaddr); 187293833Sasomers allocated_uaddr = c_uaddr; 188293229Sasomers } 189293229Sasomers else if (saddr != NULL) { 19074462Salfred c_uaddr = saddr; 19174462Salfred } else { 19274462Salfred c_uaddr = taddr2uaddr(fdl->nconf, svc_getrpccaller(xprt)); 19374462Salfred allocated_uaddr = c_uaddr; 19474462Salfred } 195293833Sasomers if (c_uaddr == NULL) { 196293833Sasomers syslog(LOG_ERR, "taddr2uaddr failed for %s", 197293833Sasomers fdl->nconf->nc_netid); 198293833Sasomers return (NULL); 199293833Sasomers } 20074462Salfred 20174462Salfred#ifdef ND_DEBUG 20274462Salfred if (debugging) { 20374462Salfred if (saddr == NULL) { 20474462Salfred fprintf(stderr, "mergeaddr: client uaddr = %s\n", 20574462Salfred c_uaddr); 20674462Salfred } else { 20774462Salfred fprintf(stderr, "mergeaddr: contact uaddr = %s\n", 20874462Salfred c_uaddr); 20974462Salfred } 21074462Salfred } 21174462Salfred#endif 21274462Salfred s_uaddr = uaddr; 21374462Salfred /* 21474462Salfred * This is all we should need for IP 4 and 6 21574462Salfred */ 21674462Salfred m_uaddr = addrmerge(svc_getrpccaller(xprt), s_uaddr, c_uaddr, netid); 21774462Salfred#ifdef ND_DEBUG 21874462Salfred if (debugging) 21974462Salfred fprintf(stderr, "mergeaddr: uaddr = %s, merged uaddr = %s\n", 22074462Salfred uaddr, m_uaddr); 22174462Salfred#endif 222300942Sngie free(allocated_uaddr); 22374462Salfred return (m_uaddr); 22474462Salfred} 22574462Salfred 22674462Salfred/* 22774462Salfred * Returns a netconf structure from its internal list. This 22874462Salfred * structure should not be freed. 22974462Salfred */ 23074462Salfredstruct netconfig * 231293229Sasomersrpcbind_get_conf(const char *netid) 23274462Salfred{ 23374462Salfred struct fdlist *fdl; 23474462Salfred 23574462Salfred for (fdl = fdhead; fdl; fdl = fdl->next) 23674462Salfred if (strcmp(fdl->nconf->nc_netid, netid) == 0) 23774462Salfred break; 23874462Salfred if (fdl == NULL) 23974462Salfred return (NULL); 24074462Salfred return (fdl->nconf); 24174462Salfred} 242