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);
99 #endif /* no afp/asp */
101 static int dsi_start(AFPConfig *config, AFPConfig *configs,
102 server_child *server_children)
106 if (!(dsi = dsi_getsession(config->obj.handle, server_children,
107 config->obj.options.tickleval))) {
108 syslog( LOG_ERR, "main: dsi_getsession: %m" );
114 configfree(configs, config);
115 afp_over_dsi(&config->obj); /* start a session */
121 static AFPConfig *ASPConfigInit(const struct afp_options *options,
122 unsigned char *refcount)
127 char *Obj, *Type = "AFPServer", *Zone = "*";
129 if ((config = (AFPConfig *) calloc(1, sizeof(AFPConfig))) == NULL)
132 if ((atp = atp_open(ATADDR_ANYPORT, &options->ddpaddr)) == NULL) {
133 syslog( LOG_ERR, "main: atp_open: %m");
138 if ((asp = asp_init( atp )) == NULL) {
139 syslog( LOG_ERR, "main: asp_init: %m" );
145 /* register asp server */
146 Obj = (char *) options->hostname;
147 if (nbp_name(options->server, &Obj, &Type, &Zone )) {
148 syslog( LOG_ERR, "main: can't parse %s", options->server );
149 goto serv_free_return;
152 /* dup Obj, Type and Zone as they get assigned to a single internal
153 * buffer by nbp_name */
154 if ((config->obj.Obj = strdup(Obj)) == NULL)
155 goto serv_free_return;
157 if ((config->obj.Type = strdup(Type)) == NULL) {
158 free(config->obj.Obj);
159 goto serv_free_return;
162 if ((config->obj.Zone = strdup(Zone)) == NULL) {
163 free(config->obj.Obj);
164 free(config->obj.Type);
165 goto serv_free_return;
168 /* make sure we're not registered */
169 nbp_unrgstr(Obj, Type, Zone, &options->ddpaddr);
170 if (nbp_rgstr( atp_sockaddr( atp ), Obj, Type, Zone ) < 0 ) {
171 syslog( LOG_ERR, "Can't register %s:%s@%s", Obj, Type, Zone );
172 free(config->obj.Obj);
173 free(config->obj.Type);
174 free(config->obj.Zone);
175 goto serv_free_return;
178 syslog( LOG_INFO, "%s:%s@%s started on %u.%u:%u (%s)", Obj, Type, Zone,
179 ntohs( atp_sockaddr( atp )->sat_addr.s_net ),
180 atp_sockaddr( atp )->sat_addr.s_node,
181 atp_sockaddr( atp )->sat_port, VERSION );
183 config->fd = atp_fileno(atp);
184 config->obj.handle = asp;
185 config->obj.config = config;
186 config->obj.proto = AFPPROTO_ASP;
188 memcpy(&config->obj.options, options, sizeof(struct afp_options));
189 config->optcount = refcount;
192 config->server_start = asp_start;
193 config->server_cleanup = asp_cleanup;
202 #endif /* no afp/asp */
205 static AFPConfig *DSIConfigInit(const struct afp_options *options,
206 unsigned char *refcount,
207 const dsi_proto protocol)
213 if ((config = (AFPConfig *) calloc(1, sizeof(AFPConfig))) == NULL) {
214 syslog( LOG_ERR, "DSIConfigInit: malloc(config): %m" );
218 if ((dsi = dsi_init(protocol, "afpd", options->hostname,
219 options->ipaddr, options->port,
220 options->flags & OPTION_PROXY,
221 options->server_quantum)) == NULL) {
222 syslog( LOG_ERR, "main: dsi_init: %m" );
227 if (options->flags & OPTION_PROXY) {
228 syslog(LOG_INFO, "ASIP proxy initialized for %s:%d (%s)",
229 inet_ntoa(dsi->server.sin_addr), ntohs(dsi->server.sin_port),
232 syslog(LOG_INFO, "ASIP started on %s:%d(%d) (%s)",
233 inet_ntoa(dsi->server.sin_addr), ntohs(dsi->server.sin_port),
234 dsi->serversock, VERSION);
237 config->fd = dsi->serversock;
238 config->obj.handle = dsi;
239 config->obj.config = config;
240 config->obj.proto = AFPPROTO_DSI;
242 memcpy(&config->obj.options, options, sizeof(struct afp_options));
243 /* get rid of any appletalk info. we use the fact that the DSI
244 * stuff is done after the ASP stuff. */
245 p = config->obj.options.server;
246 if (p && (q = strchr(p, ':')))
249 config->optcount = refcount;
252 config->server_start = dsi_start;
256 /* allocate server configurations. this should really store the last
257 * entry in config->last or something like that. that would make
258 * supporting multiple dsi transports easier. */
259 static AFPConfig *AFPConfigInit(const struct afp_options *options,
260 const struct afp_options *defoptions)
262 AFPConfig *config = NULL, *next = NULL;
263 unsigned char *refcount;
265 if ((refcount = (unsigned char *)
266 calloc(1, sizeof(unsigned char))) == NULL) {
267 syslog( LOG_ERR, "AFPConfigInit: calloc(refcount): %m" );
272 /* handle asp transports */
273 if ((options->transports & AFPTRANS_DDP) &&
274 (config = ASPConfigInit(options, refcount)))
275 config->defoptions = defoptions;
278 /* handle dsi transports and dsi proxies. we only proxy
279 * for DSI connections. */
281 /* this should have something like the following:
282 * for (i=mindsi; i < maxdsi; i++)
283 * if (options->transports & (1 << i) &&
284 * (next = DSIConfigInit(options, refcount, i)))
285 * next->defoptions = defoptions;
287 if ((options->transports & AFPTRANS_TCP) &&
288 (((options->flags & OPTION_PROXY) == 0) ||
289 ((options->flags & OPTION_PROXY) && config))
290 && (next = DSIConfigInit(options, refcount, DSI_TCPIP)))
291 next->defoptions = defoptions;
293 /* load in all the authentication modules. we can load the same
294 things multiple times if necessary. however, loading different
295 things with the same names will cause complaints. by not loading
296 in any uams with proxies, we prevent ddp connections from succeeding.
298 auth_load(options->uampath, options->uamlist);
300 /* this should be able to accept multiple dsi transports. i think
301 * the only thing that gets affected is the net addresses. */
302 status_init(config, next, options);
304 /* attach dsi config to tail of asp config */
313 /* fill in the appropriate bits for each interface */
314 AFPConfig *configinit(struct afp_options *cmdline)
317 char buf[LINESIZE + 1], *p, have_option = 0;
318 struct afp_options options;
319 AFPConfig *config, *first = NULL;
321 /* if config file doesn't exist, load defaults */
322 if ((fp = fopen(cmdline->configfile, "r")) == NULL)
323 return AFPConfigInit(cmdline, cmdline);
325 /* scan in the configuration file */
327 if (!fgets(buf, sizeof(buf), fp) || buf[0] == '#')
330 /* a little pre-processing to get rid of spaces and end-of-lines */
332 while (p && isspace(*p))
334 if (!p || (*p == '\0'))
339 memcpy(&options, cmdline, sizeof(options));
340 if (!afp_options_parseline(p, &options))
343 /* this should really get a head and a tail to simplify things. */
345 if ((first = AFPConfigInit(&options, cmdline)))
346 config = first->next ? first->next : first;
347 } else if ((config->next = AFPConfigInit(&options, cmdline))) {
348 config = config->next->next ? config->next->next : config->next;
355 return AFPConfigInit(cmdline, cmdline);