Skip to content

Commit

Permalink
AFP statistics via dbus IPC
Browse files Browse the repository at this point in the history
Fix PAM config installation. make distcheck was failing on Solaris
in uninstall, because the uninstall target ran some `rm -f PAMFILE`
where PAMFILE is hardcoded to /etc/pam.d. The resulting EPERM
causes the make target to fail.
  • Loading branch information
slowfranklin committed Feb 19, 2013
1 parent 01e4f40 commit 22ad101
Show file tree
Hide file tree
Showing 29 changed files with 648 additions and 55 deletions.
7 changes: 7 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ Changes in 3.0.3
* FIX: Fix an issue with user homes when user home directory has not the
same name as the username.
Fixes bug #497.
* UPD: Fix PAM config install, new default installation dir is
$sysconfdir/pam.d/. Add configure option --with-pam-confdir
to specify alternative path.
* NEW: AFP stats about active session via dbus IPC. Client side python
program `afpstats`. Requires dbus, dbus-glib any python-dbus.
configure option --dbus-sysconf-dir for specifying dbus
system security configuration files.

Changes in 3.0.2
================
Expand Down
8 changes: 7 additions & 1 deletion config/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,19 @@ SUFFIXES = .tmpl .
TMPLFILES = afp.conf.tmpl
GENFILES = afp.conf
CLEANFILES = $(GENFILES)
EXTRA_DIST = afp.conf.tmpl extmap.conf
EXTRA_DIST = afp.conf.tmpl extmap.conf netatalk-dbus.conf

OVERWRITE_CONFIG = @OVERWRITE_CONFIG@

CONFFILES = extmap.conf

pkgconfdir = @PKGCONFDIR@

if HAVE_DBUS_GLIB
dbusservicedir = $(DBUS_SYS_DIR)
dbusservice_DATA = netatalk-dbus.conf
endif

#
# rule to parse template files
#
Expand Down
17 changes: 17 additions & 0 deletions config/netatalk-dbus.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>

<!-- Only root can own AFP stats service -->
<policy user="root">
<allow own="org.netatalk.AFPStats"/>
</policy>

<!-- Allow anyone to invoke methods on time-sliderd -->
<policy context="default">
<allow send_destination="org.netatalk.AFPStats"/>
<allow receive_sender="org.netatalk.AFPStats"/>
</policy>

</busconfig>
2 changes: 1 addition & 1 deletion config/pam/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Makefile
Makefile.in
netatalk.pam
.gitignore
netatalk
*.o
28 changes: 5 additions & 23 deletions config/pam/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
## Makefile for distrib/pam/

SUFFIXES = .tmpl .
pamdir = @PAMDIR@/etc/pam.d
EXTRA_DIST = netatalk.pam.tmpl
noinst_SCRIPTS = netatalk.pam
CLEANFILES = netatalk.pam
EXTRA_DIST = netatalk.tmpl
noinst_SCRIPTS = netatalk
CLEANFILES = netatalk

.tmpl:
sed -e "s,[@]PAM_DIRECTIVE[@],${PAM_DIRECTIVE},g" \
Expand All @@ -15,23 +14,6 @@ CLEANFILES = netatalk.pam
<$< >$@

if USE_PAM
install-data-local: netatalk.pam
$(mkinstalldirs) $(DESTDIR)$(pamdir)
if test "x$(OVERWRITE_CONFIG)" = "xyes" -o ! -f $(DESTDIR)$(pamdir)/netatalk; then \
echo "$(INSTALL_DATA) $$f $(DESTDIR)$(pamdir)/netatalk"; \
$(INSTALL_DATA) netatalk.pam $(DESTDIR)$(pamdir)/netatalk || echo "WARNING: Can't install PAM files"; \
else \
echo "not overwriting $(DESTDIR)$(pamdir)/netatalk"; \
fi;

uninstall-local:
echo rm -f $(DESTDIR)$(pamdir)/netatalk; \
rm -f $(DESTDIR)$(pamdir)/netatalk; \
for f in $(CONFFILES) $(GENFILES); do \
echo rm -f $(DESTDIR)$(pkgconfdir)/$$f; \
rm -f $(DESTDIR)$(pkgconfdir)/$$f; \
done
else
install-data-local:
uninstall-local:
pamdir = $(PAMDIR)
pam_DATA = netatalk
endif
File renamed without changes.
3 changes: 3 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ AC_NETATALK_FHS
dnl netatalk lockfile path, must come after AC_NETATALK_FHS
AC_NETATALK_LOCKFILE

dnl Check for dbus-glib, for AFP stats on dbus
AC_NETATALK_DBUS_GLIB

CFLAGS="-I\$(top_srcdir)/include -I\$(top_srcdir)/sys $CFLAGS"
UAMS_PATH="${uams_path}"

Expand Down
4 changes: 2 additions & 2 deletions contrib/shell_utils/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ SUFFIXES = .tmpl .

CLEANFILES = $(GENERATED_FILES)

bin_SCRIPTS = $(PERLSCRIPTS) $(GENERATED_FILES)
bin_SCRIPTS = $(PERLSCRIPTS) $(GENERATED_FILES) afpstats

EXTRA_DIST = $(TEMPLATE_FILES) make-casetable.pl make-precompose.h.pl
EXTRA_DIST = $(TEMPLATE_FILES) make-casetable.pl make-precompose.h.pl afpstats
29 changes: 29 additions & 0 deletions contrib/shell_utils/afpstats
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env python

usage = """Usage:
python afpstats.py
"""

import sys
from traceback import print_exc
import dbus

def main():
bus = dbus.SystemBus()

try:
remote_object = bus.get_object("org.netatalk.AFPStats",
"/org/netatalk/AFPStats")

except dbus.DBusException:
print_exc()
sys.exit(1)

iface = dbus.Interface(remote_object, "org.netatalk.AFPStats")

reply = iface.GetUsers()
for name in reply:
print name

if __name__ == '__main__':
main()
23 changes: 22 additions & 1 deletion etc/afpd/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Makefile.am for etc/afpd/

pkgconfdir = @PKGCONFDIR@
BUILT_SOURCES =
EXTRA_DIST =
CLEANFILES =
DISTCLEANFILES =

sbin_PROGRAMS = afpd
noinst_PROGRAMS = hash fce
Expand Down Expand Up @@ -61,11 +65,28 @@ if HAVE_ACLS
afpd_SOURCES += acls.c
endif

if HAVE_DBUS_GLIB
BUILT_SOURCES += afpstats_service_glue.h
EXTRA_DIST += afpstats-service.xml
DISTCLEANFILES += afpstats_service_glue.h

afpstats_service_glue.h: afpstats-service.xml
$(LIBTOOL) --mode=execute \
dbus-binding-tool \
--prefix=afpstats_obj \
--mode=glib-server \
--output=afpstats_service_glue.h \
$(top_srcdir)/etc/afpd/afpstats-service.xml

afpd_SOURCES += afpstats.c afpstats_obj.c
afpd_CFLAGS += $(DBUS_CFLAGS) $(DBUS_GLIB_CFLAGS) -DDBUS_COMPILATION
afpd_LDFLAGS += $(DBUS_LIBS) $(DBUS_GLIB_LIBS) -ldbus-glib-1
endif

noinst_HEADERS = auth.h afp_config.h desktop.h directory.h fce_api_internal.h file.h \
filedir.h fork.h icon.h mangle.h misc.h status.h switch.h \
uam_auth.h uid.h unix.h volume.h hash.h acls.h acl_mappings.h extattrs.h \
dircache.h afp_zeroconf.h afp_avahi.h afp_mdns.h
dircache.h afp_zeroconf.h afp_avahi.h afp_mdns.h afpstats.h afpstats_obj.h

hash_SOURCES = hash.c
hash_CFLAGS = -DKAZLIB_TEST_MAIN -I$(top_srcdir)/include
Expand Down
15 changes: 6 additions & 9 deletions etc/afpd/afp_dsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,8 @@ void afp_over_dsi(AFPObj *obj)
int flag = 1;
setsockopt(dsi->socket, SOL_TCP, TCP_NODELAY, &flag, sizeof(flag));

ipc_child_state(obj, DSI_RUNNING);

/* get stuck here until the end */
while (1) {
if (sigsetjmp(recon_jmp, 1) != 0)
Expand All @@ -497,15 +499,6 @@ void afp_over_dsi(AFPObj *obj)
exit(0);
}

#if 0
/* got ECONNRESET in read from client => exit*/
if (dsi->flags & DSI_GOT_ECONNRESET) {
LOG(log_note, logtype_afpd, "afp_over_dsi: client connection reset");
afp_dsi_close(obj);
exit(0);
}
#endif

if (dsi->flags & DSI_RECONINPROG) {
LOG(log_note, logtype_afpd, "afp_over_dsi: failed reconnect");
afp_dsi_close(obj);
Expand All @@ -516,8 +509,11 @@ void afp_over_dsi(AFPObj *obj)
if (dsi_disconnect(dsi) != 0)
afp_dsi_die(EXITERR_CLNT);

ipc_child_state(obj, DSI_DISCONNECTED);

while (dsi->flags & DSI_DISCONNECTED)
pause(); /* gets interrupted by SIGALARM or SIGURG tickle */
ipc_child_state(obj, DSI_RUNNING);
continue; /* continue receiving until disconnect timer expires
* or a primary reconnect succeeds */
}
Expand All @@ -526,6 +522,7 @@ void afp_over_dsi(AFPObj *obj)
LOG(log_debug, logtype_afpd, "afp_over_dsi: got data, ending normal sleep");
dsi->flags &= ~DSI_SLEEPING;
dsi->tickle = 0;
ipc_child_state(obj, DSI_RUNNING);
}

if (reload_request) {
Expand Down
8 changes: 8 additions & 0 deletions etc/afpd/afpstats-service.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" ?>
<node name="/org/netatalk/AFPStats">
<interface name="org.netatalk.AFPStats">
<method name="GetUsers">
<arg name="ret" type="as" direction="out"/>
</method>
</interface>
</node>
118 changes: 118 additions & 0 deletions etc/afpd/afpstats.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Copyright (c) 2013 Frank Lahm <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <glib.h>
#include <gio/gio.h>
#include <dbus/dbus-glib.h>

#include <atalk/logger.h>
#include <atalk/compat.h>
#include <atalk/errchk.h>
#include <atalk/server_child.h>

#include "afpstats_obj.h"
#include "afpstats_service_glue.h"

/*
* Beware: this struct is accessed and modified from the main thread
* and from this thread, thus be careful to lock and unlock the mutex.
*/
static server_child_t *childs;

static gpointer afpstats_thread(gpointer _data)
{
DBusGConnection *bus;
DBusGProxy *bus_proxy;
GError *error = NULL;
GMainLoop *thread_loop;
guint request_name_result;
sigset_t sigs;

/* Block all signals in this thread */
sigfillset(&sigs);
pthread_sigmask(SIG_BLOCK, &sigs, NULL);

dbus_g_object_type_install_info(AFPSTATS_TYPE_OBJECT, &dbus_glib_afpstats_obj_object_info);

thread_loop = g_main_loop_new(NULL, FALSE);

if (!(bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error))) {
LOG(log_error, logtype_afpd,"Couldn't connect to system bus: %s", error->message);
return NULL;
}

if (!(bus_proxy = dbus_g_proxy_new_for_name(bus, "org.freedesktop.DBus",
"/org/freedesktop/DBus",
"org.freedesktop.DBus"))) {
LOG(log_error, logtype_afpd,"Couldn't create bus proxy");
return NULL;
}

if (!dbus_g_proxy_call(bus_proxy, "RequestName", &error,
G_TYPE_STRING, "org.netatalk.AFPStats",
G_TYPE_UINT, 0,
G_TYPE_INVALID,
G_TYPE_UINT, &request_name_result,
G_TYPE_INVALID)) {
LOG(log_error, logtype_afpd, "Failed to acquire DBUS name: %s", error->message);
return NULL;
}

AFPStatsObj *obj = g_object_new(AFPSTATS_TYPE_OBJECT, NULL);
dbus_g_connection_register_g_object(bus, "/org/netatalk/AFPStats", G_OBJECT(obj));

g_main_loop_run(thread_loop);
return thread_loop;
}

static void my_glib_log(const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message,
gpointer user_data)
{
LOG(log_error, logtype_afpd, "%s: %s", log_domain, message);
}

server_child_t *afpstats_get_and_lock_childs(void)
{
pthread_mutex_lock(&childs->servch_lock);
return childs;
}

void afpstats_unlock_childs(void)
{
pthread_mutex_unlock(&childs->servch_lock);
}

int afpstats_init(server_child_t *childs_in)
{
GThread *thread;

childs = childs_in;
g_type_init();
(void)g_log_set_default_handler(my_glib_log, NULL);
g_thread_init(NULL);
thread = g_thread_create(afpstats_thread, NULL, TRUE, NULL);

return 0;
}
23 changes: 23 additions & 0 deletions etc/afpd/afpstats.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2013 Frank Lahm <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/

#ifndef AFPD_AFPSTATS_H
#define AFPD_AFPSTATS_H

#include <atalk/server_child.h>

extern int afpstats_init(server_child_t *);
extern server_child_t *afpstats_get_and_lock_childs(void);
extern void afpstats_unlock_childs(void);
#endif
Loading

0 comments on commit 22ad101

Please sign in to comment.