Coverage Report

Created: 2025-11-24 06:34

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 = NULL;
41
0
  char addressString[256] = { 0 };
42
0
  struct addrinfo hints = { 0 };
43
0
  struct addrinfo* result = { 0 };
44
0
  int status = 0;
45
0
  char* colonPos = NULL;
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
  if (!log || !appender)
85
0
    return FALSE;
86
87
0
  return TRUE;
88
0
}
89
90
static BOOL WLog_UdpAppender_WriteMessage(wLog* log, wLogAppender* appender,
91
                                          const wLogMessage* cmessage)
92
0
{
93
0
  if (!log || !appender || !cmessage)
94
0
    return FALSE;
95
96
0
  wLogUdpAppender* udpAppender = (wLogUdpAppender*)appender;
97
98
0
  char prefix[WLOG_MAX_PREFIX_SIZE] = { 0 };
99
0
  WLog_Layout_GetMessagePrefix(log, appender->Layout, cmessage, prefix, sizeof(prefix));
100
101
0
  (void)_sendto(udpAppender->sock, prefix, (int)strnlen(prefix, ARRAYSIZE(prefix)), 0,
102
0
                &udpAppender->targetAddr, udpAppender->targetAddrLen);
103
0
  (void)_sendto(udpAppender->sock, cmessage->TextString,
104
0
                (int)strnlen(cmessage->TextString, INT_MAX), 0, &udpAppender->targetAddr,
105
0
                udpAppender->targetAddrLen);
106
0
  (void)_sendto(udpAppender->sock, "\n", 1, 0, &udpAppender->targetAddr,
107
0
                udpAppender->targetAddrLen);
108
0
  return TRUE;
109
0
}
110
111
static BOOL WLog_UdpAppender_WriteDataMessage(wLog* log, wLogAppender* appender,
112
                                              const wLogMessage* message)
113
0
{
114
0
  if (!log || !appender || !message)
115
0
    return FALSE;
116
117
0
  return TRUE;
118
0
}
119
120
static BOOL WLog_UdpAppender_WriteImageMessage(wLog* log, wLogAppender* appender,
121
                                               const wLogMessage* message)
122
0
{
123
0
  if (!log || !appender || !message)
124
0
    return FALSE;
125
126
0
  return TRUE;
127
0
}
128
129
static BOOL WLog_UdpAppender_Set(wLogAppender* appender, const char* setting, void* value)
130
0
{
131
0
  const char target[] = "target";
132
0
  wLogUdpAppender* udpAppender = (wLogUdpAppender*)appender;
133
134
  /* Just check the value string is not empty */
135
0
  if (!value || (strnlen(value, 2) == 0))
136
0
    return FALSE;
137
138
0
  if (strncmp(target, setting, sizeof(target)) != 0)
139
0
    return FALSE;
140
141
0
  udpAppender->targetAddrLen = 0;
142
143
0
  if (udpAppender->host)
144
0
    free(udpAppender->host);
145
146
0
  udpAppender->host = _strdup((const char*)value);
147
0
  return (udpAppender->host != NULL) && WLog_UdpAppender_Open(NULL, appender);
148
0
}
149
150
static void WLog_UdpAppender_Free(wLogAppender* appender)
151
0
{
152
0
  wLogUdpAppender* udpAppender = NULL;
153
154
0
  if (appender)
155
0
  {
156
0
    udpAppender = (wLogUdpAppender*)appender;
157
158
0
    if (udpAppender->sock != INVALID_SOCKET)
159
0
    {
160
0
      closesocket(udpAppender->sock);
161
0
      udpAppender->sock = INVALID_SOCKET;
162
0
    }
163
164
0
    free(udpAppender->host);
165
0
    free(udpAppender);
166
0
  }
167
0
}
168
169
wLogAppender* WLog_UdpAppender_New(wLog* log)
170
0
{
171
0
  DWORD nSize = 0;
172
0
  LPCSTR name = NULL;
173
0
  wLogUdpAppender* appender = (wLogUdpAppender*)calloc(1, sizeof(wLogUdpAppender));
174
175
0
  if (!appender)
176
0
    return NULL;
177
178
0
  appender->common.Type = WLOG_APPENDER_UDP;
179
0
  appender->common.Open = WLog_UdpAppender_Open;
180
0
  appender->common.Close = WLog_UdpAppender_Close;
181
0
  appender->common.WriteMessage = WLog_UdpAppender_WriteMessage;
182
0
  appender->common.WriteDataMessage = WLog_UdpAppender_WriteDataMessage;
183
0
  appender->common.WriteImageMessage = WLog_UdpAppender_WriteImageMessage;
184
0
  appender->common.Free = WLog_UdpAppender_Free;
185
0
  appender->common.Set = WLog_UdpAppender_Set;
186
0
  appender->sock = _socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
187
188
0
  if (appender->sock == INVALID_SOCKET)
189
0
    goto error_sock;
190
191
0
  name = "WLOG_UDP_TARGET";
192
0
  nSize = GetEnvironmentVariableA(name, NULL, 0);
193
194
0
  if (nSize)
195
0
  {
196
0
    appender->host = (LPSTR)malloc(nSize);
197
198
0
    if (!appender->host)
199
0
      goto error_open;
200
201
0
    if (GetEnvironmentVariableA(name, appender->host, nSize) != nSize - 1)
202
0
      goto error_open;
203
204
0
    if (!WLog_UdpAppender_Open(log, (wLogAppender*)appender))
205
0
      goto error_open;
206
0
  }
207
0
  else
208
0
  {
209
0
    appender->host = _strdup("127.0.0.1:20000");
210
211
0
    if (!appender->host)
212
0
      goto error_open;
213
0
  }
214
215
0
  return &appender->common;
216
0
error_open:
217
0
  free(appender->host);
218
0
  closesocket(appender->sock);
219
0
error_sock:
220
0
  free(appender);
221
  return NULL;
222
0
}