Coverage Report

Created: 2026-03-04 06:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/FreeRDP/winpr/libwinpr/utils/wlog/UdpAppender.c
Line
Count
Source
1
/**
2
 * WinPR: Windows Portable Runtime
3
 * WinPR Logger
4
 *
5
 * Copyright © 2015 Thincast Technologies GmbH
6
 * Copyright © 2015 David FORT <contact@hardening-consulting.com>
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
21
#include <winpr/config.h>
22
23
#include <winpr/crt.h>
24
#include <winpr/environment.h>
25
#include <winpr/winsock.h>
26
27
#include "wlog.h"
28
29
typedef struct
30
{
31
  wLogAppender common;
32
  char* host;
33
  struct sockaddr targetAddr;
34
  int targetAddrLen;
35
  SOCKET sock;
36
} wLogUdpAppender;
37
38
static BOOL WLog_UdpAppender_Open(WINPR_ATTR_UNUSED wLog* log, wLogAppender* appender)
39
0
{
40
0
  wLogUdpAppender* udpAppender = nullptr;
41
0
  char addressString[256] = WINPR_C_ARRAY_INIT;
42
0
  struct addrinfo hints = WINPR_C_ARRAY_INIT;
43
0
  struct addrinfo* result = WINPR_C_ARRAY_INIT;
44
0
  int status = 0;
45
0
  char* colonPos = nullptr;
46
47
0
  if (!appender)
48
0
    return FALSE;
49
50
0
  udpAppender = (wLogUdpAppender*)appender;
51
52
0
  if (udpAppender->targetAddrLen) /* already opened */
53
0
    return TRUE;
54
55
0
  colonPos = strchr(udpAppender->host, ':');
56
57
0
  if (!colonPos)
58
0
    return FALSE;
59
60
0
  const size_t addrLen = WINPR_ASSERTING_INT_CAST(size_t, (colonPos - udpAppender->host));
61
0
  memcpy(addressString, udpAppender->host, addrLen);
62
0
  addressString[addrLen] = '\0';
63
0
  hints.ai_family = AF_INET;
64
0
  hints.ai_socktype = SOCK_DGRAM;
65
0
  status = getaddrinfo(addressString, colonPos + 1, &hints, &result);
66
67
0
  if (status != 0)
68
0
    return FALSE;
69
70
0
  if (result->ai_addrlen > sizeof(udpAppender->targetAddr))
71
0
  {
72
0
    freeaddrinfo(result);
73
0
    return FALSE;
74
0
  }
75
76
0
  memcpy(&udpAppender->targetAddr, result->ai_addr, result->ai_addrlen);
77
0
  udpAppender->targetAddrLen = (int)result->ai_addrlen;
78
0
  freeaddrinfo(result);
79
0
  return TRUE;
80
0
}
81
82
static BOOL WLog_UdpAppender_Close(wLog* log, wLogAppender* appender)
83
0
{
84
0
  return !(!log || !appender);
85
0
}
86
87
static BOOL WLog_UdpAppender_WriteMessage(wLog* log, wLogAppender* appender,
88
                                          const wLogMessage* cmessage)
89
0
{
90
0
  if (!log || !appender || !cmessage)
91
0
    return FALSE;
92
93
0
  wLogUdpAppender* udpAppender = (wLogUdpAppender*)appender;
94
95
0
  char prefix[WLOG_MAX_PREFIX_SIZE] = WINPR_C_ARRAY_INIT;
96
0
  WLog_Layout_GetMessagePrefix(log, appender->Layout, cmessage, prefix, sizeof(prefix));
97
98
0
  BOOL res = TRUE;
99
0
  if (_sendto(udpAppender->sock, prefix, (int)strnlen(prefix, ARRAYSIZE(prefix)), 0,
100
0
              &udpAppender->targetAddr, udpAppender->targetAddrLen) < 0)
101
0
    res = FALSE;
102
0
  if (_sendto(udpAppender->sock, cmessage->TextString,
103
0
              (int)strnlen(cmessage->TextString, INT_MAX), 0, &udpAppender->targetAddr,
104
0
              udpAppender->targetAddrLen) < 0)
105
0
    res = FALSE;
106
0
  if (_sendto(udpAppender->sock, "\n", 1, 0, &udpAppender->targetAddr,
107
0
              udpAppender->targetAddrLen) < 0)
108
0
    res = FALSE;
109
0
  return res;
110
0
}
111
112
static BOOL WLog_UdpAppender_WriteDataMessage(wLog* log, wLogAppender* appender,
113
                                              const wLogMessage* message)
114
0
{
115
0
  return !(!log || !appender || !message);
116
0
}
117
118
static BOOL WLog_UdpAppender_WriteImageMessage(wLog* log, wLogAppender* appender,
119
                                               const wLogMessage* message)
120
0
{
121
0
  return !(!log || !appender || !message);
122
0
}
123
124
static BOOL WLog_UdpAppender_Set(wLogAppender* appender, const char* setting, void* value)
125
0
{
126
0
  const char target[] = "target";
127
0
  wLogUdpAppender* udpAppender = (wLogUdpAppender*)appender;
128
129
  /* Just check the value string is not empty */
130
0
  if (!value || (strnlen(value, 2) == 0))
131
0
    return FALSE;
132
133
0
  if (strncmp(target, setting, sizeof(target)) != 0)
134
0
    return FALSE;
135
136
0
  udpAppender->targetAddrLen = 0;
137
138
0
  if (udpAppender->host)
139
0
    free(udpAppender->host);
140
141
0
  udpAppender->host = _strdup((const char*)value);
142
0
  return (udpAppender->host != nullptr) && WLog_UdpAppender_Open(nullptr, appender);
143
0
}
144
145
static void WLog_UdpAppender_Free(wLogAppender* appender)
146
0
{
147
0
  wLogUdpAppender* udpAppender = nullptr;
148
149
0
  if (appender)
150
0
  {
151
0
    udpAppender = (wLogUdpAppender*)appender;
152
153
0
    if (udpAppender->sock != INVALID_SOCKET)
154
0
    {
155
0
      closesocket(udpAppender->sock);
156
0
      udpAppender->sock = INVALID_SOCKET;
157
0
    }
158
159
0
    free(udpAppender->host);
160
0
    free(udpAppender);
161
0
  }
162
0
}
163
164
wLogAppender* WLog_UdpAppender_New(wLog* log)
165
0
{
166
0
  DWORD nSize = 0;
167
0
  LPCSTR name = nullptr;
168
0
  wLogUdpAppender* appender = (wLogUdpAppender*)calloc(1, sizeof(wLogUdpAppender));
169
170
0
  if (!appender)
171
0
    return nullptr;
172
173
0
  appender->common.Type = WLOG_APPENDER_UDP;
174
0
  appender->common.Open = WLog_UdpAppender_Open;
175
0
  appender->common.Close = WLog_UdpAppender_Close;
176
0
  appender->common.WriteMessage = WLog_UdpAppender_WriteMessage;
177
0
  appender->common.WriteDataMessage = WLog_UdpAppender_WriteDataMessage;
178
0
  appender->common.WriteImageMessage = WLog_UdpAppender_WriteImageMessage;
179
0
  appender->common.Free = WLog_UdpAppender_Free;
180
0
  appender->common.Set = WLog_UdpAppender_Set;
181
0
  appender->sock = _socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
182
183
0
  if (appender->sock == INVALID_SOCKET)
184
0
    goto error_sock;
185
186
0
  name = "WLOG_UDP_TARGET";
187
0
  nSize = GetEnvironmentVariableA(name, nullptr, 0);
188
189
0
  if (nSize)
190
0
  {
191
0
    appender->host = (LPSTR)malloc(nSize);
192
193
0
    if (!appender->host)
194
0
      goto error_open;
195
196
0
    if (GetEnvironmentVariableA(name, appender->host, nSize) != nSize - 1)
197
0
      goto error_open;
198
199
0
    if (!WLog_UdpAppender_Open(log, (wLogAppender*)appender))
200
0
      goto error_open;
201
0
  }
202
0
  else
203
0
  {
204
0
    appender->host = _strdup("127.0.0.1:20000");
205
206
0
    if (!appender->host)
207
0
      goto error_open;
208
0
  }
209
210
0
  return &appender->common;
211
0
error_open:
212
0
  free(appender->host);
213
0
  closesocket(appender->sock);
214
0
error_sock:
215
0
  free(appender);
216
0
  return nullptr;
217
0
}