• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *          Copyright Andrey Semashev 2007 - 2020.
3  * Distributed under the Boost Software License, Version 1.0.
4  *    (See accompanying file LICENSE_1_0.txt or copy at
5  *          http://www.boost.org/LICENSE_1_0.txt)
6  */
7 /*!
8  * \file   syslog_backend.cpp
9  * \author Andrey Semashev
10  * \date   08.01.2008
11  *
12  * \brief  This header is the Boost.Log library implementation, see the library documentation
13  *         at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
14  */
15 
16 #include <boost/log/detail/config.hpp>
17 
18 #ifndef BOOST_LOG_WITHOUT_SYSLOG
19 
20 #include <ctime>
21 #include <algorithm>
22 #include <stdexcept>
23 #include <boost/limits.hpp>
24 #include <boost/assert.hpp>
25 #include <boost/smart_ptr/weak_ptr.hpp>
26 #include <boost/smart_ptr/shared_ptr.hpp>
27 #include <boost/smart_ptr/make_shared_object.hpp>
28 #include <boost/throw_exception.hpp>
29 #if !defined(BOOST_LOG_NO_ASIO)
30 #include <boost/asio/buffer.hpp>
31 #include <boost/asio/socket_base.hpp>
32 #include <boost/asio/io_context.hpp>
33 #include <boost/asio/ip/udp.hpp>
34 #include <boost/asio/ip/address.hpp>
35 #include <boost/asio/ip/host_name.hpp>
36 #include <boost/asio/ip/resolver_base.hpp>
37 #endif
38 #include <boost/system/error_code.hpp>
39 #include <boost/date_time/c_time.hpp>
40 #include <boost/log/sinks/syslog_backend.hpp>
41 #include <boost/log/sinks/syslog_constants.hpp>
42 #include <boost/log/detail/singleton.hpp>
43 #include <boost/log/detail/snprintf.hpp>
44 #include <boost/log/exceptions.hpp>
45 #if !defined(BOOST_LOG_NO_THREADS)
46 #include <boost/thread/locks.hpp>
47 #include <boost/thread/mutex.hpp>
48 #endif
49 #include "unique_ptr.hpp"
50 
51 #ifdef BOOST_LOG_USE_NATIVE_SYSLOG
52 #include <syslog.h>
53 #endif // BOOST_LOG_USE_NATIVE_SYSLOG
54 
55 #include <boost/log/detail/header.hpp>
56 
57 namespace boost {
58 
59 BOOST_LOG_OPEN_NAMESPACE
60 
61 namespace sinks {
62 
63 namespace syslog {
64 
65     //! The function constructs log record level from an integer
make_level(int lev)66     BOOST_LOG_API level make_level(int lev)
67     {
68         if (BOOST_UNLIKELY(static_cast< unsigned int >(lev) >= 8u))
69             BOOST_THROW_EXCEPTION(std::out_of_range("syslog level value is out of range"));
70         return static_cast< level >(lev);
71     }
72 
73     //! The function constructs log source facility from an integer
make_facility(int fac)74     BOOST_LOG_API facility make_facility(int fac)
75     {
76         if (BOOST_UNLIKELY((static_cast< unsigned int >(fac) & 7u) != 0u
77             || static_cast< unsigned int >(fac) > (23u * 8u)))
78         {
79             BOOST_THROW_EXCEPTION(std::out_of_range("syslog facility code value is out of range"));
80         }
81         return static_cast< facility >(fac);
82     }
83 
84 } // namespace syslog
85 
86 ////////////////////////////////////////////////////////////////////////////////
87 //! Syslog sink backend implementation
88 ////////////////////////////////////////////////////////////////////////////////
89 struct syslog_backend::implementation
90 {
91 #ifdef BOOST_LOG_USE_NATIVE_SYSLOG
92     struct native;
93 #endif // BOOST_LOG_USE_NATIVE_SYSLOG
94 #if !defined(BOOST_LOG_NO_ASIO)
95     struct udp_socket_based;
96 #endif
97 
98     //! Level mapper
99     severity_mapper_type m_LevelMapper;
100 
101     //! Logging facility (portable or native, depending on the backend implementation)
102     const int m_Facility;
103 
104     //! Constructor
implementationboost::sinks::syslog_backend::implementation105     explicit implementation(int facility) :
106         m_Facility(facility)
107     {
108     }
109     //! Virtual destructor
~implementationboost::sinks::syslog_backend::implementation110     virtual ~implementation() {}
111 
112     //! The method sends the formatted message to the syslog host
113     virtual void send(syslog::level lev, string_type const& formatted_message) = 0;
114 };
115 
116 
117 ////////////////////////////////////////////////////////////////////////////////
118 //  Native syslog API support
119 ////////////////////////////////////////////////////////////////////////////////
120 
121 #ifdef BOOST_LOG_USE_NATIVE_SYSLOG
122 
123 BOOST_LOG_ANONYMOUS_NAMESPACE {
124 
125     //! Syslog service initializer (implemented as a weak singleton)
126 #if !defined(BOOST_LOG_NO_THREADS)
127     class native_syslog_initializer :
128         private log::aux::lazy_singleton< native_syslog_initializer, mutex >
129 #else
130     class native_syslog_initializer
131 #endif
132     {
133 #if !defined(BOOST_LOG_NO_THREADS)
134         friend class log::aux::lazy_singleton< native_syslog_initializer, mutex >;
135         typedef log::aux::lazy_singleton< native_syslog_initializer, mutex > mutex_holder;
136 #endif
137 
138     private:
139         /*!
140          * \brief Application identification string
141          *
142          * \note We have to keep it as an immutable member because some syslog implementations (e.g. glibc)
143          *       do not deep-copy the ident string to internal storage when \c openlog is called
144          *       and instead save a pointer to the user-provided string. This means the user-provided
145          *       string needs to remain accessible for the whole duration of logging.
146          *
147          *       https://github.com/boostorg/log/issues/97
148          *       https://sourceware.org/bugzilla/show_bug.cgi?id=25442
149          */
150         const std::string m_Ident;
151 
152     public:
153         native_syslog_initializer(std::string const& ident, int facility) :
154             m_Ident(ident)
155         {
156             ::openlog((m_Ident.empty() ? static_cast< const char* >(NULL) : m_Ident.c_str()), 0, facility);
157         }
158         ~native_syslog_initializer()
159         {
160             ::closelog();
161         }
162 
163         static shared_ptr< native_syslog_initializer > get_instance(std::string const& ident, int facility)
164         {
165 #if !defined(BOOST_LOG_NO_THREADS)
166             lock_guard< mutex > lock(mutex_holder::get());
167 #endif
168             static weak_ptr< native_syslog_initializer > instance;
169             shared_ptr< native_syslog_initializer > p(instance.lock());
170             if (!p)
171             {
172                 p = boost::make_shared< native_syslog_initializer >(ident, facility);
173                 instance = p;
174             }
175             return p;
176         }
177 
178         BOOST_DELETED_FUNCTION(native_syslog_initializer(native_syslog_initializer const&))
179         BOOST_DELETED_FUNCTION(native_syslog_initializer& operator= (native_syslog_initializer const&))
180     };
181 
182 } // namespace
183 
184 struct syslog_backend::implementation::native :
185     public implementation
186 {
187     //! Reference to the syslog service initializer
188     const shared_ptr< native_syslog_initializer > m_pSyslogInitializer;
189 
190     //! Constructor
nativeboost::sinks::syslog_backend::implementation::native191     native(syslog::facility const& fac, std::string const& ident) :
192         implementation(convert_facility(fac)),
193         m_pSyslogInitializer(native_syslog_initializer::get_instance(ident, this->m_Facility))
194     {
195     }
196 
197     //! The method sends the formatted message to the syslog host
sendboost::sinks::syslog_backend::implementation::native198     void send(syslog::level lev, string_type const& formatted_message) BOOST_OVERRIDE
199     {
200         int native_level;
201         switch (lev)
202         {
203         case syslog::emergency:
204             native_level = LOG_EMERG; break;
205         case syslog::alert:
206             native_level = LOG_ALERT; break;
207         case syslog::critical:
208             native_level = LOG_CRIT; break;
209         case syslog::error:
210             native_level = LOG_ERR; break;
211         case syslog::warning:
212             native_level = LOG_WARNING; break;
213         case syslog::notice:
214             native_level = LOG_NOTICE; break;
215         case syslog::debug:
216             native_level = LOG_DEBUG; break;
217         default:
218             native_level = LOG_INFO; break;
219         }
220 
221         ::syslog(this->m_Facility | native_level, "%s", formatted_message.c_str());
222     }
223 
224 private:
225     //! The function converts portable facility codes to the native codes
convert_facilityboost::sinks::syslog_backend::implementation::native226     static int convert_facility(syslog::facility const& fac)
227     {
228         // POSIX does not specify anything except for LOG_USER and LOG_LOCAL*
229         #ifndef LOG_KERN
230         #define LOG_KERN LOG_USER
231         #endif
232         #ifndef LOG_DAEMON
233         #define LOG_DAEMON LOG_KERN
234         #endif
235         #ifndef LOG_MAIL
236         #define LOG_MAIL LOG_USER
237         #endif
238         #ifndef LOG_AUTH
239         #define LOG_AUTH LOG_DAEMON
240         #endif
241         #ifndef LOG_SYSLOG
242         #define LOG_SYSLOG LOG_DAEMON
243         #endif
244         #ifndef LOG_LPR
245         #define LOG_LPR LOG_DAEMON
246         #endif
247         #ifndef LOG_NEWS
248         #define LOG_NEWS LOG_USER
249         #endif
250         #ifndef LOG_UUCP
251         #define LOG_UUCP LOG_USER
252         #endif
253         #ifndef LOG_CRON
254         #define LOG_CRON LOG_DAEMON
255         #endif
256         #ifndef LOG_AUTHPRIV
257         #define LOG_AUTHPRIV LOG_AUTH
258         #endif
259         #ifndef LOG_FTP
260         #define LOG_FTP LOG_DAEMON
261         #endif
262 
263         static const int native_facilities[24] =
264         {
265             LOG_KERN,
266             LOG_USER,
267             LOG_MAIL,
268             LOG_DAEMON,
269             LOG_AUTH,
270             LOG_SYSLOG,
271             LOG_LPR,
272             LOG_NEWS,
273             LOG_UUCP,
274             LOG_CRON,
275             LOG_AUTHPRIV,
276             LOG_FTP,
277 
278             // reserved values
279             LOG_USER,
280             LOG_USER,
281             LOG_USER,
282             LOG_USER,
283 
284             LOG_LOCAL0,
285             LOG_LOCAL1,
286             LOG_LOCAL2,
287             LOG_LOCAL3,
288             LOG_LOCAL4,
289             LOG_LOCAL5,
290             LOG_LOCAL6,
291             LOG_LOCAL7
292         };
293 
294         std::size_t n = static_cast< unsigned int >(fac) / 8u;
295         BOOST_ASSERT(n < sizeof(native_facilities) / sizeof(*native_facilities));
296         return native_facilities[n];
297     }
298 };
299 
300 #endif // BOOST_LOG_USE_NATIVE_SYSLOG
301 
302 
303 ////////////////////////////////////////////////////////////////////////////////
304 //  Socket-based implementation
305 ////////////////////////////////////////////////////////////////////////////////
306 
307 #if !defined(BOOST_LOG_NO_ASIO)
308 
309 BOOST_LOG_ANONYMOUS_NAMESPACE {
310 
311     //! The shared UDP socket
312     struct syslog_udp_socket
313     {
314     private:
315         //! The socket primitive
316         asio::ip::udp::socket m_Socket;
317 
318     public:
319         //! The constructor creates a socket bound to the specified local address and port
320         explicit syslog_udp_socket(asio::io_context& io_ctx, asio::ip::udp const& protocol, asio::ip::udp::endpoint const& local_address) :
321             m_Socket(io_ctx)
322         {
323             m_Socket.open(protocol);
324             m_Socket.set_option(asio::socket_base::reuse_address(true));
325             m_Socket.bind(local_address);
326         }
327         //! The destructor closes the socket
328         ~syslog_udp_socket()
329         {
330             boost::system::error_code ec;
331             m_Socket.shutdown(asio::socket_base::shutdown_both, ec);
332             m_Socket.close(ec);
333         }
334 
335         //! The method sends the syslog message to the specified endpoint
336         void send_message(int pri, const char* local_host_name, asio::ip::udp::endpoint const& target, const char* message);
337 
338         BOOST_DELETED_FUNCTION(syslog_udp_socket(syslog_udp_socket const&))
339         BOOST_DELETED_FUNCTION(syslog_udp_socket& operator= (syslog_udp_socket const&))
340     };
341 
342     //! The class contains the UDP service for syslog sockets to function
343     class syslog_udp_service :
344         public log::aux::lazy_singleton< syslog_udp_service, shared_ptr< syslog_udp_service > >
345     {
346         friend class log::aux::lazy_singleton< syslog_udp_service, shared_ptr< syslog_udp_service > >;
347         typedef log::aux::lazy_singleton< syslog_udp_service, shared_ptr< syslog_udp_service > > base_type;
348 
349     public:
350         //! The IO context instance
351         asio::io_context m_IOContext;
352         //! The local host name to put into log message
353         std::string m_LocalHostName;
354 
355 #if !defined(BOOST_LOG_NO_THREADS)
356         //! A synchronization primitive to protect the host name resolver
357         mutex m_Mutex;
358         //! The resolver is used to acquire connection endpoints
359         asio::ip::udp::resolver m_HostNameResolver;
360 #endif // !defined(BOOST_LOG_NO_THREADS)
361 
362     private:
363         //! Default constructor
364         syslog_udp_service()
365 #if !defined(BOOST_LOG_NO_THREADS)
366             : m_HostNameResolver(m_IOContext)
367 #endif // !defined(BOOST_LOG_NO_THREADS)
368         {
369             boost::system::error_code err;
370             m_LocalHostName = asio::ip::host_name(err);
371         }
372         //! Initializes the singleton instance
373         static void init_instance()
374         {
375             base_type::get_instance().reset(new syslog_udp_service());
376         }
377     };
378 
379     //! The method sends the syslog message to the specified endpoint
380     void syslog_udp_socket::send_message(
381         int pri, const char* local_host_name, asio::ip::udp::endpoint const& target, const char* message)
382     {
383         std::time_t t = std::time(NULL);
384         std::tm ts;
385         std::tm* time_stamp = boost::date_time::c_time::localtime(&t, &ts);
386 
387         // Month will have to be injected separately, as involving locale won't do here
388         static const char months[12][4] =
389         {
390             "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
391         };
392 
393         // The packet size is mandated in RFC3164, plus one for the terminating zero
394         char packet[1025];
395         int n = boost::log::aux::snprintf
396         (
397             packet,
398             sizeof(packet),
399             "<%d>%s %2d %02d:%02d:%02d %s %s",
400             pri,
401             months[time_stamp->tm_mon],
402             time_stamp->tm_mday,
403             time_stamp->tm_hour,
404             time_stamp->tm_min,
405             time_stamp->tm_sec,
406             local_host_name,
407             message
408         );
409         if (BOOST_LIKELY(n > 0))
410         {
411             std::size_t packet_size = static_cast< std::size_t >(n) >= sizeof(packet) ? sizeof(packet) - 1u : static_cast< std::size_t >(n);
412             m_Socket.send_to(asio::buffer(packet, packet_size), target);
413         }
414     }
415 
416 } // namespace
417 
418 struct syslog_backend::implementation::udp_socket_based :
419     public implementation
420 {
421     //! Protocol to be used
422     asio::ip::udp m_Protocol;
423     //! Pointer to the list of sockets
424     shared_ptr< syslog_udp_service > m_pService;
425     //! Pointer to the socket being used
426     log::aux::unique_ptr< syslog_udp_socket > m_pSocket;
427     //! The target host to send packets to
428     asio::ip::udp::endpoint m_TargetHost;
429 
430     //! Constructor
udp_socket_basedboost::sinks::syslog_backend::implementation::udp_socket_based431     explicit udp_socket_based(syslog::facility const& fac, asio::ip::udp const& protocol) :
432         implementation(fac),
433         m_Protocol(protocol),
434         m_pService(syslog_udp_service::get())
435     {
436         if (m_Protocol == asio::ip::udp::v4())
437         {
438             m_TargetHost = asio::ip::udp::endpoint(asio::ip::address_v4(0x7F000001), 514); // 127.0.0.1:514
439         }
440         else
441         {
442             // ::1, port 514
443             asio::ip::address_v6::bytes_type addr;
444             std::fill_n(addr.data(), addr.size() - 1u, static_cast< unsigned char >(0u));
445             addr[addr.size() - 1u] = 1u;
446             m_TargetHost = asio::ip::udp::endpoint(asio::ip::address_v6(addr), 514);
447         }
448     }
449 
450     //! The method sends the formatted message to the syslog host
sendboost::sinks::syslog_backend::implementation::udp_socket_based451     void send(syslog::level lev, string_type const& formatted_message) BOOST_OVERRIDE
452     {
453         if (!m_pSocket.get())
454         {
455             asio::ip::udp::endpoint any_local_address;
456             m_pSocket.reset(new syslog_udp_socket(m_pService->m_IOContext, m_Protocol, any_local_address));
457         }
458 
459         m_pSocket->send_message(
460             this->m_Facility | static_cast< int >(lev),
461             m_pService->m_LocalHostName.c_str(),
462             m_TargetHost,
463             formatted_message.c_str());
464     }
465 };
466 
467 #endif // !defined(BOOST_LOG_NO_ASIO)
468 
469 ////////////////////////////////////////////////////////////////////////////////
470 //  Sink backend implementation
471 ////////////////////////////////////////////////////////////////////////////////
syslog_backend()472 BOOST_LOG_API syslog_backend::syslog_backend()
473 {
474     construct(log::aux::empty_arg_list());
475 }
476 
477 //! Destructor
~syslog_backend()478 BOOST_LOG_API syslog_backend::~syslog_backend()
479 {
480     delete m_pImpl;
481 }
482 
483 //! The method installs the function object that maps application severity levels to Syslog levels
set_severity_mapper(severity_mapper_type const & mapper)484 BOOST_LOG_API void syslog_backend::set_severity_mapper(severity_mapper_type const& mapper)
485 {
486     m_pImpl->m_LevelMapper = mapper;
487 }
488 
489 //! The method writes the message to the sink
consume(record_view const & rec,string_type const & formatted_message)490 BOOST_LOG_API void syslog_backend::consume(record_view const& rec, string_type const& formatted_message)
491 {
492     m_pImpl->send(
493         m_pImpl->m_LevelMapper.empty() ? syslog::info : m_pImpl->m_LevelMapper(rec),
494         formatted_message);
495 }
496 
497 
498 //! The method creates the backend implementation
construct(syslog::facility fac,syslog::impl_types use_impl,ip_versions ip_version,std::string const & ident)499 BOOST_LOG_API void syslog_backend::construct(syslog::facility fac, syslog::impl_types use_impl, ip_versions ip_version, std::string const& ident)
500 {
501 #ifdef BOOST_LOG_USE_NATIVE_SYSLOG
502     if (use_impl == syslog::native)
503     {
504         typedef implementation::native native_impl;
505         m_pImpl = new native_impl(fac, ident);
506         return;
507     }
508 #endif // BOOST_LOG_USE_NATIVE_SYSLOG
509 
510 #if !defined(BOOST_LOG_NO_ASIO)
511     typedef implementation::udp_socket_based udp_socket_based_impl;
512     asio::ip::udp protocol = asio::ip::udp::v4();
513     switch (ip_version)
514     {
515     case v4:
516         break;
517     case v6:
518         protocol = asio::ip::udp::v6();
519         break;
520     default:
521         BOOST_LOG_THROW_DESCR(setup_error, "Incorrect IP version specified");
522     }
523 
524     m_pImpl = new udp_socket_based_impl(fac, protocol);
525 #endif
526 }
527 
528 #if !defined(BOOST_LOG_NO_ASIO)
529 
530 //! The method sets the local address which log records will be sent from.
set_local_address(std::string const & addr,unsigned short port)531 BOOST_LOG_API void syslog_backend::set_local_address(std::string const& addr, unsigned short port)
532 {
533 #if !defined(BOOST_LOG_NO_THREADS)
534     typedef implementation::udp_socket_based udp_socket_based_impl;
535     if (udp_socket_based_impl* impl = dynamic_cast< udp_socket_based_impl* >(m_pImpl))
536     {
537         char service_name[std::numeric_limits< unsigned int >::digits10 + 3];
538         boost::log::aux::snprintf(service_name, sizeof(service_name), "%u", static_cast< unsigned int >(port));
539 
540         asio::ip::udp::endpoint local_address;
541         {
542             lock_guard< mutex > lock(impl->m_pService->m_Mutex);
543             asio::ip::udp::resolver::results_type results = impl->m_pService->m_HostNameResolver.resolve
544             (
545                 impl->m_Protocol,
546                 addr,
547                 service_name,
548                 asio::ip::resolver_base::address_configured | asio::ip::resolver_base::passive
549             );
550 
551             local_address = *results.cbegin();
552         }
553 
554         impl->m_pSocket.reset(new syslog_udp_socket(impl->m_pService->m_IOContext, impl->m_Protocol, local_address));
555     }
556 #else
557     // Boost.ASIO requires threads for the host name resolver,
558     // so without threads we simply assume the string already contains IP address
559     set_local_address(boost::asio::ip::address::from_string(addr), port);
560 #endif // !defined(BOOST_LOG_NO_THREADS)
561 }
562 //! The method sets the local address which log records will be sent from.
set_local_address(boost::asio::ip::address const & addr,unsigned short port)563 BOOST_LOG_API void syslog_backend::set_local_address(boost::asio::ip::address const& addr, unsigned short port)
564 {
565     typedef implementation::udp_socket_based udp_socket_based_impl;
566     if (udp_socket_based_impl* impl = dynamic_cast< udp_socket_based_impl* >(m_pImpl))
567     {
568         if ((impl->m_Protocol == asio::ip::udp::v4() && !addr.is_v4()) || (impl->m_Protocol == asio::ip::udp::v6() && !addr.is_v6()))
569             BOOST_LOG_THROW_DESCR(setup_error, "Incorrect IP version specified in the local address");
570 
571         impl->m_pSocket.reset(new syslog_udp_socket(
572             impl->m_pService->m_IOContext, impl->m_Protocol, asio::ip::udp::endpoint(addr, port)));
573     }
574 }
575 
576 //! The method sets the address of the remote host where log records will be sent to.
set_target_address(std::string const & addr,unsigned short port)577 BOOST_LOG_API void syslog_backend::set_target_address(std::string const& addr, unsigned short port)
578 {
579 #if !defined(BOOST_LOG_NO_THREADS)
580     typedef implementation::udp_socket_based udp_socket_based_impl;
581     if (udp_socket_based_impl* impl = dynamic_cast< udp_socket_based_impl* >(m_pImpl))
582     {
583         char service_name[std::numeric_limits< unsigned int >::digits10 + 3];
584         boost::log::aux::snprintf(service_name, sizeof(service_name), "%u", static_cast< unsigned int >(port));
585 
586         asio::ip::udp::endpoint remote_address;
587         {
588             lock_guard< mutex > lock(impl->m_pService->m_Mutex);
589             asio::ip::udp::resolver::results_type results = impl->m_pService->m_HostNameResolver.resolve
590             (
591                 impl->m_Protocol,
592                 addr,
593                 service_name,
594                 asio::ip::resolver_query_base::address_configured
595             );
596 
597             remote_address = *results.cbegin();
598         }
599 
600         impl->m_TargetHost = remote_address;
601     }
602 #else
603     // Boost.ASIO requires threads for the host name resolver,
604     // so without threads we simply assume the string already contains IP address
605     set_target_address(boost::asio::ip::address::from_string(addr), port);
606 #endif // !defined(BOOST_LOG_NO_THREADS)
607 }
608 //! The method sets the address of the remote host where log records will be sent to.
set_target_address(boost::asio::ip::address const & addr,unsigned short port)609 BOOST_LOG_API void syslog_backend::set_target_address(boost::asio::ip::address const& addr, unsigned short port)
610 {
611     typedef implementation::udp_socket_based udp_socket_based_impl;
612     if (udp_socket_based_impl* impl = dynamic_cast< udp_socket_based_impl* >(m_pImpl))
613     {
614         if ((impl->m_Protocol == asio::ip::udp::v4() && !addr.is_v4()) || (impl->m_Protocol == asio::ip::udp::v6() && !addr.is_v6()))
615             BOOST_LOG_THROW_DESCR(setup_error, "Incorrect IP version specified in the target address");
616 
617         impl->m_TargetHost = asio::ip::udp::endpoint(addr, port);
618     }
619 }
620 
621 #endif // !defined(BOOST_LOG_NO_ASIO)
622 
623 } // namespace sinks
624 
625 BOOST_LOG_CLOSE_NAMESPACE // namespace log
626 
627 } // namespace boost
628 
629 #include <boost/log/detail/footer.hpp>
630 
631 #endif // !defined(BOOST_LOG_WITHOUT_SYSLOG)
632