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