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