2 * $Id: afp_config.c,v 1.5 2001-09-17 13:41:26 rufustfirefly Exp $
4 * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
18 #else /* STDC_HEADERS */
22 #endif /* HAVE_STRCHR */
23 char *strchr (), *strrchr ();
25 #define memcpy(d,s,n) bcopy ((s), (d), (n))
26 #define memmove(d,s,n) bcopy ((s), (d), (n))
27 #endif /* ! HAVE_MEMCPY */
28 #endif /* STDC_HEADERS */
32 #endif /* HAVE_UNISTD_H */
36 #include <sys/socket.h>
37 #include <netinet/in.h>
38 #include <arpa/inet.h>
40 #include <atalk/dsi.h>
41 #include <atalk/atp.h>
42 #include <atalk/asp.h>
43 #include <atalk/nbp.h>
44 #include <atalk/afp.h>
45 #include <atalk/compat.h>
46 #include <atalk/server_child.h>
49 static char srvloc_url[512];
53 #include "afp_config.h"
59 /* get rid of unneeded configurations. i use reference counts to deal
60 * w/ multiple configs sharing the same afp_options. oh, to dream of
61 * garbage collection ... */
62 void configfree(AFPConfig *configs, const AFPConfig *config)
66 for (p = configs; p; p = q) {
71 /* do a little reference counting */
72 if (--(*p->optcount) < 1) {
73 afp_options_free(&p->obj.options, p->defoptions);
77 switch (p->obj.proto) {
83 atp_close(((ASP) p->obj.handle)->asp_atp);
86 #endif /* no afp/asp */
97 static void SRVLOC_callback(SLPHandle hslp, SLPError errcode, void *cookie) {
98 *(SLPError*)cookie = errcode;
103 static void dsi_cleanup(const AFPConfig *config)
106 SLPError callbackerr;
108 err = SLPOpen("en", SLP_FALSE, &hslp);
110 syslog(LOG_ERR, "Error opening SRVLOC handle");
111 goto srvloc_dereg_err;
119 syslog(LOG_ERR, "Error unregistering %s from SRVLOC", srvloc_url);
120 goto srvloc_dereg_err;
123 if (callbackerr != SLP_OK) {
124 syslog(LOG_ERR, "Error in callback while trying to unregister %s from SRVLOC (%i)", srvloc_url, callbackerr);
125 goto srvloc_dereg_err;
134 static void asp_cleanup(const AFPConfig *config)
136 nbp_unrgstr(config->obj.Obj, config->obj.Type, config->obj.Zone,
137 &config->obj.options.ddpaddr);
140 /* these two are almost identical. it should be possible to collapse them
141 * into one with minimal junk. */
142 static int asp_start(AFPConfig *config, AFPConfig *configs,
143 server_child *server_children)
147 if (!(asp = asp_getsession(config->obj.handle, server_children,
148 config->obj.options.tickleval))) {
149 syslog( LOG_ERR, "main: asp_getsession: %m" );
154 configfree(configs, config); /* free a bunch of stuff */
155 afp_over_asp(&config->obj);
161 #endif /* no afp/asp */
163 static int dsi_start(AFPConfig *config, AFPConfig *configs,
164 server_child *server_children)
168 if (!(dsi = dsi_getsession(config->obj.handle, server_children,
169 config->obj.options.tickleval))) {
170 syslog( LOG_ERR, "main: dsi_getsession: %m" );
176 configfree(configs, config);
177 afp_over_dsi(&config->obj); /* start a session */
185 static AFPConfig *ASPConfigInit(const struct afp_options *options,
186 unsigned char *refcount)
191 char *Obj, *Type = "AFPServer", *Zone = "*";
193 if ((config = (AFPConfig *) calloc(1, sizeof(AFPConfig))) == NULL)
196 if ((atp = atp_open(ATADDR_ANYPORT, &options->ddpaddr)) == NULL) {
197 syslog( LOG_ERR, "main: atp_open: %m");
202 if ((asp = asp_init( atp )) == NULL) {
203 syslog( LOG_ERR, "main: asp_init: %m" );
209 /* register asp server */
210 Obj = (char *) options->hostname;
211 if (nbp_name(options->server, &Obj, &Type, &Zone )) {
212 syslog( LOG_ERR, "main: can't parse %s", options->server );
213 goto serv_free_return;
216 /* dup Obj, Type and Zone as they get assigned to a single internal
217 * buffer by nbp_name */
218 if ((config->obj.Obj = strdup(Obj)) == NULL)
219 goto serv_free_return;
221 if ((config->obj.Type = strdup(Type)) == NULL) {
222 free(config->obj.Obj);
223 goto serv_free_return;
226 if ((config->obj.Zone = strdup(Zone)) == NULL) {
227 free(config->obj.Obj);
228 free(config->obj.Type);
229 goto serv_free_return;
232 /* make sure we're not registered */
233 nbp_unrgstr(Obj, Type, Zone, &options->ddpaddr);
234 if (nbp_rgstr( atp_sockaddr( atp ), Obj, Type, Zone ) < 0 ) {
235 syslog( LOG_ERR, "Can't register %s:%s@%s", Obj, Type, Zone );
236 free(config->obj.Obj);
237 free(config->obj.Type);
238 free(config->obj.Zone);
239 goto serv_free_return;
242 syslog( LOG_INFO, "%s:%s@%s started on %u.%u:%u (%s)", Obj, Type, Zone,
243 ntohs( atp_sockaddr( atp )->sat_addr.s_net ),
244 atp_sockaddr( atp )->sat_addr.s_node,
245 atp_sockaddr( atp )->sat_port, VERSION );
247 config->fd = atp_fileno(atp);
248 config->obj.handle = asp;
249 config->obj.config = config;
250 config->obj.proto = AFPPROTO_ASP;
252 memcpy(&config->obj.options, options, sizeof(struct afp_options));
253 config->optcount = refcount;
256 config->server_start = asp_start;
257 config->server_cleanup = asp_cleanup;
266 #endif /* no afp/asp */
269 static AFPConfig *DSIConfigInit(const struct afp_options *options,
270 unsigned char *refcount,
271 const dsi_proto protocol)
278 SLPError callbackerr;
282 if ((config = (AFPConfig *) calloc(1, sizeof(AFPConfig))) == NULL) {
283 syslog( LOG_ERR, "DSIConfigInit: malloc(config): %m" );
287 if ((dsi = dsi_init(protocol, "afpd", options->hostname,
288 options->ipaddr, options->port,
289 options->flags & OPTION_PROXY,
290 options->server_quantum)) == NULL) {
291 syslog( LOG_ERR, "main: dsi_init: %m" );
296 if (options->flags & OPTION_PROXY) {
297 syslog(LOG_INFO, "ASIP proxy initialized for %s:%d (%s)",
298 inet_ntoa(dsi->server.sin_addr), ntohs(dsi->server.sin_port),
301 syslog(LOG_INFO, "ASIP started on %s:%d(%d) (%s)",
302 inet_ntoa(dsi->server.sin_addr), ntohs(dsi->server.sin_port),
303 dsi->serversock, VERSION);
307 err = SLPOpen("en", SLP_FALSE, &hslp);
309 syslog(LOG_ERR, "Error opening SRVLOC handle");
313 snprintf(srvloc_url, sizeof(srvloc_url), "afp://%s:%d?NAME=%s", inet_ntoa(dsi->server.sin_addr), ntohs(dsi->server.sin_port), options->hostname);
317 SLP_LIFETIME_MAXIMUM,
324 syslog(LOG_ERR, "Error registering %s with SRVLOC", srvloc_url);
328 if (callbackerr != SLP_OK) {
329 syslog(LOG_ERR, "Error in callback trying to register %s with SRVLOC", srvloc_url);
333 syslog(LOG_INFO, "Sucessfully registered %s with SRVLOC", srvloc_url);
340 config->fd = dsi->serversock;
341 config->obj.handle = dsi;
342 config->obj.config = config;
343 config->obj.proto = AFPPROTO_DSI;
345 memcpy(&config->obj.options, options, sizeof(struct afp_options));
346 /* get rid of any appletalk info. we use the fact that the DSI
347 * stuff is done after the ASP stuff. */
348 p = config->obj.options.server;
349 if (p && (q = strchr(p, ':')))
352 config->optcount = refcount;
355 config->server_start = dsi_start;
357 config->server_cleanup = dsi_cleanup;
362 /* allocate server configurations. this should really store the last
363 * entry in config->last or something like that. that would make
364 * supporting multiple dsi transports easier. */
365 static AFPConfig *AFPConfigInit(const struct afp_options *options,
366 const struct afp_options *defoptions)
368 AFPConfig *config = NULL, *next = NULL;
369 unsigned char *refcount;
371 if ((refcount = (unsigned char *)
372 calloc(1, sizeof(unsigned char))) == NULL) {
373 syslog( LOG_ERR, "AFPConfigInit: calloc(refcount): %m" );
378 /* handle asp transports */
379 if ((options->transports & AFPTRANS_DDP) &&
380 (config = ASPConfigInit(options, refcount)))
381 config->defoptions = defoptions;
384 /* handle dsi transports and dsi proxies. we only proxy
385 * for DSI connections. */
387 /* this should have something like the following:
388 * for (i=mindsi; i < maxdsi; i++)
389 * if (options->transports & (1 << i) &&
390 * (next = DSIConfigInit(options, refcount, i)))
391 * next->defoptions = defoptions;
393 if ((options->transports & AFPTRANS_TCP) &&
394 (((options->flags & OPTION_PROXY) == 0) ||
395 ((options->flags & OPTION_PROXY) && config))
396 && (next = DSIConfigInit(options, refcount, DSI_TCPIP)))
397 next->defoptions = defoptions;
399 /* load in all the authentication modules. we can load the same
400 things multiple times if necessary. however, loading different
401 things with the same names will cause complaints. by not loading
402 in any uams with proxies, we prevent ddp connections from succeeding.
404 auth_load(options->uampath, options->uamlist);
406 /* this should be able to accept multiple dsi transports. i think
407 * the only thing that gets affected is the net addresses. */
408 status_init(config, next, options);
410 /* attach dsi config to tail of asp config */
419 /* fill in the appropriate bits for each interface */
420 AFPConfig *configinit(struct afp_options *cmdline)
423 char buf[LINESIZE + 1], *p, have_option = 0;
424 struct afp_options options;
425 AFPConfig *config, *first = NULL;
427 /* if config file doesn't exist, load defaults */
428 if ((fp = fopen(cmdline->configfile, "r")) == NULL)
429 return AFPConfigInit(cmdline, cmdline);
431 /* scan in the configuration file */
433 if (!fgets(buf, sizeof(buf), fp) || buf[0] == '#')
436 /* a little pre-processing to get rid of spaces and end-of-lines */
438 while (p && isspace(*p))
440 if (!p || (*p == '\0'))
445 memcpy(&options, cmdline, sizeof(options));
446 if (!afp_options_parseline(p, &options))
449 /* this should really get a head and a tail to simplify things. */
451 if ((first = AFPConfigInit(&options, cmdline)))
452 config = first->next ? first->next : first;
453 } else if ((config->next = AFPConfigInit(&options, cmdline))) {
454 config = config->next->next ? config->next->next : config->next;
461 return AFPConfigInit(cmdline, cmdline);