ModUdp.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9/* DEBUG: section 50 Log file handling */
10
11#include "squid.h"
12#include "comm.h"
13#include "comm/Connection.h"
14#include "fatal.h"
15#include "fd.h"
16#include "fs_io.h"
17#include "log/File.h"
18#include "log/ModUdp.h"
19#include "Parsing.h"
20#include "SquidConfig.h"
21
22#include <cerrno>
23
24/*
25 * This logfile UDP module is mostly inspired by a patch by Tim Starling
26 * from Wikimedia.
27 *
28 * It doesn't do any UDP buffering - it'd be quite a bit of work for
29 * something which the kernel could be doing for you!
30 */
31
32typedef struct {
33 int fd;
34 char *buf;
35 size_t bufsz;
36 int offset;
37} l_udp_t;
38
39static void
40logfile_mod_udp_write(Logfile * lf, const char *buf, size_t len)
41{
42 l_udp_t *ll = (l_udp_t *) lf->data;
43 ssize_t s;
44 s = write(ll->fd, (char const *) buf, len);
45 fd_bytes(ll->fd, s, FD_WRITE);
46#if 0
47 // TODO: Enable after polishing to properly log these errors.
48 if (s < 0) {
49 int xerrno = errno;
50 debugs(1, DBG_IMPORTANT, "logfile (udp): got errno (" << errno << "):" << xstrerr(xerrno));
51 }
52 if (s != len) {
53 debugs(1, DBG_IMPORTANT, "logfile (udp): len=" << len << ", wrote=" << s);
54 }
55#endif
56
57 /* We don't worry about network errors for now */
58}
59
60static void
62{
63 l_udp_t *ll = (l_udp_t *) lf->data;
64 if (0 == ll->offset)
65 return;
66 logfile_mod_udp_write(lf, ll->buf, (size_t) ll->offset);
67 ll->offset = 0;
68}
69
70static void
71logfile_mod_udp_writeline(Logfile * lf, const char *buf, size_t len)
72{
73 l_udp_t *ll = (l_udp_t *) lf->data;
74
75 if (0 == ll->bufsz) {
76 /* buffering disabled */
77 logfile_mod_udp_write(lf, buf, len);
78 return;
79 }
80 if (ll->offset > 0 && (ll->offset + len + 4) > ll->bufsz)
82
83 if (len > ll->bufsz) {
84 /* too big to fit in buffer */
85 logfile_mod_udp_write(lf, buf, len);
86 return;
87 }
88 /* buffer it */
89 memcpy(ll->buf + ll->offset, buf, len);
90
91 ll->offset += len;
92
93 assert(ll->offset >= 0);
94
95 assert((size_t) ll->offset <= ll->bufsz);
96}
97
98static void
100{
101}
102
103static void
105{
107 lf->f_flush(lf);
108}
109
110static void
112{
113}
114
115static void
117{
118 l_udp_t *ll = (l_udp_t *) lf->data;
119 lf->f_flush(lf);
120
121 if (ll->fd >= 0)
122 file_close(ll->fd);
123
124 if (ll->buf)
125 xfree(ll->buf);
126
127 xfree(lf->data);
128 lf->data = nullptr;
129}
130
131/*
132 * This code expects the path to be //host:port
133 */
134int
135logfile_mod_udp_open(Logfile * lf, const char *path, size_t bufsz, int fatal_flag)
136{
137 Ip::Address addr;
138 char *strAddr;
139
146
147 l_udp_t *ll = static_cast<l_udp_t*>(xcalloc(1, sizeof(*ll)));
148 lf->data = ll;
149
150 if (strncmp(path, "//", 2) == 0) {
151 path += 2;
152 }
153 strAddr = xstrdup(path);
154 if (!GetHostWithPort(strAddr, &addr)) {
155 if (lf->flags.fatal) {
156 fatalf("Invalid UDP logging address '%s'\n", lf->path);
157 } else {
158 debugs(50, DBG_IMPORTANT, "ERROR: Invalid UDP logging address '" << lf->path << "'");
159 safe_free(strAddr);
160 return FALSE;
161 }
162 }
163 safe_free(strAddr);
164
165 Ip::Address any_addr;
166 any_addr.setAnyAddr();
167
168 // require the sending UDP port to be of the right family for the destination address.
169 if (addr.isIPv4())
170 any_addr.setIPv4();
171
172 ll->fd = comm_open(SOCK_DGRAM, IPPROTO_UDP, any_addr, COMM_NONBLOCKING, "UDP log socket");
173 int xerrno = errno;
174 if (ll->fd < 0) {
175 if (lf->flags.fatal) {
176 fatalf("Unable to open UDP socket for logging\n");
177 } else {
178 debugs(50, DBG_IMPORTANT, "ERROR: Unable to open UDP socket for logging");
179 return FALSE;
180 }
181 } else if (!comm_connect_addr(ll->fd, addr)) {
182 xerrno = errno;
183 if (lf->flags.fatal) {
184 fatalf("Unable to connect to %s for UDP log: %s\n", lf->path, xstrerr(xerrno));
185 } else {
186 debugs(50, DBG_IMPORTANT, "ERROR: Unable to connect to " << lf->path << " for UDP log: " << xstrerr(xerrno));
187 return FALSE;
188 }
189 }
190 if (ll->fd == -1) {
191 if (ENOENT == xerrno && fatal_flag) {
192 fatalf("Cannot open '%s' because\n"
193 "\tthe parent directory does not exist.\n"
194 "\tPlease create the directory.\n", path);
195 } else if (EACCES == xerrno && fatal_flag) {
196 fatalf("Cannot open '%s' for writing.\n"
197 "\tThe parent directory must be writeable by the\n"
198 "\tuser '%s', which is the cache_effective_user\n"
199 "\tset in squid.conf.", path, Config.effectiveUser);
200 } else {
201 debugs(50, DBG_IMPORTANT, "logfileOpen (UDP): " << lf->path << ": " << xstrerr(xerrno));
202 return 0;
203 }
204 }
205 /* Force buffer size to something roughly fitting inside an MTU */
206 /*
207 * XXX note the receive side needs to receive the whole packet at once;
208 * applications like netcat have a small default receive buffer and will
209 * truncate!
210 */
211 if (bufsz > 1400)
212 bufsz = 1400;
213 if (bufsz > 0) {
214 ll->buf = static_cast<char*>(xmalloc(bufsz));
215 ll->bufsz = bufsz;
216 }
217
218 return 1;
219}
220
#define COMM_NONBLOCKING
Definition: Connection.h:46
static void logfile_mod_udp_writeline(Logfile *lf, const char *buf, size_t len)
Definition: ModUdp.cc:71
static void logfile_mod_udp_rotate(Logfile *, const int16_t)
Definition: ModUdp.cc:111
int logfile_mod_udp_open(Logfile *lf, const char *path, size_t bufsz, int fatal_flag)
Definition: ModUdp.cc:135
static void logfile_mod_udp_linestart(Logfile *)
Definition: ModUdp.cc:99
static void logfile_mod_udp_close(Logfile *lf)
Definition: ModUdp.cc:116
static void logfile_mod_udp_lineend(Logfile *lf)
Definition: ModUdp.cc:104
static void logfile_mod_udp_flush(Logfile *lf)
Definition: ModUdp.cc:61
static void logfile_mod_udp_write(Logfile *lf, const char *buf, size_t len)
Definition: ModUdp.cc:40
bool GetHostWithPort(char *token, Ip::Address *ipa)
Definition: Parsing.cc:257
class SquidConfig Config
Definition: SquidConfig.cc:12
#define assert(EX)
Definition: assert.h:17
bool setIPv4()
Definition: Address.cc:224
bool isIPv4() const
Definition: Address.cc:158
void setAnyAddr()
NOTE: Does NOT clear the Port stored. Only the Address and Type.
Definition: Address.cc:177
Definition: File.h:39
LOGLINEEND * f_lineend
Definition: File.h:59
LOGFLUSH * f_flush
Definition: File.h:60
void * data
Definition: File.h:55
LOGCLOSE * f_close
Definition: File.h:62
char path[MAXPATHLEN]
Definition: File.h:46
struct Logfile::@79 flags
LOGLINESTART * f_linestart
Definition: File.h:57
LOGWRITE * f_linewrite
Definition: File.h:58
unsigned int fatal
Definition: File.h:49
LOGROTATE * f_rotate
Definition: File.h:61
struct SquidConfig::@106 onoff
int buffered_logs
Definition: SquidConfig.h:284
char * effectiveUser
Definition: SquidConfig.h:196
int comm_open(int sock_type, int proto, Ip::Address &addr, int flags, const char *note)
Definition: comm.cc:242
int comm_connect_addr(int sock, const Ip::Address &address)
Definition: comm.cc:634
#define DBG_IMPORTANT
Definition: Stream.h:38
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:194
@ FD_WRITE
Definition: enums.h:24
void fatalf(const char *fmt,...)
Definition: fatal.cc:68
void fd_bytes(int fd, int len, unsigned int type)
Definition: fd.cc:226
void file_close(int fd)
Definition: fs_io.cc:73
#define xfree
#define xstrdup
#define xmalloc
#define FALSE
Definition: std-includes.h:56
int fd
Definition: ModUdp.cc:33
int offset
Definition: ModUdp.cc:36
char * buf
Definition: ModUdp.cc:34
size_t bufsz
Definition: ModUdp.cc:35
void * xcalloc(size_t n, size_t sz)
Definition: xalloc.cc:71
#define safe_free(x)
Definition: xalloc.h:73
const char * xstrerr(int error)
Definition: xstrerror.cc:83

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors