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 (nm_netlink_monitor_open_connection (singleton, &error)) {
			nm_netlink_monitor_attach (singleton);
			/* Request initial status of cards */
			nm_netlink_monitor_request_status (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;
		}
	} else
		g_object_ref (singleton);

	return singleton;
}
int
main (void)
{
	NmNetlinkMonitor *monitor;
	GMainLoop *loop;
	GError *error;

	g_type_init ();

	monitor = nm_netlink_monitor_new ();

	error = NULL;
	nm_netlink_monitor_open_connection (monitor, &error);

	if (error != NULL)
	{
		g_printerr ("could not open connection: %s\n",
			    error->message);
		g_error_free (error);
		return 1;
	}

	loop = g_main_loop_new (NULL, FALSE);

	g_signal_connect (G_OBJECT (monitor),
			  "interface-connected",
			  G_CALLBACK (device_added), NULL);

	g_signal_connect (G_OBJECT (monitor),
			  "interface-disconnected",
			  G_CALLBACK (device_removed), NULL);

	nm_netlink_monitor_attach (monitor, NULL);

	nm_netlink_monitor_request_status (monitor, &error);

	if (error != NULL)
	{
		g_printerr ("could not request status of interfaces: %s\n",
			    error->message);
		g_error_free (error);
		return 2;
	}

	g_main_loop_run (loop);

	return 0;
}
static GObject*
constructor (GType type,
			 guint n_construct_params,
			 GObjectConstructParam *construct_params)
{
	GObject *object;
	NMDeviceWiredPrivate *priv;
	NMDevice *self;
	guint32 caps;

	object = G_OBJECT_CLASS (nm_device_wired_parent_class)->constructor (type,
	                                                                     n_construct_params,
	                                                                     construct_params);
	if (!object)
		return NULL;

	self = NM_DEVICE (object);
	priv = NM_DEVICE_WIRED_GET_PRIVATE (self);

	nm_log_dbg (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (NM_DEVICE (self)),
	            "(%s): kernel ifindex %d",
	            nm_device_get_iface (NM_DEVICE (self)),
	            nm_device_get_ifindex (NM_DEVICE (self)));

	if (nm_device_get_device_type (self) == NM_DEVICE_TYPE_ETHERNET) {
		priv->hw_addr_type = ARPHRD_ETHER;
		priv->hw_addr_len = ETH_ALEN;
	} else if (nm_device_get_device_type (self) == NM_DEVICE_TYPE_INFINIBAND) {
		priv->hw_addr_type = ARPHRD_INFINIBAND;
		priv->hw_addr_len = INFINIBAND_ALEN;
	} else if (nm_device_get_device_type (self) == NM_DEVICE_TYPE_BOND) {
		/* We may not know the hardware address type until a slave is added */
		priv->hw_addr_type = ARPHRD_ETHER;
		priv->hw_addr_len = ETH_ALEN;
	} else
		g_assert_not_reached ();

	caps = nm_device_get_capabilities (self);
	if (caps & NM_DEVICE_CAP_CARRIER_DETECT) {
		/* Only listen to netlink for cards that support carrier detect */
		priv->monitor = nm_netlink_monitor_get ();

		priv->link_connected_id = g_signal_connect (priv->monitor, "carrier-on",
		                                            G_CALLBACK (carrier_on),
		                                            self);
		priv->link_disconnected_id = g_signal_connect (priv->monitor, "carrier-off",
		                                               G_CALLBACK (carrier_off),
		                                               self);

		priv->carrier = get_carrier_sync (NM_DEVICE_WIRED (self));

		nm_log_info (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (NM_DEVICE (self)),
		             "(%s): carrier is %s",
		             nm_device_get_iface (NM_DEVICE (self)),
		             priv->carrier ? "ON" : "OFF");

		/* Request link state again just in case an error occurred getting the
		 * initial link state.
		 */
		nm_netlink_monitor_request_status (priv->monitor);
	} else {
		nm_log_info (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (NM_DEVICE (self)),
		             "(%s): driver '%s' does not support carrier detection.",
		             nm_device_get_iface (self),
		             nm_device_get_driver (self));
		priv->carrier = TRUE;
	}

	return object;
}