If a firmware update is fetched from a server, and no port number is set
in the URI (e.g. coap://example.com/fw_update), the client will try
to connect on the port specified by CONFIG_LWM2M_PEER_PORT.
If a port different from the peer port is to be used for firmware
update, this has to be set explicitly in the URI:
coap://example.com:5683/fw_update.
This fix adds CONFIG_LWM2M_FIRMWARE_PORT, which will be used when
fetching a firmware update without specifying the port number in the
URI.
Signed-off-by: Tjerand Bjornsen <tjerand.bjornsen@nordicsemi.no>
Add __printf_like modifier to validate strings used by shell.
Fixing warnings triggered by this change.
Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
Replace the custom float32_value_t LwM2M type with native double, to
facilitate LwM2M API and improve floating point precission.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
The irq_lock() usage here is incompatible with SMP systems, and one's
first reaction might be to convert it to a spinlock.
But are those irq_lock() instances really necessary?
Commit 6161ea2542 ("net: socket: socketpair: mitigate possible race
condition") doesn't say much:
> There was a possible race condition between sock_is_nonblock()
> and k_sem_take() in spair_read() and spair_write() that was
> mitigated.
A possible race without the irq_lock would be:
thread A thread B
| |
+ spair_write(): |
+ is_nonblock = sock_is_nonblock(spair); [false]
* [preemption here] |
| + spair_ioctl():
| + res = k_sem_take(&spair->sem, K_FOREVER);
| + [...]
| + spair->flags |= SPAIR_FLAG_NONBLOCK;
| * [preemption here]
+ res = k_sem_take(&spair->sem, K_NO_WAIT); [-1]
+ if (res < 0) { |
+ if (is_nonblock) { [skipped] }
* res = k_sem_take(&spair->sem, K_FOREVER); [blocks here]
| + [...]
But the version with irq_lock() isn't much better:
thread A thread B
| |
| + spair_ioctl():
| + res = k_sem_take(&spair->sem, K_FOREVER);
| + [...]
| * [preemption here]
+ spair_write(): |
+ irq_lock(); |
+ is_nonblock = sock_is_nonblock(spair); [false]
+ res = k_sem_take(&spair->sem, K_NO_WAIT); [-1]
+ irq_unlock(); |
* [preemption here] |
| + spair->flags |= SPAIR_FLAG_NONBLOCK;
| + [...]
| + k_sem_give(&spair->sem);
| + spair_read():
| + res = k_sem_take(&spair->sem, K_NO_WAIT);
| * [preemption here]
+ if (res < 0) { |
+ if (is_nonblock) { [skipped] }
* res = k_sem_take(&spair->sem, K_FOREVER); [blocks here]
In both cases the last k_sem_take(K_FOREVER) will block despite
SPAIR_FLAG_NONBLOCK being set at that moment. Other race scenarios
exist too, and on SMP they are even more likely.
The only guarantee provided by the irq_lock() is to make sure that
whenever the semaphore is acquired then the is_nonblock value is always
current. A better way to achieve that and be SMP compatible is to simply
move the initial sock_is_nonblock() *after* the k_sem_take() and remove
those irq_locks().
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
While adding support for service type enumeration, a regression was
introduced which prevented mDNS ptr query responses.
1. There was an off-by-one error with label size checking
2. Valid queries were failing to match in `dns_rec_match()` due to
not checking for either NULL or 0 "wildcard" port
Fixes#39284
Signed-off-by: Christopher Friedt <chrisfriedt@gmail.com>
From the OMA LwM2M Object and Resource Registry: "When the single Device
Object Instance is initiated, there is only one error code Resource
Instance whose value is equal to 0 that means no error."
This fix creates that initial error code resource instance, and makes
sure that it doesn't get deleted by the Reset Error Code resource.
Signed-off-by: Tjerand Bjornsen <tjerand.bjornsen@nordicsemi.no>
Mbed TLS 3.0 removes the definition for MBED_ERR_SSL_PEER_VERIFY_FAILED,
since non of its code ever returns that value. Since there isn't really
a perfect response, instead return a somewhat generic response
indicating this was unexpected.
Signed-off-by: David Brown <david.brown@linaro.org>
Several fields of structures in mbedTLS 3.0 are now private. To access
them directly is necessary to define MBEDTLS_ALLOW_PRIVATE_ACCESS.
That is a temporary fix, the proper solution is not access directly
but using proper API.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
Fixes#38994, ARP messages were being sent to IPvXmcast MAC addresses
rather than the expected source MAC address or the broadcast address.
Signed-off-by: Robert Melchers <rmelch@hotmail.com>
Implements mechanism similar to the one available in net/lib/sockets.c
(since the merge of #27054) in sockets_can to enable parallel rx/tx.
Fixes#38698
Signed-off-by: Mateusz Karlic <mkarlic@internships.antmicro.com>
Add an option to force close the LwM2M connection
instead of always trying to deregister.
If on a cellular connection and the connection is dropped,
deregistering will never complete and take a long time
before retries fail. This option allows the app to close the
socket and quickly re-establish the connection when the
network connection is available again.
Signed-off-by: Ryan Erickson <ryan.erickson@lairdconnect.com>
If blockwise transfer is not in use it must be possible to send bigger
CoAP messages than what is the block size used with blockwise transfers.
To compensate for the increased memory usage number of in-flight packets
allowed could be decreased.
Signed-off-by: Veijo Pesonen <veijo.pesonen@nordicsemi.no>
...range for LWM2M_COAP_BLOCK_SIZE.
The range has been set to start from 64 bytes and now the help text has
been brought up to date.
Signed-off-by: Veijo Pesonen <veijo.pesonen@nordicsemi.no>
Support DNS-SD Service Type Enumeration in the dns_sd library
and mdns_responder sample application.
For more information, please see Section 9, "Service Type
Enumeration" in RFC 6763.
https://datatracker.ietf.org/doc/html/rfc6763Fixes#38673
Signed-off-by: Christopher Friedt <chrisfriedt@gmail.com>
According to `sendmsg()` man pages, the `struct msghdr` can contain
empty records (iov_len equal to 0). Ignore them in TLS `sendmsg()`
implementation to avoid unnecessary calls to mbed TLS.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
In case zsock_sendmsg did not send all of the data requested, update the
`struct msghdr` content and retry.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
If data for `context_sendto()` was provided in a form of
`struct msghdr` (for instance via `sendmsg()`), it was not verified that
the provided data would actually fit into allocated net_pkt. In result,
and error could be returned in case the provided data was larger than
net_pkt allows.
Fix this, by verifying the remaining buffer length when iterating over
`struct msghdr`. Once the buffer is filled up, break the loop. In
result, functions like `sendmsg()` will return the actual length of data
sent instead of an error.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
When creating a socket, all of the registered socket implementation are
processed in a sequence, allowing to find appropriate socket
implementation for specified family/type/protocol. So far however,
the order of processing was not clearly defined, leaving ambiguity if
multiple implmentations supported the same set of parameters.
Fix this, by registering socket priority along with implementation. This
makes the processing order of particular socket implementations
explicit, giving more flexibility to the user, for example when it's
neeed to prioritze one implementation over another if they support the
same set of parameters.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
As with IPv6, the mdns and llmnr responders should join their multicast
groups for IPv4 instead of just adding the multicast address to the
interface.
Signed-off-by: Markus Fuchs <markus.fuchs@ch.sauter-bc.com>
As per #38352, we would like to start building out PTP (IEEE 1588)
support for superset of gPTP functionality in Zephyr. This is the first
step to abstract away some key interfaces from NET_GPTP umbrella to
NET_L2_PTP.
Signed-off-by: Alex Sergeev <asergeev@carbonrobotics.com>
RFC 2460 Sec. 5 requires that a ICMPv6 Time Exceeded message is sent
upon reassembly timeout, if we received the first fragment (i.e. the one
with a Fragment Offset of zero).
Implement this requirement.
Signed-off-by: Florian Vaussard <florian.vaussard@gmail.com>
The purpose of shift_packets() is to make room to insert one fragment in
the list. This is not what it does currently, potentially leading to
-ENOMEM even if there is enough free room.
To see the current behaviour, let's assume that we receive 3 fragments
in reverse order:
- Frag3(offset = 0x40, M=0)
- Frag2(offset = 0x20, M=1)
- Frag1(offset = 0x00, M=1)
After receiving Frag3 and Frag2, pkt[] will look like:
.-------.-------.-------.
| Frag2 | Frag3 | NULL |
| 0x20 | 0x40 | |
'-------'-------'-------'
pkt[0] pkt[1] pkt[2]
When receiving Frag1, shift_packets(pos = 0) is called to make some room
at position 0. It will iterate up to i = 2 where there is a free
element. The current algorithm will try to shift pkt[0] to pkt[2], which
is indeed impossible but also unnecessary. It is only required to shift
pkt[0] and pkt[1] by one element in order to free pkt[0] to insert
Frag1.
Update the algorithm in order to shift the memory only by one element.
As a result, the ENOMEM test is only simpler: as long as we encounter
one free element, we are guaranteed that we can shift by one element.
Also assign a NULL value to the newly freed element since memmove() only
copy bytes.
Signed-off-by: Florian Vaussard <florian.vaussard@gmail.com>
Currently net_ipv6_handle_fragment_hdr() performs 2 distinct tests: it
checks the M-bit of the most recent fragment to decide if we can proceed
with the reassembly. Then it performs some sanity checks which can lead
to dropping the whole packet if not successful.
The test on the M-bit assumes that fragments arrive in order. But this
will fail if packets arrive out-of-order, since the last fragment can
arrive before some other fragments. In that case, we proceed with the
reassembly but it will fail because not all the fragments have been
received.
We need a more complete check before proceeding with the reassembly:
- We received the first fragment (offset = 0)
- All intermediate fragments are contiguous
- The More bit of the last fragment is 0
Since these conditions can also detect a malformed fragmented packet, we
can replace the existing sanity check that is performed before
reassembly. As a bonus, we can now detect and rejected overlapping
fragments, since this can have some security issues (see RFC 5722).
Signed-off-by: Florian Vaussard <florian.vaussard@gmail.com>
Currently we only store the fragment offset. But in some cases it might
be necessary to also inspect the M-bit (More Fragment) of all received
fragments.
Modify the semantics of the field to store all the flags, rename the
setter to account for this change, and add a getter for the M-bit.
Signed-off-by: Florian Vaussard <florian.vaussard@gmail.com>
The special handling of the 1st fragment in unnecessary, since it will
be correctly handled even without it. Moreover it causes some corner
cases, like a single packet with a fragment header (M=0), to be
incorrectly handled since the reassembly code is skipped.
Remove the special handling of the 1st fragment to fix these problems.
Signed-off-by: Florian Vaussard <florian.vaussard@gmail.com>
Currently the requirement of the length being a multiple of 8 is not
tested for the first fragment, since the first fragment takes a
different path due to the goto.
Move the test earlier in the process, so that it is performed on all
fragments, including the first one.
Signed-off-by: Florian Vaussard <florian.vaussard@gmail.com>
If we have less fragments than what can be stored in the reassembly
array, some loops will blindly dereference NULL pointers.
Add checks for NULL pointers when necessary and exit the loop.
Signed-off-by: Florian Vaussard <florian.vaussard@gmail.com>
Currently the stack is limited to a maximum of 2 incoming fragments per
packet. While this can be enough in most cases, it might not be enough
in other cases.
Make this value configurable at build time.
Signed-off-by: Florian Vaussard <florian.vaussard@gmail.com>
Currently prev_hdr_offset always equals 6, which is the offset of
the nexthdr field in the IPv6 header. This value is used to overwrite it
when removing an IPv6 Fragment header, so it will work as long as there
is no other Extension header between the IPv6 header and the Fragment
header.
However this does not work in the other cases: the nexthdr field of the
IPv6 header will be overwritten instead of the nexthdr field of the last
Extension header before the Fragment, leading to unwanted results.
Update prev_hdr_offset so that it always point to the nexthdr field of
the previous header, either the IPv6 header or an Extension header.
Signed-off-by: Florian Vaussard <florian.vaussard@gmail.com>
The current validation code waits to process the header before rejecting
it, while some checks can be already enforced when reading the nexthdr
field of the previous header.
The main problem is a wrong pointer field in the resulting ICMPv6 error
message: the pointer should have the offset of the invalid nexthdr
field, while currently it will the offset the invalid header.
To solve that problem, reorganize the loop in two parts: the first
switch validates nexthdr, while the second switch processes the current
header. This allows to reject invalid nexthdr earlier.
The check for duplicated headers is also generalized, so that we can
catch other kind of headers (like the Fragment header).
Signed-off-by: Florian Vaussard <florian.vaussard@gmail.com>
By definition, NET_IPV6_NEXTHDR_NONE is void. So we must stop processing
before trying to read any data, since we will start reading values that
are outside the Extension Header (likely the payload, if any).
Signed-off-by: Florian Vaussard <florian.vaussard@gmail.com>
When an unknown option is encountered, an ICMPv6 error message must be
sent in some cases. The message contains a pointer field, which must be
the offset to the unknown option. Currently the offset is computed from
the beginning of the option list, while it should be computed with
respect to the beginning of the IPv6 header.
Record the offset when reading the option type and pass it later to
ipv6_drop_on_unknown_option() to correctly set the pointer field. Also
rename the argument in ipv6_drop_on_unknown_option() to make the
purpose more clear.
Signed-off-by: Florian Vaussard <florian.vaussard@gmail.com>
Currently PADN data are not skipped, which results in the stack to think
that the next header starts in the middle of the padding. We have to
skip the bytes before going on.
Also clarify the PAD1 does not have any length field.
Signed-off-by: Florian Vaussard <florian.vaussard@gmail.com>