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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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, ... )
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, ...)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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,
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,
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)
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)
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 | }