From 9cdbd6a40181df931765a7cb5cf506d76fced59b Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 10 Feb 2014 19:03:43 -0600 Subject: trivial: remove unused nm-netlink-monitor Obsoleted by the platform, no longer used. --- po/POTFILES.in | 1 - src/Makefile.am | 2 - src/nm-netlink-monitor.c | 604 ----------------------------------------------- src/nm-netlink-monitor.h | 76 ------ 4 files changed, 683 deletions(-) delete mode 100644 src/nm-netlink-monitor.c delete mode 100644 src/nm-netlink-monitor.h diff --git a/po/POTFILES.in b/po/POTFILES.in index 28bb161620..5c63b9d941 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -58,7 +58,6 @@ src/devices/nm-device-olpc-mesh.c src/devices/nm-device-team.c src/devices/nm-device-vlan.c src/nm-manager.c -src/nm-netlink-monitor.c src/nm-sleep-monitor-systemd.c src/settings/plugins/ifcfg-rh/reader.c src/settings/nm-settings-utils.c diff --git a/src/Makefile.am b/src/Makefile.am index 3b0cd3f115..96de1124b7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -253,8 +253,6 @@ nm_sources = \ nm-auth-subject.h \ nm-manager.c \ nm-manager.h \ - nm-netlink-monitor.c \ - nm-netlink-monitor.h \ nm-policy-hosts.c \ nm-policy-hosts.h \ nm-policy.c \ diff --git a/src/nm-netlink-monitor.c b/src/nm-netlink-monitor.c deleted file mode 100644 index 1e8d8b3726..0000000000 --- a/src/nm-netlink-monitor.c +++ /dev/null @@ -1,604 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * 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. - * - * 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2005 - 2010 Red Hat, Inc. - * Copyright (C) 2005 - 2008 Novell, Inc. - * Copyright (C) 2005 Ray Strode - * - * Some code borrowed from HAL: - * - * Copyright (C) 2003 David Zeuthen, - * Copyright (C) 2004 Novell, Inc. - */ - -/* for struct ucred and LIBNL_NEEDS_ADDR_CACHING_WORKAROUND */ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "NetworkManagerUtils.h" -#include "nm-netlink-monitor.h" -#include "nm-logging.h" - -#define EVENT_CONDITIONS ((GIOCondition) (G_IO_IN | G_IO_PRI)) -#define ERROR_CONDITIONS ((GIOCondition) (G_IO_ERR | G_IO_NVAL)) -#define DISCONNECT_CONDITIONS ((GIOCondition) (G_IO_HUP)) - -#define NM_NETLINK_MONITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ - NM_TYPE_NETLINK_MONITOR, \ - NMNetlinkMonitorPrivate)) - -typedef struct { - /* Async event listener connection */ - struct nl_sock *nlh_event; - GIOChannel * io_channel; - guint event_id; - - /* Sync/blocking request/response connection */ - struct nl_sock *nlh_sync; - - GHashTable *subscriptions; -} NMNetlinkMonitorPrivate; - -enum { - NOTIFICATION = 0, - CARRIER_ON, - CARRIER_OFF, - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL] = { 0 }; - - -G_DEFINE_TYPE (NMNetlinkMonitor, nm_netlink_monitor, G_TYPE_OBJECT); - -/****************************************************************/ - -static void -detach (NMNetlinkMonitor *self) -{ - NMNetlinkMonitorPrivate *priv; - - g_return_if_fail (NM_IS_NETLINK_MONITOR (self)); - - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - g_return_if_fail (priv->event_id > 0); - - g_source_remove (priv->event_id); - priv->event_id = 0; -} - -static gboolean -detach_monitor (gpointer data) -{ - nm_log_warn (LOGD_HW, "detaching netlink event monitor"); - detach (NM_NETLINK_MONITOR (data)); - return FALSE; -} - -static void -log_error_limited (NMNetlinkMonitor *monitor, guint32 code, const char *fmt, ...) -{ - static gint64 rl_time = -10001; - static guint32 rl_code = 0; - static guint32 rl_count = 0; - va_list args; - char *msg; - gint64 now; - - g_return_if_fail (monitor != NULL); - - now = nm_utils_get_monotonic_timestamp_ms (); - - if (code != rl_code || now > rl_time + 10000) { - va_start (args, fmt); - msg = g_strdup_vprintf (fmt, args); - va_end (args); - - nm_log_warn (LOGD_HW, "error monitoring device for netlink events: %s\n", msg); - g_free (msg); - - rl_time = now; - rl_code = code; - rl_count = 0; - } - - rl_count++; - if (rl_count > 100) { - /* Broken drivers will sometimes cause a flood of netlink errors. - * rh #459205, novell #443429, lp #284507 - */ - nm_log_warn (LOGD_HW, "excessive netlink errors ocurred, disabling netlink monitor."); - nm_log_warn (LOGD_HW, "link change events will not be processed."); - g_idle_add_full (G_PRIORITY_HIGH, detach_monitor, monitor, NULL); - } -} - -/****************************************************************/ - -static int -event_msg_recv (struct nl_msg *msg, void *arg) -{ - struct nl_sock *nlh = arg; - struct nlmsghdr *hdr = nlmsg_hdr (msg); - struct ucred *creds = nlmsg_get_creds (msg); - const struct sockaddr_nl *snl; - guint32 local_port; - gboolean accept_msg = FALSE; - - /* Only messages sent from the kernel */ - if (!creds || creds->uid != 0) { - nm_log_dbg (LOGD_HW, "ignoring netlink message from UID %d", - creds ? creds->uid : -1); - return NL_SKIP; - } - - snl = nlmsg_get_src (msg); - g_assert (snl); - - /* Accept any messages from the kernel */ - if (hdr->nlmsg_pid == 0 || snl->nl_pid == 0) - accept_msg = TRUE; - - /* And any multicast message directed to our netlink PID, since multicast - * currently requires CAP_ADMIN to use. - */ - local_port = nl_socket_get_local_port (nlh); - if ((hdr->nlmsg_pid == local_port) && snl->nl_groups) - accept_msg = TRUE; - - if (accept_msg == FALSE) { - nm_log_dbg (LOGD_HW, "ignoring netlink message from PID %d (local PID %d, multicast %d)", - hdr->nlmsg_pid, - local_port, - (hdr->nlmsg_flags & NLM_F_MULTI)); - return NL_SKIP; - } - - return NL_OK; -} - -static int -event_msg_ready (struct nl_msg *msg, void *arg) -{ - NMNetlinkMonitor *self = NM_NETLINK_MONITOR (arg); - - /* By the time the message gets here we've already checked the sender - * and we're sure it's safe to parse this message. - */ - - /* Let clients handle generic messages */ - g_signal_emit (self, signals[NOTIFICATION], 0, msg); - - return NL_OK; -} - -static gboolean -event_handler (GIOChannel *channel, - GIOCondition io_condition, - gpointer user_data) -{ - NMNetlinkMonitor *self = (NMNetlinkMonitor *) user_data; - NMNetlinkMonitorPrivate *priv; - int err; - - g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), TRUE); - - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - g_return_val_if_fail (priv->event_id > 0, TRUE); - - if (io_condition & ERROR_CONDITIONS) { - const char *err_msg = _("error occurred while waiting for data on socket"); - int err_code = 0; - socklen_t err_len = sizeof (err_code); - - /* Grab error information */ - if (getsockopt (g_io_channel_unix_get_fd (channel), - SOL_SOCKET, SO_ERROR, - (void *) &err_code, &err_len) == 0) - err_msg = strerror (err_code); - - log_error_limited (self, NM_NETLINK_MONITOR_ERROR_WAITING_FOR_SOCKET_DATA, "%s", err_msg); - return TRUE; - } else if (io_condition & DISCONNECT_CONDITIONS) - return FALSE; - - g_return_val_if_fail (!(io_condition & ~EVENT_CONDITIONS), FALSE); - - /* Process the netlink messages */ - err = nl_recvmsgs_default (priv->nlh_event); - if (err < 0) { - log_error_limited (self, NM_NETLINK_MONITOR_ERROR_PROCESSING_MESSAGE, - _("error processing netlink message: %s"), - nl_geterror (err)); - } - - return TRUE; -} - -static gboolean -nlh_setup (struct nl_sock *nlh, - nl_recvmsg_msg_cb_t valid_func, - gpointer cb_data, - GError **error) -{ - int err; - - nl_socket_modify_cb (nlh, NL_CB_MSG_IN, NL_CB_CUSTOM, event_msg_recv, cb_data); - - if (valid_func) - nl_socket_modify_cb (nlh, NL_CB_VALID, NL_CB_CUSTOM, valid_func, cb_data); - - err = nl_connect (nlh, NETLINK_ROUTE); - if (err < 0) { - g_set_error (error, NM_NETLINK_MONITOR_ERROR, - NM_NETLINK_MONITOR_ERROR_NETLINK_CONNECT, - _("unable to connect to netlink for monitoring link status: %s"), - nl_geterror (err)); - return FALSE; - } - - /* Enable unix socket peer credentials which we use for verifying that the - * sender of the message is actually the kernel. - */ - if (nl_socket_set_passcred (nlh, 1) < 0) { - g_set_error (error, NM_NETLINK_MONITOR_ERROR, - NM_NETLINK_MONITOR_ERROR_NETLINK_CONNECT, - _("unable to enable netlink handle credential passing: %s"), - nl_geterror (err)); - return FALSE; - } - - return TRUE; -} - -static void -close_connection (NMNetlinkMonitor *self) -{ - NMNetlinkMonitorPrivate *priv; - - g_return_if_fail (NM_IS_NETLINK_MONITOR (self)); - - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - g_return_if_fail (priv->io_channel != NULL); - - if (priv->event_id) - detach (self); - - g_io_channel_shutdown (priv->io_channel, - TRUE /* flush pending data */, - NULL); - g_io_channel_unref (priv->io_channel); - priv->io_channel = NULL; -} - -static gboolean -event_connection_setup (NMNetlinkMonitor *self, GError **error) -{ - NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - GError *channel_error = NULL; - GIOFlags channel_flags; - int fd; - int nle; - - g_return_val_if_fail (priv->io_channel == NULL, FALSE); - - /* Set up the event listener connection */ - priv->nlh_event = nl_socket_alloc (); - if (!priv->nlh_event) { - g_set_error (error, NM_NETLINK_MONITOR_ERROR, - NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_HANDLE, - _("unable to allocate netlink handle for monitoring link status: %s"), - nl_geterror (ENOMEM)); - goto error; - } - - if (!nlh_setup (priv->nlh_event, event_msg_ready, self, error)) - goto error; - - nl_socket_disable_seq_check (priv->nlh_event); - - /* The default buffer size wasn't enough for the testsuites. It might just - * as well happen with NetworkManager itself. For now let's hope 128KB is - * good enough. - */ - nle = nl_socket_set_buffer_size (priv->nlh_event, 131072, 0); - g_assert (!nle); - - /* Subscribe to the LINK group for internal carrier signals */ - if (!nm_netlink_monitor_subscribe (self, RTNLGRP_LINK, error)) - goto error; - - fd = nl_socket_get_fd (priv->nlh_event); - priv->io_channel = g_io_channel_unix_new (fd); - - g_io_channel_set_encoding (priv->io_channel, NULL, &channel_error); - /* Encoding is NULL, so no conversion error can possibly occur */ - g_assert (channel_error == NULL); - - g_io_channel_set_close_on_unref (priv->io_channel, TRUE); - channel_flags = g_io_channel_get_flags (priv->io_channel); - channel_error = NULL; - g_io_channel_set_flags (priv->io_channel, - channel_flags | G_IO_FLAG_NONBLOCK, - &channel_error); - if (channel_error != NULL) { - g_propagate_error (error, channel_error); - goto error; - } - - return TRUE; - -error: - if (priv->io_channel) - close_connection (self); - - if (priv->nlh_event) { - nl_socket_free (priv->nlh_event); - priv->nlh_event = NULL; - } - - return FALSE; -} - -static gboolean -sync_connection_setup (NMNetlinkMonitor *self, GError **error) -{ - NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - /* Set up the event listener connection */ - priv->nlh_sync = nl_socket_alloc (); - if (!priv->nlh_sync) { - g_set_error (error, NM_NETLINK_MONITOR_ERROR, - NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_HANDLE, - _("unable to allocate netlink handle for monitoring link status: %s"), - nl_geterror (ENOMEM)); - goto error; - } - - if (!nlh_setup (priv->nlh_sync, NULL, self, error)) - goto error; - - return TRUE; -error: - if (priv->nlh_sync) { - nl_socket_free (priv->nlh_sync); - priv->nlh_sync = NULL; - } - - return FALSE; -} - -static gboolean -open_connection (NMNetlinkMonitor *self, GError **error) -{ - g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), FALSE); - - if (!event_connection_setup (self, error)) - return FALSE; - - if (!sync_connection_setup (self, error)) - return FALSE; - - return TRUE; -} - -static void -attach (NMNetlinkMonitor *self) -{ - NMNetlinkMonitorPrivate *priv; - - g_return_if_fail (NM_IS_NETLINK_MONITOR (self)); - - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - g_return_if_fail (priv->nlh_event != NULL); - g_return_if_fail (priv->event_id == 0); - - priv->event_id = g_io_add_watch (priv->io_channel, - (EVENT_CONDITIONS | ERROR_CONDITIONS | DISCONNECT_CONDITIONS), - event_handler, self); -} - -static int -get_subs (NMNetlinkMonitor *self, int group) -{ - NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - - return GPOINTER_TO_INT (g_hash_table_lookup (priv->subscriptions, - GINT_TO_POINTER (group))); -} - -static void -set_subs (NMNetlinkMonitor *self, int group, int new_subs) -{ - NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - - g_hash_table_insert (priv->subscriptions, - GINT_TO_POINTER (group), - GINT_TO_POINTER (new_subs)); -} - -gboolean -nm_netlink_monitor_subscribe (NMNetlinkMonitor *self, int group, GError **error) -{ - NMNetlinkMonitorPrivate *priv; - int subs, err; - - g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), FALSE); - - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - - if (!priv->nlh_event) { - if (!open_connection (self, error)) - return FALSE; - } - - subs = get_subs (self, group) + 1; - if (subs == 1) { - err = nl_socket_add_membership (priv->nlh_event, group); - if (err < 0) { - g_set_error (error, NM_NETLINK_MONITOR_ERROR, - NM_NETLINK_MONITOR_ERROR_NETLINK_JOIN_GROUP, - _("unable to join netlink group: %s"), - nl_geterror (err)); - return FALSE; - } - } - - /* Update # of subscriptions for this group */ - set_subs (self, group, subs); - - return TRUE; -} - -/***************************************************************/ - -gboolean -nm_netlink_monitor_request_ip6_info (NMNetlinkMonitor *self, GError **error) -{ - NMNetlinkMonitorPrivate *priv; - - g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), FALSE); - - priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - - /* FIXME: nl_rtgen_request() gets the return value screwed up with - * libnl-1.1; revisit this and return a proper error when we port to - * a later libnl. - */ - nl_rtgen_request (priv->nlh_event, RTM_GETLINK, AF_INET6, NLM_F_DUMP); - - return TRUE; -} - -/***************************************************************/ - -struct nl_sock * -nm_netlink_get_default_handle (void) -{ - NMNetlinkMonitor *self; - struct nl_sock *nlh; - - self = nm_netlink_monitor_get (); - nlh = NM_NETLINK_MONITOR_GET_PRIVATE (self)->nlh_sync; - - return nlh; -} - -/***************************************************************/ - -NMNetlinkMonitor * -nm_netlink_monitor_get (void) -{ - static NMNetlinkMonitor *singleton = NULL; - GError *error = NULL; - - if (!singleton) { - singleton = (NMNetlinkMonitor *) g_object_new (NM_TYPE_NETLINK_MONITOR, NULL); - g_return_val_if_fail (singleton != NULL, NULL); - - if (open_connection (singleton, &error)) { - attach (singleton); - } else { - nm_log_warn (LOGD_HW, "Failed to connect to netlink: (%d) %s", - error ? error->code : 0, - (error && error->message) ? error->message : "(unknown)"); - g_clear_error (&error); - - g_object_unref (singleton); - singleton = NULL; - } - } - - return singleton; -} - -static void -nm_netlink_monitor_init (NMNetlinkMonitor *self) -{ - NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - - priv->subscriptions = g_hash_table_new (g_direct_hash, g_direct_equal); -} - -static void -finalize (GObject *object) -{ - NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (object); - - if (priv->io_channel) - close_connection (NM_NETLINK_MONITOR (object)); - - if (priv->nlh_event) { - nl_socket_free (priv->nlh_event); - priv->nlh_event = NULL; - } - - if (priv->nlh_sync) { - nl_socket_free (priv->nlh_sync); - priv->nlh_sync = NULL; - } - - g_hash_table_destroy (priv->subscriptions); - - G_OBJECT_CLASS (nm_netlink_monitor_parent_class)->finalize (object); -} - -static void -nm_netlink_monitor_class_init (NMNetlinkMonitorClass *monitor_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (monitor_class); - - g_type_class_add_private (monitor_class, sizeof (NMNetlinkMonitorPrivate)); - - /* Virtual methods */ - object_class->finalize = finalize; - - /* Signals */ - signals[NOTIFICATION] = - g_signal_new ("notification", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMNetlinkMonitorClass, notification), - NULL, NULL, g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); -} - -GQuark -nm_netlink_monitor_error_quark (void) -{ - static GQuark error_quark = 0; - - if (G_UNLIKELY (error_quark == 0)) - error_quark = g_quark_from_static_string ("nm-netlink-monitor-error-quark"); - return error_quark; -} - diff --git a/src/nm-netlink-monitor.h b/src/nm-netlink-monitor.h deleted file mode 100644 index 7295616b9a..0000000000 --- a/src/nm-netlink-monitor.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * 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. - * - * 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2005 - 2010 Red Hat, Inc. - * Copyright (C) 2005 - 2008 Novell, Inc. - * Copyright (C) 2005 Ray Strode - */ - -#ifndef NM_NETLINK_MONITOR_H -#define NM_NETLINK_MONITOR_H - -#include -#include - -#define NM_TYPE_NETLINK_MONITOR (nm_netlink_monitor_get_type ()) -#define NM_NETLINK_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_NETLINK_MONITOR, NMNetlinkMonitor)) -#define NM_NETLINK_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_NETLINK_MONITOR, NMNetlinkMonitorClass)) -#define NM_IS_NETLINK_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_NETLINK_MONITOR)) -#define NM_IS_NETLINK_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_NETLINK_MONITOR)) -#define NM_NETLINK_MONITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_NETLINK_MONITOR, NMNetlinkMonitorClass)) - -typedef enum { - NM_NETLINK_MONITOR_ERROR_GENERIC = 0, - NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_HANDLE, - NM_NETLINK_MONITOR_ERROR_NETLINK_CONNECT, - NM_NETLINK_MONITOR_ERROR_NETLINK_JOIN_GROUP, - NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_LINK_CACHE, - NM_NETLINK_MONITOR_ERROR_PROCESSING_MESSAGE, - NM_NETLINK_MONITOR_ERROR_BAD_ALLOC, - NM_NETLINK_MONITOR_ERROR_WAITING_FOR_SOCKET_DATA, - NM_NETLINK_MONITOR_ERROR_LINK_CACHE_UPDATE -} NMNetlinkMonitorError; - -typedef struct { - GObject parent; -} NMNetlinkMonitor; - -typedef struct { - GObjectClass parent_class; - - /* Signals */ - void (*notification) (NMNetlinkMonitor *monitor, struct nl_msg *msg); -} NMNetlinkMonitorClass; - - -#define NM_NETLINK_MONITOR_ERROR (nm_netlink_monitor_error_quark ()) -GType nm_netlink_monitor_get_type (void) G_GNUC_CONST; -GQuark nm_netlink_monitor_error_quark (void) G_GNUC_CONST; - -NMNetlinkMonitor *nm_netlink_monitor_get (void); - -gboolean nm_netlink_monitor_subscribe (NMNetlinkMonitor *monitor, - int group, - GError **error); - -gboolean nm_netlink_monitor_request_ip6_info (NMNetlinkMonitor *monitor, - GError **error); - -/* Generic utility functions */ -struct nl_sock * nm_netlink_get_default_handle (void); - -#endif /* NM_NETLINK_MONITOR_H */ -- cgit v1.2.1