2fb9cd422ba8215e39bb9820d8b8c26c202302dc
[openafs.git] / src / libafscp / afscp_server.c
1 /* AUTORIGHTS
2 Copyright (C) 2003 - 2010 Chaskiel Grundman
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
7 are met:
8
9 1. Redistributions of source code must retain the above copyright
10    notice, this list of conditions and the following disclaimer.
11
12 2. Redistributions in binary form must reproduce the above copyright
13    notice, this list of conditions and the following disclaimer in the
14    documentation and/or other materials provided with the distribution.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 #include <afs/param.h>
28 #include <afs/afsint.h>
29 #include <afs/vlserver.h>
30 #include <afs/vldbint.h>
31 #include <afs/volint.h>
32 #include <afs/cellconfig.h>
33 #ifndef AFSCONF_CLIENTNAME
34 #include <afs/dirpath.h>
35 #define AFSCONF_CLIENTNAME AFSDIR_CLIENT_ETC_DIRPATH
36 #endif
37 #include <stdlib.h>
38 #include <string.h>
39 #include <rx/rx.h>
40 #include "afscp.h"
41 #include "afscp_internal.h"
42
43 static int afs_ncells=0,afs_cellsalloced=0;
44 static struct afs_cell *allcells=NULL;
45 static int afs_nservers=0,afs_srvsalloced=0;
46 static struct afs_server **allservers=NULL;
47 static char *defcell;
48 int afs_errno=0;
49
50 struct afs_cell *afs_cellbyid(int id)
51 {
52      if (id >= afs_ncells)
53           return NULL;
54      return &allcells[id];
55 }
56
57 struct afs_cell *afs_cellbyname(const char *cellname)
58 {
59      int i;
60      struct afs_cell *newlist, *thecell;
61
62      for (i=0;i<afs_ncells;i++) {
63           if (!strcmp(allcells[i].name, cellname))
64                return &allcells[i];
65      }
66      if (afs_ncells >= afs_cellsalloced) {
67           if (afs_cellsalloced)
68                afs_cellsalloced = afs_cellsalloced *2;
69           else
70                afs_cellsalloced = 4;
71           newlist=realloc(allcells, afs_cellsalloced * sizeof(struct afs_cell));
72           if (!newlist)
73                return NULL;
74           allcells=newlist;
75      }
76      thecell=&allcells[afs_ncells];
77      memset(thecell, 0, sizeof(struct afs_cell));
78      strcpy(thecell->name, cellname);
79      if (_GetSecurityObject(thecell))
80        return NULL;
81      if (_GetVLservers(thecell)) {
82        RXS_Close(thecell->security);
83        return NULL;
84      }
85      thecell->id=afs_ncells++;
86      return thecell;
87 }
88 struct afs_cell *afs_defaultcell(void)
89 {
90      struct afsconf_dir *dir;
91      char localcell[MAXCELLCHARS+1];
92      int code;
93
94
95      if (defcell) {
96           return afs_cellbyname(defcell);
97      }
98
99      dir=afsconf_Open(AFSCONF_CLIENTNAME);
100      if (!dir) {
101           afs_errno=AFSCONF_NODB;
102           return NULL;
103      }
104      code=afsconf_GetLocalCell(dir, localcell, MAXCELLCHARS);
105      if (code){
106           afs_errno=code;
107           return NULL;
108      }
109      afsconf_Close(dir);
110      return afs_cellbyname(localcell);
111 }
112
113 int afs_setdefaultcell(const char *cellname) {
114      struct afs_cell *this;
115      char *newdefcell;
116      if (!cellname) {
117           if (defcell)
118                free(defcell);
119           defcell=NULL;
120           return 0;
121      }
122
123      this=afs_cellbyname(cellname);
124      if (!this)
125           return -1;
126      newdefcell=strdup(cellname);
127      if (!newdefcell)
128         return -1;
129      if (defcell)
130           free(defcell);
131      defcell = newdefcell;
132      return 0;
133 }
134
135 int afs_cellid(struct afs_cell *cell) {
136         return cell->id;
137 }
138
139 static void _xdr_free(bool_t (*fn)(XDR *xdrs, void *obj), void *obj) {
140      XDR xdrs;
141      xdrs.x_op=XDR_FREE;
142      fn(&xdrs, obj);
143 }
144 static bool_t _xdr_bulkaddrs(XDR *xdrs, void *objp) {
145      return xdr_bulkaddrs(xdrs, objp);
146 }
147
148
149 struct afs_server *afs_serverbyid(struct afs_cell *thecell, afsUUID *u)
150 {
151      /* impliment uniquifiers? */
152      int i;
153      struct afs_server **newlist;
154      struct afs_server **newall;
155      struct afs_server *ret;
156      afsUUID tmp;
157      bulkaddrs addrs;
158      struct ListAddrByAttributes attrs;
159      afs_int32 nentries, uniq;
160
161      char s[512];
162
163      afsUUID_to_string(u, s, 511);
164      afscp_dprintf(("GetServerByID %s\n", s));
165
166      for (i=0;i<thecell->nservers;i++) {
167           if (afs_uuid_equal(&thecell->fsservers[i]->id, u))
168                return thecell->fsservers[i];
169      }
170
171      if (thecell->nservers >= thecell->srvsalloced) {
172           if (thecell->srvsalloced)
173                thecell->srvsalloced = thecell->srvsalloced *2;
174           else
175                thecell->srvsalloced = 4;
176           newlist=realloc(thecell->fsservers,
177                           thecell->srvsalloced * sizeof(struct afs_server *));
178           if (!newlist)
179                return NULL;
180           thecell->fsservers=newlist;
181      }
182      ret=malloc(sizeof(struct afs_server));
183      if (!ret)
184           return NULL;
185      thecell->fsservers[thecell->nservers]=ret;
186      memmove(&ret->id, u, sizeof(afsUUID));
187      ret->cell=thecell->id;
188      memset(&tmp, 0, sizeof(tmp));
189      memset(&addrs, 0, sizeof(addrs));
190      memset(&attrs, 0, sizeof(attrs));
191      attrs.Mask = VLADDR_UUID;
192      memmove(&attrs.uuid, u, sizeof(afsUUID));
193
194      if (ubik_VL_GetAddrsU(thecell->vlservers, 0, &attrs, &tmp,
195                       &uniq, &nentries, &addrs))
196           return NULL;
197      if (nentries > MAXADDRS) {
198           nentries=MAXADDRS;
199           /* XXX I don't want to do *that* much dynamic allocation */
200           abort();
201      }
202
203      ret->naddrs=nentries;
204      for (i=0; i< nentries;i++) {
205           ret->addrs[i]=htonl(addrs.bulkaddrs_val[i]);
206           ret->conns[i]=rx_NewConnection(ret->addrs[i],
207                                          htons(AFSCONF_FILEPORT),
208                                          1, thecell->security,
209                                          thecell->scindex);
210      }
211      _xdr_free(_xdr_bulkaddrs, &addrs);
212      thecell->nservers++;
213
214      if (afs_nservers >= afs_srvsalloced) {
215           if (afs_srvsalloced)
216                afs_srvsalloced = afs_srvsalloced *2;
217           else
218                afs_srvsalloced = 4;
219           newall=realloc(allservers,
220                           afs_srvsalloced * sizeof(struct afs_server *));
221           if (!newall)
222                return ret;
223           allservers=newall;
224      }
225      ret->index=afs_nservers;
226      allservers[afs_nservers++]=ret;
227      return ret;
228 }
229
230 struct afs_server *afs_serverbyaddr(struct afs_cell *thecell, afs_uint32 addr)
231 {
232      /* impliment uniquifiers? */
233      int i,j;
234      struct afs_server **newlist;
235      struct afs_server **newall;
236      struct afs_server *ret;
237      afsUUID uuid;
238      bulkaddrs addrs;
239      struct ListAddrByAttributes attrs;
240      afs_int32 nentries, code, uniq;
241
242
243      for (i=0;i<thecell->nservers;i++) {
244           ret=thecell->fsservers[i];
245           for (j=0;j<ret->naddrs;j++)
246                if (ret->addrs[j] == htonl(addr))
247                     return ret;
248      }
249
250      if (thecell->nservers >= thecell->srvsalloced) {
251           if (thecell->srvsalloced)
252                thecell->srvsalloced = thecell->srvsalloced *2;
253           else
254                thecell->srvsalloced = 4;
255           newlist=realloc(thecell->fsservers,
256                           thecell->srvsalloced * sizeof(struct afs_server));
257           if (!newlist)
258                return NULL;
259           thecell->fsservers=newlist;
260      }
261      ret=malloc(sizeof(struct afs_server));
262      if (!ret)
263           return NULL;
264      thecell->fsservers[thecell->nservers]=ret;
265      ret->cell=thecell->id;
266      memset(&uuid, 0, sizeof(uuid));
267      memset(&addrs, 0, sizeof(addrs));
268      memset(&attrs, 0, sizeof(attrs));
269      attrs.Mask = VLADDR_IPADDR;
270      attrs.ipaddr=addr;
271
272
273      if ((code=ubik_VL_GetAddrsU(thecell->vlservers, 0, &attrs, &uuid,
274                       &uniq, &nentries, &addrs))) {
275        memset(&ret->id, 0, sizeof(uuid));
276        ret->naddrs=1;
277        ret->addrs[0]=htonl(addr);
278        ret->conns[0]=rx_NewConnection(ret->addrs[0],
279                                       htons(AFSCONF_FILEPORT),
280                                       1, thecell->security,
281                                       thecell->scindex);
282      } else {
283        char s[512];
284
285        afsUUID_to_string(&uuid, s, 511);
286        afscp_dprintf(("GetServerByAddr 0x%x -> uuid %s\n", addr, s));
287
288        if (nentries > MAXADDRS) {
289          nentries=MAXADDRS;
290          /* XXX I don't want to do *that* much dynamic allocation */
291          abort();
292        }
293        memmove(&ret->id, &uuid, sizeof(afsUUID));
294
295        ret->naddrs=nentries;
296        for (i=0; i< nentries;i++) {
297          ret->addrs[i]=htonl(addrs.bulkaddrs_val[i]);
298          ret->conns[i]=rx_NewConnection(ret->addrs[i],
299                                         htons(AFSCONF_FILEPORT),
300                                         1, thecell->security,
301                                         thecell->scindex);
302        }
303        _xdr_free(_xdr_bulkaddrs, &addrs);
304      }
305
306      thecell->nservers++;
307      if (afs_nservers >= afs_srvsalloced) {
308           if (afs_srvsalloced)
309                afs_srvsalloced = afs_srvsalloced *2;
310           else
311                afs_srvsalloced = 4;
312           newall=realloc(allservers,
313                           afs_srvsalloced * sizeof(struct afs_server *));
314           if (!newall)
315                return ret;
316           allservers=newall;
317      }
318      ret->index=afs_nservers;
319      allservers[afs_nservers++]=ret;
320      return ret;
321 }
322
323 struct afs_server *afs_anyserverbyaddr(afs_uint32 addr)
324 {
325      /* no idea what this means: "impliment uniquifiers?" */
326      int i,j;
327      struct afs_server *ret;
328
329      for (i=0;i<afs_nservers;i++) {
330           ret=allservers[i];
331           for (j=0;j<ret->naddrs;j++)
332                if (ret->addrs[j] == htonl(addr))
333                     return ret;
334      }
335      return NULL;
336 }
337
338 struct afs_server *afs_serverbyindex(int i)
339 {
340
341      if (i>= afs_nservers)
342           return NULL;
343      return allservers[i];
344 }
345
346 struct rx_connection *afs_serverconnection(const struct afs_server *srv, int i) {
347   if (i >= srv->naddrs)
348     return NULL;
349   return srv->conns[i];
350 }