/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * GXSNMP -- An snmp mangament application
 * Copyright (C) 1998 Gregory McLean & Jochen Friedrich
 * Beholder RMON ethernet network monitor,Copyright (C) 1993 DNPAP group
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#include <glib.h>

#ifndef _GXSNMP_ASN1_H_
#define _GXSNMP_ASN1_H_

/* ASN1 Class */
typedef enum
{
  GXSNMP_ASN1_UNI = 0, /* Universal   */
  GXSNMP_ASN1_APL = 1, /* Application */
  GXSNMP_ASN1_CTX = 2, /* Context     */
  GXSNMP_ASN1_PRV = 3  /* Private     */
} GxsnmpAsn1Class;

/* ASN1 Tag */
typedef enum
{
  GXSNMP_ASN1_EOC    =  0, /* End Of Contents    */
  GXSNMP_ASN1_BOL    =  1, /* Boolean            */
  GXSNMP_ASN1_INT    =  2, /* Integer            */
  GXSNMP_ASN1_BTS    =  3, /* Bit String         */
  GXSNMP_ASN1_OTS    =  4, /* Octet String       */
  GXSNMP_ASN1_NUL    =  5, /* Null               */
  GXSNMP_ASN1_OJI    =  6, /* Object Identifier  */
  GXSNMP_ASN1_OJD    =  7, /* Object Description */
  GXSNMP_ASN1_EXT    =  8, /* External           */
  GXSNMP_ASN1_SEQ    = 16, /* Sequence           */
  GXSNMP_ASN1_SET    = 17, /* Set                */
  GXSNMP_ASN1_NUMSTR = 18, /* Numerical String   */
  GXSNMP_ASN1_PRNSTR = 19, /* Printable String   */
  GXSNMP_ASN1_TEXSTR = 20, /* Teletext String    */
  GXSNMP_ASN1_VIDSTR = 21, /* Video String       */
  GXSNMP_ASN1_IA5STR = 22, /* IA5 String         */
  GXSNMP_ASN1_UNITIM = 23, /* Universal Time     */
  GXSNMP_ASN1_GENTIM = 24, /* General Time       */
  GXSNMP_ASN1_GRASTR = 25, /* Graphical String   */
  GXSNMP_ASN1_VISSTR = 26, /* Visible String     */
  GXSNMP_ASN1_GENSTR = 27  /* General String     */
} GxsnmpAsn1Tag;

/* ASN1 Primitie / Constructed */
typedef enum
{
  GXSNMP_ASN1_PRI = 0, /* Primitive   */
  GXSNMP_ASN1_CON = 1  /* Constructed */
} GxsnmpAsn1Constructed;

/* Mode to open ASN11 */
typedef enum
{
  GXSNMP_ASN1_ENC = 0, /* encoding */
  GXSNMP_ASN1_DEC = 1  /* decoding */
} GxsnmpAsn1Mode; 

typedef enum
{
  GXSNMP_ASN1_ERR_NOERROR	      = 0, /* No error          */
  GXSNMP_ASN1_ERR_ENC_FULL	      = 1, /* Encoding Overrun  */
  GXSNMP_ASN1_ERR_DEC_EMPTY	      = 2, /* Decoding Underrun */
  GXSNMP_ASN1_ERR_DEC_EOC_MISMATCH    = 3,
  GXSNMP_ASN1_ERR_DEC_LENGTH_MISMATCH = 4, 
  GXSNMP_ASN1_ERR_DEC_BADVALUE	      = 5, /* Decoding Overflow */
  GXSNMP_ASN1_ERR_ENC_BADVALUE	      = 6  /* Invalid OID       */
} GxsnmpAsn1Error;

typedef struct _GxsnmpAsn1 GxsnmpAsn1;

struct _GxsnmpAsn1
{                                   /* ASN1 object                         */
    guchar         *pointer;        /* Octet just encoded or to be decoded */
    guchar         *begin;          /* First octet                         */
    guchar         *end;            /* Octet after last octet              */
    GxsnmpAsn1Error error;          /* Error condition                     */
};


GxsnmpAsn1* gxsnmp_asn1_new (guchar *buf, guint len, GxsnmpAsn1Mode mode);
void gxsnmp_asn1_destroy (GxsnmpAsn1 *asn1, guchar **buf, guint *len);
gboolean gxsnmp_asn1_octet_encode (GxsnmpAsn1 *asn1, guchar ch);
gboolean gxsnmp_asn1_octet_decode (GxsnmpAsn1 *asn1, guchar *ch);
gboolean gxsnmp_asn1_tag_encode (GxsnmpAsn1 *asn1, GxsnmpAsn1Tag tag);
gboolean gxsnmp_asn1_tag_decode (GxsnmpAsn1 *asn1, GxsnmpAsn1Tag *tag);
gboolean gxsnmp_asn1_id_encode (GxsnmpAsn1 *asn1, GxsnmpAsn1Class cls, 
		GxsnmpAsn1Constructed con, GxsnmpAsn1Tag tag);
gboolean gxsnmp_asn1_id_decode (GxsnmpAsn1 *asn1, GxsnmpAsn1Class *cls,
		GxsnmpAsn1Constructed *con, GxsnmpAsn1Tag *tag);
gboolean gxsnmp_asn1_length_encode (GxsnmpAsn1 *asn1, guint def, guint len);
gboolean gxsnmp_asn1_length_decode (GxsnmpAsn1 *asn1, guint *def, guint *len);
gboolean gxsnmp_asn1_header_encode (GxsnmpAsn1 *asn1, guchar *eoc, 
		GxsnmpAsn1Class cls, GxsnmpAsn1Constructed con, 
		GxsnmpAsn1Tag tag);
gboolean gxsnmp_asn1_header_decode (GxsnmpAsn1 *asn1, guchar **eoc,
		GxsnmpAsn1Class *cls, GxsnmpAsn1Constructed *con, 
		GxsnmpAsn1Tag *tag);
gboolean gxsnmp_asn1_eoc (GxsnmpAsn1 *asn1, guchar *eoc);
gboolean gxsnmp_asn1_eoc_encode (GxsnmpAsn1 *asn1, guchar **eoc);
gboolean gxsnmp_asn1_eoc_decode (GxsnmpAsn1 *asn1, guchar *eoc);
gboolean gxsnmp_asn1_null_encode (GxsnmpAsn1 *asn1, guchar **eoc);
gboolean gxsnmp_asn1_null_decode (GxsnmpAsn1 *asn1, guchar *eoc);
gboolean gxsnmp_asn1_boolean_encode (GxsnmpAsn1 *asn1, guchar **eoc, 
		gboolean bool);
gboolean gxsnmp_asn1_boolean_decode (GxsnmpAsn1 *asn1, guchar *eoc, 
		gboolean *bool);
gboolean gxsnmp_asn1_int_encode (GxsnmpAsn1 *asn1, guchar **eoc, gint integen);
gboolean gxsnmp_asn1_int_decode (GxsnmpAsn1 *asn1, guchar *eoc, gint *integer);
gboolean gxsnmp_asn1_long_encode (GxsnmpAsn1 *asn1, guchar **eoc, 
		glong integer);
gboolean gxsnmp_asn1_long_decode (GxsnmpAsn1 *asn1, guchar *eoc, 
		glong *integer);
gboolean gxsnmp_asn1_uint_encode (GxsnmpAsn1 *asn1, guchar **eoc, 
		guint integer);
gboolean gxsnmp_asn1_uint_decode (GxsnmpAsn1 *asn1, guchar *eoc, 
		guint *integer);
gboolean gxsnmp_asn1_ulong_encode (GxsnmpAsn1 *asn1, guchar **eoc, 
		gulong integer);
gboolean gxsnmp_asn1_ulong_decode (GxsnmpAsn1 *asn1, guchar *eoc, 
		gulong *integer);
gboolean gxsnmp_asn1_bits_encode (GxsnmpAsn1 *asn1, guchar **eoc, guchar *bits, 
		guint len, guchar unused);
gboolean gxsnmp_asn1_bits_decode (GxsnmpAsn1 *asn1, guchar *eoc, guchar **bits, 
		guint *len, guchar *unused);
gboolean gxsnmp_asn1_octets_encode (GxsnmpAsn1 *asn1, guchar **eoc,
		guchar *octs, guint len);
gboolean gxsnmp_asn1_octets_decode (GxsnmpAsn1 *asn1, guchar *eoc,
		guchar **octs, guint *len);
gboolean gxsnmp_asn1_subid_encode (GxsnmpAsn1 *asn1, gulong subid);
gboolean gxsnmp_asn1_subid_decode (GxsnmpAsn1 *asn1, gulong *subid);
gboolean gxsnmp_asn1_oid_encode (GxsnmpAsn1 *asn1, guchar **eoc, 
		gulong *oid, guint len);
gboolean gxsnmp_asn1_oid_decode (GxsnmpAsn1 *asn1, guchar *eoc, 
		gulong **oid, guint *len);
#endif
