Refactoring: Moved check parameters from unsorted.py to dedicated modules (CMK-1393)
[check_mk.git] / bin / mkeventd_open514.cc
blob1a5ebcf2c7115ec93974e9cbd61e278c71977c53
1 // +------------------------------------------------------------------+
2 // | ____ _ _ __ __ _ __ |
3 // | / ___| |__ ___ ___| | __ | \/ | |/ / |
4 // | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
5 // | | |___| | | | __/ (__| < | | | | . \ |
6 // | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
7 // | |
8 // | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
9 // +------------------------------------------------------------------+
11 // This file is part of Check_MK.
12 // The official homepage is at http://mathias-kettner.de/check_mk.
14 // check_mk is free software; you can redistribute it and/or modify it
15 // under the terms of the GNU General Public License as published by
16 // the Free Software Foundation in version 2. check_mk is distributed
17 // in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
18 // out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
19 // PARTICULAR PURPOSE. See the GNU General Public License for more de-
20 // ails. You should have received a copy of the GNU General Public
21 // License along with GNU Make; see the file COPYING. If not, write
22 // to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
23 // Boston, MA 02110-1301 USA.
25 /* This small helper program is intended to be installed SUID root.
26 Otherwise it is pointless. It creates a UDP socket with port 514.
27 This is a priviledged operation. Then it drops the priviledges,
28 moves that port to file descriptor 3 and executes the mkeventd.
30 That can then simply use filedescriptor 3 and receive syslog
31 messages */
33 #include <netinet/in.h>
34 #include <sys/socket.h>
35 #include <unistd.h>
36 #include <cstdio>
37 #include <cstdlib>
38 #include <cstring>
40 #define SYSLOG_PORT 514
41 #define SNMPTRAP_PORT 162
43 #define PROGRAM "mkeventd"
45 // Example command line:
46 // mkeventd_open514 --syslog --syslog-fd 3 --syslog-tcp --syslog-tcp-fd 4
47 // --snmptrap --snmptrap-fd 5
49 int main(int argc, char **argv) {
50 int do_syslog = 0;
51 int do_syslog_tcp = 0;
52 int do_snmptrap = 0;
54 int syslog_fd = -1;
55 int syslog_tcp_fd = -1;
56 int snmptrap_fd = -1;
58 int i;
60 for (i = 1; i < argc; i++) {
61 if (strcmp(argv[i], "--syslog") == 0) {
62 do_syslog = 1;
63 } else if (strcmp(argv[i], "--syslog-tcp") == 0) {
64 do_syslog_tcp = 1;
65 } else if (strcmp(argv[i], "--snmptrap") == 0) {
66 do_snmptrap = 1;
67 } else if (strcmp(argv[i], "--syslog-fd") == 0) {
68 syslog_fd = atoi(argv[i + 1]);
69 } else if (strcmp(argv[i], "--syslog-tcp-fd") == 0) {
70 syslog_tcp_fd = atoi(argv[i + 1]);
71 } else if (strcmp(argv[i], "--snmptrap-fd") == 0) {
72 snmptrap_fd = atoi(argv[i + 1]);
76 // Syslog via UDP
77 if (do_syslog != 0 && syslog_fd > 0) {
78 // Create socket
79 int syslog_sock;
80 if (0 > (syslog_sock = socket(PF_INET, SOCK_DGRAM, 0))) {
81 perror("Cannot create UDP socket for syslog");
82 exit(1);
85 // set REUSEADDR
86 int optval = 1;
87 if (0 != setsockopt(syslog_sock, SOL_SOCKET, SO_REUSEADDR, &optval,
88 sizeof(optval))) {
89 perror("Cannot set UDP socket for syslog to SO_REUSEADDR");
90 exit(1);
93 // Bind it to the port (this requires priviledges)
94 struct sockaddr_in addr;
95 addr.sin_family = AF_INET;
96 addr.sin_port = htons(SYSLOG_PORT);
97 addr.sin_addr.s_addr = 0;
98 if (0 != bind(syslog_sock, reinterpret_cast<struct sockaddr *>(&addr),
99 sizeof(addr))) {
100 perror(
101 "Cannot bind UDP socket for syslog to port "
102 "(Is SUID bit set on mkeventd_open514? Is \"nosuid\" not set on the filesystem?)");
103 exit(1);
106 // Make sure it is at the correct FD
107 if (syslog_sock != 0 && syslog_sock != syslog_fd) {
108 dup2(syslog_sock, syslog_fd);
109 close(syslog_sock);
113 // Syslog via TCP
114 if (do_syslog_tcp != 0 && syslog_tcp_fd > 0) {
115 // Create socket
116 int syslog_tcp_sock;
117 if (0 > (syslog_tcp_sock = socket(PF_INET, SOCK_STREAM, 0))) {
118 perror("Cannot create TCP socket for syslog-tcp");
119 exit(1);
122 // set REUSEADDR
123 int optval = 1;
124 if (0 != setsockopt(syslog_tcp_sock, SOL_SOCKET, SO_REUSEADDR, &optval,
125 sizeof(optval))) {
126 perror("Cannot set TCP socket for syslog-tcp to SO_REUSEADDR");
127 exit(1);
130 // Bind it to the port (this requires priviledges)
131 struct sockaddr_in addr;
132 addr.sin_family = AF_INET;
133 addr.sin_port = htons(SYSLOG_PORT);
134 addr.sin_addr.s_addr = 0;
135 if (0 != bind(syslog_tcp_sock,
136 reinterpret_cast<struct sockaddr *>(&addr),
137 sizeof(addr))) {
138 perror(
139 "Cannot bind TCP socket for syslog-tcp to port "
140 "(Is SUID bit set on mkeventd_open514? Is \"nosuid\" not set on the filesystem?)");
141 exit(1);
144 // Make sure it is at the correct FD
145 if (syslog_tcp_sock != 0 && syslog_tcp_sock != syslog_tcp_fd) {
146 dup2(syslog_tcp_sock, syslog_tcp_fd);
147 close(syslog_tcp_sock);
151 // SNMP traps
152 if (do_snmptrap != 0 && snmptrap_fd > 0) {
153 // Create socket
154 int snmptrap_sock;
155 if (0 > (snmptrap_sock = socket(PF_INET, SOCK_DGRAM, 0))) {
156 perror("Cannot create UDP socket for snmptrap");
157 exit(1);
160 // set REUSEADDR
161 int optval = 1;
162 if (0 != setsockopt(snmptrap_sock, SOL_SOCKET, SO_REUSEADDR, &optval,
163 sizeof(optval))) {
164 perror("Cannot set UDP socket for snmptrap to SO_REUSEADDR");
165 exit(1);
168 // Bind it to the port (this requires priviledges)
169 struct sockaddr_in addr;
170 addr.sin_family = AF_INET;
171 addr.sin_port = htons(SNMPTRAP_PORT);
172 addr.sin_addr.s_addr = 0;
173 if (0 != bind(snmptrap_sock, reinterpret_cast<struct sockaddr *>(&addr),
174 sizeof(addr))) {
175 perror(
176 "Cannot bind UDP socket for snmptrap to port "
177 "(Is SUID bit set on mkeventd_open514? Is \"nosuid\" not set on the filesystem?)");
178 exit(1);
181 // Make sure it is at the correct FD
182 if (snmptrap_sock != 0 && snmptrap_sock != snmptrap_fd) {
183 dup2(snmptrap_sock, snmptrap_fd);
184 close(snmptrap_sock);
188 // Drop priviledges
189 if (getuid() != geteuid()) {
190 if (0 != seteuid(getuid())) {
191 perror("Cannot drop priviledges");
192 exit(1);
196 // Execute the actual program that needs access to the
197 // socket. We take the path from argv[0]
198 char *last_slash = argv[0];
199 char *scan = argv[0];
200 while (*scan != 0) {
201 if (*scan == '/') {
202 last_slash = scan + 1;
204 scan++;
206 char newpath[512];
207 bzero(&newpath, 512);
208 int len_to_copy = last_slash - argv[0];
209 if (len_to_copy >= 512) {
210 exit(1);
213 memcpy(newpath, argv[0], len_to_copy);
214 strncpy(newpath + len_to_copy, PROGRAM, 511 - len_to_copy);
215 execv(newpath, argv);
216 perror("Cannot execute mkeventd");