1122394Sharti/* 2122394Sharti * Copyright (c) 2001-2003 3122394Sharti * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4122394Sharti * All rights reserved. 5122394Sharti * 6122394Sharti * Author: Harti Brandt <harti@freebsd.org> 7133211Sharti * 8133211Sharti * Redistribution and use in source and binary forms, with or without 9133211Sharti * modification, are permitted provided that the following conditions 10133211Sharti * are met: 11133211Sharti * 1. Redistributions of source code must retain the above copyright 12133211Sharti * notice, this list of conditions and the following disclaimer. 13122394Sharti * 2. Redistributions in binary form must reproduce the above copyright 14122394Sharti * notice, this list of conditions and the following disclaimer in the 15122394Sharti * documentation and/or other materials provided with the distribution. 16133211Sharti * 17133211Sharti * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18133211Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19133211Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20133211Sharti * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 21133211Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22133211Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23133211Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24133211Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25133211Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26133211Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27133211Sharti * SUCH DAMAGE. 28122394Sharti * 29156066Sharti * $Begemot: bsnmp/snmpd/export.c,v 1.8 2006/02/14 09:04:20 brandt_h Exp $ 30122394Sharti * 31122394Sharti * Support functions for modules. 32122394Sharti */ 33122394Sharti#include <sys/types.h> 34216294Ssyrinx#include <sys/queue.h> 35122394Sharti#include <sys/un.h> 36122394Sharti#include <stdio.h> 37122394Sharti#include <stdlib.h> 38122394Sharti#include <string.h> 39122394Sharti#include <syslog.h> 40122394Sharti#include <stdarg.h> 41122394Sharti 42122394Sharti#include "snmpmod.h" 43122394Sharti#include "snmpd.h" 44122394Sharti#include "tree.h" 45122394Sharti 46122394Sharti/* 47122394Sharti * Support functions 48122394Sharti */ 49122394Sharti 50122394Sharti/* 51122394Sharti * This is user for SET of string variables. If 'req' is not -1 then 52122394Sharti * the arguments is checked to be of that length. The old value is saved 53122394Sharti * in scratch->ptr1 and the new value is allocated and copied. 54122394Sharti * If there is an old values it must have been allocated by malloc. 55122394Sharti */ 56122394Shartiint 57122394Shartistring_save(struct snmp_value *value, struct snmp_context *ctx, 58122394Sharti ssize_t req_size, u_char **valp) 59122394Sharti{ 60122394Sharti if (req_size != -1 && value->v.octetstring.len != (u_long)req_size) 61122394Sharti return (SNMP_ERR_BADVALUE); 62122394Sharti 63122394Sharti ctx->scratch->ptr1 = *valp; 64122394Sharti 65122394Sharti if ((*valp = malloc(value->v.octetstring.len + 1)) == NULL) { 66122394Sharti *valp = ctx->scratch->ptr1; 67122394Sharti return (SNMP_ERR_RES_UNAVAIL); 68122394Sharti } 69122394Sharti 70122394Sharti memcpy(*valp, value->v.octetstring.octets, value->v.octetstring.len); 71122394Sharti (*valp)[value->v.octetstring.len] = '\0'; 72122394Sharti 73122394Sharti return (0); 74122394Sharti} 75122394Sharti 76122394Sharti/* 77122394Sharti * Commit a string. This is easy - free the old value. 78122394Sharti */ 79122394Shartivoid 80122394Shartistring_commit(struct snmp_context *ctx) 81122394Sharti{ 82122394Sharti free(ctx->scratch->ptr1); 83122394Sharti} 84122394Sharti 85122394Sharti/* 86122394Sharti * Rollback a string - free new value and copy back old one. 87122394Sharti */ 88122394Shartivoid 89122394Shartistring_rollback(struct snmp_context *ctx, u_char **valp) 90122394Sharti{ 91122394Sharti free(*valp); 92122394Sharti *valp = ctx->scratch->ptr1; 93122394Sharti} 94122394Sharti 95122394Sharti/* 96122394Sharti * ROLLBACK or COMMIT fails because instance has disappeared. Free string. 97122394Sharti */ 98122394Shartivoid 99122394Shartistring_free(struct snmp_context *ctx) 100122394Sharti{ 101122394Sharti free(ctx->scratch->ptr1); 102122394Sharti} 103122394Sharti 104122394Sharti/* 105122394Sharti * Get a string value for a response packet 106122394Sharti */ 107122394Shartiint 108122394Shartistring_get(struct snmp_value *value, const u_char *ptr, ssize_t len) 109122394Sharti{ 110122394Sharti if (ptr == NULL) { 111122394Sharti value->v.octetstring.len = 0; 112122394Sharti value->v.octetstring.octets = NULL; 113122394Sharti return (SNMP_ERR_NOERROR); 114122394Sharti } 115122394Sharti if (len == -1) 116122394Sharti len = strlen(ptr); 117122394Sharti value->v.octetstring.len = (u_long)len; 118122394Sharti if ((value->v.octetstring.octets = malloc((size_t)len)) == NULL) 119122394Sharti return (SNMP_ERR_RES_UNAVAIL); 120122394Sharti memcpy(value->v.octetstring.octets, ptr, (size_t)len); 121122394Sharti return (SNMP_ERR_NOERROR); 122122394Sharti} 123122394Sharti 124122394Sharti/* 125155429Sharti * Get a string value for a response packet but cut it if it is too long. 126155429Sharti */ 127155429Shartiint 128155429Shartistring_get_max(struct snmp_value *value, const u_char *ptr, ssize_t len, 129155429Sharti size_t maxlen) 130155429Sharti{ 131155429Sharti 132155429Sharti if (ptr == NULL) { 133155429Sharti value->v.octetstring.len = 0; 134155429Sharti value->v.octetstring.octets = NULL; 135155429Sharti return (SNMP_ERR_NOERROR); 136155429Sharti } 137155429Sharti if (len == -1) 138155429Sharti len = strlen(ptr); 139155429Sharti if ((size_t)len > maxlen) 140155429Sharti len = maxlen; 141155429Sharti value->v.octetstring.len = (u_long)len; 142155429Sharti if ((value->v.octetstring.octets = malloc((size_t)len)) == NULL) 143155429Sharti return (SNMP_ERR_RES_UNAVAIL); 144155429Sharti memcpy(value->v.octetstring.octets, ptr, (size_t)len); 145155429Sharti return (SNMP_ERR_NOERROR); 146155429Sharti} 147155429Sharti 148155429Sharti/* 149122394Sharti * Support for IPADDRESS 150122394Sharti * 151122394Sharti * Save the old IP address in scratch->int1 and set the new one. 152122394Sharti */ 153122394Shartiint 154122394Shartiip_save(struct snmp_value *value, struct snmp_context *ctx, u_char *valp) 155122394Sharti{ 156122394Sharti ctx->scratch->int1 = (valp[0] << 24) | (valp[1] << 16) | (valp[2] << 8) 157122394Sharti | valp[3]; 158122394Sharti 159122394Sharti valp[0] = value->v.ipaddress[0]; 160122394Sharti valp[1] = value->v.ipaddress[1]; 161122394Sharti valp[2] = value->v.ipaddress[2]; 162122394Sharti valp[3] = value->v.ipaddress[3]; 163122394Sharti 164122394Sharti return (0); 165122394Sharti} 166122394Sharti 167122394Sharti/* 168122394Sharti * Rollback the address by copying back the old one 169122394Sharti */ 170122394Shartivoid 171122394Shartiip_rollback(struct snmp_context *ctx, u_char *valp) 172122394Sharti{ 173122394Sharti valp[0] = ctx->scratch->int1 >> 24; 174122394Sharti valp[1] = ctx->scratch->int1 >> 16; 175122394Sharti valp[2] = ctx->scratch->int1 >> 8; 176122394Sharti valp[3] = ctx->scratch->int1; 177122394Sharti} 178122394Sharti 179122394Sharti/* 180122394Sharti * Nothing to do for commit 181122394Sharti */ 182122394Shartivoid 183122394Shartiip_commit(struct snmp_context *ctx __unused) 184122394Sharti{ 185122394Sharti} 186122394Sharti 187122394Sharti/* 188122394Sharti * Retrieve an IP address 189122394Sharti */ 190122394Shartiint 191122394Shartiip_get(struct snmp_value *value, u_char *valp) 192122394Sharti{ 193122394Sharti value->v.ipaddress[0] = valp[0]; 194122394Sharti value->v.ipaddress[1] = valp[1]; 195122394Sharti value->v.ipaddress[2] = valp[2]; 196122394Sharti value->v.ipaddress[3] = valp[3]; 197122394Sharti return (SNMP_ERR_NOERROR); 198122394Sharti} 199122394Sharti 200122394Sharti/* 201122394Sharti * Object ID support 202122394Sharti * 203122394Sharti * Save the old value in a fresh allocated oid pointed to by scratch->ptr1. 204122394Sharti */ 205122394Shartiint 206122394Shartioid_save(struct snmp_value *value, struct snmp_context *ctx, 207122394Sharti struct asn_oid *oid) 208122394Sharti{ 209122394Sharti if ((ctx->scratch->ptr1 = malloc(sizeof(struct asn_oid))) == NULL) 210122394Sharti return (SNMP_ERR_RES_UNAVAIL); 211122394Sharti *(struct asn_oid *)ctx->scratch->ptr1 = *oid; 212122394Sharti *oid = value->v.oid; 213122394Sharti 214122394Sharti return (0); 215122394Sharti} 216122394Sharti 217122394Shartivoid 218122394Shartioid_rollback(struct snmp_context *ctx, struct asn_oid *oid) 219122394Sharti{ 220122394Sharti *oid = *(struct asn_oid *)ctx->scratch->ptr1; 221122394Sharti free(ctx->scratch->ptr1); 222122394Sharti} 223122394Sharti 224122394Shartivoid 225122394Shartioid_commit(struct snmp_context *ctx) 226122394Sharti{ 227122394Sharti free(ctx->scratch->ptr1); 228122394Sharti} 229122394Sharti 230122394Shartiint 231122394Shartioid_get(struct snmp_value *value, const struct asn_oid *oid) 232122394Sharti{ 233122394Sharti value->v.oid = *oid; 234122394Sharti return (SNMP_ERR_NOERROR); 235122394Sharti} 236122394Sharti 237122394Sharti/* 238122394Sharti * Decode an index 239122394Sharti */ 240122394Shartiint 241122394Shartiindex_decode(const struct asn_oid *oid, u_int sub, u_int code, ...) 242122394Sharti{ 243122394Sharti va_list ap; 244122394Sharti u_int index_count; 245122394Sharti void *octs[10]; 246122394Sharti u_int nocts; 247122394Sharti u_int idx; 248122394Sharti 249122394Sharti va_start(ap, code); 250122394Sharti index_count = SNMP_INDEX_COUNT(code); 251122394Sharti nocts = 0; 252122394Sharti 253122394Sharti for (idx = 0; idx < index_count; idx++) { 254122394Sharti switch (SNMP_INDEX(code, idx)) { 255122394Sharti 256122394Sharti case SNMP_SYNTAX_NULL: 257122394Sharti break; 258122394Sharti 259122394Sharti case SNMP_SYNTAX_INTEGER: 260122394Sharti if (sub == oid->len) 261122394Sharti goto err; 262122394Sharti *va_arg(ap, int32_t *) = oid->subs[sub++]; 263122394Sharti break; 264122394Sharti 265122394Sharti case SNMP_SYNTAX_COUNTER64: 266122394Sharti if (sub == oid->len) 267122394Sharti goto err; 268122394Sharti *va_arg(ap, u_int64_t *) = oid->subs[sub++]; 269122394Sharti break; 270122394Sharti 271122394Sharti case SNMP_SYNTAX_OCTETSTRING: 272122394Sharti { 273122394Sharti u_char **cval; 274122394Sharti size_t *sval; 275122394Sharti u_int i; 276122394Sharti 277122394Sharti /* only variable size supported */ 278122394Sharti if (sub == oid->len) 279122394Sharti goto err; 280122394Sharti cval = va_arg(ap, u_char **); 281122394Sharti sval = va_arg(ap, size_t *); 282122394Sharti *sval = oid->subs[sub++]; 283122394Sharti if (sub + *sval > oid->len) 284122394Sharti goto err; 285122394Sharti if ((*cval = malloc(*sval)) == NULL) { 286122394Sharti syslog(LOG_ERR, "%s: %m", __func__); 287122394Sharti goto err; 288122394Sharti } 289122394Sharti octs[nocts++] = *cval; 290122394Sharti for (i = 0; i < *sval; i++) { 291122394Sharti if (oid->subs[sub] > 0xff) 292122394Sharti goto err; 293122394Sharti (*cval)[i] = oid->subs[sub++]; 294122394Sharti } 295122394Sharti break; 296122394Sharti } 297122394Sharti 298122394Sharti case SNMP_SYNTAX_OID: 299122394Sharti { 300122394Sharti struct asn_oid *aval; 301122394Sharti u_int i; 302122394Sharti 303122394Sharti if (sub == oid->len) 304122394Sharti goto err; 305122394Sharti aval = va_arg(ap, struct asn_oid *); 306122394Sharti aval->len = oid->subs[sub++]; 307122394Sharti if (aval->len > ASN_MAXOIDLEN) 308122394Sharti goto err; 309122394Sharti for (i = 0; i < aval->len; i++) 310122394Sharti aval->subs[i] = oid->subs[sub++]; 311122394Sharti break; 312122394Sharti } 313122394Sharti 314122394Sharti case SNMP_SYNTAX_IPADDRESS: 315122394Sharti { 316122394Sharti u_int8_t *pval; 317122394Sharti u_int i; 318122394Sharti 319122394Sharti if (sub + 4 > oid->len) 320122394Sharti goto err; 321122394Sharti pval = va_arg(ap, u_int8_t *); 322122394Sharti for (i = 0; i < 4; i++) { 323122394Sharti if (oid->subs[sub] > 0xff) 324122394Sharti goto err; 325122394Sharti pval[i] = oid->subs[sub++]; 326122394Sharti } 327122394Sharti break; 328122394Sharti } 329122394Sharti 330122394Sharti case SNMP_SYNTAX_COUNTER: 331122394Sharti case SNMP_SYNTAX_GAUGE: 332122394Sharti case SNMP_SYNTAX_TIMETICKS: 333122394Sharti if (sub == oid->len) 334122394Sharti goto err; 335122394Sharti if (oid->subs[sub] > 0xffffffff) 336122394Sharti goto err; 337122394Sharti *va_arg(ap, u_int32_t *) = oid->subs[sub++]; 338122394Sharti break; 339122394Sharti } 340122394Sharti } 341122394Sharti 342122394Sharti va_end(ap); 343122394Sharti return (0); 344122394Sharti 345122394Sharti err: 346122394Sharti va_end(ap); 347122394Sharti while(nocts > 0) 348122394Sharti free(octs[--nocts]); 349122394Sharti return (-1); 350122394Sharti} 351122394Sharti 352122394Sharti/* 353122394Sharti * Compare the index part of an OID and an index. 354122394Sharti */ 355122394Shartiint 356122394Shartiindex_compare_off(const struct asn_oid *oid, u_int sub, 357122394Sharti const struct asn_oid *idx, u_int off) 358122394Sharti{ 359122394Sharti u_int i; 360122394Sharti 361122394Sharti for (i = off; i < idx->len && i < oid->len - sub; i++) { 362122394Sharti if (oid->subs[sub + i] < idx->subs[i]) 363122394Sharti return (-1); 364122394Sharti if (oid->subs[sub + i] > idx->subs[i]) 365122394Sharti return (+1); 366122394Sharti } 367122394Sharti if (oid->len - sub < idx->len) 368122394Sharti return (-1); 369122394Sharti if (oid->len - sub > idx->len) 370122394Sharti return (+1); 371122394Sharti 372122394Sharti return (0); 373122394Sharti} 374122394Sharti 375122394Shartiint 376122394Shartiindex_compare(const struct asn_oid *oid, u_int sub, const struct asn_oid *idx) 377122394Sharti{ 378122394Sharti return (index_compare_off(oid, sub, idx, 0)); 379122394Sharti} 380122394Sharti 381122394Sharti/* 382122394Sharti * Append an index to an oid 383122394Sharti */ 384122394Shartivoid 385122394Shartiindex_append_off(struct asn_oid *var, u_int sub, const struct asn_oid *idx, 386122394Sharti u_int off) 387122394Sharti{ 388122394Sharti u_int i; 389122394Sharti 390122394Sharti var->len = sub + idx->len; 391122394Sharti for (i = off; i < idx->len; i++) 392122394Sharti var->subs[sub + i] = idx->subs[i]; 393122394Sharti} 394122394Shartivoid 395122394Shartiindex_append(struct asn_oid *var, u_int sub, const struct asn_oid *idx) 396122394Sharti{ 397122394Sharti index_append_off(var, sub, idx, 0); 398122394Sharti} 399122394Sharti 400