xref: /dragonfly/usr.sbin/rpcbind/check_bound.c (revision bd91f5c31d05935d34ffa5befc63a95350bbf000)
1 /*
2  * Copyright (c) 2009, Sun Microsystems, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * - Redistributions of source code must retain the above copyright notice,
8  *   this list of conditions and the following disclaimer.
9  * - Redistributions in binary form must reproduce the above copyright notice,
10  *   this list of conditions and the following disclaimer in the documentation
11  *   and/or other materials provided with the distribution.
12  * - Neither the name of Sun Microsystems, Inc. nor the names of its
13  *   contributors may be used to endorse or promote products derived
14  *   from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  *
28  * @(#)check_bound.c          1.15      93/07/05 SMI; 1.11 89/04/21 Copyr 1989 Sun Micro
29  * $NetBSD: check_bound.c,v 1.2 2000/06/22 08:09:26 fvdl Exp $
30  * $FreeBSD: src/usr.sbin/rpcbind/check_bound.c,v 1.5 2007/11/07 10:53:39 kevlo Exp $
31  */
32 /*
33  * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
34  */
35 
36 /*
37  * check_bound.c
38  * Checks to see whether the program is still bound to the
39  * claimed address and returns the univeral merged address
40  *
41  */
42 
43 #include <sys/types.h>
44 #include <sys/socket.h>
45 #include <rpc/rpc.h>
46 #include <stdio.h>
47 #include <netconfig.h>
48 #include <syslog.h>
49 #include <string.h>
50 #include <unistd.h>
51 #include <stdlib.h>
52 
53 #include "rpcbind.h"
54 
55 struct fdlist {
56           int fd;
57           struct netconfig *nconf;
58           struct fdlist *next;
59           int check_binding;
60 };
61 
62 static struct fdlist *fdhead; /* Link list of the check fd's */
63 static struct fdlist *fdtail;
64 static char *nullstring = "";
65 
66 static bool_t       check_bound(struct fdlist *, char *uaddr);
67 
68 /*
69  * Returns 1 if the given address is bound for the given addr & transport
70  * For all error cases, we assume that the address is bound
71  * Returns 0 for success.
72  */
73 static bool_t
check_bound(struct fdlist * fdl,char * uaddr)74 check_bound(struct fdlist *fdl, char *uaddr)
75 {
76           int fd;
77           struct netbuf *na;
78           int ans;
79 
80           if (fdl->check_binding == FALSE)
81                     return (TRUE);
82 
83           na = uaddr2taddr(fdl->nconf, uaddr);
84           if (!na)
85                     return (TRUE); /* punt, should never happen */
86 
87           fd = __rpc_nconf2fd(fdl->nconf);
88           if (fd < 0) {
89                     free(na->buf);
90                     free(na);
91                     return (TRUE);
92           }
93 
94           ans = bind(fd, (struct sockaddr *)na->buf, na->len);
95 
96           close(fd);
97           free(na->buf);
98           free(na);
99 
100           return (ans == 0 ? FALSE : TRUE);
101 }
102 
103 int
add_bndlist(struct netconfig * nconf,struct netbuf * baddr __unused)104 add_bndlist(struct netconfig *nconf, struct netbuf *baddr __unused)
105 {
106           struct fdlist *fdl;
107           struct netconfig *newnconf;
108 
109           newnconf = getnetconfigent(nconf->nc_netid);
110           if (newnconf == NULL)
111                     return (-1);
112           fdl = malloc(sizeof (struct fdlist));
113           if (fdl == NULL) {
114                     freenetconfigent(newnconf);
115                     syslog(LOG_ERR, "no memory!");
116                     return (-1);
117           }
118           fdl->nconf = newnconf;
119           fdl->next = NULL;
120           if (fdhead == NULL) {
121                     fdhead = fdl;
122                     fdtail = fdl;
123           } else {
124                     fdtail->next = fdl;
125                     fdtail = fdl;
126           }
127           /* XXX no bound checking for now */
128           fdl->check_binding = FALSE;
129 
130           return 0;
131 }
132 
133 bool_t
is_bound(char * netid,char * uaddr)134 is_bound(char *netid, char *uaddr)
135 {
136           struct fdlist *fdl;
137 
138           for (fdl = fdhead; fdl; fdl = fdl->next)
139                     if (strcmp(fdl->nconf->nc_netid, netid) == 0)
140                               break;
141           if (fdl == NULL)
142                     return (TRUE);
143           return (check_bound(fdl, uaddr));
144 }
145 
146 /*
147  * Returns NULL if there was some system error.
148  * Returns "" if the address was not bound, i.e the server crashed.
149  * Returns the merged address otherwise.
150  */
151 char *
mergeaddr(SVCXPRT * xprt,char * netid,char * uaddr,char * saddr)152 mergeaddr(SVCXPRT *xprt, char *netid, char *uaddr, char *saddr)
153 {
154           struct fdlist *fdl;
155           char *c_uaddr, *s_uaddr, *m_uaddr, *allocated_uaddr = NULL;
156 
157           for (fdl = fdhead; fdl; fdl = fdl->next)
158                     if (strcmp(fdl->nconf->nc_netid, netid) == 0)
159                               break;
160           if (fdl == NULL)
161                     return (NULL);
162           if (check_bound(fdl, uaddr) == FALSE)
163                     /* that server died */
164                     return (nullstring);
165           /*
166            * If saddr is not NULL, the remote client may have included the
167            * address by which it contacted us.  Use that for the "client" uaddr,
168            * otherwise use the info from the SVCXPRT.
169            */
170           if (saddr != NULL) {
171                     c_uaddr = saddr;
172           } else {
173                     c_uaddr = taddr2uaddr(fdl->nconf, svc_getrpccaller(xprt));
174                     if (c_uaddr == NULL) {
175                               syslog(LOG_ERR, "taddr2uaddr failed for %s",
176                                         fdl->nconf->nc_netid);
177                               return (NULL);
178                     }
179                     allocated_uaddr = c_uaddr;
180           }
181 
182 #ifdef ND_DEBUG
183           if (debugging) {
184                     if (saddr == NULL) {
185                               fprintf(stderr, "mergeaddr: client uaddr = %s\n",
186                                   c_uaddr);
187                     } else {
188                               fprintf(stderr, "mergeaddr: contact uaddr = %s\n",
189                                   c_uaddr);
190                     }
191           }
192 #endif
193           s_uaddr = uaddr;
194           /*
195            * This is all we should need for IP 4 and 6
196            */
197           m_uaddr = addrmerge(svc_getrpccaller(xprt), s_uaddr, c_uaddr, netid);
198 #ifdef ND_DEBUG
199           if (debugging)
200                     fprintf(stderr, "mergeaddr: uaddr = %s, merged uaddr = %s\n",
201                                         uaddr, m_uaddr);
202 #endif
203           if (allocated_uaddr != NULL)
204                     free(allocated_uaddr);
205           return (m_uaddr);
206 }
207 
208 /*
209  * Returns a netconf structure from its internal list.  This
210  * structure should not be freed.
211  */
212 struct netconfig *
rpcbind_get_conf(char * netid)213 rpcbind_get_conf(char *netid)
214 {
215           struct fdlist *fdl;
216 
217           for (fdl = fdhead; fdl; fdl = fdl->next)
218                     if (strcmp(fdl->nconf->nc_netid, netid) == 0)
219                               break;
220           if (fdl == NULL)
221                     return (NULL);
222           return (fdl->nconf);
223 }
224