modules/nt/notification.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- NT_ntfy_filename_generate
- NT_forwd_filename_generate
- NT_cross_filename_generate
- NT_crossntfy_filename_generate
- NT_add_to_ntfy_hash
- NT_add_to_frwd_hash
- NT_add_to_cross_hash
- NT_add_to_ntfy_hash_list
- NT_add_to_frwd_hash_list
- NT_add_to_cross_hash_list
- NT_add_to_ntfy
- NT_add_to_cross
- NT_add_to_ntfy_list
- NT_send_ntfy
- NT_log_ntfy
- NT_delete_ntfy
- nt_gfunc_send
- NT_send_ntfy_list
- nt_gfunc_log
- NT_log_ntfy_list
- nt_gfunc_delete
- NT_delete_ntfy_list
- nt_free_list
- NT_unify_list
- NT_compare_lists
- NT_check_irtnfy
- NT_gather_ntfy_addresses
- NT_gather_frwd_addresses
- get_overlapping_routes_list
- NT_write_all_ntfs
- NT_write_all_frwds
- NT_send_forw_creation
- NT_forw_create_req
1 /***************************************
2 $Revision: 1.11 $
3
4 NT (Notifications) module
5
6 Status: REVIEWED, NOT TESTED
7
8 Author(s): Engin Gunduz
9
10 ******************/ /******************
11 Modification History:
12 engin (06/07/2000) Created.
13 denis (25/09/2001) Modified for new API
14 ******************/ /******************
15 Copyright (c) 2000,2001,2002 RIPE NCC
16
17 All Rights Reserved
18
19 Permission to use, copy, modify, and distribute this software and its
20 documentation for any purpose and without fee is hereby granted,
21 provided that the above copyright notice appear in all copies and that
22 both that copyright notice and this permission notice appear in
23 supporting documentation, and that the name of the author not be
24 used in advertising or publicity pertaining to distribution of the
25 software without specific, written prior permission.
26
27 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
28 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
29 AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
30 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
31 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
32 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
33 ***************************************/
34
35
36
37
38
39
40 #include "notification.h"
41 extern int supress_ack_notif;
42 extern char * defmail;
43 extern int reading_from_mail;
44 extern char * forwlog;
45
46 /* Generates a unique file name and returns the full path of the filename
47 for storing notification message. Creates the file at the same time.
48 May use PID or time or both to ensure uniqueness. */
49
50 char * NT_ntfy_filename_generate( const char * tmpdir, const char * e_mail)
/* [<][>][^][v][top][bottom][index][help] */
51 {
52 FILE * ntfy_file;
53 char * name;
54 char * replaced_notimailtxt;
55 char * replaced_notinetworktxt;
56
57 /* allocate space for name. 32 should be enough for PID */
58 name = (char*)malloc(strlen(tmpdir) + strlen(e_mail) + strlen("notify") +36 );
59
60 sprintf(name, "%s/%s-%s.%i", tmpdir, "notify", e_mail, (int)(getpid()) );
61
62 /* create the file */
63 if (( ntfy_file = fopen(name, "w")) == NULL)
64 {
65 fprintf(stderr, "Can't open notification file for creating, %s", name);
66 }
67
68 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);
69 if (reading_from_mail)
70 {
71 replaced_notimailtxt = UP_replace_globals(notimailtxt);
72 fprintf(ntfy_file, "%s\n\n", replaced_notimailtxt);
73 free(replaced_notimailtxt);
74 }
75
76 if (networkupdate)
77 {
78 replaced_notinetworktxt = UP_replace_globals(notinetworktxt);
79 fprintf(ntfy_file, "%s\n\n", replaced_notinetworktxt);
80 free(replaced_notinetworktxt);
81 }
82
83 /* close it */
84 fclose(ntfy_file);
85
86 return name;
87 }
88
89
90
91
92 /* Generates a unique file name and returns the full path of the filename
93 for storing forwarded message. Creates the file at the same time. */
94 char * NT_forwd_filename_generate( const char * tmpdir, const char * e_mail)
/* [<][>][^][v][top][bottom][index][help] */
95 {
96 FILE * forwd_file;
97 char * name;
98 char * replaced_fwmailtxt;
99
100 /* allocate space for name. 32 should be enough for PID */
101 name = (char*)malloc(strlen(tmpdir) + strlen(e_mail) + strlen("forwd") +36 );
102
103 sprintf(name, "%s/%s-%s.%i", tmpdir, "forwd", e_mail, (int)(getpid()) );
104 /* create the file */
105 if (( forwd_file = fopen(name, "w")) == NULL)
106 {
107 fprintf(stderr, "Can't open forward file, %s", name);
108 }
109
110 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);
111 if (reading_from_mail)
112 {
113 replaced_fwmailtxt = UP_replace_globals(fwmailtxt);
114 fprintf(forwd_file, "\n%s\n", replaced_fwmailtxt);
115 free(replaced_fwmailtxt);
116 }
117
118 /* close it */
119 fclose(forwd_file);
120
121 return name;
122 }
123
124
125
126
127 /* Generates a unique file name and returns the full path of the filename
128 for storing cross notification message. Creates the file at the same time. */
129 char * NT_cross_filename_generate( const char * tmpdir, const char * e_mail, int mode)
/* [<][>][^][v][top][bottom][index][help] */
130 {
131 FILE * cross_file;
132 char * name;
133
134 /* allocate space for name. 32 should be enough for PID */
135 name = (char*)malloc(strlen(tmpdir) + strlen(e_mail) + strlen("cross") +36 );
136
137 sprintf(name, "%s/%s-%s.%i", tmpdir, "cross", e_mail, (int)(getpid()) );
138 /* create the file */
139 if (( cross_file = fopen(name, "w")) == NULL)
140 {
141 fprintf(stderr, "Can't open cross notif file, %s", name);
142 }
143
144 if (mode == ADDITION)
145 {
146 fprintf(cross_file, "To: %s\nFrom: %s\n%s\nReply-To: %s\n\n", e_mail, humailbox, cno_subject_add, humailbox);
147 }
148 else
149 {
150 fprintf(cross_file, "To: %s\nFrom: %s\n%s\nReply-To: %s\n\n", e_mail, humailbox, cno_subject_del, humailbox);
151 }
152
153 /* close it */
154 fclose(cross_file);
155
156 return name;
157 }
158
159
160
161
162
163 /* Generates a unique file name and returns the full path of the filename for
164 storing notification message. Creates the file at the same time. */
165 char * NT_crossntfy_filename_generate( const char * tmpdir, const char * e_mail)
/* [<][>][^][v][top][bottom][index][help] */
166 {
167 FILE * cross_file;
168 char * name;
169
170 /* allocate space for name. 32 should be enough for PID */
171 name = (char*)malloc(strlen(tmpdir) + strlen(e_mail) + strlen("cross") +36 );
172
173 sprintf(name, "%s/%s-%s.%i", tmpdir, "cross", e_mail, (int)(getpid()) );
174
175 /* create the file */
176 if (( cross_file = fopen(name, "w")) == NULL)
177 {
178 fprintf(stderr, "Can't open cross file, %s", name);
179 }
180
181 /* close it */
182 fclose(cross_file);
183
184 return name;
185 }
186
187
188
189 /* Adds the e-mail to the notify hash, generating appropriate temp files */
190 void NT_add_to_ntfy_hash(GHashTable * ntfy_hash, char * e_mail)
/* [<][>][^][v][top][bottom][index][help] */
191 {
192 if (g_hash_table_lookup(ntfy_hash ,e_mail) == NULL)
193 { /* there is no such entry, so create it */
194
195 g_hash_table_insert(ntfy_hash, strdup(e_mail), NT_ntfy_filename_generate(tmpdir, e_mail));
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)
205 { /* there is no such entry, so create it */
206 g_hash_table_insert(frwd_hash, strdup(e_mail), NT_forwd_filename_generate(tmpdir, e_mail));
207 }
208
209 }
210
211
212
213 /* Adds the e-mail to the cross hash, generating appropriate temp files */
214 void NT_add_to_cross_hash(GHashTable * cross_hash, const char * e_mail, int mode)
/* [<][>][^][v][top][bottom][index][help] */
215 {
216 /* if e-mail is NULL, immediately return */
217 if (e_mail == NULL)
218 {
219 return;
220 }
221
222 if (g_hash_table_lookup(cross_hash ,e_mail) == NULL)
223 { /* there is no such entry, so create it */
224 g_hash_table_insert(cross_hash, strdup(e_mail), NT_cross_filename_generate(tmpdir, e_mail, mode));
225 }
226 }
227
228
229
230 /* Adds the e-mails in a linked list to the hash */
231 void NT_add_to_ntfy_hash_list(GHashTable * ntfy_hash, GList * e_mail_list)
/* [<][>][^][v][top][bottom][index][help] */
232 {
233 GList * temp = NULL;
234
235 for (temp = e_mail_list; temp != NULL; temp = g_list_next(temp))
236 {
237 NT_add_to_ntfy_hash( ntfy_hash, (char *)(temp->data) );
238 }
239 }
240
241
242
243 /* Adds the e-mails in a linked list to the hash */
244 void NT_add_to_frwd_hash_list(GHashTable * frwd_hash, GList * e_mail_list)
/* [<][>][^][v][top][bottom][index][help] */
245 {
246 GList * temp = NULL;
247
248 for (temp = e_mail_list; temp != NULL; temp = g_list_next(temp))
249 {
250 NT_add_to_frwd_hash(frwd_hash, (char *)temp->data);
251 }
252 }
253
254
255
256 /* Adds the e-mails in a linked list to the hash */
257 void NT_add_to_cross_hash_list(GHashTable * cross_hash, GList * e_mail_list, int mode)
/* [<][>][^][v][top][bottom][index][help] */
258 {
259 GList * temp = NULL;
260
261 for (temp = e_mail_list; temp != NULL; temp = g_list_next(temp))
262 {
263 NT_add_to_cross_hash(cross_hash, (char *)temp->data, mode);
264 }
265 }
266
267
268
269 /* Appends the argument strings to the file. */
270 void NT_add_to_ntfy( char * filename, char * fmt, ... )
/* [<][>][^][v][top][bottom][index][help] */
271 {
272 va_list ap; /* points to each unnamed arg in turn */
273 FILE * ntfy_file;
274
275 if (tracing)
276 {
277 printf("TRACING: NT_add_to_ntfy\n");
278 }
279 if (( ntfy_file = fopen(filename, "a")) == NULL)
280 {
281 fprintf(stderr, "Can't open notification file for writing, %s\n", filename);
282 return;
283 }
284
285 va_start(ap, fmt);
286 vfprintf(ntfy_file, fmt, ap);
287
288 va_end(ap); /* clean up */
289 fclose(ntfy_file);
290 }
291
292
293
294 /* Appends the argument strings to the file. */
295 void NT_add_to_cross(const char * e_mail, GHashTable * hash, char * fmt, ...)
/* [<][>][^][v][top][bottom][index][help] */
296 {
297 va_list ap; /* points to each unnamed arg in turn */
298 FILE * cross_file = NULL;
299 char * filename = NULL;
300
301 if (tracing)
302 {
303 printf("TRACING: NT_add_to_cross\n");
304 }
305
306 /* if e-mail is NULL, immediately return */
307 if(e_mail == NULL)
308 {
309 return;
310 }
311
312 if ( (filename = (char *)g_hash_table_lookup(hash, find_email_address(e_mail))) == NULL )
313 {
314 fprintf(stderr, "Can't find a cross notification file for e-mail %s\n", e_mail);
315 return;
316 }
317
318 if ( ( cross_file = fopen(filename, "a")) == NULL )
319 {
320 fprintf(stderr, "Can't open cross notification file for writing, %s\n", filename);
321 }
322
323 va_start(ap, fmt);
324 vfprintf(cross_file, fmt, ap);
325
326 va_end(ap); /* clean up */
327 fclose(cross_file);
328 }
329
330
331
332
333 /* Appends the argument string to the temp notif files in the list */
334 void NT_add_to_ntfy_list(GList * list, GHashTable * hash, char * arg)
/* [<][>][^][v][top][bottom][index][help] */
335 {
336 GList * temp = NULL;
337
338 for(temp = list; temp != NULL; temp = g_list_next(temp))
339 {
340 NT_add_to_ntfy((char *)g_hash_table_lookup(hash, ((char *)temp->data)), "%s", arg);
341 }
342 }
343
344
345
346 /* Sends the notification message which is stored in the temporary filefilename. */
347 void NT_send_ntfy( const char * filename, const char * to_address, const char * mailercommand)
/* [<][>][^][v][top][bottom][index][help] */
348 {
349 char * mail_command_line = NULL;
350 char * supress_file = NULL;
351 FILE * notif_file, * supr_file_hdl;
352 char buf[1024];
353
354 /* if we are not supressing acks and notifs, send the notif */
355 if (!supress_ack_notif)
356 {
357 if (to_address != NULL)
358 {
359 mail_command_line = (char *)malloc(strlen(mailercommand) + strlen(filename) + 128);
360 sprintf(mail_command_line, "%s %s < %s", mailercommand, to_address, filename);
361 system(mail_command_line);
362 }
363 }
364 /* if we are supressing acks and notifs, send notif to DEFMAIL */
365 else
366 {
367 supress_file = (char *)malloc(strlen(filename) + strlen(".supress") + 2);
368 sprintf(supress_file, "%s.supress", filename);
369 if (( supr_file_hdl = fopen(supress_file, "w")) == NULL)
370 {
371 fprintf(stderr, "Can't open supress notif file, %s", supress_file);
372 }
373 else
374 {
375 fprintf(supr_file_hdl, "From: %s\nTo: %s\nSubject: Supressed notif mail\n\n",
376 humailbox, defmail);
377 if (( notif_file = fopen(filename, "r")) == NULL)
378 {
379 fprintf(stderr, "Can't open notif file for reading, %s", filename);
380 }
381 else
382 {
383 while (fgets(buf, 1023, notif_file) != NULL)
384 {
385 fprintf(supr_file_hdl, buf);
386 }
387 fclose(notif_file);
388 }
389 }
390 fclose(supr_file_hdl);
391 mail_command_line = (char *)malloc(strlen(mailercommand) + strlen(defmail)
392 + strlen(supress_file) + 128);
393 sprintf(mail_command_line, "%s %s < %s", mailercommand, defmail, supress_file);
394 system(mail_command_line);
395 unlink(supress_file);
396 free(supress_file);
397 }
398 }
399
400
401
402 /* Adds the notification message which is in the filename into "logfilename.date". */
403 void NT_log_ntfy( const char * filename, const char * logfilename)
/* [<][>][^][v][top][bottom][index][help] */
404 {
405 FILE * notif_file, * log_file;
406 char * buf;
407 time_t cur_time;
408 char * time_str;
409 char * logfile_date;
410 char * date;
411
412 if (tracing)
413 {
414 printf("TRACING: NT_log_ntfy is running: filename [%s] logfilename [%s]\n", filename, logfilename);
415 }
416
417 buf = (char *)malloc(1024);
418 if (( notif_file = fopen(filename, "r")) == NULL)
419 {
420 fprintf(stderr, "NT_log_ntfy: Can't open notification file for reading, [%s]\n", filename);
421 return;
422 }
423
424 /* construct the "logfilename.date" string */
425 logfile_date = (char *)malloc(strlen(logfilename) + 10);
426 date = UP_get_current_date();
427 snprintf(logfile_date, strlen(logfilename) + 10, "%s.%s", logfilename, date);
428 free(date);
429
430 if (( log_file = fopen(logfile_date, "a")) == NULL)
431 {
432 fprintf(stderr, "NT_log_ntfy: Can't open log file, %s\n", logfilename);
433 return;
434 }
435
436 /* get time */
437 cur_time = time(NULL);
438 time_str = strdup(ctime(&cur_time));
439 /* cut the '\n' at the end */
440 time_str[strlen(time_str) - 1] = '\0';
441
442 fprintf(log_file, ">>> time: %s NOTIF <<<\n\n", time_str);
443
444
445 while ( (buf=fgets(buf, 1024, notif_file)) != NULL )
446 {
447 fprintf(log_file, "%s", buf);
448 }
449 free(buf);
450
451 fclose(notif_file);
452 fclose(log_file);
453 }
454
455
456 /* Deletes the temporary notification file. */
457 void NT_delete_ntfy( const char * filename)
/* [<][>][^][v][top][bottom][index][help] */
458 {
459 unlink(filename);
460 }
461
462
463 /* The function required for NT_send_ntfy_list */
464 void nt_gfunc_send(gpointer key, gpointer value, gpointer user_data)
/* [<][>][^][v][top][bottom][index][help] */
465 {
466 NT_send_ntfy((char *)value, (char *)key, (char *)user_data);
467 }
468
469
470
471 /* Sends the notification messages whose temp files are stored in filehash. */
472 void NT_send_ntfy_list( GHashTable * filehash, char * mailercommand)
/* [<][>][^][v][top][bottom][index][help] */
473 {
474 g_hash_table_foreach( filehash, (GHFunc)nt_gfunc_send, mailercommand);
475 }
476
477
478
479
480 /* The function required for NT_log_ntfy_list */
481 void nt_gfunc_log(gpointer key, gpointer value, gpointer user_data)
/* [<][>][^][v][top][bottom][index][help] */
482 {
483 NT_log_ntfy((char *)value, (char *)user_data);
484 }
485
486
487
488
489 /* Logs the notification whose temp files are in filehash to log_file. */
490 void NT_log_ntfy_list( GHashTable * filehash, char * log_file)
/* [<][>][^][v][top][bottom][index][help] */
491 {
492 g_hash_table_foreach( filehash, (GHFunc)nt_gfunc_log, log_file);
493 }
494
495
496
497 /* The function required for NT_delete_ntfy_list */
498 void nt_gfunc_delete(gpointer key, gpointer value, gpointer user_data)
/* [<][>][^][v][top][bottom][index][help] */
499 {
500 NT_delete_ntfy((char *)value);
501 }
502
503
504
505 /* Deletes the temporary notification messages in the filehash. Empties and frees
506 the hash too. */
507 void NT_delete_ntfy_list( GHashTable * filehash)
/* [<][>][^][v][top][bottom][index][help] */
508 {
509 g_hash_table_foreach(filehash, (GHFunc)nt_gfunc_delete, NULL);
510 g_hash_table_destroy(filehash);
511 }
512
513
514 /* to be used with g_hash_table_foreach in NT_unify_list.
515 Adds the 'value' to the list (a GList) */
516 /* void nt_add_to_list(char * key, rpsl_attr_t * value, GList ** list)
517 {
518 *list = g_list_append(*list, strdup(value));
519 }
520 */
521
522
523 /* to be used with g_hash_table_foreach in NT_unify_list.
524 frees the 'key' and 'value' in the list (a GList) */
525 void nt_free_list(char * key, char * value, void *nothing)
/* [<][>][^][v][top][bottom][index][help] */
526 {
527 if ( key != NULL )
528 free(key);
529 if ( value != NULL )
530 free(value);
531 }
532
533
534
535 /* "unifies" a list in a case insensitive manner */
536 GList * NT_unify_list(GList * in_list)
/* [<][>][^][v][top][bottom][index][help] */
537 {
538 GHashTable * unification_hash;
539 GList ** out_list;
540 GList * temp;
541 GList *return_list = NULL;
542 char * key, * value;
543 int strcmp();
544
545 /* allocate space for out_list */
546 out_list = (GList **)malloc(sizeof(GList *));
547 *out_list = NULL;
548
549 /* initialize the hash to be used for unification process */
550 unification_hash = g_hash_table_new(g_str_hash, g_str_equal);
551
552 /* first put the list elements into a hash, to unify them */
553 for (temp = in_list; temp != NULL; temp = g_list_next(temp))
554 {
555 /* convert the email address into lowercase, for comparison reasons only */
556 key = rpsl_attr_get_clean_value((rpsl_attr_t *)(temp->data));
557 value = strdup(key);
558 g_strdown(key);
559
560 if (g_hash_table_lookup(unification_hash, key) == NULL)
561 { /* if it is not already in the hash table, add to the hash and append to new list */
562 g_hash_table_insert(unification_hash, key, value);
563 *out_list = g_list_insert_sorted( *out_list, strdup(value), strcmp );
564 /* *out_list = g_list_append( *out_list, strdup(value) ); */
565 }
566 else
567 { /* it is a duplicate email address, don't append to new list */
568 free(key);
569 free(value);
570 }
571 }
572
573 /* now, delete the elements in the hash */
574 g_hash_table_foreach(unification_hash, (GHFunc)nt_free_list, NULL);
575
576 g_hash_table_destroy(unification_hash);
577
578 return_list = *out_list;
579 free(out_list);
580 return return_list;
581 }
582
583
584
585 /* Gets GLists of irt atributes from old and new object. Compares these
586 lists and returns a list of diferences */
587
588 /* if option==1, return list contains only newly deleted irts
589 if option==2, return list contains only newly added irts
590 if option==3, return list contains both */
591
592 GList *NT_compare_lists(GList *old_irts, GList *new_irts, int option)
/* [<][>][^][v][top][bottom][index][help] */
593 {
594 typedef struct irt_details
595 {
596 gchar *irt_name;
597 rpsl_attr_t *irts;
598 gint matched;
599 } irt_details_t;
600
601 GList *old_irt_details = NULL;
602 GList *new_irt_details = NULL;
603 GList *old_irts_item = NULL;
604 GList *new_irts_item = NULL;
605 GList *return_list = NULL;
606 irt_details_t *irt_details;
607 char *irt_name;
608
609 if (tracing)
610 {
611 printf("TRACING: NT_compare_lists is running: option: [%d]\n", option);
612 }
613
614 /* collect data from the old_irts */
615 for ( old_irts_item = old_irts; old_irts_item != NULL; old_irts_item = g_list_next(old_irts_item) )
616 {
617 irt_details = (irt_details_t *)malloc(sizeof(irt_details_t));
618 /* get irt name from attr */
619 irt_name = rpsl_attr_get_clean_value( (rpsl_attr_t *)(old_irts_item->data) );
620 /* enter details into irt_details structure */
621 irt_details->irts = (rpsl_attr_t *)(old_irts_item->data);
622 irt_details->irt_name = irt_name;
623 irt_details->matched = 0;
624 /* append irt_details structure to old_irt_details list */
625 old_irt_details = g_list_append(old_irt_details, irt_details);
626 }
627
628 /* collect data from the new_irts and compare with the old in the same loop */
629 for ( new_irts_item = new_irts; new_irts_item != NULL; new_irts_item = g_list_next(new_irts_item) )
630 {
631 irt_details = (irt_details_t *)malloc(sizeof(irt_details_t));
632 /* get irt name from attr */
633 irt_name = rpsl_attr_get_clean_value( (rpsl_attr_t *)(new_irts_item->data) );
634 /* enter details into irt_details structure */
635 irt_details->irts = (rpsl_attr_t *)(new_irts_item->data);
636 irt_details->irt_name = irt_name;
637 irt_details->matched = 0;
638
639 /* compare the name with the names from the old list */
640 for ( old_irts_item = old_irt_details; old_irts_item != NULL; old_irts_item = g_list_next(old_irts_item) )
641 {
642 if ( ! strcmp(irt_name, ((irt_details_t *)(old_irts_item->data))->irt_name ) )
643 {
644 irt_details->matched = 1;
645 ((irt_details_t *)(old_irts_item->data))->matched = 1;
646 break;
647 }
648 }
649
650 /* append irt_details structure to new_irt_details list */
651 new_irt_details = g_list_append(new_irt_details, irt_details);
652 }
653
654 /* we now want a list of irts taken from the old and new irt_details lists
655 where the matched flag is _NOT_ set. These will only exist in one list
656 and have therefore just been added/deleted */
657 /* if option==1, return list contains only newly deleted irts
658 if option==2, return list contains only newly added irts
659 if option==3, return list contains both */
660 if ( option == 1 || option == 3 )
661 {
662 for ( old_irts_item = old_irt_details; old_irts_item != NULL; old_irts_item = g_list_next(old_irts_item) )
663 {
664 if ( ! ((irt_details_t *)(old_irts_item->data))->matched )
665 {
666 if (tracing)
667 {
668 printf("TRACING: NT_compare_lists: adding old irt to return list [%s]\n", ((irt_details_t *)(new_irts_item->data))->irt_name);
669 }
670
671 return_list = g_list_append(return_list, ((irt_details_t *)(old_irts_item->data))->irts );
672 }
673 free ( ((irt_details_t *)(old_irts_item->data))->irt_name );
674 }
675 }
676 g_list_free(old_irt_details);
677 if ( option == 2 || option == 3 )
678 {
679 for ( new_irts_item = new_irt_details; new_irts_item != NULL; new_irts_item = g_list_next(new_irts_item) )
680 {
681 if ( ! ((irt_details_t *)(new_irts_item->data))->matched )
682 {
683 if (tracing)
684 {
685 printf("TRACING: NT_compare_lists: adding new irt to return list [%s]\n", ((irt_details_t *)(new_irts_item->data))->irt_name);
686 }
687
688 return_list = g_list_append(return_list, ((irt_details_t *)(new_irts_item->data))->irts );
689 }
690 free ( ((irt_details_t *)(new_irts_item->data))->irt_name );
691 }
692 }
693 g_list_free(new_irt_details);
694
695 return return_list;
696 }
697
698
699 /* Gets old and new objects supplied, forms lists of any irt objects referenced
700 by these. Returns a GList of irt-nfy for any irt objects that heve been added
701 or deleted.
702 */
703 GList *NT_check_irtnfy(rpsl_object_t *old_obj, rpsl_object_t *new_obj)
/* [<][>][^][v][top][bottom][index][help] */
704 {
705 GList *old_irts = NULL;
706 GList *new_irts = NULL;
707 GList *changed_irts = NULL;
708
709 if (old_obj != NULL)
710 old_irts = get_irts(old_obj);
711 if (new_obj != NULL)
712 new_irts = get_irts(new_obj);
713
714 if ( old_irts != NULL && new_irts!= NULL )
715 {
716 /* compare lists for additions and deletions */
717 changed_irts = NT_compare_lists(old_irts, new_irts, 3);
718 return get_irtnfy_vector(changed_irts);
719 }
720 else if ( old_irts != NULL )
721 {
722 /* these irts have been deleted */
723 return get_irtnfy_vector(old_irts);
724 }
725 else if ( new_irts != NULL )
726 {
727 /* these irts have been added */
728 return get_irtnfy_vector(new_irts);
729 }
730 else
731 return NULL; /* no irt objects at all */
732 }
733
734
735 /* Gathers e-mail boxes to which we will send normal notification messages. It
736 takes old and new object strings, looks up maintainers and less specific inetnums/domains/routes
737 when necessary, finds the addresses (in mnt-nfy and notify attributes) and returns
738 a list of email addresses as strings.
739 Also now checks for irt-nfy in any irt objects that have been added or deleted */
740 GList * NT_gather_ntfy_addresses( const char * old_object_str, const char * new_object_str)
/* [<][>][^][v][top][bottom][index][help] */
741 {
742 GList *return_list = NULL, *temp = NULL;
743 GList *mntners = NULL;
744 const GList *error_list = NULL;
745 rpsl_object_t *old_obj = NULL;
746 rpsl_object_t *new_obj = NULL;
747
748 if (tracing)
749 {
750 printf("TRACING: NT_gather_ntfy_addresses is running: old_object_str : [%s]; new_object_str: [%s]\n", old_object_str ? old_object_str : "", new_object_str ? new_object_str : "");
751 }
752
753 if (old_object_str != NULL && new_object_str != NULL)
754 { /* it was an update */
755 old_obj = rpsl_object_init(old_object_str);
756 error_list = rpsl_object_errors(old_obj);
757 new_obj = rpsl_object_init(new_object_str);
758 error_list = rpsl_object_errors(old_obj);
759
760 /* start with the 'notify' in the object itself */
761 temp = get_attr_list(old_obj, "notify");
762 mntners = get_mntners(old_obj);
763 /* now add the 'mnt-by' from any of the mntners in the old object only */
764 temp = g_list_concat(temp, get_mntnfy_vector(mntners));
765 /* now add the 'irt-by' from any of the irts in the old and new objects
766 if they have just been added or deleted */
767 temp = g_list_concat(temp, NT_check_irtnfy(old_obj, new_obj));
768 }
769 else if (old_object_str == NULL && new_object_str != NULL)
770 { /* it was a creation */
771 new_obj = rpsl_object_init(new_object_str);
772 error_list = rpsl_object_errors(new_obj);
773
774 if ( ! rpsl_object_has_error( new_obj, RPSL_ERRLVL_ERROR ) )
775 {
776 /* start with the 'notify' in the object itself */
777 temp = get_attr_list(new_obj, "notify");
778 mntners = get_mntners(new_obj);
779 /* now add the 'mnt-by' from any of the mntners in the new object only */
780 temp = g_list_concat(temp, get_mntnfy_vector(mntners));
781 /* now add the 'irt-by' from any of the irts in the new object
782 as they have just been added */
783 temp = g_list_concat(temp, NT_check_irtnfy(old_obj, new_obj));
784 }
785 }
786 else if (old_object_str != NULL && new_object_str == NULL)
787 { /* it was a deletion */
788 old_obj = rpsl_object_init(old_object_str);
789 error_list = rpsl_object_errors(old_obj);
790
791 /* start with the 'notify' in the object itself */
792 temp = get_attr_list(old_obj, "notify");
793 mntners = get_mntners(old_obj);
794 /* now add the 'mnt-by' from any of the mntners in the old object only */
795 temp = g_list_concat(temp, get_mntnfy_vector(mntners));
796 /* now add the 'irt-by' from any of the irts in the old object
797 as they have just been deleted */
798 temp = g_list_concat(temp, NT_check_irtnfy(old_obj, new_obj));
799 }
800
801 /* we have to 'unify' the list here!, return_list is now a list of malloc'd email address strings */
802 return_list = NT_unify_list(temp);
803 rpsl_attr_delete_list( temp );
804 if ( old_obj )
805 rpsl_object_delete(old_obj);
806 if ( new_obj )
807 rpsl_object_delete(new_obj);
808
809 if (tracing)
810 {
811 printf( "TRACING: notif email addresses\n" );
812 for ( temp=return_list; temp!=NULL; temp=g_list_next(temp) )
813 printf( "TRACING: [%s]\n", (char *)(temp->data) );
814 }
815
816 return return_list;
817 }
818
819
820
821 /* Gathers e-mail boxes to which we will forward messages (or rather, objects). It
822 an object, looks up maintainers, finds the addresses (in upd-to attributes) and returns
823 a list of them. */
824 GList * NT_gather_frwd_addresses(char * object_str)
/* [<][>][^][v][top][bottom][index][help] */
825 {
826 GList *temp = NULL;
827 GList *attr_item = NULL;
828 GList *email_list = NULL;
829 char *email;
830 const GList *error_list = NULL;
831 rpsl_object_t *object;
832 GList * mntners = NULL;
833
834 object = rpsl_object_init(object_str);
835 error_list = rpsl_object_errors(object);
836
837 mntners = get_mntners(object);
838 /* get a list of upd-to attributes */
839 temp = get_updto_vector(mntners);
840 /* now extract the email text strings from the values of these attributes */
841 for ( attr_item = temp; attr_item != NULL ; attr_item = g_list_next(attr_item) )
842 {
843 email = rpsl_attr_get_clean_value((rpsl_attr_t *)(attr_item->data));
844 printf("NT_gather_frwd_addresses: email [%s]\n", email );
845 email_list = g_list_append(email_list, email );
846 }
847 return email_list;
848 }
849
850
851
852 /* Accepts a parsed route object and returns a list of overlapping routes */
853 overlap_routes get_overlapping_routes_list(rpsl_object_t * object)
/* [<][>][^][v][top][bottom][index][help] */
854 {
855 char * route_prefix = NULL;
856 GList * tmp_list;
857 char * result;
858 char * query_string;
859 overlap_routes result_routes;
860
861 result_routes.less_spec = NULL;
862 result_routes.exact_match = NULL;
863 result_routes.more_spec = NULL;
864
865 tmp_list = rpsl_object_get_attr(object, "route");
866
867 if (tmp_list != NULL && tmp_list->data != NULL)
868 {
869 route_prefix = rpsl_attr_get_clean_value((rpsl_attr_t *)(tmp_list->data));
870 }
871 else
872 {
873 return result_routes; /* then, this wasn't a route object */
874 }
875
876 /* get the less specific route objects */
877 /* form the query string */
878 query_string = (char *)malloc(strlen("-Troute -r -l ") + strlen(route_prefix) + 2);
879 sprintf(query_string, "-Troute -r -l %s", route_prefix);
880
881 /* get the results */
882 result = send_and_get(query_host, query_port, query_string);
883 free(query_string);
884
885 /* and fill in the result field */
886 result_routes.less_spec = take_objects(result);
887
888 /* get the exact match route objects */
889 /* form the query string */
890 query_string = (char *)malloc(strlen("-Troute -r -x ") + strlen(route_prefix) + 2);
891 sprintf(query_string, "-Troute -r -x %s", route_prefix);
892
893 /* get the results */
894 result = send_and_get(query_host, query_port, query_string);
895 free(query_string);
896
897
898 /* filter out the route object itself */
899 result = UP_filter_out_same_origins(result, object);
900
901 /* and fill in the result field */
902 if (result != NULL)
903 {
904 result_routes.exact_match = take_objects(result);
905 }
906
907 /* get the more specific route objects */
908 /* form the query string */
909 query_string = (char *)malloc(strlen("-Troute -r -M ") + strlen(route_prefix) + 2);
910 sprintf(query_string, "-Troute -r -M %s", route_prefix);
911
912 /* get the results */
913 result = send_and_get(query_host, query_port, query_string);
914 free(query_string);
915
916 /* and fill in the result field */
917 result_routes.more_spec = take_objects(result);
918
919 /* Return the results */
920 return result_routes;
921 }
922
923
924
925 /* Gets old and new versions of the object, and creates temporary notification
926 files when necessary, and then writes appropriate strings into those
927 temporary files. */
928 void NT_write_all_ntfs(char * old_object, char * new_object, char * formatted_object,
/* [<][>][^][v][top][bottom][index][help] */
929 const char * tempdir,
930 GHashTable * ntfy_hash, GHashTable * forwd_hash, GHashTable * cross_hash,
931 char * from_address)
932 {
933 GList * e_mail_list = NULL;
934 GList * temp = NULL;
935 const GList *error_list = NULL;
936 char * e_mail_address = NULL;
937 overlap_routes overlapping_routes;
938 rpsl_object_t *object;
939 char *arg2;
940
941 if ( reading_from_mail )
942 {
943 /* from_address may contain also the name, like "Johnny Bravo <johnny@inter.net>",
944 so extract the e-mail address from it */
945 e_mail_address = find_email_address(from_address);
946
947 if (tracing)
948 {
949 printf("TRACING: NT_write_all_ntfs: from_address=[%s], e_mail_address=[%s]\n", from_address, e_mail_address);
950 }
951 }
952 if (old_object != NULL && new_object != NULL)
953 {
954 /* it was an update */
955 object = rpsl_object_init(formatted_object ? formatted_object : new_object);
956 error_list = rpsl_object_errors(object);
957
958 if ( UP_remove_override_attr(object) )
959 arg2 = rpsl_object_get_text(object, RPSL_STD_COLUMN);
960 else
961 {
962 /* there was an override attr in this object and it has not been removed */
963 arg2 = (char *)malloc(2);
964 strcpy(arg2, ""); /* Don't include object in ack/notif msgs */
965 }
966
967 rpsl_object_delete(object);
968
969 e_mail_list = NT_gather_ntfy_addresses(old_object, new_object);
970 NT_add_to_ntfy_hash_list(ntfy_hash, e_mail_list);
971 NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "---\nPREVIOUS OBJECT:\n\n");
972 NT_add_to_ntfy_list(e_mail_list, ntfy_hash, old_object);
973 NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "\n\nREPLACED BY:\n\n");
974 NT_add_to_ntfy_list(e_mail_list, ntfy_hash, arg2);
975 NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "\n");
976 }
977 else if (old_object == NULL && new_object != NULL)
978 {
979 /* it was a creation */
980 object = rpsl_object_init(formatted_object ? formatted_object : new_object);
981 error_list = rpsl_object_errors(object);
982
983 if ( UP_remove_override_attr(object) )
984 arg2 = rpsl_object_get_text(object, RPSL_STD_COLUMN);
985 else
986 {
987 /* there was an override attr in this object and it has not been removed */
988 arg2 = (char *)malloc(2);
989 strcpy(arg2, ""); /* Don't include object in ack/notif msgs */
990 }
991
992 rpsl_object_delete(object);
993
994 e_mail_list = NT_gather_ntfy_addresses(old_object, new_object);
995 NT_add_to_ntfy_hash_list(ntfy_hash, e_mail_list);
996 NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "---\nOBJECT BELOW CREATED:\n\n");
997 NT_add_to_ntfy_list(e_mail_list, ntfy_hash, arg2);
998 NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "\n");
999
1000 /* We'll deal with cross notifications only when we create or delete route objects */
1001 object = rpsl_object_init(new_object);
1002 error_list = rpsl_object_errors(object);
1003
1004 if (strcmp(rpsl_object_get_class(object), "route") == 0)
1005 {
1006 overlapping_routes = get_overlapping_routes_list(object);
1007 if (overlapping_routes.less_spec != NULL || overlapping_routes.exact_match != NULL ||
1008 overlapping_routes.more_spec != NULL )
1009 {
1010 NT_add_to_cross_hash(cross_hash, e_mail_address, ADDITION);
1011 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);
1012 if (overlapping_routes.less_spec != NULL)
1013 {
1014 NT_add_to_cross(from_address, cross_hash, "LESS SPECIFIC MATCHES\n\n");
1015 for (temp = overlapping_routes.less_spec; temp != NULL; temp = g_list_next(temp))
1016 {
1017 NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
1018 }
1019 }
1020 if (overlapping_routes.exact_match != NULL)
1021 {
1022 NT_add_to_cross(from_address, cross_hash, "EXACT MATCHES\n\n");
1023 for (temp = overlapping_routes.exact_match; temp != NULL; temp = g_list_next(temp))
1024 {
1025 NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
1026 }
1027 }
1028 if (overlapping_routes.more_spec != NULL)
1029 {
1030 NT_add_to_cross(from_address, cross_hash, "MORE SPECIFIC MATCHES\n\n");
1031 for (temp = overlapping_routes.more_spec; temp != NULL; temp = g_list_next(temp))
1032 {
1033 NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
1034 }
1035 }
1036 }
1037 }
1038 rpsl_object_delete(object);
1039 }
1040 else if (old_object != NULL && new_object == NULL)
1041 { /* it was a deletion */
1042 old_object = delete_delete_attrib(old_object);
1043 object = rpsl_object_init(old_object);
1044 error_list = rpsl_object_errors(object);
1045
1046 if ( UP_remove_override_attr(object) )
1047 arg2 = rpsl_object_get_text(object, RPSL_STD_COLUMN);
1048 else
1049 {
1050 /* there was an override attr in this object and it has not been removed */
1051 arg2 = (char *)malloc(2);
1052 strcpy(arg2, ""); /* Don't include object in ack/notif msgs */
1053 }
1054
1055 e_mail_list = NT_gather_ntfy_addresses(old_object, new_object);
1056 NT_add_to_ntfy_hash_list(ntfy_hash, e_mail_list);
1057 NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "---\nOBJECT BELOW DELETED:\n\n");
1058 NT_add_to_ntfy_list(e_mail_list, ntfy_hash, arg2);
1059 NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "\n");
1060
1061 /* We'll deal with cross notifications only when we create or delete route objects */
1062 if (strcmp(rpsl_object_get_class(object), "route") == 0)
1063 {
1064 overlapping_routes = get_overlapping_routes_list(object);
1065 if (overlapping_routes.less_spec != NULL || overlapping_routes.exact_match != NULL ||
1066 overlapping_routes.more_spec != NULL )
1067 {
1068 NT_add_to_cross_hash(cross_hash, e_mail_address, DELETION);
1069 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);
1070 if (overlapping_routes.less_spec != NULL)
1071 {
1072 NT_add_to_cross(from_address, cross_hash, "LESS SPECIFIC MATCHES\n\n");
1073 for (temp = overlapping_routes.less_spec; temp != NULL; temp = g_list_next(temp))
1074 {
1075 NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
1076 }
1077 }
1078 if (overlapping_routes.exact_match != NULL)
1079 {
1080 NT_add_to_cross(from_address, cross_hash, "EXACT MATCHES\n\n");
1081 for (temp = overlapping_routes.exact_match; temp != NULL; temp = g_list_next(temp))
1082 {
1083 NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
1084 }
1085 }
1086 if (overlapping_routes.more_spec != NULL)
1087 {
1088 NT_add_to_cross(from_address, cross_hash, "MORE SPECIFIC MATCHES\n\n");
1089 for (temp = overlapping_routes.more_spec; temp != NULL; temp = g_list_next(temp))
1090 {
1091 NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
1092 }
1093 }
1094 }
1095 }
1096 rpsl_object_delete(object);
1097 }
1098 free(arg2);
1099 }
1100
1101
1102
1103 /* Gets old and new versions of the object, and creates temporary notification
1104 files when necessary, and then writes appropriate strings into those
1105 temporary files. */
1106 void NT_write_all_frwds(char * old_object_str, char * new_object_str, const char * tempdir,
/* [<][>][^][v][top][bottom][index][help] */
1107 GHashTable * ntfy_hash, GHashTable * forwd_hash, GHashTable * cross_hash,
1108 const char * from_address)
1109 {
1110 GList *e_mail_list = NULL;
1111 rpsl_object_t *object;
1112 char *arg2;
1113 const GList * error_list = NULL;
1114
1115 if (tracing)
1116 {
1117 printf("TRACING: NT_write_all_frwds is running\n");
1118 }
1119
1120 if ( new_object_str )
1121 {
1122 object = rpsl_object_init(new_object_str);
1123 error_list = rpsl_object_errors(object);
1124
1125 if ( UP_remove_override_attr(object) )
1126 arg2 = rpsl_object_get_text(object, RPSL_STD_COLUMN);
1127 else
1128 {
1129 /* there was an override attr in this object and it has not been removed */
1130 arg2 = (char *)malloc(2);
1131 strcpy(arg2, ""); /* Don't include object in ack/notif msgs */
1132 }
1133 }
1134
1135 if (old_object_str != NULL && new_object_str != NULL)
1136 { /* it was an update */
1137 e_mail_list = NT_gather_frwd_addresses(old_object_str);
1138 NT_add_to_frwd_hash_list(forwd_hash, e_mail_list);
1139 NT_add_to_ntfy_list(e_mail_list, forwd_hash, "----\nUPDATE REQUESTED FOR:\n\n");
1140 NT_add_to_ntfy_list(e_mail_list, forwd_hash, arg2);
1141 }
1142 else if (old_object_str == NULL && new_object_str != NULL)
1143 { /* it was a creation */
1144 e_mail_list = NT_gather_frwd_addresses(new_object_str);
1145 NT_add_to_frwd_hash_list(forwd_hash, e_mail_list);
1146 NT_add_to_ntfy_list(e_mail_list, forwd_hash, "----\nADDITION REQUESTED FOR:\n\n");
1147 NT_add_to_ntfy_list(e_mail_list, forwd_hash, arg2);
1148 }
1149 else if (old_object_str != NULL && new_object_str == NULL)
1150 { /* it was a deletion */
1151 e_mail_list = NT_gather_frwd_addresses(old_object_str);
1152 NT_add_to_frwd_hash_list(forwd_hash, e_mail_list);
1153 NT_add_to_ntfy_list(e_mail_list, forwd_hash, "----\nDELETION REQUESTED FOR:\n\n");
1154 NT_add_to_ntfy_list(e_mail_list, forwd_hash, old_object_str);
1155 }
1156 }
1157
1158
1159
1160 /* Sends the creation forward message which is stored in the temporary file filename. */
1161 void NT_send_forw_creation( const char * filename, const char * to_address, const char * mailercommand)
/* [<][>][^][v][top][bottom][index][help] */
1162 {
1163 char * mail_command_line = NULL;
1164
1165 if (to_address != NULL)
1166 {
1167 mail_command_line = (char *)malloc(strlen(mailercommand) + strlen(filename) + 128);
1168 sprintf(mail_command_line, "%s %s < %s", mailercommand, to_address, filename);
1169 system(mail_command_line);
1170 free(mail_command_line);
1171 }
1172 }
1173
1174
1175 /* NT_forw_create_req forwards the maintainer, as-block and irt creation requests
1176 to <HUMAILBOX> */
1177 void NT_forw_create_req(const char * object_str)
/* [<][>][^][v][top][bottom][index][help] */
1178 {
1179 FILE * forw_file;
1180 char * filename;
1181 char * replaced_mtfwheader;
1182 char * replaced_mtfwtxt;
1183
1184 /* allocate space for name. 32 should be enough for PID */
1185 filename = (char*)malloc(strlen(tmpdir) + strlen("creat-forw") +34 );
1186
1187 sprintf(filename, "%s/%s.%i", tmpdir, "creat-forw", (int)(getpid()) );
1188
1189 /* create the file */
1190 if (( forw_file = fopen(filename, "w")) == NULL)
1191 {
1192 fprintf(stderr, "NT_forw_create_req: Can't open creation forward file for creating, %s", filename);
1193 }
1194
1195 replaced_mtfwheader = UP_replace_globals(mtfwheader);
1196 replaced_mtfwtxt = UP_replace_globals(mtfwtxt);
1197
1198 fprintf(forw_file, "%s\n\n", replaced_mtfwheader);
1199
1200 if (reading_from_mail)
1201 {
1202 fprintf(forw_file, "%s\n\n", replaced_mtfwtxt);
1203 }
1204
1205 /* print the object */
1206 fprintf(forw_file, "%s\n\n", object_str);
1207
1208 /* close it */
1209 fclose(forw_file);
1210
1211 /* send it */
1212 NT_send_forw_creation(filename, humailbox, mailcmd);
1213
1214 /* log it */
1215 NT_log_ntfy(filename, forwlog);
1216
1217 /* delete it */
1218 unlink(filename);
1219
1220 /* free the mem */
1221 free(filename);
1222 free(replaced_mtfwheader);
1223 free(replaced_mtfwtxt);
1224 }