2 * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
3 * All Rights Reserved. See COPYRIGHT.
17 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
21 #include <atalk/dsi.h>
22 #include <atalk/atp.h>
23 #include <atalk/asp.h>
24 #include <atalk/nbp.h>
25 #include <atalk/afp.h>
26 #include <atalk/compat.h>
27 #include <atalk/server_child.h>
30 #include "afp_config.h"
36 /* get rid of unneeded configurations. i use reference counts to deal
37 * w/ multiple configs sharing the same afp_options. oh, to dream of
38 * garbage collection ... */
39 void configfree(AFPConfig *configs, const AFPConfig *config)
43 for (p = configs; p; p = q) {
48 /* do a little reference counting */
49 if (--(*p->optcount) < 1) {
50 afp_options_free(&p->obj.options, p->defoptions);
54 switch (p->obj.proto) {
60 atp_close(((ASP) p->obj.handle)->asp_atp);
63 #endif /* no afp/asp */
74 static void asp_cleanup(const AFPConfig *config)
76 nbp_unrgstr(config->obj.Obj, config->obj.Type, config->obj.Zone,
77 &config->obj.options.ddpaddr);
80 /* these two are almost identical. it should be possible to collapse them
81 * into one with minimal junk. */
82 static int asp_start(AFPConfig *config, AFPConfig *configs,
83 server_child *server_children)
87 if (!(asp = asp_getsession(config->obj.handle, server_children,
88 config->obj.options.tickleval))) {
89 syslog( LOG_ERR, "main: asp_getsession: %m" );
94 configfree(configs, config); /* free a bunch of stuff */
95 afp_over_asp(&config->obj);
101 #endif /* no afp/asp */
103 static int dsi_start(AFPConfig *config, AFPConfig *configs,
104 server_child *server_children)
108 if (!(dsi = dsi_getsession(config->obj.handle, server_children,
109 config->obj.options.tickleval))) {
110 syslog( LOG_ERR, "main: dsi_getsession: %m" );
116 configfree(configs, config);
117 afp_over_dsi(&config->obj); /* start a session */
125 static AFPConfig *ASPConfigInit(const struct afp_options *options,
126 unsigned char *refcount)
131 char *Obj, *Type = "AFPServer", *Zone = "*";
133 if ((config = (AFPConfig *) calloc(1, sizeof(AFPConfig))) == NULL)
136 if ((atp = atp_open(ATADDR_ANYPORT, &options->ddpaddr)) == NULL) {
137 syslog( LOG_ERR, "main: atp_open: %m");
142 if ((asp = asp_init( atp )) == NULL) {
143 syslog( LOG_ERR, "main: asp_init: %m" );
149 /* register asp server */
150 Obj = (char *) options->hostname;
151 if (nbp_name(options->server, &Obj, &Type, &Zone )) {
152 syslog( LOG_ERR, "main: can't parse %s", options->server );
153 goto serv_free_return;
156 /* dup Obj, Type and Zone as they get assigned to a single internal
157 * buffer by nbp_name */
158 if ((config->obj.Obj = strdup(Obj)) == NULL)
159 goto serv_free_return;
161 if ((config->obj.Type = strdup(Type)) == NULL) {
162 free(config->obj.Obj);
163 goto serv_free_return;
166 if ((config->obj.Zone = strdup(Zone)) == NULL) {
167 free(config->obj.Obj);
168 free(config->obj.Type);
169 goto serv_free_return;
172 /* make sure we're not registered */
173 nbp_unrgstr(Obj, Type, Zone, &options->ddpaddr);
174 if (nbp_rgstr( atp_sockaddr( atp ), Obj, Type, Zone ) < 0 ) {
175 syslog( LOG_ERR, "Can't register %s:%s@%s", Obj, Type, Zone );
176 free(config->obj.Obj);
177 free(config->obj.Type);
178 free(config->obj.Zone);
179 goto serv_free_return;
182 syslog( LOG_INFO, "%s:%s@%s started on %u.%u:%u (%s)", Obj, Type, Zone,
183 ntohs( atp_sockaddr( atp )->sat_addr.s_net ),
184 atp_sockaddr( atp )->sat_addr.s_node,
185 atp_sockaddr( atp )->sat_port, VERSION );
187 config->fd = atp_fileno(atp);
188 config->obj.handle = asp;
189 config->obj.config = config;
190 config->obj.proto = AFPPROTO_ASP;
192 memcpy(&config->obj.options, options, sizeof(struct afp_options));
193 config->optcount = refcount;
196 config->server_start = asp_start;
197 config->server_cleanup = asp_cleanup;
206 #endif /* no afp/asp */
209 static AFPConfig *DSIConfigInit(const struct afp_options *options,
210 unsigned char *refcount,
211 const dsi_proto protocol)
217 if ((config = (AFPConfig *) calloc(1, sizeof(AFPConfig))) == NULL) {
218 syslog( LOG_ERR, "DSIConfigInit: malloc(config): %m" );
222 if ((dsi = dsi_init(protocol, "afpd", options->hostname,
223 options->ipaddr, options->port,
224 options->flags & OPTION_PROXY,
225 options->server_quantum)) == NULL) {
226 syslog( LOG_ERR, "main: dsi_init: %m" );
231 if (options->flags & OPTION_PROXY) {
232 syslog(LOG_INFO, "ASIP proxy initialized for %s:%d (%s)",
233 inet_ntoa(dsi->server.sin_addr), ntohs(dsi->server.sin_port),
236 syslog(LOG_INFO, "ASIP started on %s:%d(%d) (%s)",
237 inet_ntoa(dsi->server.sin_addr), ntohs(dsi->server.sin_port),
238 dsi->serversock, VERSION);
241 config->fd = dsi->serversock;
242 config->obj.handle = dsi;
243 config->obj.config = config;
244 config->obj.proto = AFPPROTO_DSI;
246 memcpy(&config->obj.options, options, sizeof(struct afp_options));
247 /* get rid of any appletalk info. we use the fact that the DSI
248 * stuff is done after the ASP stuff. */
249 p = config->obj.options.server;
250 if (p && (q = strchr(p, ':')))
253 config->optcount = refcount;
256 config->server_start = dsi_start;
260 /* allocate server configurations. this should really store the last
261 * entry in config->last or something like that. that would make
262 * supporting multiple dsi transports easier. */
263 static AFPConfig *AFPConfigInit(const struct afp_options *options,
264 const struct afp_options *defoptions)
266 AFPConfig *config = NULL, *next = NULL;
267 unsigned char *refcount;
269 if ((refcount = (unsigned char *)
270 calloc(1, sizeof(unsigned char))) == NULL) {
271 syslog( LOG_ERR, "AFPConfigInit: calloc(refcount): %m" );
276 /* handle asp transports */
277 if ((options->transports & AFPTRANS_DDP) &&
278 (config = ASPConfigInit(options, refcount)))
279 config->defoptions = defoptions;
282 /* handle dsi transports and dsi proxies. we only proxy
283 * for DSI connections. */
285 /* this should have something like the following:
286 * for (i=mindsi; i < maxdsi; i++)
287 * if (options->transports & (1 << i) &&
288 * (next = DSIConfigInit(options, refcount, i)))
289 * next->defoptions = defoptions;
291 if ((options->transports & AFPTRANS_TCP) &&
292 (((options->flags & OPTION_PROXY) == 0) ||
293 ((options->flags & OPTION_PROXY) && config))
294 && (next = DSIConfigInit(options, refcount, DSI_TCPIP)))
295 next->defoptions = defoptions;
297 /* load in all the authentication modules. we can load the same
298 things multiple times if necessary. however, loading different
299 things with the same names will cause complaints. by not loading
300 in any uams with proxies, we prevent ddp connections from succeeding.
302 auth_load(options->uampath, options->uamlist);
304 /* this should be able to accept multiple dsi transports. i think
305 * the only thing that gets affected is the net addresses. */
306 status_init(config, next, options);
308 /* attach dsi config to tail of asp config */
317 /* fill in the appropriate bits for each interface */
318 AFPConfig *configinit(struct afp_options *cmdline)
321 char buf[LINESIZE + 1], *p, have_option = 0;
322 struct afp_options options;
323 AFPConfig *config, *first = NULL;
325 /* if config file doesn't exist, load defaults */
326 if ((fp = fopen(cmdline->configfile, "r")) == NULL)
327 return AFPConfigInit(cmdline, cmdline);
329 /* scan in the configuration file */
331 if (!fgets(buf, sizeof(buf), fp) || buf[0] == '#')
334 /* a little pre-processing to get rid of spaces and end-of-lines */
336 while (p && isspace(*p))
338 if (!p || (*p == '\0'))
343 memcpy(&options, cmdline, sizeof(options));
344 if (!afp_options_parseline(p, &options))
347 /* this should really get a head and a tail to simplify things. */
349 if ((first = AFPConfigInit(&options, cmdline)))
350 config = first->next ? first->next : first;
351 } else if ((config->next = AFPConfigInit(&options, cmdline))) {
352 config = config->next->next ? config->next->next : config->next;
359 return AFPConfigInit(cmdline, cmdline);