2 * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
3 * All Rights Reserved. See COPYRIGHT.
8 #endif /* HAVE_CONFIG_H */
17 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
20 #ifdef HAVE_GETIFADDRS
24 #include <atalk/logger.h>
25 #include <atalk/util.h>
26 #include <atalk/dsi.h>
27 #include <atalk/afp.h>
28 #include <atalk/compat.h>
29 #include <atalk/server_child.h>
30 #include <atalk/globals.h>
31 #include <atalk/errchk.h>
32 #include <atalk/netatalk_conf.h>
33 #include <atalk/fce_api.h>
36 #include <atalk/ldapconfig.h>
39 #include "afp_config.h"
45 * Free and cleanup config and DSI
47 * "dsi" can be NULL in which case all DSI objects and the config object is freed,
48 * otherwise its an afpd session child and only any unneeded DSI objects are freed
50 void configfree(AFPObj *obj, DSI *dsi)
55 /* Master afpd reloading config */
61 /* Master and child releasing unneeded DSI handles */
62 for (p = obj->dsi; p; p = q) {
71 /* afpd session child passes dsi handle to obj handle */
79 * Get everything running
81 int configinit(AFPObj *obj)
85 DSI **next = &obj->dsi;
86 char *p = NULL, *q = NULL, *savep;
88 struct ifaddrs *ifaddr, *ifa;
90 static char interfaddr[NI_MAXHOST];
92 auth_load(obj, obj->options.uampath, obj->options.uamlist);
93 set_signature(&obj->options);
95 acl_ldap_freeconfig();
96 #endif /* HAVE_LDAP */
98 LOG(log_debug, logtype_afpd, "DSIConfigInit: hostname: %s, listen: %s, interfaces: %s, port: %s",
99 obj->options.hostname,
100 obj->options.listen ? obj->options.listen : "-",
101 obj->options.interfaces ? obj->options.interfaces : "-",
105 * Setup addresses we listen on from hostname and/or "afp listen" option
107 if (obj->options.listen) {
108 EC_NULL( q = p = strdup(obj->options.listen) );
109 EC_NULL( p = strtok_r(p, ", ", &savep) );
111 if ((dsi = dsi_init(obj, obj->options.hostname, p, obj->options.port)) == NULL)
114 status_init(obj, dsi);
119 LOG(log_note, logtype_afpd, "Netatalk AFP/TCP listening on %s:%d",
120 getip_string((struct sockaddr *)&dsi->server),
121 getip_port((struct sockaddr *)&dsi->server));
123 p = strtok_r(NULL, ", ", &savep);
132 * Setup addresses we listen on from "afp interfaces".
133 * We use getifaddrs() instead of if_nameindex() because the latter appears still
134 * to be unable to return ipv4 addresses
136 if (obj->options.interfaces) {
137 #ifndef HAVE_GETIFADDRS
138 LOG(log_error, logtype_afpd, "option \"afp interfaces\" not supported");
140 if (getifaddrs(&ifaddr) == -1) {
141 LOG(log_error, logtype_afpd, "getinterfaddr: getifaddrs() failed: %s", strerror(errno));
145 EC_NULL( q = p = strdup(obj->options.interfaces) );
146 EC_NULL( p = strtok_r(p, ", ", &savep) );
148 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
149 if (ifa->ifa_addr == NULL)
151 if (STRCMP(ifa->ifa_name, !=, p))
154 family = ifa->ifa_addr->sa_family;
155 if (family == AF_INET || family == AF_INET6) {
156 if (getnameinfo(ifa->ifa_addr,
157 (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6),
158 interfaddr, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) != 0) {
159 LOG(log_error, logtype_afpd, "getinterfaddr: getnameinfo() failed %s", gai_strerror(errno));
163 if ((dsi = dsi_init(obj, obj->options.hostname, interfaddr, obj->options.port)) == NULL)
166 status_init(obj, dsi);
171 LOG(log_note, logtype_afpd, "Netatalk AFP/TCP listening on interface %s with address %s:%d",
173 getip_string((struct sockaddr *)&dsi->server),
174 getip_port((struct sockaddr *)&dsi->server));
175 } /* if (family == AF_INET || family == AF_INET6) */
176 } /* for (ifa != NULL) */
177 p = strtok_r(NULL, ", ", &savep);
184 * Check whether we got a valid DSI from options.listen or options.interfaces,
185 * if not add a DSI that accepts all connections and goes though the list of
186 * network interaces for determining an IP we can advertise in DSIStatus
189 if ((dsi = dsi_init(obj, obj->options.hostname, NULL, obj->options.port)) == NULL)
190 EC_FAIL_LOG("no suitable network address found, use \"afp listen\" or \"afp interfaces\"", 0);
191 status_init(obj, dsi);
196 LOG(log_note, logtype_afpd, "Netatalk AFP/TCP listening on %s:%d",
197 getip_string((struct sockaddr *)&dsi->server),
198 getip_port((struct sockaddr *)&dsi->server));
203 acl_ldap_readconfig(obj->iniconfig);
204 #endif /* HAVE_LDAP */
206 if ((r = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce listener", NULL))) {
207 LOG(log_note, logtype_afpd, "Adding FCE listener: %s", r);
208 fce_add_udp_socket(r);
210 if ((r = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce coalesce", NULL))) {
211 LOG(log_note, logtype_afpd, "Fce coalesce: %s", r);
214 if ((r = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce events", NULL))) {
215 LOG(log_note, logtype_afpd, "Fce events: %s", r);
218 r = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce version", "1");
219 LOG(log_debug, logtype_afpd, "Fce version: %s", r);
220 obj->fce_version = atoi(r);
222 if ((r = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce ignore names", ".DS_Store"))) {
223 obj->fce_ign_names = strdup(r);
226 if ((r = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce notify script", NULL))) {
227 obj->fce_notify_script = strdup(r);