mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-07-22 02:35:25 +00:00
2008-07-09 Dan Williams <dcbw@redhat.com>
* callouts/Makefile.am callouts/nm-avahi-autoipd-action.c callouts/nm-avahi-autoipd.conf - avahi-autoipd callout to send options back to NM * src/autoip.c src/autoip.h - remove * src/nm-device.c src/nm-device-private.h src/nm-manager.c - Use avahi-autoipd for IPv4LL functionality rather than really crappy old custom stuff git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3816 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
parent
e059e6176d
commit
64f1a1d423
17
ChangeLog
17
ChangeLog
|
@ -1,3 +1,20 @@
|
|||
2008-07-09 Dan Williams <dcbw@redhat.com>
|
||||
|
||||
* callouts/Makefile.am
|
||||
callouts/nm-avahi-autoipd-action.c
|
||||
callouts/nm-avahi-autoipd.conf
|
||||
- avahi-autoipd callout to send options back to NM
|
||||
|
||||
* src/autoip.c
|
||||
src/autoip.h
|
||||
- remove
|
||||
|
||||
* src/nm-device.c
|
||||
src/nm-device-private.h
|
||||
src/nm-manager.c
|
||||
- Use avahi-autoipd for IPv4LL functionality rather than really crappy
|
||||
old custom stuff
|
||||
|
||||
2008-07-07 Dan Williams <dcbw@redhat.com>
|
||||
|
||||
* system-settings/plugins/ifcfg-fedora/reader.c
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
dbusservicedir = $(DBUS_SYS_DIR)
|
||||
dbusservice_DATA = \
|
||||
nm-dhcp-client.conf \
|
||||
nm-dispatcher.conf
|
||||
nm-dispatcher.conf \
|
||||
nm-avahi-autoipd.conf
|
||||
|
||||
libexec_PROGRAMS = \
|
||||
nm-dhcp-client.action \
|
||||
nm-dispatcher.action
|
||||
nm-dispatcher.action \
|
||||
nm-avahi-autoipd.action
|
||||
|
||||
nm_dhcp_client_action_SOURCES = \
|
||||
nm-dhcp-client-action.c
|
||||
|
@ -23,6 +25,22 @@ nm_dhcp_client_action_LDADD = \
|
|||
$(GTHREAD_LIBS)
|
||||
|
||||
|
||||
nm_avahi_autoipd_action_SOURCES = \
|
||||
nm-avahi-autoipd-action.c
|
||||
|
||||
nm_avahi_autoipd_action_CPPFLAGS = \
|
||||
$(DBUS_CFLAGS) \
|
||||
$(GTHREAD_CFLAGS) \
|
||||
-DDBUS_API_SUBJECT_TO_CHANGE \
|
||||
-DG_DISABLE_DEPRECATED \
|
||||
-DSYSCONFDIR=\"$(sysconfdir)\" \
|
||||
-DLIBEXECDIR=\"$(libexecdir)\"
|
||||
|
||||
nm_avahi_autoipd_action_LDADD = \
|
||||
$(DBUS_LIBS) \
|
||||
$(GTHREAD_LIBS)
|
||||
|
||||
|
||||
nm_dispatcher_action_SOURCES = \
|
||||
nm-dispatcher-action.c \
|
||||
nm-dispatcher-action.h
|
||||
|
|
151
callouts/nm-avahi-autoipd-action.c
Normal file
151
callouts/nm-avahi-autoipd-action.c
Normal file
|
@ -0,0 +1,151 @@
|
|||
/* NetworkManager -- Network link manager
|
||||
*
|
||||
* Dan Williams <dcbw@redhat.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* (C) Copyright 2008 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <dbus/dbus.h>
|
||||
#include <dbus/dbus-glib-lowlevel.h>
|
||||
#include <dbus/dbus-glib.h>
|
||||
|
||||
#define NM_AVAHI_AUTOIPD_DBUS_SERVICE "org.freedesktop.nm_avahi_autoipd"
|
||||
#define NM_AVAHI_AUTOIPD_DBUS_IFACE "org.freedesktop.nm_avahi_autoipd"
|
||||
|
||||
static DBusConnection *
|
||||
dbus_init (void)
|
||||
{
|
||||
DBusConnection * connection;
|
||||
DBusError error;
|
||||
int ret, flags;
|
||||
|
||||
dbus_connection_set_change_sigpipe (TRUE);
|
||||
|
||||
dbus_error_init (&error);
|
||||
connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
|
||||
if (dbus_error_is_set (&error)) {
|
||||
fprintf (stderr, "Error: could not get the system bus. Make sure "
|
||||
"the message bus daemon is running! Message: (%s) %s\n",
|
||||
error.name,
|
||||
error.message);
|
||||
goto error;
|
||||
}
|
||||
|
||||
dbus_connection_set_exit_on_disconnect (connection, FALSE);
|
||||
|
||||
#if (DBUS_VERSION_MAJOR == 0) && (DBUS_VERSION_MINOR < 60)
|
||||
flags = DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT;
|
||||
#else
|
||||
flags = DBUS_NAME_FLAG_DO_NOT_QUEUE;
|
||||
#endif
|
||||
|
||||
dbus_error_init (&error);
|
||||
ret = dbus_bus_request_name (connection,
|
||||
NM_AVAHI_AUTOIPD_DBUS_SERVICE,
|
||||
flags,
|
||||
&error);
|
||||
if (dbus_error_is_set (&error)) {
|
||||
fprintf (stderr, "Error: Could not acquire the NM DHCP client service. "
|
||||
"Message: (%s) %s\n",
|
||||
error.name,
|
||||
error.message);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
|
||||
fprintf (stderr, "Error: Could not acquire the NM DHCP client service "
|
||||
"as it is already taken. Return: %d\n",
|
||||
ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
return connection;
|
||||
|
||||
error:
|
||||
if (dbus_error_is_set (&error))
|
||||
dbus_error_free (&error);
|
||||
if (connection)
|
||||
dbus_connection_unref (connection);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
DBusConnection *connection;
|
||||
DBusMessage *message;
|
||||
dbus_bool_t result;
|
||||
char *event, *iface, *address;
|
||||
|
||||
g_type_init ();
|
||||
|
||||
if (argc != 4) {
|
||||
fprintf (stderr, "Error: expected 3 arguments (event, interface, address).\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
event = argv[1];
|
||||
iface = argv[2];
|
||||
address = argv[3] ? argv[3] : "";
|
||||
|
||||
if (!event || !iface || !strlen (event) || !strlen (iface)) {
|
||||
fprintf (stderr, "Error: unexpected arguments received from avahi-autoipd.\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Get a connection to the system bus */
|
||||
connection = dbus_init ();
|
||||
if (connection == NULL)
|
||||
exit (1);
|
||||
|
||||
message = dbus_message_new_signal ("/", NM_AVAHI_AUTOIPD_DBUS_IFACE, "Event");
|
||||
if (message == NULL) {
|
||||
fprintf (stderr, "Error: not enough memory to send autoip Event signal.\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (!dbus_message_append_args (message,
|
||||
DBUS_TYPE_STRING, &event,
|
||||
DBUS_TYPE_STRING, &iface,
|
||||
DBUS_TYPE_STRING, &address,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
fprintf (stderr, "Error: failed to construct autoip Event signal.\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* queue the message */
|
||||
result = dbus_connection_send (connection, message, NULL);
|
||||
if (!result) {
|
||||
fprintf (stderr, "Error: could not send send autoip Event signal.\n");
|
||||
exit (1);
|
||||
}
|
||||
dbus_message_unref (message);
|
||||
|
||||
/* Send out the message */
|
||||
dbus_connection_flush (connection);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
14
callouts/nm-avahi-autoipd.conf
Normal file
14
callouts/nm-avahi-autoipd.conf
Normal file
|
@ -0,0 +1,14 @@
|
|||
<!DOCTYPE busconfig PUBLIC
|
||||
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
|
||||
<busconfig>
|
||||
<policy user="root">
|
||||
<allow own="org.freedesktop.nm_avahi_autoipd"/>
|
||||
<allow send_interface="org.freedesktop.nm_avahi_autoipd"/>
|
||||
</policy>
|
||||
<policy context="default">
|
||||
<deny own="org.freedesktop.nm_avahi_autoipd"/>
|
||||
<deny send_interface="org.freedesktop.nm_avahi_autoipd"/>
|
||||
</policy>
|
||||
</busconfig>
|
||||
|
|
@ -65,8 +65,6 @@ NetworkManager_SOURCES = \
|
|||
nm-gsm-device.h \
|
||||
nm-cdma-device.c \
|
||||
nm-cdma-device.h \
|
||||
autoip.c \
|
||||
autoip.h \
|
||||
wpa.c \
|
||||
wpa.h \
|
||||
nm-netlink.c \
|
||||
|
|
379
src/autoip.c
379
src/autoip.c
|
@ -1,379 +0,0 @@
|
|||
// Based upon http://www.zeroconf.org/AVH-IPv4LL.c
|
||||
// Merged into NetworkManager by Tom Parker <palfrey@tevp.net>
|
||||
// Original copyright continues below
|
||||
//
|
||||
// ----------------------------------
|
||||
// Simple IPv4 Link-Local addressing (see <http://www.zeroconf.org/>)
|
||||
// @(#)llip.c, 1.5, Copyright 2003 by Arthur van Hoff (avh@strangeberry.com)
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
// See <http://www.gnu.org/copyleft/lesser.html>
|
||||
//
|
||||
// This library 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
|
||||
// Lesser General Public License for more details.
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/poll.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/ether.h>
|
||||
#include <linux/sockios.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <syslog.h>
|
||||
#include <glib.h>
|
||||
#include <unistd.h>
|
||||
#include "NetworkManager.h"
|
||||
#include "nm-device.h"
|
||||
#include "nm-device-ethernet.h"
|
||||
#include "nm-device-wifi.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "nm-utils.h"
|
||||
#include "autoip.h"
|
||||
|
||||
// Times here are in seconds
|
||||
#define LINKLOCAL_ADDR 0xa9fe0000
|
||||
#define LINKLOCAL_BCAST 0xa9feffff
|
||||
#define PROBE_NUM 3
|
||||
#define PROBE_MIN 1
|
||||
#define PROBE_MAX 2
|
||||
#define ANNOUNCE_NUM 3
|
||||
#define ANNOUNCE_INTERVAL 2
|
||||
#define ANNOUNCE_WAIT 2
|
||||
|
||||
#define FAILURE_TIMEOUT 14
|
||||
|
||||
|
||||
typedef struct EtherHeader
|
||||
{
|
||||
u_int8_t ether_dhost[ETH_ALEN]; /* destination eth addr */
|
||||
u_int8_t ether_shost[ETH_ALEN]; /* source ether addr */
|
||||
u_int16_t ether_type; /* packet type ID field */
|
||||
} __attribute__((packed)) EtherHeader;
|
||||
|
||||
|
||||
typedef struct ARPMessage
|
||||
{
|
||||
EtherHeader ethhdr;
|
||||
u_short htype; /* hardware type (must be ARPHRD_ETHER) */
|
||||
u_short ptype; /* protocol type (must be ETHERTYPE_IP) */
|
||||
u_char hlen; /* hardware address length (must be 6) */
|
||||
u_char plen; /* protocol address length (must be 4) */
|
||||
u_short operation; /* ARP opcode */
|
||||
u_char sHaddr[ETH_ALEN]; /* sender's hardware address */
|
||||
u_char sInaddr[4]; /* sender's IP address */
|
||||
u_char tHaddr[ETH_ALEN]; /* target's hardware address */
|
||||
u_char tInaddr[4]; /* target's IP address */
|
||||
u_char pad[18]; /* pad for min. Ethernet payload (60 bytes) */
|
||||
} __attribute__((packed)) ARPMessage;
|
||||
|
||||
|
||||
// Times here are in seconds
|
||||
#define ARP_DEFAULT_LEASETIME 100
|
||||
|
||||
static struct in_addr null_ip = {0};
|
||||
static struct ether_addr null_addr = {{0, 0, 0, 0, 0, 0}};
|
||||
static struct ether_addr broadcast_addr = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
|
||||
|
||||
/**
|
||||
* Pick a random link local IP address.
|
||||
*/
|
||||
static void pick (struct in_addr *ip)
|
||||
{
|
||||
ip->s_addr = htonl (LINKLOCAL_ADDR | ((abs(random()) % 0xFD00) + (abs(random()) % 0x0100)));
|
||||
|
||||
/* Make sure we don't use 0xFF or 0x00 anywhere */
|
||||
while (((ip->s_addr & 0x0000FF00) == 0xFF00) || ((ip->s_addr & 0x0000FF00) == 0x0000))
|
||||
ip->s_addr = (ip->s_addr & 0xFFFF00FF) + (abs(random()) && 0xFFFF);
|
||||
|
||||
while (((ip->s_addr & 0x000000FF) == 0xFF) || ((ip->s_addr & 0x000000FF) == 0x00))
|
||||
ip->s_addr = (ip->s_addr & 0xFFFFFF00) + (abs(random()) && 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send out an ARP packet.
|
||||
*/
|
||||
static gboolean arp(int fd, struct sockaddr *saddr, int op,
|
||||
struct ether_addr *source_addr, struct in_addr source_ip,
|
||||
struct ether_addr *target_addr, struct in_addr target_ip)
|
||||
{
|
||||
struct ARPMessage p;
|
||||
gboolean success = FALSE;
|
||||
|
||||
memset (&p, 0, sizeof (p));
|
||||
|
||||
/* ether header */
|
||||
p.ethhdr.ether_type = htons (ETHERTYPE_ARP);
|
||||
memcpy (p.ethhdr.ether_shost, source_addr, ETH_ALEN);
|
||||
memcpy (p.ethhdr.ether_dhost, &broadcast_addr, ETH_ALEN);
|
||||
|
||||
/* arp request */
|
||||
p.htype = htons (ARPHRD_ETHER);
|
||||
p.ptype = htons (ETHERTYPE_IP);
|
||||
p.hlen = ETH_ALEN;
|
||||
p.plen = 4;
|
||||
p.operation = htons (op);
|
||||
memcpy (&p.sHaddr, source_addr, ETH_ALEN);
|
||||
memcpy (&p.sInaddr, &source_ip, sizeof (p.sInaddr));
|
||||
memcpy (&p.tHaddr, target_addr, ETH_ALEN);
|
||||
memcpy (&p.tInaddr, &target_ip, sizeof (p.tInaddr));
|
||||
|
||||
/* send it */
|
||||
if (sendto (fd, &p, sizeof (p), 0, saddr, sizeof (*saddr)) < 0)
|
||||
nm_warning ("autoip ARP sendto() failed.");
|
||||
else
|
||||
success = TRUE;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Subtract the `struct timeval' values X and Y,
|
||||
storing the result in RESULT.
|
||||
Return 1 if the difference is negative, otherwise 0. */
|
||||
static int timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y)
|
||||
{
|
||||
/* Perform the carry for the later subtraction by updating Y. */
|
||||
if (x->tv_usec < y->tv_usec)
|
||||
{
|
||||
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
|
||||
y->tv_usec -= 1000000 * nsec;
|
||||
y->tv_sec += nsec;
|
||||
}
|
||||
if (x->tv_usec - y->tv_usec > 1000000)
|
||||
{
|
||||
int nsec = (x->tv_usec - y->tv_usec) / 1000000;
|
||||
y->tv_usec += 1000000 * nsec;
|
||||
y->tv_sec -= nsec;
|
||||
}
|
||||
|
||||
/* Compute the time remaining to wait.
|
||||
`tv_usec' is certainly positive. */
|
||||
result->tv_sec = x->tv_sec - y->tv_sec;
|
||||
result->tv_usec = x->tv_usec - y->tv_usec;
|
||||
|
||||
/* Return 1 if result is negative. */
|
||||
return x->tv_sec < y->tv_sec;
|
||||
}
|
||||
|
||||
enum return_vals
|
||||
{
|
||||
RET_ERROR = 0,
|
||||
RET_TIMEOUT,
|
||||
RET_CEASED,
|
||||
RET_SUCCESS
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/* "timeout" should be the future point in time when we wish to stop
|
||||
* checking for data on the socket.
|
||||
*/
|
||||
static int peekfd (NMDevice *dev, int sk, struct timeval *timeout)
|
||||
{
|
||||
struct timeval diff;
|
||||
struct timeval now;
|
||||
|
||||
/* Wake up each second to check whether or not we've been told
|
||||
* to stop with iface->cease and check our timeout.
|
||||
*/
|
||||
gettimeofday (&now, NULL);
|
||||
// nm_info ("autoip waiting for data, overall timeout = {%ds, %dus}\n", (int)timeout->tv_sec, (int)timeout->tv_usec);
|
||||
while (timeval_subtract (&diff, timeout, &now) == 0)
|
||||
{
|
||||
fd_set fs;
|
||||
struct timeval wait = {1, 0};
|
||||
// nm_info ("autoip waiting for data, remaining timeout = {%ds, %dus}\n", (int)diff.tv_sec, (int)diff.tv_usec);
|
||||
|
||||
FD_ZERO (&fs);
|
||||
FD_SET (sk, &fs);
|
||||
|
||||
if (select (sk+1, &fs, NULL, NULL, &wait) == -1)
|
||||
return RET_ERROR;
|
||||
if (FD_ISSET(sk, &fs))
|
||||
return RET_SUCCESS;
|
||||
gettimeofday (&now, NULL);
|
||||
};
|
||||
return RET_TIMEOUT;
|
||||
}
|
||||
|
||||
|
||||
gboolean get_autoip (NMDevice *dev, struct in_addr *out_ip)
|
||||
{
|
||||
struct sockaddr saddr;
|
||||
ARPMessage p;
|
||||
struct ether_addr addr;
|
||||
struct in_addr ip = {0};
|
||||
int fd = -1;
|
||||
int nprobes = 0;
|
||||
int nannounce = 0;
|
||||
gboolean success = FALSE;
|
||||
const char *iface;
|
||||
char buf[INET_ADDRSTRLEN+1];
|
||||
|
||||
memset(&buf, '\0', sizeof (buf));
|
||||
|
||||
g_return_val_if_fail (dev != NULL, FALSE);
|
||||
g_return_val_if_fail (out_ip != NULL, FALSE);
|
||||
|
||||
out_ip->s_addr = 0;
|
||||
iface = nm_device_get_iface (dev);
|
||||
|
||||
/* initialize saddr */
|
||||
memset (&saddr, 0, sizeof (saddr));
|
||||
strncpy (saddr.sa_data, iface, sizeof (saddr.sa_data));
|
||||
|
||||
if (NM_IS_DEVICE_ETHERNET (dev))
|
||||
nm_device_ethernet_get_address (NM_DEVICE_ETHERNET (dev), &addr);
|
||||
else if (NM_IS_DEVICE_WIFI (dev))
|
||||
nm_device_wifi_get_address (NM_DEVICE_WIFI (dev), &addr);
|
||||
else
|
||||
goto out;
|
||||
|
||||
/* open an ARP socket */
|
||||
fd = socket (AF_PACKET, SOCK_PACKET, htons (ETH_P_ALL));
|
||||
if (fd < 0) {
|
||||
nm_warning ("%s: Couldn't open network control socket.", iface);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* bind to the ARP socket */
|
||||
if (bind (fd, &saddr, sizeof (saddr)) < 0) {
|
||||
nm_warning ("%s: Couldn't bind to the device.", iface);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* initialize pseudo random selection of IP addresses */
|
||||
srandom ( (addr.ether_addr_octet[ETHER_ADDR_LEN-4] << 24) |
|
||||
(addr.ether_addr_octet[ETHER_ADDR_LEN-3] << 16) |
|
||||
(addr.ether_addr_octet[ETHER_ADDR_LEN-2] << 8) |
|
||||
(addr.ether_addr_octet[ETHER_ADDR_LEN-1] << 0));
|
||||
|
||||
/* pick an ip address */
|
||||
if (ip.s_addr == 0)
|
||||
pick (&ip);
|
||||
|
||||
while (1)
|
||||
{
|
||||
struct timeval timeout;
|
||||
int err;
|
||||
|
||||
if (nprobes < PROBE_NUM)
|
||||
{
|
||||
if (!inet_ntop (AF_INET, &ip, buf, INET_ADDRSTRLEN)) {
|
||||
nm_warning ("%s: error converting IP4 address 0x%X",
|
||||
__func__, ntohl (ip.s_addr));
|
||||
continue;
|
||||
}
|
||||
nm_info ("autoip: Sending probe #%d for IP address %s.", nprobes, buf);
|
||||
arp (fd, &saddr, ARPOP_REQUEST, &addr, null_ip, &null_addr, ip);
|
||||
nprobes++;
|
||||
gettimeofday (&timeout, NULL);
|
||||
if (nprobes == PROBE_NUM)
|
||||
{
|
||||
/* Link local specifies a different interval between
|
||||
* the end of probe requests and announce packets.
|
||||
*/
|
||||
timeout.tv_sec += ANNOUNCE_WAIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int usecs_to_sleep = ((PROBE_MAX - PROBE_MIN) * 1000000) - 1;
|
||||
|
||||
/* We want to sleep between PROBE_MIN and PROBE_MAX seconds, exclusive */
|
||||
timeout.tv_sec += PROBE_MIN;
|
||||
timeout.tv_usec += 1 + (random () % usecs_to_sleep);
|
||||
}
|
||||
}
|
||||
else if (nannounce < ANNOUNCE_NUM)
|
||||
{
|
||||
if (!inet_ntop (AF_INET, &ip, buf, INET_ADDRSTRLEN)) {
|
||||
nm_warning ("%s: error converting IP4 address 0x%X",
|
||||
__func__, ntohl (ip.s_addr));
|
||||
continue;
|
||||
}
|
||||
nm_info ("autoip: Sending announce #%d for IP address %s.", nannounce, buf);
|
||||
arp (fd, &saddr, ARPOP_REQUEST, &addr, ip, &addr, ip);
|
||||
nannounce++;
|
||||
gettimeofday (&timeout, NULL);
|
||||
timeout.tv_sec += ANNOUNCE_INTERVAL;
|
||||
timeout.tv_usec += (random () % 200000);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Use our address! */
|
||||
memcpy (out_ip, &ip, sizeof (ip));
|
||||
success = TRUE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
nm_info ("autoip: Waiting for reply...");
|
||||
err = peekfd (dev, fd, &timeout);
|
||||
if ((err == RET_ERROR) || (err == RET_CEASED))
|
||||
goto out;
|
||||
|
||||
/* There's some data waiting for us */
|
||||
if (err == RET_SUCCESS) {
|
||||
nm_info ("autoip: Got some data to check for reply packet.");
|
||||
|
||||
/* read ARP packet */
|
||||
if (recv (fd, &p, sizeof (p), 0) < 0) {
|
||||
nm_warning ("autoip: packet receive failure, ignoring it.");
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef ARP_DEBUG
|
||||
nm_warning ("autoip: (%s) recv arp type=%d, op=%d, ", iface, ntohs(p.ethhdr.ether_type), ntohs(p.operation));
|
||||
{
|
||||
struct in_addr a;
|
||||
memcpy (&(a.s_addr), &(p.sInaddr), sizeof (a.s_addr));
|
||||
if (!inet_ntop (AF_INET, &a, buf, INET_ADDRSTRLEN)) {
|
||||
nm_warning ("%s: error converting IP4 address 0x%X",
|
||||
__func__, ntohl (a.s_addr));
|
||||
continue;
|
||||
}
|
||||
nm_warning (" source = %s %02X:%02X:%02X:%02X:%02X:%02X, ", buf,
|
||||
p.sHaddr[0], p.sHaddr[1], p.sHaddr[2], p.sHaddr[3], p.sHaddr[4], p.sHaddr[5]);
|
||||
memcpy (&(a.s_addr), &(p.tInaddr), sizeof (a.s_addr));
|
||||
if (!inet_ntop (AF_INET, &a, buf, INET_ADDRSTRLEN)) {
|
||||
nm_warning ("%s: error converting IP4 address 0x%X",
|
||||
__func__, ntohl (a.s_addr));
|
||||
continue;
|
||||
}
|
||||
nm_warning (" target = %s %02X:%02X:%02X:%02X:%02X:%02X\n", buf,
|
||||
p.tHaddr[0], p.tHaddr[1], p.tHaddr[2], p.tHaddr[3], p.tHaddr[4], p.tHaddr[5]);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( (ntohs (p.ethhdr.ether_type) == ETHERTYPE_ARP)
|
||||
&& (ntohs (p.operation) == ARPOP_REPLY)
|
||||
&& ((uint32_t)(*p.tInaddr) == ip.s_addr)
|
||||
&& (memcmp (&addr, &p.tHaddr, ETH_ALEN) != 0))
|
||||
{
|
||||
#ifdef ARP_DEBUG
|
||||
if (!inet_ntop (AF_INET, &ip, buf, INET_ADDRSTRLEN)) {
|
||||
nm_warning ("%s: error converting IP4 address 0x%X",
|
||||
__func__, ntohl (ip.s_addr));
|
||||
continue;
|
||||
}
|
||||
nm_warning ("autoip: (%s) ARP conflict for IP address %s.\n", iface, buf);
|
||||
#endif
|
||||
|
||||
/* Ok, start all over again */
|
||||
pick (&ip);
|
||||
nprobes = 0;
|
||||
nannounce = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (fd >= 0)
|
||||
close (fd);
|
||||
return success;
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
#ifndef _SRC_AUTOIP_H
|
||||
#define _SRC_AUTOIP_H
|
||||
|
||||
#include "nm-device.h"
|
||||
|
||||
extern gboolean get_autoip (NMDevice *dev, struct in_addr *out_ip);
|
||||
|
||||
#endif /* _SRC_AUTOIP_H */
|
|
@ -36,4 +36,8 @@ gboolean nm_device_hw_bring_up (NMDevice *self, gboolean wait);
|
|||
|
||||
void nm_device_hw_take_down (NMDevice *self, gboolean wait);
|
||||
|
||||
void nm_device_handle_autoip4_event (NMDevice *self,
|
||||
const char *event,
|
||||
const char *address);
|
||||
|
||||
#endif /* NM_DEVICE_PRIVATE_H */
|
||||
|
|
359
src/nm-device.c
359
src/nm-device.c
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* NetworkManager -- Network link manager
|
||||
*
|
||||
* Dan Williams <dcbw@redhat.com>
|
||||
|
@ -17,7 +17,7 @@
|
|||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* (C) Copyright 2005 Red Hat, Inc.
|
||||
* (C) Copyright 2005 - 2008 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
|
@ -29,6 +29,10 @@
|
|||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "nm-device-interface.h"
|
||||
#include "nm-device.h"
|
||||
|
@ -40,7 +44,6 @@
|
|||
#include "nm-dbus-manager.h"
|
||||
#include "nm-named-manager.h"
|
||||
#include "nm-utils.h"
|
||||
#include "autoip.h"
|
||||
#include "nm-netlink.h"
|
||||
#include "nm-setting-ip4-config.h"
|
||||
#include "nm-setting-connection.h"
|
||||
|
@ -88,8 +91,15 @@ struct _NMDevicePrivate
|
|||
gulong dhcp_state_sigid;
|
||||
gulong dhcp_timeout_sigid;
|
||||
|
||||
/* dnsmasq stuff for shared connections */
|
||||
NMDnsMasqManager * dnsmasq_manager;
|
||||
gulong dnsmasq_state_id;
|
||||
|
||||
/* avahi-autoipd stuff */
|
||||
GPid aipd_pid;
|
||||
guint aipd_watch;
|
||||
guint aipd_timeout;
|
||||
guint32 aipd_addr;
|
||||
};
|
||||
|
||||
static gboolean check_connection_compatible (NMDeviceInterface *device,
|
||||
|
@ -521,6 +531,271 @@ nm_device_activate_schedule_stage2_device_config (NMDevice *self)
|
|||
nm_device_get_iface (self));
|
||||
}
|
||||
|
||||
static void
|
||||
aipd_timeout_remove (NMDevice *self)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
if (priv->aipd_timeout) {
|
||||
g_source_remove (priv->aipd_timeout);
|
||||
priv->aipd_timeout = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
aipd_cleanup (NMDevice *self)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
if (priv->aipd_pid > 0) {
|
||||
kill (priv->aipd_pid, SIGKILL);
|
||||
priv->aipd_pid = -1;
|
||||
}
|
||||
|
||||
if (priv->aipd_watch) {
|
||||
g_source_remove (priv->aipd_watch);
|
||||
priv->aipd_watch = 0;
|
||||
}
|
||||
|
||||
aipd_timeout_remove (self);
|
||||
|
||||
priv->aipd_addr = 0;
|
||||
}
|
||||
|
||||
static NMIP4Config *
|
||||
aipd_get_ip4_config (NMDevice *self)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMIP4Config *config = NULL;
|
||||
NMSettingIP4Address *addr;
|
||||
|
||||
g_return_val_if_fail (priv->aipd_addr > 0, NULL);
|
||||
|
||||
config = nm_ip4_config_new ();
|
||||
addr = g_malloc0 (sizeof (NMSettingIP4Address));
|
||||
addr->address = (guint32) priv->aipd_addr;
|
||||
addr->prefix = 16;
|
||||
nm_ip4_config_take_address (config, addr);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_autoip_change (NMDevice *self)
|
||||
{
|
||||
NMActRequest *req;
|
||||
NMConnection *connection;
|
||||
NMIP4Config *config;
|
||||
|
||||
config = aipd_get_ip4_config (self);
|
||||
if (!config) {
|
||||
nm_warning ("failed to get autoip config for rebind");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
req = nm_device_get_act_request (self);
|
||||
g_assert (req);
|
||||
connection = nm_act_request_get_connection (req);
|
||||
g_assert (connection);
|
||||
|
||||
g_object_set_data (G_OBJECT (req), NM_ACT_REQUEST_IP4_CONFIG, config);
|
||||
|
||||
if (!nm_device_set_ip4_config (self, config)) {
|
||||
nm_warning ("(%s): failed to update IP4 config in response to autoip event.",
|
||||
nm_device_get_iface (self));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define IPV4LL_NETWORK (htonl (0xA9FE0000L))
|
||||
#define IPV4LL_NETMASK (htonl (0xFFFF0000L))
|
||||
|
||||
void
|
||||
nm_device_handle_autoip4_event (NMDevice *self,
|
||||
const char *event,
|
||||
const char *address)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMActRequest *req;
|
||||
NMConnection *connection = NULL;
|
||||
NMSettingIP4Config *s_ip4 = NULL;
|
||||
NMDeviceState state;
|
||||
const char *iface;
|
||||
|
||||
g_return_if_fail (event != NULL);
|
||||
|
||||
req = nm_device_get_act_request (self);
|
||||
if (!req)
|
||||
return;
|
||||
|
||||
connection = nm_act_request_get_connection (req);
|
||||
if (!connection)
|
||||
return;
|
||||
|
||||
/* Ignore if the connection isn't an AutoIP connection */
|
||||
s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
|
||||
if (!s_ip4 || !s_ip4->method || strcmp (s_ip4->method, NM_SETTING_IP4_CONFIG_METHOD_AUTOIP))
|
||||
return;
|
||||
|
||||
iface = nm_device_get_iface (self);
|
||||
state = nm_device_get_state (self);
|
||||
|
||||
if (strcmp (event, "BIND") == 0) {
|
||||
struct in_addr ip;
|
||||
|
||||
if (inet_pton (AF_INET, address, &ip) <= 0) {
|
||||
nm_warning ("(%s): invalid address %s received from avahi-autoipd.",
|
||||
iface, address);
|
||||
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ip.s_addr & IPV4LL_NETMASK) != IPV4LL_NETWORK) {
|
||||
nm_warning ("(%s): invalid address %s received from avahi-autoipd.",
|
||||
iface, address);
|
||||
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case NM_DEVICE_STATE_IP_CONFIG:
|
||||
if (priv->aipd_addr) {
|
||||
nm_warning ("(%s): already have autoip address!", iface);
|
||||
return;
|
||||
}
|
||||
|
||||
priv->aipd_addr = ip.s_addr;
|
||||
aipd_timeout_remove (self);
|
||||
nm_device_activate_schedule_stage4_ip_config_get (self);
|
||||
break;
|
||||
case NM_DEVICE_STATE_ACTIVATED:
|
||||
priv->aipd_addr = ip.s_addr;
|
||||
if (!handle_autoip_change (self))
|
||||
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED);
|
||||
break;
|
||||
default:
|
||||
nm_warning ("(%s): unexpected avahi-autoip event %s for %s.",
|
||||
iface, event, address);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
nm_warning ("%s: autoip address %s no longer valid because '%s'.",
|
||||
iface, address, event);
|
||||
|
||||
/* The address is gone; terminate the connection or fail activation */
|
||||
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
aipd_watch_cb (GPid pid, gint status, gpointer user_data)
|
||||
{
|
||||
NMDevice *self = NM_DEVICE (user_data);
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMDeviceState state;
|
||||
const char *iface;
|
||||
|
||||
if (!priv->aipd_watch)
|
||||
return;
|
||||
priv->aipd_watch = 0;
|
||||
|
||||
iface = nm_device_get_iface (self);
|
||||
|
||||
if (WIFEXITED (status))
|
||||
nm_warning ("%s: avahi-autoipd exited with error code %d", iface, WEXITSTATUS (status));
|
||||
else if (WIFSTOPPED (status))
|
||||
nm_warning ("%s: avahi-autoipd stopped unexpectedly with signal %d", iface, WSTOPSIG (status));
|
||||
else if (WIFSIGNALED (status))
|
||||
nm_warning ("%s: avahi-autoipd died with signal %d", iface, WTERMSIG (status));
|
||||
else
|
||||
nm_warning ("%s: avahi-autoipd died from an unknown cause", iface);
|
||||
|
||||
aipd_cleanup (self);
|
||||
|
||||
state = nm_device_get_state (self);
|
||||
if (nm_device_is_activating (self) || (state == NM_DEVICE_STATE_ACTIVATED))
|
||||
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
aipd_timeout_cb (gpointer user_data)
|
||||
{
|
||||
NMDevice *self = NM_DEVICE (user_data);
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
if (!priv->aipd_timeout)
|
||||
return FALSE;
|
||||
priv->aipd_timeout = 0;
|
||||
|
||||
nm_info ("%s: avahi-autoipd timed out.", nm_device_get_iface (self));
|
||||
aipd_cleanup (self);
|
||||
|
||||
if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG)
|
||||
nm_device_activate_schedule_stage4_ip_config_timeout (self);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
aipd_child_setup (gpointer user_data G_GNUC_UNUSED)
|
||||
{
|
||||
/* We are in the child process at this point.
|
||||
* Give child it's own program group for signal
|
||||
* separation.
|
||||
*/
|
||||
pid_t pid = getpid ();
|
||||
setpgid (pid, pid);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
aipd_exec (NMDevice *self, GError **error)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
char *argv[5];
|
||||
gboolean success = FALSE;
|
||||
const char **aipd_binary = NULL;
|
||||
static const char *aipd_paths[] = {
|
||||
"/usr/sbin/avahi-autoipd",
|
||||
"/usr/local/sbin/avahi-autoipd",
|
||||
NULL
|
||||
};
|
||||
|
||||
aipd_cleanup (self);
|
||||
|
||||
/* Find avahi-autoipd */
|
||||
aipd_binary = aipd_paths;
|
||||
while (*aipd_binary != NULL) {
|
||||
if (g_file_test (*aipd_binary, G_FILE_TEST_EXISTS))
|
||||
break;
|
||||
aipd_binary++;
|
||||
}
|
||||
|
||||
if (!*aipd_binary) {
|
||||
g_set_error (error, 0, 0, "%s", "couldn't find avahi-autoipd");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
argv[0] = (char *) (*aipd_binary);
|
||||
argv[1] = "--script";
|
||||
argv[2] = LIBEXECDIR "/nm-avahi-autoipd.action";
|
||||
argv[3] = (char *) nm_device_get_iface (self);
|
||||
argv[4] = NULL;
|
||||
|
||||
success = g_spawn_async ("/", argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
|
||||
&aipd_child_setup, NULL, &(priv->aipd_pid), error);
|
||||
if (!success)
|
||||
return FALSE;
|
||||
|
||||
/* Monitor the child process so we know when it dies */
|
||||
priv->aipd_watch = g_child_watch_add (priv->aipd_pid, aipd_watch_cb, self);
|
||||
|
||||
/* Start a timeout to bound the address attempt */
|
||||
priv->aipd_timeout = g_timeout_add (20000, aipd_timeout_cb, self);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static NMActStageReturn
|
||||
real_act_stage3_ip_config_start (NMDevice *self)
|
||||
|
@ -528,6 +803,9 @@ real_act_stage3_ip_config_start (NMDevice *self)
|
|||
NMSettingIP4Config *s_ip4;
|
||||
NMActRequest *req;
|
||||
NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
|
||||
const char *iface;
|
||||
|
||||
iface = nm_device_get_iface (self);
|
||||
|
||||
req = nm_device_get_act_request (self);
|
||||
s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (nm_act_request_get_connection (req),
|
||||
|
@ -544,12 +822,7 @@ real_act_stage3_ip_config_start (NMDevice *self)
|
|||
/* DHCP manager will cancel any transaction already in progress and we do not
|
||||
want to cancel this activation if we get "down" state from that. */
|
||||
g_signal_handler_block (priv->dhcp_manager, priv->dhcp_state_sigid);
|
||||
|
||||
success = nm_dhcp_manager_begin_transaction (priv->dhcp_manager,
|
||||
nm_device_get_iface (self),
|
||||
s_ip4,
|
||||
45);
|
||||
|
||||
success = nm_dhcp_manager_begin_transaction (priv->dhcp_manager, iface, s_ip4, 45);
|
||||
g_signal_handler_unblock (priv->dhcp_manager, priv->dhcp_state_sigid);
|
||||
|
||||
if (success) {
|
||||
|
@ -559,6 +832,21 @@ real_act_stage3_ip_config_start (NMDevice *self)
|
|||
ret = NM_ACT_STAGE_RETURN_POSTPONE;
|
||||
} else
|
||||
ret = NM_ACT_STAGE_RETURN_FAILURE;
|
||||
} else if (s_ip4 && !strcmp (s_ip4->method, NM_SETTING_IP4_CONFIG_METHOD_AUTOIP)) {
|
||||
GError *error = NULL;
|
||||
|
||||
/* Start avahi-autoipd */
|
||||
if (aipd_exec (self, &error)) {
|
||||
nm_info ("Activation (%s) Stage 3 of 5 (IP Configure Start) started"
|
||||
" avahi-autoipd...", iface);
|
||||
ret = NM_ACT_STAGE_RETURN_POSTPONE;
|
||||
} else {
|
||||
nm_info ("Activation (%s) Stage 3 of 5 (IP Configure Start) failed"
|
||||
" to start avahi-autoipd: %s", iface, error->message);
|
||||
g_error_free (error);
|
||||
aipd_cleanup (self);
|
||||
ret = NM_ACT_STAGE_RETURN_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -625,35 +913,6 @@ nm_device_activate_schedule_stage3_ip_config_start (NMDevice *self)
|
|||
nm_device_get_iface (self));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* nm_device_new_ip4_autoip_config
|
||||
*
|
||||
* Build up an IP config with a Link Local address
|
||||
*
|
||||
*/
|
||||
static NMIP4Config *
|
||||
nm_device_new_ip4_autoip_config (NMDevice *self)
|
||||
{
|
||||
struct in_addr ip;
|
||||
NMIP4Config *config = NULL;
|
||||
NMSettingIP4Address *addr;
|
||||
|
||||
g_return_val_if_fail (self != NULL, NULL);
|
||||
|
||||
// FIXME: make our autoip implementation not suck; use avahi-autoip
|
||||
if (!get_autoip (self, &ip))
|
||||
return NULL;
|
||||
|
||||
config = nm_ip4_config_new ();
|
||||
addr = g_malloc0 (sizeof (NMSettingIP4Address));
|
||||
addr->address = (guint32) ip.s_addr;
|
||||
addr->prefix = 16;
|
||||
nm_ip4_config_take_address (config, addr);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
static GHashTable *shared_ips = NULL;
|
||||
|
||||
static void
|
||||
|
@ -735,7 +994,7 @@ real_act_stage4_get_ip4_config (NMDevice *self,
|
|||
g_assert (s_ip4);
|
||||
|
||||
if (!strcmp (s_ip4->method, NM_SETTING_IP4_CONFIG_METHOD_AUTOIP)) {
|
||||
*config = nm_device_new_ip4_autoip_config (self);
|
||||
*config = aipd_get_ip4_config (self);
|
||||
} else if (!strcmp (s_ip4->method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) {
|
||||
*config = nm_ip4_config_new ();
|
||||
if (*config)
|
||||
|
@ -879,7 +1138,7 @@ out:
|
|||
/*
|
||||
* nm_device_activate_schedule_stage4_ip_config_timeout
|
||||
*
|
||||
* Deal with a timed out DHCP transaction
|
||||
* Deal with a timeout of the IP configuration
|
||||
*
|
||||
*/
|
||||
void
|
||||
|
@ -1057,6 +1316,8 @@ nm_device_deactivate_quickly (NMDevice *self)
|
|||
}
|
||||
}
|
||||
|
||||
aipd_cleanup (self);
|
||||
|
||||
/* Tear down an existing activation request */
|
||||
clear_act_request (self);
|
||||
|
||||
|
@ -1343,7 +1604,7 @@ dhcp_timeout (NMDHCPManager *dhcp_manager,
|
|||
return;
|
||||
|
||||
if (nm_device_get_state (device) == NM_DEVICE_STATE_IP_CONFIG)
|
||||
nm_device_activate_schedule_stage4_ip_config_timeout (device);
|
||||
nm_device_activate_schedule_stage4_ip_config_timeout (device);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -1494,7 +1755,7 @@ nm_device_is_up (NMDevice *self)
|
|||
}
|
||||
|
||||
gboolean
|
||||
nm_device_hw_bring_up (NMDevice *self, gboolean wait)
|
||||
nm_device_hw_bring_up (NMDevice *self, gboolean do_wait)
|
||||
{
|
||||
gboolean success;
|
||||
guint32 tries = 0;
|
||||
|
@ -1513,7 +1774,7 @@ nm_device_hw_bring_up (NMDevice *self, gboolean wait)
|
|||
}
|
||||
|
||||
/* Wait for the device to come up if requested */
|
||||
while (wait && !nm_device_hw_is_up (self) && (tries++ < 50))
|
||||
while (do_wait && !nm_device_hw_is_up (self) && (tries++ < 50))
|
||||
g_usleep (200);
|
||||
|
||||
if (!nm_device_hw_is_up (self)) {
|
||||
|
@ -1531,7 +1792,7 @@ out:
|
|||
}
|
||||
|
||||
void
|
||||
nm_device_hw_take_down (NMDevice *self, gboolean wait)
|
||||
nm_device_hw_take_down (NMDevice *self, gboolean do_wait)
|
||||
{
|
||||
guint32 tries = 0;
|
||||
|
||||
|
@ -1546,18 +1807,18 @@ nm_device_hw_take_down (NMDevice *self, gboolean wait)
|
|||
NM_DEVICE_GET_CLASS (self)->hw_take_down (self);
|
||||
|
||||
/* Wait for the device to come up if requested */
|
||||
while (wait && nm_device_hw_is_up (self) && (tries++ < 50))
|
||||
while (do_wait && nm_device_hw_is_up (self) && (tries++ < 50))
|
||||
g_usleep (200);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
nm_device_bring_up (NMDevice *self, gboolean wait)
|
||||
nm_device_bring_up (NMDevice *self, gboolean do_wait)
|
||||
{
|
||||
gboolean success;
|
||||
|
||||
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
||||
|
||||
if (!nm_device_hw_bring_up (self, wait))
|
||||
if (!nm_device_hw_bring_up (self, do_wait))
|
||||
return FALSE;
|
||||
|
||||
if (nm_device_is_up (self))
|
||||
|
@ -1575,7 +1836,7 @@ nm_device_bring_up (NMDevice *self, gboolean wait)
|
|||
}
|
||||
|
||||
void
|
||||
nm_device_take_down (NMDevice *self, gboolean wait)
|
||||
nm_device_take_down (NMDevice *self, gboolean do_wait)
|
||||
{
|
||||
g_return_if_fail (NM_IS_DEVICE (self));
|
||||
|
||||
|
@ -1589,7 +1850,7 @@ nm_device_take_down (NMDevice *self, gboolean wait)
|
|||
NM_DEVICE_GET_CLASS (self)->take_down (self);
|
||||
}
|
||||
|
||||
nm_device_hw_take_down (self, wait);
|
||||
nm_device_hw_take_down (self, do_wait);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
#include "nm-dbus-glib-types.h"
|
||||
#include "nm-hal-manager.h"
|
||||
|
||||
#define NM_AUTOIP_DBUS_SERVICE "org.freedesktop.nm_avahi_autoipd"
|
||||
#define NM_AUTOIP_DBUS_IFACE "org.freedesktop.nm_avahi_autoipd"
|
||||
|
||||
static gboolean impl_manager_get_devices (NMManager *manager, GPtrArray **devices, GError **err);
|
||||
static void impl_manager_activate_connection (NMManager *manager,
|
||||
const char *service_name,
|
||||
|
@ -108,6 +111,8 @@ typedef struct {
|
|||
NMVPNManager *vpn_manager;
|
||||
guint vpn_manager_id;
|
||||
|
||||
DBusGProxy *aipd_proxy;
|
||||
|
||||
gboolean disposed;
|
||||
} NMManagerPrivate;
|
||||
|
||||
|
@ -210,10 +215,50 @@ vpn_manager_connection_deactivated_cb (NMVPNManager *manager,
|
|||
g_object_notify (G_OBJECT (user_data), NM_MANAGER_ACTIVE_CONNECTIONS);
|
||||
}
|
||||
|
||||
static void
|
||||
aipd_handle_event (DBusGProxy *proxy,
|
||||
const char *event,
|
||||
const char *iface,
|
||||
const char *address,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMManager *manager = NM_MANAGER (user_data);
|
||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
|
||||
GSList *iter;
|
||||
gboolean handled;
|
||||
|
||||
if (!event || !iface) {
|
||||
nm_warning ("Incomplete message received from avahi-autoipd");
|
||||
return;
|
||||
}
|
||||
|
||||
if ( (strcmp (event, "BIND") != 0)
|
||||
&& (strcmp (event, "CONFLICT") != 0)
|
||||
&& (strcmp (event, "UNBIND") != 0)
|
||||
&& (strcmp (event, "STOP") != 0)) {
|
||||
nm_warning ("Unknown event '%s' received from avahi-autoipd", event);
|
||||
return;
|
||||
}
|
||||
|
||||
for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
|
||||
NMDevice *candidate = NM_DEVICE (iter->data);
|
||||
|
||||
if (!strcmp (nm_device_get_iface (candidate), iface)) {
|
||||
nm_device_handle_autoip4_event (candidate, event, address);
|
||||
handled = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!handled)
|
||||
nm_warning ("Unhandled avahi-autoipd event for '%s'", iface);
|
||||
}
|
||||
|
||||
static void
|
||||
nm_manager_init (NMManager *manager)
|
||||
{
|
||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
|
||||
DBusGConnection *g_connection;
|
||||
guint id;
|
||||
|
||||
priv->wireless_enabled = TRUE;
|
||||
|
@ -237,6 +282,29 @@ nm_manager_init (NMManager *manager)
|
|||
id = g_signal_connect (G_OBJECT (priv->vpn_manager), "connection-deactivated",
|
||||
G_CALLBACK (vpn_manager_connection_deactivated_cb), manager);
|
||||
priv->vpn_manager_id = id;
|
||||
|
||||
g_connection = nm_dbus_manager_get_connection (priv->dbus_mgr);
|
||||
priv->aipd_proxy = dbus_g_proxy_new_for_name (g_connection,
|
||||
NM_AUTOIP_DBUS_SERVICE,
|
||||
"/",
|
||||
NM_AUTOIP_DBUS_IFACE);
|
||||
if (priv->aipd_proxy) {
|
||||
dbus_g_object_register_marshaller (nm_marshal_VOID__STRING_STRING_STRING,
|
||||
G_TYPE_NONE,
|
||||
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
|
||||
G_TYPE_INVALID);
|
||||
|
||||
dbus_g_proxy_add_signal (priv->aipd_proxy,
|
||||
"Event",
|
||||
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
|
||||
G_TYPE_INVALID);
|
||||
|
||||
dbus_g_proxy_connect_signal (priv->aipd_proxy, "Event",
|
||||
G_CALLBACK (aipd_handle_event),
|
||||
manager,
|
||||
NULL);
|
||||
} else
|
||||
nm_warning ("Could not initialize avahi-autoipd D-Bus proxy");
|
||||
}
|
||||
|
||||
NMState
|
||||
|
|
Loading…
Reference in a new issue