#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <unistd.h>
#include "hdr_comm.h"
int verbose;
/* local yokel's */
static u_int dup_token_field (char *line, trans_info_t *ti);
static u_int is_from_field (char *line, trans_info_t *ti);
static u_int is_list_field (trace_t *tr, char *line, trans_info_t *ti);
static u_int int_type_field (char *line, trans_info_t *ti);
static u_int list_members_field (trace_t *tr, char *line, trans_info_t *ti);
static int get_list_members (trace_t *tr, char *p, char *addr_buf, char **next);
static int present_in_list (char *list, char *last, char *target_str);
static int is_valid_op (char *);
static char *my_concat (char *, char *);
static char *free_mem (char *);
static int find_token (char **x, char **y);
static char *myconcat (char *x, char *y);
static u_int is_new_list_field (trace_t *tr, char *line, trans_info_t *ti);
/* Action is to initialize the trans_info struct
* with the header information located at the begining
* of the transaction and to mark the fields that were encountred.
* Routine assumes the file pos pointer is on the field immediately
* after the 'HDR-START' field.
*
* Return:
* 0 'HDR-END' is encountered
* 1 no 'HDR-END' field found
*/
/* JW still need to put in checks for buffer overflow */
int parse_header (trace_t *tr, FILE *fin, long *offset, trans_info_t *ti) {
char buf[MAXLINE];
char *cp;
u_int hdr_f, hdr_flds = 0;
/* clear the hdr structure */
memset ((char *) ti, 0, sizeof (*ti));
ti->nnext = ti->notify_addrs;
ti->fnext = ti->forward_addrs;
ti->snext = ti->sender_addrs;
while ((cp = fgets (buf, MAXLINE - 1, fin)) != NULL) {
/*fprintf (stderr, "parse_header () line offset (%ld): %s", *offset, buf);*/
/* exit loop when HDR-END field is encountered */
if (!memcmp (HDR_END, buf, strlen (HDR_END))) {
hdr_flds |= HDR_END_F;
break;
}
if (!(hdr_f = dup_token_field (buf, ti)) &&
!(hdr_f = list_members_field (tr, buf, ti)) &&
!(hdr_f = int_type_field (buf, ti)) &&
!(hdr_f = is_from_field (buf, ti)) &&
!(hdr_f = is_list_field (tr, buf, ti)) &&
!(hdr_f = is_new_list_field (tr, buf, ti))) {
/* Yikes! We should never get here. */
trace (ERROR, tr,
"ERROR: parse_header () illegal header field encountered \"%s\"\n", buf);
continue;
}
hdr_flds |= hdr_f;
}
ti->hdr_fields = hdr_flds;
*offset = ftell (fin);
/* 'cp' is NULL means no 'HDR-END' found */
return (cp == NULL);
}
/*
* Dup the token pointed to by *p
*/
char *dup_single_token (char *p) {
char *q = p;
for (;*q == ' ' || *q == '\t'; q++);
newline_remove (q);
if (*q == '\0')
return NULL;
return strdup (q);
}
/* Given a '"' delimeted string, return everything between
* the '"'s, minus the "'s.
*
* Return:
* char * string of the char's between "'s
* NULL otherwise
*/
char *dup_string_field (char *p) {
char *q, *r;
if ((q = strchr (p, '"')) == NULL)
return NULL;
if ((r = strrchr (++q, '"')) == NULL)
return NULL;
*r = '\0';
return strdup (q);
}
u_int dup_token_field (char *line, trans_info_t *ti) {
if (!strncmp (SOURCE, line, strlen (SOURCE)) &&
(ti->source = dup_single_token (line + strlen (SOURCE))) != NULL)
return SOURCE_F;
if (!strncmp (OBJ_TYPE, line, strlen (OBJ_TYPE)) &&
(ti->obj_type = dup_single_token (line + strlen (OBJ_TYPE))) != NULL)
return OBJ_TYPE_F;
if (!strncmp (OBJ_KEY, line, strlen (OBJ_KEY)) &&
(ti->obj_key = dup_single_token (line + strlen (OBJ_KEY))) != NULL)
return OBJ_KEY_F;
if (!strncmp (OP, line, strlen (OP)) &&
(ti->op = dup_single_token (line + strlen (OP))) != NULL &&
is_valid_op (ti->op))
return OP_F;
/* subject line can be blank */
if (!strncmp (SUBJECT, line, strlen (SUBJECT))) {
ti->subject = dup_single_token (line + strlen (SUBJECT));
return SUBJECT_F;
}
if (!strncmp (DATE, line, strlen (DATE)) &&
(ti->date = dup_single_token (line + strlen (DATE))) != NULL)
return DATE_F;
if (!strncmp (MSG_ID, line, strlen (MSG_ID)) &&
(ti->msg_id = dup_single_token (line + strlen (MSG_ID))) != NULL)
return MSG_ID_F;
if (!strncmp (PGP_KEY, line, strlen (PGP_KEY)) &&
(ti->pgp_key = dup_single_token (line + strlen (PGP_KEY))) != NULL)
return PGP_KEY_F;
if (!strncmp (OVERRIDE, line, strlen (OVERRIDE)) &&
(ti->override = dup_single_token (line + strlen (OVERRIDE))) != NULL)
return OVERRIDE_F;
if (!strncmp (KEYCERTFN, line, strlen (KEYCERTFN)) &&
(ti->keycertfn = dup_single_token (line + strlen (KEYCERTFN))) != NULL)
return KEYCERTFN_F;
if (!strncmp (PASSWORD, line, strlen (PASSWORD)) &&
(ti->crypt_pw = dup_string_field (line + strlen (PASSWORD))) != NULL)
return PASSWORD_F;
if (!strncmp (OTHERFAIL, line, strlen (OTHERFAIL)) &&
(ti->otherfail = dup_single_token (line + strlen (OTHERFAIL))) != NULL)
return OTHERFAIL_F;
if (!strncmp (OLD_OBJ_FILE, line, strlen (OLD_OBJ_FILE)) &&
(ti->old_obj_fname =
dup_single_token (line + strlen (OLD_OBJ_FILE))) != NULL)
return OLD_OBJ_FILE_F;
return 0;
}
u_int is_from_field (char *line, trans_info_t *ti) {
char *p;
if (!strncmp (FROM, line, strlen (FROM))) {
p = line + strlen(FROM);
for (;*p == ' ' || *p == '\t'; p++);
newline_remove (p);
if (*p != '\0')
strcpy (ti->sender_addrs, p);
else
strcpy (ti->sender_addrs, TCP_USER);
ti->snext += strlen (ti->sender_addrs) + 1;
return FROM_F;
}
return 0;
}
u_int is_new_list_field (trace_t *tr, char *line, trans_info_t *ti) {
char *p, *q, **r;
enum HDR_FLDS_T fld;
if (!strncmp (CHECK_NOTIFY, line, strlen (CHECK_NOTIFY))) {
p = line + strlen (CHECK_NOTIFY);
r = &(ti->check_notify);
fld = CHECK_NOTIFY_F;
}
else if (!strncmp (CHECK_MNT_NFY, line, strlen (CHECK_MNT_NFY))) {
p = line + strlen (CHECK_MNT_NFY);
r = &(ti->check_mnt_nfy);
fld = CHECK_MNT_NFY_F;
}
else
return 0;
*r = NULL;
q = p;
while (find_token (&p, &q) > 0) {
*q = '\0';
*r = myconcat (*r, p);
*q = ' ';
}
if (*r == NULL)
return 0;
return fld;
}
u_int is_list_field (trace_t *tr, char *line, trans_info_t *ti) {
char *p;
if (!strncmp (MAINT_NO_EXIST, line, strlen (MAINT_NO_EXIST))) {
ti->maint_no_exist = NULL;
p = line + strlen (MAINT_NO_EXIST);
if ((p = strtok (p, " ")) == NULL) {
fprintf (stderr, "ERROR: empty MAINT_NO_EXIST hdr field\n");
return 0;
}
while (p != NULL) {
if (*p != '\n') {
ti->maint_no_exist = my_concat (ti->maint_no_exist, " ");
ti->maint_no_exist = my_concat (ti->maint_no_exist, p);
}
p = strtok (NULL, " ");
}
if (ti->maint_no_exist != NULL)
return MAINT_NO_EXIST_F;
}
if (!strncmp (MNT_BY, line, strlen (MNT_BY))) {
ti->mnt_by[0] = '\0';
p = line + strlen (MNT_BY);
if ((p = strtok (p, " ")) == NULL) {
fprintf (stderr, "ERROR: empty MNT_BY hdr field\n");
return 0;
}
while (p != NULL) {
strcat (ti->mnt_by, " ");
strcat (ti->mnt_by, p);
p = strtok (NULL, " ");
}
/* get rid of \n if there is one
p = ti->mnt_by + strlen (ti->mnt_by) - 1;
if (*p == '\n')
*p = '\0';
*/
newline_remove(ti->mnt_by);
if (ti->mnt_by[0] != '\0')
return MNT_BY_F;
}
return 0;
}
u_int int_type_field (char *line, trans_info_t *ti) {
if (!memcmp (SYNTAX_ERRORS, line, strlen (SYNTAX_ERRORS)))
return ((u_int)(ti->syntax_errors = SYNTAX_ERRORS_F));
if (!memcmp (SYNTAX_WARNS, line, strlen (SYNTAX_WARNS)))
return ((u_int)(ti->syntax_warns = SYNTAX_WARNS_F));
if (!memcmp (DEL_NO_EXIST, line, strlen (DEL_NO_EXIST)))
return ((u_int)(ti->del_no_exist = DEL_NO_EXIST_F));
if (!memcmp (AUTHFAIL, line, strlen (AUTHFAIL)))
return ((u_int)(ti->authfail = AUTHFAIL_F));
if (!memcmp (NEW_MNT_ERROR, line, strlen (NEW_MNT_ERROR)))
return ((u_int)(ti->new_mnt_error = NEW_MNT_ERROR_F));
if (!memcmp (DEL_MNT_ERROR, line, strlen (DEL_MNT_ERROR)))
return ((u_int)(ti->del_mnt_error = DEL_MNT_ERROR_F));
if (!memcmp (BAD_OVERRIDE, line, strlen (BAD_OVERRIDE)))
return ((u_int)(ti->bad_override = BAD_OVERRIDE_F));
if (!memcmp (UNKNOWN_USER, line, strlen (UNKNOWN_USER)))
return ((u_int)(ti->unknown_user = UNKNOWN_USER_F));
return 0;
}
u_int list_members_field (trace_t *tr, char *line, trans_info_t *ti) {
if (!memcmp (NOTIFY, line, strlen (NOTIFY)) &&
get_list_members (tr, line + strlen (NOTIFY),
ti->notify_addrs, &(ti->nnext)))
return NOTIFY_F;
if (!memcmp (MNT_NFY, line, strlen (MNT_NFY)) &&
get_list_members (tr, line + strlen (MNT_NFY),
ti->notify_addrs, &(ti->nnext)))
return MNT_NFY_F;
if (!memcmp (UPD_TO, line, strlen (UPD_TO)) &&
get_list_members (tr, line + strlen (UPD_TO),
ti->forward_addrs, &(ti->fnext)))
return UPD_TO_F;
return 0;
}
/* return index of element in list or return -1 */
int present_in_list (char *list, char *last, char *target_str) {
char *p;
int i = 0;
for (p = list; p < last; p += strlen (p) + 1, i++)
if (!strcasecmp (target_str, p))
return i;
return -1;
}
/*
* Get the list of notifiers (ie, list of email addr's) and
* place into the buffer pointed to by *next
* (ie, forward or notify buffer).
* Return 1 if field is non-empty, else return 0.
*/
int get_list_members (trace_t *tr, char *p, char *addr_buf, char **next) {
char *q;
if ((q = strtok (p, " ")) == NULL) {
fprintf (stderr, "ERROR: empty list hdr field\n");
return 0;
}
while (q != NULL) {
newline_remove(q);
if (*q != '\0' &&
present_in_list (addr_buf, *next, q) < 0) {
strcpy (*next, q);
*next += strlen (q) + 1;
}
q = strtok (NULL, " ");
}
return 1;
}
void free_ti_mem (trans_info_t *ti) {
if (ti->subject != NULL)
free (ti->subject);
if (ti->date != NULL)
free (ti->date);
if (ti->msg_id != NULL)
free (ti->msg_id);
if (ti->source != NULL)
free (ti->source);
if (ti->obj_type != NULL)
free (ti->obj_type);
/* causing memory problems... chl */
if (ti->obj_key != NULL)
free (ti->obj_key);
if (ti->op != NULL)
free (ti->op);
if (ti->check_notify != NULL)
free (ti->check_notify);
if (ti->check_mnt_nfy != NULL)
free (ti->check_mnt_nfy);
}
void print_hdr_struct (FILE *fout, trans_info_t *ti) {
char *p;
fprintf (fout, "%s\n", HDR_START);
/*
fprintf (stderr, "trans_code-(%d)\n", ti->trans_success);
*/
/* pgp and email processing */
if (ti->sender_addrs[0] != '\0')
fprintf (fout, "%s%s\n", FROM, ti->sender_addrs);
if (ti->date != NULL)
fprintf (fout, "%s%s\n", DATE, ti->date);
if (ti->subject != NULL)
fprintf (fout, "%s%s\n", SUBJECT, ti->subject);
if (ti->msg_id != NULL)
fprintf (fout, "%s%s\n", MSG_ID, ti->msg_id);
if (ti->pgp_key != NULL)
fprintf (fout, "%s%s\n", PGP_KEY, ti->pgp_key);
/* irr_check */
if (ti->op != NULL)
fprintf (fout, "%s%s\n", OP, ti->op);
if (ti->obj_type != NULL)
fprintf (fout, "%s%s\n", OBJ_TYPE, ti->obj_type);
if (ti->obj_key != NULL)
fprintf (fout, "%s%s\n", OBJ_KEY, ti->obj_key);
if (ti->source != NULL)
fprintf (fout, "%s%s\n", SOURCE, ti->source);
if (ti->syntax_errors)
fprintf (fout, "%s\n", SYNTAX_ERRORS);
if (ti->syntax_warns)
fprintf (fout, "%s\n", SYNTAX_WARNS);
if (ti->mnt_by[0] != '\0')
fprintf (fout, "%s%s\n", MNT_BY, ti->mnt_by);
if (ti->override != NULL)
fprintf (fout, "%s%s\n", OVERRIDE, ti->override);
if (ti->keycertfn != NULL)
fprintf (fout, "%s%s\n", KEYCERTFN, ti->keycertfn);
if (ti->crypt_pw != NULL)
fprintf (fout, "%s\"%s\"\n", PASSWORD, ti->crypt_pw);
/* irr_auth */
if (ti->otherfail != NULL)
fprintf (fout, "%s%s\n", OTHERFAIL, ti->otherfail);
if (ti->authfail)
fprintf (fout, "%s\n", AUTHFAIL);
if (ti->del_no_exist)
fprintf (fout, "%s\n", DEL_NO_EXIST);
if (ti->maint_no_exist != NULL)
fprintf (fout, "%s%s\n", MAINT_NO_EXIST, ti->maint_no_exist);
if (ti->old_obj_fname != NULL)
fprintf (fout, "%s%s\n", OLD_OBJ_FILE, ti->old_obj_fname);
if (ti->notify != NULL)
fprintf (fout, "%s%s\n", NOTIFY, ti->notify);
if (ti->forward != NULL)
fprintf (fout, "%s%s\n", UPD_TO, ti->forward);
if (ti->new_mnt_error)
fprintf (fout, "%s\n", NEW_MNT_ERROR);
if (ti->del_mnt_error)
fprintf (fout, "%s\n", DEL_MNT_ERROR);
if (ti->bad_override)
fprintf (fout, "%s\n", BAD_OVERRIDE);
if (ti->unknown_user)
fprintf (fout, "%s\n", UNKNOWN_USER);
fprintf (fout, "%s\n", HDR_END);
return;
fprintf (fout, "NOTIFY---\n");
if (ti->nnext != ti->notify_addrs) {
p = ti->notify_addrs;
for (;p < ti->nnext; p += strlen (p) + 1)
fprintf (fout, " %s", p);
fprintf (fout, ":\n");
}
fprintf (fout, "FORWARD---\n");
if (ti->fnext != ti->forward_addrs) {
p = ti->forward_addrs;
for (; p < ti->fnext; p += strlen (p) + 1)
fprintf (fout, " %s", p);
fprintf (fout, ":\n");
}
fprintf (fout, "----------\n");
}
/*
* See if *op is a valid operation
*/
int is_valid_op (char *op) {
if (strcmp (op, ADD_OP) &&
strcmp (op, DEL_OP) &&
strcmp (op, REPLACE_OP) &&
strcmp (op, NOOP_OP))
return 0;
return 1;
}
/*
* This routine concat's x and y. It assumes that the
* caller is placing the result in x, so the routine
* free's x if it points to something.
* So the calling convention should be like this:
* x = my_concat (x, y);
* x and/or y may be NULL and routine will work.
*/
char *my_concat (char *x, char *y) {
char buf[MAXLINE];
if (x == NULL)
buf[0] = '\0';
else {
strcpy (buf, x);
free_mem (x);
}
if (y != NULL)
strcat (buf, y);
if (buf[0] == '\0')
return NULL;
else
return strdup (buf);
}
char *free_mem (char *p) {
if (p != NULL)
free (p);
return NULL;
}
/* Given the transaction struct for this update, determine if there
* are any errors. Updates that do not have errors will be sent to
* IRRd in a !us...!ue DB update.
*
* Return:
* 1 if any error is found
* 0 if no errors were found
*/
int update_has_errors (trans_info_t *ti) {
return (ti->hdr_fields & ERROR_FLDS);
}
/* This routine finds a token in the string. *x will
* point to the first character in the string and *y will
* point to the first character after the token. A token
* is a printable character string. A '\n' is not considered
* part of a legal token.
* This function is rpsl-capable. It will look for '#'s in
* the string and assume everything after is a comment.
* Invoke this routine by setting 'x' and 'y' to the beginning
* of the target string like this: 'x = y = target_string;
* if (find_token (&x, &y) < 0) ...
* each successive call to find_token () will move the pointer
* along.
*
* Return:
* 1 if a token is found (*x points to token, *y first token after)
* -1 if no token is found (*x and *y are to be ignored)
*/
int find_token (char **x, char **y) {
/* It's possible the target string is NULL
* or we are in a rpsl comment
*/
if (*y == NULL || **y == '#')
return -1;
*x = *y;
/* fprintf (stderr, "p-(%c)\n",**x); */
/* find the start of a token, ie, first printable character */
while (**x != '\0' && (**x == ' ' || **x == '\t' || **x == '\n')) (*x)++;
if (**x == '\0' || **x == '#')
return -1;
/* find the first space at the end of the token */
*y = *x + 1;
while (**y != '\0' && (isgraph ((int) **y) && **y != '#')) (*y)++;
/* fprintf (stderr, "JW: find_token () returns 1..\n"); */
return 1;
}
/* This routine concat's x and y, putting a space
* beteen x and y. It assumes that the
* caller is placing the result in x, so the routine
* free's x if it points to something.
*
* The calling convention should be like this:
* x = myconcat (x, y);
* x and/or y may be NULL and routine will work.
*/
char *myconcat (char *x, char *y) {
char buf[MAXLINE];
if (x == NULL)
buf[0] = '\0';
else {
strcpy (buf, x);
free_mem (x);
}
if (y != NULL) {
if (buf[0] != '\0')
strcat (buf, " ");
strcat (buf, y);
}
if (buf[0] == '\0')
return NULL;
else
return strdup (buf);
}
syntax highlighted by Code2HTML, v. 0.9.1