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"
43 #include "afp_zeroconf.h"
46 * Free and cleanup config and DSI
48 * "dsi" can be NULL in which case all DSI objects and the config object is freed,
49 * otherwise its an afpd session child and only any unneeded DSI objects are freed
51 void configfree(AFPObj *obj, DSI *dsi)
56 /* Master afpd reloading config */
58 if (! (obj->options.flags & OPTION_NOZEROCONF)) {
59 zeroconf_deregister();
65 /* Master and child releasing unneeded DSI handles */
66 for (p = obj->dsi; p; p = q) {
75 /* afpd session child passes dsi handle to obj handle */
83 * Get everything running
85 int configinit(AFPObj *obj)
89 DSI **next = &obj->dsi;
90 char *p = NULL, *q = NULL, *savep;
92 struct ifaddrs *ifaddr, *ifa;
94 static char interfaddr[NI_MAXHOST];
96 auth_load(obj, obj->options.uampath, obj->options.uamlist);
97 set_signature(&obj->options);
99 acl_ldap_freeconfig();
100 #endif /* HAVE_LDAP */
102 LOG(log_debug, logtype_afpd, "DSIConfigInit: hostname: %s, listen: %s, interfaces: %s, port: %s",
103 obj->options.hostname,
104 obj->options.listen ? obj->options.listen : "-",
105 obj->options.interfaces ? obj->options.interfaces : "-",
109 * Setup addresses we listen on from hostname and/or "afp listen" option
111 if (obj->options.listen) {
112 EC_NULL( q = p = strdup(obj->options.listen) );
113 EC_NULL( p = strtok_r(p, ", ", &savep) );
115 if ((dsi = dsi_init(obj, obj->options.hostname, p, obj->options.port)) == NULL)
118 status_init(obj, dsi);
123 LOG(log_note, logtype_afpd, "Netatalk AFP/TCP listening on %s:%d",
124 getip_string((struct sockaddr *)&dsi->server),
125 getip_port((struct sockaddr *)&dsi->server));
127 p = strtok_r(NULL, ", ", &savep);
136 * Setup addresses we listen on from "afp interfaces".
137 * We use getifaddrs() instead of if_nameindex() because the latter appears still
138 * to be unable to return ipv4 addresses
140 if (obj->options.interfaces) {
141 #ifndef HAVE_GETIFADDRS
142 LOG(log_error, logtype_afpd, "option \"afp interfaces\" not supported");
144 if (getifaddrs(&ifaddr) == -1) {
145 LOG(log_error, logtype_afpd, "getinterfaddr: getifaddrs() failed: %s", strerror(errno));
149 EC_NULL( q = p = strdup(obj->options.interfaces) );
150 EC_NULL( p = strtok_r(p, ", ", &savep) );
152 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
153 if (ifa->ifa_addr == NULL)
155 if (STRCMP(ifa->ifa_name, !=, p))
158 family = ifa->ifa_addr->sa_family;
159 if (family == AF_INET || family == AF_INET6) {
160 if (getnameinfo(ifa->ifa_addr,
161 (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6),
162 interfaddr, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) != 0) {
163 LOG(log_error, logtype_afpd, "getinterfaddr: getnameinfo() failed %s", gai_strerror(errno));
167 if ((dsi = dsi_init(obj, obj->options.hostname, interfaddr, obj->options.port)) == NULL)
170 status_init(obj, dsi);
175 LOG(log_note, logtype_afpd, "Netatalk AFP/TCP listening on interface %s with address %s:%d",
177 getip_string((struct sockaddr *)&dsi->server),
178 getip_port((struct sockaddr *)&dsi->server));
179 } /* if (family == AF_INET || family == AF_INET6) */
180 } /* for (ifa != NULL) */
181 p = strtok_r(NULL, ", ", &savep);
188 * Check whether we got a valid DSI from options.listen or options.interfaces,
189 * if not add a DSI that accepts all connections and goes though the list of
190 * network interaces for determining an IP we can advertise in DSIStatus
193 if ((dsi = dsi_init(obj, obj->options.hostname, NULL, obj->options.port)) == NULL)
194 EC_FAIL_LOG("no suitable network address found, use \"afp listen\" or \"afp interfaces\"", 0);
195 status_init(obj, dsi);
200 LOG(log_note, logtype_afpd, "Netatalk AFP/TCP listening on %s:%d",
201 getip_string((struct sockaddr *)&dsi->server),
202 getip_port((struct sockaddr *)&dsi->server));
207 acl_ldap_readconfig(obj->iniconfig);
208 #endif /* HAVE_LDAP */
210 /* Now register with zeroconf, we also need the volumes for that */
211 if (! (obj->options.flags & OPTION_NOZEROCONF)) {
212 load_volumes(obj, lv_all);
213 zeroconf_register(obj);
216 if ((r = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce listener", NULL))) {
217 LOG(log_note, logtype_afpd, "Adding FCE listener: %s", r);
218 fce_add_udp_socket(r);
220 if ((r = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce coalesce", NULL))) {
221 LOG(log_note, logtype_afpd, "Fce coalesce: %s", r);
224 if ((r = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce events", NULL))) {
225 LOG(log_note, logtype_afpd, "Fce events: %s", r);