1
0
Files
irix-657m-src/irix/cmd/netman/include/protocol.h
2022-09-29 17:59:04 +03:00

371 lines
14 KiB
C

#ifndef PROTOCOL_H
#define PROTOCOL_H
/*
* Copyright 1990 Silicon Graphics, Inc. All rights reserved.
*
* Protocol interface.
*/
#include "datastream.h"
#include "expr.h"
#include "scope.h"
struct snooper;
struct snooppacket;
struct snoopfilter;
struct protostack;
typedef struct protocol {
/* mandatory statically initialized state */
char *pr_name; /* string name */
int pr_namlen; /* and length */
char *pr_title; /* verbose name */
int pr_id; /* fast identifier */
enum dsbyteorder pr_byteorder; /* byte order */
int pr_maxhdrlen; /* frame header size */
struct protofield *pr_discriminant; /* nested type field */
/* protocol operation pointers */
int (*prop_init)(); /* (re)initialize */
int (*prop_setopt)(); /* set option */
void (*prop_embed)(); /* embed in protocol */
Expr *(*prop_resolve)(); /* resolve string */
enum exprtype (*prop_compile)(); /* compile raw filter */
int (*prop_match)(); /* match nested proto */
int (*prop_fetch)(); /* fetch field */
void (*prop_decode)(); /* decode frame */
/* optional statically initialized state */
unsigned short pr_flags; /* optional flags */
unsigned short pr_numoptions; /* number of options */
struct protoptdesc *pr_optdesc; /* option descriptors */
int (*pr_xdrstate)(); /* xdr decode state */
/* automatically initialized state */
struct scope pr_scope; /* symbol table */
int pr_level; /* decoding level */
} Protocol;
/*
* Initialized declaration macro for a protocol interface object.
* Tag is the prefix of the interface structure and of its operations.
* Name must be a string constant or a sized char array.
*/
#define DefineProtocol(tag, name, title, id, order, maxhdrlen, discrim, \
flags, optdesc, numopts, xdrstate) \
int makeident2(tag,_init)(); \
int makeident2(tag,_setopt)(int, char *); \
void makeident2(tag,_embed)(Protocol *, long, long); \
Expr *makeident2(tag,_resolve)(char *, int, struct snooper *); \
ExprType makeident2(tag,_compile)(struct protofield *, Expr *, Expr *, \
struct protocompiler *); \
int makeident2(tag,_match)(Expr *, DataStream *, \
struct protostack *, Expr *); \
int makeident2(tag,_fetch)(struct protofield *, DataStream *, \
struct protostack *, Expr *); \
void makeident2(tag,_decode)(DataStream *, struct protostack *, \
struct packetview *); \
Protocol makeident2(tag,_proto) = { \
name, constrlen(name), title, id, order, maxhdrlen, discrim, \
makeident2(tag,_init), \
makeident2(tag,_setopt), \
makeident2(tag,_embed), \
makeident2(tag,_resolve), \
makeident2(tag,_compile), \
makeident2(tag,_match), \
makeident2(tag,_fetch), \
makeident2(tag,_decode), \
flags, numopts, optdesc, xdrstate, \
}
/*
* Shorter macros to define protocols.
*/
#define DefineBranchProtocol(tag,name,title,id,order,maxhdrlen,discrim) \
DefineProtocol(tag,name,title,id,order,maxhdrlen,discrim,0,0,0,0)
#define DefineLeafProtocol(tag,name,title,id,order,maxhdrlen) \
DefineProtocol(tag,name,title,id,order,maxhdrlen,0,0,0,0,0)
/*
* Macros to call protocol operations.
*/
#define pr_init(pr) ((*(pr)->prop_init)())
#define pr_setopt(pr, id, val) ((*(pr)->prop_setopt)(id, val))
#define pr_embed(pr, npr, type, qual) ((*(pr)->prop_embed)(npr, type, qual))
#define pr_resolve(pr, str, len, sn) ((*(pr)->prop_resolve)(str, len, sn))
#define pr_compile(pr,pf,mex,tex,pc) ((*(pr)->prop_compile)(pf,mex,tex,pc))
#define pr_match(pr, pex, ds, ps, rex) ((*(pr)->prop_match)(pex, ds, ps, rex))
#define pr_fetch(pr, pf, ds, ps, rex) ((*(pr)->prop_fetch)(pf, ds, ps, rex))
#define pr_decode(pr, ds, ps, pv) ((*(pr)->prop_decode)(ds, ps, pv))
/*
* Protocol flags used by generic routines to control operation usage.
*/
#define PR_COMPILETEST 0x0001 /* compile all test expressions */
#define PR_EMBEDCACHED 0x0002 /* embed transiently-nested protocol */
#define PR_MATCHNOTIFY 0x0004 /* notify protocol when matched */
#define PR_DECODESTALE 0x0008 /* decode stale nested protocol */
/*
* Protocol scope operations.
*/
#define pr_lookupsym(pr, name, namlen) \
sc_lookupsym(&(pr)->pr_scope, name, namlen)
#define pr_addsym(pr, name, namlen, type) \
sc_addsym(&(pr)->pr_scope, name, namlen, type)
#define pr_deletesym(pr, name, namlen) \
sc_deletesym(&(pr)->pr_scope, name, namlen)
#define pr_addaddress(pr, name, namlen, addr, addrlen) \
sc_addaddress(&(pr)->pr_scope, name, namlen, addr, addrlen)
#define pr_addnumber(pr, name, namlen, val) \
sc_addnumber(&(pr)->pr_scope, name, namlen, val)
#define pr_addmacro(pr, name, namlen, def, deflen, src) \
sc_addmacro(&(pr)->pr_scope, name, namlen, def, deflen, src)
#define pr_addfunction(pr, name, namlen, func, nargs, desc) \
sc_addfunction(&(pr)->pr_scope, name, namlen, func, nargs, desc)
void sc_addaddress(Scope *, char *, int, char *, int);
void sc_addnumber(Scope *, char *, int, long);
void sc_addmacro(Scope *, char *, int, char *, int, ExprSource *);
void sc_addfunction(Scope *, char *, int, int (*)(), int, char *);
/*
* Generic protocol operations. Initprotocols raises an exception if
* any protocol module cannot be initialized. Possible errors include
* misordered or cyclic protocol dependencies, and invalid protocol
* field descriptors.
*/
struct protomacro;
void initprotocols(void);
Protocol *findprotobyname(char *, int);
Protocol *findprotobyid(unsigned int);
int pr_register(Protocol *, struct protofield *, int, int);
int pr_nest(Protocol *, int, long, struct protomacro *, int);
int pr_nestqual(Protocol *, int, long, long, struct protomacro *,
int);
int pr_unnest(Protocol *, int, long);
int pr_unnestqual(Protocol *, int, long, long);
int pr_test(Protocol *, Expr *, struct snooppacket *, int,
struct snooper *);
int pr_eval(Protocol *, Expr *, struct snooppacket *, int,
struct snooper *, ExprError *, Expr *);
/*
* This function is called by various protocols' match operations to skip
* the current (matched) component in a protocol path expression and then
* to evaluate the remaining components.
*/
int ex_match(Expr *, DataStream *, struct protostack *, Expr *);
/*
* Macros to call protocol and scope operations with constant string names.
*/
#define findprotobyconstname(name) \
findprotobyname(name, constrlen(name))
#define pr_addconstaddress(pr, name, addr, addrlen) \
pr_addaddress(pr, name, constrlen(name), addr, addrlen)
#define pr_addconstnumber(pr, name, val) \
pr_addnumber(pr, name, constrlen(name), val)
#define pr_addconstmacro(pr, name, def) \
pr_addmacro(pr, name, constrlen(name), def, constrlen(def), 0)
#define pr_addconstfunction(pr, name, func, nargs, desc) \
pr_addfunction(pr, name, constrlen(name), func, nargs, desc)
/*
* Protocol field descriptor, passed in a vector to pr_register and added
* to the registered protocol's scope. If pf_size is PF_VARIABLE, then
* pf_off contains a protocol-specific cookie. If pf_size is negative,
* its 2's-complement is the number of bits in the field, and pf_off is
* the bit offset from protocol origin.
*
* If a fixed (bit or byte) protofield passed to pr_register has a negative
* pf_off, pr_register will compute its offset by summing prior field sizes
* with the last field with a non-negative offset, or with zero if all prior
* fields in the vector had negative offsets. Bit fields must sum to a
* byte-congruent size and offset.
*/
#define PF_VARIABLE 0
typedef struct protofield {
char *pf_name; /* field name string */
int pf_namlen; /* name length */
char *pf_title; /* lengthy name string */
int pf_id; /* field identifier code */
void *pf_data; /* type specific data */
int pf_size; /* bitsize if <0, byte if >0 */
int pf_off; /* offset in bits or bytes */
enum exop pf_type; /* expression type */
int pf_level; /* viewing detail level */
} ProtoField;
#define pf_cookie pf_off
#define pf_extendhow(pf) ((enum dsextendhow)(unsigned long)(pf)->pf_data)
#define pf_element(pf) ((ProtoField *) (pf)->pf_data)
#define pf_struct(pf) ((ProtoStruct *) (pf)->pf_data)
/*
* Static initializer macros for variable, byte, bit, and int-typed fields.
* Names must be string constants or char arrays of known size.
* PFI_VAR variable field
* PFI_BYTE fixed-length byte string field
* PFI_ADDR 1- to 8-byte address field
* PFI_SBIT, PFI_UBIT signed/unsigned bit field
* PFI_SINT, PFI_UINT signed/unsigned int field
* PFI_ARRAY, PFI_STRUCT array or structure field
*/
#define PFI(name, title, id, data, size, off, type, level) \
{ name, constrlen(name), title, (int) id, (void *) data, size, off, \
type, level }
#define PFI_VAR(name, title, id, cookie, level) \
PFI(name, title, id, DS_ZERO_EXTEND, PF_VARIABLE, cookie, EXOP_STRING, \
level)
#define PFI_BYTE(name, title, id, size, level) \
PFI(name, title, id, DS_ZERO_EXTEND, size, -1, EXOP_STRING, level)
#define PFI_ADDR(name, title, id, size, level) \
PFI(name, title, id, DS_ZERO_EXTEND, size, -1, EXOP_ADDRESS, level)
#define PFI_BIT(name, title, id, extendhow, bitsize, level) \
PFI(name, title, id, extendhow, -(bitsize), -1, EXOP_NUMBER, level)
#define PFI_SBIT(name, title, id, bitsize, level) \
PFI_BIT(name, title, id, DS_SIGN_EXTEND, bitsize, level)
#define PFI_UBIT(name, title, id, bitsize, level) \
PFI_BIT(name, title, id, DS_ZERO_EXTEND, bitsize, level)
#define PFI_INT(name, title, id, extendhow, type, level) \
PFI(name, title, id, extendhow, sizeof(type), -1, EXOP_NUMBER, level)
#define PFI_SINT(name, title, id, type, level) \
PFI_INT(name, title, id, DS_SIGN_EXTEND, type, level)
#define PFI_UINT(name, title, id, type, level) \
PFI_INT(name, title, id, DS_ZERO_EXTEND, type, level)
#define PFI_ARRAY(name, title, id, type, dim, level) \
PFI(name, title, id, type, dim, -1, EXOP_ARRAY, level)
#define PFI_STRUCT(name, title, id, struct, level) \
PFI(name, title, id, struct, 0, -1, EXOP_STRUCT, level)
#define pr_findfield(pr, pfid) sc_findfield(&(pr)->pr_scope, pfid)
ProtoField *sc_findfield(Scope *, int); /* XXXbe */
/*
* Protocol structure descriptor.
*/
typedef struct protostruct {
/* statically initialized members */
char *pst_name; /* struct tag */
ProtoField *pst_fields; /* array of member fields */
int pst_numfields; /* number of members */
/* dynamically initialized members */
ProtoField *pst_parent; /* this struct's field */
Scope pst_scope; /* symbol table */
} ProtoStruct;
#define PSI(name, fields) { name, fields, lengthof(fields), }
/*
* Protocol option descriptor. Those protocols that implement pr_setopt
* should define an initialized vector of descriptors and pass it to their
* DefineProtocol calls.
*/
typedef struct protoptdesc {
char *pod_name; /* option name */
int pod_id; /* identification code */
char *pod_desc; /* brief description */
} ProtOptDesc;
#define POD(name, id, desc) { name, (int) id, desc }
ProtOptDesc *pr_findoptdesc(Protocol *, const char *);
/*
* Protocol macro, passed in a vector to pr_nest and defined in the
* encapsulating protocol's scope.
*/
typedef struct protomacro {
char *pm_name; /* protocol macro name */
int pm_namlen; /* name string length */
char *pm_def; /* and defined value */
int pm_deflen; /* def string length */
} ProtoMacro;
#define PMI(name, def) { name, constrlen(name), def, constrlen(def) }
#define pr_addmacros(pr, pm, npm) \
sc_addmacros(&(pr)->pr_scope, pm, npm)
void sc_addmacros(Scope *, ProtoMacro *, int);
/*
* Protocol function descriptor, for multiple function definition driven by
* a list of descriptors. If the function takes arguments, pfd_desc should
* end with an '@' followed by a comma-separated formal argument name list.
*/
typedef struct protofuncdesc {
char *pfd_name; /* function name */
int pfd_namlen; /* name string length */
int (*pfd_func)(); /* function pointer */
int pfd_nargs; /* number of arguments */
char *pfd_desc; /* brief description */
} ProtoFuncDesc;
#define PFD(name, func, nargs, desc) \
{ name, constrlen(name), func, nargs, desc }
#define pr_addfunctions(pr, pfd, npfd) \
sc_addfunctions(&(pr)->pr_scope, pfd, npfd)
void sc_addfunctions(Scope *, ProtoFuncDesc *, int);
/*
* Snoop filter compilation uses two datastreams, to encode mask bits
* and field values to match.
*/
typedef struct protocompiler {
unsigned short *pc_errflags; /* pointer to snoop error flags */
DataStream pc_mask; /* encoder for snoopfilter mask */
DataStream pc_match; /* encoder for fields to match */
ExprError *pc_error; /* compiler error report */
} ProtoCompiler;
#define PC_ALLINTBITS (-1L) /* mask to match all bits in any int */
#define PC_ALLBYTES ((char *) 0) /* exact mask for pc_bytes */
#define pc_loc(pc) ds_tell(&(pc)->pc_mask)
void pc_init(ProtoCompiler *, struct snoopfilter *, int,
enum dsbyteorder, unsigned short *,
ExprError *);
void pc_stop(ProtoCompiler *);
enum dsbyteorder pc_setbyteorder(ProtoCompiler *, enum dsbyteorder);
int pc_skipbytes(ProtoCompiler *, int);
int pc_skipbits(ProtoCompiler *, int);
int pc_byte(ProtoCompiler *, char, char);
int pc_bytes(ProtoCompiler *, char *, char *, int);
int pc_bits(ProtoCompiler *, long, long, int);
int pc_short(ProtoCompiler *, short, short);
int pc_long(ProtoCompiler *, long, long);
int pc_int(ProtoCompiler *, long, long, int);
int pc_intfield(ProtoCompiler *, ProtoField *, long,
long, int);
int pc_bytefield(ProtoCompiler *, ProtoField *, char *,
char *, int);
int pc_intmask(ProtoCompiler *, Expr *, long *);
void pc_error(ProtoCompiler *, Expr *, char *);
void pc_badop(ProtoCompiler *, Expr *);
/*
* Default or no-op stubs for use by top-layer and simple protocols.
* setopt, resolve, and match return 0
* embed does nothing
* compile returns ET_COMPLEX, to halt snoop filter compilation
* fetch calls ds_field
*/
int pr_stub_setopt(int, char *);
void pr_stub_embed(Protocol *, long, long);
Expr *pr_stub_resolve(char *, int, struct snooper *);
ExprType pr_stub_compile(ProtoField *, Expr *, Expr *, ProtoCompiler *);
int pr_stub_match(Expr *, DataStream *, struct protostack *, Expr *);
int pr_stub_fetch(ProtoField *, DataStream *, struct protostack *,
Expr *);
#endif