This is bgp_init.c in view mode; [Download] [Up]
/* * $Header: /disk/d/src/devel/gated/dist/src/RCS/bgp_init.c,v 2.1 92/02/24 14:12:25 jch Exp $ */ /*%Copyright%*/ /************************************************************************ * * * GateD, Release 2 * * * * Copyright (c) 1990,1991,1992 by Cornell University * * All rights reserved. * * * * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY * * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT * * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY * * AND FITNESS FOR A PARTICULAR PURPOSE. * * * * Royalty-free licenses to redistribute GateD Release * * 2 in whole or in part may be obtained by writing to: * * * * GateDaemon Project * * Information Technologies/Network Resources * * 143 Caldwell Hall * * Cornell University * * Ithaca, NY 14853-2602 * * * * GateD is based on Kirton's EGP, UC Berkeley's routing * * daemon (routed), and DCN's HELLO routing Protocol. * * Development of Release 2 has been supported by the * * National Science Foundation. * * * * Please forward bug fixes, enhancements and questions to the * * gated mailing list: gated-people@gated.cornell.edu. * * * * Authors: * * * * Jeffrey C Honig <jch@gated.cornell.edu> * * Scott W Brim <swb@gated.cornell.edu> * * * ************************************************************************* * * * Portions of this software may fall under the following * * copyrights: * * * * Copyright (c) 1988 Regents of the University of California. * * All rights reserved. * * * * Redistribution and use in source and binary forms are * * permitted provided that the above copyright notice and * * this paragraph are duplicated in all such forms and that * * any documentation, advertising materials, and other * * materials related to such distribution and use * * acknowledge that the software was developed by the * * University of California, Berkeley. The name of the * * University may not be used to endorse or promote * * products derived from this software without specific * * prior written permission. THIS SOFTWARE IS PROVIDED * * ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, * * INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * * ************************************************************************/ #include "include.h" #ifndef vax11c #include <sys/file.h> #endif /* vax11c */ #include "bgp.h" #ifdef PROTO_BGP int doing_bgp = FALSE; /* Is BGP active? */ pref_t bgp_preference = RTPREF_BGP; /* Preference for BGP routes */ u_short bgp_port; /* Well known BGP port */ metric_t bgp_default_metric = bgpMetricInfinity; /* Default metric if no announce clauses specified */ bgpPeer *bgp_peers; /* Linked list of BGP peers */ int bgp_n_peers; /* Number of BGP peers */ bgpPdu *bgp_send_buffer; /* Send buffer */ adv_entry *bgp_accept_list = NULL; /* List of BGP advise entries */ adv_entry *bgp_propagate_list = NULL; /* List of BGP propagate entries */ static timer *bgp_flash_timer = (timer *) 0; static time_t bgp_next_flash = (time_t) 0; int notifyLengths[BGPERRCD_MAX + 1] = { 0, BGPERRLEN_LINKTYPE, BGPERRLEN_AUTHCODE, BGPERRLEN_AUTHFAIL, BGPERRLEN_UPDATE, BGPERRLEN_SYNC, BGPERRLEN_MSGLEN, BGPERRLEN_MSGTYPE, BGPERRLEN_VERSION, BGPERRLEN_OPENAS }; bits bgpFlags[] = { {BGPF_HEADER, "Header"}, {BGPF_DELETE, "Delete"}, {BGPF_WAIT, "Wait"}, {BGPF_GENDEFAULT, "GenDefault"}, {0} }; bits bgpOptions[] = { {BGPO_METRICOUT, "MetricOut"}, {BGPO_ASIN, "AsIn"}, {BGPO_ASOUT, "AsOut"}, {BGPO_NOGENDEFAULT, "NoGenDefault"}, {BGPO_GATEWAY, "Gateway"}, {BGPO_PREFERENCE, "Preference"}, {BGPO_INTERFACE, "Interface"}, {BGPO_LINKTYPE, "LinkType"}, {BGPO_HOLDTIME, "HoldTime"}, {0} }; bits bgpStates[] = { {0, "Invalid"}, {BGPSTATE_IDLE, "Idle"}, {BGPSTATE_ACTIVE, "Active"}, {BGPSTATE_CONNECT, "Connect"}, {BGPSTATE_OPENSENT, "OpenSent"}, {BGPSTATE_OPENCONFIRM, "Confirm"}, {BGPSTATE_ESTABLISHED, "Established"}, {0} }; bits bgpEvents[] = { {0, "Invalid"}, {BGPEVENT_START, "Start"}, {BGPEVENT_OPEN, "Open"}, {BGPEVENT_CLOSED, "Closed"}, {BGPEVENT_OPENFAIL, "OpenFail"}, {BGPEVENT_RECVOPEN, "RecvOpen"}, {BGPEVENT_RECVCONFIRM, "RecvConfirm"}, {BGPEVENT_RECVKEEPALIVE, "RecvKeepAlive"}, {BGPEVENT_RECVUPDATE, "RecvUpdate"}, {BGPEVENT_RECVNOTIFY, "RecvNotify"}, {BGPEVENT_HOLDTIME, "HoldTime"}, {BGPEVENT_KEEPALIVE, "KeepAlive"}, {BGPEVENT_CEASE, "Cease"}, {BGPEVENT_STOP, "Stop"}, {0} }; bits bgpAsDirs[] = { {0, "Invalid"}, {asDirUp, "Up"}, {asDirDown, "Down"}, {asDirHorizontal, "Horizontal"}, {asDirEgp, "Egp"}, {asDirIncomplete, "Incomplete"}, {0} }; bits bgpOpenType[] = { {openLinkInternal, "Internal"}, {openLinkUp, "Up"}, {openLinkDown, "Down"}, {openLinkHorizontal, "Horizontal"}, {0} }; bits bgpPduType[] = { {0, "Invalid"}, {bgpPduOpen, "Open"}, {bgpPduUpdate, "Update"}, {bgpPduNotify, "Notify"}, {bgpPduKeepAlive, "KeepAlive"}, {bgpPduOpenConfirm, "OpenConfirm"}, {0} }; bits bgpErrors[] = { {0, NULL}, {BGPERRCD_LINKTYPE, "link type error in open"}, {BGPERRCD_AUTHCODE, "unknown authentication code"}, {BGPERRCD_AUTHFAIL, "authentication failure"}, {BGPERRCD_UPDATE, "update error"}, {BGPERRCD_SYNC, "connection out of sync"}, {BGPERRCD_MSGLEN, "invalid message length"}, {BGPERRCD_MSGTYPE, "invalid message type"}, {BGPERRCD_VERSION, "invalid version number"}, {BGPERRCD_OPENAS, "invalid AS field in Open"}, {BGPERRCD_CEASE, "BGP neighbor Cease"}, }; bits bgpUpdateErrors[] = { {0, NULL}, {BGPUPDERR_ASCOUNT, "Invalid AS count"}, {BGPUPDERR_DIRECTION, "Invalid Direction code"}, {BGPUPDERR_AS, "Invalid AS"}, {BGPUPDERR_ORDER, "Terminal Direction in middle of path"}, {BGPUPDERR_LOOP, "Routing loop detected"}, {BGPUPDERR_GATEWAY, "Invalid Gateway"}, {BGPUPDERR_NETCOUNT, "Invalid Network count"}, {BGPUPDERR_NETWORK, "Invalid Network"} }; /* We have a socket, create the task */ void bgp_session_init(bnp, bgp_socket) bgpPeer *bnp; int bgp_socket; { struct sockaddr_in addr; int addrlen = socksize(&addr); if (getpeername(bgp_socket, (struct sockaddr *) & addr, &addrlen) < 0) { trace(TR_ALL, LOG_ERR, "bgp_session_init: getpeername(%d): %m", bgp_socket); } else { IF_BGPPROTO trace(TR_BGP, 0, "bgp_session_init: peer %s socket %d is connected to %A", bnp->bgp_name, bgp_socket, &addr); } bnp->bgp_task->task_recv = bgp_read; task_set_socket(bnp->bgp_task, bgp_socket); if (task_set_option(bnp->bgp_task, TASKOPTION_NONBLOCKING, (caddr_t) TRUE) < 0) { quit(errno); } if (task_set_option(bnp->bgp_task, TASKOPTION_RECVBUF, (caddr_t) (32 * 1024)) < 0) { quit(errno); } if (task_set_option(bnp->bgp_task, TASKOPTION_SENDBUF, (caddr_t) (32 * 1024)) < 0) { quit(errno); } if (if_withdst((sockaddr_un *) & bnp->bgp_addr) && task_set_option(bnp->bgp_task, TASKOPTION_DONTROUTE, (caddr_t) TRUE) < 0) { quit(errno); } (void) timer_create(bnp->bgp_task, BGPTIMER_KEEPALIVE, "KeepAlive", 0, (time_t) 0, bgp_event_KeepAlive); } /* Close the socket and delete the task */ void bgp_session_finit(bnp, quick) bgpPeer *bnp; int quick; { IF_BGPPROTO trace(TR_BGP, 0, "bgp_session_finit: peer %s", bnp->bgp_name); if (!quick) { if (task_set_option(bnp->bgp_task, TASKOPTION_LINGER, (caddr_t) BGP_CLOSE_TIMER) < 0) { quit(errno); } } if (close(bnp->bgp_task->task_socket) < 0) { trace(TR_ALL, LOG_ERR, "bgp_session_finit: close: %m"); } task_reset_socket(bnp->bgp_task); timer_delete(bnp->bgp_task->task_timer[BGPTIMER_KEEPALIVE]); } /* * Clean up when connect has completed */ void bgp_connect_finit(bnp) bgpPeer *bnp; { task_reset_socket(bnp->bgp_task); timer_delete(bnp->bgp_task->task_timer[BGPTIMER_CONNECT]); } /* * Connect has completed or failed */ void bgp_connect_complete(tp) task *tp; { int length; int bgp_socket = tp->task_socket; struct sockaddr_in addr; bgpPeer *bnp = (bgpPeer *) tp->task_data; tracef("bgp_connect_complete: peer %s state %s ", bnp->bgp_name, trace_state(bgpStates, bnp->bgp_state)); length = socksize(&addr); if (getpeername(tp->task_socket, (struct sockaddr *) & addr, &length) < 0) { trace(TR_EXT, 0, "Connection error: %m"); if (close(bnp->bgp_task->task_socket) < 0) { trace(TR_ALL, LOG_ERR, "bgp_connect_complete: close(%d): %m", bnp->bgp_task->task_socket); quit(errno); } bgp_connect_finit(bnp); bgp_event_OpenFail(bnp); } else { trace(TR_BGP, 0, "Connection established with %A", &addr); bgp_connect_finit(bnp); bgp_session_init(bnp, bgp_socket); bgp_event_Open(bnp); } } void bgp_connect_start(bnp) bgpPeer *bnp; { int bgp_socket; struct sockaddr_in addr; IF_BGPPROTO trace(TR_BGP, 0, "bgp_connect_start: peer %s", bnp->bgp_name); if ((bgp_socket = task_get_socket(AF_INET, SOCK_STREAM, 0)) < 0) { quit(errno); } bnp->bgp_task->task_flags |= TASKF_CONNECT; bnp->bgp_task->task_connect = bgp_connect_complete; task_set_socket(bnp->bgp_task, bgp_socket); if (task_set_option(bnp->bgp_task, TASKOPTION_NONBLOCKING, (caddr_t) TRUE) < 0) { quit(errno); } if (task_set_option(bnp->bgp_task, TASKOPTION_REUSEADDR, (caddr_t) TRUE) < 0) { quit(errno); } /* There are problems with the linger_close if you bind the local */ /* address */ addr = bnp->bgp_interface->int_addr.in; /* struct copy */ #ifdef notdef addr.sin_port = bgp_port; #else addr.sin_port = 0; /* leave port wildcarded, should work okay */ #endif /* notdef */ if (bind(bgp_socket, &addr, socksize(&addr)) < 0) { trace(TR_ALL, LOG_ERR, "bgp_connect_start: bind %A: %m", &addr); quit(errno); } if (connect(bgp_socket, (struct sockaddr *) & bnp->bgp_addr, socksize(&bnp->bgp_addr)) < 0) { int log_level = LOG_WARNING; int trace_level = TR_BGP | TR_TASK; switch (errno) { case EINPROGRESS: log_level = 0; if (!(trace_flags & TR_PROTOCOL)) { trace_level = 0; } /* Fall Thru */ case ENETDOWN: case ENETUNREACH: case EHOSTDOWN: case EHOSTUNREACH: case EADDRINUSE: trace(trace_level, log_level, "bgp_connect_start: connect %A: %m", &bnp->bgp_addr); timer_set(bnp->bgp_task->task_timer[BGPTIMER_CONNECT], (time_t) BGP_WAIT_RETRY); break; default: trace(TR_ALL, LOG_ERR, "bgp_connect_start: connect %A: %m", &bnp->bgp_addr); quit(errno); } } else { IF_BGPPROTO trace(TR_BGP, 0, "bgp_connect_start: connect %A succeded", &bnp->bgp_addr); bgp_connect_complete(bnp->bgp_task); } } /* * Close the current socket and start a new connect by calling bgp_connect_start() */ /*ARGSUSED*/ void bgp_connect_job(tip, interval) timer *tip; time_t interval; { task *tp = tip->timer_task; bgpPeer *bnp = (bgpPeer *) tp->task_data; IF_BGPPROTO trace(TR_BGP, 0, "bgp_connect_job: %s", timer_name(tip)); if (close(tp->task_socket) < 0) { trace(TR_ALL, LOG_ERR, "bgp_connect_job: close(%d): %m", tp->task_socket); quit(errno); } task_reset_socket(tp); bgp_connect_start(bnp); } /* * Initialize for connecting to peer. */ void bgp_connect_init(bnp) bgpPeer *bnp; { (void) timer_create(bnp->bgp_task, BGPTIMER_CONNECT, "Connect", 0, (time_t) 0, bgp_connect_job); bgp_connect_start(bnp); } /*ARGSUSED*/ void bgp_do_flash(tp, interval) task *tp; time_t interval; { bgpPeer *bnp; trace(TR_TASK, 0, "bgp_do_flash: Doing flash update for BGP"); BGP_LIST(bnp) { if (bnp->bgp_state == BGPSTATE_ESTABLISHED) { bgp_send_update(bnp, TRUE); } } BGP_LISTEND; bgp_flash_timer = (timer *) 0; bgp_next_flash = (time_t) BGP_FLASH_INTERVAL + time_sec; trace(TR_TASK, 0, "bgp_do_flash: Flash update done, none before %T", bgp_next_flash); } /* * Check to see if a flash update packet is allowed and send or schedule it */ void bgp_flash(tp) task *tp; { if (time_sec >= bgp_next_flash) { /* A flash update can be sent now, do it */ bgp_do_flash(tp, (time_t) 0); } else if (!bgp_flash_timer) { /* A flash update can't be sent and one is not yet scheduled */ bgp_flash_timer = timer_create(tp, 0, "Flash", TIMERF_DELETE | TIMERF_ABSOLUTE, bgp_next_flash - time_sec, bgp_do_flash); } } /* * Process an incoming connection */ void bgp_listen_accept(tp) task *tp; { int bgp_socket; int addrlen; struct sockaddr_in addr; bgpPeer *bnp; addrlen = socksize(&addr); if ((bgp_socket = accept(tp->task_socket, (struct sockaddr *) & addr, &addrlen)) < 0) { trace(TR_ALL, LOG_ERR, "bgp_listen_accept: accept(%d): %m", tp->task_socket); quit(errno); } if (addrlen != socksize(&addr)) { trace(TR_ALL, LOG_ERR, "bgp_listen_accept: incorrect address length, ignoring connection"); (void) close(bgp_socket); return; } if (addr.sin_family != AF_INET) { trace(TR_ALL, LOG_ERR, "bgp_listen_accept: ignoring non-inet connection request"); (void) close(bgp_socket); return; } BGP_LIST(bnp) { if (equal_in(bnp->bgp_addr.sin_addr, addr.sin_addr)) { switch (bnp->bgp_state) { case BGPSTATE_IDLE: case BGPSTATE_OPENSENT: case BGPSTATE_OPENCONFIRM: case BGPSTATE_ESTABLISHED: trace(TR_EXT, LOG_NOTICE, "bgp_listen_accept: peer %s state %s rejecting connection", bnp->bgp_name, trace_state(bgpStates, bnp->bgp_state)); (void) close(bgp_socket); break; case BGPSTATE_CONNECT: /* Prevent the active connect from succeding */ if (close(bnp->bgp_task->task_socket) < 0) { trace(TR_ALL, LOG_ERR, "bgp_connect_complete: close(%d): %m", bnp->bgp_task->task_socket); quit(errno); } bgp_connect_finit(bnp); case BGPSTATE_ACTIVE: bgp_session_init(bnp, bgp_socket); bgp_event_Open(bnp); } break; } } BGP_LISTEND; if (!bnp) { trace(TR_EXT, LOG_NOTICE, "bgp_listen_accept: rejecting connection from unknown peer %A", &addr); (void) close(bgp_socket); } } /* * Cleanup before re-parse */ /*ARGSUSED*/ static void bgp_cleanup(tp) task *tp; { bgp_default_metric = bgpMetricInfinity; bgp_preference = RTPREF_BGP; adv_free_list(bgp_accept_list); bgp_accept_list = (adv_entry *) 0; adv_free_list(bgp_propagate_list); bgp_propagate_list = (adv_entry *) 0; } /* * Setup to catch incoming connections */ void bgp_listen_init() { int bgp_socket; static task *bgp_task = (task *) 0; struct sockaddr_in addr; int on = 1; if (doing_bgp && !bgp_task) { sockclear_in(&addr); addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = bgp_port; if ((bgp_socket = task_get_socket(AF_INET, SOCK_STREAM, 0)) < 0) { quit(errno); } if (setsockopt(bgp_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(int)) < 0) { trace(TR_ALL, LOG_ERR, "bgp_listen_init: setsockopt: %m"); quit(errno); } if (bind(bgp_socket, (struct sockaddr *) & addr, socksize(&addr)) < 0) { trace(TR_ALL, LOG_ERR, "bgp_listen_init: bind %A: %m", &addr); quit(errno); } if (listen(bgp_socket, 5) < 0) { trace(TR_ALL, LOG_ERR, "bgp_listen_init: listen: %m"); quit(errno); } bgp_task = task_alloc("BGP_listen"); bgp_task->task_flags = TASKF_ACCEPT; sockcopy(&addr, &bgp_task->task_addr); bgp_task->task_socket = bgp_socket; bgp_task->task_rtproto = RTPROTO_BGP; bgp_task->task_accept = bgp_listen_accept; bgp_task->task_cleanup = bgp_cleanup; bgp_task->task_flash = bgp_flash; /* Flash updates handled here */ bgp_task->task_dump = bgp_dump; if (!task_create(bgp_task, 0)) { quit(EINVAL); } } else if (!doing_bgp && bgp_task) { task_delete(bgp_task); bgp_task = (task *) 0; } } /* * Receive from socket */ int bgp_recv(tp) task *tp; { int count, length; bgpPeer *bnp = (bgpPeer *) tp->task_data; length = bnp->bgp_length - bnp->bgp_length_accumulated; errno = 0; count = recv(tp->task_socket, bnp->bgp_readpointer, length, 0); if (count > 0) { bnp->bgp_length_accumulated += count; bnp->bgp_readpointer += count; trace(TR_TASK, 0, "bgp_recv: peer %s received %d bytes (%d of %d so far)", bnp->bgp_name, count, bnp->bgp_length_accumulated, bnp->bgp_length); } else if (count < 0) { int log_level = LOG_WARNING; int trace_level = TR_BGP | TR_TASK; switch (errno) { case EWOULDBLOCK: log_level = 0; /* Fall Thru */ case ENETDOWN: case ENETUNREACH: case EHOSTDOWN: case EHOSTUNREACH: count = 0; break; default: trace_level = TR_ALL; log_level = LOG_ERR; } trace(trace_level, log_level, "bgp_recv: peer %s recv: %m", bnp->bgp_name); } else { trace(TR_EXT, LOG_ERR, "bgp_recv: peer %s recv: End of File (Connection Closed)", bnp->bgp_name); /* Count is zero - end of file */ count = -1; } return (count); } /* * Delete a peer */ static void bgp_delete(bnp) bgpPeer *bnp; { if (bnp == bgp_peers) { bgp_peers = bnp->bgp_next; } else { bgpPeer *bnp2; BGP_LIST(bnp2) { if (bnp2->bgp_next == bnp) { bnp2->bgp_next = bnp->bgp_next; break; } } BGP_LISTEND; } bgp_n_peers--; (void) free((caddr_t) bnp); } /* * Clean up and shut down */ static void bgp_terminate(tp) task *tp; { bgpPeer *bnp = (bgpPeer *) tp->task_data; bgp_event_Stop(bnp); timer_delete(tp->task_timer[BGPTIMER_HOLDTIME]); task_delete(tp); bgp_delete(bnp); } /* * Cleanup for a peer */ static void bgp_peer_cleanup(tp) task *tp; { bgpPeer *bnp = (bgpPeer *) tp->task_data; bnp->bgp_flags |= BGPF_DELETE; adv_cleanup((int *) 0, (int *) 0, (gw_entry *) 0, &bnp->bgp_accept, &bnp->bgp_propagate, (adv_entry ***) 0, (adv_entry ***) 0); } /* * Reinit a peer */ static void bgp_peer_reinit(tp) task *tp; { bgpPeer *bnp = (bgpPeer *) tp->task_data; if (!doing_bgp || (bnp->bgp_flags & BGPF_DELETE)) { bnp->bgp_flags |= BGPF_DELETE; bgp_terminate(tp); } else { /* Issue a start event for Idle peers */ switch (bnp->bgp_state) { case BGPSTATE_IDLE: case BGPSTATE_ACTIVE: bgp_event_Start(bnp); break; case BGPSTATE_CONNECT: case BGPSTATE_OPENSENT: case BGPSTATE_OPENCONFIRM: case BGPSTATE_ESTABLISHED: break; } /* Locate our new policy */ if (bnp->bgp_asin) { /* If the AS isn't valid now, the correct policy will be located */ /* when the AS becomes valid */ bnp->bgp_accept = control_exterior_locate(bgp_accept_list, bnp->bgp_asin); bnp->bgp_propagate = control_exterior_locate(bgp_propagate_list, bnp->bgp_asin); } } } void bgp_init() { bgpPeer *bnp; if_entry *ifp; struct servent *sp; struct sockaddr_in addr; if (doing_bgp) { if ((sp = getservbyname("bgp", "tcp")) == NULL) { trace(TR_ALL, LOG_ERR, "bgp_init: getservbyname(bgp, tcp): %m - using port %d", IPPROTO_BGP); bgp_port = htons(IPPROTO_BGP); } else { bgp_port = sp->s_port; } sockclear_in(&addr); addr.sin_port = bgp_port; BGP_LIST(bnp) { if (!bnp->bgp_task) { if (!(bnp->bgp_options & BGPO_INTERFACE)) { if (!(bnp->bgp_options & BGPO_GATEWAY)) { sockcopy(&bnp->bgp_addr, &addr); } else { addr = bnp->bgp_gateway; /* struct copy */ } ifp = if_withdst((sockaddr_un *) & addr); if (ifp) { bnp->bgp_interface = ifp; } else if (!(bnp->bgp_options & BGPO_GATEWAY)) { /* If we only have one interface, use it */ ifp = NULL; if (n_interfaces == 1) { IF_LIST(ifp) { if (!(ifp->int_state & IFS_LOOPBACK)) { bnp->bgp_interface = ifp; break; } } IF_LISTEND(ifp) ; } if (!ifp) { trace(TR_INT, LOG_ERR, "bgp_init: Can't determine interface for peer %s", bnp->bgp_name); quit(EDESTADDRREQ); } } else { trace(TR_INT, LOG_ERR, "bgp_init: no direct net to gateway %s", bnp->bgp_name); quit(EDESTADDRREQ); } } /* If AsOut was not specified, default to my_system */ if (!(bnp->bgp_options & BGPO_ASOUT)) { bnp->bgp_asout = my_system; } if (bnp->bgp_options & BGPO_ASIN) { bnp->bgp_accept = control_exterior_locate(bgp_accept_list, bnp->bgp_asin); bnp->bgp_propagate = control_exterior_locate(bgp_propagate_list, bnp->bgp_asin); } /* If HoldTime is not specified, assume default */ if (!(bnp->bgp_options & BGPO_HOLDTIME)) { bnp->bgp_holdtime_out = BGP_KEEP_ALIVE; } /* If link type is not specifed, Horizontal is assumed if */ /* the incoming and outgoing AS are different. If they */ /* are the same, Internal is the default. */ if (!(bnp->bgp_options & BGPO_LINKTYPE)) { if ((bnp->bgp_options & BGPO_ASIN) && (bnp->bgp_asin == bnp->bgp_asout)) { bnp->bgp_linktype = openLinkInternal; } else { bnp->bgp_linktype = openLinkHorizontal; } trace(TR_BGP, LOG_INFO, "bgp_init: peer %s - link type not specified, assuming %s", bnp->bgp_name, trace_state(bgpOpenType, bnp->bgp_linktype)); } if (!(bnp->bgp_options & BGPO_PREFERENCE)) { bnp->bgp_preference = bgp_preference; } /* If the link type is internal, the protocol is IBGP and */ /* the default preference is different. The protocol is */ /* not set here though, it is set when the task is */ /* allocated. */ if (bnp->bgp_linktype == openLinkInternal) { if (!(bnp->bgp_options & BGPO_PREFERENCE)) { bnp->bgp_preference = RTPREF_IBGP; } } /* Initially in the Idle state */ bnp->bgp_state = BGPSTATE_IDLE; /* Create the abort timer task */ bnp->bgp_task = task_alloc("BGP"); bnp->bgp_addr.sin_port = bgp_port; bnp->bgp_task->task_addr.in = bnp->bgp_addr; /* struct copy */ bnp->bgp_task->task_rtproto = RTPROTO_BGP; bnp->bgp_task->task_terminate = bgp_terminate; bnp->bgp_task->task_cleanup = bgp_peer_cleanup; bnp->bgp_task->task_reinit = bgp_peer_reinit; bnp->bgp_task->task_data = (caddr_t) bnp; if (!task_create(bnp->bgp_task, 0)) { quit(EINVAL); } /* The hold timer is used to start a connect after a few seconds */ (void) timer_create(bnp->bgp_task, BGPTIMER_HOLDTIME, "Holdtime", TIMERF_ABSOLUTE, (time_t) BGP_IDLE_INIT, bgp_event_Holdtime); } } BGP_LISTEND; if (!test_flag) { /* Listen for incoming connections */ bgp_listen_init(); if ((bgp_send_buffer = (bgpPdu *) malloc(BGPMAXPACKETSIZE)) == NULL) { trace(TR_ALL, LOG_ERR, "bgp_init: malloc send buffer: %m"); } } } else { /* BGP is not running, but it may have been. Delete all peers that do not have tasks */ BGP_LIST(bnp) { if (!bnp->bgp_task) { bgp_delete(bnp); } } BGP_LISTEND; bgp_cleanup((task *) 0); bgp_listen_init(); } } #endif /* PROTO_BGP */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.