3 * Used to advertise routes for upstream (l2tp port, rather than gratiutious
4 * arp) and downstream--allowing routers to load-balance both.
6 * Implementation limitations:
7 * - We never listen for incoming connections (session always initiated by us).
8 * - Any routes advertised by the peer are accepted, but ignored.
9 * - No password support; neither RFC1771 (which no-one seems to do anyway)
10 * nor RFC2385 (which requires a kernel patch on 2.4 kernels).
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
28 static void bgp_clear(struct bgp_peer
*peer
);
29 static void bgp_set_retry(struct bgp_peer
*peer
);
30 static void bgp_cidr(in_addr_t ip
, in_addr_t mask
, struct bgp_ip_prefix
*pfx
);
31 static struct bgp_route_list
*bgp_insert_route(struct bgp_route_list
*head
,
32 struct bgp_route_list
*new);
34 static void bgp_free_routes(struct bgp_route_list
*routes
);
35 static char const *bgp_msg_type_str(uint8_t type
);
36 static int bgp_connect(struct bgp_peer
*peer
);
37 static int bgp_handle_connect(struct bgp_peer
*peer
);
38 static int bgp_write(struct bgp_peer
*peer
);
39 static int bgp_read(struct bgp_peer
*peer
);
40 static int bgp_handle_input(struct bgp_peer
*peer
);
41 static int bgp_send_open(struct bgp_peer
*peer
);
42 static int bgp_send_keepalive(struct bgp_peer
*peer
);
43 static int bgp_send_update(struct bgp_peer
*peer
);
44 static int bgp_send_notification(struct bgp_peer
*peer
, uint8_t code
,
47 static uint16_t our_as
;
48 static struct bgp_route_list
*bgp_routes
= 0;
50 int bgp_configured
= 0;
51 struct bgp_peer
*bgp_peers
= 0;
53 /* prepare peer structure, globals */
57 struct bgp_peer
*peer
;
59 for (i
= 0; i
< BGP_NUM_PEERS
; i
++)
62 memset(peer
, 0, sizeof(*peer
));
64 peer
->addr
= INADDR_NONE
;
66 peer
->state
= peer
->next_state
= Disabled
;
68 if (!((peer
->outbuf
= malloc(sizeof(*peer
->outbuf
)))
69 && (peer
->inbuf
= malloc(sizeof(*peer
->inbuf
)))))
71 LOG(0, 0, 0, "Can't allocate buffers for bgp peer (%s)\n",
77 peer
->edata
.type
= FD_TYPE_BGP
;
78 peer
->edata
.index
= i
;
89 bgp_configured
= 0; /* set by bgp_start */
94 /* start connection with a peer */
95 int bgp_start(struct bgp_peer
*peer
, char *name
, int as
, int keepalive
,
101 struct bgp_path_attr a
;
103 char *p
= path_attrs
;
105 uint32_t metric
= htonl(BGP_METRIC
);
106 uint32_t no_export
= htonl(BGP_COMMUNITY_NO_EXPORT
);
111 if (peer
->state
!= Disabled
)
114 snprintf(peer
->name
, sizeof(peer
->name
), "%s", name
);
116 if (!(h
= gethostbyname(name
)) || h
->h_addrtype
!= AF_INET
)
118 LOG(0, 0, 0, "Can't get address for BGP peer %s (%s)\n",
119 name
, h
? "no address" : hstrerror(h_errno
));
124 memcpy(&peer
->addr
, h
->h_addr
, sizeof(peer
->addr
));
125 peer
->as
= as
> 0 ? as
: our_as
;
126 ibgp
= peer
->as
== our_as
;
128 /* set initial timer values */
129 peer
->init_keepalive
= keepalive
== -1 ? BGP_KEEPALIVE_TIME
: keepalive
;
130 peer
->init_hold
= hold
== -1 ? BGP_HOLD_TIME
: hold
;
132 if (peer
->init_hold
< 3)
135 if (peer
->init_keepalive
* 3 > peer
->init_hold
)
136 peer
->init_keepalive
= peer
->init_hold
/ 3;
138 /* clear buffers, go to Idle state */
139 peer
->next_state
= Idle
;
142 /* set initial routing state */
143 peer
->routing
= enable
;
145 /* all our routes use the same attributes, so prepare it in advance */
146 if (peer
->path_attrs
)
147 free(peer
->path_attrs
);
149 peer
->path_attr_len
= 0;
152 a
.flags
= BGP_PATH_ATTR_FLAG_TRANS
;
153 a
.code
= BGP_PATH_ATTR_CODE_ORIGIN
;
155 a
.data
.s
.value
[0] = BGP_PATH_ATTR_CODE_ORIGIN_IGP
;
157 #define ADD_ATTRIBUTE() do { \
158 i = BGP_PATH_ATTR_SIZE(a); \
161 peer->path_attr_len += i; } while (0)
166 a
.flags
= BGP_PATH_ATTR_FLAG_TRANS
;
167 a
.code
= BGP_PATH_ATTR_CODE_AS_PATH
;
181 BGP_PATH_ATTR_CODE_AS_PATH_AS_SEQUENCE
,
186 a
.data
.s
.len
= sizeof(as_path
);
187 memcpy(&a
.data
.s
.value
, &as_path
, sizeof(as_path
));
193 a
.flags
= BGP_PATH_ATTR_FLAG_TRANS
;
194 a
.code
= BGP_PATH_ATTR_CODE_NEXT_HOP
;
195 ip
= my_address
; /* we're it */
196 a
.data
.s
.len
= sizeof(ip
);
197 memcpy(a
.data
.s
.value
, &ip
, sizeof(ip
));
201 /* MULTI_EXIT_DISC */
202 a
.flags
= BGP_PATH_ATTR_FLAG_OPTIONAL
;
203 a
.code
= BGP_PATH_ATTR_CODE_MULTI_EXIT_DISC
;
204 a
.data
.s
.len
= sizeof(metric
);
205 memcpy(a
.data
.s
.value
, &metric
, sizeof(metric
));
211 uint32_t local_pref
= htonl(BGP_LOCAL_PREF
);
214 a
.flags
= BGP_PATH_ATTR_FLAG_TRANS
;
215 a
.code
= BGP_PATH_ATTR_CODE_LOCAL_PREF
;
216 a
.data
.s
.len
= sizeof(local_pref
);
217 memcpy(a
.data
.s
.value
, &local_pref
, sizeof(local_pref
));
223 a
.flags
= BGP_PATH_ATTR_FLAG_OPTIONAL
| BGP_PATH_ATTR_FLAG_TRANS
;
224 a
.code
= BGP_PATH_ATTR_CODE_COMMUNITIES
;
225 a
.data
.s
.len
= sizeof(no_export
);
226 memcpy(a
.data
.s
.value
, &no_export
, sizeof(no_export
));
230 if (!(peer
->path_attrs
= malloc(peer
->path_attr_len
)))
232 LOG(0, 0, 0, "Can't allocate path_attrs for %s (%s)\n",
233 name
, strerror(errno
));
238 memcpy(peer
->path_attrs
, path_attrs
, peer
->path_attr_len
);
240 LOG(4, 0, 0, "Initiating BGP connection to %s (routing %s)\n",
241 name
, enable
? "enabled" : "suspended");
243 /* we have at least one peer configured */
247 return bgp_connect(peer
);
250 /* clear counters, timers, routes and buffers; close socket; move to
251 next_state, which may be Disabled or Idle */
252 static void bgp_clear(struct bgp_peer
*peer
)
254 if (peer
->sock
!= -1)
260 peer
->keepalive_time
= 0;
261 peer
->expire_time
= 0;
263 peer
->keepalive
= peer
->init_keepalive
;
264 peer
->hold
= peer
->init_hold
;
266 bgp_free_routes(peer
->routes
);
269 peer
->outbuf
->packet
.header
.len
= 0;
270 peer
->outbuf
->done
= 0;
271 peer
->inbuf
->packet
.header
.len
= 0;
272 peer
->inbuf
->done
= 0;
277 if (peer
->state
!= peer
->next_state
)
279 peer
->state
= peer
->next_state
;
280 peer
->state_time
= time_now
;
282 LOG(4, 0, 0, "BGP peer %s: state %s\n", peer
->name
,
283 bgp_state_str(peer
->next_state
));
287 /* initiate a clean shutdown */
288 void bgp_stop(struct bgp_peer
*peer
)
290 LOG(4, 0, 0, "Terminating BGP connection to %s\n", peer
->name
);
291 bgp_send_notification(peer
, BGP_ERR_CEASE
, 0);
294 /* drop connection (if any) and set state to Disabled */
295 void bgp_halt(struct bgp_peer
*peer
)
297 LOG(4, 0, 0, "Aborting BGP connection to %s\n", peer
->name
);
298 peer
->next_state
= Disabled
;
302 /* drop connection (if any) and set to Idle for connection retry */
303 int bgp_restart(struct bgp_peer
*peer
)
305 peer
->next_state
= Idle
;
309 peer
->retry_time
= time_now
;
310 peer
->retry_count
= 0;
313 return bgp_connect(peer
);
316 static void bgp_set_retry(struct bgp_peer
*peer
)
318 if (peer
->retry_count
++ < BGP_MAX_RETRY
)
320 peer
->retry_time
= time_now
+ (BGP_RETRY_BACKOFF
* peer
->retry_count
);
321 peer
->next_state
= Idle
;
325 bgp_halt(peer
); /* give up */
328 /* convert ip/mask to CIDR notation */
329 static void bgp_cidr(in_addr_t ip
, in_addr_t mask
, struct bgp_ip_prefix
*pfx
)
334 /* convert to prefix notation */
338 if (!mask
) /* bogus */
341 for (i
= 0; i
< 32 && ((b
= ntohl(1 << i
)), !(mask
& b
)); i
++)
348 /* insert route into list; sorted */
349 static struct bgp_route_list
*bgp_insert_route(struct bgp_route_list
*head
,
350 struct bgp_route_list
*new)
352 struct bgp_route_list
*p
= head
;
353 struct bgp_route_list
*e
= 0;
355 while (p
&& memcmp(&p
->dest
, &new->dest
, sizeof(p
->dest
)) < 0)
375 /* add route to list for peers */
377 * Note: this doesn't do route aggregation, nor drop routes if a less
378 * specific match already exists (partly because I'm lazy, but also so
379 * that if that route is later deleted we don't have to be concerned
380 * about adding back the more specific one).
382 int bgp_add_route(in_addr_t ip
, in_addr_t mask
)
384 struct bgp_route_list
*r
= bgp_routes
;
385 struct bgp_route_list add
;
388 bgp_cidr(ip
, mask
, &add
.dest
);
391 /* check for duplicate */
394 i
= memcmp(&r
->dest
, &add
.dest
, sizeof(r
->dest
));
396 return 1; /* already covered */
404 /* insert into route list; sorted */
405 if (!(r
= malloc(sizeof(*r
))))
407 LOG(0, 0, 0, "Can't allocate route for %s/%d (%s)\n",
408 fmtaddr(add
.dest
.prefix
, 0), add
.dest
.len
, strerror(errno
));
413 memcpy(r
, &add
, sizeof(*r
));
414 bgp_routes
= bgp_insert_route(bgp_routes
, r
);
416 /* flag established peers for update */
417 for (i
= 0; i
< BGP_NUM_PEERS
; i
++)
418 if (bgp_peers
[i
].state
== Established
)
419 bgp_peers
[i
].update_routes
= 1;
421 LOG(4, 0, 0, "Registered BGP route %s/%d\n",
422 fmtaddr(add
.dest
.prefix
, 0), add
.dest
.len
);
427 /* remove route from list for peers */
428 int bgp_del_route(in_addr_t ip
, in_addr_t mask
)
430 struct bgp_route_list
*r
= bgp_routes
;
431 struct bgp_route_list
*e
= 0;
432 struct bgp_route_list del
;
435 bgp_cidr(ip
, mask
, &del
.dest
);
438 /* find entry in routes list and remove */
441 i
= memcmp(&r
->dest
, &del
.dest
, sizeof(r
->dest
));
447 bgp_routes
= r
->next
;
465 /* flag established peers for update */
466 for (i
= 0; i
< BGP_NUM_PEERS
; i
++)
467 if (bgp_peers
[i
].state
== Established
)
468 bgp_peers
[i
].update_routes
= 1;
470 LOG(4, 0, 0, "Removed BGP route %s/%d\n",
471 fmtaddr(del
.dest
.prefix
, 0), del
.dest
.len
);
476 /* enable or disable routing */
477 void bgp_enable_routing(int enable
)
481 for (i
= 0; i
< BGP_NUM_PEERS
; i
++)
483 bgp_peers
[i
].routing
= enable
;
485 /* flag established peers for update */
486 if (bgp_peers
[i
].state
== Established
)
487 bgp_peers
[i
].update_routes
= 1;
490 LOG(4, 0, 0, "%s BGP routing\n", enable
? "Enabled" : "Suspended");
494 # include <sys/epoll.h>
496 # include "fake_epoll.h"
499 /* return a bitmask of the events required to poll this peer's fd */
507 for (i
= 0; i
< BGP_NUM_PEERS
; i
++)
509 struct bgp_peer
*peer
= &bgp_peers
[i
];
512 if (peer
->state
== Disabled
|| peer
->state
== Idle
)
515 if (peer
->inbuf
->done
< BGP_MAX_PACKET_SIZE
)
518 if (peer
->state
== Connect
|| /* connection in progress */
519 peer
->update_routes
|| /* routing updates */
520 peer
->outbuf
->packet
.header
.len
) /* pending output */
523 if (peer
->events
!= events
)
525 struct epoll_event ev
;
527 ev
.events
= peer
->events
= events
;
528 ev
.data
.ptr
= &peer
->edata
;
529 epoll_ctl(epollfd
, EPOLL_CTL_MOD
, peer
->sock
, &ev
);
536 /* process bgp events/timers */
537 int bgp_process(uint32_t events
[])
544 for (i
= 0; i
< BGP_NUM_PEERS
; i
++)
546 struct bgp_peer
*peer
= &bgp_peers
[i
];
548 if (*peer
->name
&& peer
->cli_flag
== BGP_CLI_RESTART
)
554 if (peer
->state
== Disabled
)
559 switch (peer
->cli_flag
)
561 case BGP_CLI_SUSPEND
:
565 if (peer
->state
== Established
)
566 peer
->update_routes
= 1;
575 if (peer
->state
== Established
)
576 peer
->update_routes
= 1;
585 /* handle empty/fill of buffers */
586 if (events
[i
] & EPOLLOUT
)
589 if (peer
->state
== Connect
)
590 r
= bgp_handle_connect(peer
);
591 else if (peer
->outbuf
->packet
.header
.len
)
598 if (events
[i
] & (EPOLLIN
|EPOLLHUP
))
604 /* process input buffer contents */
605 while (peer
->inbuf
->done
>= sizeof(peer
->inbuf
->packet
.header
)
606 && !peer
->outbuf
->packet
.header
.len
) /* may need to queue a response */
608 if (bgp_handle_input(peer
) < 0)
612 /* process pending updates */
613 if (peer
->update_routes
614 && !peer
->outbuf
->packet
.header
.len
) /* ditto */
616 if (!bgp_send_update(peer
))
621 if (peer
->state
== Established
)
623 if (time_now
> peer
->expire_time
)
625 LOG(1, 0, 0, "No message from BGP peer %s in %ds\n",
626 peer
->name
, peer
->hold
);
628 bgp_send_notification(peer
, BGP_ERR_HOLD_TIMER_EXP
, 0);
632 if (time_now
> peer
->keepalive_time
&& !peer
->outbuf
->packet
.header
.len
)
633 bgp_send_keepalive(peer
);
635 else if (peer
->state
== Idle
)
637 if (time_now
> peer
->retry_time
)
640 else if (time_now
> peer
->state_time
+ BGP_STATE_TIME
)
642 LOG(1, 0, 0, "%s timer expired for BGP peer %s\n",
643 bgp_state_str(peer
->state
), peer
->name
);
652 static void bgp_free_routes(struct bgp_route_list
*routes
)
654 struct bgp_route_list
*tmp
;
656 while ((tmp
= routes
))
663 char const *bgp_state_str(enum bgp_state state
)
667 case Disabled
: return "Disabled";
668 case Idle
: return "Idle";
669 case Connect
: return "Connect";
670 case Active
: return "Active";
671 case OpenSent
: return "OpenSent";
672 case OpenConfirm
: return "OpenConfirm";
673 case Established
: return "Established";
679 static char const *bgp_msg_type_str(uint8_t type
)
683 case BGP_MSG_OPEN
: return "OPEN";
684 case BGP_MSG_UPDATE
: return "UPDATE";
685 case BGP_MSG_NOTIFICATION
: return "NOTIFICATION";
686 case BGP_MSG_KEEPALIVE
: return "KEEPALIVE";
692 /* attempt to connect to peer */
693 static int bgp_connect(struct bgp_peer
*peer
)
695 static int bgp_port
= 0;
696 struct sockaddr_in addr
;
697 struct epoll_event ev
;
701 struct servent
*serv
;
702 if (!(serv
= getservbyname("bgp", "tcp")))
704 LOG(0, 0, 0, "Can't get bgp service (%s)\n", strerror(errno
));
708 bgp_port
= serv
->s_port
;
711 if ((peer
->sock
= socket(PF_INET
, SOCK_STREAM
, IPPROTO_TCP
)) < 0)
713 LOG(0, 0, 0, "Can't create a socket for BGP peer %s (%s)\n",
714 peer
->name
, strerror(errno
));
716 peer
->state
= peer
->next_state
= Disabled
;
720 /* add to poll set */
721 ev
.events
= peer
->events
= EPOLLOUT
;
722 ev
.data
.ptr
= &peer
->edata
;
723 epoll_ctl(epollfd
, EPOLL_CTL_ADD
, peer
->sock
, &ev
);
725 /* set to non-blocking */
726 fcntl(peer
->sock
, F_SETFL
, fcntl(peer
->sock
, F_GETFL
, 0) | O_NONBLOCK
);
729 memset(&addr
, 0, sizeof(addr
));
730 addr
.sin_family
= AF_INET
;
731 addr
.sin_port
= bgp_port
;
732 addr
.sin_addr
.s_addr
= peer
->addr
;
734 while (connect(peer
->sock
, (struct sockaddr
*) &addr
, sizeof(addr
)) == -1)
736 if (errno
== EINTR
) /* SIGALARM handler */
739 if (errno
!= EINPROGRESS
)
741 LOG(1, 0, 0, "Can't connect to BGP peer %s (%s)\n",
742 inet_ntoa(addr
.sin_addr
), strerror(errno
));
748 peer
->state
= Connect
;
749 peer
->state_time
= time_now
;
751 LOG(4, 0, 0, "BGP peer %s: state Connect\n", peer
->name
);
755 peer
->state
= Active
;
756 peer
->state_time
= time_now
;
757 peer
->retry_time
= peer
->retry_count
= 0;
759 LOG(4, 0, 0, "BGP peer %s: state Active\n", inet_ntoa(addr
.sin_addr
));
761 return bgp_send_open(peer
);
764 /* complete partial connection (state = Connect) */
765 static int bgp_handle_connect(struct bgp_peer
*peer
)
768 socklen_t len
= sizeof(int);
769 getsockopt(peer
->sock
, SOL_SOCKET
, SO_ERROR
, &err
, &len
);
772 LOG(1, 0, 0, "Can't connect to BGP peer %s (%s)\n", peer
->name
,
779 peer
->state
= Active
;
780 peer
->state_time
= time_now
;
782 LOG(4, 0, 0, "BGP peer %s: state Active\n", peer
->name
);
784 return bgp_send_open(peer
);
787 /* initiate a write */
788 static int bgp_write(struct bgp_peer
*peer
)
790 int len
= htons(peer
->outbuf
->packet
.header
.len
);
793 while ((r
= write(peer
->sock
, &peer
->outbuf
->packet
+ peer
->outbuf
->done
,
794 len
- peer
->outbuf
->done
)) == -1)
803 LOG(1, 0, 0, "Connection to BGP peer %s closed\n", peer
->name
);
805 LOG(1, 0, 0, "Can't write to BGP peer %s (%s)\n", peer
->name
,
814 peer
->outbuf
->done
+= r
;
818 LOG(4, 0, 0, "Sent %s to BGP peer %s\n",
819 bgp_msg_type_str(peer
->outbuf
->packet
.header
.type
), peer
->name
);
821 peer
->outbuf
->packet
.header
.len
= 0;
822 peer
->outbuf
->done
= 0;
824 if (peer
->state
== Established
)
825 peer
->keepalive_time
= time_now
+ peer
->keepalive
;
827 if (peer
->state
!= peer
->next_state
)
829 if (peer
->next_state
== Disabled
|| peer
->next_state
== Idle
)
835 peer
->state
= peer
->next_state
;
836 peer
->state_time
= time_now
;
838 LOG(4, 0, 0, "BGP peer %s: state %s\n", peer
->name
,
839 bgp_state_str(peer
->state
));
845 /* initiate a read */
846 static int bgp_read(struct bgp_peer
*peer
)
850 while ((r
= read(peer
->sock
, &peer
->inbuf
->packet
+ peer
->inbuf
->done
,
851 BGP_MAX_PACKET_SIZE
- peer
->inbuf
->done
)) < 1)
855 LOG(1, 0, 0, "Connection to BGP peer %s closed\n", peer
->name
);
865 LOG(1, 0, 0, "Can't read from BGP peer %s (%s)\n", peer
->name
,
873 peer
->inbuf
->done
+= r
;
877 /* process buffered packets */
878 static int bgp_handle_input(struct bgp_peer
*peer
)
880 struct bgp_packet
*p
= &peer
->inbuf
->packet
;
881 int len
= ntohs(p
->header
.len
);
883 if (len
> BGP_MAX_PACKET_SIZE
)
885 LOG(1, 0, 0, "Bad header length from BGP %s\n", peer
->name
);
886 bgp_send_notification(peer
, BGP_ERR_HEADER
, BGP_ERR_HDR_BAD_LEN
);
890 if (peer
->inbuf
->done
< len
)
893 LOG(4, 0, 0, "Received %s from BGP peer %s\n",
894 bgp_msg_type_str(p
->header
.type
), peer
->name
);
896 switch (p
->header
.type
)
900 struct bgp_data_open data
;
904 for (i
= 0; i
< sizeof(p
->header
.marker
); i
++)
906 if ((unsigned char) p
->header
.marker
[i
] != 0xff)
908 LOG(1, 0, 0, "Invalid marker from BGP peer %s\n",
911 bgp_send_notification(peer
, BGP_ERR_HEADER
,
912 BGP_ERR_HDR_NOT_SYNC
);
918 if (peer
->state
!= OpenSent
)
920 LOG(1, 0, 0, "OPEN from BGP peer %s in %s state\n",
921 peer
->name
, bgp_state_str(peer
->state
));
923 bgp_send_notification(peer
, BGP_ERR_FSM
, 0);
927 memcpy(&data
, p
->data
, len
- sizeof(p
->header
));
929 if (data
.version
!= BGP_VERSION
)
931 LOG(1, 0, 0, "Bad version (%d) sent by BGP peer %s\n",
932 (int) data
.version
, peer
->name
);
934 bgp_send_notification(peer
, BGP_ERR_OPEN
, BGP_ERR_OPN_VERSION
);
938 if (ntohs(data
.as
) != peer
->as
)
940 LOG(1, 0, 0, "Bad AS sent by BGP peer %s (got %d, "
941 "expected %d)\n", peer
->name
, (int) htons(data
.as
),
944 bgp_send_notification(peer
, BGP_ERR_OPEN
, BGP_ERR_OPN_BAD_AS
);
948 if ((hold
= ntohs(data
.hold_time
)) < 3)
950 LOG(1, 0, 0, "Bad hold time (%d) from BGP peer %s\n",
953 bgp_send_notification(peer
, BGP_ERR_OPEN
, BGP_ERR_OPN_HOLD_TIME
);
957 /* pick lowest hold time */
958 if (hold
< peer
->hold
)
961 /* adjust our keepalive based on negotiated hold value */
962 if (peer
->keepalive
* 3 > peer
->hold
)
963 peer
->keepalive
= peer
->hold
/ 3;
965 /* next transition requires an exchange of keepalives */
966 bgp_send_keepalive(peer
);
968 /* FIXME: may need to check for optional params */
973 case BGP_MSG_KEEPALIVE
:
974 if (peer
->state
== OpenConfirm
)
976 peer
->state
= peer
->next_state
= Established
;
977 peer
->state_time
= time_now
;
978 peer
->keepalive_time
= time_now
+ peer
->keepalive
;
979 peer
->update_routes
= 1;
980 peer
->retry_count
= 0;
981 peer
->retry_time
= 0;
983 LOG(4, 0, 0, "BGP peer %s: state Established\n", peer
->name
);
988 case BGP_MSG_NOTIFICATION
:
989 if (len
> sizeof(p
->header
))
991 struct bgp_data_notification
*notification
=
992 (struct bgp_data_notification
*) p
->data
;
994 if (notification
->error_code
== BGP_ERR_CEASE
)
996 LOG(4, 0, 0, "BGP peer %s sent CEASE\n", peer
->name
);
1001 /* FIXME: should handle more notifications */
1002 LOG(4, 0, 0, "BGP peer %s sent unhandled NOTIFICATION %d\n",
1003 peer
->name
, (int) notification
->error_code
);
1010 peer
->expire_time
= time_now
+ peer
->hold
;
1012 /* see if there's another message in the same packet/buffer */
1013 if (peer
->inbuf
->done
> len
)
1015 peer
->inbuf
->done
-= len
;
1016 memmove(p
, (char *) p
+ len
, peer
->inbuf
->done
);
1020 peer
->inbuf
->packet
.header
.len
= 0;
1021 peer
->inbuf
->done
= 0;
1024 return peer
->inbuf
->done
;
1027 /* send/buffer OPEN message */
1028 static int bgp_send_open(struct bgp_peer
*peer
)
1030 struct bgp_data_open data
;
1031 uint16_t len
= sizeof(peer
->outbuf
->packet
.header
);
1033 memset(peer
->outbuf
->packet
.header
.marker
, 0xff,
1034 sizeof(peer
->outbuf
->packet
.header
.marker
));
1036 peer
->outbuf
->packet
.header
.type
= BGP_MSG_OPEN
;
1038 data
.version
= BGP_VERSION
;
1039 data
.as
= htons(our_as
);
1040 data
.hold_time
= htons(peer
->hold
);
1041 data
.identifier
= my_address
;
1044 memcpy(peer
->outbuf
->packet
.data
, &data
, BGP_DATA_OPEN_SIZE
);
1045 len
+= BGP_DATA_OPEN_SIZE
;
1047 peer
->outbuf
->packet
.header
.len
= htons(len
);
1048 peer
->outbuf
->done
= 0;
1049 peer
->next_state
= OpenSent
;
1051 return bgp_write(peer
);
1054 /* send/buffer KEEPALIVE message */
1055 static int bgp_send_keepalive(struct bgp_peer
*peer
)
1057 memset(peer
->outbuf
->packet
.header
.marker
, 0xff,
1058 sizeof(peer
->outbuf
->packet
.header
.marker
));
1060 peer
->outbuf
->packet
.header
.type
= BGP_MSG_KEEPALIVE
;
1061 peer
->outbuf
->packet
.header
.len
=
1062 htons(sizeof(peer
->outbuf
->packet
.header
));
1064 peer
->outbuf
->done
= 0;
1065 peer
->next_state
= (peer
->state
== OpenSent
) ? OpenConfirm
: peer
->state
;
1067 return bgp_write(peer
);
1070 /* send/buffer UPDATE message */
1071 static int bgp_send_update(struct bgp_peer
*peer
)
1073 uint16_t unf_len
= 0;
1075 uint16_t len
= sizeof(peer
->outbuf
->packet
.header
);
1076 struct bgp_route_list
*have
= peer
->routes
;
1077 struct bgp_route_list
*want
= peer
->routing
? bgp_routes
: 0;
1078 struct bgp_route_list
*e
= 0;
1079 struct bgp_route_list
*add
= 0;
1082 char *data
= (char *) &peer
->outbuf
->packet
.data
;
1084 /* need leave room for attr_len, bgp_path_attrs and one prefix */
1085 char *max
= (char *) &peer
->outbuf
->packet
.data
1086 + sizeof(peer
->outbuf
->packet
.data
)
1087 - sizeof(attr_len
) - peer
->path_attr_len
- sizeof(struct bgp_ip_prefix
);
1089 /* skip over unf_len */
1090 data
+= sizeof(unf_len
);
1091 len
+= sizeof(unf_len
);
1093 memset(peer
->outbuf
->packet
.header
.marker
, 0xff,
1094 sizeof(peer
->outbuf
->packet
.header
.marker
));
1096 peer
->outbuf
->packet
.header
.type
= BGP_MSG_UPDATE
;
1098 peer
->update_routes
= 0; /* tentatively clear */
1100 /* find differences */
1101 while ((have
|| want
) && data
< (max
- sizeof(struct bgp_ip_prefix
)))
1105 ? memcmp(&have
->dest
, &want
->dest
, sizeof(have
->dest
))
1110 if (s
< 0) /* found one to delete */
1112 struct bgp_route_list
*tmp
= have
;
1115 s
= BGP_IP_PREFIX_SIZE(tmp
->dest
);
1116 memcpy(data
, &tmp
->dest
, s
);
1121 LOG(5, 0, 0, "Withdrawing route %s/%d from BGP peer %s\n",
1122 fmtaddr(tmp
->dest
.prefix
, 0), tmp
->dest
.len
, peer
->name
);
1129 peer
->routes
= have
;
1135 e
= have
; /* stash the last found to relink above */
1139 else if (s
> 0) /* addition reqd. */
1143 peer
->update_routes
= 1; /* only one add per packet */
1157 peer
->update_routes
= 1; /* more to do */
1159 /* anything changed? */
1160 if (!(unf_len
|| add
))
1163 /* go back and insert unf_len */
1164 unf_len
= htons(unf_len
);
1165 memcpy(&peer
->outbuf
->packet
.data
, &unf_len
, sizeof(unf_len
));
1169 if (!(e
= malloc(sizeof(*e
))))
1171 LOG(0, 0, 0, "Can't allocate route for %s/%d (%s)\n",
1172 fmtaddr(add
->dest
.prefix
, 0), add
->dest
.len
, strerror(errno
));
1177 memcpy(e
, add
, sizeof(*e
));
1179 peer
->routes
= bgp_insert_route(peer
->routes
, e
);
1181 attr_len
= htons(peer
->path_attr_len
);
1182 memcpy(data
, &attr_len
, sizeof(attr_len
));
1183 data
+= sizeof(attr_len
);
1184 len
+= sizeof(attr_len
);
1186 memcpy(data
, peer
->path_attrs
, peer
->path_attr_len
);
1187 data
+= peer
->path_attr_len
;
1188 len
+= peer
->path_attr_len
;
1190 s
= BGP_IP_PREFIX_SIZE(add
->dest
);
1191 memcpy(data
, &add
->dest
, s
);
1195 LOG(5, 0, 0, "Advertising route %s/%d to BGP peer %s\n",
1196 fmtaddr(add
->dest
.prefix
, 0), add
->dest
.len
, peer
->name
);
1201 memcpy(data
, &attr_len
, sizeof(attr_len
));
1202 data
+= sizeof(attr_len
);
1203 len
+= sizeof(attr_len
);
1206 peer
->outbuf
->packet
.header
.len
= htons(len
);
1207 peer
->outbuf
->done
= 0;
1209 return bgp_write(peer
);
1212 /* send/buffer NOTIFICATION message */
1213 static int bgp_send_notification(struct bgp_peer
*peer
, uint8_t code
,
1216 struct bgp_data_notification data
;
1219 data
.error_code
= code
;
1220 len
+= sizeof(data
.error_code
);
1222 data
.error_subcode
= subcode
;
1223 len
+= sizeof(data
.error_code
);
1225 memset(peer
->outbuf
->packet
.header
.marker
, 0xff,
1226 sizeof(peer
->outbuf
->packet
.header
.marker
));
1228 peer
->outbuf
->packet
.header
.type
= BGP_MSG_NOTIFICATION
;
1229 peer
->outbuf
->packet
.header
.len
=
1230 htons(sizeof(peer
->outbuf
->packet
.header
) + len
);
1232 memcpy(peer
->outbuf
->packet
.data
, &data
, len
);
1234 peer
->outbuf
->done
= 0;
1235 peer
->next_state
= code
== BGP_ERR_CEASE
? Disabled
: Idle
;
1237 /* we're dying; ignore any pending input */
1238 peer
->inbuf
->packet
.header
.len
= 0;
1239 peer
->inbuf
->done
= 0;
1241 return bgp_write(peer
);