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 * 8 * Redistribution of this software and documentation and use in source and --- 16 unchanged lines hidden (view full) --- 25 * FRAUNHOFER FOKUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 28 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 31 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * |
33 * $Begemot: bsnmp/lib/snmpagent.c,v 1.17 2004/04/13 14:58:46 novo Exp $ |
34 * 35 * SNMP Agent functions 36 */ 37#include <sys/types.h> 38#include <sys/queue.h> 39#include <stdio.h> 40#include <stdlib.h> 41#include <stddef.h> --- 22 unchanged lines hidden (view full) --- 64 size_t len; /* size of data part */ 65 snmp_depop_t func; 66 struct snmp_dependency dep; 67 u_char data[]; 68}; 69TAILQ_HEAD(depend_list, depend); 70 71/* |
72 * Set context 73 */ 74struct context { 75 struct snmp_context ctx; 76 struct depend_list dlist; |
77 const struct snmp_node *node[SNMP_MAX_BINDINGS]; 78 struct snmp_scratch scratch[SNMP_MAX_BINDINGS]; 79 struct depend *depend; 80}; 81 82#define TR(W) (snmp_trace & SNMP_TRACE_##W) 83u_int snmp_trace = 0; 84 --- 7 unchanged lines hidden (view full) --- 92{ 93 struct context *context; 94 95 if ((context = malloc(sizeof(*context))) == NULL) 96 return (NULL); 97 98 memset(context, 0, sizeof(*context)); 99 TAILQ_INIT(&context->dlist); |
100 101 return (&context->ctx); 102} 103 104/* 105 * Find a variable for SET/GET and the first GETBULK pass. 106 * Return the node pointer. If the search fails, set the errp to 107 * the correct SNMPv2 GET exception code. --- 496 unchanged lines hidden (view full) --- 604 asn_oid2str_r(&ctx->dep->idx, idxbuf)); 605 if (ret1 == SNMP_ERR_NOERROR) 606 ret1 = ret; 607 } 608 } 609 return (ret1); 610} 611 |
612void 613snmp_dep_finish(struct snmp_context *ctx) 614{ 615 struct context *context = (struct context *)ctx; 616 struct depend *d; 617 618 while ((d = TAILQ_FIRST(&context->dlist)) != NULL) { 619 ctx->dep = &d->dep; 620 (void)d->func(ctx, ctx->dep, SNMP_DEPOP_FINISH); 621 TAILQ_REMOVE(&context->dlist, d, link); 622 free(d); 623 } 624} 625 |
626/* 627 * Do a SET operation. 628 */ 629enum snmp_ret 630snmp_set(struct snmp_pdu *pdu, struct asn_buf *resp_b, 631 struct snmp_pdu *resp, void *data) 632{ 633 int ret; 634 u_int i; |
635 enum asn_err asnerr; 636 struct context context; 637 const struct snmp_node *np; |
638 struct snmp_value *b; 639 enum snmp_syntax except; 640 641 memset(&context, 0, sizeof(context)); 642 TAILQ_INIT(&context.dlist); |
643 context.ctx.data = data; 644 645 memset(resp, 0, sizeof(*resp)); 646 strcpy(resp->community, pdu->community); 647 resp->type = SNMP_PDU_RESPONSE; 648 resp->request_id = pdu->request_id; 649 resp->version = pdu->version; 650 --- 81 unchanged lines hidden (view full) --- 732 pdu->error_index = i + 1; 733 pdu->error_status = SNMP_ERR_GENERR; 734 snmp_pdu_free(resp); 735 return (SNMP_RET_ERR); 736 } 737 resp->nbindings++; 738 } 739 |
740 context.ctx.code = SNMP_RET_OK; |
741 742 /* 743 * 2. Call the SET method for each node. If a SET fails, rollback 744 * everything. Map error codes depending on the version. 745 */ 746 for (i = 0; i < pdu->nbindings; i++) { 747 b = &pdu->bindings[i]; 748 np = context.node[i]; --- 55 unchanged lines hidden (view full) --- 804 } 805 if (ret != SNMP_ERR_NOERROR) { 806 pdu->error_index = i + 1; 807 pdu->error_status = ret; 808 809 rollback(&context, pdu, i); 810 snmp_pdu_free(resp); 811 |
812 context.ctx.code = SNMP_RET_ERR; |
813 814 goto errout; 815 } 816 } 817 818 /* 819 * 3. Call dependencies 820 */ --- 8 unchanged lines hidden (view full) --- 829 if (pdu->version != SNMP_V1) { 830 pdu->error_status = SNMP_ERR_UNDO_FAILED; 831 pdu->error_index = 0; 832 } 833 } 834 rollback(&context, pdu, i); 835 snmp_pdu_free(resp); 836 |
837 context.ctx.code = SNMP_RET_ERR; |
838 839 goto errout; 840 } 841 842 /* 843 * 4. Commit and copy values from the original packet to the response. 844 * This is not the commit operation from RFC 1905 but rather an 845 * 'FREE RESOURCES' operation. It shouldn't fail. --- 15 unchanged lines hidden (view full) --- 861 snmp_error("set: commit failed (%d) on" 862 " variable %s index %u", ret, 863 asn_oid2str_r(&b->var, oidbuf), i); 864 } 865 866 if (snmp_fix_encoding(resp_b, resp) != SNMP_CODE_OK) { 867 snmp_error("set: fix_encoding failed"); 868 snmp_pdu_free(resp); |
869 context.ctx.code = SNMP_RET_IGN; |
870 } 871 872 /* 873 * Done 874 */ 875 errout: |
876 snmp_dep_finish(&context.ctx); |
877 |
878 if (TR(SET)) |
879 snmp_debug("set: returning %d", context.ctx.code); |
880 |
881 return (context.ctx.code); |
882} 883/* 884 * Lookup a dependency. If it doesn't exist, create one 885 */ 886struct snmp_dependency * 887snmp_dep_lookup(struct snmp_context *ctx, const struct asn_oid *obj, 888 const struct asn_oid *idx, size_t len, snmp_depop_t func) 889{ --- 32 unchanged lines hidden (view full) --- 922 d->func = func; 923 924 TAILQ_INSERT_TAIL(&context->dlist, d, link); 925 926 return (&d->dep); 927} 928 929/* |
930 * Make an error response from a PDU. We do this without decoding the 931 * variable bindings. This means we can sent the junk back to a caller 932 * that has sent us junk in the first place. 933 */ 934enum snmp_ret 935snmp_make_errresp(const struct snmp_pdu *pdu, struct asn_buf *pdu_b, 936 struct asn_buf *resp_b) 937{ --- 60 unchanged lines hidden --- |