ModUdp.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2025 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 "compat/unistd.h"
15 #include "fatal.h"
16 #include "fd.h"
17 #include "fs_io.h"
18 #include "log/File.h"
19 #include "log/ModUdp.h"
20 #include "Parsing.h"
21 #include "SquidConfig.h"
22 
23 #include <cerrno>
24 
25 /*
26  * This logfile UDP module is mostly inspired by a patch by Tim Starling
27  * from Wikimedia.
28  *
29  * It doesn't do any UDP buffering - it'd be quite a bit of work for
30  * something which the kernel could be doing for you!
31  */
32 
33 typedef struct {
34  int fd;
35  char *buf;
36  size_t bufsz;
37  int offset;
38 } l_udp_t;
39 
40 static void
41 logfile_mod_udp_write(Logfile * lf, const char *buf, size_t len)
42 {
43  l_udp_t *ll = (l_udp_t *) lf->data;
44  const auto s = xwrite(ll->fd, buf, len);
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 
60 static 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 
70 static void
71 logfile_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 
98 static void
100 {
101 }
102 
103 static void
105 {
107  lf->f_flush(lf);
108 }
109 
110 static void
112 {
113 }
114 
115 static 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  */
134 int
135 logfile_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  ll->fd = -1;
149  lf->data = ll;
150 
151  if (strncmp(path, "//", 2) == 0) {
152  path += 2;
153  }
154  strAddr = xstrdup(path);
155  if (!GetHostWithPort(strAddr, &addr)) {
156  if (lf->flags.fatal) {
157  fatalf("Invalid UDP logging address '%s'\n", lf->path);
158  } else {
159  debugs(50, DBG_IMPORTANT, "ERROR: Invalid UDP logging address '" << lf->path << "'");
160  safe_free(strAddr);
161  return FALSE;
162  }
163  }
164  safe_free(strAddr);
165 
166  Ip::Address any_addr;
167  any_addr.setAnyAddr();
168 
169  // require the sending UDP port to be of the right family for the destination address.
170  if (addr.isIPv4())
171  any_addr.setIPv4();
172 
173  ll->fd = comm_open(SOCK_DGRAM, IPPROTO_UDP, any_addr, COMM_NONBLOCKING, "UDP log socket");
174  int xerrno = errno;
175  if (ll->fd < 0) {
176  if (lf->flags.fatal) {
177  fatalf("Unable to open UDP socket for logging\n");
178  } else {
179  debugs(50, DBG_IMPORTANT, "ERROR: Unable to open UDP socket for logging");
180  return FALSE;
181  }
182  } else if (comm_connect_addr(ll->fd, addr) == Comm::COMM_ERROR) {
183  xerrno = errno;
184  if (lf->flags.fatal) {
185  fatalf("Unable to connect to %s for UDP log: %s\n", lf->path, xstrerr(xerrno));
186  } else {
187  debugs(50, DBG_IMPORTANT, "ERROR: Unable to connect to " << lf->path << " for UDP log: " << xstrerr(xerrno));
188  return FALSE;
189  }
190  }
191  if (ll->fd == -1) {
192  if (ENOENT == xerrno && fatal_flag) {
193  fatalf("Cannot open '%s' because\n"
194  "\tthe parent directory does not exist.\n"
195  "\tPlease create the directory.\n", path);
196  } else if (EACCES == xerrno && fatal_flag) {
197  fatalf("Cannot open '%s' for writing.\n"
198  "\tThe parent directory must be writeable by the\n"
199  "\tuser '%s', which is the cache_effective_user\n"
200  "\tset in squid.conf.", path, Config.effectiveUser);
201  } else {
202  debugs(50, DBG_IMPORTANT, "logfileOpen (UDP): " << lf->path << ": " << xstrerr(xerrno));
203  return 0;
204  }
205  }
206  /* Force buffer size to something roughly fitting inside an MTU */
207  /*
208  * XXX note the receive side needs to receive the whole packet at once;
209  * applications like netcat have a small default receive buffer and will
210  * truncate!
211  */
212  if (bufsz > 1400)
213  bufsz = 1400;
214  if (bufsz > 0) {
215  ll->buf = static_cast<char*>(xmalloc(bufsz));
216  ll->bufsz = bufsz;
217  }
218 
219  return 1;
220 }
221 
#define FALSE
Definition: defines.h:16
const char * xstrerr(int error)
Definition: xstrerror.cc:83
static void logfile_mod_udp_linestart(Logfile *)
Definition: ModUdp.cc:99
void * xcalloc(size_t n, size_t sz)
Definition: xalloc.cc:71
#define xmalloc
void fd_bytes(const int fd, const int len, const IoDirection direction)
Definition: fd.cc:221
char * buf
Definition: ModUdp.cc:35
int offset
Definition: ModUdp.cc:37
struct Logfile::@63 flags
int comm_connect_addr(int sock, const Ip::Address &address)
Definition: comm.cc:631
#define xstrdup
int xwrite(int fd, const void *buf, size_t bufSize)
POSIX write(2) equivalent.
Definition: unistd.h:67
bool isIPv4() const
Definition: Address.cc:178
LOGWRITE * f_linewrite
Definition: File.h:58
void file_close(int fd)
Definition: fs_io.cc:92
unsigned int fatal
Definition: File.h:49
#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
void * data
Definition: File.h:55
int fd
Definition: ModUdp.cc:34
int buffered_logs
Definition: SquidConfig.h:284
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_rotate(Logfile *, const int16_t)
Definition: ModUdp.cc:111
LOGLINEEND * f_lineend
Definition: File.h:59
static void logfile_mod_udp_lineend(Logfile *lf)
Definition: ModUdp.cc:104
#define safe_free(x)
Definition: xalloc.h:73
#define assert(EX)
Definition: assert.h:17
void fatalf(const char *fmt,...)
Definition: fatal.cc:68
bool setIPv4()
Definition: Address.cc:244
@ COMM_ERROR
Definition: Flag.h:17
LOGCLOSE * f_close
Definition: File.h:62
int comm_open(int sock_type, int proto, Ip::Address &addr, int flags, const char *note)
Definition: comm.cc:245
LOGROTATE * f_rotate
Definition: File.h:61
static void logfile_mod_udp_write(Logfile *lf, const char *buf, size_t len)
Definition: ModUdp.cc:41
char * effectiveUser
Definition: SquidConfig.h:196
#define xfree
Definition: File.h:38
static void logfile_mod_udp_flush(Logfile *lf)
Definition: ModUdp.cc:61
bool GetHostWithPort(char *token, Ip::Address *ipa)
Definition: Parsing.cc:257
size_t bufsz
Definition: ModUdp.cc:36
LOGFLUSH * f_flush
Definition: File.h:60
void setAnyAddr()
NOTE: Does NOT clear the Port stored. Only the Address and Type.
Definition: Address.cc:197
#define DBG_IMPORTANT
Definition: Stream.h:38
static void logfile_mod_udp_close(Logfile *lf)
Definition: ModUdp.cc:116
LOGLINESTART * f_linestart
Definition: File.h:57
struct SquidConfig::@90 onoff
char path[MAXPATHLEN]
Definition: File.h:46
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:192
class SquidConfig Config
Definition: SquidConfig.cc:12

 

Introduction

Documentation

Support

Miscellaneous