Update NEWS for 1.6.22
[pkg-k5-afs_openafs.git] / src / libafscp / afscp_server.c
blobe67ee48a9dc11ed7dca12d6e348952c47628fe96
1 /* AUTORIGHTS
2 Copyright (C) 2003 - 2010 Chaskiel Grundman
3 All rights reserved
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
9 1. Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
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.
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.
27 #include <afsconfig.h>
28 #include <afs/param.h>
30 #include <afs/vlserver.h>
31 #include <afs/vldbint.h>
32 #include <afs/volint.h>
33 #include <afs/cellconfig.h>
34 #ifndef AFSCONF_CLIENTNAME
35 #include <afs/dirpath.h>
36 #define AFSCONF_CLIENTNAME AFSDIR_CLIENT_ETC_DIRPATH
37 #endif
38 #include <rx/rx.h>
39 #ifdef HAVE_KERBEROS
40 # define KERBEROS_APPLE_DEPRECATED(x)
41 # include <krb5.h>
42 #endif
43 #include "afscp.h"
44 #include "afscp_internal.h"
46 static int afscp_ncells = 0, afscp_cellsalloced = 0;
47 static struct afscp_cell *allcells = NULL;
48 static int afscp_nservers = 0, afscp_srvsalloced = 0;
49 static struct afscp_server **allservers = NULL;
50 static char *defcell = NULL;
51 static char *defrealm = NULL;
52 int afscp_errno = 0;
54 void
55 afscp_FreeAllCells(void)
57 int i;
59 if (allcells == NULL)
60 return;
62 for (i = 0; i < afscp_ncells; i++) {
63 if (allcells[i].realm != NULL)
64 free(allcells[i].realm);
65 if (allcells[i].fsservers != NULL)
66 free(allcells[i].fsservers);
69 free(allcells);
70 allcells = NULL;
71 afscp_ncells = 0;
72 afscp_cellsalloced = 0;
75 void
76 afscp_FreeAllServers(void)
78 if (allservers == NULL)
79 return;
80 free(allservers);
81 allservers = NULL;
82 afscp_nservers = 0;
83 afscp_srvsalloced = 0;
86 struct afscp_cell *
87 afscp_CellById(int id)
89 if (id >= afscp_ncells || id < 0)
90 return NULL;
91 return &allcells[id];
94 struct afscp_cell *
95 afscp_CellByName(const char *cellname, const char *realmname)
97 int i;
98 struct afscp_cell *newlist, *thecell;
100 if (cellname == NULL) {
101 return NULL;
103 for (i = 0; i < afscp_ncells; i++) {
104 if (strcmp(allcells[i].name, cellname) == 0) {
105 return &allcells[i];
108 if (afscp_ncells >= afscp_cellsalloced) {
109 if (afscp_cellsalloced)
110 afscp_cellsalloced = afscp_cellsalloced * 2;
111 else
112 afscp_cellsalloced = 4;
113 newlist =
114 realloc(allcells, afscp_cellsalloced * sizeof(struct afscp_cell));
115 if (newlist == NULL) {
116 return NULL;
118 allcells = newlist;
120 thecell = &allcells[afscp_ncells];
121 memset(thecell, 0, sizeof(struct afscp_cell));
122 strlcpy(thecell->name, cellname, sizeof(thecell->name));
123 if (realmname != NULL) {
124 thecell->realm = strdup(realmname);
125 } else {
126 thecell->realm = NULL;
128 if (_GetSecurityObject(thecell)) {
129 return NULL;
131 if (_GetVLservers(thecell)) {
132 RXS_Close(thecell->security);
133 return NULL;
135 thecell->id = afscp_ncells++;
136 return thecell;
139 struct afscp_cell *
140 afscp_DefaultCell(void)
142 struct afsconf_dir *dir;
143 char localcell[MAXCELLCHARS + 1];
144 int code;
146 if (defcell) {
147 return afscp_CellByName(defcell, defrealm);
150 dir = afsconf_Open(AFSCONF_CLIENTNAME);
151 if (dir == NULL) {
152 afscp_errno = AFSCONF_NODB;
153 return NULL;
155 code = afsconf_GetLocalCell(dir, localcell, MAXCELLCHARS);
156 if (code != 0) {
157 afscp_errno = code;
158 return NULL;
160 afsconf_Close(dir);
161 return afscp_CellByName(localcell, defrealm);
165 afscp_SetDefaultRealm(const char *realmname)
167 char *newdefrealm;
169 #ifdef HAVE_KERBEROS
170 /* krb5_error_code k5ec; */
171 krb5_context k5con;
172 int code;
174 if (realmname == NULL) {
175 if (defrealm != NULL)
176 free(defrealm);
177 defrealm = NULL;
178 return 0;
181 code = krb5_init_context(&k5con); /* see aklog.c main() */
182 if (code != 0) {
183 return -1;
185 /* k5ec = */
186 krb5_set_default_realm(k5con, realmname);
187 /* if (k5ec != KRB5KDC_ERR_NONE) {
188 * com_err("libafscp", k5ec, "k5ec = %d (compared to KRB5KDC_ERR_NONE = %d)", k5ec, KRB5KDC_ERR_NONE);
189 * return -1;
190 * } */
191 /* krb5_set_default_realm() is returning 0 on success, not KRB5KDC_ERR_NONE */
192 #endif /* HAVE_KERBEROS */
194 newdefrealm = strdup(realmname);
195 if (newdefrealm == NULL) {
196 return -1;
198 if (defrealm != NULL)
199 free(defrealm);
200 defrealm = newdefrealm;
201 return 0;
205 afscp_SetDefaultCell(const char *cellname)
207 struct afscp_cell *this;
208 char *newdefcell;
209 if (cellname == NULL) {
210 if (defcell != NULL)
211 free(defcell);
212 defcell = NULL;
213 return 0;
216 this = afscp_CellByName(cellname, defrealm);
217 if (this == NULL) {
218 return -1;
220 newdefcell = strdup(cellname);
221 if (newdefcell == NULL) {
222 return -1;
224 if (defcell != NULL)
225 free(defcell);
226 defcell = newdefcell;
227 return 0;
231 afscp_CellId(struct afscp_cell *cell)
233 if (cell == NULL)
234 return -1;
235 return cell->id;
238 static void
239 _xdr_free(bool_t(*fn) (XDR * xdrs, void *obj), void *obj)
241 XDR xdrs;
242 xdrs.x_op = XDR_FREE;
243 fn(&xdrs, obj);
246 static bool_t
247 _xdr_bulkaddrs(XDR * xdrs, void *objp)
249 return xdr_bulkaddrs(xdrs, objp);
252 /* takes server in host byte order */
253 struct afscp_server *
254 afscp_ServerById(struct afscp_cell *thecell, afsUUID * u)
256 /* impliment uniquifiers? */
257 int i, code;
258 struct afscp_server **newlist;
259 struct afscp_server **newall;
260 struct afscp_server *ret = NULL;
261 afsUUID tmp;
262 bulkaddrs addrs;
263 struct ListAddrByAttributes attrs;
264 afs_int32 nentries, uniq;
265 char s[512];
266 afsUUID_to_string(u, s, 511);
267 afs_dprintf(("GetServerByID %s\n", s));
269 for (i = 0; i < thecell->nservers; i++) {
270 if (afs_uuid_equal(&thecell->fsservers[i]->id, u)) {
271 return thecell->fsservers[i];
275 if (thecell->nservers >= thecell->srvsalloced) {
276 if (thecell->srvsalloced)
277 thecell->srvsalloced = thecell->srvsalloced * 2;
278 else
279 thecell->srvsalloced = 4;
280 newlist = realloc(thecell->fsservers,
281 thecell->srvsalloced *
282 sizeof(struct afscp_server *));
283 if (newlist == NULL) {
284 return NULL;
286 thecell->fsservers = newlist;
288 ret = malloc(sizeof(struct afscp_server));
289 if (ret == NULL) {
290 return NULL;
292 memset(ret, 0, sizeof(struct afscp_server));
293 thecell->fsservers[thecell->nservers] = ret;
294 memmove(&ret->id, u, sizeof(afsUUID));
295 ret->cell = thecell->id;
296 memset(&tmp, 0, sizeof(tmp));
297 memset(&addrs, 0, sizeof(addrs));
298 memset(&attrs, 0, sizeof(attrs));
299 attrs.Mask = VLADDR_UUID;
300 memmove(&attrs.uuid, u, sizeof(afsUUID));
302 code = ubik_VL_GetAddrsU(thecell->vlservers, 0, &attrs, &tmp,
303 &uniq, &nentries, &addrs);
304 if (code != 0) {
305 return NULL;
307 if (nentries > AFS_MAXHOSTS) {
308 nentries = AFS_MAXHOSTS;
309 /* XXX I don't want to do *that* much dynamic allocation */
310 abort();
313 ret->naddrs = nentries;
314 for (i = 0; i < nentries; i++) {
315 ret->addrs[i] = htonl(addrs.bulkaddrs_val[i]);
316 ret->conns[i] = rx_NewConnection(ret->addrs[i],
317 htons(AFSCONF_FILEPORT),
318 1, thecell->security,
319 thecell->scindex);
321 _xdr_free(_xdr_bulkaddrs, &addrs);
322 thecell->nservers++;
324 if (afscp_nservers >= afscp_srvsalloced) {
325 if (afscp_srvsalloced)
326 afscp_srvsalloced = afscp_srvsalloced * 2;
327 else
328 afscp_srvsalloced = 4;
329 newall = realloc(allservers,
330 afscp_srvsalloced * sizeof(struct afscp_server *));
331 if (newall == NULL) {
332 return ret;
334 allservers = newall;
336 ret->index = afscp_nservers;
337 allservers[afscp_nservers++] = ret;
338 return ret;
341 /* takes server in host byte order */
342 struct afscp_server *
343 afscp_ServerByAddr(struct afscp_cell *thecell, afs_uint32 addr)
345 /* implement uniquifiers? */
346 int i, j;
347 struct afscp_server **newlist;
348 struct afscp_server **newall;
349 struct afscp_server *ret = NULL;
350 afsUUID uuid;
351 bulkaddrs addrs;
352 struct ListAddrByAttributes attrs;
353 afs_int32 nentries, code, uniq;
355 if (thecell == NULL)
356 return ret; /* cannot continue without thecell */
358 for (i = 0; i < thecell->nservers; i++) {
359 ret = thecell->fsservers[i];
360 for (j = 0; j < ret->naddrs; j++)
361 if (ret->addrs[j] == htonl(addr)) {
362 return ret;
366 if (thecell->nservers >= thecell->srvsalloced) {
367 if (thecell->srvsalloced)
368 thecell->srvsalloced = thecell->srvsalloced * 2;
369 else
370 thecell->srvsalloced = 4;
371 newlist = realloc(thecell->fsservers,
372 thecell->srvsalloced * sizeof(struct afscp_server));
373 if (newlist == NULL) {
374 return NULL;
376 thecell->fsservers = newlist;
378 ret = malloc(sizeof(struct afscp_server));
379 if (ret == NULL) {
380 return NULL;
382 memset(ret, 0, sizeof(struct afscp_server));
383 thecell->fsservers[thecell->nservers] = ret;
384 ret->cell = thecell->id;
385 memset(&uuid, 0, sizeof(uuid));
386 memset(&addrs, 0, sizeof(addrs));
387 memset(&attrs, 0, sizeof(attrs));
388 attrs.Mask = VLADDR_IPADDR;
389 attrs.ipaddr = addr;
391 code = ubik_VL_GetAddrsU(thecell->vlservers, 0, &attrs, &uuid,
392 &uniq, &nentries, &addrs);
393 if (code != 0) {
394 memset(&ret->id, 0, sizeof(uuid));
395 ret->naddrs = 1;
396 ret->addrs[0] = htonl(addr);
397 ret->conns[0] = rx_NewConnection(ret->addrs[0],
398 htons(AFSCONF_FILEPORT),
399 1, thecell->security,
400 thecell->scindex);
401 } else {
402 char s[512];
404 afsUUID_to_string(&uuid, s, 511);
405 afs_dprintf(("GetServerByAddr 0x%x -> uuid %s\n", addr, s));
407 if (nentries > AFS_MAXHOSTS) {
408 nentries = AFS_MAXHOSTS;
409 /* XXX I don't want to do *that* much dynamic allocation */
410 abort();
412 memmove(&ret->id, &uuid, sizeof(afsUUID));
414 ret->naddrs = nentries;
415 for (i = 0; i < nentries; i++) {
416 ret->addrs[i] = htonl(addrs.bulkaddrs_val[i]);
417 ret->conns[i] = rx_NewConnection(ret->addrs[i],
418 htons(AFSCONF_FILEPORT),
419 1, thecell->security,
420 thecell->scindex);
422 _xdr_free(_xdr_bulkaddrs, &addrs);
425 thecell->nservers++;
426 if (afscp_nservers >= afscp_srvsalloced) {
427 if (afscp_srvsalloced)
428 afscp_srvsalloced = afscp_srvsalloced * 2;
429 else
430 afscp_srvsalloced = 4;
431 newall = realloc(allservers,
432 afscp_srvsalloced * sizeof(struct afscp_server *));
433 if (newall == NULL) {
434 return ret;
436 allservers = newall;
438 ret->index = afscp_nservers;
439 allservers[afscp_nservers++] = ret;
440 return ret;
443 /* takes server in host byte order */
444 struct afscp_server *
445 afscp_AnyServerByAddr(afs_uint32 addr)
447 /* implement uniquifiers? */
448 int i, j;
449 struct afscp_server *ret = NULL;
451 if (allservers == NULL)
452 return ret;
453 for (i = 0; i < afscp_nservers; i++) {
454 ret = allservers[i];
455 for (j = 0; j < ret->naddrs; j++)
456 if (ret->addrs[j] == htonl(addr)) {
457 return ret;
460 return NULL;
463 /* takes server in host byte order */
464 struct afscp_server *
465 afscp_ServerByIndex(int i)
467 if (i >= afscp_nservers || i < 0)
468 return NULL;
469 return allservers[i];
472 struct rx_connection *
473 afscp_ServerConnection(const struct afscp_server *srv, int i)
475 if (srv == NULL)
476 return NULL;
477 if (i >= srv->naddrs || i < 0)
478 return NULL;
479 return srv->conns[i];