"Fossies" - the Fresh Open Source Software Archive 
Member "ospfd/control.c" (6 Jun 2009, 6670 Bytes) of package /linux/privat/old/openospfd-4.6.tgz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "control.c" see the
Fossies "Dox" file reference documentation.
1 /* $OpenBSD: control.c,v 1.27 2009/06/06 07:31:26 eric Exp $ */
2
3 /*
4 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <sys/socket.h>
22 #include <sys/un.h>
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28
29 #include "ospfd.h"
30 #include "ospf.h"
31 #include "ospfe.h"
32 #include "log.h"
33 #include "control.h"
34
35 #define CONTROL_BACKLOG 5
36
37 int control_imsg_relay(struct imsg *imsg);
38
39 struct ctl_conn *control_connbyfd(int);
40 struct ctl_conn *control_connbypid(pid_t);
41 void control_close(int);
42
43 int
44 control_init(char *path)
45 {
46 struct sockaddr_un sun;
47 int fd;
48 mode_t old_umask;
49
50 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
51 log_warn("control_init: socket");
52 return (-1);
53 }
54
55 bzero(&sun, sizeof(sun));
56 sun.sun_family = AF_UNIX;
57 strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
58
59 if (unlink(path) == -1)
60 if (errno != ENOENT) {
61 log_warn("control_init: unlink %s", path);
62 close(fd);
63 return (-1);
64 }
65
66 old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH);
67 if (bind(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
68 log_warn("control_init: bind: %s", path);
69 close(fd);
70 umask(old_umask);
71 return (-1);
72 }
73 umask(old_umask);
74
75 if (chmod(path, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) == -1) {
76 log_warn("control_init: chmod");
77 close(fd);
78 (void)unlink(path);
79 return (-1);
80 }
81
82 session_socket_blockmode(fd, BM_NONBLOCK);
83 control_state.fd = fd;
84
85 return (0);
86 }
87
88 int
89 control_listen(void)
90 {
91
92 if (listen(control_state.fd, CONTROL_BACKLOG) == -1) {
93 log_warn("control_listen: listen");
94 return (-1);
95 }
96
97 event_set(&control_state.ev, control_state.fd, EV_READ | EV_PERSIST,
98 control_accept, NULL);
99 event_add(&control_state.ev, NULL);
100
101 return (0);
102 }
103
104 void
105 control_cleanup(char *path)
106 {
107 if (path)
108 unlink(path);
109 }
110
111 /* ARGSUSED */
112 void
113 control_accept(int listenfd, short event, void *bula)
114 {
115 int connfd;
116 socklen_t len;
117 struct sockaddr_un sun;
118 struct ctl_conn *c;
119
120 len = sizeof(sun);
121 if ((connfd = accept(listenfd,
122 (struct sockaddr *)&sun, &len)) == -1) {
123 if (errno != EWOULDBLOCK && errno != EINTR)
124 log_warn("control_accept");
125 return;
126 }
127
128 session_socket_blockmode(connfd, BM_NONBLOCK);
129
130 if ((c = malloc(sizeof(struct ctl_conn))) == NULL) {
131 log_warn("control_accept");
132 close(connfd);
133 return;
134 }
135
136 imsg_init(&c->iev.ibuf, connfd);
137 c->iev.handler = control_dispatch_imsg;
138 c->iev.events = EV_READ;
139 event_set(&c->iev.ev, c->iev.ibuf.fd, c->iev.events,
140 c->iev.handler, &c->iev);
141 event_add(&c->iev.ev, NULL);
142
143 TAILQ_INSERT_TAIL(&ctl_conns, c, entry);
144 }
145
146 struct ctl_conn *
147 control_connbyfd(int fd)
148 {
149 struct ctl_conn *c;
150
151 for (c = TAILQ_FIRST(&ctl_conns); c != NULL && c->iev.ibuf.fd != fd;
152 c = TAILQ_NEXT(c, entry))
153 ; /* nothing */
154
155 return (c);
156 }
157
158 struct ctl_conn *
159 control_connbypid(pid_t pid)
160 {
161 struct ctl_conn *c;
162
163 for (c = TAILQ_FIRST(&ctl_conns); c != NULL && c->iev.ibuf.pid != pid;
164 c = TAILQ_NEXT(c, entry))
165 ; /* nothing */
166
167 return (c);
168 }
169
170 void
171 control_close(int fd)
172 {
173 struct ctl_conn *c;
174
175 if ((c = control_connbyfd(fd)) == NULL) {
176 log_warn("control_close: fd %d: not found", fd);
177 return;
178 }
179
180 msgbuf_clear(&c->iev.ibuf.w);
181 TAILQ_REMOVE(&ctl_conns, c, entry);
182
183 event_del(&c->iev.ev);
184 close(c->iev.ibuf.fd);
185 free(c);
186 }
187
188 /* ARGSUSED */
189 void
190 control_dispatch_imsg(int fd, short event, void *bula)
191 {
192 struct ctl_conn *c;
193 struct imsg imsg;
194 ssize_t n;
195 unsigned int ifidx;
196
197 if ((c = control_connbyfd(fd)) == NULL) {
198 log_warn("control_dispatch_imsg: fd %d: not found", fd);
199 return;
200 }
201
202 if (event & EV_READ) {
203 if ((n = imsg_read(&c->iev.ibuf)) == -1 || n == 0) {
204 control_close(fd);
205 return;
206 }
207 }
208 if (event & EV_WRITE) {
209 if (msgbuf_write(&c->iev.ibuf.w) == -1) {
210 control_close(fd);
211 return;
212 }
213 }
214
215 for (;;) {
216 if ((n = imsg_get(&c->iev.ibuf, &imsg)) == -1) {
217 control_close(fd);
218 return;
219 }
220
221 if (n == 0)
222 break;
223
224 switch (imsg.hdr.type) {
225 case IMSG_CTL_FIB_COUPLE:
226 case IMSG_CTL_FIB_DECOUPLE:
227 ospfe_fib_update(imsg.hdr.type);
228 /* FALLTHROUGH */
229 case IMSG_CTL_RELOAD:
230 c->iev.ibuf.pid = imsg.hdr.pid;
231 ospfe_imsg_compose_parent(imsg.hdr.type, 0, NULL, 0);
232 break;
233 case IMSG_CTL_KROUTE:
234 case IMSG_CTL_KROUTE_ADDR:
235 case IMSG_CTL_IFINFO:
236 c->iev.ibuf.pid = imsg.hdr.pid;
237 ospfe_imsg_compose_parent(imsg.hdr.type,
238 imsg.hdr.pid, imsg.data,
239 imsg.hdr.len - IMSG_HEADER_SIZE);
240 break;
241 case IMSG_CTL_SHOW_INTERFACE:
242 if (imsg.hdr.len == IMSG_HEADER_SIZE +
243 sizeof(ifidx)) {
244 memcpy(&ifidx, imsg.data, sizeof(ifidx));
245 ospfe_iface_ctl(c, ifidx);
246 imsg_compose_event(&c->iev, IMSG_CTL_END, 0,
247 0, -1, NULL, 0);
248 }
249 break;
250 case IMSG_CTL_SHOW_DATABASE:
251 case IMSG_CTL_SHOW_DB_EXT:
252 case IMSG_CTL_SHOW_DB_NET:
253 case IMSG_CTL_SHOW_DB_RTR:
254 case IMSG_CTL_SHOW_DB_SELF:
255 case IMSG_CTL_SHOW_DB_SUM:
256 case IMSG_CTL_SHOW_DB_ASBR:
257 case IMSG_CTL_SHOW_RIB:
258 case IMSG_CTL_SHOW_SUM:
259 c->iev.ibuf.pid = imsg.hdr.pid;
260 ospfe_imsg_compose_rde(imsg.hdr.type, 0, imsg.hdr.pid,
261 imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
262 break;
263 case IMSG_CTL_SHOW_NBR:
264 ospfe_nbr_ctl(c);
265 break;
266 default:
267 log_debug("control_dispatch_imsg: "
268 "error handling imsg %d", imsg.hdr.type);
269 break;
270 }
271 imsg_free(&imsg);
272 }
273
274 imsg_event_add(&c->iev);
275 }
276
277 int
278 control_imsg_relay(struct imsg *imsg)
279 {
280 struct ctl_conn *c;
281
282 if ((c = control_connbypid(imsg->hdr.pid)) == NULL)
283 return (0);
284
285 return (imsg_compose_event(&c->iev, imsg->hdr.type, 0, imsg->hdr.pid,
286 -1, imsg->data, imsg->hdr.len - IMSG_HEADER_SIZE));
287 }
288
289 void
290 session_socket_blockmode(int fd, enum blockmodes bm)
291 {
292 int flags;
293
294 if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
295 fatal("fcntl F_GETFL");
296
297 if (bm == BM_NONBLOCK)
298 flags |= O_NONBLOCK;
299 else
300 flags &= ~O_NONBLOCK;
301
302 if ((flags = fcntl(fd, F_SETFL, flags)) == -1)
303 fatal("fcntl F_SETFL");
304 }