2 * $Id: afp_config.c,v 1.4 2001-09-06 20:00:59 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 #include "afp_config.h"
55 /* get rid of unneeded configurations. i use reference counts to deal
56 * w/ multiple configs sharing the same afp_options. oh, to dream of
57 * garbage collection ... */
58 void configfree(AFPConfig *configs, const AFPConfig *config)
62 for (p = configs; p; p = q) {
67 /* do a little reference counting */
68 if (--(*p->optcount) < 1) {
69 afp_options_free(&p->obj.options, p->defoptions);
73 switch (p->obj.proto) {
79 atp_close(((ASP) p->obj.handle)->asp_atp);
82 #endif /* no afp/asp */
93 static void asp_cleanup(const AFPConfig *config)
95 nbp_unrgstr(config->obj.Obj, config->obj.Type, config->obj.Zone,
96 &config->obj.options.ddpaddr);
99 /* these two are almost identical. it should be possible to collapse them
100 * into one with minimal junk. */
101 static int asp_start(AFPConfig *config, AFPConfig *configs,
102 server_child *server_children)
106 if (!(asp = asp_getsession(config->obj.handle, server_children,
107 config->obj.options.tickleval))) {
108 syslog( LOG_ERR, "main: asp_getsession: %m" );
113 configfree(configs, config); /* free a bunch of stuff */
114 afp_over_asp(&config->obj);
120 #endif /* no afp/asp */
122 static int dsi_start(AFPConfig *config, AFPConfig *configs,
123 server_child *server_children)
127 if (!(dsi = dsi_getsession(config->obj.handle, server_children,
128 config->obj.options.tickleval))) {
129 syslog( LOG_ERR, "main: dsi_getsession: %m" );
135 configfree(configs, config);
136 afp_over_dsi(&config->obj); /* start a session */
144 static AFPConfig *ASPConfigInit(const struct afp_options *options,
145 unsigned char *refcount)
150 char *Obj, *Type = "AFPServer", *Zone = "*";
152 if ((config = (AFPConfig *) calloc(1, sizeof(AFPConfig))) == NULL)
155 if ((atp = atp_open(ATADDR_ANYPORT, &options->ddpaddr)) == NULL) {
156 syslog( LOG_ERR, "main: atp_open: %m");
161 if ((asp = asp_init( atp )) == NULL) {
162 syslog( LOG_ERR, "main: asp_init: %m" );
168 /* register asp server */
169 Obj = (char *) options->hostname;
170 if (nbp_name(options->server, &Obj, &Type, &Zone )) {
171 syslog( LOG_ERR, "main: can't parse %s", options->server );
172 goto serv_free_return;
175 /* dup Obj, Type and Zone as they get assigned to a single internal
176 * buffer by nbp_name */
177 if ((config->obj.Obj = strdup(Obj)) == NULL)
178 goto serv_free_return;
180 if ((config->obj.Type = strdup(Type)) == NULL) {
181 free(config->obj.Obj);
182 goto serv_free_return;
185 if ((config->obj.Zone = strdup(Zone)) == NULL) {
186 free(config->obj.Obj);
187 free(config->obj.Type);
188 goto serv_free_return;
191 /* make sure we're not registered */
192 nbp_unrgstr(Obj, Type, Zone, &options->ddpaddr);
193 if (nbp_rgstr( atp_sockaddr( atp ), Obj, Type, Zone ) < 0 ) {
194 syslog( LOG_ERR, "Can't register %s:%s@%s", Obj, Type, Zone );
195 free(config->obj.Obj);
196 free(config->obj.Type);
197 free(config->obj.Zone);
198 goto serv_free_return;
201 syslog( LOG_INFO, "%s:%s@%s started on %u.%u:%u (%s)", Obj, Type, Zone,
202 ntohs( atp_sockaddr( atp )->sat_addr.s_net ),
203 atp_sockaddr( atp )->sat_addr.s_node,
204 atp_sockaddr( atp )->sat_port, VERSION );
206 config->fd = atp_fileno(atp);
207 config->obj.handle = asp;
208 config->obj.config = config;
209 config->obj.proto = AFPPROTO_ASP;
211 memcpy(&config->obj.options, options, sizeof(struct afp_options));
212 config->optcount = refcount;
215 config->server_start = asp_start;
216 config->server_cleanup = asp_cleanup;
225 #endif /* no afp/asp */
228 static AFPConfig *DSIConfigInit(const struct afp_options *options,
229 unsigned char *refcount,
230 const dsi_proto protocol)
236 if ((config = (AFPConfig *) calloc(1, sizeof(AFPConfig))) == NULL) {
237 syslog( LOG_ERR, "DSIConfigInit: malloc(config): %m" );
241 if ((dsi = dsi_init(protocol, "afpd", options->hostname,
242 options->ipaddr, options->port,
243 options->flags & OPTION_PROXY,
244 options->server_quantum)) == NULL) {
245 syslog( LOG_ERR, "main: dsi_init: %m" );
250 if (options->flags & OPTION_PROXY) {
251 syslog(LOG_INFO, "ASIP proxy initialized for %s:%d (%s)",
252 inet_ntoa(dsi->server.sin_addr), ntohs(dsi->server.sin_port),
255 syslog(LOG_INFO, "ASIP started on %s:%d(%d) (%s)",
256 inet_ntoa(dsi->server.sin_addr), ntohs(dsi->server.sin_port),
257 dsi->serversock, VERSION);
260 config->fd = dsi->serversock;
261 config->obj.handle = dsi;
262 config->obj.config = config;
263 config->obj.proto = AFPPROTO_DSI;
265 memcpy(&config->obj.options, options, sizeof(struct afp_options));
266 /* get rid of any appletalk info. we use the fact that the DSI
267 * stuff is done after the ASP stuff. */
268 p = config->obj.options.server;
269 if (p && (q = strchr(p, ':')))
272 config->optcount = refcount;
275 config->server_start = dsi_start;
279 /* allocate server configurations. this should really store the last
280 * entry in config->last or something like that. that would make
281 * supporting multiple dsi transports easier. */
282 static AFPConfig *AFPConfigInit(const struct afp_options *options,
283 const struct afp_options *defoptions)
285 AFPConfig *config = NULL, *next = NULL;
286 unsigned char *refcount;
288 if ((refcount = (unsigned char *)
289 calloc(1, sizeof(unsigned char))) == NULL) {
290 syslog( LOG_ERR, "AFPConfigInit: calloc(refcount): %m" );
295 /* handle asp transports */
296 if ((options->transports & AFPTRANS_DDP) &&
297 (config = ASPConfigInit(options, refcount)))
298 config->defoptions = defoptions;
301 /* handle dsi transports and dsi proxies. we only proxy
302 * for DSI connections. */
304 /* this should have something like the following:
305 * for (i=mindsi; i < maxdsi; i++)
306 * if (options->transports & (1 << i) &&
307 * (next = DSIConfigInit(options, refcount, i)))
308 * next->defoptions = defoptions;
310 if ((options->transports & AFPTRANS_TCP) &&
311 (((options->flags & OPTION_PROXY) == 0) ||
312 ((options->flags & OPTION_PROXY) && config))
313 && (next = DSIConfigInit(options, refcount, DSI_TCPIP)))
314 next->defoptions = defoptions;
316 /* load in all the authentication modules. we can load the same
317 things multiple times if necessary. however, loading different
318 things with the same names will cause complaints. by not loading
319 in any uams with proxies, we prevent ddp connections from succeeding.
321 auth_load(options->uampath, options->uamlist);
323 /* this should be able to accept multiple dsi transports. i think
324 * the only thing that gets affected is the net addresses. */
325 status_init(config, next, options);
327 /* attach dsi config to tail of asp config */
336 /* fill in the appropriate bits for each interface */
337 AFPConfig *configinit(struct afp_options *cmdline)
340 char buf[LINESIZE + 1], *p, have_option = 0;
341 struct afp_options options;
342 AFPConfig *config, *first = NULL;
344 /* if config file doesn't exist, load defaults */
345 if ((fp = fopen(cmdline->configfile, "r")) == NULL)
346 return AFPConfigInit(cmdline, cmdline);
348 /* scan in the configuration file */
350 if (!fgets(buf, sizeof(buf), fp) || buf[0] == '#')
353 /* a little pre-processing to get rid of spaces and end-of-lines */
355 while (p && isspace(*p))
357 if (!p || (*p == '\0'))
362 memcpy(&options, cmdline, sizeof(options));
363 if (!afp_options_parseline(p, &options))
366 /* this should really get a head and a tail to simplify things. */
368 if ((first = AFPConfigInit(&options, cmdline)))
369 config = first->next ? first->next : first;
370 } else if ((config->next = AFPConfigInit(&options, cmdline))) {
371 config = config->next->next ? config->next->next : config->next;
378 return AFPConfigInit(cmdline, cmdline);