
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));