ModUdp.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 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 
32 typedef struct {
33  int fd;
34  char *buf;
35  size_t bufsz;
36  int offset;
37 } l_udp_t;
38 
39 static void
40 logfile_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) {
48  int xerrno = errno;
49  debugs(1, DBG_IMPORTANT, "logfile (udp): got errno (" << errno << "):" << xstrerr(xerrno));
50  }
51  if (s != len) {
52  debugs(1, DBG_IMPORTANT, "logfile (udp): len=" << len << ", wrote=" << s);
53  }
54 #endif
55 
56  /* We don't worry about network errors for now */
57 }
58 
59 static void
61 {
62  l_udp_t *ll = (l_udp_t *) lf->data;
63  if (0 == ll->offset)
64  return;
65  logfile_mod_udp_write(lf, ll->buf, (size_t) ll->offset);
66  ll->offset = 0;
67 }
68 
69 static void
70 logfile_mod_udp_writeline(Logfile * lf, const char *buf, size_t len)
71 {
72  l_udp_t *ll = (l_udp_t *) lf->data;
73 
74  if (0 == ll->bufsz) {
75  /* buffering disabled */
76  logfile_mod_udp_write(lf, buf, len);
77  return;
78  }
79  if (ll->offset > 0 && (ll->offset + len + 4) > ll->bufsz)
81 
82  if (len > ll->bufsz) {
83  /* too big to fit in buffer */
84  logfile_mod_udp_write(lf, buf, len);
85  return;
86  }
87  /* buffer it */
88  memcpy(ll->buf + ll->offset, buf, len);
89 
90  ll->offset += len;
91 
92  assert(ll->offset >= 0);
93 
94  assert((size_t) ll->offset <= ll->bufsz);
95 }
96 
97 static void
99 {
100 }
101 
102 static void
104 {
105 }
106 
107 static void
109 {
110 }
111 
112 static void
114 {
115  l_udp_t *ll = (l_udp_t *) lf->data;
116  lf->f_flush(lf);
117 
118  if (ll->fd >= 0)
119  file_close(ll->fd);
120 
121  if (ll->buf)
122  xfree(ll->buf);
123 
124  xfree(lf->data);
125  lf->data = NULL;
126 }
127 
128 /*
129  * This code expects the path to be //host:port
130  */
131 int
132 logfile_mod_udp_open(Logfile * lf, const char *path, size_t bufsz, int fatal_flag)
133 {
135  char *strAddr;
136 
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) {
148  path += 2;
149  }
150  strAddr = xstrdup(path);
151  if (!GetHostWithPort(strAddr, &addr)) {
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  }
159  }
160  safe_free(strAddr);
161 
162  Ip::Address any_addr;
163  any_addr.setAnyAddr();
164 
165  // require the sending UDP port to be of the right family for the destination address.
166  if (addr.isIPv4())
167  any_addr.setIPv4();
168 
169  ll->fd = comm_open(SOCK_DGRAM, IPPROTO_UDP, any_addr, COMM_NONBLOCKING, "UDP log socket");
170  int xerrno = errno;
171  if (ll->fd < 0) {
172  if (lf->flags.fatal) {
173  fatalf("Unable to open UDP socket for logging\n");
174  } else {
175  debugs(50, DBG_IMPORTANT, "Unable to open UDP socket for logging");
176  return FALSE;
177  }
178  } else if (!comm_connect_addr(ll->fd, addr)) {
179  xerrno = errno;
180  if (lf->flags.fatal) {
181  fatalf("Unable to connect to %s for UDP log: %s\n", lf->path, xstrerr(xerrno));
182  } else {
183  debugs(50, DBG_IMPORTANT, "Unable to connect to " << lf->path << " for UDP log: " << xstrerr(xerrno));
184  return FALSE;
185  }
186  }
187  if (ll->fd == -1) {
188  if (ENOENT == xerrno && fatal_flag) {
189  fatalf("Cannot open '%s' because\n"
190  "\tthe parent directory does not exist.\n"
191  "\tPlease create the directory.\n", path);
192  } else if (EACCES == xerrno && fatal_flag) {
193  fatalf("Cannot open '%s' for writing.\n"
194  "\tThe parent directory must be writeable by the\n"
195  "\tuser '%s', which is the cache_effective_user\n"
196  "\tset in squid.conf.", path, Config.effectiveUser);
197  } else {
198  debugs(50, DBG_IMPORTANT, "logfileOpen (UDP): " << lf->path << ": " << xstrerr(xerrno));
199  return 0;
200  }
201  }
202  /* Force buffer size to something roughly fitting inside an MTU */
203  /*
204  * XXX note the receive side needs to receive the whole packet at once;
205  * applications like netcat have a small default receive buffer and will
206  * truncate!
207  */
208  bufsz = 1400;
209  if (bufsz > 0) {
210  ll->buf = static_cast<char*>(xmalloc(bufsz));
211  ll->bufsz = bufsz;
212  }
213 
214  return 1;
215 }
216 
bool setIPv4()
Definition: Address.cc:217
LOGFLUSH * f_flush
Definition: File.h:60
char * buf
Definition: ModUdp.cc:34
#define assert(EX)
Definition: assert.h:17
LOGWRITE * f_linewrite
Definition: File.h:58
int comm_connect_addr(int sock, const Ip::Address &address)
Definition: comm.cc:591
int fd
Definition: ModUdp.cc:33
Definition: File.h:38
unsigned int fatal
Definition: File.h:49
#define xcalloc
Definition: membanger.c:57
char * effectiveUser
Definition: SquidConfig.h:185
#define xstrdup
int comm_open(int sock_type, int proto, Ip::Address &addr, int flags, const char *note)
Definition: comm.cc:222
static void logfile_mod_udp_close(Logfile *lf)
Definition: ModUdp.cc:113
#define safe_free(x)
Definition: xalloc.h:73
int offset
Definition: ModUdp.cc:36
Definition: enums.h:24
static void logfile_mod_udp_lineend(Logfile *)
Definition: ModUdp.cc:103
LOGLINEEND * f_lineend
Definition: File.h:59
void fatalf(const char *fmt,...)
Definition: fatal.cc:79
static void logfile_mod_udp_write(Logfile *lf, const char *buf, size_t len)
Definition: ModUdp.cc:40
void fd_bytes(int fd, int len, unsigned int type)
Definition: fd.cc:261
void * data
Definition: File.h:55
char path[MAXPATHLEN]
Definition: File.h:46
const char * xstrerr(int error)
Definition: xstrerror.cc:83
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
#define DBG_IMPORTANT
Definition: Debug.h:45
void * addr
Definition: membanger.c:46
bool isIPv4() const
Definition: Address.cc:151
int unsigned int const char *desc STUB void int len
Definition: stub_fd.cc:20
void const char * buf
Definition: stub_helper.cc:16
static void logfile_mod_udp_linestart(Logfile *)
Definition: ModUdp.cc:98
#define FALSE
Definition: std-includes.h:56
#define xmalloc
LOGLINESTART * f_linestart
Definition: File.h:57
void setAnyAddr()
NOTE: Does NOT clear the Port stored. Ony the Address and Type.
Definition: Address.cc:170
static void logfile_mod_udp_rotate(Logfile *, const int16_t)
Definition: ModUdp.cc:108
struct Logfile::@85 flags
bool GetHostWithPort(char *token, Ip::Address *ipa)
Definition: Parsing.cc:251
int logfile_mod_udp_open(Logfile *lf, const char *path, size_t bufsz, int fatal_flag)
Definition: ModUdp.cc:132
LOGROTATE * f_rotate
Definition: File.h:61
#define COMM_NONBLOCKING
Definition: Connection.h:44
#define xfree
void file_close(int fd)
Definition: fs_io.cc:76
static void logfile_mod_udp_flush(Logfile *lf)
Definition: ModUdp.cc:60
class SquidConfig Config
Definition: SquidConfig.cc:12
#define NULL
Definition: types.h:166
size_t bufsz
Definition: ModUdp.cc:35
static void logfile_mod_udp_writeline(Logfile *lf, const char *buf, size_t len)
Definition: ModUdp.cc:70
LOGCLOSE * f_close
Definition: File.h:62

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors