?? bgp_output.c
字號:
/* * Copyright (C) 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include "include.h"#include "bgp.h"#include "router.h"#include "task.h"#include "rt_table.h"#include "aspath.h"#include "bgp_var.h"#include "in6.h"#include "ripng.h"#define BGP_LOG_SEND(type, len) IFLOG(LOG_BGPOUTPUT) \ do { syslog(LOG_DEBUG,\ "BGP+ SEND %s+%d -> %s+%d",\ ip6str2(&bnp->rp_myaddr),\ ntohs(bnp->rp_myaddr.sin6_port),\ bgp_peerstr(bnp),\ ntohs(bnp->rp_addr.sin6_port));\ syslog(LOG_DEBUG,\ "BGP+ SEND message type %d (%s) length %d",\ (type), bgp_msgstr[(type)], (len));\ } while (0)/* * bgp_send_open() */intbgp_send_open(struct rpcb *bnp){ int i; u_int16_t netasnum, nethldtim; struct bgphdr *bh; task *tsk; extern byte outpkt[]; extern char *bgp_msgstr[]; extern u_int16_t my_as_number, bgpHoldtime; extern u_int32_t bgpIdentifier; extern fd_set fdmask; extern task *taskhead; memset(outpkt, 0, BGPMAXPACKETSIZE); bh = (struct bgphdr *)outpkt; /** fixed-size header **/ /* Marker (16-octet to be all 1) */ memset(bh->bh_marker, 0xff, BGP_HEADER_MARKER_LEN); /* Type (1-octet) */ bh->bh_type = BGP_OPEN; i = BGP_HEADER_LEN; /*** Open Message Format ***/ /* Version (1-octet) */ outpkt[i++] = BGP_VERSION_4; /* My Autonomous System (2-octet) */ netasnum = htons(my_as_number); memcpy(&outpkt[i], &netasnum, 2); i += 2; /* Hold Time (2-octet) */ nethldtim = htons(bgpHoldtime); memcpy(&outpkt[i], &nethldtim, 2); i += 2; /* BGP Identifier (4-octet) */ memcpy(&outpkt[i], &bgpIdentifier, 4); /* net-order (jinmei) */ i += 4; /* Optional Parameters (length is specified by "Opt Parm Len") */ /* Opt Parm Len (1-octet) */ i++; /* NO authentification is supported. */ /* again, total msg Length (2-octet) field in the header */ bh->bh_length = htons(i); /**** send OPEN message ****/ if ((write(bnp->rp_socket, outpkt, i)) != i) { syslog(LOG_ERR, "<bgp_send_open>: write failed"); bgp_cease(bnp); return NULL; } bgp_update_stat(bnp, BGPS_OPENSENT); BGP_LOG_SEND(BGP_OPEN, i); /*** OpenSent ***/ bnp->rp_state = BGPSTATE_OPENSENT; IFLOG(LOG_BGPSTATE) syslog(LOG_DEBUG, "<%s>: BGP state shift[%s] peer: %s", __FUNCTION__, bgp_statestr[bnp->rp_state], bgp_peerstr(bnp)); FD_SET(bnp->rp_socket, &fdmask); /* open-sent Socket (to the global) */ MALLOC(tsk, task); if (taskhead) { insque(tsk, taskhead); /* will be sorted later by task_timer_update() */ } else { tsk->tsk_next = tsk; tsk->tsk_prev = tsk; taskhead = tsk; } tsk->tsk_bgp = bnp; tsk->tsk_timename = BGP_HOLD_TIMER; bnp->rp_hold_timer = tsk; /* was originally set to a large value */ tsk->tsk_timefull.tv_sec = bgpHoldtime; tsk->tsk_timefull.tv_usec = 0; /* Hold timer ON. */ task_timer_update(tsk); return NULL;}/* * bgp_send_notification() */intbgp_send_notification(bnp, errcode, subcode, len, data) struct rpcb *bnp; byte errcode; byte subcode; int len; byte *data;{ int i; /* bytes to send */ int wlen; struct bgphdr *bh; extern byte outpkt[]; extern char *bgp_errstr[]; extern char *bgp_hdrerrstr[]; extern char *bgp_opnerrstr[]; extern char *bgp_upderrstr[]; extern char *bgp_msgstr[]; memset(outpkt, 0, BGPMAXPACKETSIZE); bh = (struct bgphdr *)outpkt; /** fixed-size header **/ /* Marker (16-octet to be all 1) */ memset(bh->bh_marker, 0xff, BGP_HEADER_MARKER_LEN); /* Type (1-octet) */ bh->bh_type = BGP_NOTIFY; i = BGP_HEADER_LEN; /*** NOTIFICATION Message Format ***/ /* Error Code, Sub Code */ outpkt[i++] = errcode; outpkt[i++] = subcode; memcpy(&outpkt[i], data, len); i += len; /* again, total msg Length (2-octet) field in the header */ bh->bh_length = htons(i); /**** send NOTIFICATION message ****/ if ((wlen = write(bnp->rp_socket, outpkt, i)) != i) syslog(LOG_ERR, "%s: write to %s (%s AS %d) failed: %s", __FUNCTION__, bgp_peerstr(bnp), ((bnp->rp_mode & BGPO_IGP) ? "Internal" : "External"), (int)bnp->rp_as, strerror(errno)); else syslog(LOG_NOTICE, "NOTIFICATION sent to %s (%s AS %d): code %d (%s) data %s", bgp_peerstr(bnp), ((bnp->rp_mode & BGPO_IGP) ? "Internal" : "External"), (int)bnp->rp_as, errcode, bgp_errstr[errcode], bgp_errdatastr(data, len)); switch (errcode) { /* code */ case BGP_ERR_HEADER: if (subcode <= BGP_ERRHDR_TYPE) syslog(LOG_NOTICE, "\t subcode (%d) %s", subcode, bgp_hdrerrstr[subcode]); break; case BGP_ERR_OPEN: if (subcode <= BGP_ERROPN_BADHOLDTIME) syslog(LOG_NOTICE, "\t subcode (%d) %s", subcode, bgp_opnerrstr[subcode]); break; case BGP_ERR_UPDATE: if (subcode <= BGP_ERRUPD_ASPATH) syslog(LOG_NOTICE, "\t subcode (%d) %s", subcode, bgp_upderrstr[subcode]); break; default: break; } bgp_update_stat(bnp, BGPS_NOTIFYSENT); BGP_LOG_SEND(BGP_NOTIFY, i); bnp->rp_state = BGPSTATE_IDLE; IFLOG(LOG_BGPSTATE) syslog(LOG_NOTICE, "<%s>: BGP state shift[%s] peer: %s", __FUNCTION__, bgp_statestr[bnp->rp_state], bgp_peerstr(bnp)); return NULL; /* End of bgp_send_notification() */}/* * bgp_send_keepalive() */intbgp_send_keepalive(struct rpcb *bnp){ struct bgphdr *bh; extern byte outpkt[]; extern char *bgp_msgstr[]; memset(outpkt, 0, BGPMAXPACKETSIZE); bh = (struct bgphdr *)outpkt; /** fixed-size header **/ /* Marker (16-octet to be all 1) */ memset(bh->bh_marker, 0xff, BGP_HEADER_MARKER_LEN); /* Type (1-octet) */ bh->bh_type = BGP_KEEPALIVE; /* again, total msg Length (2-octet) field in the header */ bh->bh_length = htons(BGP_HEADER_LEN);#if 0 /* * XXX: we have to introduce a jitter here, but usleep * is not appropriate... */ usleep(BGP_ADV_DELAY); /* <---- important !! */#endif /**** send KEEPALIVE message ****/ if ((write(bnp->rp_socket, outpkt, BGP_HEADER_LEN)) != BGP_HEADER_LEN) { dperror("<bgp_send_keepalive>: write failed"); syslog(LOG_ERR, "<bgp_send_keepalive>: write failed"); bgp_cease(bnp); return NULL; } bgp_update_stat(bnp, BGPS_KEEPALIVESENT); BGP_LOG_SEND(BGP_KEEPALIVE, BGP_HEADER_LEN); /* KeepAlive Timer ON. */ task_timer_update(bnp->rp_keepalive_timer); return NULL;}#define BGP_LOG_ATTR IFLOG(LOG_BGPOUTPUT) { syslog(LOG_DEBUG,\ "BGP+ SEND flags 0x%x code %s(%d):\\",\ outpkt[i-2],\ pa_typestr[outpkt[i-1]],\ outpkt[i-1]); }/* * * bgp_send_update() * RETURN VALUES: last rte */struct rt_entry *bgp_send_update(bnp, rte, headrte) struct rpcb *bnp; struct rt_entry *rte, *headrte; /* is ring, and, have the same aspath. */{ struct bgphdr *bh; int i, topa_p, mp_p, lennh_p, nlri_p; /* cursor */ u_int8_t origin; int aspathlen; struct aspath *asp; u_int16_t netafi; u_int16_t netmpnlrilen, nettpalen, netaspathlen; u_int32_t netorigid = 0; u_int16_t netnlrilen; struct rtproto *rtp; /* origin protocol of rte */ struct rtproto artp; struct rt_entry *rt; /* return value. the last RTE which advd. */ struct rt_entry *agg; /* (1998/06/12) */ struct optatr *optatr; extern byte outpkt[]; extern u_int16_t my_as_number; extern byte IamRR; extern u_int32_t bgpIdentifier; extern char *bgp_msgstr[], *bgp_statestr[]; extern char *pa_typestr[], *origin_str[]; IFLOG(LOG_BGPOUTPUT) syslog(LOG_DEBUG, "<%s>: invoked. AS=%u, ID=%s, state=%s", /* iw97 */ __FUNCTION__, bnp->rp_as, inet_ntoa(*(struct in_addr *)&bnp->rp_id), bgp_statestr[bnp->rp_state]); if (bnp->rp_state != BGPSTATE_ESTABLISHED) fatalx("<bgp_send_update>: internal error: invalid state"); if (rte == NULL) { /* argument */ IFLOG(LOG_BGPOUTPUT) syslog(LOG_DEBUG, "<%s>: Nothing to be sent.", __FUNCTION__); return NULL; } memset(&artp, 0, sizeof(artp)); artp.rtp_type = RTPROTO_BGP; artp.rtp_bgp = bnp; memset(outpkt, 0, BGPMAXPACKETSIZE); rt = NULL; bh = (struct bgphdr *)outpkt; /*** fixed-size header ***/ /* Marker (16 octets to be all 1) */ memset(bh->bh_marker, 0xff, BGP_HEADER_MARKER_LEN); /* Type (1 octet) */ bh->bh_type = BGP_UPDATE; i = BGP_HEADER_LEN; /*** Update Message Format ***/ /* Unfeasible Routes Length (2 octets) */ i += 2; /* IPv6 (BGP4+) doesn't send this. */ /* Total Path Attribute Length (2 octets) (0...65535) */ i += 2; topa_p = i; rtp = &rte->rt_proto; /* identical to each RTE */ /* * Path Attributes */ /** ORIGIN (Type Code 1) **/ outpkt[i++] |= PA_FLAG_TRANS; /* well-known mandatory */ outpkt[i++] = PA4_TYPE_ORIGIN; /* T */ BGP_LOG_ATTR; outpkt[i++] = PA4_LEN_ORIGIN; /* L */ /* data len */ /* V */ switch (rtp->rtp_type) {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -