modules/nt/notification.cc

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. NT_ntfy_filename_generate
  2. NT_forwd_filename_generate
  3. NT_cross_filename_generate
  4. NT_crossntfy_filename_generate
  5. NT_add_to_ntfy_hash
  6. NT_add_to_frwd_hash
  7. NT_add_to_cross_hash
  8. NT_add_to_ntfy_hash_list
  9. NT_add_to_frwd_hash_list
  10. NT_add_to_cross_hash_list
  11. NT_add_to_ntfy
  12. NT_add_to_cross
  13. NT_add_to_ntfy_list
  14. NT_send_ntfy
  15. NT_log_ntfy
  16. NT_delete_ntfy
  17. nt_gfunc_send
  18. NT_send_ntfy_list
  19. nt_gfunc_log
  20. NT_log_ntfy_list
  21. nt_gfunc_delete
  22. NT_delete_ntfy_list
  23. nt_add_to_list
  24. NT_unify_list
  25. NT_gather_ntfy_addresses
  26. NT_gather_frwd_addresses
  27. get_overlapping_routes_list
  28. NT_write_all_ntfs
  29. NT_write_all_frwds
  30. NT_send_forw_creation
  31. NT_forw_create_req

   1 /***************************************
   2   $Revision: 1.21 $
   3 
   4   NT (Notifications) module
   5 
   6   Status: NOT REVIEWED, NOT TESTED
   7 
   8   Author(s):       Engin Gunduz
   9 
  10   ******************/ /******************
  11   Modification History:
  12         engin (06/07/2000) Created.
  13   ******************/ /******************
  14   Copyright (c) 2000                              RIPE NCC
  15  
  16   All Rights Reserved
  17   
  18   Permission to use, copy, modify, and distribute this software and its
  19   documentation for any purpose and without fee is hereby granted,
  20   provided that the above copyright notice appear in all copies and that
  21   both that copyright notice and this permission notice appear in
  22   supporting documentation, and that the name of the author not be
  23   used in advertising or publicity pertaining to distribution of the
  24   software without specific, written prior permission.
  25   
  26   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  27   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  28   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  29   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  30   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  31   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  32  ***************************************/
  33 
  34 
  35 
  36 
  37 
  38 
  39 #include "notification.h"
  40 extern int supress_ack_notif;
  41 extern char * defmail;
  42 extern int reading_from_mail;
  43 extern char * forwlog;
  44 
  45 /*  Generates a unique file name and returns the full path of the filename 
  46     for storing notification message.  Creates the file at the same time. 
  47     May use PID or time or both to ensure uniqueness.  */
  48       
  49 char * NT_ntfy_filename_generate( const char * tmpdir, const char * e_mail){
     /* [<][>][^][v][top][bottom][index][help] */
  50 
  51    FILE * ntfy_file;
  52    char * name;
  53    char * replaced_notimailtxt;
  54    char * replaced_notinetworktxt;
  55        
  56    /* allocate space for name.  32 should be enough for PID */
  57    name = (char*)malloc(strlen(tmpdir) + strlen(e_mail) + strlen("notify") +32 ); 
  58    
  59    sprintf(name, "%s/%s-%s.%i", tmpdir, "notify", e_mail, getpid());
  60 
  61    /* create the file */
  62    if(( ntfy_file = fopen(name, "w")) == NULL){
  63      fprintf(stderr, "Can't open notification file for creating, %s", name);
  64    }
  65 
  66    fprintf(ntfy_file, "To: %s\nFrom: %s\nSubject: Notification of RIPE Database changes\nReply-To: %s\n\n%s\n", e_mail, humailbox, humailbox, notitxt);
  67    if(reading_from_mail){
  68      replaced_notimailtxt = UP_replace_globals(notimailtxt);
  69      fprintf(ntfy_file, "%s\n\n", replaced_notimailtxt);
  70      free(replaced_notimailtxt);
  71    }
  72 
  73    if(networkupdate){
  74      replaced_notinetworktxt = UP_replace_globals(notinetworktxt);
  75      fprintf(ntfy_file, "%s\n\n", replaced_notinetworktxt);
  76      free(replaced_notinetworktxt);
  77    }
  78    
  79    /* close it */
  80    fclose(ntfy_file);
  81     
  82    return name;
  83       
  84 }
  85 
  86 
  87 
  88 
  89 
  90 /* Generates a unique file name and returns the full path of the filename 
  91    for storing forwarded message. Creates the file at the same time.  */ 
  92 char * NT_forwd_filename_generate( const char * tmpdir, const char * e_mail){
     /* [<][>][^][v][top][bottom][index][help] */
  93 
  94    FILE * forwd_file;
  95    char * name;
  96    char * replaced_fwmailtxt;
  97           
  98    /* allocate space for name.  32 should be enough for PID */
  99    name = (char*)malloc(strlen(tmpdir) + strlen(e_mail) + strlen("forwd") +32 ); 
 100    
 101    sprintf(name, "%s/%s-%s.%i", tmpdir, "forwd", e_mail, getpid());
 102    /* create the file */
 103    if(( forwd_file = fopen(name, "w")) == NULL){
 104      fprintf(stderr, "Can't open forward file, %s", name);
 105    }
 106 
 107    fprintf(forwd_file, "To: %s\nFrom: %s\nSubject:  Requested RIPE database object changes \nReply-To: %s\n\n%s\n", e_mail, humailbox, humailbox, fwtxt);
 108    if(reading_from_mail){
 109      replaced_fwmailtxt = UP_replace_globals(fwmailtxt);
 110      fprintf(forwd_file, "\n%s\n", replaced_fwmailtxt);
 111      free(replaced_fwmailtxt);
 112    }
 113 
 114    /* close it */
 115    fclose(forwd_file);
 116     
 117    return name;
 118 
 119 }
 120 
 121 
 122 
 123 
 124 
 125 /* Generates a unique file name and returns the full path of the filename 
 126    for storing cross notification message. Creates the file at the same time.  */ 
 127 char * NT_cross_filename_generate( const char * tmpdir, const char * e_mail, int mode){
     /* [<][>][^][v][top][bottom][index][help] */
 128 
 129    FILE * cross_file;
 130    char * name;
 131       
 132    /* allocate space for name.  32 should be enough for PID */
 133    name = (char*)malloc(strlen(tmpdir) + strlen(e_mail) + strlen("cross") +32 ); 
 134    
 135    sprintf(name, "%s/%s-%s.%i", tmpdir, "cross", e_mail, getpid());
 136    /* create the file */
 137    if(( cross_file = fopen(name, "w")) == NULL){
 138      fprintf(stderr, "Can't open cross notif file, %s", name);
 139    }
 140 
 141    if(mode == ADDITION){
 142      fprintf(cross_file, "To: %s\nFrom: %s\n%s\nReply-To: %s\n\n", e_mail, humailbox, cno_subject_add, humailbox);
 143    }else{
 144      fprintf(cross_file, "To: %s\nFrom: %s\n%s\nReply-To: %s\n\n", e_mail, humailbox, cno_subject_del, humailbox);
 145    }
 146    
 147    /* close it */
 148    fclose(cross_file);
 149     
 150    return name;
 151 
 152 }
 153 
 154 
 155 
 156 
 157 
 158 
 159 
 160 /* Generates a unique file name and returns the full path of the filename for 
 161    storing notification message. Creates the file at the same time.  */
 162 char * NT_crossntfy_filename_generate( const char * tmpdir, const char * e_mail){
     /* [<][>][^][v][top][bottom][index][help] */
 163    FILE * cross_file;
 164    char * name;
 165       
 166    /* allocate space for name.  32 should be enough for PID */
 167    name = (char*)malloc(strlen(tmpdir) + strlen(e_mail) + strlen("cross") +32 ); 
 168    
 169    sprintf(name, "%s/%s-%s.%i", tmpdir, "cross", e_mail, getpid());
 170 
 171    /* create the file */
 172    if(( cross_file = fopen(name, "w")) == NULL){
 173      fprintf(stderr, "Can't open cross file, %s", name);
 174    }
 175 
 176    /* close it */
 177    fclose(cross_file);
 178     
 179    return name;
 180 
 181 }
 182 
 183 
 184 
 185 
 186 
 187 /* Adds the e-mail to the notify hash, generating appropriate temp files */
 188 void NT_add_to_ntfy_hash(GHashTable * ntfy_hash, char * e_mail){
     /* [<][>][^][v][top][bottom][index][help] */
 189 
 190   if(g_hash_table_lookup(ntfy_hash ,e_mail) == NULL){/* there is no such entry, so create it */
 191 
 192     g_hash_table_insert(ntfy_hash, strdup(e_mail), NT_ntfy_filename_generate(tmpdir, e_mail));
 193 
 194   }
 195 
 196 }
 197 
 198 
 199 
 200 
 201 /* Adds the e-mail to the forw hash, generating appropriate temp files */
 202 void NT_add_to_frwd_hash(GHashTable * frwd_hash, char * e_mail){
     /* [<][>][^][v][top][bottom][index][help] */
 203 
 204   if(g_hash_table_lookup(frwd_hash ,e_mail) == NULL){/* there is no such entry, so create it */
 205     g_hash_table_insert(frwd_hash, strdup(e_mail), NT_forwd_filename_generate(tmpdir, e_mail));
 206   }
 207     
 208 }
 209 
 210 
 211 
 212 
 213 
 214 /* Adds the e-mail to the cross hash, generating appropriate temp files */
 215 void NT_add_to_cross_hash(GHashTable * cross_hash, const char * e_mail, int mode){
     /* [<][>][^][v][top][bottom][index][help] */
 216 
 217   /*  if e-mail is NULL, immediately return */
 218   if(e_mail == NULL){
 219     return;
 220   }
 221 
 222   if(g_hash_table_lookup(cross_hash ,e_mail) == NULL){/* there is no such entry, so create it */
 223     g_hash_table_insert(cross_hash, strdup(e_mail), NT_cross_filename_generate(tmpdir, e_mail, mode));
 224   }
 225     
 226 }
 227 
 228 
 229 
 230 
 231 
 232 /* Adds the e-mails in a linked list to the hash */
 233 void NT_add_to_ntfy_hash_list(GHashTable * ntfy_hash, GSList * e_mail_list){
     /* [<][>][^][v][top][bottom][index][help] */
 234 
 235    GSList * temp = NULL;
 236 
 237    for(temp = e_mail_list; temp != NULL; temp = g_slist_next(temp)){
 238      NT_add_to_ntfy_hash(ntfy_hash, (char *)temp->data);
 239    }
 240   
 241 }
 242 
 243 
 244 
 245 
 246 /* Adds the e-mails in a linked list to the hash */
 247 void NT_add_to_frwd_hash_list(GHashTable * frwd_hash, GSList * e_mail_list){
     /* [<][>][^][v][top][bottom][index][help] */
 248 
 249    GSList * temp = NULL;
 250 
 251    for(temp = e_mail_list; temp != NULL; temp = g_slist_next(temp)){
 252      NT_add_to_frwd_hash(frwd_hash, (char *)temp->data);
 253    }
 254   
 255 }
 256 
 257 
 258 
 259 /* Adds the e-mails in a linked list to the hash */
 260 void NT_add_to_cross_hash_list(GHashTable * cross_hash, GSList * e_mail_list, int mode){
     /* [<][>][^][v][top][bottom][index][help] */
 261 
 262    GSList * temp = NULL;
 263 
 264    for(temp = e_mail_list; temp != NULL; temp = g_slist_next(temp)){
 265      NT_add_to_cross_hash(cross_hash, (char *)temp->data, mode);
 266    }
 267   
 268 }
 269 
 270 
 271 
 272 
 273 
 274 
 275 /* Appends the argument strings to the file.  */
 276 void NT_add_to_ntfy( char * filename, char * fmt, ... ){
     /* [<][>][^][v][top][bottom][index][help] */
 277   va_list ap;  /* points to each unnamed arg in turn */
 278   FILE * ntfy_file;
 279  
 280   if(tracing){
 281     printf("TRACING: NT_add_to_ntfy\n"); 
 282   }
 283   if(( ntfy_file = fopen(filename, "a")) == NULL){
 284     fprintf(stderr, "Can't open notification file for writing, %s\n", filename);
 285     return;
 286   }
 287     
 288   va_start(ap, fmt);
 289   vfprintf(ntfy_file, fmt, ap);
 290 
 291   va_end(ap); /* clean up */
 292   fclose(ntfy_file);
 293 }
 294 
 295 
 296 
 297 /* Appends the argument strings to the file.  */
 298 void NT_add_to_cross(const char * e_mail, GHashTable * hash, char * fmt, ...){
     /* [<][>][^][v][top][bottom][index][help] */
 299 
 300   va_list ap;  /* points to each unnamed arg in turn */
 301   FILE * cross_file;
 302   char * filename;
 303 
 304   /* if e-mail is NULL, immediately return */
 305   if(e_mail == NULL){
 306     return;
 307   }
 308    
 309   if(g_hash_table_lookup(hash, find_email_address(e_mail)) != NULL){
 310     filename = (char *)g_hash_table_lookup(hash, find_email_address(e_mail));
 311   }else{
 312     fprintf(stderr, "Can't find a cross notification file for e-mail %s\n", e_mail);
 313     return;
 314   }
 315 
 316   if(( cross_file = fopen(filename, "a")) == NULL){
 317     fprintf(stderr, "Can't open cross notification file, %s\n", filename);
 318   }
 319   
 320  
 321    
 322   if(tracing){
 323     printf("TRACING: NT_add_to_cross\n"); 
 324   }
 325   if(( cross_file = fopen(filename, "a")) == NULL){
 326     fprintf(stderr, "Can't open cross notification file for writing, %s\n", filename);
 327   }
 328     
 329   va_start(ap, fmt);
 330   vfprintf(cross_file, fmt, ap);
 331 
 332   va_end(ap); /* clean up */
 333   fclose(cross_file);
 334   
 335 
 336 }
 337 
 338 
 339 
 340 
 341 
 342 /* Appends the argument string to the temp notif files in the list */
 343 void NT_add_to_ntfy_list(GSList * list, GHashTable * hash, char * arg){
     /* [<][>][^][v][top][bottom][index][help] */
 344   
 345   GSList * temp = NULL;
 346 
 347   for(temp = list; temp != NULL; temp = g_slist_next(temp)){
 348     NT_add_to_ntfy((char *)g_hash_table_lookup(hash, ((char *)temp->data)), arg);
 349   }
 350 }
 351 
 352 
 353 
 354 
 355 
 356 
 357 
 358 
 359 /* Sends the notification message which is stored in the temporary filefilename.  */
 360 void NT_send_ntfy( const char * filename, const char * to_address, const char * mailercommand){
     /* [<][>][^][v][top][bottom][index][help] */
 361 
 362     char * mail_command_line = NULL;
 363     char * supress_file = NULL;
 364     FILE * notif_file, * supr_file_hdl;
 365     char buf[1024];
 366 
 367 
 368     /* if we are not supressing acks and notifs, send the notif */
 369     if(!supress_ack_notif){
 370       if(to_address != NULL){
 371         mail_command_line = (char *)malloc(strlen(mailercommand) + strlen(filename) + 128);
 372         sprintf(mail_command_line, "%s %s < %s", mailercommand, to_address, filename);
 373         system(mail_command_line);
 374       }
 375     /* if we are supressing acks and notifs, send notif to DEFMAIL  */
 376     }else{
 377       supress_file = (char *)malloc(strlen(filename) + strlen(".supress") + 2); 
 378       sprintf(supress_file, "%s.supress", filename);
 379       if(( supr_file_hdl = fopen(supress_file, "w")) == NULL){
 380         fprintf(stderr, "Can't open supress notif file, %s", supress_file);
 381       }else{
 382         fprintf(supr_file_hdl, "From: %s\nTo: %s\nSubject: Supressed notif mail\n\n",
 383             humailbox, defmail);
 384         if(( notif_file = fopen(filename, "r")) == NULL){
 385           fprintf(stderr, "Can't open notif file for reading, %s", filename);
 386         }else{
 387           while(fgets(buf, 1023, notif_file) != NULL){
 388             fprintf(supr_file_hdl, buf);
 389           }
 390           fclose(notif_file);
 391         }
 392       }
 393       fclose(supr_file_hdl);
 394       mail_command_line = (char *)malloc(strlen(mailercommand) + strlen(defmail) 
 395             + strlen(supress_file) + 128);
 396       sprintf(mail_command_line, "%s %s < %s", mailercommand, defmail, supress_file);
 397       system(mail_command_line);
 398       unlink(supress_file);
 399       free(supress_file);
 400     }
 401 
 402 
 403 }
 404 
 405 
 406 
 407 /* Adds the notification message which is in the filename into "logfilename.date". */
 408 void NT_log_ntfy( const char * filename, const char * logfilename){
     /* [<][>][^][v][top][bottom][index][help] */
 409 
 410   FILE * notif_file, * log_file;
 411   char * buf;
 412   time_t cur_time;
 413   char * time_str;
 414   char * logfile_date;
 415   char * date;
 416 
 417   buf = (char *)malloc(1024);
 418   if(( notif_file = fopen(filename, "r")) == NULL){
 419     fprintf(stderr, "Can't open notification file for reading, [%s]\n", filename);
 420     return;
 421   }
 422 
 423   /* construct the "logfilename.date" string */
 424   logfile_date = (char *)malloc(strlen(logfilename) + 10);
 425   date = UP_get_current_date();
 426   snprintf(logfile_date, strlen(logfilename) + 10, "%s.%s", logfilename, date);
 427   free(date);
 428 
 429   if(( log_file = fopen(logfile_date, "a")) == NULL){
 430     fprintf(stderr, "Can't open log file, %s\n", logfilename);
 431     return;
 432   }
 433 
 434   /* get time */
 435   cur_time = time(NULL);
 436   time_str = strdup(ctime(&cur_time));
 437   /* cut the '\n' at the end */
 438   time_str[strlen(time_str) - 1] = '\0';
 439 
 440   fprintf(log_file, ">>> time: %s NOTIF <<<\n\n", time_str);
 441 
 442 
 443   while((buf=fgets(buf, 1023, notif_file)) > 0){
 444     fprintf(log_file, "%s", buf);
 445   }
 446   free(buf);
 447 
 448   fclose(notif_file);
 449   fclose(log_file);
 450 
 451 }
 452 
 453 
 454 /* Deletes the temporary notification file. */ 
 455 void NT_delete_ntfy( const char * filename){
     /* [<][>][^][v][top][bottom][index][help] */
 456 
 457    unlink(filename);
 458    
 459 }
 460 
 461 
 462 /* The function required for NT_send_ntfy_list */
 463 void  nt_gfunc_send(gpointer key, gpointer value, gpointer user_data){
     /* [<][>][^][v][top][bottom][index][help] */
 464   NT_send_ntfy((char *)value, (char *)key, (char *)user_data);
 465 }
 466 
 467 
 468        
 469 /* Sends the notification messages whose temp files are stored in filehash. */              
 470 void NT_send_ntfy_list( GHashTable * filehash, char * mailercommand){
     /* [<][>][^][v][top][bottom][index][help] */
 471 
 472   g_hash_table_foreach( filehash, (GHFunc)nt_gfunc_send, mailercommand);
 473   
 474 }
 475 
 476 
 477 
 478 
 479 /* The function required for NT_log_ntfy_list */
 480 void  nt_gfunc_log(gpointer key, gpointer value, gpointer user_data){
     /* [<][>][^][v][top][bottom][index][help] */
 481   NT_log_ntfy((char *)value, (char *)user_data);
 482 }
 483 
 484 
 485 
 486 
 487 /* Logs the notification whose temp files are in filehash to log_file. */
 488 void NT_log_ntfy_list( GHashTable * filehash, char * log_file){
     /* [<][>][^][v][top][bottom][index][help] */
 489 
 490    g_hash_table_foreach( filehash, (GHFunc)nt_gfunc_log, log_file);
 491   
 492 }
 493 
 494 
 495 
 496 /* The function required for NT_delete_ntfy_list */
 497 void  nt_gfunc_delete(gpointer key, gpointer value, gpointer user_data){
     /* [<][>][^][v][top][bottom][index][help] */
 498   NT_delete_ntfy((char *)value);
 499 }
 500 
 501 
 502 
 503 /* Deletes the temporary notification messages in the filehash. Empties and frees 
 504    the hash too.  */
 505 void NT_delete_ntfy_list( GHashTable * filehash){
     /* [<][>][^][v][top][bottom][index][help] */
 506 
 507   g_hash_table_foreach(filehash, (GHFunc)nt_gfunc_delete, NULL);
 508   g_hash_table_destroy(filehash);
 509   
 510 }
 511 
 512 
 513 /* to be used with g_hash_table_foreach in NT_unify_list.
 514    Adds the 'key' to the list (a GSList) */
 515 void nt_add_to_list(char * key, char * value, GSList ** list){
     /* [<][>][^][v][top][bottom][index][help] */
 516 
 517   *list = g_slist_append(*list, strdup(value));
 518 
 519   
 520 }
 521 
 522 
 523 
 524 /* "unifies" a list in a case insensitive manner */
 525 GSList * NT_unify_list(GSList * in_list){
     /* [<][>][^][v][top][bottom][index][help] */
 526 
 527   GHashTable * unification_hash;
 528   GSList ** out_list;
 529   GSList * temp;
 530   char * key, * value;
 531 
 532   /* allocate space for out_list */ 
 533   out_list = (GSList **)malloc(sizeof(GSList *));
 534   *out_list = NULL;
 535 
 536   /* initialize the hash to be used for unification process */
 537   unification_hash = g_hash_table_new(g_str_hash, g_str_equal);
 538 
 539   /* first put the list elements into a hash, to unify them */
 540   for(temp = in_list; temp != NULL; temp = g_slist_next(temp)){
 541     
 542     /* convert the string into lowercase */
 543     key = strdup((char *)(temp->data));
 544     g_strdown(key);
 545     value = strdup((char *)(temp->data));
 546     
 547     if(g_hash_table_lookup(unification_hash, key) == NULL){/* if it is not there */
 548       
 549       g_hash_table_insert(unification_hash, key, value);
 550       
 551     }
 552   }
 553 
 554   /* now, get the elements back from the hash into a list */
 555   g_hash_table_foreach(unification_hash, (GHFunc)nt_add_to_list, out_list);
 556 
 557   g_slist_free(in_list);
 558   g_hash_table_destroy(unification_hash);
 559   
 560   return *out_list;
 561 
 562 }
 563 
 564 
 565 
 566 
 567 
 568 
 569 
 570 
 571 /* Gathers e-mail boxes to which we will send normal notification messages. It 
 572    takes old and new objects, looks up maintainers and less specific inetnums/domains/routes 
 573    when necessary, finds the addresses (in mnt-nfy and notify attributes) and returns 
 574    a list of them. */
 575 GSList * NT_gather_ntfy_addresses( char * old_object, char * new_object){
     /* [<][>][^][v][top][bottom][index][help] */
 576   GSList * return_list = NULL, * temp = NULL;
 577   GSList * mntners = NULL; 
 578 
 579   if(old_object != NULL && new_object != NULL){/* it was an update */
 580     temp = get_attr_list(old_object, "notify");
 581     mntners = get_mntners(old_object);
 582     temp = g_slist_concat(temp, get_mntnfy_vector(mntners));
 583   }else if(old_object == NULL && new_object != NULL){/* it was a creation */
 584     temp = get_attr_list(new_object, "notify");
 585     mntners = get_mntners(new_object);
 586     temp = g_slist_concat(temp, get_mntnfy_vector(mntners));
 587   }else if(old_object != NULL && new_object == NULL){/* it was a deletion */
 588     temp = get_attr_list(old_object, "notify");
 589     mntners = get_mntners(old_object);
 590     temp = g_slist_concat(temp, get_mntnfy_vector(mntners));
 591   }
 592 
 593   /* we have to 'unify' the list here! */
 594   return_list = NT_unify_list(temp);
 595 
 596   return return_list;
 597 }
 598 
 599 
 600 
 601 /* Gathers e-mail boxes to which we will forward messages (or rather, objects). It 
 602    an object, looks up maintainers, finds the addresses (in upd-to attributes) and returns 
 603    a list of them. */
 604 GSList * NT_gather_frwd_addresses(char * object){
     /* [<][>][^][v][top][bottom][index][help] */
 605   GSList *temp = NULL;
 606   GSList * mntners = NULL; 
 607 
 608   mntners = get_mntners(object);
 609   temp = get_updto_vector(mntners);
 610   return temp;
 611 }
 612 
 613 
 614 
 615 
 616 /* Accepts a route object as a "* char" and returns a list of overlapping routes */
 617 overlap_routes get_overlapping_routes_list(char * object){
     /* [<][>][^][v][top][bottom][index][help] */
 618 
 619   char * route_prefix = NULL;
 620   GSList * tmp_list;
 621   char * result;
 622   char * query_string;  
 623   overlap_routes result_routes;
 624   char * origin;
 625   bool code;
 626   
 627     
 628   result_routes.less_spec = NULL;
 629   result_routes.exact_match = NULL;
 630   result_routes.more_spec = NULL;
 631       
 632   tmp_list = get_attr_list(object, "route");  
 633 
 634   if(tmp_list != NULL && tmp_list->data != NULL){
 635     route_prefix = strdup((char *)(tmp_list->data));
 636   }else{
 637     return result_routes; /* then, this wasn't a route object */
 638   }
 639   
 640   /* get the less specific route objects */
 641   /* form the query string */
 642   query_string = (char *)malloc(strlen("-Troute -r -l ") + strlen(route_prefix) + 2);
 643   sprintf(query_string, "-Troute -r -l %s", route_prefix);
 644 
 645   /* get the results */ 
 646   result = send_and_get(query_host, query_port, query_string);
 647   free(query_string);
 648 
 649   /* and fill in the result field  */
 650   result_routes.less_spec = take_objects(result);
 651 
 652   /* get the exact match route objects */
 653   /* form the query string */
 654   query_string = (char *)malloc(strlen("-Troute -r -x ") + strlen(route_prefix) + 2);
 655   sprintf(query_string, "-Troute -r -x %s", route_prefix);
 656 
 657   /* get the results */ 
 658   result = send_and_get(query_host, query_port, query_string);
 659   free(query_string);
 660   
 661 
 662   /* filter out the route object itself */
 663   result = UP_filter_out_same_origins(result, object);
 664 
 665   /* and fill in the result field  */
 666   if(result != NULL){
 667     result_routes.exact_match = take_objects(result);
 668   }
 669   
 670 
 671   /* get the more specific route objects */
 672   /* form the query string */
 673   query_string = (char *)malloc(strlen("-Troute -r -M ") + strlen(route_prefix) + 2);
 674   sprintf(query_string, "-Troute -r -M %s", route_prefix);
 675 
 676   /* get the results */ 
 677   result = send_and_get(query_host, query_port, query_string);
 678   free(query_string);
 679 
 680   /* and fill in the result field  */
 681   result_routes.more_spec = take_objects(result);
 682 
 683   /* Return the results */
 684   return result_routes;
 685   
 686 }
 687 
 688 
 689 
 690 
 691 
 692 /* Gets old and new versions of the object, and creates temporary notification
 693    files when necessary, and then writes appropriate strings into those
 694    temporary files. */
 695 void NT_write_all_ntfs(char * old_object, char * new_object, char * formatted_object,
     /* [<][>][^][v][top][bottom][index][help] */
 696                        const char * tempdir,
 697                        GHashTable * ntfy_hash,  GHashTable * forwd_hash, GHashTable * cross_hash, 
 698                        char * from_address){ 
 699 
 700    GSList * e_mail_list = NULL;
 701    GSList * temp = NULL;
 702    char * e_mail_address;
 703    overlap_routes overlapping_routes; 
 704     
 705    /* from_address may contain also the name, like "Johnny Bravo <johnny@inter.net>",
 706       so extract the e-mail address from it */
 707    e_mail_address = find_email_address(from_address); 
 708 
 709 
 710    if(tracing && reading_from_mail){
 711      printf("TRACING: NT_write_all_ntfs: from_address=[%s], e_mail_address=[%s]\n", from_address, e_mail_address);
 712    }
 713    if(old_object != NULL && new_object != NULL){/* it was an update */
 714      e_mail_list = NT_gather_ntfy_addresses(old_object, new_object);
 715      NT_add_to_ntfy_hash_list(ntfy_hash, e_mail_list); 
 716      NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "---\nPREVIOUS OBJECT:\n\n");
 717      NT_add_to_ntfy_list(e_mail_list, ntfy_hash, old_object);
 718      NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "\n\nREPLACED BY:\n\n");
 719      NT_add_to_ntfy_list(e_mail_list, ntfy_hash, new_object);
 720      NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "\n");
 721    }else if(old_object == NULL && new_object != NULL){/* it was a creation */
 722      e_mail_list = NT_gather_ntfy_addresses(old_object, new_object);
 723      NT_add_to_ntfy_hash_list(ntfy_hash, e_mail_list); 
 724      NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "---\nOBJECT BELOW CREATED:\n\n");
 725      NT_add_to_ntfy_list(e_mail_list, ntfy_hash, 
 726             formatted_object ? formatted_object : new_object);
 727      NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "\n");
 728      /* We'll deal with cross notifications only when we create or delete route objects */
 729      if(strcmp(get_class_type_char(new_object), "route") == 0){
 730        overlapping_routes = get_overlapping_routes_list(new_object);
 731        if(overlapping_routes.less_spec != NULL || overlapping_routes.exact_match != NULL ||
 732           overlapping_routes.more_spec != NULL ){
 733          NT_add_to_cross_hash(cross_hash, e_mail_address, ADDITION);
 734          NT_add_to_cross(e_mail_address, cross_hash, "%s\n\n%s\n\n%s\n\n", cno_explain_add, new_object, cno_overlap_add);
 735          if(overlapping_routes.less_spec != NULL){
 736            NT_add_to_cross(from_address, cross_hash, "LESS SPECIFIC MATCHES\n\n");
 737            for(temp = overlapping_routes.less_spec; temp != NULL; temp = g_slist_next(temp)){
 738              NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
 739            }
 740          }
 741          if(overlapping_routes.exact_match != NULL){
 742            NT_add_to_cross(from_address, cross_hash, "EXACT MATCHES\n\n");
 743            for(temp = overlapping_routes.exact_match; temp != NULL; temp = g_slist_next(temp)){
 744              NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
 745            }
 746          }
 747          if(overlapping_routes.more_spec != NULL){
 748            NT_add_to_cross(from_address, cross_hash, "MORE SPECIFIC MATCHES\n\n");
 749            for(temp = overlapping_routes.more_spec; temp != NULL; temp = g_slist_next(temp)){
 750              NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
 751            }
 752          }
 753        }
 754      }
 755    }else if(old_object != NULL && new_object == NULL){/* it was a deletion */
 756      old_object = delete_delete_attrib(old_object);
 757      e_mail_list = NT_gather_ntfy_addresses(old_object, new_object);
 758      NT_add_to_ntfy_hash_list(ntfy_hash, e_mail_list); 
 759      NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "---\nOBJECT BELOW DELETED:\n\n");
 760      NT_add_to_ntfy_list(e_mail_list, ntfy_hash, old_object);
 761      NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "\n");
 762      /* We'll deal with cross notifications only when we create or delete route objects */
 763      if(strcmp(get_class_type_char(old_object), "route") == 0){
 764        overlapping_routes = get_overlapping_routes_list(old_object);
 765        if(overlapping_routes.less_spec != NULL || overlapping_routes.exact_match != NULL ||
 766           overlapping_routes.more_spec != NULL ){
 767          NT_add_to_cross_hash(cross_hash, e_mail_address, DELETION);
 768          NT_add_to_cross(e_mail_address, cross_hash, "%s\n\n%s\n\n%s\n\n", cno_explain_del, old_object, cno_overlap_del);
 769          if(overlapping_routes.less_spec != NULL){
 770            NT_add_to_cross(from_address, cross_hash, "LESS SPECIFIC MATCHES\n\n");
 771            for(temp = overlapping_routes.less_spec; temp != NULL; temp = g_slist_next(temp)){
 772              NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
 773            }
 774          }
 775          if(overlapping_routes.exact_match != NULL){
 776            NT_add_to_cross(from_address, cross_hash, "EXACT MATCHES\n\n");
 777            for(temp = overlapping_routes.exact_match; temp != NULL; temp = g_slist_next(temp)){
 778              NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
 779            }
 780          }
 781          if(overlapping_routes.more_spec != NULL){
 782            NT_add_to_cross(from_address, cross_hash, "MORE SPECIFIC MATCHES\n\n");
 783            for(temp = overlapping_routes.more_spec; temp != NULL; temp = g_slist_next(temp)){
 784              NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
 785            }
 786          }
 787        }
 788      }
 789    }
 790 }
 791 
 792 
 793 
 794 
 795 
 796 /* Gets old and new versions of the object, and creates temporary notification
 797    files when necessary, and then writes appropriate strings into those
 798    temporary files. */
 799 void NT_write_all_frwds(char * old_object, char * new_object, const char * tempdir,
     /* [<][>][^][v][top][bottom][index][help] */
 800                        GHashTable * ntfy_hash,  GHashTable * forwd_hash, GHashTable * cross_hash, 
 801                        const char * from_address){ 
 802 
 803    GSList * e_mail_list = NULL;
 804 
 805 
 806    if(tracing){
 807      printf("TRACING: NT_write_all_frwds\n");
 808    }
 809    if(old_object != NULL && new_object != NULL){/* it was an update */
 810      e_mail_list = NT_gather_frwd_addresses(old_object);
 811      NT_add_to_frwd_hash_list(forwd_hash, e_mail_list);
 812      NT_add_to_ntfy_list(e_mail_list, forwd_hash, "----\nUPDATE REQUESTED FOR:\n\n");
 813      NT_add_to_ntfy_list(e_mail_list, forwd_hash, new_object);
 814    }else if(old_object == NULL && new_object != NULL){/* it was a creation */
 815      e_mail_list = NT_gather_frwd_addresses(new_object);
 816      NT_add_to_frwd_hash_list(forwd_hash, e_mail_list);
 817      NT_add_to_ntfy_list(e_mail_list, forwd_hash, "----\nADDITION REQUESTED FOR:\n\n");
 818      NT_add_to_ntfy_list(e_mail_list, forwd_hash, new_object);
 819    }else if(old_object != NULL && new_object == NULL){/* it was a deletion */
 820      e_mail_list = NT_gather_frwd_addresses(old_object);
 821      NT_add_to_frwd_hash_list(forwd_hash, e_mail_list);
 822      NT_add_to_ntfy_list(e_mail_list, forwd_hash, "----\nDELETION REQUESTED FOR:\n\n");
 823      NT_add_to_ntfy_list(e_mail_list, forwd_hash, old_object);
 824    }
 825 }
 826 
 827 
 828 
 829 /* Sends the creation forward message which is stored in the temporary filefilename.  */
 830 void NT_send_forw_creation( const char * filename, const char * to_address, const char * mailercommand){
     /* [<][>][^][v][top][bottom][index][help] */
 831 
 832     char * mail_command_line = NULL;
 833 
 834 
 835     if(to_address != NULL){
 836       mail_command_line = (char *)malloc(strlen(mailercommand) + strlen(filename) + 128);
 837       sprintf(mail_command_line, "%s %s < %s", mailercommand, to_address, filename);
 838       system(mail_command_line);
 839       free(mail_command_line);
 840     }
 841 
 842 }
 843 
 844 
 845 
 846 
 847 
 848 /* NT_forw_create_req forwards the maintainer and as-block creation requests
 849    to <HUMAILBOX> */
 850 void NT_forw_create_req(const char * object){
     /* [<][>][^][v][top][bottom][index][help] */
 851 
 852    FILE * forw_file;
 853    char * filename;
 854    char * replaced_mtfwheader;
 855    char * replaced_mtfwtxt;
 856 
 857    /* allocate space for name.  32 should be enough for PID */
 858    filename = (char*)malloc(strlen(tmpdir) + strlen("creat-forw") +32 ); 
 859    
 860    sprintf(filename, "%s/%s.%i", tmpdir, "creat-forw", getpid());
 861 
 862    /* create the file */
 863    if(( forw_file = fopen(filename, "w")) == NULL){
 864      fprintf(stderr, "Can't open creation forward file for creating, %s", filename);
 865    }
 866 
 867    replaced_mtfwheader = UP_replace_globals(mtfwheader);
 868    replaced_mtfwtxt = UP_replace_globals(mtfwtxt);
 869    
 870    fprintf(forw_file, "%s\n\n", replaced_mtfwheader);
 871    
 872    if(reading_from_mail){
 873      fprintf(forw_file, "%s\n\n", replaced_mtfwtxt);
 874    }
 875 
 876    /* print the object */
 877    fprintf(forw_file, "%s\n\n", object);
 878     
 879    /* close it */
 880    fclose(forw_file);
 881     
 882    /* send it */ 
 883    NT_send_forw_creation(filename, humailbox, mailcmd);
 884 
 885    /* log it */
 886    NT_log_ntfy(filename, forwlog);
 887    
 888    /* delete it */
 889    unlink(filename);
 890  
 891    /* free the mem */ 
 892    free(filename);
 893    free(replaced_mtfwheader);
 894    free(replaced_mtfwtxt);
 895 }

/* [<][>][^][v][top][bottom][index][help] */