1 /* $NetBSD: monitor.c,v 1.15 2008/04/28 20:24:16 martin Exp $ */
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Martin Husemann <martin@NetBSD.org>.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
34 #ifndef I4B_EXTERNAL_MONITOR
37 * dummy version of routines needed by config file parser
38 * (config files should be valid with and without external montioring
39 * support compiled into the daemon)
42 void monitor_clear_rights()
45 int monitor_start_rights(const char *clientspec
)
48 void monitor_add_rights(int rights_mask
)
51 void monitor_fixup_rights()
57 #include <sys/socket.h>
59 #ifndef I4B_NOTCPIP_MONITOR
60 #include <netinet/in.h>
61 #include <arpa/inet.h>
66 static TAILQ_HEAD(rights_q
, monitor_rights
) rights
= TAILQ_HEAD_INITIALIZER(rights
);
68 static struct monitor_rights
* local_rights
= NULL
; /* entry for local socket */
70 /* for each active monitor connection we have one of this: */
72 struct monitor_connection
{
73 TAILQ_ENTRY(monitor_connection
) connections
;
74 int sock
; /* socket for this connection */
75 int rights
; /* active rights for this connection */
76 int events
; /* bitmask of events client is interested in */
77 char source
[FILENAME_MAX
];
80 static TAILQ_HEAD(connections_tq
, monitor_connection
) connections
= TAILQ_HEAD_INITIALIZER(connections
);
82 /* local prototypes */
83 struct monitor_rights
* monitor_next_rights(const struct monitor_rights
*r
);
84 static int cmp_rights(const struct monitor_rights
*pa
, const struct monitor_rights
*pb
);
85 static int monitor_command(struct monitor_connection
*con
, int fd
, int rights
);
86 static void cmd_dump_rights(int fd
, int rights
, u_int8_t
*cmd
, const char * source
);
87 static void cmd_dump_mcons(int fd
, int rights
, u_int8_t
*cmd
, const char * source
);
88 static void cmd_reread_cfg(int fd
, int rights
, u_int8_t
*cmd
, const char * source
);
89 static void cmd_hangup(int fd
, int rights
, u_int8_t
*cmd
, const char * source
);
90 static void monitor_broadcast(int mask
, u_int8_t
*pkt
, size_t bytes
);
91 static int anybody(int mask
);
92 static void hangup_channel(int controller
, int channel
, const char *source
);
93 static ssize_t
sock_read(int fd
, void *buf
, size_t nbytes
);
94 static ssize_t
sock_write(int fd
, void *buf
, size_t nbytes
);
97 * Due to the way we structure config files, the rights for an external
98 * monitor might be stated in multiple steps. First a call to
99 * monitor_start_rights opens an entry. Further (optional) calls to
100 * montior_add_rights assemble additional rights for this "current"
101 * entry. When closing the sys-file section of the config file, the
102 * "current" entry becomes invalid.
104 static struct monitor_rights
* cur_add_entry
= NULL
;
106 /*---------------------------------------------------------------------------
107 * Initialize the monitor server module. This affects only active
108 * connections, the access rights are not modified here!
109 *---------------------------------------------------------------------------*/
113 struct monitor_connection
* con
;
115 while ((con
= TAILQ_FIRST(&connections
)) != NULL
)
117 TAILQ_REMOVE(&connections
, con
, connections
);
122 /*---------------------------------------------------------------------------
124 *---------------------------------------------------------------------------*/
128 struct monitor_connection
*c
;
130 /* Close all open connections. */
131 while((c
= TAILQ_FIRST(&connections
)) != NULL
) {
133 TAILQ_REMOVE(&connections
, c
, connections
);
138 /*---------------------------------------------------------------------------
139 * Initialize access rights. No active connections are affected!
140 *---------------------------------------------------------------------------*/
142 monitor_clear_rights(void)
144 struct monitor_rights
*r
;
145 while ((r
= TAILQ_FIRST(&rights
)) != NULL
) {
146 TAILQ_REMOVE(&rights
, r
, list
);
149 cur_add_entry
= NULL
;
153 /*---------------------------------------------------------------------------
154 * Add an entry to the access lists. The clientspec either is
155 * the name of the local socket or a host- or networkname or
156 * numeric ip/host-bit-len spec.
157 *---------------------------------------------------------------------------*/
159 monitor_start_rights(const char *clientspec
)
161 struct monitor_rights r
;
163 /* initialize the new rights entry */
165 memset(&r
, 0, sizeof r
);
167 /* check clientspec */
169 if (*clientspec
== '/')
171 struct sockaddr_un sa
;
173 /* this is a local socket spec, check if we already have one */
175 if (local_rights
!= NULL
)
178 /* does it fit in a local socket address? */
180 if (strlen(clientspec
) > sizeof sa
.sun_path
)
181 return I4BMAR_LENGTH
;
184 strlcpy(r
.name
, clientspec
, sizeof(r
.name
));
186 #ifndef I4B_NOTCPIP_MONITOR
191 /* remote entry, parse host/net and cidr */
193 struct monitor_rights
* rp
;
194 char hostname
[FILENAME_MAX
];
197 p
= strchr(clientspec
, '/');
201 struct hostent
*host
;
204 /* must be a host spec */
207 host
= gethostbyname(clientspec
);
212 memcpy(&hn
, host
->h_addr_list
[0], sizeof hn
);
213 r
.net
= (u_int32_t
)ntohl(hn
);
217 /* must be net/cidr spec */
222 int num
= strtol(p
+1, NULL
, 10);
224 if (num
< 0 || num
> 32)
231 if (l
>= (int)sizeof hostname
)
232 return I4BMAR_LENGTH
;
234 strncpy(hostname
, clientspec
, l
);
238 net
= getnetbyname(hostname
);
241 r
.net
= (u_int32_t
)inet_network(hostname
);
243 r
.net
= (u_int32_t
)net
->n_net
;
253 /* check for duplicate entry */
255 for (rp
= TAILQ_FIRST(&rights
); rp
!= NULL
; rp
= TAILQ_NEXT(rp
, list
))
257 if (rp
->mask
== r
.mask
&&
259 rp
->local
== r
.local
)
269 /* entry ok, add it to the collection */
271 cur_add_entry
= malloc(sizeof(r
));
272 memcpy(cur_add_entry
, &r
, sizeof(r
));
273 TAILQ_INSERT_TAIL(&rights
, cur_add_entry
, list
);
276 local_rights
= cur_add_entry
;
278 DBGL(DL_RCCF
, (logit(LL_DBG
, "system: monitor = %s", clientspec
)));
283 /*---------------------------------------------------------------------------
284 * Add rights to the currently constructed entry - if any.
285 *---------------------------------------------------------------------------*/
287 monitor_add_rights(int rights_mask
)
289 if (cur_add_entry
== NULL
)
290 return; /* noone under construction */
292 cur_add_entry
->rights
|= rights_mask
;
294 DBGL(DL_RCCF
, (logit(LL_DBG
, "system: monitor-access = 0x%x", rights_mask
)));
297 /*---------------------------------------------------------------------------
298 * All rights have been added now. Sort the to get most specific
299 * host/net masks first, so we can travel the list and use the first
300 * match for actual rights.
301 *---------------------------------------------------------------------------*/
303 monitor_fixup_rights(void)
305 struct monitor_rights
* cur
, * test
, * next
;
307 /* no more rights may be added to the current entry */
309 cur_add_entry
= NULL
;
311 /* sort the rights */
312 for (next
= NULL
, cur
= TAILQ_FIRST(&rights
); cur
!= NULL
; cur
= next
)
314 next
= TAILQ_NEXT(cur
, list
);
315 for (test
= TAILQ_FIRST(&rights
); test
!= NULL
&& test
!= cur
; test
= TAILQ_NEXT(test
, list
))
317 if (cmp_rights(cur
, test
) > 0) {
318 /* move cur up the list and insert before test */
319 TAILQ_REMOVE(&rights
, cur
, list
);
320 if (test
== TAILQ_FIRST(&rights
))
321 TAILQ_INSERT_HEAD(&rights
, cur
, list
);
323 TAILQ_INSERT_BEFORE(test
, cur
, list
);
330 /*---------------------------------------------------------------------------
331 * comparator for rights
332 *---------------------------------------------------------------------------*/
334 cmp_rights(const struct monitor_rights
*pa
, const struct monitor_rights
*pb
)
338 /* local sorts first */
343 /* which is the less specific netmask? */
347 if ((pb
->mask
& mask
) == 0)
350 /* are the entries disjunct? */
352 if ((pa
->net
& mask
) != (pb
->net
& mask
))
354 /* simply compare net part of address */
355 return ((pa
->net
& mask
) < (pb
->net
& mask
)) ? -1 : 1;
358 /* One entry is part of the others net. We already now "mask" is
359 * the netmask of the less specific (i.e. greater) one */
361 return (pa
->mask
== mask
) ? 1 : -1;
364 #ifndef I4B_NOTCPIP_MONITOR
365 /*---------------------------------------------------------------------------
366 * Check if access rights for a remote socket are specified and
367 * create this socket. Return -1 otherwise.
368 *---------------------------------------------------------------------------*/
370 monitor_create_remote_socket(int portno
)
372 struct sockaddr_in sa
;
376 remotesockfd
= socket(AF_INET
, SOCK_STREAM
, 0);
378 if (remotesockfd
== -1)
380 logit(LL_MER
, "could not create remote monitor socket: %s", strerror(errno
));
386 if (setsockopt(remotesockfd
, SOL_SOCKET
, SO_REUSEADDR
, &val
, sizeof val
))
388 logit(LL_MER
, "could not setsockopt: %s", strerror(errno
));
392 memset(&sa
, 0, sizeof sa
);
393 sa
.sin_len
= sizeof sa
;
394 sa
.sin_family
= AF_INET
;
395 sa
.sin_port
= htons(portno
);
396 sa
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
398 if (bind(remotesockfd
, (struct sockaddr
*)&sa
, sizeof sa
) == -1)
400 logit(LL_MER
, "could not bind remote monitor socket to port %d: %s", portno
, strerror(errno
));
404 if (listen(remotesockfd
, 0))
406 logit(LL_MER
, "could not listen on monitor socket: %s", strerror(errno
));
410 return(remotesockfd
);
414 /*---------------------------------------------------------------------------
415 * Check if access rights for a local socket are specified and
416 * create this socket. Return -1 otherwise.
417 *---------------------------------------------------------------------------*/
419 monitor_create_local_socket(void)
422 struct sockaddr_un sa
;
424 /* check for a local entry */
426 if (local_rights
== NULL
)
429 /* create and setup socket */
431 s
= socket(AF_LOCAL
, SOCK_STREAM
, 0);
435 logit(LL_MER
, "could not create local monitor socket, errno = %d", errno
);
439 unlink(local_rights
->name
);
441 memset(&sa
, 0, sizeof sa
);
442 sa
.sun_len
= sizeof sa
;
443 sa
.sun_family
= AF_LOCAL
;
444 strlcpy(sa
.sun_path
, local_rights
->name
, sizeof(sa
.sun_path
));
446 if (bind(s
, (struct sockaddr
*)&sa
, SUN_LEN(&sa
)))
448 logit(LL_MER
, "could not bind local monitor socket [%s], errno = %d", local_rights
->name
, errno
);
452 chmod(local_rights
->name
, 0600);
456 logit(LL_MER
, "could not listen on local monitor socket, errno = %d", errno
);
463 /*---------------------------------------------------------------------------
464 * Prepare a fd_set for a select call. Add all our local
465 * filedescriptors to the set, increment max_fd if appropriate.
466 *---------------------------------------------------------------------------*/
468 monitor_prepselect(fd_set
*selset
, int *max_fd
)
470 struct monitor_connection
* con
;
472 for (con
= TAILQ_FIRST(&connections
); con
!= NULL
; con
= TAILQ_NEXT(con
, connections
))
483 /*---------------------------------------------------------------------------
484 * Check if the result from a select call indicates something
486 *---------------------------------------------------------------------------*/
488 monitor_handle_input(fd_set
*selset
)
490 struct monitor_connection
* con
, * next
;
492 for (next
= NULL
, con
= TAILQ_FIRST(&connections
); con
!= NULL
; con
= next
)
495 next
= TAILQ_NEXT(con
, connections
);
497 if (FD_ISSET(fd
, selset
))
499 /* handle command from this client */
501 if (monitor_command(con
, fd
, con
->rights
) != 0)
503 /* broken or closed connection */
505 char source
[FILENAME_MAX
];
507 strlcpy(source
, con
->source
, sizeof(source
));
508 TAILQ_REMOVE(&connections
, con
, connections
);
510 logit(LL_DMN
, "monitor closed from %s", source
);
515 /* all connections gone? */
517 if (TAILQ_FIRST(&connections
) == NULL
)
521 /*---------------------------------------------------------------------------
522 * Try new incoming connection on the given socket.
523 * Setup client descriptor and send initial data.
524 *---------------------------------------------------------------------------*/
526 monitor_handle_connect(int sockfd
, int is_local
)
528 struct monitor_connection
*con
;
529 struct monitor_rights
*rp
;
530 struct isdn_ctrl_state
*ctrl
;
531 struct cfg_entry
*cfe
;
534 #ifndef I4B_NOTCPIP_MONITOR
535 struct sockaddr_in ia
;
539 struct sockaddr_un ua
;
541 u_int8_t idata
[I4B_MON_IDATA_SIZE
];
542 int fd
= -1, r_mask
, t_events
;
543 char source
[FILENAME_MAX
];
545 /* accept the connection */
550 fd
= accept(sockfd
, (struct sockaddr
*)&ua
, &s
);
551 strlcpy(source
, "local", sizeof(source
));
553 #ifndef I4B_NOTCPIP_MONITOR
560 fd
= accept(sockfd
, (struct sockaddr
*)&ia
, &s
);
562 hp
= gethostbyaddr((char *)&ia
.sin_addr
, 4, AF_INET
);
565 snprintf(source
, sizeof source
, "%s (%s)", inet_ntoa(ia
.sin_addr
), inet_ntoa(ia
.sin_addr
));
567 snprintf(source
, sizeof source
, "%s (%s)", hp
->h_name
, inet_ntoa(ia
.sin_addr
));
569 memcpy(&ha
, &ia
.sin_addr
.s_addr
, sizeof ha
);
575 /* check the access rights of this connection */
579 for (rp
= TAILQ_FIRST(&rights
); rp
!= NULL
; rp
= TAILQ_NEXT(rp
, list
))
589 #ifndef I4B_NOTCPIP_MONITOR
593 if ((ha
& rp
->mask
) == rp
->net
)
604 /* no rights - go away */
605 logit(LL_MER
, "monitor access denied from %s", source
);
612 con
= malloc(sizeof(struct monitor_connection
));
613 memset(con
, 0, sizeof *con
);
614 TAILQ_INSERT_TAIL(&connections
, con
, connections
);
616 con
->rights
= r_mask
;
617 strlcpy(con
->source
, source
, sizeof(con
->source
));
619 logit(LL_DMN
, "monitor opened from %s rights 0x%x", source
, r_mask
);
621 /* send initial data */
622 I4B_PREP_CMD(idata
, I4B_MON_IDATA_CODE
);
623 I4B_PUT_2B(idata
, I4B_MON_IDATA_VERSMAJOR
, MPROT_VERSION
);
624 I4B_PUT_2B(idata
, I4B_MON_IDATA_VERSMINOR
, MPROT_REL
);
625 n
= count_ctrl_states();
626 I4B_PUT_2B(idata
, I4B_MON_IDATA_NUMCTRL
, n
);
627 n
= count_cfg_entries();
628 I4B_PUT_2B(idata
, I4B_MON_IDATA_NUMENTR
, n
);
629 I4B_PUT_4B(idata
, I4B_MON_IDATA_CLACCESS
, r_mask
);
631 if ((sock_write(fd
, idata
, sizeof idata
)) == -1)
633 logit(LL_MER
, "monitor_handle_connect: sock_write 1 error - %s", strerror(errno
));
636 for (ctrl
= get_first_ctrl_state(); ctrl
; ctrl
= NEXT_CTRL(ctrl
)) {
637 u_int8_t ictrl
[I4B_MON_ICTRL_SIZE
];
640 snprintf(ctrl_desc
, sizeof(ctrl_desc
), "%s: %s",
641 ctrl
->device_name
, ctrl
->controller
);
643 I4B_PREP_CMD(ictrl
, I4B_MON_ICTRL_CODE
);
644 I4B_PUT_STR(ictrl
, I4B_MON_ICTRL_NAME
, ctrl_desc
);
645 I4B_PUT_2B(ictrl
, I4B_MON_ICTRL_BUSID
, ctrl
->isdnif
);
646 I4B_PUT_4B(ictrl
, I4B_MON_ICTRL_FLAGS
, 0);
647 I4B_PUT_2B(ictrl
, I4B_MON_ICTRL_NCHAN
, 2);
649 if ((sock_write(fd
, ictrl
, sizeof ictrl
)) == -1)
651 logit(LL_MER
, "monitor_handle_connect: sock_write 2 error - %s", strerror(errno
));
656 /* send device names from entries */
658 for (cfe
= get_first_cfg_entry(); cfe
; cfe
= NEXT_CFE(cfe
)) {
659 u_int8_t ictrl
[I4B_MON_IDEV_SIZE
];
662 snprintf(nbuf
, sizeof(nbuf
), "%s%d ", cfe
->usrdevicename
, cfe
->usrdeviceunit
);
664 I4B_PREP_CMD(ictrl
, I4B_MON_IDEV_CODE
);
665 /*XXX*/ I4B_PUT_2B(ictrl
, I4B_MON_IDEV_STATE
, 1);
666 I4B_PUT_STR(ictrl
, I4B_MON_IDEV_NAME
, nbuf
);
668 if ((sock_write(fd
, ictrl
, sizeof ictrl
)) == -1)
670 logit(LL_MER
, "monitor_handle_connect: sock_write 3 error - %s", strerror(errno
));
674 /*XXX*/ t_events
= con
->events
;
675 /*XXX*/ con
->events
= -1;
677 /* current state of controller(s) */
679 for (ctrl
= get_first_ctrl_state(); ctrl
; ctrl
= NEXT_CTRL(ctrl
)) {
680 monitor_evnt_tei(ctrl
->isdnif
, ctrl
->tei
);
681 monitor_evnt_l12stat(ctrl
->isdnif
, LAYER_ONE
, ctrl
->l1stat
);
682 monitor_evnt_l12stat(ctrl
->isdnif
, LAYER_TWO
, ctrl
->l2stat
);
685 /* current state of entries */
687 for (cfe
= get_first_cfg_entry(); cfe
; cfe
= NEXT_CFE(cfe
)) {
689 if (cfe
->state
== ST_CONNECTED
)
691 monitor_evnt_connect(cfe
);
692 monitor_evnt_acct(cfe
);
693 monitor_evnt_charge(cfe
, cfe
->charge
, 1);
697 /*XXX*/ con
->events
= t_events
;
701 /*---------------------------------------------------------------------------
702 * dump all monitor rights
703 *---------------------------------------------------------------------------*/
705 cmd_dump_rights(int fd
, int r_mask
, u_int8_t
*cmd
, const char *source
)
707 struct monitor_rights
* r
;
709 u_int8_t drini
[I4B_MON_DRINI_SIZE
];
710 u_int8_t dr
[I4B_MON_DR_SIZE
];
712 for (num_rights
= 0, r
= TAILQ_FIRST(&rights
); r
!= NULL
; r
= TAILQ_NEXT(r
, list
))
715 I4B_PREP_EVNT(drini
, I4B_MON_DRINI_CODE
);
716 I4B_PUT_2B(drini
, I4B_MON_DRINI_COUNT
, num_rights
);
718 if ((sock_write(fd
, drini
, sizeof drini
)) == -1)
720 logit(LL_MER
, "cmd_dump_rights: sock_write 1 error - %s", strerror(errno
));
723 for (r
= TAILQ_FIRST(&rights
); r
!= NULL
; r
= TAILQ_NEXT(r
, list
))
725 I4B_PREP_EVNT(dr
, I4B_MON_DR_CODE
);
726 I4B_PUT_4B(dr
, I4B_MON_DR_RIGHTS
, r
->rights
);
727 I4B_PUT_4B(dr
, I4B_MON_DR_NET
, r
->net
);
728 I4B_PUT_4B(dr
, I4B_MON_DR_MASK
, r
->mask
);
729 I4B_PUT_1B(dr
, I4B_MON_DR_LOCAL
, r
->local
);
730 if ((sock_write(fd
, dr
, sizeof dr
)) == -1)
732 logit(LL_MER
, "cmd_dump_rights: sock_write 2 error - %s", strerror(errno
));
737 /*---------------------------------------------------------------------------
739 *---------------------------------------------------------------------------*/
741 cmd_reread_cfg(int fd
, int _rights
, u_int8_t
*cmd
, const char * source
)
746 /*---------------------------------------------------------------------------
747 * drop one connection
748 *---------------------------------------------------------------------------*/
750 cmd_hangup(int fd
, int _rights
, u_int8_t
*cmd
, const char * source
)
752 int channel
= I4B_GET_4B(cmd
, I4B_MON_HANGUP_CHANNEL
);
753 int ctrl
= I4B_GET_4B(cmd
, I4B_MON_HANGUP_CTRL
);
755 hangup_channel(ctrl
, channel
, source
);
758 /*---------------------------------------------------------------------------
759 * dump all active monitor connections
760 *---------------------------------------------------------------------------*/
762 cmd_dump_mcons(int fd
, int _rights
, u_int8_t
*cmd
, const char * source
)
765 struct monitor_connection
*con
;
766 u_int8_t dcini
[I4B_MON_DCINI_SIZE
];
768 for (num_connections
= 0, con
= TAILQ_FIRST(&connections
); con
!= NULL
; con
= TAILQ_NEXT(con
, connections
))
771 I4B_PREP_EVNT(dcini
, I4B_MON_DCINI_CODE
);
772 I4B_PUT_2B(dcini
, I4B_MON_DCINI_COUNT
, num_connections
);
774 if ((sock_write(fd
, dcini
, sizeof dcini
)) == -1)
776 logit(LL_MER
, "cmd_dump_mcons: sock_write 1 error - %s", strerror(errno
));
779 for (con
= TAILQ_FIRST(&connections
); con
!= NULL
; con
= TAILQ_NEXT(con
, connections
))
781 #ifndef I4B_NOTCPIP_MONITOR
783 struct sockaddr_in name
;
785 u_int8_t dc
[I4B_MON_DC_SIZE
];
787 I4B_PREP_EVNT(dc
, I4B_MON_DC_CODE
);
788 I4B_PUT_4B(dc
, I4B_MON_DC_RIGHTS
, con
->rights
);
790 #ifndef I4B_NOTCPIP_MONITOR
791 namelen
= sizeof name
;
793 if (getpeername(con
->sock
, (struct sockaddr
*)&name
, &namelen
) == 0)
794 memcpy(dc
+I4B_MON_DC_WHO
, &name
.sin_addr
, sizeof name
.sin_addr
);
796 if ((sock_write(fd
, dc
, sizeof dc
)) == -1)
798 logit(LL_MER
, "cmd_dump_mcons: sock_write 2 error - %s", strerror(errno
));
803 /*---------------------------------------------------------------------------
804 * Handle a command from the given socket. The client
805 * has rights as specified in the rights parameter.
806 * Return non-zero if connection is closed.
807 *---------------------------------------------------------------------------*/
809 monitor_command(struct monitor_connection
* con
, int fd
, int mcrights
)
811 char cmd
[I4B_MAX_MON_CLIENT_CMD
];
814 /* command dispatch table */
815 typedef void (*cmd_func_t
)(int fd
, int rights
, u_int8_t
*cmd
, const char *source
);
818 cmd_func_t call
; /* function to execute */
819 u_int rights
; /* necessary rights */
823 /* 1 */ { cmd_dump_rights
, I4B_CA_COMMAND_FULL
},
824 /* 2 */ { cmd_dump_mcons
, I4B_CA_COMMAND_FULL
},
825 /* 3 */ { cmd_reread_cfg
, I4B_CA_COMMAND_FULL
},
826 /* 4 */ { cmd_hangup
, I4B_CA_COMMAND_FULL
},
828 #define NUMCMD (sizeof cmd_tab / sizeof cmd_tab[0])
830 int avail
, bytes
, err
;
832 /* Network transfer may deliver two or more packets concatenated.
833 * Peek at the header and read only one event at a time... */
836 err
= ioctl(fd
, FIONREAD
, &avail
);
838 if (err
== -1 || avail
< I4B_MON_CMD_HDR
)
840 if (err
== -1 && errno
== EINTR
)
841 return 0; /* try again later */
843 if (err
== -1 || avail
== 0)
845 /* logit(LL_MER, "monitor read 0 bytes"); */
846 /* socket closed by peer */
850 return 0; /* not enough data there yet */
853 bytes
= recv(fd
, cmd
, I4B_MON_CMD_HDR
, MSG_PEEK
);
855 if (bytes
< I4B_MON_CMD_HDR
)
857 logit(LL_MER
, "monitor read only %d bytes", bytes
);
858 return 0; /* errh? something must be wrong... */
861 bytes
= I4B_GET_2B(cmd
, I4B_MON_CMD_LEN
);
863 if (bytes
>= (int)sizeof cmd
)
866 logit(LL_MER
, "monitor: garbage on connection");
870 /* now we know the size, it fits, so lets read it! */
872 if (sock_read(fd
, cmd
, bytes
) <= 0)
874 logit(LL_MER
, "monitor: sock_read <= 0");
880 code
= I4B_GET_2B(cmd
, I4B_MON_CMD
);
882 /* special case: may modify our connection descriptor, is
883 * beyound all rights checks */
885 if (code
== I4B_MON_CCMD_SETMASK
)
889 u_int major = I4B_GET_2B(cmd, I4B_MON_ICLIENT_VERMAJOR);
890 u_int minor = I4B_GET_2B(cmd, I4B_MON_ICLIENT_VERMINOR);
893 int events
= I4B_GET_4B(cmd
, I4B_MON_ICLIENT_EVENTS
);
894 con
->events
= events
& mcrights
;
900 logit(LL_MER
, "illegal command from client, code = %d\n",
905 if (cmd_tab
[code
].call
== NULL
)
908 if ((cmd_tab
[code
].rights
& mcrights
) == cmd_tab
[code
].rights
)
909 cmd_tab
[code
].call(fd
, mcrights
, (u_char
*)cmd
, con
->source
);
914 /*---------------------------------------------------------------------------
915 * Check if somebody would receive an event with this mask.
916 * We are lazy and try to avoid assembling unneccesary packets.
917 * Return 0 if no one interested, nonzero otherwise.
918 *---------------------------------------------------------------------------*/
922 struct monitor_connection
* con
;
924 for (con
= TAILQ_FIRST(&connections
); con
!= NULL
; con
= TAILQ_NEXT(con
, connections
))
926 if ((con
->events
& mask
) == mask
)
932 /*---------------------------------------------------------------------------
933 * exec hangup command
934 *---------------------------------------------------------------------------*/
936 hangup_channel(int controller
, int channel
, const char *source
)
938 struct cfg_entry
* cep
= NULL
;
939 struct isdn_ctrl_state
* ctrl
= NULL
;
942 ctrl
= find_ctrl_state(controller
);
944 if (ctrl
->state
!= CTRL_UP
)
946 for (i
= 0; i
< ctrl
->nbch
; i
++) {
947 if (ctrl
->stateb
[i
] != CHAN_IDLE
) {
948 cep
= get_cep_by_cc(controller
, i
);
950 && cep
->isdnchannelused
== channel
951 && cep
->isdncontrollerused
== controller
)
960 logit(LL_CHD
, "%05d %s manual disconnect (remote from %s)", cep
->cdid
, cep
->name
, source
);
965 /*---------------------------------------------------------------------------
966 * Send an event to every connection interested in this kind of
968 *---------------------------------------------------------------------------*/
970 monitor_broadcast(int mask
, u_int8_t
*pkt
, size_t bytes
)
972 struct monitor_connection
*con
;
974 for (con
= TAILQ_FIRST(&connections
); con
!= NULL
; con
= TAILQ_NEXT(con
, connections
))
976 if ((con
->events
& mask
) == mask
)
980 if ((sock_write(fd
, pkt
, bytes
)) == -1)
982 logit(LL_MER
, "monitor_broadcast: sock_write error - %s", strerror(errno
));
988 /*---------------------------------------------------------------------------
989 * Post a logfile event
990 *---------------------------------------------------------------------------*/
992 monitor_evnt_log(int prio
, const char * what
, const char * msg
)
994 u_int8_t evnt
[I4B_MON_LOGEVNT_SIZE
];
997 if (!anybody(I4B_CA_EVNT_I4B
))
1002 I4B_PREP_EVNT(evnt
, I4B_MON_LOGEVNT_CODE
);
1003 I4B_PUT_4B(evnt
, I4B_MON_LOGEVNT_TSTAMP
, (long)now
);
1004 I4B_PUT_4B(evnt
, I4B_MON_LOGEVNT_PRIO
, prio
);
1005 I4B_PUT_STR(evnt
, I4B_MON_LOGEVNT_WHAT
, what
);
1006 I4B_PUT_STR(evnt
, I4B_MON_LOGEVNT_MSG
, msg
);
1008 monitor_broadcast(I4B_CA_EVNT_I4B
, evnt
, sizeof evnt
);
1011 /*---------------------------------------------------------------------------
1012 * Post a charging event on the connection described
1013 * by the given config entry.
1014 *---------------------------------------------------------------------------*/
1016 monitor_evnt_charge(struct cfg_entry
*cep
, int units
, int estimate
)
1020 u_int8_t evnt
[I4B_MON_CHRG_SIZE
];
1022 mask
= (cep
->direction
== DIR_IN
) ? I4B_CA_EVNT_CALLIN
: I4B_CA_EVNT_CALLOUT
;
1029 I4B_PREP_EVNT(evnt
, I4B_MON_CHRG_CODE
);
1030 I4B_PUT_4B(evnt
, I4B_MON_CHRG_TSTAMP
, (long)now
);
1031 I4B_PUT_4B(evnt
, I4B_MON_CHRG_CTRL
, cep
->isdncontrollerused
);
1032 I4B_PUT_4B(evnt
, I4B_MON_CHRG_CHANNEL
, cep
->isdnchannelused
);
1033 I4B_PUT_4B(evnt
, I4B_MON_CHRG_UNITS
, units
);
1034 I4B_PUT_4B(evnt
, I4B_MON_CHRG_ESTIMATED
, estimate
? 1 : 0);
1036 monitor_broadcast(mask
, evnt
, sizeof evnt
);
1039 /*---------------------------------------------------------------------------
1040 * Post a connection event
1041 *---------------------------------------------------------------------------*/
1043 monitor_evnt_connect(struct cfg_entry
*cep
)
1045 u_int8_t evnt
[I4B_MON_CONNECT_SIZE
];
1046 char devnam
[I4B_MAX_MON_STRING
];
1050 mask
= (cep
->direction
== DIR_IN
) ? I4B_CA_EVNT_CALLIN
: I4B_CA_EVNT_CALLOUT
;
1057 snprintf(devnam
, sizeof devnam
, "%s%d", cep
->usrdevicename
, cep
->usrdeviceunit
);
1059 I4B_PREP_EVNT(evnt
, I4B_MON_CONNECT_CODE
);
1060 I4B_PUT_4B(evnt
, I4B_MON_CONNECT_TSTAMP
, (long)now
);
1061 I4B_PUT_4B(evnt
, I4B_MON_CONNECT_DIR
, cep
->direction
== DIR_OUT
? 1 : 0);
1062 I4B_PUT_4B(evnt
, I4B_MON_CONNECT_CTRL
, cep
->isdncontrollerused
);
1063 I4B_PUT_4B(evnt
, I4B_MON_CONNECT_CHANNEL
, cep
->isdnchannelused
);
1064 I4B_PUT_STR(evnt
, I4B_MON_CONNECT_CFGNAME
, cep
->name
);
1065 I4B_PUT_STR(evnt
, I4B_MON_CONNECT_DEVNAME
, devnam
);
1067 if (cep
->direction
== DIR_OUT
)
1069 I4B_PUT_STR(evnt
, I4B_MON_CONNECT_REMPHONE
, cep
->remote_phone_dialout
);
1070 I4B_PUT_STR(evnt
, I4B_MON_CONNECT_LOCPHONE
, cep
->local_phone_dialout
);
1074 I4B_PUT_STR(evnt
, I4B_MON_CONNECT_REMPHONE
, cep
->real_phone_incoming
);
1075 I4B_PUT_STR(evnt
, I4B_MON_CONNECT_LOCPHONE
, cep
->local_phone_incoming
);
1077 monitor_broadcast(mask
, evnt
, sizeof evnt
);
1080 /*---------------------------------------------------------------------------
1081 * Post a disconnect event
1082 *---------------------------------------------------------------------------*/
1084 monitor_evnt_disconnect(struct cfg_entry
*cep
)
1086 u_int8_t evnt
[I4B_MON_DISCONNECT_SIZE
];
1090 mask
= (cep
->direction
== DIR_IN
) ? I4B_CA_EVNT_CALLIN
: I4B_CA_EVNT_CALLOUT
;
1097 I4B_PREP_EVNT(evnt
, I4B_MON_DISCONNECT_CODE
);
1098 I4B_PUT_4B(evnt
, I4B_MON_DISCONNECT_TSTAMP
, (long)now
);
1099 I4B_PUT_4B(evnt
, I4B_MON_DISCONNECT_CTRL
, cep
->isdncontrollerused
);
1100 I4B_PUT_4B(evnt
, I4B_MON_DISCONNECT_CHANNEL
, cep
->isdnchannelused
);
1102 monitor_broadcast(mask
, evnt
, sizeof evnt
);
1105 /*---------------------------------------------------------------------------
1106 * Post an up/down event
1107 *---------------------------------------------------------------------------*/
1109 monitor_evnt_updown(struct cfg_entry
*cep
, int up
)
1111 u_int8_t evnt
[I4B_MON_UPDOWN_SIZE
];
1115 mask
= (cep
->direction
== DIR_IN
) ? I4B_CA_EVNT_CALLIN
: I4B_CA_EVNT_CALLOUT
;
1122 I4B_PREP_EVNT(evnt
, I4B_MON_UPDOWN_CODE
);
1123 I4B_PUT_4B(evnt
, I4B_MON_UPDOWN_TSTAMP
, (long)now
);
1124 I4B_PUT_4B(evnt
, I4B_MON_UPDOWN_CTRL
, cep
->isdncontrollerused
);
1125 I4B_PUT_4B(evnt
, I4B_MON_UPDOWN_CHANNEL
, cep
->isdnchannelused
);
1126 I4B_PUT_4B(evnt
, I4B_MON_UPDOWN_ISUP
, up
);
1128 monitor_broadcast(mask
, evnt
, sizeof evnt
);
1131 /*---------------------------------------------------------------------------
1132 * Post a Layer1/2 status change event
1133 *---------------------------------------------------------------------------*/
1135 monitor_evnt_l12stat(int controller
, int layer
, int state
)
1137 u_int8_t evnt
[I4B_MON_L12STAT_SIZE
];
1140 if (!anybody(I4B_CA_EVNT_I4B
))
1145 I4B_PREP_EVNT(evnt
, I4B_MON_L12STAT_CODE
);
1146 I4B_PUT_4B(evnt
, I4B_MON_L12STAT_TSTAMP
, (long)now
);
1147 I4B_PUT_4B(evnt
, I4B_MON_L12STAT_CTRL
, controller
);
1148 I4B_PUT_4B(evnt
, I4B_MON_L12STAT_LAYER
, layer
);
1149 I4B_PUT_4B(evnt
, I4B_MON_L12STAT_STATE
, state
);
1151 monitor_broadcast(I4B_CA_EVNT_I4B
, evnt
, sizeof evnt
);
1154 /*---------------------------------------------------------------------------
1155 * Post a TEI change event
1156 *---------------------------------------------------------------------------*/
1158 monitor_evnt_tei(int controller
, int tei
)
1160 u_int8_t evnt
[I4B_MON_TEI_SIZE
];
1163 if (!anybody(I4B_CA_EVNT_I4B
))
1168 I4B_PREP_EVNT(evnt
, I4B_MON_TEI_CODE
);
1169 I4B_PUT_4B(evnt
, I4B_MON_TEI_TSTAMP
, (long)now
);
1170 I4B_PUT_4B(evnt
, I4B_MON_TEI_CTRL
, controller
);
1171 I4B_PUT_4B(evnt
, I4B_MON_TEI_TEI
, tei
);
1173 monitor_broadcast(I4B_CA_EVNT_I4B
, evnt
, sizeof evnt
);
1176 /*---------------------------------------------------------------------------
1177 * Post an accounting event
1178 *---------------------------------------------------------------------------*/
1180 monitor_evnt_acct(struct cfg_entry
*cep
)
1182 u_int8_t evnt
[I4B_MON_ACCT_SIZE
];
1185 if (!anybody(I4B_CA_EVNT_I4B
))
1190 I4B_PREP_EVNT(evnt
, I4B_MON_ACCT_CODE
);
1191 I4B_PUT_4B(evnt
, I4B_MON_ACCT_TSTAMP
, (long)now
);
1193 I4B_PUT_4B(evnt
, I4B_MON_ACCT_CTRL
, cep
->isdncontrollerused
);
1194 I4B_PUT_4B(evnt
, I4B_MON_ACCT_CHAN
, cep
->isdnchannelused
);
1195 I4B_PUT_4B(evnt
, I4B_MON_ACCT_OBYTES
, cep
->outbytes
);
1196 I4B_PUT_4B(evnt
, I4B_MON_ACCT_OBPS
, cep
->outbps
);
1197 I4B_PUT_4B(evnt
, I4B_MON_ACCT_IBYTES
, cep
->inbytes
);
1198 I4B_PUT_4B(evnt
, I4B_MON_ACCT_IBPS
, cep
->inbps
);
1200 monitor_broadcast(I4B_CA_EVNT_I4B
, evnt
, sizeof evnt
);
1203 /*---------------------------------------------------------------------------
1204 * read from a socket
1205 *---------------------------------------------------------------------------*/
1207 sock_read(int fd
, void *buf
, size_t nbytes
)
1218 if ((nread
= read(fd
, ptr
, nleft
)) < 0)
1229 else if (nread
== 0)
1237 return(nbytes
- nleft
);
1240 /*---------------------------------------------------------------------------
1242 *---------------------------------------------------------------------------*/
1244 sock_write(int fd
, void *buf
, size_t nbytes
)
1255 if ((nwritten
= write(fd
, ptr
, nleft
)) <= 0)
1273 struct monitor_rights
* monitor_next_rights(const struct monitor_rights
*r
)
1276 return TAILQ_FIRST(&rights
);
1278 return TAILQ_NEXT(r
, list
);
1281 #endif /* I4B_EXTERNAL_MONITOR */