Branch data Line data Source code
1 : : /* SPDX-FileCopyrightText: Copyright 2026 Cozens Software Solutions Limited
2 : : * SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 OR LicenseRef-PolyForm-Internal-Use-1.0.0 OR LicenseRef-COSOSO-Commercial
3 : : */
4 : :
5 : : #include "lwip/opt.h"
6 : :
7 : : /* This component resolves names through lwIP's getaddrinfo, which the stack
8 : : provides only when built with both the sockets layer and DNS. */
9 : : #if LWIP_SOCKET && LWIP_DNS
10 : :
11 : : #include "lwip/netdb.h"
12 : : #include "lwip/sockets.h"
13 : :
14 : : #include <stdbool.h>
15 : : #include <stddef.h>
16 : : #include <stdint.h>
17 : :
18 : : #include "SolidSyslogError.h"
19 : : #include "SolidSyslogLwipSocketAddressPrivate.h"
20 : : #include "SolidSyslogLwipSocketResolverErrors.h"
21 : : #include "SolidSyslogLwipSocketResolverPrivate.h"
22 : : #include "SolidSyslogNullResolver.h"
23 : : #include "SolidSyslogResolverCategories.h"
24 : : #include "SolidSyslogResolverDefinition.h"
25 : : #include "SolidSyslogTransport.h"
26 : :
27 : : const struct SolidSyslogErrorSource SolidSyslogLwipSocketResolverErrorSource = {
28 : : "LwipSocketResolver",
29 : : SolidSyslogResolverErrors_Name
30 : : };
31 : :
32 : : struct SolidSyslogAddress;
33 : :
34 : : enum
35 : : {
36 : : GETADDRINFO_SUCCESS = 0
37 : : };
38 : :
39 : : static bool LwipSocketResolver_Resolve(
40 : : struct SolidSyslogResolver* base,
41 : : enum SolidSyslogTransport transport,
42 : : const char* host,
43 : : uint16_t port,
44 : : struct SolidSyslogAddress* result
45 : : );
46 : : static inline bool LwipSocketResolver_IsIpv4(const struct addrinfo* info);
47 : :
48 : 19 : void SolidSyslogLwipSocketResolver_Initialise(struct SolidSyslogResolver* base)
49 : : {
50 : 19 : base->Resolve = LwipSocketResolver_Resolve;
51 : 19 : }
52 : :
53 : 11 : static bool LwipSocketResolver_Resolve(
54 : : struct SolidSyslogResolver* base,
55 : : enum SolidSyslogTransport transport,
56 : : const char* host,
57 : : uint16_t port,
58 : : struct SolidSyslogAddress* result
59 : : )
60 : : {
61 : : (void) base;
62 : : /* lwIP's getaddrinfo does not act on ai_socktype, so the transport tells the
63 : : * lookup nothing. The port is applied to the answer instead of being asked
64 : : * for as a service name. */
65 : : (void) transport;
66 : :
67 : : /* IPv4 only, which is what the sockaddr_in the transports send to can
68 : : * carry. The stack narrows its own lookup on this where it is built for
69 : : * both families; the refusal below does not depend on it doing so. */
70 : 11 : struct addrinfo hints = {0};
71 : 11 : hints.ai_family = AF_INET;
72 : :
73 : 11 : struct addrinfo* info = NULL;
74 : 11 : bool resolved = false;
75 : :
76 : : /* EAI_FAMILY is the same fault seen from the other side: the stack will not
77 : : * serve the family asked for, rather than answering in another one. Every
78 : : * other failure is a lookup that may answer later, and is left to the
79 : : * sender's delivery reporting. */
80 : 11 : int lookup = lwip_getaddrinfo(host, NULL, &hints, &info);
81 : 11 : bool isFamilyUnsupported = (lookup == EAI_FAMILY);
82 : :
83 [ + + ]: 11 : if (lookup == GETADDRINFO_SUCCESS)
84 : : {
85 [ + + ]: 7 : if (LwipSocketResolver_IsIpv4(info) == true)
86 : : {
87 : 4 : struct sockaddr_in* sin = SolidSyslogLwipSocketAddress_AsSockaddrIn(result);
88 : 4 : *sin = *(struct sockaddr_in*) info->ai_addr;
89 : 4 : sin->sin_port = lwip_htons(port);
90 : 4 : resolved = true;
91 : : }
92 : : else
93 : : {
94 : 3 : isFamilyUnsupported = true;
95 : : }
96 : : /* Freed on both paths: the answer comes out of a fixed pool, so a
97 : : * refusal that keeps it spends the pool on destinations we reject. */
98 : 7 : lwip_freeaddrinfo(info);
99 : : }
100 : :
101 [ + + ]: 11 : if (isFamilyUnsupported == true)
102 : : {
103 : 5 : LwipSocketResolver_Report(
104 : : SOLIDSYSLOG_SEVERITY_ERROR,
105 : : SOLIDSYSLOG_CAT_RESOLVER_RESOLVE_FAILED,
106 : : SOLIDSYSLOG_RESOLVER_ERROR_ADDRESS_FAMILY_UNSUPPORTED
107 : : );
108 : : }
109 : :
110 : 11 : return resolved;
111 : : }
112 : :
113 : 7 : static inline bool LwipSocketResolver_IsIpv4(const struct addrinfo* info)
114 : : {
115 : 7 : return (info->ai_family == AF_INET);
116 : : }
117 : :
118 : 19 : void SolidSyslogLwipSocketResolver_Cleanup(struct SolidSyslogResolver* base)
119 : : {
120 : : /* Overwrite the abstract base with the shared NullResolver vtable so
121 : : * use-after-destroy is a safe no-op rather than a NULL-fn-pointer crash. */
122 : 19 : *base = *SolidSyslogNullResolver_Get();
123 : 19 : }
124 : :
125 : : #else
126 : :
127 : : /* ISO C forbids an empty translation unit. */
128 : : typedef int LwipSocketResolver_EmptyTranslationUnit;
129 : :
130 : : #endif /* LWIP_SOCKET && LWIP_DNS */
|