c538433400fbd2a1ac142eaa9191e92811a8a8bd
[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     tf = fopen(adir->cellservDB, "w");
144     if (!tf) {
145         UNLOCK_GLOBAL_MUTEX;
146         return AFSCONF_NOTFOUND;
147     }
148     fprintf(tf, ">%s    #Cell name\n", acellInfo->name);
149     for (i = 0; i < acellInfo->numServers; i++) {
150         code = acellInfo->hostAddr[i].sin_addr.s_addr;  /* net order */
151         if (code == 0)
152             continue;           /* delete request */
153         code = ntohl(code);     /* convert to host order */
154         if (clones && clones[i])
155             fprintf(tf, "[%d.%d.%d.%d]  #%s\n", (code >> 24) & 0xff,
156                     (code >> 16) & 0xff, (code >> 8) & 0xff, code & 0xff,
157                     acellInfo->hostName[i]);
158         else
159             fprintf(tf, "%d.%d.%d.%d    #%s\n", (code >> 24) & 0xff,
160                     (code >> 16) & 0xff, (code >> 8) & 0xff, code & 0xff,
161                     acellInfo->hostName[i]);
162     }
163     if (ferror(tf)) {
164         fclose(tf);
165         UNLOCK_GLOBAL_MUTEX;
166         return AFSCONF_FAILURE;
167     }
168     code = fclose(tf);
169
170     /* Reset the timestamp in the cache, so that
171      * the CellServDB is read into the cache next time.
172      * Resolves the lost update problem due to an inconsistent cache
173      */
174     if (adir)
175         adir->timeRead = 0;
176
177     UNLOCK_GLOBAL_MUTEX;
178     if (code == EOF)
179         return AFSCONF_FAILURE;
180     return 0;
181 }