Although having different parts of NM in different subdirectories
keeps the source tree neat, it has made the build messy, particularly
because of cross-dependencies between the subdirs.
Reorganize to build all of the pieces of the NetworkManager binary
from src/Makefile, and only use recursive make for test programs,
helper binaries, and plugins.
As part of this, get rid of all the per-directory convenience
libraries, and switch to building a single top-level
libNetworkManager.la, containing everything except main.c, which all
of the test programs can then link against.
The private reference to the NMDBusManager is created at
NMModemManager init time, and should only be cleared when the
NMModemManager is disposed. Instead it was getting cleared
whenever ModemManager1 was seen on the bus, and thus was unavailable
later when it was required to watch for the old ModemManager.
This caused NetworkManager to print warnings about NULL object
access to the console, and could prevent it from noticing when
ModemManager appeared on the system bus.
We will very likely get the result of the connection attempt before the 2 mins,
either successful or error, but still we need to explicitly ask to keep the
DBus call open enough time.
This time should be enough to handle both the connection time (usually around
60s max), plus the time needed to register in the network and all the other
Simple.Connect() steps.
MM won't always be present, and if it's not, your logs will fill up
with warnings about MM not being able to be launched. And when
running with systemd, you'll get a different class of errors like:
<warn> error poking ModemManager: GDBus.Error:org.freedesktop.systemd1.LoadFailed:
Unit dbus-org.freedesktop.ModemManager1.service failed to load: No such file or
directory. See system logs and 'systemctl status
dbus-org.freedesktop.ModemManager1.service' for details.
and I'm tired of chasing and special-casing all the launch-failed
errors that D-Bus and systemd use.
Plus, we have dynamic log level changing via the D-Bus interface so if
people need to debug this, just chaning the log level will tell you
what's wrong.
As with the other connection-matching methods, move the loop and the
device-independent bits into NMDevice. By reusing
nm_device_check_connection_compatible(), this means that most device
types now no longer need any type-specific code for this.
https://bugzilla.gnome.org/show_bug.cgi?id=693684
Avoid warnings about GValueArray being deprecated by adding macros
that wrap G_GNUC_BEGIN_IGNORE_DEPRECATIONS /
G_GNUC_END_IGNORE_DEPRECATIONS around the GValueArray calls.
data_iface is the serial port over which PPP should be run, so
we need to preserve that and not overwrite it with the PPP interface
name. When reconnecting, pppd wants the TTY to run PPP over (eg the
ModemManager data_port like ttyUSB0) but if we overwrote that with
ppp0 on the last connection, that's extremely unhelpful and pppd will
fail to start.
The 'GDBusObjectManagerClient' won't signal added or removed objects when it
was created but no name owner was available in the bus. We can still use it for
name-owner changes, but in order to have added/removed object signals, we'll
need to re-create the whole 'MMManager' when we know the service came alive in
the bus.
See GLib/GIO/GDBus bug:
https://bugzilla.gnome.org/show_bug.cgi?id=693285
We avoid requesting to auto-start the service when the 'MMManager' is created,
so that we can use it to follow name-owner changes (when auto-starting
requested the 'MMManager' creation may fail).
We still handle the periodic poking to the service, but instead of re-creating
the 'MMManager', we just call org.freedesktop.DBus.Peer.Ping().
Instead of a 'modem#' identifier, use the primary port of the modem as unique
identifier. The modem UID will be set afterwards as the Device Iface, which is
then used by libnm-glib to gather vendor/product string from the udev device
associated with the Device Iface; so it really needs to be a real port.
Trying to ARP with no other machines in the broadcast domain
is pretty pointless, and in many cases doesn't work (ZTE MF691
/T-Mobile Rocket 2), so turn it off.
The only case where this was being used was in PPP-based connections, as the
ppp0 interface was reported by pppd once the IP setup was done. Instead, just
update the 'NM_MODEM_DATA_PORT' property, as the NMDevices already listen for
changes in that property.
G_TYPE_INSTANCE_GET_PRIVATE() is known to be slow, so just call it once when
the private data is created, and keep a 'priv' pointer around for easy access.
The new `MMManager' object takes care of notifying modems added or removed from
the ModemManager1 interface.
We will listen to both the old and new ModemManager implementations, but as soon
as the first ModemManager implementation is found, the other one gets cleared,
so that we don't wait forever to appear.
The new ModemManager comes with its own headers, and defines its own symbols to
name e.g. each interface. In order not to collide with the new ones, rename the
existing ones with a 'MM_OLD_DBUS' prefix instead of just 'MM_DBUS'.
The logic behind the `iface' property (which actually is removed) gets split
into three new properties, as follows::
* `uid': Just defines a new string property which must contain a unique ID of
the modem, mainly for logging.
* `control-port': a string property defining which is the control port the
modem uses. This property is actually optional and may be specified as NULL.
The main purpose of this property is to allow the easy integration of the
new ModemManager into the `NMDeviceBt' object. The bluetooth device needs
to know the port used by the modem; and we cannot use the Data port
information as that is only available until the bearer is created. Instead,
for the new ModemManager we will use the control port information exposed.
* `data-port': a string property defining which is the data port to use in the
connection. This property is always defined in the `NMModemGsm' and
`NMModemCdma' objects.
We don't want to depend in the `NMModem' interface on an enumeration which is
very specific to the old ModemManager interface, so we'll just skip exposing it
and instead we'll just give a new boolean property which tells whether the modem
is connected or not (which was at the end the whole purpose of the `state'
property).
This property is not really used anywhere; so pointless to have it around.
Also, we already make sure in `NMModemManager' that the so called 'master'
device is valid and exists.
The `NMModem' object is split into two objects now:
* The new `NMModemGeneric' object contains all the implementation specific to
the old ModemManager interface.
* The `NMModem' object keeps all the generic stuff; e.g. it doesn't even depend
on dbus-glib for anything. Several properties in `NMModem' are also now set
as non-construct-only, as we know that the new ModemManager only knows some
of the stuff once a bearer has been created, not once a modem is available.
See src/modem-manager/README for more information.
The idea was copied from gtk, but it's only used there in cases where
the method's wrapper function and default implementation would
otherwise have the same name, which never happens in NM because our
method implementations aren't prefixed with the type name, so it's
just noise here.
The MM API defines the GetIP4Config method return as (uuuu) which
is [ IP, DNS1, DNS2, DNS3 ]. Unfortunately the for() loop in the
static_stage3_done() function started at index 0, which is the IP
address. This caused the IP address to be added to the DNS list.
It should start at index 1 instead.
This worked fine with PPP because PPP terminates, and NM watches
for that and handles it fine. But modems with pseudo-ethernet ports
don't have anything like that, so we have to watch the modem's state
property instead. This works only with MM 0.5.4 and later (including
0.6).
WiMAX failed distcheck if the iwmxsdk devel files were installed but
--enable-wimax=no was used, since the distcheck configure bits found
the iwmxsdk headers, defaulted WiMAX support to 'on', and then proceeded
to use the generated headers from the top srcdir, where of course
wimax was turned off (due to --enable-wimax=no). Instead, everything
should use the headers from the builddir, which reflects the options
that 'make distcheck' actually selects.
At the same time, re-order various includes everywhere to ensure that
the builddir paths come before the srcdir paths to prevent this from
happening in the future.
The disconnect request gets sent just as a precaution, but usually when
the device fails the modem is already gone from ModemManager and the
Disconnect() method will fail. Just don't log the failure.
Kernel ifindexes are always greater than zero (see dev_new_index()
in net/core/dev.c). Also don't bother warning about ifindex
lookup failures for devices we know aren't kernel network interfaces.
Like IPv4, if the connection contains no IPv6 setting, perform
IPv6 addressing. Since may-fail defaults to TRUE for IPv6, failure
should have no consequence.
When using the either DHCP or STATIC IpMethods the modem manager
or device itself negotiates the PPP session so we need to pass
the authentication preferences through to MM.
Notes:
1/ Using a bitfield now that happens to match the Ericsson
in the lower orders so that it's far more tidy.
2/ Devices that wish to utilise this should observe the
following:
If the bitfield doesn't exist in the dict, then MM uses the
modem default, if it does, MM tries to fulfill the request. If the
modem can only accept one value (Qualcomm-type devices accept only
None, PAP or CHAP with AT$QCPDPP) then MM picks the appropriate one
from the dict if only one of PAP or CHAP was given, otherwise we
default to PAP.
(dcbw: make enum a bitfield instead of the bit position)
When NM was registering all of its enum types by hand, it was using
NamesLikeThis rather than the default names-like-this for the "nick"
values. When we switched to using glib-mkenums, this resulted in
dbus-glib using different strings for the D-Bus error names, causing
compatibility problems.
Fix this by using glib-mkenums annotations to manually fix all the
enum values back to what they were before. (This can't be done in a
more automated way, because the old names aren't 100% consistent. Eg,
"UNKNOWN" frequently becomes "UnknownError" rather than just
"Unknown".)