2 * Copyright (c) 1998,1999 Martin Husemann. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the author nor the names of any co-contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 * 4. Altered versions must be plainly marked as such, and must not be
17 * misrepresented as being the original software and/or documentation.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 *---------------------------------------------------------------------------
33 * i4b daemon - network monitor server module
34 * ------------------------------------------
36 * $Id: monitor.c,v 1.30 2000/10/09 12:53:29 hm Exp $
38 * $FreeBSD: src/usr.sbin/i4b/isdnd/monitor.c,v 1.6.2.2 2001/08/01 17:45:03 obrien Exp $
39 * $DragonFly: src/usr.sbin/i4b/isdnd/monitor.c,v 1.3 2003/11/16 15:17:35 eirikn Exp $
41 * last edit-date: [Mon Dec 13 21:47:44 1999]
43 *---------------------------------------------------------------------------*/
47 #ifndef I4B_EXTERNAL_MONITOR
50 * dummy version of routines needed by config file parser
51 * (config files should be valid with and without external montioring
52 * support compiled into the daemon)
55 void monitor_clear_rights(void)
59 int monitor_start_rights(const char *clientspec)
64 void monitor_add_rights(int rights_mask)
68 void monitor_fixup_rights(void)
75 #include <sys/socket.h>
77 #ifndef I4B_NOTCPIP_MONITOR
78 #include <netinet/in.h>
79 #include <arpa/inet.h>
84 static TAILQ_HEAD(rights_q, monitor_rights) rights = TAILQ_HEAD_INITIALIZER(rights);
86 static struct monitor_rights * local_rights = NULL; /* entry for local socket */
88 /* for each active monitor connection we have one of this: */
90 struct monitor_connection {
91 TAILQ_ENTRY(monitor_connection) connections;
92 int sock; /* socket for this connection */
93 int rights; /* active rights for this connection */
94 int events; /* bitmask of events client is interested in */
95 char source[FILENAME_MAX];
98 static TAILQ_HEAD(connections_tq, monitor_connection) connections = TAILQ_HEAD_INITIALIZER(connections);
100 /* local prototypes */
101 static int cmp_rights(const struct monitor_rights *pa, const struct monitor_rights *pb);
102 static int monitor_command(struct monitor_connection *con, int fd, int rights);
103 static void cmd_dump_rights(int fd, int rights, u_int8_t *cmd, const char * source);
104 static void cmd_dump_mcons(int fd, int rights, u_int8_t *cmd, const char * source);
105 static void cmd_reread_cfg(int fd, int rights, u_int8_t *cmd, const char * source);
106 static void cmd_hangup(int fd, int rights, u_int8_t *cmd, const char * source);
107 static void monitor_broadcast(int mask, u_int8_t *pkt, size_t bytes);
108 static int anybody(int mask);
109 static void hangup_channel(int controller, int channel, const char *source);
110 static ssize_t sock_read(int fd, void *buf, size_t nbytes);
111 static ssize_t sock_write(int fd, void *buf, size_t nbytes);
114 * Due to the way we structure config files, the rights for an external
115 * monitor might be stated in multiple steps. First a call to
116 * monitor_start_rights opens an entry. Further (optional) calls to
117 * montior_add_rights assemble additional rights for this "current"
118 * entry. When closing the sys-file section of the config file, the
119 * "current" entry becomes invalid.
121 static struct monitor_rights * cur_add_entry = NULL;
123 /*---------------------------------------------------------------------------
124 * Initialize the monitor server module. This affects only active
125 * connections, the access rights are not modified here!
126 *---------------------------------------------------------------------------*/
130 struct monitor_connection * con;
132 while ((con = TAILQ_FIRST(&connections)) != NULL)
134 TAILQ_REMOVE(&connections, con, connections);
139 /*---------------------------------------------------------------------------
141 *---------------------------------------------------------------------------*/
145 struct monitor_connection *c;
147 /* Close all open connections. */
148 while((c = TAILQ_FIRST(&connections)) != NULL) {
150 TAILQ_REMOVE(&connections, c, connections);
155 /*---------------------------------------------------------------------------
156 * Initialize access rights. No active connections are affected!
157 *---------------------------------------------------------------------------*/
159 monitor_clear_rights(void)
161 struct monitor_rights *r;
162 while ((r = TAILQ_FIRST(&rights)) != NULL) {
163 TAILQ_REMOVE(&rights, r, list);
166 cur_add_entry = NULL;
170 /*---------------------------------------------------------------------------
171 * Add an entry to the access lists. The clientspec either is
172 * the name of the local socket or a host- or networkname or
173 * numeric ip/host-bit-len spec.
174 *---------------------------------------------------------------------------*/
176 monitor_start_rights(const char *clientspec)
178 struct monitor_rights r;
180 /* initialize the new rights entry */
182 memset(&r, 0, sizeof r);
184 /* check clientspec */
186 if (*clientspec == '/')
188 struct sockaddr_un sa;
190 /* this is a local socket spec, check if we already have one */
192 if (local_rights != NULL)
195 /* does it fit in a local socket address? */
197 if (strlen(clientspec) > sizeof sa.sun_path)
198 return I4BMAR_LENGTH;
201 strcpy(r.name, clientspec);
203 #ifndef I4B_NOTCPIP_MONITOR
208 /* remote entry, parse host/net and cidr */
210 struct monitor_rights * rp;
211 char hostname[FILENAME_MAX];
214 p = strchr(clientspec, '/');
218 struct hostent *host;
221 /* must be a host spec */
224 host = gethostbyname(clientspec);
229 memcpy(&hn, host->h_addr_list[0], sizeof hn);
230 r.net = (u_int32_t)ntohl(hn);
234 /* must be net/cidr spec */
239 int num = strtol(p+1, NULL, 10);
241 if (num < 0 || num > 32)
248 if (l >= sizeof hostname)
249 return I4BMAR_LENGTH;
251 strncpy(hostname, clientspec, l);
255 net = getnetbyname(hostname);
258 r.net = (u_int32_t)inet_network(hostname);
260 r.net = (u_int32_t)net->n_net;
270 /* check for duplicate entry */
272 for (rp = TAILQ_FIRST(&rights); rp != NULL; rp = TAILQ_NEXT(rp, list))
274 if (rp->mask == r.mask &&
276 rp->local == r.local)
286 /* entry ok, add it to the collection */
288 cur_add_entry = malloc(sizeof(r));
289 memcpy(cur_add_entry, &r, sizeof(r));
290 TAILQ_INSERT_TAIL(&rights, cur_add_entry, list);
293 local_rights = cur_add_entry;
295 DBGL(DL_RCCF, (log(LL_DBG, "system: monitor = %s", clientspec)));
300 /*---------------------------------------------------------------------------
301 * Add rights to the currently constructed entry - if any.
302 *---------------------------------------------------------------------------*/
304 monitor_add_rights(int rights_mask)
306 if(cur_add_entry == NULL)
307 return; /* noone under construction */
309 cur_add_entry->rights |= rights_mask;
311 DBGL(DL_RCCF, (log(LL_DBG, "system: monitor-access = 0x%x", rights_mask)));
314 /*---------------------------------------------------------------------------
315 * All rights have been added now. Sort the to get most specific
316 * host/net masks first, so we can travel the list and use the first
317 * match for actual rights.
318 *---------------------------------------------------------------------------*/
320 monitor_fixup_rights(void)
322 struct monitor_rights * cur, * test, * next;
324 /* no more rights may be added to the current entry */
326 cur_add_entry = NULL;
328 /* sort the rights */
329 for (next = NULL, cur = TAILQ_FIRST(&rights); cur != NULL; cur = next)
331 next = TAILQ_NEXT(cur, list);
332 for (test = TAILQ_FIRST(&rights); test != NULL && test != cur; test = TAILQ_NEXT(test, list))
334 if (cmp_rights(cur, test) > 0) {
335 /* move cur up the list and insert before test */
336 TAILQ_REMOVE(&rights, cur, list);
337 if (test == TAILQ_FIRST(&rights))
338 TAILQ_INSERT_HEAD(&rights, cur, list);
340 TAILQ_INSERT_BEFORE(test, cur, list);
347 /*---------------------------------------------------------------------------
348 * comparator for rights
349 *---------------------------------------------------------------------------*/
351 cmp_rights(const struct monitor_rights *pa, const struct monitor_rights *pb)
355 /* local sorts first */
360 /* which is the less specific netmask? */
364 if ((pb->mask & mask) == 0)
367 /* are the entries disjunct? */
369 if ((pa->net & mask) != (pb->net & mask))
371 /* simply compare net part of address */
372 return ((pa->net & mask) < (pb->net & mask)) ? -1 : 1;
375 /* One entry is part of the others net. We already now "mask" is
376 * the netmask of the less specific (i.e. greater) one */
378 return (pa->mask == mask) ? 1 : -1;
381 #ifndef I4B_NOTCPIP_MONITOR
382 /*---------------------------------------------------------------------------
383 * Check if access rights for a remote socket are specified and
384 * create this socket. Return -1 otherwise.
385 *---------------------------------------------------------------------------*/
387 monitor_create_remote_socket(int portno)
389 struct sockaddr_in sa;
393 remotesockfd = socket(AF_INET, SOCK_STREAM, 0);
395 if(remotesockfd == -1)
397 log(LL_MER, "could not create remote monitor socket: %s", strerror(errno));
403 if(setsockopt(remotesockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof val))
405 log(LL_MER, "could not setsockopt: %s", strerror(errno));
409 memset(&sa, 0, sizeof sa);
410 sa.sin_len = sizeof sa;
411 sa.sin_family = AF_INET;
412 sa.sin_port = htons(portno);
413 sa.sin_addr.s_addr = htonl(INADDR_ANY);
415 if(bind(remotesockfd, (struct sockaddr *)&sa, sizeof sa) == -1)
417 log(LL_MER, "could not bind remote monitor socket to port %d: %s", portno, strerror(errno));
421 if(listen(remotesockfd, 0))
423 log(LL_MER, "could not listen on monitor socket: %s", strerror(errno));
427 return(remotesockfd);
431 /*---------------------------------------------------------------------------
432 * Check if access rights for a local socket are specified and
433 * create this socket. Return -1 otherwise.
434 *---------------------------------------------------------------------------*/
436 monitor_create_local_socket(void)
439 struct sockaddr_un sa;
441 /* check for a local entry */
443 if (local_rights == NULL)
446 /* create and setup socket */
448 s = socket(AF_LOCAL, SOCK_STREAM, 0);
452 log(LL_MER, "could not create local monitor socket, errno = %d", errno);
456 unlink(local_rights->name);
458 memset(&sa, 0, sizeof sa);
459 sa.sun_len = sizeof sa;
460 sa.sun_family = AF_LOCAL;
461 strcpy(sa.sun_path, local_rights->name);
463 if (bind(s, (struct sockaddr *)&sa, SUN_LEN(&sa)))
465 log(LL_MER, "could not bind local monitor socket [%s], errno = %d", local_rights->name, errno);
469 chmod(local_rights->name, 0500);
473 log(LL_MER, "could not listen on local monitor socket, errno = %d", errno);
480 /*---------------------------------------------------------------------------
481 * Prepare a fd_set for a select call. Add all our local
482 * filedescriptors to the set, increment max_fd if appropriate.
483 *---------------------------------------------------------------------------*/
485 monitor_prepselect(fd_set *selset, int *max_fd)
487 struct monitor_connection * con;
489 for (con = TAILQ_FIRST(&connections); con != NULL; con = TAILQ_NEXT(con, connections))
500 /*---------------------------------------------------------------------------
501 * Check if the result from a select call indicates something
503 *---------------------------------------------------------------------------*/
505 monitor_handle_input(fd_set *selset)
507 struct monitor_connection * con, * next;
509 for (next = NULL, con = TAILQ_FIRST(&connections); con != NULL; con = next)
512 next = TAILQ_NEXT(con, connections);
514 if (FD_ISSET(fd, selset))
516 /* handle command from this client */
518 if (monitor_command(con, fd, con->rights) != 0)
520 /* broken or closed connection */
522 char source[FILENAME_MAX];
524 strcpy(source, con->source);
525 TAILQ_REMOVE(&connections, con, connections);
527 log(LL_DMN, "monitor closed from %s", source );
532 /* all connections gone? */
534 if (TAILQ_FIRST(&connections) == NULL)
538 /*---------------------------------------------------------------------------
539 * Try new incoming connection on the given socket.
540 * Setup client descriptor and send initial data.
541 *---------------------------------------------------------------------------*/
543 monitor_handle_connect(int sockfd, int is_local)
545 struct monitor_connection *con;
546 struct monitor_rights *rp;
548 #ifndef I4B_NOTCPIP_MONITOR
549 struct sockaddr_in ia;
553 struct sockaddr_un ua;
554 u_int8_t idata[I4B_MON_IDATA_SIZE];
555 int fd = -1, s, i, r_mask, t_events;
556 char source[FILENAME_MAX];
558 /* accept the connection */
563 fd = accept(sockfd, (struct sockaddr *)&ua, &s);
564 strcpy(source, "local");
566 #ifndef I4B_NOTCPIP_MONITOR
573 fd = accept(sockfd, (struct sockaddr *)&ia, &s);
575 hp = gethostbyaddr((char *)&ia.sin_addr, 4, AF_INET);
578 snprintf(source, sizeof source, "%s (%s)", inet_ntoa(ia.sin_addr), inet_ntoa(ia.sin_addr));
580 snprintf(source, sizeof source, "%s (%s)", hp->h_name, inet_ntoa(ia.sin_addr));
582 memcpy(&ha, &ia.sin_addr.s_addr, sizeof ha);
588 /* check the access rights of this connection */
592 for (rp = TAILQ_FIRST(&rights); rp != NULL; rp = TAILQ_NEXT(rp, list))
602 #ifndef I4B_NOTCPIP_MONITOR
606 if((ha & rp->mask) == rp->net)
617 /* no rights - go away */
618 log(LL_MER, "monitor access denied from %s", source);
625 con = malloc(sizeof(struct monitor_connection));
626 memset(con, 0, sizeof *con);
627 TAILQ_INSERT_TAIL(&connections, con, connections);
629 con->rights = r_mask;
630 strcpy(con->source, source);
632 log(LL_DMN, "monitor opened from %s rights 0x%x", source, r_mask);
634 /* send initial data */
635 I4B_PREP_CMD(idata, I4B_MON_IDATA_CODE);
636 I4B_PUT_2B(idata, I4B_MON_IDATA_VERSMAJOR, MPROT_VERSION);
637 I4B_PUT_2B(idata, I4B_MON_IDATA_VERSMINOR, MPROT_REL);
638 I4B_PUT_2B(idata, I4B_MON_IDATA_NUMCTRL, ncontroller);
639 I4B_PUT_2B(idata, I4B_MON_IDATA_NUMENTR, nentries);
640 I4B_PUT_4B(idata, I4B_MON_IDATA_CLACCESS, r_mask);
642 if((sock_write(fd, idata, sizeof idata)) == -1)
644 log(LL_MER, "monitor_handle_connect: sock_write 1 error - %s", strerror(errno));
647 for (i = 0; i < ncontroller; i++)
649 u_int8_t ictrl[I4B_MON_ICTRL_SIZE];
651 I4B_PREP_CMD(ictrl, I4B_MON_ICTRL_CODE);
652 I4B_PUT_STR(ictrl, I4B_MON_ICTRL_NAME, name_of_controller(isdn_ctrl_tab[i].ctrl_type, isdn_ctrl_tab[i].card_type));
653 I4B_PUT_2B(ictrl, I4B_MON_ICTRL_BUSID, 0);
654 I4B_PUT_4B(ictrl, I4B_MON_ICTRL_FLAGS, 0);
655 I4B_PUT_4B(ictrl, I4B_MON_ICTRL_NCHAN, 2);
657 if((sock_write(fd, ictrl, sizeof ictrl)) == -1)
659 log(LL_MER, "monitor_handle_connect: sock_write 2 error - %s", strerror(errno));
664 /* send device names from entries */
666 for(i=0; i < nentries; i++) /* walk thru all entries */
668 u_int8_t ictrl[I4B_MON_IDEV_SIZE];
671 p = &cfg_entry_tab[i]; /* get ptr to enry */
673 snprintf(nbuf, sizeof(nbuf), "%s%d ", bdrivername(p->usrdevicename), p->usrdeviceunit);
675 I4B_PREP_CMD(ictrl, I4B_MON_IDEV_CODE);
676 /*XXX*/ I4B_PUT_2B(ictrl, I4B_MON_IDEV_STATE, 1);
677 I4B_PUT_STR(ictrl, I4B_MON_IDEV_NAME, nbuf);
679 if((sock_write(fd, ictrl, sizeof ictrl)) == -1)
681 log(LL_MER, "monitor_handle_connect: sock_write 3 error - %s", strerror(errno));
685 /*XXX*/ t_events = con->events;
686 /*XXX*/ con->events = -1;
688 /* current state of controller(s) */
690 for(i=0; i < ncontroller; i++)
692 monitor_evnt_tei(i, isdn_ctrl_tab[i].tei);
693 monitor_evnt_l12stat(i, LAYER_ONE, isdn_ctrl_tab[i].l1stat);
694 monitor_evnt_l12stat(i, LAYER_TWO, isdn_ctrl_tab[i].l2stat);
697 /* current state of entries */
699 for(i=0; i < nentries; i++)
701 cfg_entry_t *cep = &cfg_entry_tab[i];
703 if(cep->state == ST_CONNECTED)
705 monitor_evnt_connect(cep);
706 monitor_evnt_acct(cep);
707 monitor_evnt_charge(cep, cep->charge, 1);
711 /*XXX*/ con->events = t_events;
715 /*---------------------------------------------------------------------------
716 * dump all monitor rights
717 *---------------------------------------------------------------------------*/
719 cmd_dump_rights(int fd, int r_mask, u_int8_t *cmd, const char *source)
721 struct monitor_rights * r;
723 u_int8_t drini[I4B_MON_DRINI_SIZE];
724 u_int8_t dr[I4B_MON_DR_SIZE];
726 for (num_rights = 0, r = TAILQ_FIRST(&rights); r != NULL; r = TAILQ_NEXT(r, list))
729 I4B_PREP_EVNT(drini, I4B_MON_DRINI_CODE);
730 I4B_PUT_2B(drini, I4B_MON_DRINI_COUNT, num_rights);
732 if((sock_write(fd, drini, sizeof drini)) == -1)
734 log(LL_MER, "cmd_dump_rights: sock_write 1 error - %s", strerror(errno));
737 for (r = TAILQ_FIRST(&rights); r != NULL; r = TAILQ_NEXT(r, list))
739 I4B_PREP_EVNT(dr, I4B_MON_DR_CODE);
740 I4B_PUT_4B(dr, I4B_MON_DR_RIGHTS, r->rights);
741 I4B_PUT_4B(dr, I4B_MON_DR_NET, r->net);
742 I4B_PUT_4B(dr, I4B_MON_DR_MASK, r->mask);
743 I4B_PUT_1B(dr, I4B_MON_DR_LOCAL, r->local);
744 if((sock_write(fd, dr, sizeof dr)) == -1)
746 log(LL_MER, "cmd_dump_rights: sock_write 2 error - %s", strerror(errno));
751 /*---------------------------------------------------------------------------
753 *---------------------------------------------------------------------------*/
755 cmd_reread_cfg(int fd, int rights, u_int8_t *cmd, const char * source)
760 /*---------------------------------------------------------------------------
761 * drop one connection
762 *---------------------------------------------------------------------------*/
764 cmd_hangup(int fd, int rights, u_int8_t *cmd, const char * source)
766 int channel = I4B_GET_4B(cmd, I4B_MON_HANGUP_CHANNEL);
767 int ctrl = I4B_GET_4B(cmd, I4B_MON_HANGUP_CTRL);
769 hangup_channel(ctrl, channel, source);
772 /*---------------------------------------------------------------------------
773 * dump all active monitor connections
774 *---------------------------------------------------------------------------*/
776 cmd_dump_mcons(int fd, int rights, u_int8_t *cmd, const char * source)
779 struct monitor_connection *con;
780 u_int8_t dcini[I4B_MON_DCINI_SIZE];
782 for (num_connections = 0, con = TAILQ_FIRST(&connections); con != NULL; con = TAILQ_NEXT(con, connections))
785 I4B_PREP_EVNT(dcini, I4B_MON_DCINI_CODE);
786 I4B_PUT_2B(dcini, I4B_MON_DCINI_COUNT, num_connections);
788 if((sock_write(fd, dcini, sizeof dcini)) == -1)
790 log(LL_MER, "cmd_dump_mcons: sock_write 1 error - %s", strerror(errno));
793 for (con = TAILQ_FIRST(&connections); con != NULL; con = TAILQ_NEXT(con, connections))
795 #ifndef I4B_NOTCPIP_MONITOR
797 struct sockaddr_in name;
799 u_int8_t dc[I4B_MON_DC_SIZE];
801 I4B_PREP_EVNT(dc, I4B_MON_DC_CODE);
802 I4B_PUT_4B(dc, I4B_MON_DC_RIGHTS, con->rights);
804 #ifndef I4B_NOTCPIP_MONITOR
805 namelen = sizeof name;
807 if (getpeername(con->sock, (struct sockaddr*)&name, &namelen) == 0)
808 memcpy(dc+I4B_MON_DC_WHO, &name.sin_addr, sizeof name.sin_addr);
810 if((sock_write(fd, dc, sizeof dc)) == -1)
812 log(LL_MER, "cmd_dump_mcons: sock_write 2 error - %s", strerror(errno));
817 /*---------------------------------------------------------------------------
818 * Handle a command from the given socket. The client
819 * has rights as specified in the rights parameter.
820 * Return non-zero if connection is closed.
821 *---------------------------------------------------------------------------*/
823 monitor_command(struct monitor_connection * con, int fd, int rights)
825 char cmd[I4B_MAX_MON_CLIENT_CMD];
828 /* command dispatch table */
829 typedef void (*cmd_func_t)(int fd, int rights, u_int8_t *cmd, const char *source);
832 cmd_func_t call; /* function to execute */
833 u_int rights; /* necessary rights */
837 /* 1 */ { cmd_dump_rights, I4B_CA_COMMAND_FULL },
838 /* 2 */ { cmd_dump_mcons, I4B_CA_COMMAND_FULL },
839 /* 3 */ { cmd_reread_cfg, I4B_CA_COMMAND_FULL },
840 /* 4 */ { cmd_hangup, I4B_CA_COMMAND_FULL },
842 #define NUMCMD (sizeof cmd_tab / sizeof cmd_tab[0])
847 /* Network transfer may deliver two or more packets concatenated.
848 * Peek at the header and read only one event at a time... */
850 ioctl(fd, FIONREAD, &u);
852 if (u < I4B_MON_CMD_HDR)
856 /* log(LL_MER, "monitor read 0 bytes"); */
857 /* socket closed by peer */
861 return 0; /* not enough data there yet */
864 bytes = recv(fd, cmd, I4B_MON_CMD_HDR, MSG_PEEK);
866 if (bytes < I4B_MON_CMD_HDR)
868 log(LL_MER, "monitor read only %d bytes", bytes);
869 return 0; /* errh? something must be wrong... */
872 bytes = I4B_GET_2B(cmd, I4B_MON_CMD_LEN);
874 if (bytes >= sizeof cmd)
877 log(LL_MER, "monitor: garbage on connection");
881 /* now we know the size, it fits, so lets read it! */
883 if(sock_read(fd, cmd, bytes) <= 0)
885 log(LL_MER, "monitor: sock_read <= 0");
891 code = I4B_GET_2B(cmd, I4B_MON_CMD);
893 /* special case: may modify our connection descriptor, is
894 * beyound all rights checks */
896 if (code == I4B_MON_CCMD_SETMASK)
900 u_int major = I4B_GET_2B(cmd, I4B_MON_ICLIENT_VERMAJOR);
901 u_int minor = I4B_GET_2B(cmd, I4B_MON_ICLIENT_VERMINOR);
904 int events = I4B_GET_4B(cmd, I4B_MON_ICLIENT_EVENTS);
905 con->events = events & rights;
909 if (code < 0 || code >= NUMCMD)
911 log(LL_MER, "illegal command from client, code = %d\n",
916 if (cmd_tab[code].call == NULL)
919 if ((cmd_tab[code].rights & rights) == cmd_tab[code].rights)
920 cmd_tab[code].call(fd, rights, cmd, con->source);
925 /*---------------------------------------------------------------------------
926 * Check if somebody would receive an event with this mask.
927 * We are lazy and try to avoid assembling unneccesary packets.
928 * Return 0 if no one interested, nonzero otherwise.
929 *---------------------------------------------------------------------------*/
933 struct monitor_connection * con;
935 for (con = TAILQ_FIRST(&connections); con != NULL; con = TAILQ_NEXT(con, connections))
937 if ((con->events & mask) == mask)
943 /*---------------------------------------------------------------------------
944 * exec hangup command
945 *---------------------------------------------------------------------------*/
947 hangup_channel(int controller, int channel, const char *source)
949 cfg_entry_t * cep = NULL;
952 if(controller < ncontroller)
954 if(isdn_ctrl_tab[controller].state != CTRL_UP)
956 for (i = 0; i < isdn_ctrl_tab[controller].nbch; i++)
958 if(isdn_ctrl_tab[controller].stateb[i] != CHAN_IDLE)
960 cep = get_cep_by_cc(controller, i);
961 if (cep != NULL && cep->isdnchannelused == channel &&
962 cep->isdncontrollerused == controller)
971 log(LL_CHD, "%05d %s manual disconnect (remote from %s)", cep->cdid, cep->name, source);
976 /*---------------------------------------------------------------------------
977 * Send an event to every connection interested in this kind of
979 *---------------------------------------------------------------------------*/
981 monitor_broadcast(int mask, u_int8_t *pkt, size_t bytes)
983 struct monitor_connection *con;
985 for (con = TAILQ_FIRST(&connections); con != NULL; con = TAILQ_NEXT(con, connections))
987 if ((con->events & mask) == mask)
991 if((sock_write(fd, pkt, bytes)) == -1)
993 log(LL_MER, "monitor_broadcast: sock_write error - %s", strerror(errno));
999 /*---------------------------------------------------------------------------
1000 * Post a logfile event
1001 *---------------------------------------------------------------------------*/
1003 monitor_evnt_log(int prio, const char * what, const char * msg)
1005 u_int8_t evnt[I4B_MON_LOGEVNT_SIZE];
1008 if (!anybody(I4B_CA_EVNT_I4B))
1013 I4B_PREP_EVNT(evnt, I4B_MON_LOGEVNT_CODE);
1014 I4B_PUT_4B(evnt, I4B_MON_LOGEVNT_TSTAMP, (long)now);
1015 I4B_PUT_4B(evnt, I4B_MON_LOGEVNT_PRIO, prio);
1016 I4B_PUT_STR(evnt, I4B_MON_LOGEVNT_WHAT, what);
1017 I4B_PUT_STR(evnt, I4B_MON_LOGEVNT_MSG, msg);
1019 monitor_broadcast(I4B_CA_EVNT_I4B, evnt, sizeof evnt);
1022 /*---------------------------------------------------------------------------
1023 * Post a charging event on the connection described
1024 * by the given config entry.
1025 *---------------------------------------------------------------------------*/
1027 monitor_evnt_charge(cfg_entry_t *cep, int units, int estimate)
1031 u_int8_t evnt[I4B_MON_CHRG_SIZE];
1033 mask = (cep->direction == DIR_IN) ? I4B_CA_EVNT_CALLIN : I4B_CA_EVNT_CALLOUT;
1040 I4B_PREP_EVNT(evnt, I4B_MON_CHRG_CODE);
1041 I4B_PUT_4B(evnt, I4B_MON_CHRG_TSTAMP, (long)now);
1042 I4B_PUT_4B(evnt, I4B_MON_CHRG_CTRL, cep->isdncontrollerused);
1043 I4B_PUT_4B(evnt, I4B_MON_CHRG_CHANNEL, cep->isdnchannelused);
1044 I4B_PUT_4B(evnt, I4B_MON_CHRG_UNITS, units);
1045 I4B_PUT_4B(evnt, I4B_MON_CHRG_ESTIMATED, estimate ? 1 : 0);
1047 monitor_broadcast(mask, evnt, sizeof evnt);
1050 /*---------------------------------------------------------------------------
1051 * Post a connection event
1052 *---------------------------------------------------------------------------*/
1054 monitor_evnt_connect(cfg_entry_t *cep)
1056 u_int8_t evnt[I4B_MON_CONNECT_SIZE];
1057 char devname[I4B_MAX_MON_STRING];
1061 mask = (cep->direction == DIR_IN) ? I4B_CA_EVNT_CALLIN : I4B_CA_EVNT_CALLOUT;
1068 snprintf(devname, sizeof devname, "%s%d", bdrivername(cep->usrdevicename), cep->usrdeviceunit);
1070 I4B_PREP_EVNT(evnt, I4B_MON_CONNECT_CODE);
1071 I4B_PUT_4B(evnt, I4B_MON_CONNECT_TSTAMP, (long)now);
1072 I4B_PUT_4B(evnt, I4B_MON_CONNECT_DIR, cep->direction == DIR_OUT ? 1 : 0);
1073 I4B_PUT_4B(evnt, I4B_MON_CONNECT_CTRL, cep->isdncontrollerused);
1074 I4B_PUT_4B(evnt, I4B_MON_CONNECT_CHANNEL, cep->isdnchannelused);
1075 I4B_PUT_STR(evnt, I4B_MON_CONNECT_CFGNAME, cep->name);
1076 I4B_PUT_STR(evnt, I4B_MON_CONNECT_DEVNAME, devname);
1078 if(cep->direction == DIR_OUT)
1080 I4B_PUT_STR(evnt, I4B_MON_CONNECT_REMPHONE, cep->remote_phone_dialout);
1081 I4B_PUT_STR(evnt, I4B_MON_CONNECT_LOCPHONE, cep->local_phone_dialout);
1085 I4B_PUT_STR(evnt, I4B_MON_CONNECT_REMPHONE, cep->real_phone_incoming);
1086 I4B_PUT_STR(evnt, I4B_MON_CONNECT_LOCPHONE, cep->local_phone_incoming);
1088 monitor_broadcast(mask, evnt, sizeof evnt);
1091 /*---------------------------------------------------------------------------
1092 * Post a disconnect event
1093 *---------------------------------------------------------------------------*/
1095 monitor_evnt_disconnect(cfg_entry_t *cep)
1097 u_int8_t evnt[I4B_MON_DISCONNECT_SIZE];
1101 mask = (cep->direction == DIR_IN) ? I4B_CA_EVNT_CALLIN : I4B_CA_EVNT_CALLOUT;
1108 I4B_PREP_EVNT(evnt, I4B_MON_DISCONNECT_CODE);
1109 I4B_PUT_4B(evnt, I4B_MON_DISCONNECT_TSTAMP, (long)now);
1110 I4B_PUT_4B(evnt, I4B_MON_DISCONNECT_CTRL, cep->isdncontrollerused);
1111 I4B_PUT_4B(evnt, I4B_MON_DISCONNECT_CHANNEL, cep->isdnchannelused);
1113 monitor_broadcast(mask, evnt, sizeof evnt);
1116 /*---------------------------------------------------------------------------
1117 * Post an up/down event
1118 *---------------------------------------------------------------------------*/
1120 monitor_evnt_updown(cfg_entry_t *cep, int up)
1122 u_int8_t evnt[I4B_MON_UPDOWN_SIZE];
1126 mask = (cep->direction == DIR_IN) ? I4B_CA_EVNT_CALLIN : I4B_CA_EVNT_CALLOUT;
1133 I4B_PREP_EVNT(evnt, I4B_MON_UPDOWN_CODE);
1134 I4B_PUT_4B(evnt, I4B_MON_UPDOWN_TSTAMP, (long)now);
1135 I4B_PUT_4B(evnt, I4B_MON_UPDOWN_CTRL, cep->isdncontrollerused);
1136 I4B_PUT_4B(evnt, I4B_MON_UPDOWN_CHANNEL, cep->isdnchannelused);
1137 I4B_PUT_4B(evnt, I4B_MON_UPDOWN_ISUP, up);
1139 monitor_broadcast(mask, evnt, sizeof evnt);
1142 /*---------------------------------------------------------------------------
1143 * Post a Layer1/2 status change event
1144 *---------------------------------------------------------------------------*/
1146 monitor_evnt_l12stat(int controller, int layer, int state)
1148 u_int8_t evnt[I4B_MON_L12STAT_SIZE];
1151 if(!anybody(I4B_CA_EVNT_I4B))
1156 I4B_PREP_EVNT(evnt, I4B_MON_L12STAT_CODE);
1157 I4B_PUT_4B(evnt, I4B_MON_L12STAT_TSTAMP, (long)now);
1158 I4B_PUT_4B(evnt, I4B_MON_L12STAT_CTRL, controller);
1159 I4B_PUT_4B(evnt, I4B_MON_L12STAT_LAYER, layer);
1160 I4B_PUT_4B(evnt, I4B_MON_L12STAT_STATE, state);
1162 monitor_broadcast(I4B_CA_EVNT_I4B, evnt, sizeof evnt);
1165 /*---------------------------------------------------------------------------
1166 * Post a TEI change event
1167 *---------------------------------------------------------------------------*/
1169 monitor_evnt_tei(int controller, int tei)
1171 u_int8_t evnt[I4B_MON_TEI_SIZE];
1174 if(!anybody(I4B_CA_EVNT_I4B))
1179 I4B_PREP_EVNT(evnt, I4B_MON_TEI_CODE);
1180 I4B_PUT_4B(evnt, I4B_MON_TEI_TSTAMP, (long)now);
1181 I4B_PUT_4B(evnt, I4B_MON_TEI_CTRL, controller);
1182 I4B_PUT_4B(evnt, I4B_MON_TEI_TEI, tei);
1184 monitor_broadcast(I4B_CA_EVNT_I4B, evnt, sizeof evnt);
1187 /*---------------------------------------------------------------------------
1188 * Post an accounting event
1189 *---------------------------------------------------------------------------*/
1191 monitor_evnt_acct(cfg_entry_t *cep)
1193 u_int8_t evnt[I4B_MON_ACCT_SIZE];
1196 if(!anybody(I4B_CA_EVNT_I4B))
1201 I4B_PREP_EVNT(evnt, I4B_MON_ACCT_CODE);
1202 I4B_PUT_4B(evnt, I4B_MON_ACCT_TSTAMP, (long)now);
1204 I4B_PUT_4B(evnt, I4B_MON_ACCT_CTRL, cep->isdncontrollerused);
1205 I4B_PUT_4B(evnt, I4B_MON_ACCT_CHAN, cep->isdnchannelused);
1206 I4B_PUT_4B(evnt, I4B_MON_ACCT_OBYTES, cep->outbytes);
1207 I4B_PUT_4B(evnt, I4B_MON_ACCT_OBPS, cep->outbps);
1208 I4B_PUT_4B(evnt, I4B_MON_ACCT_IBYTES, cep->inbytes);
1209 I4B_PUT_4B(evnt, I4B_MON_ACCT_IBPS, cep->inbps);
1211 monitor_broadcast(I4B_CA_EVNT_I4B, evnt, sizeof evnt);
1214 /*---------------------------------------------------------------------------
1215 * read from a socket
1216 *---------------------------------------------------------------------------*/
1218 sock_read(int fd, void *buf, size_t nbytes)
1229 if((nread = read(fd, ptr, nleft)) < 0)
1248 return(nbytes - nleft);
1251 /*---------------------------------------------------------------------------
1253 *---------------------------------------------------------------------------*/
1255 sock_write(int fd, void *buf, size_t nbytes)
1266 if((nwritten = write(fd, ptr, nleft)) <= 0)
1284 struct monitor_rights * monitor_next_rights(const struct monitor_rights *r)
1287 return TAILQ_FIRST(&rights);
1289 return TAILQ_NEXT(r, list);
1292 #endif /* I4B_EXTERNAL_MONITOR */