death to register
[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
14 #include <afs/pthread_glock.h>
15 #include <afs/afsutil.h>
16 #include <sys/types.h>
17 #ifdef AFS_NT40_ENV
18 #include <winsock2.h>
19 #include <fcntl.h>
20 #include <io.h>
21 #else
22 #include <sys/file.h>
23 #include <sys/socket.h>
24 #include <netinet/in.h>
25 #include <netdb.h>
26 #endif
27 #include <stdio.h>
28 #include <errno.h>
29 #include <string.h>
30 #ifdef HAVE_FCNTL_H
31 #include <fcntl.h>
32 #endif
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36 #include <rx/rxkad.h>
37 #include "cellconfig.h"
38 #include "keys.h"
39
40 /* write ThisCell and CellServDB containing exactly one cell's info specified
41     by acellInfo parm.   Useful only on the server (which describes only one cell).
42 */
43
44 static int
45 VerifyEntries(struct afsconf_cell *aci)
46 {
47     int i;
48     struct hostent *th;
49
50     for (i = 0; i < aci->numServers; i++) {
51         if (aci->hostAddr[i].sin_addr.s_addr == 0) {
52             /* no address spec'd */
53             if (*(aci->hostName[i]) != 0) {
54                 th = gethostbyname(aci->hostName[i]);
55                 if (!th) {
56                     printf("Host %s not found in host database...\n",
57                            aci->hostName[i]);
58                     return AFSCONF_FAILURE;
59                 }
60                 memcpy(&aci->hostAddr[i].sin_addr, th->h_addr,
61                        sizeof(afs_int32));
62             }
63             /* otherwise we're deleting this entry */
64         } else {
65             /* address spec'd, perhaps no name known */
66             if (aci->hostName[i][0] != 0)
67                 continue;       /* name known too */
68             /* figure out name, if possible */
69             th = gethostbyaddr((char *)(&aci->hostAddr[i].sin_addr), 4,
70                                AF_INET);
71             if (!th) {
72                 strcpy(aci->hostName[i], "UNKNOWNHOST");
73             } else {
74                 strcpy(aci->hostName[i], th->h_name);
75             }
76         }
77     }
78     return 0;
79 }
80
81 /* Changed the interface to accept the afsconf_dir datastructure.
82    This is a handle to the internal cache that is maintained by the bosserver.
83    */
84
85 int
86 afsconf_SetCellInfo(struct afsconf_dir *adir, const char *apath, 
87                     struct afsconf_cell *acellInfo)
88 {
89     afs_int32 code;
90
91     code = afsconf_SetExtendedCellInfo(adir, apath, acellInfo, NULL);
92     return code;
93 }
94
95 int
96 afsconf_SetExtendedCellInfo(struct afsconf_dir *adir, 
97                             const char *apath, 
98                             struct afsconf_cell *acellInfo, char clones[])
99 {
100     afs_int32 code;
101     int fd;
102     char tbuffer[1024];
103     FILE *tf;
104     afs_int32 i;
105
106     LOCK_GLOBAL_MUTEX;
107     /* write ThisCell file */
108     strcompose(tbuffer, 1024, apath, "/", AFSDIR_THISCELL_FILE, NULL);
109
110     fd = open(tbuffer, O_RDWR | O_CREAT | O_TRUNC, 0666);
111     if (fd < 0) {
112         UNLOCK_GLOBAL_MUTEX;
113         return errno;
114     }
115     i = (int)strlen(acellInfo->name);
116     code = write(fd, acellInfo->name, i);
117     if (code != i) {
118         UNLOCK_GLOBAL_MUTEX;
119         return AFSCONF_FAILURE;
120     }
121     if (close(fd) < 0) {
122         UNLOCK_GLOBAL_MUTEX;
123         return errno;
124     }
125
126     /* make sure we have both name and address for each host, looking up other
127      * if need be */
128     code = VerifyEntries(acellInfo);
129     if (code) {
130         UNLOCK_GLOBAL_MUTEX;
131         return code;
132     }
133
134     /* write CellServDB */
135     strcompose(tbuffer, 1024, apath, "/", AFSDIR_CELLSERVDB_FILE, NULL);
136     tf = fopen(tbuffer, "w");
137     if (!tf) {
138         UNLOCK_GLOBAL_MUTEX;
139         return AFSCONF_NOTFOUND;
140     }
141     fprintf(tf, ">%s    #Cell name\n", acellInfo->name);
142     for (i = 0; i < acellInfo->numServers; i++) {
143         code = acellInfo->hostAddr[i].sin_addr.s_addr;  /* net order */
144         if (code == 0)
145             continue;           /* delete request */
146         code = ntohl(code);     /* convert to host order */
147         if (clones && clones[i])
148             fprintf(tf, "[%d.%d.%d.%d]  #%s\n", (code >> 24) & 0xff,
149                     (code >> 16) & 0xff, (code >> 8) & 0xff, code & 0xff,
150                     acellInfo->hostName[i]);
151         else
152             fprintf(tf, "%d.%d.%d.%d    #%s\n", (code >> 24) & 0xff,
153                     (code >> 16) & 0xff, (code >> 8) & 0xff, code & 0xff,
154                     acellInfo->hostName[i]);
155     }
156     if (ferror(tf)) {
157         fclose(tf);
158         UNLOCK_GLOBAL_MUTEX;
159         return AFSCONF_FAILURE;
160     }
161     code = fclose(tf);
162
163     /* Reset the timestamp in the cache, so that
164      * the CellServDB is read into the cache next time.
165      * Resolves the lost update problem due to an inconsistent cache
166      */
167     if (adir)
168         adir->timeRead = 0;
169
170     UNLOCK_GLOBAL_MUTEX;
171     if (code == EOF)
172         return AFSCONF_FAILURE;
173     return 0;
174 }