Deleted Added
full compact
trap.c (216294) trap.c (216594)
1/*
2 * Copyright (c) 2001-2003
3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4 * All rights reserved.
5 *
6 * Author: Harti Brandt <harti@freebsd.org>
1/*
2 * Copyright (c) 2001-2003
3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4 * All rights reserved.
5 *
6 * Author: Harti Brandt <harti@freebsd.org>
7 *
7 *
8 * Copyright (c) 2010 The FreeBSD Foundation
9 * All rights reserved.
10 *
11 * Portions of this software were developed by Shteryana Sotirova Shopova
12 * under sponsorship from the FreeBSD Foundation.
13 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.

--- 13 unchanged lines hidden (view full) ---

29 * $Begemot: bsnmp/snmpd/trap.c,v 1.9 2005/10/04 11:21:39 brandt_h Exp $
30 *
31 * TrapSinkTable
32 */
33#include <sys/types.h>
34#include <sys/queue.h>
35#include <sys/sysctl.h>
36#include <sys/un.h>
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.

--- 13 unchanged lines hidden (view full) ---

35 * $Begemot: bsnmp/snmpd/trap.c,v 1.9 2005/10/04 11:21:39 brandt_h Exp $
36 *
37 * TrapSinkTable
38 */
39#include <sys/types.h>
40#include <sys/queue.h>
41#include <sys/sysctl.h>
42#include <sys/un.h>
43#include <stdint.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <stdarg.h>
40#include <stdarg.h>
41#include <string.h>
42#include <ctype.h>
43#include <syslog.h>
44#include <unistd.h>
45#include <netinet/in.h>
46#include <arpa/inet.h>
47
48#include "snmpmod.h"
49#include "snmpd.h"
50#include "tree.h"
51#include "oid.h"
52
53struct trapsink_list trapsink_list = TAILQ_HEAD_INITIALIZER(trapsink_list);
54
44#include <stdio.h>
45#include <stdlib.h>
46#include <stdarg.h>
47#include <stdarg.h>
48#include <string.h>
49#include <ctype.h>
50#include <syslog.h>
51#include <unistd.h>
52#include <netinet/in.h>
53#include <arpa/inet.h>
54
55#include "snmpmod.h"
56#include "snmpd.h"
57#include "tree.h"
58#include "oid.h"
59
60struct trapsink_list trapsink_list = TAILQ_HEAD_INITIALIZER(trapsink_list);
61
62/* List of target addresses */
63struct target_addresslist target_addresslist =
64 SLIST_HEAD_INITIALIZER(target_addresslist);
65
66/* List of target parameters */
67struct target_paramlist target_paramlist =
68 SLIST_HEAD_INITIALIZER(target_paramlist);
69
70/* List of notification targets */
71struct target_notifylist target_notifylist =
72 SLIST_HEAD_INITIALIZER(target_notifylist);
73
55static const struct asn_oid oid_begemotTrapSinkTable =
56 OIDX_begemotTrapSinkTable;
57static const struct asn_oid oid_sysUpTime = OIDX_sysUpTime;
58static const struct asn_oid oid_snmpTrapOID = OIDX_snmpTrapOID;
59
60struct trapsink_dep {
61 struct snmp_dependency dep;
62 u_int set;

--- 330 unchanged lines hidden (view full) ---

393 case LEAF_begemotTrapSinkVersion:
394 value->v.integer = t->version;
395 break;
396
397 }
398 return (SNMP_ERR_NOERROR);
399}
400
74static const struct asn_oid oid_begemotTrapSinkTable =
75 OIDX_begemotTrapSinkTable;
76static const struct asn_oid oid_sysUpTime = OIDX_sysUpTime;
77static const struct asn_oid oid_snmpTrapOID = OIDX_snmpTrapOID;
78
79struct trapsink_dep {
80 struct snmp_dependency dep;
81 u_int set;

--- 330 unchanged lines hidden (view full) ---

412 case LEAF_begemotTrapSinkVersion:
413 value->v.integer = t->version;
414 break;
415
416 }
417 return (SNMP_ERR_NOERROR);
418}
419
420static void
421snmp_create_v1_trap(struct snmp_pdu *pdu, char *com,
422 const struct asn_oid *trap_oid)
423{
424 memset(pdu, 0, sizeof(*pdu));
425 strcpy(pdu->community, com);
426
427 pdu->version = SNMP_V1;
428 pdu->type = SNMP_PDU_TRAP;
429 pdu->enterprise = systemg.object_id;
430 memcpy(pdu->agent_addr, snmpd.trap1addr, 4);
431 pdu->generic_trap = trap_oid->subs[trap_oid->len - 1] - 1;
432 pdu->specific_trap = 0;
433 pdu->time_stamp = get_ticks() - start_tick;
434 pdu->nbindings = 0;
435}
436
437static void
438snmp_create_v2_trap(struct snmp_pdu *pdu, char *com,
439 const struct asn_oid *trap_oid)
440{
441 memset(pdu, 0, sizeof(*pdu));
442 strcpy(pdu->community, com);
443
444 pdu->version = SNMP_V2c;
445 pdu->type = SNMP_PDU_TRAP2;
446 pdu->request_id = reqid_next(trap_reqid);
447 pdu->error_index = 0;
448 pdu->error_status = SNMP_ERR_NOERROR;
449
450 pdu->bindings[0].var = oid_sysUpTime;
451 pdu->bindings[0].var.subs[pdu->bindings[0].var.len++] = 0;
452 pdu->bindings[0].syntax = SNMP_SYNTAX_TIMETICKS;
453 pdu->bindings[0].v.uint32 = get_ticks() - start_tick;
454
455 pdu->bindings[1].var = oid_snmpTrapOID;
456 pdu->bindings[1].var.subs[pdu->bindings[1].var.len++] = 0;
457 pdu->bindings[1].syntax = SNMP_SYNTAX_OID;
458 pdu->bindings[1].v.oid = *trap_oid;
459
460 pdu->nbindings = 2;
461}
462
463static void
464snmp_create_v3_trap(struct snmp_pdu *pdu, struct target_param *target,
465 const struct asn_oid *trap_oid)
466{
467 uint64_t etime;
468 struct usm_user *usmuser;
469
470 memset(pdu, 0, sizeof(*pdu));
471
472 pdu->version = SNMP_V3;
473 pdu->type = SNMP_PDU_TRAP2;
474 pdu->request_id = reqid_next(trap_reqid);
475 pdu->error_index = 0;
476 pdu->error_status = SNMP_ERR_NOERROR;
477
478 pdu->bindings[0].var = oid_sysUpTime;
479 pdu->bindings[0].var.subs[pdu->bindings[0].var.len++] = 0;
480 pdu->bindings[0].syntax = SNMP_SYNTAX_TIMETICKS;
481 pdu->bindings[0].v.uint32 = get_ticks() - start_tick;
482
483 pdu->bindings[1].var = oid_snmpTrapOID;
484 pdu->bindings[1].var.subs[pdu->bindings[1].var.len++] = 0;
485 pdu->bindings[1].syntax = SNMP_SYNTAX_OID;
486 pdu->bindings[1].v.oid = *trap_oid;
487
488 pdu->nbindings = 2;
489
490 etime = (get_ticks() - start_tick) / 100ULL;
491 if (etime < INT32_MAX)
492 snmpd_engine.engine_time = etime;
493 else {
494 start_tick = get_ticks();
495 set_snmpd_engine();
496 snmpd_engine.engine_time = start_tick;
497 }
498
499 memcpy(pdu->engine.engine_id, snmpd_engine.engine_id,
500 snmpd_engine.engine_len);
501 pdu->engine.engine_len = snmpd_engine.engine_len;
502 pdu->engine.engine_boots = snmpd_engine.engine_boots;
503 pdu->engine.engine_time = snmpd_engine.engine_time;
504 pdu->engine.max_msg_size = snmpd_engine.max_msg_size;
505 strlcpy(pdu->user.sec_name, target->secname,
506 sizeof(pdu->user.sec_name));
507 pdu->security_model = target->sec_model;
508
509 pdu->context_engine_len = snmpd_engine.engine_len;
510 memcpy(pdu->context_engine, snmpd_engine.engine_id,
511 snmpd_engine.engine_len);
512
513 if (target->sec_model == SNMP_SECMODEL_USM &&
514 target->sec_level != SNMP_noAuthNoPriv) {
515 usmuser = usm_find_user(pdu->engine.engine_id,
516 pdu->engine.engine_len, pdu->user.sec_name);
517 if (usmuser != NULL) {
518 pdu->user.auth_proto = usmuser->suser.auth_proto;
519 pdu->user.priv_proto = usmuser->suser.priv_proto;
520 memcpy(pdu->user.auth_key, usmuser->suser.auth_key,
521 sizeof(pdu->user.auth_key));
522 memcpy(pdu->user.priv_key, usmuser->suser.priv_key,
523 sizeof(pdu->user.priv_key));
524 }
525 snmp_pdu_init_secparams(pdu);
526 }
527}
528
401void
402snmp_send_trap(const struct asn_oid *trap_oid, ...)
403{
404 struct snmp_pdu pdu;
405 struct trapsink *t;
406 const struct snmp_value *v;
529void
530snmp_send_trap(const struct asn_oid *trap_oid, ...)
531{
532 struct snmp_pdu pdu;
533 struct trapsink *t;
534 const struct snmp_value *v;
535 struct target_notify *n;
536 struct target_address *ta;
537 struct target_param *tp;
538
407 va_list ap;
408 u_char *sndbuf;
539 va_list ap;
540 u_char *sndbuf;
541 char *tag;
409 size_t sndlen;
410 ssize_t len;
542 size_t sndlen;
543 ssize_t len;
544 int32_t ip;
411
412 TAILQ_FOREACH(t, &trapsink_list, link) {
413 if (t->status != TRAPSINK_ACTIVE)
414 continue;
545
546 TAILQ_FOREACH(t, &trapsink_list, link) {
547 if (t->status != TRAPSINK_ACTIVE)
548 continue;
415 memset(&pdu, 0, sizeof(pdu));
416 strcpy(pdu.community, t->comm);
417 if (t->version == TRAPSINK_V1) {
418 pdu.version = SNMP_V1;
419 pdu.type = SNMP_PDU_TRAP;
420 pdu.enterprise = systemg.object_id;
421 memcpy(pdu.agent_addr, snmpd.trap1addr, 4);
422 pdu.generic_trap = trap_oid->subs[trap_oid->len - 1] - 1;
423 pdu.specific_trap = 0;
424 pdu.time_stamp = get_ticks() - start_tick;
549
550 if (t->version == TRAPSINK_V1)
551 snmp_create_v1_trap(&pdu, t->comm, trap_oid);
552 else
553 snmp_create_v2_trap(&pdu, t->comm, trap_oid);
425
554
426 pdu.nbindings = 0;
427 } else {
428 pdu.version = SNMP_V2c;
429 pdu.type = SNMP_PDU_TRAP2;
430 pdu.request_id = reqid_next(trap_reqid);
431 pdu.error_index = 0;
432 pdu.error_status = SNMP_ERR_NOERROR;
555 va_start(ap, trap_oid);
556 while ((v = va_arg(ap, const struct snmp_value *)) != NULL)
557 pdu.bindings[pdu.nbindings++] = *v;
558 va_end(ap);
433
559
434 pdu.bindings[0].var = oid_sysUpTime;
435 pdu.bindings[0].var.subs[pdu.bindings[0].var.len++] = 0;
436 pdu.bindings[0].syntax = SNMP_SYNTAX_TIMETICKS;
437 pdu.bindings[0].v.uint32 = get_ticks() - start_tick;
560 if (snmp_pdu_auth_access(&pdu, &ip) != SNMP_CODE_OK) {
561 syslog(LOG_DEBUG, "send trap to %s failed: no access",
562 t->comm);
563 continue;
564 }
438
565
439 pdu.bindings[1].var = oid_snmpTrapOID;
440 pdu.bindings[1].var.subs[pdu.bindings[1].var.len++] = 0;
441 pdu.bindings[1].syntax = SNMP_SYNTAX_OID;
442 pdu.bindings[1].v.oid = *trap_oid;
566 if ((sndbuf = buf_alloc(1)) == NULL) {
567 syslog(LOG_ERR, "trap send buffer: %m");
568 return;
569 }
443
570
444 pdu.nbindings = 2;
571 snmp_output(&pdu, sndbuf, &sndlen, "TRAP");
572
573 if ((len = send(t->socket, sndbuf, sndlen, 0)) == -1)
574 syslog(LOG_ERR, "send: %m");
575 else if ((size_t)len != sndlen)
576 syslog(LOG_ERR, "send: short write %zu/%zu",
577 sndlen, (size_t)len);
578
579 free(sndbuf);
580 }
581
582 SLIST_FOREACH(n, &target_notifylist, tn) {
583 if (n->status != RowStatus_active || n->taglist[0] == '\0')
584 continue;
585
586 SLIST_FOREACH(ta, &target_addresslist, ta)
587 if ((tag = strstr(ta->taglist, n->taglist)) != NULL &&
588 (tag[strlen(n->taglist)] == ' ' ||
589 tag[strlen(n->taglist)] == '\0' ||
590 tag[strlen(n->taglist)] == '\t' ||
591 tag[strlen(n->taglist)] == '\r' ||
592 tag[strlen(n->taglist)] == '\n') &&
593 ta->status == RowStatus_active)
594 break;
595 if (ta == NULL)
596 continue;
597
598 SLIST_FOREACH(tp, &target_paramlist, tp)
599 if (strcmp(tp->name, ta->paramname) == 0 &&
600 tp->status == 1)
601 break;
602 if (tp == NULL)
603 continue;
604
605 switch (tp->mpmodel) {
606 case SNMP_MPM_SNMP_V1:
607 snmp_create_v1_trap(&pdu, tp->secname, trap_oid);
608 break;
609
610 case SNMP_MPM_SNMP_V2c:
611 snmp_create_v2_trap(&pdu, tp->secname, trap_oid);
612 break;
613
614 case SNMP_MPM_SNMP_V3:
615 snmp_create_v3_trap(&pdu, tp, trap_oid);
616 break;
617
618 default:
619 continue;
445 }
446
447 va_start(ap, trap_oid);
448 while ((v = va_arg(ap, const struct snmp_value *)) != NULL)
449 pdu.bindings[pdu.nbindings++] = *v;
450 va_end(ap);
451
620 }
621
622 va_start(ap, trap_oid);
623 while ((v = va_arg(ap, const struct snmp_value *)) != NULL)
624 pdu.bindings[pdu.nbindings++] = *v;
625 va_end(ap);
626
627 if (snmp_pdu_auth_access(&pdu, &ip) != SNMP_CODE_OK) {
628 syslog(LOG_DEBUG, "send trap to %s failed: no access",
629 t->comm);
630 continue;
631 }
632
452 if ((sndbuf = buf_alloc(1)) == NULL) {
453 syslog(LOG_ERR, "trap send buffer: %m");
454 return;
455 }
456
457 snmp_output(&pdu, sndbuf, &sndlen, "TRAP");
458
633 if ((sndbuf = buf_alloc(1)) == NULL) {
634 syslog(LOG_ERR, "trap send buffer: %m");
635 return;
636 }
637
638 snmp_output(&pdu, sndbuf, &sndlen, "TRAP");
639
459 if ((len = send(t->socket, sndbuf, sndlen, 0)) == -1)
640 if ((len = send(ta->socket, sndbuf, sndlen, 0)) == -1)
460 syslog(LOG_ERR, "send: %m");
461 else if ((size_t)len != sndlen)
462 syslog(LOG_ERR, "send: short write %zu/%zu",
463 sndlen, (size_t)len);
464
465 free(sndbuf);
466 }
467}
641 syslog(LOG_ERR, "send: %m");
642 else if ((size_t)len != sndlen)
643 syslog(LOG_ERR, "send: short write %zu/%zu",
644 sndlen, (size_t)len);
645
646 free(sndbuf);
647 }
648}
649
650/*
651 * RFC 3413 SNMP Management Target MIB
652 */
653struct snmpd_target_stats *
654bsnmpd_get_target_stats(void)
655{
656 return (&snmpd_target_stats);
657}
658
659struct target_address *
660target_first_address(void)
661{
662 return (SLIST_FIRST(&target_addresslist));
663}
664
665struct target_address *
666target_next_address(struct target_address *addrs)
667{
668 if (addrs == NULL)
669 return (NULL);
670
671 return (SLIST_NEXT(addrs, ta));
672}
673
674struct target_address *
675target_new_address(char *aname)
676{
677 int cmp;
678 struct target_address *addrs, *temp, *prev;
679
680 SLIST_FOREACH(addrs, &target_addresslist, ta)
681 if (strcmp(aname, addrs->name) == 0)
682 return (NULL);
683
684 if ((addrs = (struct target_address *)malloc(sizeof(*addrs))) == NULL)
685 return (NULL);
686
687 memset(addrs, 0, sizeof(*addrs));
688 strlcpy(addrs->name, aname, sizeof(addrs->name));
689 addrs->timeout = 150;
690 addrs->retry = 3; /* XXX */
691
692 if ((prev = SLIST_FIRST(&target_addresslist)) == NULL ||
693 strcmp(aname, prev->name) < 0) {
694 SLIST_INSERT_HEAD(&target_addresslist, addrs, ta);
695 return (addrs);
696 }
697
698 SLIST_FOREACH(temp, &target_addresslist, ta) {
699 if ((cmp = strcmp(aname, temp->name)) <= 0)
700 break;
701 prev = temp;
702 }
703
704 if (temp == NULL || cmp < 0)
705 SLIST_INSERT_AFTER(prev, addrs, ta);
706 else if (cmp > 0)
707 SLIST_INSERT_AFTER(temp, addrs, ta);
708 else {
709 syslog(LOG_ERR, "Target address %s exists", addrs->name);
710 free(addrs);
711 return (NULL);
712 }
713
714 return (addrs);
715}
716
717int
718target_activate_address(struct target_address *addrs)
719{
720 struct sockaddr_in sa;
721
722 if ((addrs->socket = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
723 syslog(LOG_ERR, "socket(UDP): %m");
724 return (SNMP_ERR_RES_UNAVAIL);
725 }
726
727 (void)shutdown(addrs->socket, SHUT_RD);
728 sa.sin_len = sizeof(sa);
729 sa.sin_family = AF_INET;
730
731 sa.sin_addr.s_addr = htonl((addrs->address[0] << 24) |
732 (addrs->address[1] << 16) | (addrs->address[2] << 8) |
733 (addrs->address[3] << 0));
734 sa.sin_port = htons(addrs->address[4]) << 8 |
735 htons(addrs->address[5]) << 0;
736
737 if (connect(addrs->socket, (struct sockaddr *)&sa, sa.sin_len) == -1) {
738 syslog(LOG_ERR, "connect(%s,%u): %m",
739 inet_ntoa(sa.sin_addr), ntohs(sa.sin_port));
740 (void)close(addrs->socket);
741 return (SNMP_ERR_GENERR);
742 }
743
744 addrs->status = RowStatus_active;
745
746 return (SNMP_ERR_NOERROR);
747}
748
749int
750target_delete_address(struct target_address *addrs)
751{
752 SLIST_REMOVE(&target_addresslist, addrs, target_address, ta);
753 if (addrs->status == RowStatus_active)
754 close(addrs->socket);
755 free(addrs);
756
757 return (0);
758}
759
760struct target_param *
761target_first_param(void)
762{
763 return (SLIST_FIRST(&target_paramlist));
764}
765
766struct target_param *
767target_next_param(struct target_param *param)
768{
769 if (param == NULL)
770 return (NULL);
771
772 return (SLIST_NEXT(param, tp));
773}
774
775struct target_param *
776target_new_param(char *pname)
777{
778 int cmp;
779 struct target_param *param, *temp, *prev;
780
781 SLIST_FOREACH(param, &target_paramlist, tp)
782 if (strcmp(pname, param->name) == 0)
783 return (NULL);
784
785 if ((param = (struct target_param *)malloc(sizeof(*param))) == NULL)
786 return (NULL);
787
788 memset(param, 0, sizeof(*param));
789 strlcpy(param->name, pname, sizeof(param->name));
790
791 if ((prev = SLIST_FIRST(&target_paramlist)) == NULL ||
792 strcmp(pname, prev->name) < 0) {
793 SLIST_INSERT_HEAD(&target_paramlist, param, tp);
794 return (param);
795 }
796
797 SLIST_FOREACH(temp, &target_paramlist, tp) {
798 if ((cmp = strcmp(pname, temp->name)) <= 0)
799 break;
800 prev = temp;
801 }
802
803 if (temp == NULL || cmp < 0)
804 SLIST_INSERT_AFTER(prev, param, tp);
805 else if (cmp > 0)
806 SLIST_INSERT_AFTER(temp, param, tp);
807 else {
808 syslog(LOG_ERR, "Target parameter %s exists", param->name);
809 free(param);
810 return (NULL);
811 }
812
813 return (param);
814}
815
816int
817target_delete_param(struct target_param *param)
818{
819 SLIST_REMOVE(&target_paramlist, param, target_param, tp);
820 free(param);
821
822 return (0);
823}
824
825struct target_notify *
826target_first_notify(void)
827{
828 return (SLIST_FIRST(&target_notifylist));
829}
830
831struct target_notify *
832target_next_notify(struct target_notify *notify)
833{
834 if (notify == NULL)
835 return (NULL);
836
837 return (SLIST_NEXT(notify, tn));
838}
839
840struct target_notify *
841target_new_notify(char *nname)
842{
843 int cmp;
844 struct target_notify *notify, *temp, *prev;
845
846 SLIST_FOREACH(notify, &target_notifylist, tn)
847 if (strcmp(nname, notify->name) == 0)
848 return (NULL);
849
850 if ((notify = (struct target_notify *)malloc(sizeof(*notify))) == NULL)
851 return (NULL);
852
853 memset(notify, 0, sizeof(*notify));
854 strlcpy(notify->name, nname, sizeof(notify->name));
855
856 if ((prev = SLIST_FIRST(&target_notifylist)) == NULL ||
857 strcmp(nname, prev->name) < 0) {
858 SLIST_INSERT_HEAD(&target_notifylist, notify, tn);
859 return (notify);
860 }
861
862 SLIST_FOREACH(temp, &target_notifylist, tn) {
863 if ((cmp = strcmp(nname, temp->name)) <= 0)
864 break;
865 prev = temp;
866 }
867
868 if (temp == NULL || cmp < 0)
869 SLIST_INSERT_AFTER(prev, notify, tn);
870 else if (cmp > 0)
871 SLIST_INSERT_AFTER(temp, notify, tn);
872 else {
873 syslog(LOG_ERR, "Notification target %s exists", notify->name);
874 free(notify);
875 return (NULL);
876 }
877
878 return (notify);
879}
880
881int
882target_delete_notify(struct target_notify *notify)
883{
884 SLIST_REMOVE(&target_notifylist, notify, target_notify, tn);
885 free(notify);
886
887 return (0);
888}
889
890void
891target_flush_all(void)
892{
893 struct target_address *addrs;
894 struct target_param *param;
895 struct target_notify *notify;
896
897 while ((addrs = SLIST_FIRST(&target_addresslist)) != NULL) {
898 SLIST_REMOVE_HEAD(&target_addresslist, ta);
899 if (addrs->status == RowStatus_active)
900 close(addrs->socket);
901 free(addrs);
902 }
903 SLIST_INIT(&target_addresslist);
904
905 while ((param = SLIST_FIRST(&target_paramlist)) != NULL) {
906 SLIST_REMOVE_HEAD(&target_paramlist, tp);
907 free(param);
908 }
909 SLIST_INIT(&target_paramlist);
910
911 while ((notify = SLIST_FIRST(&target_notifylist)) != NULL) {
912 SLIST_REMOVE_HEAD(&target_notifylist, tn);
913 free(notify);
914 }
915 SLIST_INIT(&target_notifylist);
916}