1 // SPDX-License-Identifier: ISC
5 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
16 #define CONTROL_BACKLOG 5
18 static void control_accept(struct thread
*);
19 static struct ctl_conn
*control_connbyfd(int);
20 static struct ctl_conn
*control_connbypid(pid_t
);
21 static void control_close(int);
22 static void control_dispatch_imsg(struct thread
*);
24 struct ctl_conns ctl_conns
;
26 static int control_fd
;
29 control_init(char *path
)
31 struct sockaddr_un s_un
;
35 if ((fd
= socket(AF_UNIX
, SOCK_STREAM
, 0)) == -1) {
36 log_warn("%s: socket", __func__
);
39 sock_set_nonblock(fd
);
41 memset(&s_un
, 0, sizeof(s_un
));
42 s_un
.sun_family
= AF_UNIX
;
43 strlcpy(s_un
.sun_path
, path
, sizeof(s_un
.sun_path
));
45 if (unlink(path
) == -1)
46 if (errno
!= ENOENT
) {
47 log_warn("%s: unlink %s", __func__
, path
);
52 old_umask
= umask(S_IXUSR
|S_IXGRP
|S_IWOTH
|S_IROTH
|S_IXOTH
);
53 if (bind(fd
, (struct sockaddr
*)&s_un
, sizeof(s_un
)) == -1) {
54 log_warn("%s: bind: %s", __func__
, path
);
61 if (chmod(path
, S_IRUSR
|S_IWUSR
|S_IRGRP
|S_IWGRP
) == -1) {
62 log_warn("%s: chmod", __func__
);
76 if (listen(control_fd
, CONTROL_BACKLOG
) == -1) {
77 log_warn("%s: listen", __func__
);
81 return (accept_add(control_fd
, control_accept
, NULL
));
85 control_cleanup(char *path
)
87 accept_del(control_fd
);
93 static void control_accept(struct thread
*thread
)
97 struct sockaddr_un s_un
;
101 if ((connfd
= accept(THREAD_FD(thread
), (struct sockaddr
*)&s_un
,
104 * Pause accept if we are out of file descriptors, or
105 * libevent will haunt us here too.
107 if (errno
== ENFILE
|| errno
== EMFILE
)
109 else if (errno
!= EWOULDBLOCK
&& errno
!= EINTR
&&
110 errno
!= ECONNABORTED
)
111 log_warn("%s: accept", __func__
);
114 sock_set_nonblock(connfd
);
116 if ((c
= calloc(1, sizeof(struct ctl_conn
))) == NULL
) {
122 imsg_init(&c
->iev
.ibuf
, connfd
);
123 c
->iev
.handler_read
= control_dispatch_imsg
;
124 c
->iev
.ev_read
= NULL
;
125 thread_add_read(master
, c
->iev
.handler_read
, &c
->iev
, c
->iev
.ibuf
.fd
,
127 c
->iev
.handler_write
= ldp_write_handler
;
128 c
->iev
.ev_write
= NULL
;
130 TAILQ_INSERT_TAIL(&ctl_conns
, c
, entry
);
133 static struct ctl_conn
*
134 control_connbyfd(int fd
)
138 TAILQ_FOREACH(c
, &ctl_conns
, entry
) {
139 if (c
->iev
.ibuf
.fd
== fd
)
146 static struct ctl_conn
*
147 control_connbypid(pid_t pid
)
151 TAILQ_FOREACH(c
, &ctl_conns
, entry
) {
152 if (c
->iev
.ibuf
.pid
== pid
)
160 control_close(int fd
)
164 if ((c
= control_connbyfd(fd
)) == NULL
) {
165 log_warnx("%s: fd %d: not found", __func__
, fd
);
169 msgbuf_clear(&c
->iev
.ibuf
.w
);
170 TAILQ_REMOVE(&ctl_conns
, c
, entry
);
172 THREAD_OFF(c
->iev
.ev_read
);
173 THREAD_OFF(c
->iev
.ev_write
);
174 close(c
->iev
.ibuf
.fd
);
180 static void control_dispatch_imsg(struct thread
*thread
)
182 int fd
= THREAD_FD(thread
);
188 if ((c
= control_connbyfd(fd
)) == NULL
) {
189 log_warnx("%s: fd %d: not found", __func__
, fd
);
193 c
->iev
.ev_read
= NULL
;
195 if (((n
= imsg_read(&c
->iev
.ibuf
)) == -1 && errno
!= EAGAIN
) ||
202 if ((n
= imsg_get(&c
->iev
.ibuf
, &imsg
)) == -1) {
210 switch (imsg
.hdr
.type
) {
211 case IMSG_CTL_FIB_COUPLE
:
212 case IMSG_CTL_FIB_DECOUPLE
:
213 case IMSG_CTL_RELOAD
:
214 case IMSG_CTL_KROUTE
:
215 case IMSG_CTL_KROUTE_ADDR
:
216 case IMSG_CTL_IFINFO
:
219 case IMSG_CTL_SHOW_INTERFACE
:
220 if (imsg
.hdr
.len
== IMSG_HEADER_SIZE
+
222 memcpy(&ifidx
, imsg
.data
, sizeof(ifidx
));
223 ldpe_iface_ctl(c
, ifidx
);
224 imsg_compose_event(&c
->iev
, IMSG_CTL_END
, 0,
228 case IMSG_CTL_SHOW_DISCOVERY
:
231 case IMSG_CTL_SHOW_DISCOVERY_DTL
:
232 ldpe_adj_detail_ctl(c
);
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
);
241 case IMSG_CTL_SHOW_NBR
:
244 case IMSG_CTL_CLEAR_NBR
:
245 if (imsg
.hdr
.len
!= IMSG_HEADER_SIZE
+
246 sizeof(struct ctl_nbr
))
249 nbr_clear_ctl(imsg
.data
);
251 case IMSG_CTL_SHOW_LDP_SYNC
:
252 ldpe_ldp_sync_ctl(c
);
254 case IMSG_CTL_LOG_VERBOSE
:
258 log_debug("%s: error handling imsg %d", __func__
,
265 imsg_event_add(&c
->iev
);
269 control_imsg_relay(struct imsg
*imsg
)
273 if ((c
= control_connbypid(imsg
->hdr
.pid
)) == NULL
)
276 return (imsg_compose_event(&c
->iev
, imsg
->hdr
.type
, 0, imsg
->hdr
.pid
,
277 -1, imsg
->data
, imsg
->hdr
.len
- IMSG_HEADER_SIZE
));