Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / auth / writeconfig.c
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 #include <roken.h>
14 #include <afs/opr.h>
15
16 #include <afs/pthread_glock.h>
17 #include <afs/afsutil.h>
18 #include <rx/rxkad.h>
19
20 #include "cellconfig.h"
21 #include "keys.h"
22
23 /* write ThisCell and CellServDB containing exactly one cell's info specified
24 by acellInfo parm. Useful only on the server (which describes only one cell).
25 */
26
27 static int
28 VerifyEntries(struct afsconf_cell *aci)
29 {
30 int i;
31 struct hostent *th;
32
33 for (i = 0; i < aci->numServers; i++) {
34 if (aci->hostAddr[i].sin_addr.s_addr == 0) {
35 /* no address spec'd */
36 if (*(aci->hostName[i]) != 0) {
37 int code;
38 struct addrinfo hints;
39 struct addrinfo *result;
40 struct addrinfo *rp;
41
42 memset(&hints, 0, sizeof(struct addrinfo));
43 hints.ai_family = AF_INET;
44 hints.ai_socktype = SOCK_DGRAM;
45
46 code = getaddrinfo(aci->hostName[i], NULL, &hints, &result);
47 if (code) {
48 printf("Host %s not found in host database...\n",
49 aci->hostName[i]);
50 return AFSCONF_FAILURE;
51 }
52 for (rp = result; rp != NULL; rp = rp->ai_next) {
53 struct sockaddr_in *sa = (struct sockaddr_in *)rp->ai_addr;
54 if (!rx_IsLoopbackAddr(ntohl(sa->sin_addr.s_addr))) {
55 aci->hostAddr[i].sin_addr.s_addr = sa->sin_addr.s_addr;
56 break;
57 }
58 }
59 freeaddrinfo(result);
60 if (aci->hostAddr[i].sin_addr.s_addr == 0) {
61 printf("No non-loopback addresses found for host %s\n",
62 aci->hostName[i]);
63 return AFSCONF_FAILURE;
64 }
65 }
66 /* otherwise we're deleting this entry */
67 } else {
68 /* address spec'd, perhaps no name known */
69 if (aci->hostName[i][0] != 0)
70 continue; /* name known too */
71 /* figure out name, if possible */
72 th = gethostbyaddr((char *)(&aci->hostAddr[i].sin_addr), 4,
73 AF_INET);
74 if (!th) {
75 strcpy(aci->hostName[i], "UNKNOWNHOST");
76 } else {
77 if (strlcpy(aci->hostName[i],
78 th->h_name,
79 sizeof(aci->hostName[i]))
80 >= sizeof(aci->hostName[i])) {
81 strcpy(aci->hostName[i], "UNKNOWNHOST");
82 }
83 }
84 }
85 }
86 return 0;
87 }
88
89 /* Changed the interface to accept the afsconf_dir datastructure.
90 This is a handle to the internal cache that is maintained by the bosserver.
91 */
92
93 int
94 afsconf_SetCellInfo(struct afsconf_dir *adir, const char *apath,
95 struct afsconf_cell *acellInfo)
96 {
97 afs_int32 code;
98
99 code = afsconf_SetExtendedCellInfo(adir, apath, acellInfo, NULL);
100 return code;
101 }
102
103 int
104 afsconf_SetExtendedCellInfo(struct afsconf_dir *adir,
105 const char *apath,
106 struct afsconf_cell *acellInfo, char clones[])
107 {
108 afs_int32 code;
109 int fd;
110 char tbuffer[1024];
111 FILE *tf;
112 afs_int32 i;
113
114 LOCK_GLOBAL_MUTEX;
115 /* write ThisCell file */
116 strcompose(tbuffer, 1024, apath, "/", AFSDIR_THISCELL_FILE, (char *)NULL);
117
118 fd = open(tbuffer, O_RDWR | O_CREAT | O_TRUNC, 0666);
119 if (fd < 0) {
120 UNLOCK_GLOBAL_MUTEX;
121 return errno;
122 }
123 i = (int)strlen(acellInfo->name);
124 code = write(fd, acellInfo->name, i);
125 if (code != i) {
126 UNLOCK_GLOBAL_MUTEX;
127 return AFSCONF_FAILURE;
128 }
129 if (close(fd) < 0) {
130 UNLOCK_GLOBAL_MUTEX;
131 return errno;
132 }
133
134 /* make sure we have both name and address for each host, looking up other
135 * if need be */
136 code = VerifyEntries(acellInfo);
137 if (code) {
138 UNLOCK_GLOBAL_MUTEX;
139 return code;
140 }
141
142 /* write CellServDB */
143 strcompose(tbuffer, 1024, apath, "/", AFSDIR_CELLSERVDB_FILE, (char *)NULL);
144 tf = fopen(tbuffer, "w");
145 if (!tf) {
146 UNLOCK_GLOBAL_MUTEX;
147 return AFSCONF_NOTFOUND;
148 }
149 fprintf(tf, ">%s #Cell name\n", acellInfo->name);
150 for (i = 0; i < acellInfo->numServers; i++) {
151 code = acellInfo->hostAddr[i].sin_addr.s_addr; /* net order */
152 if (code == 0)
153 continue; /* delete request */
154 code = ntohl(code); /* convert to host order */
155 if (clones && clones[i])
156 fprintf(tf, "[%d.%d.%d.%d] #%s\n", (code >> 24) & 0xff,
157 (code >> 16) & 0xff, (code >> 8) & 0xff, code & 0xff,
158 acellInfo->hostName[i]);
159 else
160 fprintf(tf, "%d.%d.%d.%d #%s\n", (code >> 24) & 0xff,
161 (code >> 16) & 0xff, (code >> 8) & 0xff, code & 0xff,
162 acellInfo->hostName[i]);
163 }
164 if (ferror(tf)) {
165 fclose(tf);
166 UNLOCK_GLOBAL_MUTEX;
167 return AFSCONF_FAILURE;
168 }
169 code = fclose(tf);
170
171 /* Reset the timestamp in the cache, so that
172 * the CellServDB is read into the cache next time.
173 * Resolves the lost update problem due to an inconsistent cache
174 */
175 if (adir)
176 adir->timeRead = 0;
177
178 UNLOCK_GLOBAL_MUTEX;
179 if (code == EOF)
180 return AFSCONF_FAILURE;
181 return 0;
182 }