Blame winpr/libwinpr/utils/wlog/UdpAppender.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * WinPR: Windows Portable Runtime
Packit 1fb8d4
 * WinPR Logger
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright © 2015 Thincast Technologies GmbH
Packit 1fb8d4
 * Copyright © 2015 David FORT <contact@hardening-consulting.com>
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
#include <winpr/environment.h>
Packit 1fb8d4
#include <winpr/winsock.h>
Packit 1fb8d4
Packit 1fb8d4
#include "wlog.h"
Packit 1fb8d4
Packit 1fb8d4
struct _wLogUdpAppender
Packit 1fb8d4
{
Packit 1fb8d4
	WLOG_APPENDER_COMMON();
Packit 1fb8d4
	char* host;
Packit 1fb8d4
	struct sockaddr targetAddr;
Packit Service 5a9772
	int targetAddrLen;
Packit 1fb8d4
	SOCKET sock;
Packit 1fb8d4
};
Packit 1fb8d4
typedef struct _wLogUdpAppender wLogUdpAppender;
Packit 1fb8d4
Packit 1fb8d4
static BOOL WLog_UdpAppender_Open(wLog* log, wLogAppender* appender)
Packit 1fb8d4
{
Packit 1fb8d4
	wLogUdpAppender* udpAppender;
Packit 1fb8d4
	char addressString[256];
Packit 1fb8d4
	struct addrinfo hints;
Packit 1fb8d4
	struct addrinfo* result;
Packit 1fb8d4
	int status, addrLen;
Packit 1fb8d4
	char* colonPos;
Packit 1fb8d4
Packit 1fb8d4
	if (!appender)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	udpAppender = (wLogUdpAppender*)appender;
Packit 1fb8d4
Packit 1fb8d4
	if (udpAppender->targetAddrLen) /* already opened */
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
Packit 1fb8d4
	colonPos = strchr(udpAppender->host, ':');
Packit 1fb8d4
Packit 1fb8d4
	if (!colonPos)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	addrLen = (int)(colonPos - udpAppender->host);
Packit 1fb8d4
	memcpy(addressString, udpAppender->host, addrLen);
Packit 1fb8d4
	addressString[addrLen] = '\0';
Packit 1fb8d4
	ZeroMemory(&hints, sizeof(hints));
Packit 1fb8d4
	hints.ai_family = AF_INET;
Packit 1fb8d4
	hints.ai_socktype = SOCK_DGRAM;
Packit 1fb8d4
	status = getaddrinfo(addressString, colonPos + 1, &hints, &result);
Packit 1fb8d4
Packit 1fb8d4
	if (status != 0)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (result->ai_addrlen > sizeof(udpAppender->targetAddr))
Packit 1fb8d4
	{
Packit 1fb8d4
		freeaddrinfo(result);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	memcpy(&udpAppender->targetAddr, result->ai_addr, result->ai_addrlen);
Packit Service 5a9772
	udpAppender->targetAddrLen = (int)result->ai_addrlen;
Packit 1fb8d4
	freeaddrinfo(result);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL WLog_UdpAppender_Close(wLog* log, wLogAppender* appender)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!log || !appender)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL WLog_UdpAppender_WriteMessage(wLog* log, wLogAppender* appender, wLogMessage* message)
Packit 1fb8d4
{
Packit 1fb8d4
	char prefix[WLOG_MAX_PREFIX_SIZE];
Packit 1fb8d4
	wLogUdpAppender* udpAppender;
Packit 1fb8d4
Packit 1fb8d4
	if (!log || !appender || !message)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	udpAppender = (wLogUdpAppender*)appender;
Packit 1fb8d4
	message->PrefixString = prefix;
Packit 1fb8d4
	WLog_Layout_GetMessagePrefix(log, appender->Layout, message);
Packit Service 5a9772
	_sendto(udpAppender->sock, message->PrefixString, (int)strnlen(message->PrefixString, INT_MAX),
Packit 1fb8d4
	        0, &udpAppender->targetAddr, udpAppender->targetAddrLen);
Packit Service 5a9772
	_sendto(udpAppender->sock, message->TextString, (int)strnlen(message->TextString, INT_MAX), 0,
Packit Service 5a9772
	        &udpAppender->targetAddr, udpAppender->targetAddrLen);
Packit 1fb8d4
	_sendto(udpAppender->sock, "\n", 1, 0, &udpAppender->targetAddr, udpAppender->targetAddrLen);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL WLog_UdpAppender_WriteDataMessage(wLog* log, wLogAppender* appender,
Packit Service 5a9772
                                              wLogMessage* message)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!log || !appender || !message)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL WLog_UdpAppender_WriteImageMessage(wLog* log, wLogAppender* appender,
Packit Service 5a9772
                                               wLogMessage* message)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!log || !appender || !message)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL WLog_UdpAppender_Set(wLogAppender* appender, const char* setting, void* value)
Packit 1fb8d4
{
Packit Service 5a9772
	const char target[] = "target";
Packit 1fb8d4
	wLogUdpAppender* udpAppender = (wLogUdpAppender*)appender;
Packit 1fb8d4
Packit Service 5a9772
	/* Just check the value string is not empty */
Packit Service 5a9772
	if (!value || (strnlen(value, 2) == 0))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit Service 5a9772
	if (strncmp(target, setting, sizeof(target)))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	udpAppender->targetAddrLen = 0;
Packit 1fb8d4
Packit 1fb8d4
	if (udpAppender->host)
Packit 1fb8d4
		free(udpAppender->host);
Packit 1fb8d4
Packit 1fb8d4
	udpAppender->host = _strdup((const char*)value);
Packit 1fb8d4
	return (udpAppender->host != NULL) && WLog_UdpAppender_Open(NULL, appender);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void WLog_UdpAppender_Free(wLogAppender* appender)
Packit 1fb8d4
{
Packit 1fb8d4
	wLogUdpAppender* udpAppender;
Packit 1fb8d4
Packit 1fb8d4
	if (appender)
Packit 1fb8d4
	{
Packit 1fb8d4
		udpAppender = (wLogUdpAppender*)appender;
Packit 1fb8d4
Packit 1fb8d4
		if (udpAppender->sock != INVALID_SOCKET)
Packit 1fb8d4
		{
Packit 1fb8d4
			closesocket(udpAppender->sock);
Packit 1fb8d4
			udpAppender->sock = INVALID_SOCKET;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		free(udpAppender->host);
Packit 1fb8d4
		free(udpAppender);
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
wLogAppender* WLog_UdpAppender_New(wLog* log)
Packit 1fb8d4
{
Packit 1fb8d4
	wLogUdpAppender* appender;
Packit 1fb8d4
	DWORD nSize;
Packit 1fb8d4
	LPCSTR name;
Packit Service 5a9772
	appender = (wLogUdpAppender*)calloc(1, sizeof(wLogUdpAppender));
Packit 1fb8d4
Packit 1fb8d4
	if (!appender)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	appender->Type = WLOG_APPENDER_UDP;
Packit 1fb8d4
	appender->Open = WLog_UdpAppender_Open;
Packit 1fb8d4
	appender->Close = WLog_UdpAppender_Close;
Packit 1fb8d4
	appender->WriteMessage = WLog_UdpAppender_WriteMessage;
Packit 1fb8d4
	appender->WriteDataMessage = WLog_UdpAppender_WriteDataMessage;
Packit 1fb8d4
	appender->WriteImageMessage = WLog_UdpAppender_WriteImageMessage;
Packit 1fb8d4
	appender->Free = WLog_UdpAppender_Free;
Packit 1fb8d4
	appender->Set = WLog_UdpAppender_Set;
Packit 1fb8d4
	appender->sock = _socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
Packit 1fb8d4
Packit 1fb8d4
	if (appender->sock == INVALID_SOCKET)
Packit 1fb8d4
		goto error_sock;
Packit 1fb8d4
Packit 1fb8d4
	name = "WLOG_UDP_TARGET";
Packit 1fb8d4
	nSize = GetEnvironmentVariableA(name, NULL, 0);
Packit 1fb8d4
Packit 1fb8d4
	if (nSize)
Packit 1fb8d4
	{
Packit Service 5a9772
		appender->host = (LPSTR)malloc(nSize);
Packit 1fb8d4
Packit 1fb8d4
		if (!appender->host)
Packit 1fb8d4
			goto error_open;
Packit 1fb8d4
Packit 1fb8d4
		if (GetEnvironmentVariableA(name, appender->host, nSize) != nSize - 1)
Packit 1fb8d4
			goto error_open;
Packit 1fb8d4
Packit 1fb8d4
		if (!WLog_UdpAppender_Open(log, (wLogAppender*)appender))
Packit 1fb8d4
			goto error_open;
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		appender->host = _strdup("127.0.0.1:20000");
Packit 1fb8d4
Packit 1fb8d4
		if (!appender->host)
Packit 1fb8d4
			goto error_open;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return (wLogAppender*)appender;
Packit 1fb8d4
error_open:
Packit 1fb8d4
	free(appender->host);
Packit 1fb8d4
	closesocket(appender->sock);
Packit 1fb8d4
error_sock:
Packit 1fb8d4
	free(appender);
Packit 1fb8d4
	return NULL;
Packit 1fb8d4
}