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