IMPLEMENTING PATTERNS
I - Introduction
A pattern is a set of methods which manipulates buffers. We'll see
later that packets are buffers associated to patterns.
Some patterns are mostly fields, they focus on a particular (in
general small) data type such as "u8" which manipulates an unsigned byte
or "nu16" which manipulates a network unsigned short. Other patterns are
more complex and involves many fields such as ip header.
typedef struct s_pat
{
t_pat_name_proc name_proc; /* Name yourself */
t_pat_off_proc off_proc; /* Get offset to sub-pattern */
t_pat_sub_proc sub_proc; /* Get sub-pattern */
t_pat_sum_proc sum_proc; /* Checksum yourself */
t_pat_get_field_proc get_field_proc; /* Get field */
t_pat_set_field_proc set_field_proc; /* Set field */
t_pat_get_fields_proc get_fields_proc;/* Get possible fields */
t_pat_get_tmpl_proc get_tmpl_proc; /* Get HTML template */
t_pat_get_tmpl2_proc get_tmpl2_proc; /* Unused for now */
t_pat_has_opt_proc has_opt_proc; /* Have you got options ? */
t_pat_adapt_len_proc adapt_len_proc; /* Adapt length fields */
t_pat_get_field_pat_proc get_field_pat_proc;/* Get more about field */
t_pat_extract_proc extract_proc; /* Extract yourself */
t_pat_insert_proc insert_proc; /* Insert yourself */
t_pat_get_choices_proc get_choices_proc;/* Get possible choices */
} t_pat;
Typically, a minimal "field" pattern has got only name_proc, extract_proc
and insert_proc while a "complex" pattern must have at least
name_proc, get_field_proc and get_tmpl_proc. They are able to display
themselves.
But there are some patterns which are both "fields" and "complex",
such as "inaddr".
II - Methods
The simplest thing to write patterns is to inspire by an existing one.
Here is a little explanation about methods:
First, all methods might be NULL, but you would have some problems in
the case of name_proc is NULL!
1) name_proc
This method is used to guess the name of a pattern according to a
context (an id). By example for ip pattern, if optional_id is NULL it
might be "ip", otherwise it might be "ip[0]" or "ip[1]".
typedef t_status (*t_pat_name_proc) P((VOID_PTR data,
t_id *optional_id,
char *str,
int max_len));
Usually, you won't have to implement this method by yourself, there is
a macro which does the job for you:
PAT_NAME_GENERIC(Proc,Chan,Name)
This macro defines a function named Proc which calls
pat_name_generic(3). This function uses value pointed by Chan in id to
compute indexation and then increments this value.
Note: Each pattern should have at least one channel. Address of this channel
is used to identify this pattern in an id. See also id management in
mg_id.c.
2) off_proc
This method is used to guess pattern length. It is also used to guess
offset of sub-pattern.
typedef t_status (*t_pat_off_proc) P((VOID_PTR data,
char *buf,
int len,
t_off *off_return));
PAT_OFF_GENERIC(Proc,Off)
This macro will simply returns Off as offset. This is valid for
patterns which have a fixed length such as "ether".
3) sub_proc
It is used to guess sub-pattern. Usually, patterns determine its
sub-patterns against specific fields: E.g ip uses "protocol" field to
determine if sub-pattern is udp, tcp or icmp ...
typedef t_status (*t_pat_sub_proc) P((VOID_PTR data,
t_id *optional_id,
char *buf,
int len,
struct s_pat **pat_return));
PAT_SUB_GENERIC(Proc,SubPat)
This macro will simply returns SubPat as sub-pattern. This is valid for
patterns which have always the same pattern after them.
4) sum_proc
It is used to checksum buffer.
typedef t_status (*t_pat_sum_proc) P((VOID_PTR data,
char *buf,
int len,
char *up_buf,
int up_len));
Because some patterns need upper pattern's buffer for their checksum
(such as udp or tcp which need a portion of ip header), the method
caller provides up_buf and up_len.
5) get_field_proc
It is used to retrieve field values.
typedef t_status (*t_pat_get_field_proc) P((VOID_PTR data,
t_id *optional_id,
char *buf,
int len,
char *field,
char *str,
int max_len));
PAT_GET_FIELD_GENERIC(Proc,Fields)
This macro creates a fonction which calls
pat_get_field_generic(3). This function examines an array of t_field.
6) set_field_proc
It is used to set field values.
typedef t_status (*t_pat_get_field_proc) P((VOID_PTR data,
t_id *optional_id,
char *buf,
int len,
char *field,
char *value));
PAT_SET_FIELD_GENERIC(Proc,Fields)
This macro creates a fonction which calls
pat_set_field_generic(3). This function examines an array of t_field.
7) get_fields_proc
Retrieves all fields known by patterns in a vector of strings.
typedef t_status (*t_pat_get_fields_proc) P((VOID_PTR data,
t_vec *vec_str));
PAT_GET_FIELDS_GENERIC(Proc,Fields)
8) get_tmpl_proc
Get HTMP template associated to pattern.
typedef t_status (*t_pat_get_tmpl_proc) P((VOID_PTR data,
t_id *id,
char *buf,
int len,
char *str,
int max_len));
PAT_GET_TMPL_GENERIC(Proc,Chan,ITmpl)
9) get_tmpl2_proc
Unused for now.
typedef t_status (*t_pat_get_tmpl2_proc) P((VOID_PTR data,
t_id *id,
char *buf,
int len,
char *str,
int max_len));
PAT_GET_TMPL2_GENERIC(Proc,Chan,ITmpl2)
10) has_opt_proc
Ask pattern if it has options.
typedef t_status (*t_pat_has_opt_proc) P((VOID_PTR data,
char *buf,
int len,
t_boolean *has_opt_return,
t_off *opt_off_return,
int *opt_len_return,
struct s_pat **opt_pat_return,
VOID_PTR *opt_data_return));
11) adapt_len_proc
Make pattern arranging its various length fields to current values.
typedef t_status (*t_pat_adapt_len_proc) P((VOID_PTR data,
char *buf,
int len));
12) get_field_pat_proc
Get pattern of field. It is used to know more about fields.
typedef t_status (*t_pat_get_field_pat_proc) P((VOID_PTR data,
t_id *optional_id,
char *buf,
int len,
char *field,
struct s_pat **pat_return,
VOID_PTR *data_return));
PAT_GET_FIELD_PAT_GENERIC(Proc,Fields)
13) extract_proc
Extracts the pattern to a string representation.
typedef t_status (*t_pat_extract_proc) P((VOID_PTR data,
char *buf,
int len,
char *str,
int max_len));
14) insert_proc
Inserts a pattern from a string representation.
typedef t_status (*t_pat_insert_proc) P((VOID_PTR data,
char *buf,
int len,
char *value));
15) get_choices_proc
Get different possible values for pattern.
typedef t_status (*t_pat_get_choices_proc) P((VOID_PTR data,
char *buf,
int len,
t_vec *vec_str,
t_boolean *do_sort_return));