]> git.ipfire.org Git - thirdparty/squid.git/blame - src/log/ModUdp.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / log / ModUdp.cc
CommitLineData
82b7abe3 1/*
bbc27441 2 * Copyright (C) 1996-2014 The Squid Software Foundation and contributors
82b7abe3 3 *
bbc27441
AJ
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.
82b7abe3
AJ
7 */
8
bbc27441
AJ
9/* DEBUG: section 50 Log file handling */
10
582c2af2 11#include "squid.h"
82b7abe3 12#include "comm.h"
f9b72e0c 13#include "comm/Connection.h"
438b04d4 14#include "disk.h"
ed6e9fb9 15#include "fatal.h"
c4ad1349 16#include "fd.h"
82b7abe3
AJ
17#include "log/File.h"
18#include "log/ModUdp.h"
19#include "Parsing.h"
4d5904f7 20#include "SquidConfig.h"
82b7abe3 21
1a30fdf5 22#include <cerrno>
21d845b1 23
82b7abe3
AJ
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 if (s < 0) {
e0236918 48 debugs(1, DBG_IMPORTANT, "logfile (udp): got errno (" << errno << "):" << xstrerror());
82b7abe3
AJ
49 }
50 if (s != len) {
e0236918 51 debugs(1, DBG_IMPORTANT, "logfile (udp): len=" << len << ", wrote=" << s);
82b7abe3
AJ
52 }
53#endif
54
55 /* We don't worry about network errors for now */
56}
57
58static void
59logfile_mod_udp_flush(Logfile * lf)
60{
61 l_udp_t *ll = (l_udp_t *) lf->data;
62 if (0 == ll->offset)
9d65168e 63 return;
82b7abe3
AJ
64 logfile_mod_udp_write(lf, ll->buf, (size_t) ll->offset);
65 ll->offset = 0;
66}
67
68static void
69logfile_mod_udp_writeline(Logfile * lf, const char *buf, size_t len)
70{
71 l_udp_t *ll = (l_udp_t *) lf->data;
72
73 if (0 == ll->bufsz) {
9d65168e
A
74 /* buffering disabled */
75 logfile_mod_udp_write(lf, buf, len);
76 return;
82b7abe3
AJ
77 }
78 if (ll->offset > 0 && (ll->offset + len + 4) > ll->bufsz)
9d65168e 79 logfile_mod_udp_flush(lf);
82b7abe3
AJ
80
81 if (len > ll->bufsz) {
9d65168e
A
82 /* too big to fit in buffer */
83 logfile_mod_udp_write(lf, buf, len);
84 return;
82b7abe3
AJ
85 }
86 /* buffer it */
41d00cd3 87 memcpy(ll->buf + ll->offset, buf, len);
82b7abe3
AJ
88
89 ll->offset += len;
90
91 assert(ll->offset >= 0);
92
93 assert((size_t) ll->offset <= ll->bufsz);
94}
95
96static void
97logfile_mod_udp_linestart(Logfile * lf)
98{
99}
100
101static void
102logfile_mod_udp_lineend(Logfile * lf)
103{
104}
105
106static void
107logfile_mod_udp_rotate(Logfile * lf)
108{
109 return;
110}
111
112static void
113logfile_mod_udp_close(Logfile * lf)
114{
115 l_udp_t *ll = (l_udp_t *) lf->data;
116 lf->f_flush(lf);
117
118 if (ll->fd >= 0)
9d65168e 119 file_close(ll->fd);
82b7abe3
AJ
120
121 if (ll->buf)
9d65168e 122 xfree(ll->buf);
82b7abe3
AJ
123
124 xfree(lf->data);
125 lf->data = NULL;
126}
127
82b7abe3
AJ
128/*
129 * This code expects the path to be //host:port
130 */
131int
132logfile_mod_udp_open(Logfile * lf, const char *path, size_t bufsz, int fatal_flag)
133{
b7ac5457 134 Ip::Address addr;
82b7abe3
AJ
135 char *strAddr;
136
137 lf->f_close = logfile_mod_udp_close;
138 lf->f_linewrite = logfile_mod_udp_writeline;
139 lf->f_linestart = logfile_mod_udp_linestart;
140 lf->f_lineend = logfile_mod_udp_lineend;
141 lf->f_flush = logfile_mod_udp_flush;
142 lf->f_rotate = logfile_mod_udp_rotate;
143
144 l_udp_t *ll = static_cast<l_udp_t*>(xcalloc(1, sizeof(*ll)));
145 lf->data = ll;
146
147 if (strncmp(path, "//", 2) == 0) {
9d65168e 148 path += 2;
82b7abe3
AJ
149 }
150 strAddr = xstrdup(path);
151 if (!GetHostWithPort(strAddr, &addr)) {
9d65168e
A
152 if (lf->flags.fatal) {
153 fatalf("Invalid UDP logging address '%s'\n", lf->path);
154 } else {
155 debugs(50, DBG_IMPORTANT, "Invalid UDP logging address '" << lf->path << "'");
156 safe_free(strAddr);
157 return FALSE;
158 }
82b7abe3
AJ
159 }
160 safe_free(strAddr);
161
b7ac5457 162 Ip::Address any_addr;
4dd643d5 163 any_addr.setAnyAddr();
82b7abe3 164
82b7abe3 165 // require the sending UDP port to be of the right family for the destination address.
4dd643d5
AJ
166 if (addr.isIPv4())
167 any_addr.setIPv4();
82b7abe3 168
d938215c 169 ll->fd = comm_open(SOCK_DGRAM, IPPROTO_UDP, any_addr, COMM_NONBLOCKING, "UDP log socket");
82b7abe3 170 if (ll->fd < 0) {
9d65168e
A
171 if (lf->flags.fatal) {
172 fatalf("Unable to open UDP socket for logging\n");
173 } else {
174 debugs(50, DBG_IMPORTANT, "Unable to open UDP socket for logging");
175 return FALSE;
176 }
db772b66 177 } else if (!comm_connect_addr(ll->fd, addr)) {
9d65168e
A
178 if (lf->flags.fatal) {
179 fatalf("Unable to connect to %s for UDP log: %s\n", lf->path, xstrerror());
180 } else {
181 debugs(50, DBG_IMPORTANT, "Unable to connect to " << lf->path << " for UDP log: " << xstrerror());
182 return FALSE;
183 }
82b7abe3
AJ
184 }
185 if (ll->fd == -1) {
9d65168e
A
186 if (ENOENT == errno && fatal_flag) {
187 fatalf("Cannot open '%s' because\n"
188 "\tthe parent directory does not exist.\n"
189 "\tPlease create the directory.\n", path);
190 } else if (EACCES == errno && fatal_flag) {
191 fatalf("Cannot open '%s' for writing.\n"
192 "\tThe parent directory must be writeable by the\n"
193 "\tuser '%s', which is the cache_effective_user\n"
194 "\tset in squid.conf.", path, Config.effectiveUser);
195 } else {
196 debugs(50, DBG_IMPORTANT, "logfileOpen (UDP): " << lf->path << ": " << xstrerror());
197 return 0;
198 }
82b7abe3
AJ
199 }
200 /* Force buffer size to something roughly fitting inside an MTU */
201 /*
202 * XXX note the receive side needs to receive the whole packet at once;
203 * applications like netcat have a small default receive buffer and will
204 * truncate!
205 */
206 bufsz = 1400;
207 if (bufsz > 0) {
9d65168e
A
208 ll->buf = static_cast<char*>(xmalloc(bufsz));
209 ll->bufsz = bufsz;
82b7abe3
AJ
210 }
211
212 return 1;
213}
f53969cc 214