1 /*
2     pmacct (Promiscuous mode IP Accounting package)
3     pmacct is Copyright (C) 2003-2020 by Paolo Lucente
4 */
5 
6 /*
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11 
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16 
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21 
22 /* includes */
23 #include "pmacct.h"
24 #include "addr.h"
25 #include "pmacct-data.h"
26 #include "addr.h"
27 #include "bgp.h"
28 #include "thread_pool.h"
29 #if defined WITH_RABBITMQ
30 #include "amqp_common.h"
31 #endif
32 #ifdef WITH_KAFKA
33 #include "kafka_common.h"
34 #endif
35 
36 /* BGP Address Famiy Identifier to UNIX Address Family converter. */
bgp_afi2family(int afi)37 int bgp_afi2family (int afi)
38 {
39   if (afi == AFI_IP)
40     return AF_INET;
41   else if (afi == AFI_IP6)
42     return AF_INET6;
43   return SUCCESS;
44 }
45 
bgp_rd_ntoh(rd_t * rd)46 int bgp_rd_ntoh(rd_t *rd)
47 {
48   struct rd_ip  *rdi;
49   struct rd_as  *rda;
50   struct rd_as4 *rda4;
51 
52   if (!rd) return ERR;
53 
54   rd->type = ntohs(rd->type);
55 
56   switch(rd->type) {
57   case RD_TYPE_AS:
58     rda = (struct rd_as *) rd;
59     rda->as = ntohs(rda->as);
60     rda->val = ntohl(rda->val);
61     break;
62   case RD_TYPE_IP:
63     rdi = (struct rd_ip *) rd;
64     rdi->val = ntohs(rdi->val);
65     break;
66   case RD_TYPE_AS4:
67     rda4 = (struct rd_as4 *) rd;
68     rda4->as = ntohl(rda4->as);
69     rda4->val = ntohs(rda4->val);
70     break;
71   default:
72     return ERR;
73     break;
74   }
75 
76   return SUCCESS;
77 }
78 
bgp_rd2str(char * str,rd_t * rd)79 int bgp_rd2str(char *str, rd_t *rd)
80 {
81   struct rd_ip  *rdi;
82   struct rd_as  *rda;
83   struct rd_as4 *rda4;
84   struct host_addr a;
85   char ip_address[INET6_ADDRSTRLEN];
86 
87   switch (rd->type) {
88   case RD_TYPE_AS:
89     rda = (struct rd_as *) rd;
90     sprintf(str, "%u:%u:%u", rda->type, rda->as, rda->val);
91     break;
92   case RD_TYPE_IP:
93     rdi = (struct rd_ip *) rd;
94     a.family = AF_INET;
95     a.address.ipv4.s_addr = rdi->ip.s_addr;
96     addr_to_str(ip_address, &a);
97     sprintf(str, "%u:%s:%u", rdi->type, ip_address, rdi->val);
98     break;
99   case RD_TYPE_AS4:
100     rda4 = (struct rd_as4 *) rd;
101     sprintf(str, "%u:%u:%u", rda4->type, rda4->as, rda4->val);
102     break;
103   case RD_TYPE_VRFID:
104     rda = (struct rd_as *) rd;
105     sprintf(str, "vrfid:%u", rda->val);
106     break;
107   default:
108     sprintf(str, "unknown");
109     break;
110   }
111 
112   return TRUE;
113 }
114 
bgp_str2rd(rd_t * output,char * value)115 int bgp_str2rd(rd_t *output, char *value)
116 {
117   struct host_addr a;
118   char *endptr, *token;
119   u_int32_t tmp32;
120   struct rd_ip  *rdi;
121   struct rd_as  *rda;
122   struct rd_as4 *rda4;
123   int idx = 0;
124   rd_t rd;
125 
126   memset(&a, 0, sizeof(a));
127   memset(&rd, 0, sizeof(rd));
128 
129   /* type:RD_subfield1:RD_subfield2 */
130   while ( (token = extract_token(&value, ':')) && idx < 3) {
131     if (idx == 0) {
132       tmp32 = strtoul(token, &endptr, 10);
133       rd.type = tmp32;
134       switch (rd.type) {
135       case RD_TYPE_AS:
136         rda = (struct rd_as *) &rd;
137         break;
138       case RD_TYPE_IP:
139         rdi = (struct rd_ip *) &rd;
140         break;
141       case RD_TYPE_AS4:
142         rda4 = (struct rd_as4 *) &rd;
143         break;
144       default:
145         printf("ERROR: Invalid RD type specified\n");
146         return FALSE;
147       }
148     }
149     if (idx == 1) {
150       switch (rd.type) {
151       case RD_TYPE_AS:
152         tmp32 = strtoul(token, &endptr, 10);
153         rda->as = tmp32;
154         break;
155       case RD_TYPE_IP:
156         memset(&a, 0, sizeof(a));
157         str_to_addr(token, &a);
158         if (a.family == AF_INET) rdi->ip.s_addr = a.address.ipv4.s_addr;
159         break;
160       case RD_TYPE_AS4:
161         tmp32 = strtoul(token, &endptr, 10);
162         rda4->as = tmp32;
163         break;
164       }
165     }
166     if (idx == 2) {
167       switch (rd.type) {
168       case RD_TYPE_AS:
169         tmp32 = strtoul(token, &endptr, 10);
170         rda->val = tmp32;
171         break;
172       case RD_TYPE_IP:
173         tmp32 = strtoul(token, &endptr, 10);
174         rdi->val = tmp32;
175         break;
176       case RD_TYPE_AS4:
177         tmp32 = strtoul(token, &endptr, 10);
178         rda4->val = tmp32;
179         break;
180       }
181     }
182 
183     idx++;
184   }
185 
186   memcpy(output, &rd, sizeof(rd));
187 
188   return TRUE;
189 }
190 
bgp_label2str(char * str,u_char * label)191 int bgp_label2str(char *str, u_char *label)
192 {
193   unsigned long int tmp;
194   char *endp;
195 
196   snprintf(str, 10, "0x%02x%02x%01x",
197 	(unsigned)(unsigned char)label[0],
198 	(unsigned)(unsigned char)label[1],
199 	(unsigned)(unsigned char)(label[2] >> 4));
200 
201   tmp = strtoul(str, &endp, 16);
202   snprintf(str, 8, "%lu", tmp);
203 
204   return TRUE;
205 }
206 
207 /* Allocate bgp_info_extra */
bgp_info_extra_new(struct bgp_info * ri)208 struct bgp_info_extra *bgp_info_extra_new(struct bgp_info *ri)
209 {
210   struct bgp_misc_structs *bms;
211   struct bgp_info_extra *new;
212 
213   if (!ri || !ri->peer) return NULL;
214 
215   bms = bgp_select_misc_db(ri->peer->type);
216 
217   if (!bms) return NULL;
218 
219   new = malloc(sizeof(struct bgp_info_extra));
220   if (!new) {
221     Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (bgp_info_extra_new). Exiting ..\n", config.name, bms->log_str);
222     exit_gracefully(1);
223   }
224   else memset(new, 0, sizeof (struct bgp_info_extra));
225 
226   return new;
227 }
228 
bgp_info_extra_free(struct bgp_peer * peer,struct bgp_info_extra ** extra)229 void bgp_info_extra_free(struct bgp_peer *peer, struct bgp_info_extra **extra)
230 {
231   struct bgp_misc_structs *bms;
232 
233   bms = bgp_select_misc_db(peer->type);
234 
235   if (!bms) return;
236 
237   if (extra && *extra) {
238     if ((*extra)->bmed.id && bms->bgp_extra_data_free) (*bms->bgp_extra_data_free)(&(*extra)->bmed);
239 
240     free(*extra);
241     *extra = NULL;
242   }
243 }
244 
245 /* Get bgp_info extra information for the given bgp_info */
bgp_info_extra_get(struct bgp_info * ri)246 struct bgp_info_extra *bgp_info_extra_get(struct bgp_info *ri)
247 {
248   if (!ri->extra)
249     ri->extra = bgp_info_extra_new(ri);
250 
251   return ri->extra;
252 }
253 
bgp_info_extra_process(struct bgp_peer * peer,struct bgp_info * ri,safi_t safi,path_id_t * path_id,rd_t * rd,u_char * label)254 struct bgp_info_extra *bgp_info_extra_process(struct bgp_peer *peer, struct bgp_info *ri, safi_t safi,
255 		  			      path_id_t *path_id, rd_t *rd, u_char *label)
256 {
257   struct bgp_info_extra *rie = NULL;
258 
259   /* Install/update MPLS stuff if required */
260   if (safi == SAFI_MPLS_LABEL || safi == SAFI_MPLS_VPN) {
261     if (!rie) rie = bgp_info_extra_get(ri);
262 
263     if (rie) {
264       if (safi == SAFI_MPLS_VPN) memcpy(&rie->rd, rd, sizeof(rd_t));
265       memcpy(&rie->label, label, 3);
266     }
267   }
268 
269   /* Install/update BGP ADD-PATHs stuff if required */
270   if (peer->cap_add_paths && path_id && *path_id) {
271     if (!rie) rie = bgp_info_extra_get(ri);
272     if (rie) memcpy(&rie->path_id, path_id, sizeof(path_id_t));
273   }
274 
275   return rie;
276 }
277 
278 /* Allocate new bgp info structure. */
bgp_info_new(struct bgp_peer * peer)279 struct bgp_info *bgp_info_new(struct bgp_peer *peer)
280 {
281   struct bgp_misc_structs *bms;
282   struct bgp_info *new;
283 
284   if (!peer) return NULL;
285 
286   bms = bgp_select_misc_db(peer->type);
287 
288   if (!bms) return NULL;
289 
290   new = malloc(sizeof(struct bgp_info));
291   if (!new) {
292     Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (bgp_info_new). Exiting ..\n", config.name, bms->log_str);
293     exit_gracefully(1);
294   }
295   else memset(new, 0, sizeof (struct bgp_info));
296 
297   return new;
298 }
299 
bgp_info_add(struct bgp_peer * peer,struct bgp_node * rn,struct bgp_info * ri,u_int32_t modulo)300 void bgp_info_add(struct bgp_peer *peer, struct bgp_node *rn, struct bgp_info *ri, u_int32_t modulo)
301 {
302   struct bgp_info *top;
303 
304   top = rn->info[modulo];
305 
306   ri->next = rn->info[modulo];
307   ri->prev = NULL;
308   if (top)
309     top->prev = ri;
310   rn->info[modulo] = ri;
311 
312   bgp_lock_node(peer, rn);
313   ri->peer->lock++;
314 }
315 
bgp_info_delete(struct bgp_peer * peer,struct bgp_node * rn,struct bgp_info * ri,u_int32_t modulo)316 void bgp_info_delete(struct bgp_peer *peer, struct bgp_node *rn, struct bgp_info *ri, u_int32_t modulo)
317 {
318   if (ri->next)
319     ri->next->prev = ri->prev;
320   if (ri->prev)
321     ri->prev->next = ri->next;
322   else
323     rn->info[modulo] = ri->next;
324 
325   bgp_info_free(peer, ri);
326 
327   bgp_unlock_node(peer, rn);
328 }
329 
330 /* Free bgp route information. */
bgp_info_free(struct bgp_peer * peer,struct bgp_info * ri)331 void bgp_info_free(struct bgp_peer *peer, struct bgp_info *ri)
332 {
333   if (ri->attr)
334     bgp_attr_unintern(peer, ri->attr);
335 
336   bgp_info_extra_free(peer, &ri->extra);
337 
338   ri->peer->lock--;
339   free(ri);
340 }
341 
342 /* Initialization of attributes */
bgp_attr_init(int buckets,struct bgp_rt_structs * inter_domain_routing_db)343 void bgp_attr_init(int buckets, struct bgp_rt_structs *inter_domain_routing_db)
344 {
345   aspath_init(buckets, &inter_domain_routing_db->ashash);
346   attrhash_init(buckets, &inter_domain_routing_db->attrhash);
347   community_init(buckets, &inter_domain_routing_db->comhash);
348   ecommunity_init(buckets, &inter_domain_routing_db->ecomhash);
349   lcommunity_init(buckets, &inter_domain_routing_db->lcomhash);
350 }
351 
attrhash_key_make(void * p)352 unsigned int attrhash_key_make(void *p)
353 {
354   struct bgp_attr *attr = (struct bgp_attr *) p;
355   unsigned int key = 0;
356 
357   key += attr->origin;
358   key += attr->nexthop.s_addr;
359   key += attr->med;
360   key += attr->local_pref;
361 
362   if (attr->aspath)
363     key += aspath_key_make(attr->aspath);
364   if (attr->community)
365     key += community_hash_make(attr->community);
366   if (attr->ecommunity)
367     key += ecommunity_hash_make(attr->ecommunity);
368   if (attr->lcommunity)
369     key += lcommunity_hash_make(attr->lcommunity);
370 
371   /* XXX: add mp_nexthop to key */
372 
373   return key;
374 }
375 
attrhash_cmp(const void * p1,const void * p2)376 int attrhash_cmp(const void *p1, const void *p2)
377 {
378   const struct bgp_attr *attr1 = (const struct bgp_attr *)p1;
379   const struct bgp_attr *attr2 = (const struct bgp_attr *)p2;
380 
381   if (attr1->flag == attr2->flag
382       && attr1->origin == attr2->origin
383       && attr1->nexthop.s_addr == attr2->nexthop.s_addr
384       && attr1->aspath == attr2->aspath
385       && attr1->community == attr2->community
386       && attr1->ecommunity == attr2->ecommunity
387       && attr1->lcommunity == attr2->lcommunity
388       && attr1->med == attr2->med
389       && attr1->local_pref == attr2->local_pref
390       && !host_addr_cmp2((struct host_addr *)&attr1->mp_nexthop, (struct host_addr *)&attr2->mp_nexthop))
391     return TRUE;
392 
393   return FALSE;
394 }
395 
attrhash_init(int buckets,struct hash ** loc_attrhash)396 void attrhash_init(int buckets, struct hash **loc_attrhash)
397 {
398   (*loc_attrhash) = (struct hash *) hash_create(buckets, attrhash_key_make, attrhash_cmp);
399 }
400 
401 /* Internet argument attribute. */
bgp_attr_intern(struct bgp_peer * peer,struct bgp_attr * attr)402 struct bgp_attr *bgp_attr_intern(struct bgp_peer *peer, struct bgp_attr *attr)
403 {
404   struct bgp_rt_structs *inter_domain_routing_db;
405   struct bgp_attr *find;
406 
407   if (!peer) return NULL;
408 
409   inter_domain_routing_db = bgp_select_routing_db(peer->type);
410 
411   if (!inter_domain_routing_db) return NULL;
412 
413   /* Intern referenced strucutre. */
414   if (attr->aspath) {
415     if (! attr->aspath->refcnt)
416       attr->aspath = aspath_intern(peer, attr->aspath);
417   else
418     attr->aspath->refcnt++;
419   }
420   if (attr->community) {
421     if (! attr->community->refcnt)
422       attr->community = community_intern(peer, attr->community);
423     else
424       attr->community->refcnt++;
425   }
426   if (attr->ecommunity) {
427     if (!attr->ecommunity->refcnt)
428       attr->ecommunity = ecommunity_intern(peer, attr->ecommunity);
429   else
430     attr->ecommunity->refcnt++;
431   }
432   if (attr->lcommunity) {
433     if (!attr->lcommunity->refcnt)
434       attr->lcommunity = lcommunity_intern(peer, attr->lcommunity);
435   else
436     attr->lcommunity->refcnt++;
437   }
438 
439   find = (struct bgp_attr *) hash_get(peer, inter_domain_routing_db->attrhash, attr, bgp_attr_hash_alloc);
440   find->refcnt++;
441 
442   return find;
443 }
444 
445 /* Free bgp attribute and aspath. */
bgp_attr_unintern(struct bgp_peer * peer,struct bgp_attr * attr)446 void bgp_attr_unintern(struct bgp_peer *peer, struct bgp_attr *attr)
447 {
448   struct bgp_rt_structs *inter_domain_routing_db;
449   struct bgp_misc_structs *bms;
450   struct bgp_attr *ret;
451   struct aspath *aspath;
452   struct community *community;
453   struct ecommunity *ecommunity = NULL;
454   struct lcommunity *lcommunity = NULL;
455 
456   if (!peer) return;
457 
458   inter_domain_routing_db = bgp_select_routing_db(peer->type);
459   bms = bgp_select_misc_db(peer->type);
460 
461   if (!inter_domain_routing_db || !bms) return;
462 
463   /* Decrement attribute reference. */
464   attr->refcnt--;
465   aspath = attr->aspath;
466   community = attr->community;
467   ecommunity = attr->ecommunity;
468   lcommunity = attr->lcommunity;
469 
470   /* If reference becomes zero then free attribute object. */
471   if (attr->refcnt == 0) {
472     ret = (struct bgp_attr *) hash_release(inter_domain_routing_db->attrhash, attr);
473     // assert (ret != NULL);
474     if (!ret) Log(LOG_INFO, "INFO ( %s/%s ): bgp_attr_unintern() hash lookup failed.\n", config.name, bms->log_str);
475     free(attr);
476   }
477 
478   /* aspath refcount shoud be decrement. */
479   if (aspath)
480     aspath_unintern(peer, aspath);
481   if (community)
482     community_unintern(peer, community);
483   if (ecommunity)
484     ecommunity_unintern(peer, ecommunity);
485   if (lcommunity)
486     lcommunity_unintern(peer, lcommunity);
487 }
488 
bgp_attr_hash_alloc(void * p)489 void *bgp_attr_hash_alloc(void *p)
490 {
491   struct bgp_attr *val = (struct bgp_attr *) p;
492   struct bgp_attr *attr;
493 
494   attr = malloc(sizeof (struct bgp_attr));
495   if (!attr) {
496     Log(LOG_ERR, "ERROR ( %s/core/BGP ): malloc() failed (bgp_attr_hash_alloc). Exiting ..\n", config.name); // XXX
497     exit_gracefully(1);
498   }
499   else {
500     memset(attr, 0, sizeof (struct bgp_attr));
501     memcpy(attr, val, sizeof (struct bgp_attr));
502     attr->refcnt = 0;
503   }
504 
505   return attr;
506 }
507 
bgp_peer_cache_init(struct bgp_peer_cache_bucket * cache,u_int32_t buckets)508 void bgp_peer_cache_init(struct bgp_peer_cache_bucket *cache, u_int32_t buckets)
509 {
510   u_int32_t idx;
511 
512   for (idx = 0; idx < buckets; idx++) {
513     memset(&cache[idx], 0, sizeof(struct bgp_peer_cache_bucket));
514     pthread_mutex_init(&cache[idx].mutex, NULL);
515   }
516 }
517 
bgp_peer_cache_insert(struct bgp_peer_cache_bucket * cache,u_int32_t bucket,struct bgp_peer * peer)518 struct bgp_peer_cache *bgp_peer_cache_insert(struct bgp_peer_cache_bucket *cache, u_int32_t bucket, struct bgp_peer *peer)
519 {
520   struct bgp_peer_cache *cursor, *last, *new, *ret = NULL;
521 
522   pthread_mutex_lock(&peers_cache[bucket].mutex);
523 
524   for (cursor = peers_cache[bucket].e, last = NULL; cursor; cursor = cursor->next) last = cursor;
525 
526   new = malloc(sizeof(struct bgp_peer_cache));
527   if (new) {
528     new->ptr = peer;
529     new->next = NULL;
530 
531     if (!last) peers_cache[bucket].e = new;
532     else last->next = new;
533 
534     ret = new;
535   }
536 
537   pthread_mutex_unlock(&peers_cache[bucket].mutex);
538 
539   return ret;
540 }
541 
bgp_peer_cache_delete(struct bgp_peer_cache_bucket * cache,u_int32_t bucket,struct bgp_peer * peer)542 int bgp_peer_cache_delete(struct bgp_peer_cache_bucket *cache, u_int32_t bucket, struct bgp_peer *peer)
543 {
544   struct bgp_peer_cache *cursor, *last;
545   int ret = ERR;
546 
547   pthread_mutex_lock(&peers_cache[bucket].mutex);
548 
549   for (cursor = peers_cache[bucket].e, last = NULL; cursor; cursor = cursor->next) {
550     if (cursor->ptr == peer) {
551       if (!last) peers_cache[bucket].e = cursor->next;
552       else last->next = cursor->next;
553 
554       free(cursor);
555 
556       ret = SUCCESS;
557       break;
558     }
559 
560     last = cursor;
561   }
562 
563   pthread_mutex_unlock(&peers_cache[bucket].mutex);
564 
565   return ret;
566 }
567 
bgp_peer_cache_search(struct bgp_peer_cache_bucket * cache,u_int32_t bucket,struct host_addr * ha,u_int16_t port)568 struct bgp_peer *bgp_peer_cache_search(struct bgp_peer_cache_bucket *cache, u_int32_t bucket, struct host_addr *ha, u_int16_t port)
569 {
570   struct bgp_peer_cache *cursor;
571   struct bgp_peer *ret = NULL;
572 
573   pthread_mutex_lock(&peers_cache[bucket].mutex);
574 
575   for (cursor = peers_cache[bucket].e; cursor; cursor = cursor->next) {
576     if (port) {
577       if (cursor->ptr->tcp_port != port) continue;
578     }
579 
580     if (!host_addr_cmp(&cursor->ptr->addr, ha)) {
581       ret = cursor->ptr;
582       break;
583     }
584   }
585 
586   pthread_mutex_unlock(&peers_cache[bucket].mutex);
587 
588   return ret;
589 }
590 
bgp_peer_init(struct bgp_peer * peer,int type)591 int bgp_peer_init(struct bgp_peer *peer, int type)
592 {
593   struct bgp_misc_structs *bms;
594   int ret = TRUE;
595 
596   bms = bgp_select_misc_db(type);
597 
598   if (!peer || !bms) return ERR;
599 
600   memset(peer, 0, sizeof(struct bgp_peer));
601   peer->type = type;
602   peer->status = Idle;
603   peer->buf.tot_len = BGP_BUFFER_SIZE;
604   peer->buf.base = malloc(peer->buf.tot_len);
605   if (!peer->buf.base) {
606     Log(LOG_ERR, "ERROR ( %s/%s ): malloc() failed (bgp_peer_init). Exiting ..\n", config.name, bms->log_str);
607     exit_gracefully(1);
608   }
609   else {
610     memset(peer->buf.base, 0, peer->buf.tot_len);
611     ret = FALSE;
612   }
613 
614   return ret;
615 }
616 
bgp_peer_close(struct bgp_peer * peer,int type,int no_quiet,int send_notification,u_int8_t n_major,u_int8_t n_minor,char * shutdown_msg)617 void bgp_peer_close(struct bgp_peer *peer, int type, int no_quiet, int send_notification, u_int8_t n_major, u_int8_t n_minor, char *shutdown_msg)
618 {
619   struct bgp_misc_structs *bms;
620 
621   if (!peer) return;
622 
623   bms = bgp_select_misc_db(peer->type);
624 
625   if (!bms) return;
626 
627   if (!config.bgp_xconnect_map) {
628     if (send_notification) {
629       int ret, notification_msglen = (BGP_MIN_NOTIFICATION_MSG_SIZE + BGP_NOTIFY_CEASE_SM_LEN + 1);
630       char notification_msg[notification_msglen];
631 
632       ret = bgp_write_notification_msg(notification_msg, notification_msglen, n_major, n_minor, shutdown_msg);
633       if (ret) send(peer->fd, notification_msg, ret, 0);
634     }
635 
636     /* be quiet if we are in a signal handler and already set to exit */
637     if (!no_quiet) bgp_peer_info_delete(peer);
638 
639     if (bms->msglog_file || bms->msglog_amqp_routing_key || bms->msglog_kafka_topic)
640       bgp_peer_log_close(peer, bms->msglog_output, peer->type);
641 
642     if (bms->peers_cache && bms->peers_port_cache) {
643       u_int32_t bucket;
644 
645       bucket = addr_hash(&peer->addr, bms->max_peers);
646       bgp_peer_cache_delete(bms->peers_cache, bucket, peer);
647 
648       bucket = addr_port_hash(&peer->addr, peer->tcp_port, bms->max_peers);
649       bgp_peer_cache_delete(bms->peers_port_cache, bucket, peer);
650     }
651   }
652   else {
653     if (peer->xconnect_fd && peer->xconnect_fd != ERR) close(peer->xconnect_fd);
654   }
655 
656   if (peer->fd && peer->fd != ERR) close(peer->fd);
657 
658   peer->fd = 0;
659   memset(&peer->xc, 0, sizeof(peer->xc));
660   peer->xconnect_fd = 0;
661   memset(&peer->id, 0, sizeof(peer->id));
662   memset(&peer->addr, 0, sizeof(peer->addr));
663   memset(&peer->addr_str, 0, sizeof(peer->addr_str));
664 
665   free(peer->buf.base);
666 
667   if (bms->neighbors_file)
668     write_neighbors_file(bms->neighbors_file, peer->type);
669 }
670 
bgp_peer_xconnect_init(struct bgp_peer * peer,int type)671 int bgp_peer_xconnect_init(struct bgp_peer *peer, int type)
672 {
673   char peer_str[INET6_ADDRSTRLEN], xconnect_str[BGP_XCONNECT_STRLEN];
674   struct bgp_misc_structs *bms;
675   struct bgp_xconnects *bxm;
676   int ret = TRUE, idx, fd;
677 
678   assert(!peer->xconnect_fd);
679 
680   bms = bgp_select_misc_db(type);
681 
682   if (!peer || !bms) return ERR;
683 
684   bxm = bms->xconnects;
685 
686   if (bxm) {
687     for (idx = 0; idx < bxm->num; idx++) {
688       if (!sa_addr_cmp((struct sockaddr *) &bxm->pool[idx].src, &peer->addr) ||
689 	  !host_addr_mask_cmp(&bxm->pool[idx].src_addr, &bxm->pool[idx].src_mask, &peer->addr)) {
690 	struct sockaddr *sa = (struct sockaddr *) &bxm->pool[idx].dst;
691 
692 	memcpy(&peer->xc, &bxm->pool[idx], sizeof(struct bgp_xconnect));
693 	bgp_peer_xconnect_print(peer, xconnect_str, BGP_XCONNECT_STRLEN);
694 
695 	fd = socket(sa->sa_family, SOCK_STREAM, 0);
696 	if (fd == ERR) {
697 	  Log(LOG_WARNING, "WARN ( %s/%s ): [%s] bgp_peer_xconnect_init(): socket() failed.\n", config.name, bms->log_str, xconnect_str);
698 	  memset(&peer->xc, 0, sizeof(peer->xc));
699 	  peer->xconnect_fd = 0;
700 	  return ERR;
701 	}
702 
703 	ret = connect(fd, sa, bxm->pool[idx].dst_len);
704 	if (ret == ERR) {
705 	  Log(LOG_WARNING, "WARN ( %s/%s ): [%s] bgp_peer_xconnect_init(): connect() failed.\n", config.name, bms->log_str, xconnect_str);
706 	  memset(&peer->xc, 0, sizeof(peer->xc));
707 	  peer->xconnect_fd = 0;
708 	  return ERR;
709 	}
710 
711 	peer->xconnect_fd = fd;
712 	break;
713       }
714     }
715 
716     if (!peer->xconnect_fd) {
717       bgp_peer_print(peer, peer_str, INET6_ADDRSTRLEN);
718       Log(LOG_WARNING, "WARN ( %s/%s ): [%s] unable to xconnect BGP peer.\n", config.name, bgp_misc_db->log_str, peer_str);
719     }
720   }
721 
722   return ret;
723 }
724 
bgp_peer_print(struct bgp_peer * peer,char * buf,int len)725 void bgp_peer_print(struct bgp_peer *peer, char *buf, int len)
726 {
727   char dumb_buf[] = "0.0.0.0";
728   int ret = 0;
729 
730   if (!buf || len < INET6_ADDRSTRLEN) return;
731 
732   if (peer) {
733     if (peer->id.family) {
734       inet_ntop(AF_INET, &peer->id.address.ipv4, buf, len);
735       ret = AF_INET;
736     }
737     else ret = addr_to_str(buf, &peer->addr);
738   }
739 
740   if (!ret) strcpy(buf, dumb_buf);
741 }
742 
bgp_peer_xconnect_print(struct bgp_peer * peer,char * buf,int len)743 void bgp_peer_xconnect_print(struct bgp_peer *peer, char *buf, int len)
744 {
745   char src[INET6_ADDRSTRLEN + PORT_STRLEN + 1], dst[INET6_ADDRSTRLEN + PORT_STRLEN + 1];
746   struct sockaddr *sa_src;
747   struct sockaddr *sa_dst;
748 
749   if (peer && buf && len >= BGP_XCONNECT_STRLEN) {
750     sa_src = (struct sockaddr *) &peer->xc.src;
751     sa_dst = (struct sockaddr *) &peer->xc.dst;
752 
753     if (sa_src->sa_family) sa_to_str(src, sizeof(src), sa_src);
754     else addr_mask_to_str(src, sizeof(src), &peer->xc.src_addr, &peer->xc.src_mask);
755 
756     sa_to_str(dst, sizeof(dst), sa_dst);
757 
758     snprintf(buf, len, "%s x %s", src, dst);
759   }
760 }
761 
bgp_peer_info_delete(struct bgp_peer * peer)762 void bgp_peer_info_delete(struct bgp_peer *peer)
763 {
764   struct bgp_rt_structs *inter_domain_routing_db = bgp_select_routing_db(peer->type);
765   struct bgp_table *table;
766   afi_t afi;
767   safi_t safi;
768 
769   if (!inter_domain_routing_db) return;
770 
771   for (afi = AFI_IP; afi < AFI_MAX; afi++) {
772     for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
773       table = inter_domain_routing_db->rib[afi][safi];
774       bgp_table_info_delete(peer, table, afi, safi);
775     }
776   }
777 }
778 
bgp_table_info_delete(struct bgp_peer * peer,struct bgp_table * table,afi_t afi,safi_t safi)779 void bgp_table_info_delete(struct bgp_peer *peer, struct bgp_table *table, afi_t afi, safi_t safi)
780 {
781   struct bgp_misc_structs *bms = bgp_select_misc_db(peer->type);
782   struct bgp_node *node;
783 
784   node = bgp_table_top(peer, table);
785 
786   while (node) {
787     u_int32_t modulo;
788     u_int32_t peer_buckets;
789     struct bgp_info *ri;
790     struct bgp_info *ri_next;
791 
792     if (bms->route_info_modulo) modulo = bms->route_info_modulo(peer, NULL, bms->table_per_peer_buckets);
793     else modulo = 0;
794 
795     for (peer_buckets = 0; peer_buckets < bms->table_per_peer_buckets; peer_buckets++) {
796       for (ri = node->info[modulo + peer_buckets]; ri; ri = ri_next) {
797 	if (ri->peer == peer) {
798 	  if (bms->msglog_backend_methods) {
799 	    char event_type[] = "log";
800 
801 	    bgp_peer_log_msg(node, ri, afi, safi, event_type, bms->msglog_output, NULL, BGP_LOG_TYPE_DELETE);
802 	  }
803 
804 	  ri_next = ri->next; /* let's save pointer to next before free up */
805           bgp_info_delete(peer, node, ri, (modulo + peer_buckets));
806         }
807 	else ri_next = ri->next;
808       }
809     }
810 
811     node = bgp_route_next(peer, node);
812   }
813 }
814 
bgp_attr_munge_as4path(struct bgp_peer * peer,struct bgp_attr * attr,struct aspath * as4path)815 int bgp_attr_munge_as4path(struct bgp_peer *peer, struct bgp_attr *attr, struct aspath *as4path)
816 {
817   struct aspath *newpath;
818 
819   /* If the BGP peer supports 32bit AS_PATH then we are done */
820   if (peer->cap_4as) return SUCCESS;
821 
822   /* pre-requisite for AS4_PATH is AS_PATH indeed */
823   // XXX if (as4path && !attr->aspath) return ERR;
824 
825   newpath = aspath_reconcile_as4(attr->aspath, as4path);
826   aspath_unintern(peer, attr->aspath);
827   attr->aspath = aspath_intern(peer, newpath);
828 
829   return SUCCESS;
830 }
831 
load_comm_patterns(char ** stdcomm,char ** extcomm,char ** lrgcomm,char ** stdcomm_to_asn,char ** lrgcomm_to_asn)832 void load_comm_patterns(char **stdcomm, char **extcomm, char **lrgcomm, char **stdcomm_to_asn, char **lrgcomm_to_asn)
833 {
834   int idx;
835   char *token;
836 
837   memset(std_comm_patterns, 0, sizeof(std_comm_patterns));
838   memset(ext_comm_patterns, 0, sizeof(ext_comm_patterns));
839   memset(lrg_comm_patterns, 0, sizeof(lrg_comm_patterns));
840   memset(std_comm_patterns_to_asn, 0, sizeof(std_comm_patterns_to_asn));
841   memset(lrg_comm_patterns_to_asn, 0, sizeof(lrg_comm_patterns_to_asn));
842 
843   if (*stdcomm) {
844     idx = 0;
845     while ( (token = extract_token(stdcomm, ',')) && idx < MAX_BGP_COMM_PATTERNS ) {
846       std_comm_patterns[idx] = token;
847       trim_spaces(std_comm_patterns[idx]);
848       idx++;
849     }
850   }
851 
852   if (*extcomm) {
853     idx = 0;
854     while ( (token = extract_token(extcomm, ',')) && idx < MAX_BGP_COMM_PATTERNS ) {
855       ext_comm_patterns[idx] = token;
856       trim_spaces(ext_comm_patterns[idx]);
857       idx++;
858     }
859   }
860 
861   if (*lrgcomm) {
862     idx = 0;
863     while ( (token = extract_token(lrgcomm, ',')) && idx < MAX_BGP_COMM_PATTERNS ) {
864       lrg_comm_patterns[idx] = token;
865       trim_spaces(lrg_comm_patterns[idx]);
866       idx++;
867     }
868   }
869 
870   if (*stdcomm_to_asn) {
871     idx = 0;
872     while ( (token = extract_token(stdcomm_to_asn, ',')) && idx < MAX_BGP_COMM_PATTERNS ) {
873       std_comm_patterns_to_asn[idx] = token;
874       trim_spaces(std_comm_patterns_to_asn[idx]);
875       idx++;
876     }
877   }
878 
879   if (*lrgcomm_to_asn) {
880     idx = 0;
881     while ( (token = extract_token(lrgcomm_to_asn, ',')) && idx < MAX_BGP_COMM_PATTERNS ) {
882       lrg_comm_patterns_to_asn[idx] = token;
883       trim_spaces(lrg_comm_patterns_to_asn[idx]);
884       idx++;
885     }
886   }
887 }
888 
evaluate_comm_patterns(char * dst,char * src,char ** patterns,int dstlen)889 void evaluate_comm_patterns(char *dst, char *src, char **patterns, int dstlen)
890 {
891   char *ptr, *haystack, *delim_src, *delim_ptn;
892   char local_ptr[MAX_BGP_STD_COMMS], *auxptr;
893   int idx, i, j;
894 
895   if (!src || !dst || !dstlen) return;
896 
897   memset(dst, 0, dstlen);
898 
899   for (idx = 0, j = 0; patterns[idx]; idx++) {
900     haystack = src;
901 
902     find_again:
903     delim_ptn = strchr(patterns[idx], '.');
904     if (delim_ptn) *delim_ptn = '\0';
905     ptr = strstr(haystack, patterns[idx]);
906 
907     if (ptr && delim_ptn) {
908       delim_src = strchr(ptr, ' ');
909       if (delim_src) {
910 	memcpy(local_ptr, ptr, delim_src-ptr);
911         local_ptr[delim_src-ptr] = '\0';
912       }
913       else memcpy(local_ptr, ptr, strlen(ptr)+1);
914       *delim_ptn = '.';
915 
916       if (strlen(local_ptr) != strlen(patterns[idx])) ptr = NULL;
917       else {
918 	for (auxptr = strchr(patterns[idx], '.'); auxptr; auxptr = strchr(auxptr, '.')) {
919 	  local_ptr[auxptr-patterns[idx]] = '.';
920 	  auxptr++;
921 	}
922 	if (strncmp(patterns[idx], local_ptr, strlen(patterns[idx]))) ptr = NULL;
923       }
924     }
925     else if (delim_ptn) *delim_ptn = '.';
926 
927     if (ptr) {
928       /* If we have already something on the stack, let's insert a space */
929       if (j && j < dstlen) {
930 	dst[j] = ' ';
931 	j++;
932       }
933 
934       /* We should be able to trust this string */
935       for (i = 0; ptr[i] != ' ' && ptr[i] != '\0'; i++, j++) {
936 	if (j < dstlen) dst[j] = ptr[i];
937 	else break;
938       }
939 
940       haystack = &ptr[i];
941     }
942 
943     /* If we don't have space anymore, let's finish it here */
944     if (j >= dstlen) {
945       dst[dstlen-2] = '+';
946       dst[dstlen-1] = '\0';
947       break;
948     }
949 
950     /* Trick to find multiple occurrences */
951     if (ptr) goto find_again;
952   }
953 }
954 
evaluate_last_asn(struct aspath * as)955 as_t evaluate_last_asn(struct aspath *as)
956 {
957   if (!as) return 0;
958 
959   return as->last_as;
960 }
961 
evaluate_first_asn(char * src)962 as_t evaluate_first_asn(char *src)
963 {
964   int idx, is_space = FALSE, len = strlen(src), start, sub_as, iteration;
965   char *endptr, *ptr, saved;
966   as_t asn, real_first_asn;
967 
968   start = 0;
969   iteration = 0;
970   real_first_asn = 0;
971 
972   start_again:
973 
974   asn = 0;
975   sub_as = FALSE;
976 
977   for (idx = start; idx < len && (src[idx] != ' ' && src[idx] != ')'); idx++);
978 
979   /* Mangling the AS_PATH string */
980   if (src[idx] == ' ' || src[idx] == ')') {
981     is_space = TRUE;
982     saved =  src[idx];
983     src[idx] = '\0';
984   }
985 
986   if (src[start] == '(') {
987     ptr = &src[start+1];
988     sub_as = TRUE;
989   }
990   else ptr = &src[start];
991 
992   asn = strtoul(ptr, &endptr, 10);
993 
994   /* Restoring mangled AS_PATH */
995   if (is_space) {
996     src[idx] = saved;
997     saved = '\0';
998     is_space = FALSE;
999   }
1000 
1001   if (config.bgp_daemon_peer_as_skip_subas /* XXX */ && sub_as) {
1002     while (idx < len && (src[idx] == ' ' || src[idx] == ')')) idx++;
1003 
1004     if (idx != len-1) {
1005       start = idx;
1006       if (iteration == 0) real_first_asn = asn;
1007       iteration++;
1008       goto start_again;
1009     }
1010   }
1011 
1012   /* skip sub-as kicks-in only when traffic is delivered to a different ASN */
1013   if (real_first_asn && (!asn || sub_as)) asn = real_first_asn;
1014 
1015   return asn;
1016 }
1017 
evaluate_bgp_aspath_radius(char * path,int len,int radius)1018 void evaluate_bgp_aspath_radius(char *path, int len, int radius)
1019 {
1020   int count, idx;
1021 
1022   for (idx = 0, count = 0; idx < len; idx++) {
1023     if (path[idx] == ' ') count++;
1024     if (count == radius) {
1025       path[idx] = '\0';
1026       break;
1027     }
1028   }
1029 }
1030 
copy_stdcomm_to_asn(char * stdcomm,as_t * asn,int is_origin)1031 void copy_stdcomm_to_asn(char *stdcomm, as_t *asn, int is_origin)
1032 {
1033   char *delim, *delim2;
1034   char *p1, *p2;
1035 
1036   if (!stdcomm || !strlen(stdcomm) || (delim = strchr(stdcomm, ':')) == NULL) return;
1037   if (validate_truefalse(is_origin)) return;
1038 
1039   delim2 = strchr(stdcomm, ',');
1040   *delim = '\0';
1041   if (delim2) *delim2 = '\0';
1042   p1 = stdcomm;
1043   p2 = delim+1;
1044 
1045   if (is_origin) *asn = atoi(p2);
1046   else *asn = atoi(p1);
1047 }
1048 
copy_lrgcomm_to_asn(char * lrgcomm,as_t * asn,int is_origin)1049 void copy_lrgcomm_to_asn(char *lrgcomm, as_t *asn, int is_origin)
1050 {
1051   char *delim, *delim2;
1052   char *p1, *p2, *endptr;
1053 
1054   if (!lrgcomm || !strlen(lrgcomm) || (delim = strchr(lrgcomm, ':')) == NULL) return;
1055   if (validate_truefalse(is_origin)) return;
1056 
1057   delim2 = strchr(lrgcomm, ':');
1058   *delim = '\0';
1059   *delim2 = '\0';
1060   p1 = lrgcomm;
1061   p2 = delim+1;
1062 
1063   if (is_origin) *asn = strtoul(p2, &endptr, 10);
1064   else *asn = strtoul(p1, &endptr, 10);
1065 }
1066 
1067 /* XXX: currently only BGP is supported due to use of peers struct */
write_neighbors_file(char * filename,int type)1068 void write_neighbors_file(char *filename, int type)
1069 {
1070   struct bgp_misc_structs *bms = bgp_select_misc_db(type);
1071   FILE *file;
1072   char neighbor[INET6_ADDRSTRLEN+1];
1073   int idx, len, ret;
1074   uid_t owner = -1;
1075   gid_t group = -1;
1076 
1077   if (!bms) return;
1078 
1079   unlink(filename);
1080 
1081   if (config.files_uid) owner = config.files_uid;
1082   if (config.files_gid) group = config.files_gid;
1083 
1084   file = fopen(filename,"w");
1085   if (file) {
1086     if ((ret = chown(filename, owner, group)) == -1)
1087       Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Unable to chown() (%s).\n", config.name, bms->log_str, filename, strerror(errno));
1088 
1089     if (file_lock(fileno(file))) {
1090       Log(LOG_ERR, "ERROR ( %s/%s ): [%s] Unable to obtain lock.\n", config.name, bms->log_str, filename);
1091       return;
1092     }
1093     for (idx = 0; idx < bms->max_peers; idx++) {
1094       if (peers[idx].fd) {
1095         if (peers[idx].addr.family == AF_INET) {
1096           inet_ntop(AF_INET, &peers[idx].addr.address.ipv4, neighbor, INET6_ADDRSTRLEN);
1097 	  len = strlen(neighbor);
1098 	  neighbor[len] = '\n'; len++;
1099 	  neighbor[len] = '\0';
1100           fwrite(neighbor, len, 1, file);
1101         }
1102 	else if (peers[idx].addr.family == AF_INET6) {
1103           inet_ntop(AF_INET6, &peers[idx].addr.address.ipv6, neighbor, INET6_ADDRSTRLEN);
1104           len = strlen(neighbor);
1105           neighbor[len] = '\n'; len++;
1106           neighbor[len] = '\0';
1107           fwrite(neighbor, len, 1, file);
1108         }
1109       }
1110     }
1111 
1112     file_unlock(fileno(file));
1113     fclose(file);
1114   }
1115   else {
1116     Log(LOG_ERR, "ERROR ( %s/%s ): [%s] fopen() failed.\n", config.name, bms->log_str, filename);
1117     return;
1118   }
1119 }
1120 
bgp_config_checks(struct configuration * c)1121 void bgp_config_checks(struct configuration *c)
1122 {
1123   if (c->what_to_count & (COUNT_LOCAL_PREF|COUNT_MED|COUNT_PEER_SRC_AS|COUNT_PEER_DST_AS|
1124 			  COUNT_PEER_SRC_IP|COUNT_PEER_DST_IP|COUNT_SRC_MED|COUNT_SRC_LOCAL_PREF|
1125 			  COUNT_MPLS_VPN_RD)) {
1126     /* Sanitizing the aggregation method */
1127       if ( (c->what_to_count & COUNT_SRC_LOCAL_PREF && !c->bgp_daemon_src_local_pref_type) ||
1128 	   (c->what_to_count & COUNT_SRC_MED && !c->bgp_daemon_src_med_type) ||
1129 	   (c->what_to_count & COUNT_PEER_SRC_AS && !c->bgp_daemon_peer_as_src_type &&
1130 	     (config.acct_type != ACCT_SF && config.acct_type != ACCT_NF)) ) {
1131       printf("ERROR: At least one of the following primitives is in use but its source type is not specified:\n");
1132       printf("       peer_src_as     =>  bgp_peer_src_as_type\n");
1133       printf("       src_local_pref  =>  bgp_src_local_pref_type\n");
1134       printf("       src_med         =>  bgp_src_med_type\n");
1135       exit_gracefully(1);
1136     }
1137 
1138     c->data_type |= PIPE_TYPE_BGP;
1139   }
1140 
1141   if ((c->what_to_count & (COUNT_STD_COMM|COUNT_EXT_COMM|COUNT_AS_PATH|COUNT_SRC_STD_COMM|
1142 			  COUNT_SRC_EXT_COMM|COUNT_SRC_AS_PATH)) ||
1143       (c->what_to_count_2 & (COUNT_LRG_COMM|COUNT_SRC_LRG_COMM))) {
1144     /* Sanitizing the aggregation method */
1145     if ( (c->what_to_count & COUNT_SRC_AS_PATH && !c->bgp_daemon_src_as_path_type) ||
1146          (c->what_to_count & COUNT_SRC_STD_COMM && !c->bgp_daemon_src_std_comm_type) ||
1147 	 (c->what_to_count & COUNT_SRC_EXT_COMM && !c->bgp_daemon_src_ext_comm_type) ||
1148 	 (c->what_to_count_2 & COUNT_SRC_LRG_COMM && !c->bgp_daemon_src_lrg_comm_type) ) {
1149       printf("ERROR: At least one of the following primitives is in use but its source type is not specified:\n");
1150       printf("       src_as_path     =>  bgp_src_as_path_type\n");
1151       printf("       src_std_comm    =>  bgp_src_std_comm_type\n");
1152       printf("       src_ext_comm    =>  bgp_src_ext_comm_type\n");
1153       printf("       src_lrg_comm    =>  bgp_src_lrg_comm_type\n");
1154       exit_gracefully(1);
1155     }
1156 
1157     if (c->type_id == PLUGIN_ID_MEMORY) c->data_type |= PIPE_TYPE_LBGP;
1158     else c->data_type |= PIPE_TYPE_VLEN;
1159   }
1160 }
1161 
bgp_md5_file_init(struct bgp_md5_table * t)1162 void bgp_md5_file_init(struct bgp_md5_table *t)
1163 {
1164   if (t) memset(t, 0, sizeof(struct bgp_md5_table));
1165 }
1166 
bgp_md5_file_load(char * filename,struct bgp_md5_table * t)1167 void bgp_md5_file_load(char *filename, struct bgp_md5_table *t)
1168 {
1169   FILE *file;
1170   char buf[SRVBUFLEN], *ptr;
1171   int index = 0;
1172 
1173   if (filename && t) {
1174     Log(LOG_INFO, "INFO ( %s/core/BGP ): [%s] (re)loading map.\n", config.name, filename);
1175 
1176     if ((file = fopen(filename, "r")) == NULL) {
1177       Log(LOG_ERR, "ERROR ( %s/core/BGP ): [%s] file not found.\n", config.name, filename);
1178       exit_gracefully(1);
1179     }
1180 
1181     while (!feof(file)) {
1182       if (index >= BGP_MD5_MAP_ENTRIES) {
1183 	Log(LOG_WARNING, "WARN ( %s/core/BGP ): [%s] loaded the first %u entries.\n", config.name, filename, BGP_MD5_MAP_ENTRIES);
1184         break;
1185       }
1186       memset(buf, 0, SRVBUFLEN);
1187       if (fgets(buf, SRVBUFLEN, file)) {
1188         if (!sanitize_buf(buf)) {
1189           char *token;
1190           int tk_idx = 0, ret = 0, len = 0;
1191 
1192           ptr = buf;
1193 	  memset(&t->table[index], 0, sizeof(t->table[index]));
1194           while ( (token = extract_token(&ptr, ',')) && tk_idx < 2 ) {
1195             if (tk_idx == 0) ret = str_to_addr(token, &t->table[index].addr);
1196             else if (tk_idx == 1) {
1197               strlcpy(t->table[index].key, token, TCP_MD5SIG_MAXKEYLEN);
1198               len = strlen(t->table[index].key);
1199             }
1200             tk_idx++;
1201           }
1202 
1203           if (ret > 0 && len > 0) index++;
1204           else Log(LOG_WARNING, "WARN ( %s/core/BGP ): [%s] line '%s' ignored.\n", config.name, filename, buf);
1205         }
1206       }
1207     }
1208     t->num = index;
1209 
1210     /* Set to -1 to distinguish between no map and empty map conditions */
1211     if (!t->num) t->num = -1;
1212 
1213     Log(LOG_INFO, "INFO ( %s/core/BGP ): [%s] map successfully (re)loaded.\n", config.name, filename);
1214     fclose(file);
1215   }
1216 }
1217 
bgp_md5_file_unload(struct bgp_md5_table * t)1218 void bgp_md5_file_unload(struct bgp_md5_table *t)
1219 {
1220   int index = 0;
1221 
1222   if (!t) return;
1223 
1224   while (index < t->num) {
1225     memset(t->table[index].key, 0, TCP_MD5SIG_MAXKEYLEN);
1226     index++;
1227   }
1228 }
1229 
bgp_md5_file_process(int sock,struct bgp_md5_table * bgp_md5)1230 void bgp_md5_file_process(int sock, struct bgp_md5_table *bgp_md5)
1231 {
1232   char peer_str[INET6_ADDRSTRLEN + PORT_STRLEN + 1];
1233   struct pm_tcp_md5sig md5sig;
1234   struct sockaddr_storage ss_md5sig, ss_server;
1235   struct sockaddr *sa_md5sig = (struct sockaddr *)&ss_md5sig, *sa_server = (struct sockaddr *)&ss_server;
1236   int rc, keylen, idx = 0, ss_md5sig_len;
1237   socklen_t ss_server_len;
1238 
1239   if (!bgp_md5) return;
1240 
1241   while (idx < bgp_md5->num) {
1242     memset(&md5sig, 0, sizeof(md5sig));
1243     memset(&ss_md5sig, 0, sizeof(ss_md5sig));
1244 
1245     ss_md5sig_len = addr_to_sa((struct sockaddr *)&ss_md5sig, &bgp_md5->table[idx].addr, 0);
1246 
1247     ss_server_len = sizeof(ss_server);
1248     getsockname(sock, (struct sockaddr *)&ss_server, &ss_server_len);
1249 
1250     if (sa_md5sig->sa_family == AF_INET6 && sa_server->sa_family == AF_INET) {
1251       ipv4_mapped_to_ipv4(&ss_md5sig);
1252       ss_md5sig_len = sizeof(struct sockaddr_in);
1253     }
1254     else if (sa_md5sig->sa_family == AF_INET && sa_server->sa_family == AF_INET6) {
1255       ipv4_to_ipv4_mapped(&ss_md5sig);
1256       ss_md5sig_len = sizeof(struct sockaddr_in6);
1257     }
1258 
1259     memcpy(&md5sig.tcpm_addr, &ss_md5sig, ss_md5sig_len);
1260     keylen = strlen(bgp_md5->table[idx].key);
1261     if (keylen) {
1262       md5sig.tcpm_keylen = keylen;
1263       memcpy(md5sig.tcpm_key, &bgp_md5->table[idx].key, keylen);
1264     }
1265 
1266     sa_to_str(peer_str, sizeof(peer_str), sa_md5sig);
1267 
1268     rc = setsockopt(sock, IPPROTO_TCP, TCP_MD5SIG, &md5sig, (socklen_t) sizeof(md5sig));
1269     if (rc < 0) {
1270       Log(LOG_WARNING, "WARN ( %s/core/BGP ): setsockopt() failed for TCP_MD5SIG peer=%s (errno: %d)\n", config.name, peer_str, errno);
1271     }
1272     else {
1273       Log(LOG_DEBUG, "DEBUG ( %s/core/BGP ): setsockopt() set TCP_MD5SIG peer=%s\n", config.name, peer_str);
1274     }
1275 
1276     idx++;
1277   }
1278 }
1279 
bgp_batch_init(struct bgp_peer_batch * bp_batch,int num,int interval)1280 void bgp_batch_init(struct bgp_peer_batch *bp_batch, int num, int interval)
1281 {
1282   if (bp_batch) {
1283     memset(bp_batch, 0, sizeof(struct bgp_peer_batch));
1284 
1285     bp_batch->num = num;
1286     bp_batch->interval = interval;
1287   }
1288 }
1289 
bgp_batch_reset(struct bgp_peer_batch * bp_batch,time_t now)1290 void bgp_batch_reset(struct bgp_peer_batch *bp_batch, time_t now)
1291 {
1292   if (bp_batch) {
1293     bp_batch->num_current = bp_batch->num;
1294     bp_batch->base_stamp = now;
1295   }
1296 }
1297 
bgp_batch_is_admitted(struct bgp_peer_batch * bp_batch,time_t now)1298 int bgp_batch_is_admitted(struct bgp_peer_batch *bp_batch, time_t now)
1299 {
1300   if (bp_batch) {
1301     /* bgp_batch_is_not_empty() maybe replaced by a linear
1302        distribution of the peers over the time interval */
1303     if (bgp_batch_is_not_empty(bp_batch) || bgp_batch_is_expired(bp_batch, now)) return TRUE;
1304     else return FALSE;
1305   }
1306   else return ERR;
1307 }
1308 
bgp_batch_is_enabled(struct bgp_peer_batch * bp_batch)1309 int bgp_batch_is_enabled(struct bgp_peer_batch *bp_batch)
1310 {
1311   if (bp_batch) {
1312     if (bp_batch->num) return TRUE;
1313     else return FALSE;
1314   }
1315   else return ERR;
1316 }
1317 
bgp_batch_is_expired(struct bgp_peer_batch * bp_batch,time_t now)1318 int bgp_batch_is_expired(struct bgp_peer_batch *bp_batch, time_t now)
1319 {
1320   if (bp_batch) {
1321     if (now > (bp_batch->base_stamp + bp_batch->interval)) return TRUE;
1322     else return FALSE;
1323   }
1324   else return ERR;
1325 }
1326 
bgp_batch_is_not_empty(struct bgp_peer_batch * bp_batch)1327 int bgp_batch_is_not_empty(struct bgp_peer_batch *bp_batch)
1328 {
1329   if (bp_batch) {
1330     if (bp_batch->num_current) return TRUE;
1331     else return FALSE;
1332   }
1333   else return ERR;
1334 }
1335 
bgp_batch_increase_counter(struct bgp_peer_batch * bp_batch)1336 void bgp_batch_increase_counter(struct bgp_peer_batch *bp_batch)
1337 {
1338   if (bp_batch) bp_batch->num_current++;
1339 }
1340 
bgp_batch_decrease_counter(struct bgp_peer_batch * bp_batch)1341 void bgp_batch_decrease_counter(struct bgp_peer_batch *bp_batch)
1342 {
1343   if (bp_batch) bp_batch->num_current--;
1344 }
1345 
bgp_batch_rollback(struct bgp_peer_batch * bp_batch)1346 void bgp_batch_rollback(struct bgp_peer_batch *bp_batch)
1347 {
1348   if (bp_batch && bgp_batch_is_enabled(bp_batch)) {
1349     bgp_batch_increase_counter(bp_batch);
1350     if (bp_batch->num_current == bp_batch->num)
1351       bgp_batch_init(bp_batch, bp_batch->num, bp_batch->interval);
1352   }
1353 }
1354 
bgp_select_routing_db(int peer_type)1355 struct bgp_rt_structs *bgp_select_routing_db(int peer_type)
1356 {
1357   if (peer_type < FUNC_TYPE_MAX)
1358     return &inter_domain_routing_dbs[peer_type];
1359 
1360   return NULL;
1361 }
1362 
bgp_select_misc_db(int peer_type)1363 struct bgp_misc_structs *bgp_select_misc_db(int peer_type)
1364 {
1365   if (peer_type < FUNC_TYPE_MAX)
1366     return &inter_domain_misc_dbs[peer_type];
1367 
1368   return NULL;
1369 }
1370 
bgp_link_misc_structs(struct bgp_misc_structs * bms)1371 void bgp_link_misc_structs(struct bgp_misc_structs *bms)
1372 {
1373 #if defined WITH_RABBITMQ
1374   bms->msglog_amqp_host = &bgp_daemon_msglog_amqp_host;
1375 #endif
1376 #if defined WITH_KAFKA
1377   bms->msglog_kafka_host = &bgp_daemon_msglog_kafka_host;
1378 #endif
1379   bms->max_peers = config.bgp_daemon_max_peers;
1380   bms->peers = peers;
1381   bms->peers_cache = peers_cache;
1382   bms->peers_port_cache = peers_port_cache;
1383   bms->xconnects = &bgp_xcs_map;
1384   bms->neighbors_file = config.bgp_daemon_neighbors_file;
1385   bms->dump_file = config.bgp_table_dump_file;
1386   bms->dump_amqp_routing_key = config.bgp_table_dump_amqp_routing_key;
1387   bms->dump_amqp_routing_key_rr = config.bgp_table_dump_amqp_routing_key_rr;
1388   bms->dump_kafka_topic = config.bgp_table_dump_kafka_topic;
1389   bms->dump_kafka_topic_rr = config.bgp_table_dump_kafka_topic_rr;
1390   bms->dump_kafka_avro_schema_registry = config.bgp_table_dump_kafka_avro_schema_registry;
1391   bms->msglog_file = config.bgp_daemon_msglog_file;
1392   bms->msglog_output = config.bgp_daemon_msglog_output;
1393   bms->msglog_amqp_routing_key = config.bgp_daemon_msglog_amqp_routing_key;
1394   bms->msglog_amqp_routing_key_rr = config.bgp_daemon_msglog_amqp_routing_key_rr;
1395   bms->msglog_kafka_topic = config.bgp_daemon_msglog_kafka_topic;
1396   bms->msglog_kafka_topic_rr = config.bgp_daemon_msglog_kafka_topic_rr;
1397   bms->msglog_kafka_avro_schema_registry = config.bgp_daemon_msglog_kafka_avro_schema_registry;
1398   bms->peer_str = malloc(strlen("peer_ip_src") + 1);
1399   strcpy(bms->peer_str, "peer_ip_src");
1400   bms->peer_port_str = malloc(strlen("peer_tcp_port") + 1);
1401   strcpy(bms->peer_port_str, "peer_tcp_port");
1402   bms->bgp_peer_log_msg_extras = NULL;
1403   bms->bgp_peer_logdump_initclose_extras = NULL;
1404 
1405   bms->table_peer_buckets = config.bgp_table_peer_buckets;
1406   bms->table_per_peer_buckets = config.bgp_table_per_peer_buckets;
1407   bms->table_attr_hash_buckets = config.bgp_table_attr_hash_buckets;
1408   bms->table_per_peer_hash = config.bgp_table_per_peer_hash;
1409   bms->route_info_modulo = bgp_route_info_modulo;
1410   bms->bgp_lookup_find_peer = bgp_lookup_find_bgp_peer;
1411   bms->bgp_lookup_node_match_cmp = bgp_lookup_node_match_cmp_bgp;
1412 
1413   bms->bgp_msg_open_router_id_check = bgp_router_id_check;
1414 
1415   if (!bms->is_thread && !bms->dump_backend_methods && !bms->has_lglass && !bms->has_blackhole) {
1416     bms->skip_rib = TRUE;
1417   }
1418 }
1419 
bgp_blackhole_link_misc_structs(struct bgp_misc_structs * m_data)1420 void bgp_blackhole_link_misc_structs(struct bgp_misc_structs *m_data)
1421 {
1422   m_data->table_peer_buckets = 1; /* saving on DEFAULT_BGP_INFO_HASH for now */
1423   m_data->table_per_peer_buckets = DEFAULT_BGP_INFO_PER_PEER_HASH;
1424   m_data->table_attr_hash_buckets = HASHTABSIZE;
1425   m_data->table_per_peer_hash = BGP_ASPATH_HASH_PATHID;
1426   m_data->route_info_modulo = NULL;
1427   m_data->bgp_lookup_node_match_cmp = NULL;
1428 }
1429 
bgp_peer_cmp(const void * a,const void * b)1430 int bgp_peer_cmp(const void *a, const void *b)
1431 {
1432   return host_addr_cmp(&((struct bgp_peer *)a)->addr, &((struct bgp_peer *)b)->addr);
1433 }
1434 
bgp_peer_host_addr_cmp(const void * a,const void * b)1435 int bgp_peer_host_addr_cmp(const void *a, const void *b)
1436 {
1437   return host_addr_cmp((struct host_addr *)a, &((struct bgp_peer *)b)->addr);
1438 }
1439 
bgp_peer_sa_addr_cmp(const void * a,const void * b)1440 int bgp_peer_sa_addr_cmp(const void *a, const void *b)
1441 {
1442   return sa_addr_cmp((struct sockaddr *) a, &((struct bgp_peer *)b)->addr);
1443 }
1444 
bgp_peer_free(void * a)1445 void bgp_peer_free(void *a)
1446 {
1447 }
1448 
bgp_peers_bintree_walk_print(const void * nodep,const pm_VISIT which,const int depth,void * extra)1449 int bgp_peers_bintree_walk_print(const void *nodep, const pm_VISIT which, const int depth, void *extra)
1450 {
1451   struct bgp_misc_structs *bms;
1452   struct bgp_peer *peer;
1453   char peer_str[INET6_ADDRSTRLEN];
1454 
1455   peer = (*(struct bgp_peer **) nodep);
1456   bms = bgp_select_misc_db(peer->type);
1457 
1458   if (!bms) return FALSE;
1459 
1460   if (!peer) Log(LOG_INFO, "INFO ( %s/%s ): bgp_peers_bintree_walk_print(): null\n", config.name, bms->log_str);
1461   else {
1462     addr_to_str(peer_str, &peer->addr);
1463     Log(LOG_INFO, "INFO ( %s/%s ): bgp_peers_bintree_walk_print(): %s\n", config.name, bms->log_str, peer_str);
1464   }
1465 
1466   return TRUE;
1467 }
1468 
bgp_peers_bintree_walk_delete(const void * nodep,const pm_VISIT which,const int depth,void * extra)1469 int bgp_peers_bintree_walk_delete(const void *nodep, const pm_VISIT which, const int depth, void *extra)
1470 {
1471   struct bgp_misc_structs *bms;
1472   char peer_str[] = "peer_ip", *saved_peer_str;
1473   struct bgp_peer *peer;
1474 
1475   peer = (*(struct bgp_peer **) nodep);
1476 
1477   if (!peer) return FALSE;
1478 
1479   bms = bgp_select_misc_db(peer->type);
1480 
1481   if (!bms) return FALSE;
1482 
1483   saved_peer_str = bms->peer_str;
1484   bms->peer_str = peer_str;
1485   bgp_peer_info_delete(peer);
1486   bms->peer_str = saved_peer_str;
1487 
1488   // XXX: count tree elements to index and free() later
1489 
1490   return TRUE;
1491 }
1492 
bgp_router_id_check(struct bgp_msg_data * bmd)1493 int bgp_router_id_check(struct bgp_msg_data *bmd)
1494 {
1495   struct bgp_peer *peer = bmd->peer;
1496   struct bgp_misc_structs *bms;
1497   struct bgp_peer *peers_check;
1498   int peers_check_idx = 0;
1499 
1500   bms = bgp_select_misc_db(peer->type);
1501 
1502   if (!bms) return ERR;
1503 
1504   peers_check = bms->peers;
1505 
1506   for (; peers_check_idx < bms->max_peers; peers_check_idx++) {
1507     if (peers_check_idx != peer->idx && !memcmp(&peers_check[peers_check_idx].id, &peer->id, sizeof(peers_check[peers_check_idx].id))) {
1508       char bgp_peer_str[INET6_ADDRSTRLEN];
1509 
1510       bgp_peer_print(&peers_check[peers_check_idx], bgp_peer_str, INET6_ADDRSTRLEN);
1511       Log(LOG_WARNING, "WARN ( %s/%s ): [%s] Refusing new connection from existing Router-ID.\n", config.name, bms->log_str, bgp_peer_str);
1512 
1513       return ERR;
1514     }
1515   }
1516 
1517   return FALSE;
1518 }
1519 
1520 /*
1521   utility function when an ASN is prepended by 'AS', 'AS ', etc. strings
1522   that need to be stripped.
1523 */
bgp_str2asn(char * asn_str,as_t * asn)1524 int bgp_str2asn(char *asn_str, as_t *asn)
1525 {
1526   char *endptr, *asn_ptr = asn_str;
1527   int len, cnt;
1528 
1529   if (!asn_str || !asn) return ERR;
1530 
1531   len = strlen(asn_str);
1532 
1533   for (cnt = 0; !isdigit(asn_str[cnt]) && (cnt < len); cnt++);
1534 
1535   asn_ptr = &asn_str[cnt];
1536 
1537   (*asn) = strtoul(asn_ptr, &endptr, 10);
1538   if (endptr == asn_ptr || (*endptr) != '\0') return ERR;
1539   if (errno) {
1540     errno = FALSE;
1541     return ERR;
1542   }
1543 
1544   return SUCCESS;
1545 }
1546 
bgp_origin_print(u_int8_t origin)1547 const char *bgp_origin_print(u_int8_t origin)
1548 {
1549   if (origin <= BGP_ORIGIN_MAX) return bgp_origin[origin];
1550   else return bgp_origin[BGP_ORIGIN_UNKNOWN];
1551 }
1552 
bgp_str2origin(char * origin_str)1553 u_int8_t bgp_str2origin(char *origin_str)
1554 {
1555   if (!strcmp(origin_str, "i")) return BGP_ORIGIN_IGP;
1556   else if (!strcmp(origin_str, "e")) return BGP_ORIGIN_EGP;
1557   else if (!strcmp(origin_str, "u")) return BGP_ORIGIN_INCOMPLETE;
1558 
1559   return BGP_ORIGIN_UNKNOWN;
1560 }
1561 
bgp_get_packet_len(char * pkt)1562 u_int16_t bgp_get_packet_len(char *pkt)
1563 {
1564   struct bgp_header *bhdr = (struct bgp_header *) pkt;
1565   u_int16_t blen = 0;
1566 
1567   if (bgp_marker_check(bhdr, BGP_MARKER_SIZE) != ERR) {
1568     blen = ntohs(bhdr->bgpo_len);
1569   }
1570 
1571   return blen;
1572 }
1573