2 * $Id: afp_config.c,v 1.3 2001-06-20 18:33:04 rufustfirefly Exp $
4 * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
17 #endif /* HAVE_UNISTD_H */
21 #include <sys/socket.h>
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
25 #include <atalk/dsi.h>
26 #include <atalk/atp.h>
27 #include <atalk/asp.h>
28 #include <atalk/nbp.h>
29 #include <atalk/afp.h>
30 #include <atalk/compat.h>
31 #include <atalk/server_child.h>
34 #include "afp_config.h"
40 /* get rid of unneeded configurations. i use reference counts to deal
41 * w/ multiple configs sharing the same afp_options. oh, to dream of
42 * garbage collection ... */
43 void configfree(AFPConfig *configs, const AFPConfig *config)
47 for (p = configs; p; p = q) {
52 /* do a little reference counting */
53 if (--(*p->optcount) < 1) {
54 afp_options_free(&p->obj.options, p->defoptions);
58 switch (p->obj.proto) {
64 atp_close(((ASP) p->obj.handle)->asp_atp);
67 #endif /* no afp/asp */
78 static void asp_cleanup(const AFPConfig *config)
80 nbp_unrgstr(config->obj.Obj, config->obj.Type, config->obj.Zone,
81 &config->obj.options.ddpaddr);
84 /* these two are almost identical. it should be possible to collapse them
85 * into one with minimal junk. */
86 static int asp_start(AFPConfig *config, AFPConfig *configs,
87 server_child *server_children)
91 if (!(asp = asp_getsession(config->obj.handle, server_children,
92 config->obj.options.tickleval))) {
93 syslog( LOG_ERR, "main: asp_getsession: %m" );
98 configfree(configs, config); /* free a bunch of stuff */
99 afp_over_asp(&config->obj);
105 #endif /* no afp/asp */
107 static int dsi_start(AFPConfig *config, AFPConfig *configs,
108 server_child *server_children)
112 if (!(dsi = dsi_getsession(config->obj.handle, server_children,
113 config->obj.options.tickleval))) {
114 syslog( LOG_ERR, "main: dsi_getsession: %m" );
120 configfree(configs, config);
121 afp_over_dsi(&config->obj); /* start a session */
129 static AFPConfig *ASPConfigInit(const struct afp_options *options,
130 unsigned char *refcount)
135 char *Obj, *Type = "AFPServer", *Zone = "*";
137 if ((config = (AFPConfig *) calloc(1, sizeof(AFPConfig))) == NULL)
140 if ((atp = atp_open(ATADDR_ANYPORT, &options->ddpaddr)) == NULL) {
141 syslog( LOG_ERR, "main: atp_open: %m");
146 if ((asp = asp_init( atp )) == NULL) {
147 syslog( LOG_ERR, "main: asp_init: %m" );
153 /* register asp server */
154 Obj = (char *) options->hostname;
155 if (nbp_name(options->server, &Obj, &Type, &Zone )) {
156 syslog( LOG_ERR, "main: can't parse %s", options->server );
157 goto serv_free_return;
160 /* dup Obj, Type and Zone as they get assigned to a single internal
161 * buffer by nbp_name */
162 if ((config->obj.Obj = strdup(Obj)) == NULL)
163 goto serv_free_return;
165 if ((config->obj.Type = strdup(Type)) == NULL) {
166 free(config->obj.Obj);
167 goto serv_free_return;
170 if ((config->obj.Zone = strdup(Zone)) == NULL) {
171 free(config->obj.Obj);
172 free(config->obj.Type);
173 goto serv_free_return;
176 /* make sure we're not registered */
177 nbp_unrgstr(Obj, Type, Zone, &options->ddpaddr);
178 if (nbp_rgstr( atp_sockaddr( atp ), Obj, Type, Zone ) < 0 ) {
179 syslog( LOG_ERR, "Can't register %s:%s@%s", Obj, Type, Zone );
180 free(config->obj.Obj);
181 free(config->obj.Type);
182 free(config->obj.Zone);
183 goto serv_free_return;
186 syslog( LOG_INFO, "%s:%s@%s started on %u.%u:%u (%s)", Obj, Type, Zone,
187 ntohs( atp_sockaddr( atp )->sat_addr.s_net ),
188 atp_sockaddr( atp )->sat_addr.s_node,
189 atp_sockaddr( atp )->sat_port, VERSION );
191 config->fd = atp_fileno(atp);
192 config->obj.handle = asp;
193 config->obj.config = config;
194 config->obj.proto = AFPPROTO_ASP;
196 memcpy(&config->obj.options, options, sizeof(struct afp_options));
197 config->optcount = refcount;
200 config->server_start = asp_start;
201 config->server_cleanup = asp_cleanup;
210 #endif /* no afp/asp */
213 static AFPConfig *DSIConfigInit(const struct afp_options *options,
214 unsigned char *refcount,
215 const dsi_proto protocol)
221 if ((config = (AFPConfig *) calloc(1, sizeof(AFPConfig))) == NULL) {
222 syslog( LOG_ERR, "DSIConfigInit: malloc(config): %m" );
226 if ((dsi = dsi_init(protocol, "afpd", options->hostname,
227 options->ipaddr, options->port,
228 options->flags & OPTION_PROXY,
229 options->server_quantum)) == NULL) {
230 syslog( LOG_ERR, "main: dsi_init: %m" );
235 if (options->flags & OPTION_PROXY) {
236 syslog(LOG_INFO, "ASIP proxy initialized for %s:%d (%s)",
237 inet_ntoa(dsi->server.sin_addr), ntohs(dsi->server.sin_port),
240 syslog(LOG_INFO, "ASIP started on %s:%d(%d) (%s)",
241 inet_ntoa(dsi->server.sin_addr), ntohs(dsi->server.sin_port),
242 dsi->serversock, VERSION);
245 config->fd = dsi->serversock;
246 config->obj.handle = dsi;
247 config->obj.config = config;
248 config->obj.proto = AFPPROTO_DSI;
250 memcpy(&config->obj.options, options, sizeof(struct afp_options));
251 /* get rid of any appletalk info. we use the fact that the DSI
252 * stuff is done after the ASP stuff. */
253 p = config->obj.options.server;
254 if (p && (q = strchr(p, ':')))
257 config->optcount = refcount;
260 config->server_start = dsi_start;
264 /* allocate server configurations. this should really store the last
265 * entry in config->last or something like that. that would make
266 * supporting multiple dsi transports easier. */
267 static AFPConfig *AFPConfigInit(const struct afp_options *options,
268 const struct afp_options *defoptions)
270 AFPConfig *config = NULL, *next = NULL;
271 unsigned char *refcount;
273 if ((refcount = (unsigned char *)
274 calloc(1, sizeof(unsigned char))) == NULL) {
275 syslog( LOG_ERR, "AFPConfigInit: calloc(refcount): %m" );
280 /* handle asp transports */
281 if ((options->transports & AFPTRANS_DDP) &&
282 (config = ASPConfigInit(options, refcount)))
283 config->defoptions = defoptions;
286 /* handle dsi transports and dsi proxies. we only proxy
287 * for DSI connections. */
289 /* this should have something like the following:
290 * for (i=mindsi; i < maxdsi; i++)
291 * if (options->transports & (1 << i) &&
292 * (next = DSIConfigInit(options, refcount, i)))
293 * next->defoptions = defoptions;
295 if ((options->transports & AFPTRANS_TCP) &&
296 (((options->flags & OPTION_PROXY) == 0) ||
297 ((options->flags & OPTION_PROXY) && config))
298 && (next = DSIConfigInit(options, refcount, DSI_TCPIP)))
299 next->defoptions = defoptions;
301 /* load in all the authentication modules. we can load the same
302 things multiple times if necessary. however, loading different
303 things with the same names will cause complaints. by not loading
304 in any uams with proxies, we prevent ddp connections from succeeding.
306 auth_load(options->uampath, options->uamlist);
308 /* this should be able to accept multiple dsi transports. i think
309 * the only thing that gets affected is the net addresses. */
310 status_init(config, next, options);
312 /* attach dsi config to tail of asp config */
321 /* fill in the appropriate bits for each interface */
322 AFPConfig *configinit(struct afp_options *cmdline)
325 char buf[LINESIZE + 1], *p, have_option = 0;
326 struct afp_options options;
327 AFPConfig *config, *first = NULL;
329 /* if config file doesn't exist, load defaults */
330 if ((fp = fopen(cmdline->configfile, "r")) == NULL)
331 return AFPConfigInit(cmdline, cmdline);
333 /* scan in the configuration file */
335 if (!fgets(buf, sizeof(buf), fp) || buf[0] == '#')
338 /* a little pre-processing to get rid of spaces and end-of-lines */
340 while (p && isspace(*p))
342 if (!p || (*p == '\0'))
347 memcpy(&options, cmdline, sizeof(options));
348 if (!afp_options_parseline(p, &options))
351 /* this should really get a head and a tail to simplify things. */
353 if ((first = AFPConfigInit(&options, cmdline)))
354 config = first->next ? first->next : first;
355 } else if ((config->next = AFPConfigInit(&options, cmdline))) {
356 config = config->next->next ? config->next->next : config->next;
363 return AFPConfigInit(cmdline, cmdline);