mptable - raise WARNS to 6
[dragonfly.git] / usr.sbin / rpcbind / check_bound.c
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  */
33 /*
34  * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
35  */
36
37 /*
38  * check_bound.c
39  * Checks to see whether the program is still bound to the
40  * claimed address and returns the univeral merged address
41  *
42  */
43
44 #include <sys/types.h>
45 #include <sys/socket.h>
46 #include <rpc/rpc.h>
47 #include <stdio.h>
48 #include <netconfig.h>
49 #include <syslog.h>
50 #include <string.h>
51 #include <unistd.h>
52 #include <stdlib.h>
53
54 #include "rpcbind.h"
55
56 struct fdlist {
57         int fd;
58         struct netconfig *nconf;
59         struct fdlist *next;
60         int check_binding;
61 };
62
63 static struct fdlist *fdhead;   /* Link list of the check fd's */
64 static struct fdlist *fdtail;
65 static char *nullstring = "";
66
67 static bool_t   check_bound(struct fdlist *, char *uaddr);
68
69 /*
70  * Returns 1 if the given address is bound for the given addr & transport
71  * For all error cases, we assume that the address is bound
72  * Returns 0 for success.
73  */
74 static bool_t
75 check_bound(struct fdlist *fdl, char *uaddr)
76 {
77         int fd;
78         struct netbuf *na;
79         int ans;
80
81         if (fdl->check_binding == FALSE)
82                 return (TRUE);
83
84         na = uaddr2taddr(fdl->nconf, uaddr);
85         if (!na)
86                 return (TRUE); /* punt, should never happen */
87
88         fd = __rpc_nconf2fd(fdl->nconf);
89         if (fd < 0) {
90                 free(na->buf);
91                 free(na);
92                 return (TRUE);
93         }
94
95         ans = bind(fd, (struct sockaddr *)na->buf, na->len);
96
97         close(fd);
98         free(na->buf);
99         free(na);
100
101         return (ans == 0 ? FALSE : TRUE);
102 }
103
104 int
105 add_bndlist(struct netconfig *nconf, struct netbuf *baddr __unused)
106 {
107         struct fdlist *fdl;
108         struct netconfig *newnconf;
109
110         newnconf = getnetconfigent(nconf->nc_netid);
111         if (newnconf == NULL)
112                 return (-1);
113         fdl = malloc(sizeof (struct fdlist));
114         if (fdl == NULL) {
115                 freenetconfigent(newnconf);
116                 syslog(LOG_ERR, "no memory!");
117                 return (-1);
118         }
119         fdl->nconf = newnconf;
120         fdl->next = NULL;
121         if (fdhead == NULL) {
122                 fdhead = fdl;
123                 fdtail = fdl;
124         } else {
125                 fdtail->next = fdl;
126                 fdtail = fdl;
127         }
128         /* XXX no bound checking for now */
129         fdl->check_binding = FALSE;
130
131         return 0;
132 }
133
134 bool_t
135 is_bound(char *netid, char *uaddr)
136 {
137         struct fdlist *fdl;
138
139         for (fdl = fdhead; fdl; fdl = fdl->next)
140                 if (strcmp(fdl->nconf->nc_netid, netid) == 0)
141                         break;
142         if (fdl == NULL)
143                 return (TRUE);
144         return (check_bound(fdl, uaddr));
145 }
146
147 /*
148  * Returns NULL if there was some system error.
149  * Returns "" if the address was not bound, i.e the server crashed.
150  * Returns the merged address otherwise.
151  */
152 char *
153 mergeaddr(SVCXPRT *xprt, char *netid, char *uaddr, char *saddr)
154 {
155         struct fdlist *fdl;
156         char *c_uaddr, *s_uaddr, *m_uaddr, *allocated_uaddr = NULL;
157
158         for (fdl = fdhead; fdl; fdl = fdl->next)
159                 if (strcmp(fdl->nconf->nc_netid, netid) == 0)
160                         break;
161         if (fdl == NULL)
162                 return (NULL);
163         if (check_bound(fdl, uaddr) == FALSE)
164                 /* that server died */
165                 return (nullstring);
166         /*
167          * If saddr is not NULL, the remote client may have included the
168          * address by which it contacted us.  Use that for the "client" uaddr,
169          * otherwise use the info from the SVCXPRT.
170          */
171         if (saddr != NULL) {
172                 c_uaddr = saddr;
173         } else {
174                 c_uaddr = taddr2uaddr(fdl->nconf, svc_getrpccaller(xprt));
175                 if (c_uaddr == NULL) {
176                         syslog(LOG_ERR, "taddr2uaddr failed for %s",
177                                 fdl->nconf->nc_netid);
178                         return (NULL);
179                 }
180                 allocated_uaddr = c_uaddr;
181         }
182
183 #ifdef ND_DEBUG
184         if (debugging) {
185                 if (saddr == NULL) {
186                         fprintf(stderr, "mergeaddr: client uaddr = %s\n",
187                             c_uaddr);
188                 } else {
189                         fprintf(stderr, "mergeaddr: contact uaddr = %s\n",
190                             c_uaddr);
191                 }
192         }
193 #endif
194         s_uaddr = uaddr;
195         /*
196          * This is all we should need for IP 4 and 6
197          */
198         m_uaddr = addrmerge(svc_getrpccaller(xprt), s_uaddr, c_uaddr, netid);
199 #ifdef ND_DEBUG
200         if (debugging)
201                 fprintf(stderr, "mergeaddr: uaddr = %s, merged uaddr = %s\n",
202                                 uaddr, m_uaddr);
203 #endif
204         if (allocated_uaddr != NULL)
205                 free(allocated_uaddr);
206         return (m_uaddr);
207 }
208
209 /*
210  * Returns a netconf structure from its internal list.  This
211  * structure should not be freed.
212  */
213 struct netconfig *
214 rpcbind_get_conf(char *netid)
215 {
216         struct fdlist *fdl;
217
218         for (fdl = fdhead; fdl; fdl = fdl->next)
219                 if (strcmp(fdl->nconf->nc_netid, netid) == 0)
220                         break;
221         if (fdl == NULL)
222                 return (NULL);
223         return (fdl->nconf);
224 }