1 /* $NetBSD: monitor.c,v 1.13 2004/03/28 20:49:22 pooka Exp $ */
2
3 /*-
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Martin Husemann <martin@NetBSD.org>.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include "isdnd.h"
40
41 #ifndef I4B_EXTERNAL_MONITOR
42
43 /*
44 * dummy version of routines needed by config file parser
45 * (config files should be valid with and without external montioring
46 * support compiled into the daemon)
47 */
48
monitor_clear_rights()49 void monitor_clear_rights()
50 { }
51
monitor_start_rights(const char * clientspec)52 int monitor_start_rights(const char *clientspec)
53 { return I4BMAR_OK; }
54
monitor_add_rights(int rights_mask)55 void monitor_add_rights(int rights_mask)
56 { }
57
monitor_fixup_rights()58 void monitor_fixup_rights()
59 { }
60
61 #else
62
63 #include "monitor.h"
64 #include <sys/socket.h>
65 #include <sys/un.h>
66 #ifndef I4B_NOTCPIP_MONITOR
67 #include <netinet/in.h>
68 #include <arpa/inet.h>
69 #include <netdb.h>
70 #endif
71
72
73 static TAILQ_HEAD(rights_q, monitor_rights) rights = TAILQ_HEAD_INITIALIZER(rights);
74
75 static struct monitor_rights * local_rights = NULL; /* entry for local socket */
76
77 /* for each active monitor connection we have one of this: */
78
79 struct monitor_connection {
80 TAILQ_ENTRY(monitor_connection) connections;
81 int sock; /* socket for this connection */
82 int rights; /* active rights for this connection */
83 int events; /* bitmask of events client is interested in */
84 char source[FILENAME_MAX];
85 };
86
87 static TAILQ_HEAD(connections_tq, monitor_connection) connections = TAILQ_HEAD_INITIALIZER(connections);
88
89 /* local prototypes */
90 struct monitor_rights * monitor_next_rights(const struct monitor_rights *r);
91 static int cmp_rights(const struct monitor_rights *pa, const struct monitor_rights *pb);
92 static int monitor_command(struct monitor_connection *con, int fd, int rights);
93 static void cmd_dump_rights(int fd, int rights, u_int8_t *cmd, const char * source);
94 static void cmd_dump_mcons(int fd, int rights, u_int8_t *cmd, const char * source);
95 static void cmd_reread_cfg(int fd, int rights, u_int8_t *cmd, const char * source);
96 static void cmd_hangup(int fd, int rights, u_int8_t *cmd, const char * source);
97 static void monitor_broadcast(int mask, u_int8_t *pkt, size_t bytes);
98 static int anybody(int mask);
99 static void hangup_channel(int controller, int channel, const char *source);
100 static ssize_t sock_read(int fd, void *buf, size_t nbytes);
101 static ssize_t sock_write(int fd, void *buf, size_t nbytes);
102
103 /*
104 * Due to the way we structure config files, the rights for an external
105 * monitor might be stated in multiple steps. First a call to
106 * monitor_start_rights opens an entry. Further (optional) calls to
107 * montior_add_rights assemble additional rights for this "current"
108 * entry. When closing the sys-file section of the config file, the
109 * "current" entry becomes invalid.
110 */
111 static struct monitor_rights * cur_add_entry = NULL;
112
113 /*---------------------------------------------------------------------------
114 * Initialize the monitor server module. This affects only active
115 * connections, the access rights are not modified here!
116 *---------------------------------------------------------------------------*/
117 void
monitor_init(void)118 monitor_init(void)
119 {
120 struct monitor_connection * con;
121 accepted = 0;
122 while ((con = TAILQ_FIRST(&connections)) != NULL)
123 {
124 TAILQ_REMOVE(&connections, con, connections);
125 free(con);
126 }
127 }
128
129 /*---------------------------------------------------------------------------
130 * Prepare for exit
131 *---------------------------------------------------------------------------*/
132 void
monitor_exit(void)133 monitor_exit(void)
134 {
135 struct monitor_connection *c;
136
137 /* Close all open connections. */
138 while((c = TAILQ_FIRST(&connections)) != NULL) {
139 close(c->sock);
140 TAILQ_REMOVE(&connections, c, connections);
141 free(c);
142 }
143 }
144
145 /*---------------------------------------------------------------------------
146 * Initialize access rights. No active connections are affected!
147 *---------------------------------------------------------------------------*/
148 void
monitor_clear_rights(void)149 monitor_clear_rights(void)
150 {
151 struct monitor_rights *r;
152 while ((r = TAILQ_FIRST(&rights)) != NULL) {
153 TAILQ_REMOVE(&rights, r, list);
154 free(r);
155 }
156 cur_add_entry = NULL;
157 local_rights = NULL;
158 }
159
160 /*---------------------------------------------------------------------------
161 * Add an entry to the access lists. The clientspec either is
162 * the name of the local socket or a host- or networkname or
163 * numeric ip/host-bit-len spec.
164 *---------------------------------------------------------------------------*/
165 int
monitor_start_rights(const char * clientspec)166 monitor_start_rights(const char *clientspec)
167 {
168 struct monitor_rights r;
169
170 /* initialize the new rights entry */
171
172 memset(&r, 0, sizeof r);
173
174 /* check clientspec */
175
176 if (*clientspec == '/')
177 {
178 struct sockaddr_un sa;
179
180 /* this is a local socket spec, check if we already have one */
181
182 if (local_rights != NULL)
183 return I4BMAR_DUP;
184
185 /* does it fit in a local socket address? */
186
187 if (strlen(clientspec) > sizeof sa.sun_path)
188 return I4BMAR_LENGTH;
189
190 r.local = 1;
191 strlcpy(r.name, clientspec, sizeof(r.name));
192
193 #ifndef I4B_NOTCPIP_MONITOR
194
195 }
196 else
197 {
198 /* remote entry, parse host/net and cidr */
199
200 struct monitor_rights * rp;
201 char hostname[FILENAME_MAX];
202 char *p;
203
204 p = strchr(clientspec, '/');
205
206 if (!p)
207 {
208 struct hostent *host;
209 u_int32_t hn;
210
211 /* must be a host spec */
212
213 r.mask = ~0;
214 host = gethostbyname(clientspec);
215
216 if (!host)
217 return I4BMAR_NOIP;
218
219 memcpy(&hn, host->h_addr_list[0], sizeof hn);
220 r.net = (u_int32_t)ntohl(hn);
221 }
222 else if (p[1])
223 {
224 /* must be net/cidr spec */
225
226 int l;
227 struct netent *net;
228 u_int32_t s = ~0U;
229 int num = strtol(p+1, NULL, 10);
230
231 if (num < 0 || num > 32)
232 return I4BMAR_CIDR;
233
234 s >>= num;
235 s ^= ~0U;
236 l = p - clientspec;
237
238 if (l >= sizeof hostname)
239 return I4BMAR_LENGTH;
240
241 strncpy(hostname, clientspec, l);
242
243 hostname[l] = '\0';
244
245 net = getnetbyname(hostname);
246
247 if (net == NULL)
248 r.net = (u_int32_t)inet_network(hostname);
249 else
250 r.net = (u_int32_t)net->n_net;
251
252 r.mask = s;
253 r.net &= s;
254 }
255 else
256 {
257 return I4BMAR_CIDR;
258 }
259
260 /* check for duplicate entry */
261
262 for (rp = TAILQ_FIRST(&rights); rp != NULL; rp = TAILQ_NEXT(rp, list))
263 {
264 if (rp->mask == r.mask &&
265 rp->net == r.net &&
266 rp->local == r.local)
267 {
268 return I4BMAR_DUP;
269 }
270 }
271 #endif
272 }
273
274 r.rights = 0;
275
276 /* entry ok, add it to the collection */
277
278 cur_add_entry = malloc(sizeof(r));
279 memcpy(cur_add_entry, &r, sizeof(r));
280 TAILQ_INSERT_TAIL(&rights, cur_add_entry, list);
281
282 if (r.local)
283 local_rights = cur_add_entry;
284
285 DBGL(DL_RCCF, (logit(LL_DBG, "system: monitor = %s", clientspec)));
286
287 return I4BMAR_OK;
288 }
289
290 /*---------------------------------------------------------------------------
291 * Add rights to the currently constructed entry - if any.
292 *---------------------------------------------------------------------------*/
293 void
monitor_add_rights(int rights_mask)294 monitor_add_rights(int rights_mask)
295 {
296 if (cur_add_entry == NULL)
297 return; /* noone under construction */
298
299 cur_add_entry->rights |= rights_mask;
300
301 DBGL(DL_RCCF, (logit(LL_DBG, "system: monitor-access = 0x%x", rights_mask)));
302 }
303
304 /*---------------------------------------------------------------------------
305 * All rights have been added now. Sort the to get most specific
306 * host/net masks first, so we can travel the list and use the first
307 * match for actual rights.
308 *---------------------------------------------------------------------------*/
309 void
monitor_fixup_rights(void)310 monitor_fixup_rights(void)
311 {
312 struct monitor_rights * cur, * test, * next;
313
314 /* no more rights may be added to the current entry */
315
316 cur_add_entry = NULL;
317
318 /* sort the rights */
319 for (next = NULL, cur = TAILQ_FIRST(&rights); cur != NULL; cur = next)
320 {
321 next = TAILQ_NEXT(cur, list);
322 for (test = TAILQ_FIRST(&rights); test != NULL && test != cur; test = TAILQ_NEXT(test, list))
323 {
324 if (cmp_rights(cur, test) > 0) {
325 /* move cur up the list and insert before test */
326 TAILQ_REMOVE(&rights, cur, list);
327 if (test == TAILQ_FIRST(&rights))
328 TAILQ_INSERT_HEAD(&rights, cur, list);
329 else
330 TAILQ_INSERT_BEFORE(test, cur, list);
331 break;
332 }
333 }
334 }
335 }
336
337 /*---------------------------------------------------------------------------
338 * comparator for rights
339 *---------------------------------------------------------------------------*/
340 static int
cmp_rights(const struct monitor_rights * pa,const struct monitor_rights * pb)341 cmp_rights(const struct monitor_rights *pa, const struct monitor_rights *pb)
342 {
343 u_int32_t mask;
344
345 /* local sorts first */
346
347 if (pa->local)
348 return -1;
349
350 /* which is the less specific netmask? */
351
352 mask = pa->mask;
353
354 if ((pb->mask & mask) == 0)
355 mask = pb->mask;
356
357 /* are the entries disjunct? */
358
359 if ((pa->net & mask) != (pb->net & mask))
360 {
361 /* simply compare net part of address */
362 return ((pa->net & mask) < (pb->net & mask)) ? -1 : 1;
363 }
364
365 /* One entry is part of the others net. We already now "mask" is
366 * the netmask of the less specific (i.e. greater) one */
367
368 return (pa->mask == mask) ? 1 : -1;
369 }
370
371 #ifndef I4B_NOTCPIP_MONITOR
372 /*---------------------------------------------------------------------------
373 * Check if access rights for a remote socket are specified and
374 * create this socket. Return -1 otherwise.
375 *---------------------------------------------------------------------------*/
376 int
monitor_create_remote_socket(int portno)377 monitor_create_remote_socket(int portno)
378 {
379 struct sockaddr_in sa;
380 int val;
381 int remotesockfd;
382
383 remotesockfd = socket(AF_INET, SOCK_STREAM, 0);
384
385 if (remotesockfd == -1)
386 {
387 logit(LL_MER, "could not create remote monitor socket: %s", strerror(errno));
388 return(-1);
389 }
390
391 val = 1;
392
393 if (setsockopt(remotesockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof val))
394 {
395 logit(LL_MER, "could not setsockopt: %s", strerror(errno));
396 return(-1);
397 }
398
399 memset(&sa, 0, sizeof sa);
400 sa.sin_len = sizeof sa;
401 sa.sin_family = AF_INET;
402 sa.sin_port = htons(portno);
403 sa.sin_addr.s_addr = htonl(INADDR_ANY);
404
405 if (bind(remotesockfd, (struct sockaddr *)&sa, sizeof sa) == -1)
406 {
407 logit(LL_MER, "could not bind remote monitor socket to port %d: %s", portno, strerror(errno));
408 return(-1);
409 }
410
411 if (listen(remotesockfd, 0))
412 {
413 logit(LL_MER, "could not listen on monitor socket: %s", strerror(errno));
414 return(-1);
415 }
416
417 return(remotesockfd);
418 }
419 #endif
420
421 /*---------------------------------------------------------------------------
422 * Check if access rights for a local socket are specified and
423 * create this socket. Return -1 otherwise.
424 *---------------------------------------------------------------------------*/
425 int
monitor_create_local_socket(void)426 monitor_create_local_socket(void)
427 {
428 int s;
429 struct sockaddr_un sa;
430
431 /* check for a local entry */
432
433 if (local_rights == NULL)
434 return(-1);
435
436 /* create and setup socket */
437
438 s = socket(AF_LOCAL, SOCK_STREAM, 0);
439
440 if (s == -1)
441 {
442 logit(LL_MER, "could not create local monitor socket, errno = %d", errno);
443 return(-1);
444 }
445
446 unlink(local_rights->name);
447
448 memset(&sa, 0, sizeof sa);
449 sa.sun_len = sizeof sa;
450 sa.sun_family = AF_LOCAL;
451 strlcpy(sa.sun_path, local_rights->name, sizeof(sa.sun_path));
452
453 if (bind(s, (struct sockaddr *)&sa, SUN_LEN(&sa)))
454 {
455 logit(LL_MER, "could not bind local monitor socket [%s], errno = %d", local_rights->name, errno);
456 return(-1);
457 }
458
459 chmod(local_rights->name, 0600);
460
461 if (listen(s, 0))
462 {
463 logit(LL_MER, "could not listen on local monitor socket, errno = %d", errno);
464 return(-1);
465 }
466
467 return(s);
468 }
469
470 /*---------------------------------------------------------------------------
471 * Prepare a fd_set for a select call. Add all our local
472 * filedescriptors to the set, increment max_fd if appropriate.
473 *---------------------------------------------------------------------------*/
474 void
monitor_prepselect(fd_set * selset,int * max_fd)475 monitor_prepselect(fd_set *selset, int *max_fd)
476 {
477 struct monitor_connection * con;
478
479 for (con = TAILQ_FIRST(&connections); con != NULL; con = TAILQ_NEXT(con, connections))
480 {
481 int fd = con->sock;
482
483 if (fd > *max_fd)
484 *max_fd = fd;
485
486 FD_SET(fd, selset);
487 }
488 }
489
490 /*---------------------------------------------------------------------------
491 * Check if the result from a select call indicates something
492 * to do for us.
493 *---------------------------------------------------------------------------*/
494 void
monitor_handle_input(fd_set * selset)495 monitor_handle_input(fd_set *selset)
496 {
497 struct monitor_connection * con, * next;
498
499 for (next = NULL, con = TAILQ_FIRST(&connections); con != NULL; con = next)
500 {
501 int fd = con->sock;
502 next = TAILQ_NEXT(con, connections);
503
504 if (FD_ISSET(fd, selset))
505 {
506 /* handle command from this client */
507
508 if (monitor_command(con, fd, con->rights) != 0)
509 {
510 /* broken or closed connection */
511
512 char source[FILENAME_MAX];
513
514 strlcpy(source, con->source, sizeof(source));
515 TAILQ_REMOVE(&connections, con, connections);
516 free(con);
517 logit(LL_DMN, "monitor closed from %s", source );
518 }
519 }
520 }
521
522 /* all connections gone? */
523
524 if (TAILQ_FIRST(&connections) == NULL)
525 accepted = 0;
526 }
527
528 /*---------------------------------------------------------------------------
529 * Try new incoming connection on the given socket.
530 * Setup client descriptor and send initial data.
531 *---------------------------------------------------------------------------*/
532 void
monitor_handle_connect(int sockfd,int is_local)533 monitor_handle_connect(int sockfd, int is_local)
534 {
535 struct monitor_connection *con;
536 struct monitor_rights *rp;
537 struct isdn_ctrl_state *ctrl;
538 struct cfg_entry *cfe;
539 int n;
540
541 #ifndef I4B_NOTCPIP_MONITOR
542 struct sockaddr_in ia;
543 u_int32_t ha = 0;
544 #endif
545
546 struct sockaddr_un ua;
547 u_int8_t idata[I4B_MON_IDATA_SIZE];
548 int fd = -1, s, r_mask, t_events;
549 char source[FILENAME_MAX];
550
551 /* accept the connection */
552
553 if (is_local)
554 {
555 s = sizeof ua;
556 fd = accept(sockfd, (struct sockaddr *)&ua, &s);
557 strlcpy(source, "local", sizeof(source));
558
559 #ifndef I4B_NOTCPIP_MONITOR
560 }
561 else
562 {
563 struct hostent *hp;
564
565 s = sizeof ia;
566 fd = accept(sockfd, (struct sockaddr *)&ia, &s);
567
568 hp = gethostbyaddr((char *)&ia.sin_addr, 4, AF_INET);
569
570 if (hp == NULL)
571 snprintf(source, sizeof source, "%s (%s)", inet_ntoa(ia.sin_addr), inet_ntoa(ia.sin_addr));
572 else
573 snprintf(source, sizeof source, "%s (%s)", hp->h_name, inet_ntoa(ia.sin_addr));
574
575 memcpy(&ha, &ia.sin_addr.s_addr, sizeof ha);
576
577 ha = ntohl(ha);
578 #endif
579 }
580
581 /* check the access rights of this connection */
582
583 r_mask = 0;
584
585 for (rp = TAILQ_FIRST(&rights); rp != NULL; rp = TAILQ_NEXT(rp, list))
586 {
587 if (rp->local)
588 {
589 if (is_local)
590 {
591 r_mask = rp->rights;
592 break;
593 }
594
595 #ifndef I4B_NOTCPIP_MONITOR
596 }
597 else
598 {
599 if ((ha & rp->mask) == rp->net)
600 {
601 r_mask = rp->rights;
602 break;
603 }
604 #endif
605 }
606 }
607
608 if (r_mask == 0)
609 {
610 /* no rights - go away */
611 logit(LL_MER, "monitor access denied from %s", source);
612 close(fd);
613 return;
614 }
615
616 accepted = 1;
617
618 con = malloc(sizeof(struct monitor_connection));
619 memset(con, 0, sizeof *con);
620 TAILQ_INSERT_TAIL(&connections, con, connections);
621 con->sock = fd;
622 con->rights = r_mask;
623 strlcpy(con->source, source, sizeof(con->source));
624
625 logit(LL_DMN, "monitor opened from %s rights 0x%x", source, r_mask);
626
627 /* send initial data */
628 I4B_PREP_CMD(idata, I4B_MON_IDATA_CODE);
629 I4B_PUT_2B(idata, I4B_MON_IDATA_VERSMAJOR, MPROT_VERSION);
630 I4B_PUT_2B(idata, I4B_MON_IDATA_VERSMINOR, MPROT_REL);
631 n = count_ctrl_states();
632 I4B_PUT_2B(idata, I4B_MON_IDATA_NUMCTRL, n);
633 n = count_cfg_entries();
634 I4B_PUT_2B(idata, I4B_MON_IDATA_NUMENTR, n);
635 I4B_PUT_4B(idata, I4B_MON_IDATA_CLACCESS, r_mask);
636
637 if ((sock_write(fd, idata, sizeof idata)) == -1)
638 {
639 logit(LL_MER, "monitor_handle_connect: sock_write 1 error - %s", strerror(errno));
640 }
641
642 for (ctrl = get_first_ctrl_state(); ctrl; ctrl = NEXT_CTRL(ctrl)) {
643 u_int8_t ictrl[I4B_MON_ICTRL_SIZE];
644 char ctrl_desc[100];
645
646 snprintf(ctrl_desc, sizeof(ctrl_desc), "%s: %s",
647 ctrl->device_name, ctrl->controller);
648
649 I4B_PREP_CMD(ictrl, I4B_MON_ICTRL_CODE);
650 I4B_PUT_STR(ictrl, I4B_MON_ICTRL_NAME, ctrl_desc);
651 I4B_PUT_2B(ictrl, I4B_MON_ICTRL_BUSID, ctrl->isdnif);
652 I4B_PUT_4B(ictrl, I4B_MON_ICTRL_FLAGS, 0);
653 I4B_PUT_2B(ictrl, I4B_MON_ICTRL_NCHAN, 2);
654
655 if ((sock_write(fd, ictrl, sizeof ictrl)) == -1)
656 {
657 logit(LL_MER, "monitor_handle_connect: sock_write 2 error - %s", strerror(errno));
658 }
659
660 }
661
662 /* send device names from entries */
663
664 for (cfe = get_first_cfg_entry(); cfe; cfe = NEXT_CFE(cfe)) {
665 u_int8_t ictrl[I4B_MON_IDEV_SIZE];
666 char nbuf[64];
667
668 snprintf(nbuf, sizeof(nbuf), "%s%d ", cfe->usrdevicename, cfe->usrdeviceunit);
669
670 I4B_PREP_CMD(ictrl, I4B_MON_IDEV_CODE);
671 /*XXX*/ I4B_PUT_2B(ictrl, I4B_MON_IDEV_STATE, 1);
672 I4B_PUT_STR(ictrl, I4B_MON_IDEV_NAME, nbuf);
673
674 if ((sock_write(fd, ictrl, sizeof ictrl)) == -1)
675 {
676 logit(LL_MER, "monitor_handle_connect: sock_write 3 error - %s", strerror(errno));
677 }
678 }
679
680 /*XXX*/ t_events = con->events;
681 /*XXX*/ con->events = -1;
682
683 /* current state of controller(s) */
684
685 for (ctrl = get_first_ctrl_state(); ctrl; ctrl = NEXT_CTRL(ctrl)) {
686 monitor_evnt_tei(ctrl->isdnif, ctrl->tei);
687 monitor_evnt_l12stat(ctrl->isdnif, LAYER_ONE, ctrl->l1stat);
688 monitor_evnt_l12stat(ctrl->isdnif, LAYER_TWO, ctrl->l2stat);
689 }
690
691 /* current state of entries */
692
693 for (cfe = get_first_cfg_entry(); cfe; cfe = NEXT_CFE(cfe)) {
694
695 if (cfe->state == ST_CONNECTED)
696 {
697 monitor_evnt_connect(cfe);
698 monitor_evnt_acct(cfe);
699 monitor_evnt_charge(cfe, cfe->charge, 1);
700 }
701 }
702
703 /*XXX*/ con->events = t_events;
704
705 }
706
707 /*---------------------------------------------------------------------------
708 * dump all monitor rights
709 *---------------------------------------------------------------------------*/
710 static void
cmd_dump_rights(int fd,int r_mask,u_int8_t * cmd,const char * source)711 cmd_dump_rights(int fd, int r_mask, u_int8_t *cmd, const char *source)
712 {
713 struct monitor_rights * r;
714 int num_rights;
715 u_int8_t drini[I4B_MON_DRINI_SIZE];
716 u_int8_t dr[I4B_MON_DR_SIZE];
717
718 for (num_rights = 0, r = TAILQ_FIRST(&rights); r != NULL; r = TAILQ_NEXT(r, list))
719 num_rights++;
720
721 I4B_PREP_EVNT(drini, I4B_MON_DRINI_CODE);
722 I4B_PUT_2B(drini, I4B_MON_DRINI_COUNT, num_rights);
723
724 if ((sock_write(fd, drini, sizeof drini)) == -1)
725 {
726 logit(LL_MER, "cmd_dump_rights: sock_write 1 error - %s", strerror(errno));
727 }
728
729 for (r = TAILQ_FIRST(&rights); r != NULL; r = TAILQ_NEXT(r, list))
730 {
731 I4B_PREP_EVNT(dr, I4B_MON_DR_CODE);
732 I4B_PUT_4B(dr, I4B_MON_DR_RIGHTS, r->rights);
733 I4B_PUT_4B(dr, I4B_MON_DR_NET, r->net);
734 I4B_PUT_4B(dr, I4B_MON_DR_MASK, r->mask);
735 I4B_PUT_1B(dr, I4B_MON_DR_LOCAL, r->local);
736 if ((sock_write(fd, dr, sizeof dr)) == -1)
737 {
738 logit(LL_MER, "cmd_dump_rights: sock_write 2 error - %s", strerror(errno));
739 }
740 }
741 }
742
743 /*---------------------------------------------------------------------------
744 * rescan config file
745 *---------------------------------------------------------------------------*/
746 static void
cmd_reread_cfg(int fd,int rights,u_int8_t * cmd,const char * source)747 cmd_reread_cfg(int fd, int rights, u_int8_t *cmd, const char * source)
748 {
749 rereadconfig(42);
750 }
751
752 /*---------------------------------------------------------------------------
753 * drop one connection
754 *---------------------------------------------------------------------------*/
755 static void
cmd_hangup(int fd,int rights,u_int8_t * cmd,const char * source)756 cmd_hangup(int fd, int rights, u_int8_t *cmd, const char * source)
757 {
758 int channel = I4B_GET_4B(cmd, I4B_MON_HANGUP_CHANNEL);
759 int ctrl = I4B_GET_4B(cmd, I4B_MON_HANGUP_CTRL);
760
761 hangup_channel(ctrl, channel, source);
762 }
763
764 /*---------------------------------------------------------------------------
765 * dump all active monitor connections
766 *---------------------------------------------------------------------------*/
767 static void
cmd_dump_mcons(int fd,int rights,u_int8_t * cmd,const char * source)768 cmd_dump_mcons(int fd, int rights, u_int8_t *cmd, const char * source)
769 {
770 int num_connections;
771 struct monitor_connection *con;
772 u_int8_t dcini[I4B_MON_DCINI_SIZE];
773
774 for (num_connections = 0, con = TAILQ_FIRST(&connections); con != NULL; con = TAILQ_NEXT(con, connections))
775 num_connections++;
776
777 I4B_PREP_EVNT(dcini, I4B_MON_DCINI_CODE);
778 I4B_PUT_2B(dcini, I4B_MON_DCINI_COUNT, num_connections);
779
780 if ((sock_write(fd, dcini, sizeof dcini)) == -1)
781 {
782 logit(LL_MER, "cmd_dump_mcons: sock_write 1 error - %s", strerror(errno));
783 }
784
785 for (con = TAILQ_FIRST(&connections); con != NULL; con = TAILQ_NEXT(con, connections))
786 {
787 #ifndef I4B_NOTCPIP_MONITOR
788 int namelen;
789 struct sockaddr_in name;
790 #endif
791 u_int8_t dc[I4B_MON_DC_SIZE];
792
793 I4B_PREP_EVNT(dc, I4B_MON_DC_CODE);
794 I4B_PUT_4B(dc, I4B_MON_DC_RIGHTS, con->rights);
795
796 #ifndef I4B_NOTCPIP_MONITOR
797 namelen = sizeof name;
798
799 if (getpeername(con->sock, (struct sockaddr*)&name, &namelen) == 0)
800 memcpy(dc+I4B_MON_DC_WHO, &name.sin_addr, sizeof name.sin_addr);
801 #endif
802 if ((sock_write(fd, dc, sizeof dc)) == -1)
803 {
804 logit(LL_MER, "cmd_dump_mcons: sock_write 2 error - %s", strerror(errno));
805 }
806 }
807 }
808
809 /*---------------------------------------------------------------------------
810 * Handle a command from the given socket. The client
811 * has rights as specified in the rights parameter.
812 * Return non-zero if connection is closed.
813 *---------------------------------------------------------------------------*/
814 static int
monitor_command(struct monitor_connection * con,int fd,int rights)815 monitor_command(struct monitor_connection * con, int fd, int rights)
816 {
817 char cmd[I4B_MAX_MON_CLIENT_CMD];
818 u_int code;
819
820 /* command dispatch table */
821 typedef void (*cmd_func_t)(int fd, int rights, u_int8_t *cmd, const char *source);
822
823 static struct {
824 cmd_func_t call; /* function to execute */
825 u_int rights; /* necessary rights */
826 } cmd_tab[] =
827 {
828 /* 0 */ { NULL, 0 },
829 /* 1 */ { cmd_dump_rights, I4B_CA_COMMAND_FULL },
830 /* 2 */ { cmd_dump_mcons, I4B_CA_COMMAND_FULL },
831 /* 3 */ { cmd_reread_cfg, I4B_CA_COMMAND_FULL },
832 /* 4 */ { cmd_hangup, I4B_CA_COMMAND_FULL },
833 };
834 #define NUMCMD (sizeof cmd_tab / sizeof cmd_tab[0])
835
836 int avail, bytes, err;
837
838 /* Network transfer may deliver two or more packets concatenated.
839 * Peek at the header and read only one event at a time... */
840
841 avail = 0;
842 err = ioctl(fd, FIONREAD, &avail);
843
844 if (err == -1 || avail < I4B_MON_CMD_HDR)
845 {
846 if (err == -1 && errno == EINTR)
847 return 0; /* try again later */
848
849 if (err == -1 || avail == 0)
850 {
851 /* logit(LL_MER, "monitor read 0 bytes"); */
852 /* socket closed by peer */
853 close(fd);
854 return 1;
855 }
856 return 0; /* not enough data there yet */
857 }
858
859 bytes = recv(fd, cmd, I4B_MON_CMD_HDR, MSG_PEEK);
860
861 if (bytes < I4B_MON_CMD_HDR)
862 {
863 logit(LL_MER, "monitor read only %d bytes", bytes);
864 return 0; /* errh? something must be wrong... */
865 }
866
867 bytes = I4B_GET_2B(cmd, I4B_MON_CMD_LEN);
868
869 if (bytes >= sizeof cmd)
870 {
871 close(fd);
872 logit(LL_MER, "monitor: garbage on connection");
873 return 1;
874 }
875
876 /* now we know the size, it fits, so lets read it! */
877
878 if (sock_read(fd, cmd, bytes) <= 0)
879 {
880 logit(LL_MER, "monitor: sock_read <= 0");
881 close(fd);
882 return 1;
883 }
884
885 /* decode command */
886 code = I4B_GET_2B(cmd, I4B_MON_CMD);
887
888 /* special case: may modify our connection descriptor, is
889 * beyound all rights checks */
890
891 if (code == I4B_MON_CCMD_SETMASK)
892 {
893 /*XXX*/
894 /*
895 u_int major = I4B_GET_2B(cmd, I4B_MON_ICLIENT_VERMAJOR);
896 u_int minor = I4B_GET_2B(cmd, I4B_MON_ICLIENT_VERMINOR);
897 */
898
899 int events = I4B_GET_4B(cmd, I4B_MON_ICLIENT_EVENTS);
900 con->events = events & rights;
901 return 0;
902 }
903
904 if (code < 0 || code >= NUMCMD)
905 {
906 logit(LL_MER, "illegal command from client, code = %d\n",
907 code);
908 return 0;
909 }
910
911 if (cmd_tab[code].call == NULL)
912 return 0;
913
914 if ((cmd_tab[code].rights & rights) == cmd_tab[code].rights)
915 cmd_tab[code].call(fd, rights, cmd, con->source);
916
917 return 0;
918 }
919
920 /*---------------------------------------------------------------------------
921 * Check if somebody would receive an event with this mask.
922 * We are lazy and try to avoid assembling unneccesary packets.
923 * Return 0 if no one interested, nonzero otherwise.
924 *---------------------------------------------------------------------------*/
925 static int
anybody(int mask)926 anybody(int mask)
927 {
928 struct monitor_connection * con;
929
930 for (con = TAILQ_FIRST(&connections); con != NULL; con = TAILQ_NEXT(con, connections))
931 {
932 if ((con->events & mask) == mask)
933 return 1;
934 }
935 return 0;
936 }
937
938 /*---------------------------------------------------------------------------
939 * exec hangup command
940 *---------------------------------------------------------------------------*/
941 static void
hangup_channel(int controller,int channel,const char * source)942 hangup_channel(int controller, int channel, const char *source)
943 {
944 struct cfg_entry * cep = NULL;
945 struct isdn_ctrl_state * ctrl = NULL;
946 int i;
947
948 ctrl = find_ctrl_state(controller);
949 if (ctrl != NULL) {
950 if (ctrl->state != CTRL_UP)
951 return;
952 for (i = 0; i < ctrl->nbch; i++) {
953 if (ctrl->stateb[i] != CHAN_IDLE) {
954 cep = get_cep_by_cc(controller, i);
955 if (cep != NULL
956 && cep->isdnchannelused == channel
957 && cep->isdncontrollerused == controller)
958 goto found;
959 }
960 }
961 }
962 /* not found */
963 return;
964
965 found:
966 logit(LL_CHD, "%05d %s manual disconnect (remote from %s)", cep->cdid, cep->name, source);
967 cep->hangup = 1;
968 return;
969 }
970
971 /*---------------------------------------------------------------------------
972 * Send an event to every connection interested in this kind of
973 * event
974 *---------------------------------------------------------------------------*/
975 static void
monitor_broadcast(int mask,u_int8_t * pkt,size_t bytes)976 monitor_broadcast(int mask, u_int8_t *pkt, size_t bytes)
977 {
978 struct monitor_connection *con;
979
980 for (con = TAILQ_FIRST(&connections); con != NULL; con = TAILQ_NEXT(con, connections))
981 {
982 if ((con->events & mask) == mask)
983 {
984 int fd = con->sock;
985
986 if ((sock_write(fd, pkt, bytes)) == -1)
987 {
988 logit(LL_MER, "monitor_broadcast: sock_write error - %s", strerror(errno));
989 }
990 }
991 }
992 }
993
994 /*---------------------------------------------------------------------------
995 * Post a logfile event
996 *---------------------------------------------------------------------------*/
997 void
monitor_evnt_log(int prio,const char * what,const char * msg)998 monitor_evnt_log(int prio, const char * what, const char * msg)
999 {
1000 u_int8_t evnt[I4B_MON_LOGEVNT_SIZE];
1001 time_t now;
1002
1003 if (!anybody(I4B_CA_EVNT_I4B))
1004 return;
1005
1006 time(&now);
1007
1008 I4B_PREP_EVNT(evnt, I4B_MON_LOGEVNT_CODE);
1009 I4B_PUT_4B(evnt, I4B_MON_LOGEVNT_TSTAMP, (long)now);
1010 I4B_PUT_4B(evnt, I4B_MON_LOGEVNT_PRIO, prio);
1011 I4B_PUT_STR(evnt, I4B_MON_LOGEVNT_WHAT, what);
1012 I4B_PUT_STR(evnt, I4B_MON_LOGEVNT_MSG, msg);
1013
1014 monitor_broadcast(I4B_CA_EVNT_I4B, evnt, sizeof evnt);
1015 }
1016
1017 /*---------------------------------------------------------------------------
1018 * Post a charging event on the connection described
1019 * by the given config entry.
1020 *---------------------------------------------------------------------------*/
1021 void
monitor_evnt_charge(struct cfg_entry * cep,int units,int estimate)1022 monitor_evnt_charge(struct cfg_entry *cep, int units, int estimate)
1023 {
1024 int mask;
1025 time_t now;
1026 u_int8_t evnt[I4B_MON_CHRG_SIZE];
1027
1028 mask = (cep->direction == DIR_IN) ? I4B_CA_EVNT_CALLIN : I4B_CA_EVNT_CALLOUT;
1029
1030 if (!anybody(mask))
1031 return;
1032
1033 time(&now);
1034
1035 I4B_PREP_EVNT(evnt, I4B_MON_CHRG_CODE);
1036 I4B_PUT_4B(evnt, I4B_MON_CHRG_TSTAMP, (long)now);
1037 I4B_PUT_4B(evnt, I4B_MON_CHRG_CTRL, cep->isdncontrollerused);
1038 I4B_PUT_4B(evnt, I4B_MON_CHRG_CHANNEL, cep->isdnchannelused);
1039 I4B_PUT_4B(evnt, I4B_MON_CHRG_UNITS, units);
1040 I4B_PUT_4B(evnt, I4B_MON_CHRG_ESTIMATED, estimate ? 1 : 0);
1041
1042 monitor_broadcast(mask, evnt, sizeof evnt);
1043 }
1044
1045 /*---------------------------------------------------------------------------
1046 * Post a connection event
1047 *---------------------------------------------------------------------------*/
1048 void
monitor_evnt_connect(struct cfg_entry * cep)1049 monitor_evnt_connect(struct cfg_entry *cep)
1050 {
1051 u_int8_t evnt[I4B_MON_CONNECT_SIZE];
1052 char devname[I4B_MAX_MON_STRING];
1053 int mask;
1054 time_t now;
1055
1056 mask = (cep->direction == DIR_IN) ? I4B_CA_EVNT_CALLIN : I4B_CA_EVNT_CALLOUT;
1057
1058 if (!anybody(mask))
1059 return;
1060
1061 time(&now);
1062
1063 snprintf(devname, sizeof devname, "%s%d", cep->usrdevicename, cep->usrdeviceunit);
1064
1065 I4B_PREP_EVNT(evnt, I4B_MON_CONNECT_CODE);
1066 I4B_PUT_4B(evnt, I4B_MON_CONNECT_TSTAMP, (long)now);
1067 I4B_PUT_4B(evnt, I4B_MON_CONNECT_DIR, cep->direction == DIR_OUT ? 1 : 0);
1068 I4B_PUT_4B(evnt, I4B_MON_CONNECT_CTRL, cep->isdncontrollerused);
1069 I4B_PUT_4B(evnt, I4B_MON_CONNECT_CHANNEL, cep->isdnchannelused);
1070 I4B_PUT_STR(evnt, I4B_MON_CONNECT_CFGNAME, cep->name);
1071 I4B_PUT_STR(evnt, I4B_MON_CONNECT_DEVNAME, devname);
1072
1073 if (cep->direction == DIR_OUT)
1074 {
1075 I4B_PUT_STR(evnt, I4B_MON_CONNECT_REMPHONE, cep->remote_phone_dialout);
1076 I4B_PUT_STR(evnt, I4B_MON_CONNECT_LOCPHONE, cep->local_phone_dialout);
1077 }
1078 else
1079 {
1080 I4B_PUT_STR(evnt, I4B_MON_CONNECT_REMPHONE, cep->real_phone_incoming);
1081 I4B_PUT_STR(evnt, I4B_MON_CONNECT_LOCPHONE, cep->local_phone_incoming);
1082 }
1083 monitor_broadcast(mask, evnt, sizeof evnt);
1084 }
1085
1086 /*---------------------------------------------------------------------------
1087 * Post a disconnect event
1088 *---------------------------------------------------------------------------*/
1089 void
monitor_evnt_disconnect(struct cfg_entry * cep)1090 monitor_evnt_disconnect(struct cfg_entry *cep)
1091 {
1092 u_int8_t evnt[I4B_MON_DISCONNECT_SIZE];
1093 int mask;
1094 time_t now;
1095
1096 mask = (cep->direction == DIR_IN) ? I4B_CA_EVNT_CALLIN : I4B_CA_EVNT_CALLOUT;
1097
1098 if (!anybody(mask))
1099 return;
1100
1101 time(&now);
1102
1103 I4B_PREP_EVNT(evnt, I4B_MON_DISCONNECT_CODE);
1104 I4B_PUT_4B(evnt, I4B_MON_DISCONNECT_TSTAMP, (long)now);
1105 I4B_PUT_4B(evnt, I4B_MON_DISCONNECT_CTRL, cep->isdncontrollerused);
1106 I4B_PUT_4B(evnt, I4B_MON_DISCONNECT_CHANNEL, cep->isdnchannelused);
1107
1108 monitor_broadcast(mask, evnt, sizeof evnt);
1109 }
1110
1111 /*---------------------------------------------------------------------------
1112 * Post an up/down event
1113 *---------------------------------------------------------------------------*/
1114 void
monitor_evnt_updown(struct cfg_entry * cep,int up)1115 monitor_evnt_updown(struct cfg_entry *cep, int up)
1116 {
1117 u_int8_t evnt[I4B_MON_UPDOWN_SIZE];
1118 int mask;
1119 time_t now;
1120
1121 mask = (cep->direction == DIR_IN) ? I4B_CA_EVNT_CALLIN : I4B_CA_EVNT_CALLOUT;
1122
1123 if (!anybody(mask))
1124 return;
1125
1126 time(&now);
1127
1128 I4B_PREP_EVNT(evnt, I4B_MON_UPDOWN_CODE);
1129 I4B_PUT_4B(evnt, I4B_MON_UPDOWN_TSTAMP, (long)now);
1130 I4B_PUT_4B(evnt, I4B_MON_UPDOWN_CTRL, cep->isdncontrollerused);
1131 I4B_PUT_4B(evnt, I4B_MON_UPDOWN_CHANNEL, cep->isdnchannelused);
1132 I4B_PUT_4B(evnt, I4B_MON_UPDOWN_ISUP, up);
1133
1134 monitor_broadcast(mask, evnt, sizeof evnt);
1135 }
1136
1137 /*---------------------------------------------------------------------------
1138 * Post a Layer1/2 status change event
1139 *---------------------------------------------------------------------------*/
1140 void
monitor_evnt_l12stat(int controller,int layer,int state)1141 monitor_evnt_l12stat(int controller, int layer, int state)
1142 {
1143 u_int8_t evnt[I4B_MON_L12STAT_SIZE];
1144 time_t now;
1145
1146 if (!anybody(I4B_CA_EVNT_I4B))
1147 return;
1148
1149 time(&now);
1150
1151 I4B_PREP_EVNT(evnt, I4B_MON_L12STAT_CODE);
1152 I4B_PUT_4B(evnt, I4B_MON_L12STAT_TSTAMP, (long)now);
1153 I4B_PUT_4B(evnt, I4B_MON_L12STAT_CTRL, controller);
1154 I4B_PUT_4B(evnt, I4B_MON_L12STAT_LAYER, layer);
1155 I4B_PUT_4B(evnt, I4B_MON_L12STAT_STATE, state);
1156
1157 monitor_broadcast(I4B_CA_EVNT_I4B, evnt, sizeof evnt);
1158 }
1159
1160 /*---------------------------------------------------------------------------
1161 * Post a TEI change event
1162 *---------------------------------------------------------------------------*/
1163 void
monitor_evnt_tei(int controller,int tei)1164 monitor_evnt_tei(int controller, int tei)
1165 {
1166 u_int8_t evnt[I4B_MON_TEI_SIZE];
1167 time_t now;
1168
1169 if (!anybody(I4B_CA_EVNT_I4B))
1170 return;
1171
1172 time(&now);
1173
1174 I4B_PREP_EVNT(evnt, I4B_MON_TEI_CODE);
1175 I4B_PUT_4B(evnt, I4B_MON_TEI_TSTAMP, (long)now);
1176 I4B_PUT_4B(evnt, I4B_MON_TEI_CTRL, controller);
1177 I4B_PUT_4B(evnt, I4B_MON_TEI_TEI, tei);
1178
1179 monitor_broadcast(I4B_CA_EVNT_I4B, evnt, sizeof evnt);
1180 }
1181
1182 /*---------------------------------------------------------------------------
1183 * Post an accounting event
1184 *---------------------------------------------------------------------------*/
1185 void
monitor_evnt_acct(struct cfg_entry * cep)1186 monitor_evnt_acct(struct cfg_entry *cep)
1187 {
1188 u_int8_t evnt[I4B_MON_ACCT_SIZE];
1189 time_t now;
1190
1191 if (!anybody(I4B_CA_EVNT_I4B))
1192 return;
1193
1194 time(&now);
1195
1196 I4B_PREP_EVNT(evnt, I4B_MON_ACCT_CODE);
1197 I4B_PUT_4B(evnt, I4B_MON_ACCT_TSTAMP, (long)now);
1198
1199 I4B_PUT_4B(evnt, I4B_MON_ACCT_CTRL, cep->isdncontrollerused);
1200 I4B_PUT_4B(evnt, I4B_MON_ACCT_CHAN, cep->isdnchannelused);
1201 I4B_PUT_4B(evnt, I4B_MON_ACCT_OBYTES, cep->outbytes);
1202 I4B_PUT_4B(evnt, I4B_MON_ACCT_OBPS, cep->outbps);
1203 I4B_PUT_4B(evnt, I4B_MON_ACCT_IBYTES, cep->inbytes);
1204 I4B_PUT_4B(evnt, I4B_MON_ACCT_IBPS, cep->inbps);
1205
1206 monitor_broadcast(I4B_CA_EVNT_I4B, evnt, sizeof evnt);
1207 }
1208
1209 /*---------------------------------------------------------------------------
1210 * read from a socket
1211 *---------------------------------------------------------------------------*/
1212 static ssize_t
sock_read(int fd,void * buf,size_t nbytes)1213 sock_read(int fd, void *buf, size_t nbytes)
1214 {
1215 size_t nleft;
1216 ssize_t nread;
1217 unsigned char *ptr;
1218
1219 ptr = buf;
1220 nleft = nbytes;
1221
1222 while(nleft > 0)
1223 {
1224 if ((nread = read(fd, ptr, nleft)) < 0)
1225 {
1226 if (errno == EINTR)
1227 {
1228 nread = 0;
1229 }
1230 else
1231 {
1232 return(-1);
1233 }
1234 }
1235 else if (nread == 0)
1236 {
1237 break; /* EOF */
1238 }
1239
1240 nleft -= nread;
1241 ptr += nread;
1242 }
1243 return(nbytes - nleft);
1244 }
1245
1246 /*---------------------------------------------------------------------------
1247 * write to a socket
1248 *---------------------------------------------------------------------------*/
1249 static ssize_t
sock_write(int fd,void * buf,size_t nbytes)1250 sock_write(int fd, void *buf, size_t nbytes)
1251 {
1252 size_t nleft;
1253 ssize_t nwritten;
1254 unsigned char *ptr;
1255
1256 ptr = buf;
1257 nleft = nbytes;
1258
1259 while(nleft > 0)
1260 {
1261 if ((nwritten = write(fd, ptr, nleft)) <= 0)
1262 {
1263 if (errno == EINTR)
1264 {
1265 nwritten = 0;
1266 }
1267 else
1268 {
1269 return(-1);
1270 }
1271 }
1272
1273 nleft -= nwritten;
1274 ptr += nwritten;
1275 }
1276 return(nbytes);
1277 }
1278
monitor_next_rights(const struct monitor_rights * r)1279 struct monitor_rights * monitor_next_rights(const struct monitor_rights *r)
1280 {
1281 if (r == NULL)
1282 return TAILQ_FIRST(&rights);
1283 else
1284 return TAILQ_NEXT(r, list);
1285 }
1286
1287 #endif /* I4B_EXTERNAL_MONITOR */
1288