2 * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
3 * All Rights Reserved. See COPYRIGHT.
12 #include <sys/socket.h>
13 #include <netinet/in.h>
14 #include <arpa/inet.h>
16 #include <atalk/dsi.h>
17 #include <atalk/atp.h>
18 #include <atalk/asp.h>
19 #include <atalk/nbp.h>
20 #include <atalk/afp.h>
21 #include <atalk/compat.h>
22 #include <atalk/server_child.h>
31 /* get rid of unneeded configurations. i use reference counts to deal
32 * w/ multiple configs sharing the same afp_options. oh, to dream of
33 * garbage collection ... */
34 void configfree(AFPConfig *configs, const AFPConfig *config)
38 for (p = configs; p; p = q) {
43 /* do a little reference counting */
44 if (--(*p->optcount) < 1) {
45 afp_options_free(&p->obj.options, p->defoptions);
49 switch (p->obj.proto) {
55 atp_close(((ASP) p->obj.handle)->asp_atp);
58 #endif /* no afp/asp */
69 static void asp_cleanup(const AFPConfig *config)
71 nbp_unrgstr(config->obj.Obj, config->obj.Type, config->obj.Zone,
72 &config->obj.options.ddpaddr);
75 /* these two are almost identical. it should be possible to collapse them
76 * into one with minimal junk. */
77 static int asp_start(AFPConfig *config, AFPConfig *configs,
78 server_child *server_children)
82 if (!(asp = asp_getsession(config->obj.handle, server_children,
83 config->obj.options.tickleval))) {
84 syslog( LOG_ERR, "main: asp_getsession: %m" );
89 configfree(configs, config); /* free a bunch of stuff */
90 afp_over_asp(&config->obj);
94 #endif /* no afp/asp */
96 static int dsi_start(AFPConfig *config, AFPConfig *configs,
97 server_child *server_children)
101 if (!(dsi = dsi_getsession(config->obj.handle, server_children,
102 config->obj.options.tickleval))) {
103 syslog( LOG_ERR, "main: dsi_getsession: %m" );
109 configfree(configs, config);
110 afp_over_dsi(&config->obj); /* start a session */
116 static AFPConfig *ASPConfigInit(const struct afp_options *options,
117 unsigned char *refcount)
122 char *Obj, *Type = "AFPServer", *Zone = "*";
124 if ((config = (AFPConfig *) calloc(1, sizeof(AFPConfig))) == NULL)
127 if ((atp = atp_open(ATADDR_ANYPORT, &options->ddpaddr)) == NULL) {
128 syslog( LOG_ERR, "main: atp_open: %m");
133 if ((asp = asp_init( atp )) == NULL) {
134 syslog( LOG_ERR, "main: asp_init: %m" );
140 /* register asp server */
141 Obj = (char *) options->hostname;
142 if (nbp_name(options->server, &Obj, &Type, &Zone )) {
143 syslog( LOG_ERR, "main: can't parse %s", options->server );
144 goto serv_free_return;
147 /* dup Obj, Type and Zone as they get assigned to a single internal
148 * buffer by nbp_name */
149 if ((config->obj.Obj = strdup(Obj)) == NULL)
150 goto serv_free_return;
152 if ((config->obj.Type = strdup(Type)) == NULL) {
153 free(config->obj.Obj);
154 goto serv_free_return;
157 if ((config->obj.Zone = strdup(Zone)) == NULL) {
158 free(config->obj.Obj);
159 free(config->obj.Type);
160 goto serv_free_return;
163 /* make sure we're not registered */
164 nbp_unrgstr(Obj, Type, Zone, &options->ddpaddr);
165 if (nbp_rgstr( atp_sockaddr( atp ), Obj, Type, Zone ) < 0 ) {
166 syslog( LOG_ERR, "Can't register %s:%s@%s", Obj, Type, Zone );
167 free(config->obj.Obj);
168 free(config->obj.Type);
169 free(config->obj.Zone);
170 goto serv_free_return;
173 syslog( LOG_INFO, "%s:%s@%s started on %u.%u:%u (%s)", Obj, Type, Zone,
174 ntohs( atp_sockaddr( atp )->sat_addr.s_net ),
175 atp_sockaddr( atp )->sat_addr.s_node,
176 atp_sockaddr( atp )->sat_port, VERSION );
178 config->fd = atp_fileno(atp);
179 config->obj.handle = asp;
180 config->obj.config = config;
181 config->obj.proto = AFPPROTO_ASP;
183 memcpy(&config->obj.options, options, sizeof(struct afp_options));
184 config->optcount = refcount;
187 config->server_start = asp_start;
188 config->server_cleanup = asp_cleanup;
197 #endif /* no afp/asp */
200 static AFPConfig *DSIConfigInit(const struct afp_options *options,
201 unsigned char *refcount,
202 const dsi_proto protocol)
208 if ((config = (AFPConfig *) calloc(1, sizeof(AFPConfig))) == NULL) {
209 syslog( LOG_ERR, "DSIConfigInit: malloc(config): %m" );
213 if ((dsi = dsi_init(protocol, "afpd", options->hostname,
214 options->ipaddr, options->port,
215 options->flags & OPTION_PROXY,
216 options->server_quantum)) == NULL) {
217 syslog( LOG_ERR, "main: dsi_init: %m" );
222 if (options->flags & OPTION_PROXY) {
223 syslog(LOG_INFO, "ASIP proxy initialized for %s:%d (%s)",
224 inet_ntoa(dsi->server.sin_addr), ntohs(dsi->server.sin_port),
227 syslog(LOG_INFO, "ASIP started on %s:%d(%d) (%s)",
228 inet_ntoa(dsi->server.sin_addr), ntohs(dsi->server.sin_port),
229 dsi->serversock, VERSION);
232 config->fd = dsi->serversock;
233 config->obj.handle = dsi;
234 config->obj.config = config;
235 config->obj.proto = AFPPROTO_DSI;
237 memcpy(&config->obj.options, options, sizeof(struct afp_options));
238 /* get rid of any appletalk info. we use the fact that the DSI
239 * stuff is done after the ASP stuff. */
240 p = config->obj.options.server;
241 if (p && (q = strchr(p, ':')))
244 config->optcount = refcount;
247 config->server_start = dsi_start;
251 /* allocate server configurations. this should really store the last
252 * entry in config->last or something like that. that would make
253 * supporting multiple dsi transports easier. */
254 static AFPConfig *AFPConfigInit(const struct afp_options *options,
255 const struct afp_options *defoptions)
257 AFPConfig *config = NULL, *next = NULL;
258 unsigned char *refcount;
260 if ((refcount = (unsigned char *)
261 calloc(1, sizeof(unsigned char))) == NULL) {
262 syslog( LOG_ERR, "AFPConfigInit: calloc(refcount): %m" );
267 /* handle asp transports */
268 if ((options->transports & AFPTRANS_DDP) &&
269 (config = ASPConfigInit(options, refcount)))
270 config->defoptions = defoptions;
273 /* handle dsi transports and dsi proxies. we only proxy
274 * for DSI connections. */
276 /* this should have something like the following:
277 * for (i=mindsi; i < maxdsi; i++)
278 * if (options->transports & (1 << i) &&
279 * (next = DSIConfigInit(options, refcount, i)))
280 * next->defoptions = defoptions;
282 if ((options->transports & AFPTRANS_TCP) &&
283 (((options->flags & OPTION_PROXY) == 0) ||
284 ((options->flags & OPTION_PROXY) && config))
285 && (next = DSIConfigInit(options, refcount, DSI_TCPIP)))
286 next->defoptions = defoptions;
288 /* load in all the authentication modules. we can load the same
289 things multiple times if necessary. however, loading different
290 things with the same names will cause complaints. by not loading
291 in any uams with proxies, we prevent ddp connections from succeeding.
293 auth_load(options->uampath, options->uamlist);
295 /* this should be able to accept multiple dsi transports. i think
296 * the only thing that gets affected is the net addresses. */
297 status_init(config, next, options);
299 /* attach dsi config to tail of asp config */
308 /* fill in the appropriate bits for each interface */
309 AFPConfig *configinit(struct afp_options *cmdline)
312 char buf[LINESIZE + 1], *p, have_option = 0;
313 struct afp_options options;
314 AFPConfig *config, *first = NULL;
316 /* if config file doesn't exist, load defaults */
317 if ((fp = fopen(cmdline->configfile, "r")) == NULL)
318 return AFPConfigInit(cmdline, cmdline);
320 /* scan in the configuration file */
322 if (!fgets(buf, sizeof(buf), fp) || buf[0] == '#')
325 /* a little pre-processing to get rid of spaces and end-of-lines */
327 while (p && isspace(*p))
329 if (!p || (*p == '\0'))
334 memcpy(&options, cmdline, sizeof(options));
335 if (!afp_options_parseline(p, &options))
338 /* this should really get a head and a tail to simplify things. */
340 if ((first = AFPConfigInit(&options, cmdline)))
341 config = first->next ? first->next : first;
342 } else if ((config->next = AFPConfigInit(&options, cmdline))) {
343 config = config->next->next ? config->next->next : config->next;
350 return AFPConfigInit(cmdline, cmdline);