]> git.proxmox.com Git - mirror_frr.git/blame - ldpd/control.c
mgmtd: Add note to SETCFG_REQ and debug logging
[mirror_frr.git] / ldpd / control.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: ISC
8429abe0
RW
2/* $OpenBSD$ */
3
4/*
5 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
8429abe0
RW
6 */
7
eac6e3f0 8#include <zebra.h>
8429abe0 9#include <sys/un.h>
8429abe0
RW
10
11#include "ldpd.h"
12#include "ldpe.h"
13#include "log.h"
14#include "control.h"
15
16#define CONTROL_BACKLOG 5
17
e6685141 18static void control_accept(struct event *);
8429abe0
RW
19static struct ctl_conn *control_connbyfd(int);
20static struct ctl_conn *control_connbypid(pid_t);
21static void control_close(int);
e6685141 22static void control_dispatch_imsg(struct event *);
8429abe0
RW
23
24struct ctl_conns ctl_conns;
25
26static int control_fd;
27
28int
274f5abf 29control_init(char *path)
8429abe0 30{
e30090a6 31 struct sockaddr_un s_un;
8429abe0
RW
32 int fd;
33 mode_t old_umask;
34
eac6e3f0 35 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
8429abe0
RW
36 log_warn("%s: socket", __func__);
37 return (-1);
38 }
eac6e3f0 39 sock_set_nonblock(fd);
8429abe0 40
e30090a6
RW
41 memset(&s_un, 0, sizeof(s_un));
42 s_un.sun_family = AF_UNIX;
274f5abf 43 strlcpy(s_un.sun_path, path, sizeof(s_un.sun_path));
8429abe0 44
274f5abf 45 if (unlink(path) == -1)
8429abe0 46 if (errno != ENOENT) {
274f5abf 47 log_warn("%s: unlink %s", __func__, path);
8429abe0
RW
48 close(fd);
49 return (-1);
50 }
51
52 old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH);
e30090a6 53 if (bind(fd, (struct sockaddr *)&s_un, sizeof(s_un)) == -1) {
274f5abf 54 log_warn("%s: bind: %s", __func__, path);
8429abe0
RW
55 close(fd);
56 umask(old_umask);
57 return (-1);
58 }
59 umask(old_umask);
60
274f5abf 61 if (chmod(path, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) == -1) {
8429abe0
RW
62 log_warn("%s: chmod", __func__);
63 close(fd);
274f5abf 64 (void)unlink(path);
8429abe0
RW
65 return (-1);
66 }
67
68 control_fd = fd;
69
70 return (0);
71}
72
73int
74control_listen(void)
75{
76 if (listen(control_fd, CONTROL_BACKLOG) == -1) {
77 log_warn("%s: listen", __func__);
78 return (-1);
79 }
80
81 return (accept_add(control_fd, control_accept, NULL));
82}
83
84void
274f5abf 85control_cleanup(char *path)
8429abe0
RW
86{
87 accept_del(control_fd);
88 close(control_fd);
274f5abf 89 unlink(path);
8429abe0
RW
90}
91
92/* ARGSUSED */
e6685141 93static void control_accept(struct event *thread)
8429abe0
RW
94{
95 int connfd;
96 socklen_t len;
e30090a6 97 struct sockaddr_un s_un;
8429abe0
RW
98 struct ctl_conn *c;
99
e30090a6 100 len = sizeof(s_un);
e16d030c
DS
101 if ((connfd = accept(EVENT_FD(thread), (struct sockaddr *)&s_un,
102 &len)) == -1) {
8429abe0
RW
103 /*
104 * Pause accept if we are out of file descriptors, or
105 * libevent will haunt us here too.
106 */
107 if (errno == ENFILE || errno == EMFILE)
108 accept_pause();
109 else if (errno != EWOULDBLOCK && errno != EINTR &&
110 errno != ECONNABORTED)
eac6e3f0 111 log_warn("%s: accept", __func__);
cc9f21da 112 return;
8429abe0 113 }
eac6e3f0 114 sock_set_nonblock(connfd);
8429abe0
RW
115
116 if ((c = calloc(1, sizeof(struct ctl_conn))) == NULL) {
117 log_warn(__func__);
118 close(connfd);
cc9f21da 119 return;
8429abe0
RW
120 }
121
122 imsg_init(&c->iev.ibuf, connfd);
eac6e3f0 123 c->iev.handler_read = control_dispatch_imsg;
66e78ae6 124 c->iev.ev_read = NULL;
907a2395
DS
125 event_add_read(master, c->iev.handler_read, &c->iev, c->iev.ibuf.fd,
126 &c->iev.ev_read);
eac6e3f0
RW
127 c->iev.handler_write = ldp_write_handler;
128 c->iev.ev_write = NULL;
8429abe0
RW
129
130 TAILQ_INSERT_TAIL(&ctl_conns, c, entry);
131}
132
133static struct ctl_conn *
134control_connbyfd(int fd)
135{
136 struct ctl_conn *c;
137
b53f7b86
RW
138 TAILQ_FOREACH(c, &ctl_conns, entry) {
139 if (c->iev.ibuf.fd == fd)
140 break;
141 }
8429abe0
RW
142
143 return (c);
144}
145
146static struct ctl_conn *
147control_connbypid(pid_t pid)
148{
149 struct ctl_conn *c;
150
b53f7b86
RW
151 TAILQ_FOREACH(c, &ctl_conns, entry) {
152 if (c->iev.ibuf.pid == pid)
153 break;
154 }
8429abe0
RW
155
156 return (c);
157}
158
159static void
160control_close(int fd)
161{
162 struct ctl_conn *c;
163
164 if ((c = control_connbyfd(fd)) == NULL) {
165 log_warnx("%s: fd %d: not found", __func__, fd);
166 return;
167 }
168
169 msgbuf_clear(&c->iev.ibuf.w);
170 TAILQ_REMOVE(&ctl_conns, c, entry);
171
e16d030c
DS
172 EVENT_OFF(c->iev.ev_read);
173 EVENT_OFF(c->iev.ev_write);
8429abe0
RW
174 close(c->iev.ibuf.fd);
175 accept_unpause();
176 free(c);
177}
178
179/* ARGSUSED */
e6685141 180static void control_dispatch_imsg(struct event *thread)
8429abe0 181{
e16d030c 182 int fd = EVENT_FD(thread);
8429abe0
RW
183 struct ctl_conn *c;
184 struct imsg imsg;
185 ssize_t n;
186 unsigned int ifidx;
8429abe0
RW
187
188 if ((c = control_connbyfd(fd)) == NULL) {
189 log_warnx("%s: fd %d: not found", __func__, fd);
cc9f21da 190 return;
8429abe0
RW
191 }
192
eac6e3f0
RW
193 c->iev.ev_read = NULL;
194
195 if (((n = imsg_read(&c->iev.ibuf)) == -1 && errno != EAGAIN) ||
196 n == 0) {
197 control_close(fd);
cc9f21da 198 return;
8429abe0
RW
199 }
200
201 for (;;) {
202 if ((n = imsg_get(&c->iev.ibuf, &imsg)) == -1) {
203 control_close(fd);
cc9f21da 204 return;
8429abe0
RW
205 }
206
207 if (n == 0)
208 break;
209
210 switch (imsg.hdr.type) {
211 case IMSG_CTL_FIB_COUPLE:
212 case IMSG_CTL_FIB_DECOUPLE:
213 case IMSG_CTL_RELOAD:
8429abe0
RW
214 case IMSG_CTL_KROUTE:
215 case IMSG_CTL_KROUTE_ADDR:
216 case IMSG_CTL_IFINFO:
eac6e3f0 217 /* ignore */
8429abe0
RW
218 break;
219 case IMSG_CTL_SHOW_INTERFACE:
220 if (imsg.hdr.len == IMSG_HEADER_SIZE +
221 sizeof(ifidx)) {
222 memcpy(&ifidx, imsg.data, sizeof(ifidx));
223 ldpe_iface_ctl(c, ifidx);
224 imsg_compose_event(&c->iev, IMSG_CTL_END, 0,
225 0, -1, NULL, 0);
226 }
227 break;
228 case IMSG_CTL_SHOW_DISCOVERY:
229 ldpe_adj_ctl(c);
230 break;
bc0eb287
RW
231 case IMSG_CTL_SHOW_DISCOVERY_DTL:
232 ldpe_adj_detail_ctl(c);
233 break;
8429abe0
RW
234 case IMSG_CTL_SHOW_LIB:
235 case IMSG_CTL_SHOW_L2VPN_PW:
236 case IMSG_CTL_SHOW_L2VPN_BINDING:
237 c->iev.ibuf.pid = imsg.hdr.pid;
238 ldpe_imsg_compose_lde(imsg.hdr.type, 0, imsg.hdr.pid,
239 imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
240 break;
241 case IMSG_CTL_SHOW_NBR:
242 ldpe_nbr_ctl(c);
243 break;
244 case IMSG_CTL_CLEAR_NBR:
245 if (imsg.hdr.len != IMSG_HEADER_SIZE +
246 sizeof(struct ctl_nbr))
247 break;
248
249 nbr_clear_ctl(imsg.data);
250 break;
e1894ff7
KS
251 case IMSG_CTL_SHOW_LDP_SYNC:
252 ldpe_ldp_sync_ctl(c);
253 break;
8429abe0 254 case IMSG_CTL_LOG_VERBOSE:
eac6e3f0 255 /* ignore */
8429abe0
RW
256 break;
257 default:
258 log_debug("%s: error handling imsg %d", __func__,
259 imsg.hdr.type);
260 break;
261 }
262 imsg_free(&imsg);
263 }
264
265 imsg_event_add(&c->iev);
266}
267
268int
269control_imsg_relay(struct imsg *imsg)
270{
271 struct ctl_conn *c;
272
273 if ((c = control_connbypid(imsg->hdr.pid)) == NULL)
274 return (0);
275
276 return (imsg_compose_event(&c->iev, imsg->hdr.type, 0, imsg->hdr.pid,
277 -1, imsg->data, imsg->hdr.len - IMSG_HEADER_SIZE));
278}