diff options
author | Kay Sievers <kay.sievers@suse.de> | 2005-08-01 20:22:46 +0200 |
---|---|---|
committer | Kay Sievers <kay.sievers@suse.de> | 2005-08-01 20:22:46 +0200 |
commit | 1bc33626787f089523192c270790f9f878a4edd7 (patch) | |
tree | 9364115ab0af3a31341fddc4e217c20025162be9 | |
parent | d455b0085d65cd25915a34d84f894a4950d313a2 (diff) |
add udevmonitor, to debug netlink+udev events at the same time
This rule:
RUN+="socket:/org/kernel/udev/monitor"
send the event to the running monitor. Running udevstart give a nice
monitor output. Also the delay between the kernel uevent and the udev
udev event can be investigated:
pim:/home/kay/src/udev-kay # ./udevmonitor
UEVENT[1122920113] add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1
UEVENT[1122920113] add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0
UEVENT[1122920113] add@/class/scsi_host/host12
UEVENT[1122920113] add@/class/usb_device/usbdev2.99
UEVENT[1122920113] add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/host12/target12:0:0/12:0:0:0
UDEV [1122920113] add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1
UEVENT[1122920113] add@/block/sda
UEVENT[1122920113] add@/class/scsi_generic/sg0
UEVENT[1122920113] add@/class/scsi_device/12:0:0:0
UDEV [1122920113] add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0
UDEV [1122920113] add@/class/scsi_host/host12
UDEV [1122920113] add@/class/usb_device/usbdev2.99
UDEV [1122920113] add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/host12/target12:0:0/12:0:0:0
UDEV [1122920113] add@/block/sda
UDEV [1122920113] add@/class/scsi_generic/sg0
UDEV [1122920113] add@/class/scsi_device/12:0:0:0
UEVENT[1122920115] add@/block/sda/sda1
UDEV [1122920115] add@/block/sda/sda1
pim:/home/kay/src/udev-kay # ./udevmonitor --env
UDEV [1122920185] add@/block/sda/sda1
ACTION=add
DEVPATH=/block/sda/sda1
SUBSYSTEM=block
SEQNUM=2159
MINOR=1
MAJOR=8
PHYSDEVPATH=/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/host13/target13:0:0/13:0:0:0
PHYSDEVBUS=scsi
PHYSDEVDRIVER=sd
UDEVD_EVENT=1
UDEV_LOG=3
ID_VENDOR=IBM
ID_MODEL=Memory_Key
ID_REVISION=3.04
ID_SERIAL=IBM_Memory_Key_0218B301030027E8
ID_TYPE=disk
ID_BUS=usb
ID_PATH=usb-0218B301030027E8:0:0:0
ID_FS_USAGE=filesystem
ID_FS_TYPE=vfat
ID_FS_VERSION=FAT16
ID_FS_UUID=42D8-9E02
ID_FS_LABEL_SAFE=s_p_c
DEVNAME=/dev/sda1
Signed-off-by: Kay Sievers <kay.sievers@suse.de>
-rw-r--r-- | Makefile | 12 | ||||
-rw-r--r-- | udevd.h | 2 | ||||
-rw-r--r-- | udevmonitor.c | 185 |
3 files changed, 196 insertions, 3 deletions
@@ -49,6 +49,7 @@ COMPILE = udevrulescompile INITSENDER = udevinitsend RECORDER = udeveventrecorder CONTROL = udevcontrol +MONITOR = udevmonitor INFO = udevinfo TESTER = udevtest STARTER = udevstart @@ -204,7 +205,7 @@ endif # config files automatically generated GEN_CONFIGS = $(LOCAL_CFG_DIR)/udev.conf -all: $(ROOT) $(SENDER) $(COMPILE) $(INITSENDER) $(RECORDER) $(CONTROL) \ +all: $(ROOT) $(SENDER) $(COMPILE) $(INITSENDER) $(RECORDER) $(CONTROL) $(MONITOR)\ $(DAEMON) $(COMPILE) $(INFO) $(TESTER) $(STARTER) $(GEN_CONFIGS) $(KLCC) @extras="$(EXTRAS)" ; for target in $$extras ; do \ echo $$target ; \ @@ -275,6 +276,7 @@ $(COMPILE).o: $(HEADERS) $(GEN_HEADERS) $(HOST_PROGS) $(KLCC) $(INITSENDER).o: $(GEN_HEADERS) $(HOST_PROGS) $(KLCC) $(RECORDER).o: $(GEN_HEADERS) $(HOST_PROGS) $(KLCC) $(CONTROL).o: $(HEADERS) $( $(HEADERS)GEN_HEADERS) $(HOST_PROGS) $(KLCC) +$(MONITOR).o: $(HEADERS) $( $(HEADERS)GEN_HEADERS) $(HOST_PROGS) $(KLCC) $(STARTER).o: $(HEADERS) $(GEN_HEADERS) $(HOST_PROGS) $(KLCC) $(ROOT): $(KLCC) $(ROOT).o $(OBJS) $(HEADERS) $(GEN_MANPAGES) @@ -313,6 +315,10 @@ $(CONTROL): $(KLCC) $(CONTROL).o $(OBJS) udevd.h $(QUIET) $(LD) $(LDFLAGS) -o $@ $(CONTROL).o $(OBJS) $(LIB_OBJS) $(QUIET) $(STRIPCMD) $@ +$(MONITOR): $(KLCC) $(MONITOR).o $(OBJS) udevd.h + $(QUIET) $(LD) $(LDFLAGS) -o $@ $(MONITOR).o $(OBJS) $(LIB_OBJS) + $(QUIET) $(STRIPCMD) $@ + $(STARTER): $(KLCC) $(STARTER).o $(OBJS) $(QUIET) $(LD) $(LDFLAGS) -o $@ $(STARTER).o $(OBJS) $(LIB_OBJS) $(QUIET) $(STRIPCMD) $@ @@ -324,7 +330,7 @@ clean: -find . \( -not -type d \) -and \( -name '*~' -o -name '*.[oas]' \) -type f -print \ | xargs rm -f -rm -f core $(ROOT) $(GEN_HEADERS) $(GEN_CONFIGS) $(GEN_MANPAGES) $(INFO) $(DAEMON) \ - $(SENDER) $(COMPILE) $(INITSENDER) $(RECORDER) $(CONTROL) $(TESTER) $(STARTER) + $(SENDER) $(COMPILE) $(INITSENDER) $(RECORDER) $(CONTROL) $(MONITOR) $(TESTER) $(STARTER) -rm -f ccdv $(MAKE) -C klibc SUBDIRS=klibc clean @extras="$(EXTRAS)" ; for target in $$extras ; do \ @@ -374,6 +380,7 @@ install: install-config install-man all $(INSTALL_PROGRAM) -D $(DAEMON) $(DESTDIR)$(sbindir)/$(DAEMON) $(INSTALL_PROGRAM) -D $(SENDER) $(DESTDIR)$(sbindir)/$(SENDER) $(INSTALL_PROGRAM) -D $(CONTROL) $(DESTDIR)$(sbindir)/$(CONTROL) + $(INSTALL_PROGRAM) -D $(MONITOR) $(DESTDIR)$(sbindir)/$(MONITOR) $(INSTALL_PROGRAM) -D $(INFO) $(DESTDIR)$(usrbindir)/$(INFO) $(INSTALL_PROGRAM) -D $(TESTER) $(DESTDIR)$(usrbindir)/$(TESTER) $(INSTALL_PROGRAM) -D $(STARTER) $(DESTDIR)$(sbindir)/$(STARTER) @@ -399,6 +406,7 @@ uninstall: uninstall-man - rm $(sbindir)/$(INITSENDER) - rm $(sbindir)/$(RECORDER) - rm $(sbindir)/$(CONTROL) + - rm $(sbindir)/$(MONITOR) - rm $(sbindir)/$(STARTER) - rm $(usrbindir)/$(INFO) - rm $(usrbindir)/$(TESTER) @@ -22,7 +22,7 @@ #include "list.h" #define UDEV_MAGIC "udevd_" UDEV_VERSION -#define UDEVD_SOCK_PATH "udevd" +#define UDEVD_SOCK_PATH "/org/kernel/udev/udevd" #define UDEVSEND_WAIT_MAX_SECONDS 3 #define UDEVSEND_WAIT_LOOP_PER_SECOND 10 diff --git a/udevmonitor.c b/udevmonitor.c new file mode 100644 index 0000000000..f4f28b1659 --- /dev/null +++ b/udevmonitor.c @@ -0,0 +1,185 @@ +/* + * udevmonitor.c + * + * Copyright (C) 2004-2005 Kay Sievers <kay.sievers@vrfy.org> + * + * 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 version 2 of the License. + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <time.h> +#include <errno.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <sys/select.h> +#include <linux/netlink.h> +#include <asm/types.h> + +#include "udev.h" +#include "udevd.h" + +static int uevent_netlink_sock; +static int udev_monitor_sock; + +static int init_udev_monitor_socket(void) +{ + struct sockaddr_un saddr; + socklen_t addrlen; + const int feature_on = 1; + int retval; + + memset(&saddr, 0x00, sizeof(saddr)); + saddr.sun_family = AF_LOCAL; + /* use abstract namespace for socket path */ + strcpy(&saddr.sun_path[1], "/org/kernel/udev/monitor"); + addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path+1) + 1; + + udev_monitor_sock = socket(AF_LOCAL, SOCK_DGRAM, 0); + if (udev_monitor_sock == -1) { + fprintf(stderr, "error getting socket, %s\n", strerror(errno)); + return -1; + } + + /* the bind takes care of ensuring only one copy running */ + retval = bind(udev_monitor_sock, (struct sockaddr *) &saddr, addrlen); + if (retval < 0) { + fprintf(stderr, "bind failed, %s\n", strerror(errno)); + close(udev_monitor_sock); + return -1; + } + + /* enable receiving of the sender credentials */ + setsockopt(udev_monitor_sock, SOL_SOCKET, SO_PASSCRED, &feature_on, sizeof(feature_on)); + + return 0; +} + +static int init_uevent_netlink_sock(void) +{ + struct sockaddr_nl snl; + int retval; + + memset(&snl, 0x00, sizeof(struct sockaddr_nl)); + snl.nl_family = AF_NETLINK; + snl.nl_pid = getpid(); + snl.nl_groups = 0xffffffff; + + uevent_netlink_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); + if (uevent_netlink_sock == -1) { + fprintf(stderr, "error getting socket, %s\n", strerror(errno)); + return -1; + } + + retval = bind(uevent_netlink_sock, (struct sockaddr *) &snl, + sizeof(struct sockaddr_nl)); + if (retval < 0) { + fprintf(stderr, "bind failed, %s\n", strerror(errno)); + close(uevent_netlink_sock); + uevent_netlink_sock = -1; + return -1; + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + int env = 0; + int maxsockplus; + fd_set readfds; + int retval; + + if (getuid() != 0) { + printf("need to be root, exit\n"); + exit(1); + } + + if (argc == 2 && strstr(argv[1], "--env")) + env = 1; + + init_uevent_netlink_sock(); + init_udev_monitor_socket(); + + FD_ZERO(&readfds); + FD_SET(uevent_netlink_sock, &readfds); + FD_SET(udev_monitor_sock, &readfds); + maxsockplus = udev_monitor_sock+1; + + while (1) { + static char buf[UEVENT_BUFFER_SIZE*2]; + ssize_t buflen; + fd_set workreadfds; + + buflen = 0; + workreadfds = readfds; + + retval = select(maxsockplus, &workreadfds, NULL, NULL, NULL); + if (retval < 0) { + if (errno != EINTR) + fprintf(stderr, "error receiving uevent message\n"); + continue; + } + + if (FD_ISSET(uevent_netlink_sock, &workreadfds)) { + buflen = recv(uevent_netlink_sock, &buf, sizeof(buf), 0); + if (buflen <= 0) { + fprintf(stderr, "error receiving uevent message\n"); + continue; + } + printf("UEVENT[%i] %s\n", time(NULL), buf); + } + + if (FD_ISSET(udev_monitor_sock, &workreadfds)) { + buflen = recv(udev_monitor_sock, &buf, sizeof(buf), 0); + if (buflen <= 0) { + fprintf(stderr, "error receiving udev message\n"); + continue; + } + printf("UDEV [%i] %s\n", time(NULL), buf); + } + + if (buflen == 0) + continue; + + /* print environment */ + if (env) { + size_t bufpos; + + /* start of payload */ + bufpos = strlen(buf) + 1; + + while (bufpos < (size_t)buflen) { + int keylen; + char *key; + + key = &buf[bufpos]; + keylen = strlen(key); + if (keylen == 0) + break; + printf("%s\n", key); + bufpos += keylen + 1; + } + printf("\n"); + } + } + + close(uevent_netlink_sock); + close(udev_monitor_sock); + exit(1); +} |