9d8d479cad69b76e32076cbcc355fd35e2d83078
[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                 th = gethostbyname(aci->hostName[i]);
38                 if (!th) {
39                     printf("Host %s not found in host database...\n",
40                            aci->hostName[i]);
41                     return AFSCONF_FAILURE;
42                 }
43                 memcpy(&aci->hostAddr[i].sin_addr, th->h_addr,
44                        sizeof(afs_int32));
45             }
46             /* otherwise we're deleting this entry */
47         } else {
48             /* address spec'd, perhaps no name known */
49             if (aci->hostName[i][0] != 0)
50                 continue;       /* name known too */
51             /* figure out name, if possible */
52             th = gethostbyaddr((char *)(&aci->hostAddr[i].sin_addr), 4,
53                                AF_INET);
54             if (!th) {
55                 strcpy(aci->hostName[i], "UNKNOWNHOST");
56             } else {
57                 strcpy(aci->hostName[i], th->h_name);
58             }
59         }
60     }
61     return 0;
62 }
63
64 /* Changed the interface to accept the afsconf_dir datastructure.
65    This is a handle to the internal cache that is maintained by the bosserver.
66    */
67
68 int
69 afsconf_SetCellInfo(struct afsconf_dir *adir, const char *apath,
70                     struct afsconf_cell *acellInfo)
71 {
72     afs_int32 code;
73
74     code = afsconf_SetExtendedCellInfo(adir, apath, acellInfo, NULL);
75     return code;
76 }
77
78 int
79 afsconf_SetExtendedCellInfo(struct afsconf_dir *adir,
80                             const char *apath,
81                             struct afsconf_cell *acellInfo, char clones[])
82 {
83     afs_int32 code;
84     int fd;
85     char tbuffer[1024];
86     FILE *tf;
87     afs_int32 i;
88
89     LOCK_GLOBAL_MUTEX;
90     /* write ThisCell file */
91     strcompose(tbuffer, 1024, apath, "/", AFSDIR_THISCELL_FILE, (char *)NULL);
92
93     fd = open(tbuffer, O_RDWR | O_CREAT | O_TRUNC, 0666);
94     if (fd < 0) {
95         UNLOCK_GLOBAL_MUTEX;
96         return errno;
97     }
98     i = (int)strlen(acellInfo->name);
99     code = write(fd, acellInfo->name, i);
100     if (code != i) {
101         UNLOCK_GLOBAL_MUTEX;
102         return AFSCONF_FAILURE;
103     }
104     if (close(fd) < 0) {
105         UNLOCK_GLOBAL_MUTEX;
106         return errno;
107     }
108
109     /* make sure we have both name and address for each host, looking up other
110      * if need be */
111     code = VerifyEntries(acellInfo);
112     if (code) {
113         UNLOCK_GLOBAL_MUTEX;
114         return code;
115     }
116
117     /* write CellServDB */
118     strcompose(tbuffer, 1024, apath, "/", AFSDIR_CELLSERVDB_FILE, (char *)NULL);
119     tf = fopen(tbuffer, "w");
120     if (!tf) {
121         UNLOCK_GLOBAL_MUTEX;
122         return AFSCONF_NOTFOUND;
123     }
124     fprintf(tf, ">%s    #Cell name\n", acellInfo->name);
125     for (i = 0; i < acellInfo->numServers; i++) {
126         code = acellInfo->hostAddr[i].sin_addr.s_addr;  /* net order */
127         if (code == 0)
128             continue;           /* delete request */
129         code = ntohl(code);     /* convert to host order */
130         if (clones && clones[i])
131             fprintf(tf, "[%d.%d.%d.%d]  #%s\n", (code >> 24) & 0xff,
132                     (code >> 16) & 0xff, (code >> 8) & 0xff, code & 0xff,
133                     acellInfo->hostName[i]);
134         else
135             fprintf(tf, "%d.%d.%d.%d    #%s\n", (code >> 24) & 0xff,
136                     (code >> 16) & 0xff, (code >> 8) & 0xff, code & 0xff,
137                     acellInfo->hostName[i]);
138     }
139     if (ferror(tf)) {
140         fclose(tf);
141         UNLOCK_GLOBAL_MUTEX;
142         return AFSCONF_FAILURE;
143     }
144     code = fclose(tf);
145
146     /* Reset the timestamp in the cache, so that
147      * the CellServDB is read into the cache next time.
148      * Resolves the lost update problem due to an inconsistent cache
149      */
150     if (adir)
151         adir->timeRead = 0;
152
153     UNLOCK_GLOBAL_MUTEX;
154     if (code == EOF)
155         return AFSCONF_FAILURE;
156     return 0;
157 }