On Ubuntu 20.10, we build against ModemManager 1.14.0 and get a compiler warning:
../src/devices/wwan/nm-modem-broadband.c: In function 'try_create_connect_properties':
../src/devices/wwan/nm-modem-broadband.c:492:2: error: 'MMModemCapabilityDeprecated' is deprecated [-Werror=deprecated-declarations]
492 | if (MODEM_CAPS_3GPP (ctx->caps)) {
| ^~
Suppress it.
An alternative would be to drop the flag entirely. It seems the flag
was never used (and never will be used). But if that's true, there is
little harm done checking it. If it's not true, we better keep checking
for older versions.
0cd76bf1c4
Add nm_utils_invoke_on_timeout() beside nm_utils_invoke_on_idle().
They are fundamentally similar, except one schedules an idle handler
and the other a timeout.
Also, use the current g_main_context_get_thread_default() as context
instead of the singleton instance. That is a change in behavior, but
the only caller of nm_utils_invoke_on_idle() is the daemon, which
doesn't use different main contexts. Anyway, to avoid anybody being
tripped up by this also change the order of arguments. It anyway
seems nicer to first pass the cancellable, and the callback and user
data as last arguments. It's more in line with glib's asynchronous
methods.
Also, in the unlikely case that the cancellable is already cancelled
from the start, always schedule an idle action to complete fast.
(cherry picked from commit cd5157a0c3)
When starting with a locked modem, it may take some time for the user to
enter the PIN code, leading to the secrets request timing out. In that
case, we want the connection activation to be retried automatically once
the modem is unlocked, which can't be achieved if we propagate the error,
as the device will change state to 'failed'.
This patch ignores the 'no-secrets' error, as it means either the
request has timed out, or the user cancelled the request without
notifying NetworkManager. By doing this, we allow the connection to be
re-activated once the modem is unlocked.
Signed-off-by: Arnaud Ferraris <arnaud.ferraris@collabora.com>
When the modem is unlocked externally to NetworkManager, it is kept in
the 'need-auth' state. The current connection activation continues as
if nothing had changed, and the secrets request for the PIN code (which
is no longer necessary) eventually times out. The device state is then
changed to 'failed', meaning there won't be a new try at activating the
default connection automatically.
In order to prevent this, and retry activating the default connection
when the modem gets unlocked, we change the device state to
'deactivating' when we identify the modem has been unlocked externally.
Signed-off-by: Arnaud Ferraris <arnaud.ferraris@collabora.com>
g_clear_pointer() would always cast the destroy notify function
pointer to GDestroyNotify. That means, it lost some type safety, like
GPtrArray *ptr_arr = ...
g_clear_pointer (&ptr_arr, g_array_unref);
Since glib 2.58 ([1]), g_clear_pointer() is also more type safe. But
this is not used by NetworkManager, because we don't set
GLIB_VERSION_MIN_REQUIRED to 2.58.
[1] f9a9902aac
We have nm_clear_pointer() to avoid this issue for a long time (pre
1.12.0). Possibly we should redefine in our source tree g_clear_pointer()
as nm_clear_pointer(). However, I don't like to patch glib functions
with our own variant. Arguably, we do patch g_clear_error() in
such a manner. But there the point is to make the function inlinable.
Also, nm_clear_pointer() returns a boolean that indicates whether
anything was cleared. That is sometimes useful. I think we should
just consistently use nm_clear_pointer() instead, which does always
the preferable thing.
Replace:
sed 's/\<g_clear_pointer *(\([^;]*\), *\([a-z_A-Z0-9]\+\) *)/nm_clear_pointer (\1, \2)/g' $(git grep -l g_clear_pointer) -i
I think it's preferable to use nm_clear_g_free() instead of
g_clear_pointer(, g_free). The reasons are not very strong,
but I think it is overall preferable to have a shorthand for this
frequently used functionality.
sed 's/\<g_clear_pointer *(\([^;]*\), *\(g_free\) *)/nm_clear_g_free (\1)/g' $(git grep -l g_clear_pointer) -i
There was only API to schedule the stage on an idle handler.
Sometimes, we are just in the right situation to schedule the stage
right away. It should be possibly to avoid going through the extra hop.
For now, none of the caller makes use of this. So, there isn't any
actual change in behavior. But by adding this possibility, we may do
use in the future.
This is C, we have almost no IDE support. And ctags/cscope is much more
helpful if we use unique names.
Don't use the get_dhcp_timeout() name, because that is already used in
"src/devices/nm-device.c" already. Rename.
The _GET_PRIVATE() macros are all implemented based on
_NM_GET_PRIVATE(). That macro tries to be more type safe and uses
_Generic() to do the right thing. Explicitly casting is not only
unnecessary, it defeats these (static) type checks.
Don't do that.
Don't proceed if the context was torn down on an error in
try_create_connect_properties().
<info> [1574092292.0225] manager: NetworkManager state is now CONNECTING
<warn> [1574092292.0228] modem-broadband[ttyV0]: failed to connect 'ttyV0': unable to determine the network id
<info> [1574092292.0230] device (ttyV0): state change: prepare -> failed (reason 'modem-init-failed', sys-iface-state: 'managed')
<info> [1574092292.0236] manager: NetworkManager state is now DISCONNECTED
<warn> [1574092292.0250] device (ttyV0): Activation: failed for connection 'ttyV0'
(NetworkManager:69212): libnm-CRITICAL **: 16:51:32.025: ((libnm-core/nm-connection.c:193)): assertion '<dropped>' failed
Thread 1 "NetworkManager" received signal SIGTRAP, Trace/breakpoint trap.
0x00007ffff78da6e5 in _g_log_abort () from /lib64/libglib-2.0.so.0
(gdb) bt
#0 0x00007ffff78da6e5 in _g_log_abort () at /lib64/libglib-2.0.so.0
#1 0x00007ffff78db9b6 in g_logv () at /lib64/libglib-2.0.so.0
#2 0x00007ffff78dbb83 in g_log () at /lib64/libglib-2.0.so.0
#3 0x000055555563fcd2 in _nm_g_return_if_fail_warning (line=line@entry=193, file=0x5555557ae221 "libnm-core/nm-connection.c", log_domain=0x5555557ae23c "libnm") at ./shared/nm-default.h:219
#4 0x000055555563feba in _connection_get_setting_checkPython Exception <class 'gdb.error'> No type named TypeNode.:
(connection=0x0, setting_type=) at libnm-core/nm-connection.c:193
#5 _connection_get_setting_checkPython Exception <class 'gdb.error'> No type named TypeNode.:
(connection=0x0, setting_type=) at libnm-core/nm-connection.c:191
#6 0x00007fffe871f8b4 in nm_modem_get_connection_ip_type (self=self@entry=0x7fffd801c730, connection=0x0, error=error@entry=0x7fffffffc8e8) at src/devices/wwan/nm-modem.c:374
#7 0x00007fffe871bfed in connect_context_step (self=0x7fffd801c730) at src/devices/wwan/nm-modem-broadband.c:591
#8 0x00007fffe871c74b in modem_act_stage1_prepare (_self=0x7fffd801c730, connection=0x555555af5520, out_failure_reason=<optimized out>) at src/devices/wwan/nm-modem-broadband.c:687
#9 0x00007fffe8720203 in nm_modem_act_stage1_prepare (self=0x7fffd801c730, req=0x555555b08a30, out_failure_reason=0x7fffffffcbe0) at src/devices/wwan/nm-modem.c:1045
#10 0x0000555555705f1b in activate_stage1_device_prepare (self=0x555555a956a0) at src/devices/nm-device.c:6562
#11 0x00005555556dcbca in activation_source_handle_cb (self=0x555555a956a0, addr_family=2) at src/devices/nm-device.c:6177
#12 0x00007ffff78d0dcb in g_idle_dispatch () at /lib64/libglib-2.0.so.0
#13 0x00007ffff78d44a0 in g_main_context_dispatch () at /lib64/libglib-2.0.so.0
#14 0x00007ffff78d4830 in g_main_context_iterate.isra () at /lib64/libglib-2.0.so.0
#15 0x00007ffff78d4b23 in g_main_loop_run () at /lib64/libglib-2.0.so.0
#16 0x0000555555599ff4 in main (argc=<optimized out>, argv=<optimized out>) at src/main.c:451
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/338/
(cherry picked from commit 9ba55ea6a6)
We try to set only one time the MTU from the connection to not
interfere with manual user changes.
If at some point the parent interface changes temporarily MTU to a
lower value (for example, because the connection was reactivated), the
kernel will also lower the MTU on child interface and we will not
update it ever again.
Add a workaround to this. If we detect that the MTU we want to set
from connection is higher that the allowed one, go into a state where
we follow the parent MTU until it is possible to set again the desired
MTU. This is a bit ugly, but I can't think of any nicer way to do it.
https://bugzilla.redhat.com/show_bug.cgi?id=1751079
The devices tests' meson build files include only the build of a
single executable file and its execution as a test unit.
This has been moved to the devices' main meson build files so this
files can be removed.
The test unit name string is used in different place so it has been
replaced by a variable.
The `nm-service-providers.c` source file is appended by using a
`files` generated object.
The linker flags used when building `libnm_wwan` target uses an
array even when it only uses one value.
When using only one value the array is unnecessary so it has been
removed.
The targets that involve the use of the `NetworkManager` library,
built in the `src` build file have been improved by applying a set
of changes:
- Indentation has been fixed.
- Set of objects used in targets have been grouped together.
- Aritificial dependencies used to group dependencies and custom
compiler flags have been removed and their use replaced with
proper dependencies and compiler flags to avoid any confussion.
The `libnm-core` build file has been improved by applying a set of
changes:
- Indentation has been fixed to be consistent.
- Library variable names have been changed to `lib{name}` pattern
following their filename pattern.
- `shared` prefix has been removed from all variables using it.
- Dependencies have been reviewed to store the necessary data.
- The use of the libraries and dependencies created in this file
has been reviewed through the entire source code. This has
required the addition or the removal of different libraries and
dependencies in different targets.
- Some files used directly with the `files` function have been moved
to their nearest path build file because meson stores their full
path seamessly and they can be used anywhere later.
The `nm-default.h` header is used widely in the code by many
targets. This header includes different headers and needs different
libraries depending the compilation flags.
A new set of `*nm_default_dep` dependencies have been created to
ease the inclusion of different directorires and libraries.
This allows cleaner build files and avoiding linking unnecessary
libraries so this has been applied allowing the removal of some
dependencies involving the linking of unnecessary libraries.
This is a complete refactoring of the bluetooth code.
Now that BlueZ 4 support was dropped, the separation of NMBluezManager
and NMBluez5Manager makes no sense. They should be merged.
At that point, notice that BlueZ 5's D-Bus API is fully centered around
D-Bus's ObjectManager interface. Using that interface, we basically only
call GetManagedObjects() once and register to InterfacesAdded,
InterfacesRemoved and PropertiesChanged signals. There is no need to
fetch individual properties ever.
Note how NMBluezDevice used to query the D-Bus properties itself by
creating a GDBusProxy. This is redundant, because when using the ObjectManager
interfaces, we have all information already.
Instead, let NMBluezManager basically become the client-side cache of
all of BlueZ's ObjectManager interface. NMBluezDevice was mostly concerned
about caching the D-Bus interface's state, tracking suitable profiles
(pan_connection), and moderate between bluez and NMDeviceBt.
These tasks don't get simpler by moving them to a seprate file. Let them
also be handled by NMBluezManager.
I mean, just look how it was previously: NMBluez5Manager registers to
ObjectManager interface and sees a device appearing. It creates a
NMBluezDevice object and registers to its "initialized" and
"notify:usable" signal. In the meantime, NMBluezDevice fetches the
relevant information from D-Bus (although it was already present in the
data provided by the ObjectManager) and eventually emits these usable
and initialized signals.
Then, NMBlue5Manager emits a "bdaddr-added" signal, for which NMBluezManager
creates the NMDeviceBt instance. NMBluezManager, NMBluez5Manager and
NMBluezDevice are strongly cooperating to the point that it is simpler
to merge them.
This is not mere refactoring. This patch aims to make everything
asynchronously and always cancellable. Also, it aims to fix races
and inconsistencies of the state.
- Registering to a NAP server now waits for the response and delays
activation of the NMDeviceBridge accordingly.
- For NAP connections we now watch the bnep0 interface in platform, and tear
down the device when it goes away. Bluez doesn't send us a notification
on D-Bus in that case.
- Rework establishing a DUN connection. It no longer uses blocking
connect() and does not block until rfcomm device appears. It's
all async now. It also watches the rfcomm file descriptor for
POLLERR/POLLHUP to notice disconnect.
- drop nm_device_factory_emit_component_added() and instead let
NMDeviceBt directly register to the WWan factory's "added" signal.
The previous function arguments of nm_modem_act_stage2_config() act as if the
function could fail or even postpone the action. It never did.
We cannot treat this generic. A caller needs to know whether nm_modem_act_stage2_config()
can postpone the action, and when it does, which signal is emitted upon completion. That
is, the caller needs to know how to proceed after postponing.
In other words, since this function currently cannot fail or postpone
the stage, so must all callers already rely on that. At this point it makes
no sense to pretend that the function could be any different, if all callers
assume it is not. Simplify the API.
Currently, we cannot ask which modems exist. NMDeviceBt may claim it
via nm_device_factory_emit_component_added(), and NMWWanFactory may
take it by listening to NM_MODEM_MANAGER_MODEM_ADDED. But that's it.
We will drop nm_device_factory_emit_component_added() because it's only
used for passing modems to NMDeviceBt. Instead, NMDeviceBt can directly
subscribe to NM_MODEM_MANAGER_MODEM_ADDED. It already has a reference
to NMModemManager.
Anyway, the NM_MODEM_MANAGER_MODEM_ADDED signal is no enough, because
sometimes when the mode appears, NMDeviceBt might not yet know whether
it should take it (because the DUN connect call is not yet complete).
Currently that never happens because dun_connect() blocks waiting for
the device. That must be fixed, by not waiting. But this opens up a
race, and NMDeviceBt might after NM_MODEM_MANAGER_MODEM_ADDED need to
search for the suitable modem: by iterating the list of all modems.
NMModem-s are either used by NMDeviceModem or by NMDeviceBt.
The mechanism how that is coordinated it odd:
- the factory emits component-added, and then NMDeviceBt
might take the device (and claim it). In that case, component-added
would return TRUE to indicate that the modem should not be also
used by NMDeviceModem.
- next, if the modem has a driver that looks like bluetooth, NMDeviceModem
ignores it too.
- finally, NMDeviceModem claims the modem (which is now considered to
be non-bluetooth).
I think the first problem is that the device factory tries to have this
generic mechanism of "component-added". It's literally only used to
cover this special case. Note that NMDeviceBt is aware of modems. So,
abstracting this just adds lots of code that could be solved better
by handling the case (of giving the modem to either NMDeviceBt or
NMDeviceModem) specifically.
NMWWanFactory itself registers to the NM_MODEM_MANAGER_MODEM_ADDED
signal and emits nm_device_factory_emit_component_added().
We could just have NMWWanFactory and NMDeviceBt both register to
that signal. Signals even support priorities, so we could have
NMDeviceBt be called first to claim the device.
Anyway, as the modem can only have one owner, the modem should have
a flag that indicates whether it's claimed or not. That will allow
multiple components all look at the same modem and moderate who is
going to take ownership.
This adds capability to hand over the network configuration from
OpenFirmware (and potentially other boot loaders with openfirmware
support such as U-Boot) to NetworkManager.
It's done analogously to ACPI/iBFT. In fact, the same ip=ibft command
line option is used, adding a more general ip=fw alias. This probably
deserves some documentation, but I'm not adding any at this time.
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/257
I am about to change the when stage1 gets postponed, then the way to
proceed it is to schedule stage1 again (instead of scheduling stage2).
The reason is that stage1 handling should be reentrant and we should
keep entering it until there is no more reason to postpone it. If
a subclass postpones stage1 and then later progresses it by directly
scheduling stage2, then only the subclass is in control over postponing
stage 2.
Instead, anybody should be able to delay stage2 independently. That can
only work if everybody signals readyness to proceed by scheduling stage1
again.
NMDevice's act_stage1_prepare() now does nothing. Calling it is not
useful and has no effect.
In general, when a subclass overwrites a virtual function, it must be
defined whether the subclass must, may or must-not call the parents
implementation. Likewise, it must be clear when the parents
implementation should be chained: first, as last, does it matter?
In any case, that very much depends on how the parent is implemented
and this can only be solved by documentation and common conventions.
It's a forgiving approach to have a parents implementation do nothing,
then the subclass may call it at any time (or not call it at all).
This is especially useful if classes don't know their parent class well.
But in NetworkManager code the relationship between classes are known
at compile time, so every of these classes knows it derives directly
from NMDevice.
This forgingin approach was what NMDevice's act_stage1_prepare() was doing.
However, it also adds lines of code resulting in a different kind of complexity.
So, it's not clear that this forgiving approach is really better. Note
that it also has a (tiny) runtime and code-size overhead.
Change the expectation of how NMDevice's act_stage1_prepare() should be
called: it is no longer implemented, and subclasses *MUST* not chain up.
NM_DEVICE_MODEM_GET_PRIVATE() is based on _NM_GET_PRIVATE(), which has
some smarts to check the pointer type, but is fine with well-known parent
pointer types like "NMDevice *".
Changing "ipv4.route-table" and "ipv6.route-table" was not allowed
during reapply.
The main difficulty for supporting that is changing the sync-mode.
With route-table 0, we don't sync all tables but only the main table.
So, when reapply changes from full-sync to no-full-sync, it's slightly
more complicated.
But it's probably not too complicated either. The change from
no-full-sync to full-sync is simple: we just start doing a full-sync.
The reverse change is slightly more complicated, because we need to
do one last full-sync, to get rid of routes that we configured on those
other tables.
We no longer add these. If you use Emacs, configure it yourself.
Also, due to our "smart-tab" usage the editor anyway does a subpar
job handling our tabs. However, on the upside every user can choose
whatever tab-width he/she prefers. If "smart-tabs" are used properly
(like we do), every tab-width will work.
No manual changes, just ran commands:
F=($(git grep -l -e '-\*-'))
sed '1 { /\/\* *-\*- *[mM]ode.*\*\/$/d }' -i "${F[@]}"
sed '1,4 { /^\(#\|--\|dnl\) *-\*- [mM]ode/d }' -i "${F[@]}"
Check remaining lines with:
git grep -e '-\*-'
The ultimate purpose of this is to cleanup our files and eventually use
SPDX license identifiers. For that, first get rid of the boilerplate lines.
NM_MODEM_OPERATOR_CODE property is construct-only. Add our common
code comment to the property setter.
Construct-only setters are pretty simple. They run before the object is
constructed, hence their scope is clearer. As such, there is no need to
emit property changed notifications (also because that is already taken
care by the GObject property setter). Don't call _nm_modem_set_operator_code(),
just directly set the property.
Usually we aim to have only one place where we set state (_nm_modem_set_operator_code()).
But a construct-only property setter is trivial enough that we can affort having two
places to modify the property. In particular, because the property setter does not "modify"
the property, it merely initializes it before the object is fully
constructed.