⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spfifc.c

📁 BCAST Implementation for NS2
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *   OSPFD routing daemon *   Copyright (C) 1998 by John T. Moy *    *   This program is free software; you can redistribute it and/or *   modify it under the terms of the GNU General Public License *   as published by the Free Software Foundation; either version 2 *   of the License, or (at your option) any later version. *    *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. *    *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* Routines dealing with OSPF interfaces. * Does not include the Interface state machine, which is * contained in file ifcfsm.C. */#include "ospfinc.h"#include "ifcfsm.h"#include "nbrfsm.h"#include "system.h"#include "contrib/global.h"#include "openssl/md5.h"/* Add, modify, or delete an OSPF interface. */void OSPF::cfgIfc(CfgIfc *m, int status){    SpfIfc *ip;    bool restart=false;    bool nbr_change=false;    bool new_lsa=false;    bool new_net_lsa=false;    SpfArea *new_ap;    printf("----\nOSPF::cfgIfc\n");    ip = find_ifc(m->address, m->phyint);    // If delete, free to heap    if (status == DELETE_ITEM) {	if (ip)	    delete ip;	return;    }    // Add or modify an interface    // Type of interface (NBMA, etc.)    if (ip && ip->type() != m->IfType) {	delete ip;	ip = 0;    }    // Allocate new interface, if necessary    if (!ip) {	switch (m->IfType) {	  case IFT_BROADCAST:	    ip = new BroadcastIfc(m->address, m->phyint);	    break;	  case IFT_PP:	    ip = new PPIfc(m->address, m->phyint);	    break;	  case IFT_NBMA:	    ip = new NBMAIfc(m->address, m->phyint);	    break;	  case IFT_P2MP:	    ip = new P2mPIfc(m->address, m->phyint);	    break;	  case IFT_VL:	  default:	    return;	}	ip->if_mask = m->mask;	ip->if_net = ip->if_addr & ip->if_mask;	// Queue into global interface list	ip->next = ospf->ifcs;	ospf->ifcs = ip;	if (spflog(CFG_ADD_IFC, 5))	    log(ip);    }    // Allocate new area, if necessary    if (!(new_ap = FindArea(m->area_id)))	new_ap = new SpfArea(m->area_id);    // Change timers, if need be    if (m->hello_int != ip->if_hint || ip->if_pint != m->poll_int) {	ip->if_hint = m->hello_int;	ip->if_pint = m->poll_int;	ip->restart_hellos();    }    // Set new parameters    ip->if_mtu = m->mtu;		// Interface packet size    ip->if_xdelay = m->xmt_dly;	// Transit delay (seconds)    ip->if_rxmt = m->rxmt_int;	// Retransmission interval (seconds)    ip->if_dint = m->dead_int;	// Router dead interval (seconds)    ip->if_autype = m->auth_type; // Authentication type    memcpy(ip->if_passwd, m->auth_key, 8);// Auth key    // If using MD5, reduce mtu to compensate for appended digest    if (ip->if_autype == AUT_CRYPT)	ip->if_mtu -= 16;    // Interface address mask    if (ip->if_mask != m->mask) {	ip->if_mask = m->mask;	ip->if_net = ip->if_addr & ip->if_mask;	new_lsa = true;	new_net_lsa = true;    }    // MIB-II IfIndex    if (ip->if_IfIndex != m->IfIndex) {	ip->if_IfIndex = m->IfIndex;	new_lsa = true;    }    // Designated router priority    if (ip->if_drpri != m->dr_pri) {	ip->if_drpri = m->dr_pri;	ip->ifa_allnbrs_event(NBE_EVAL);	nbr_change = true;    }    // Interface cost    // First verify cost    if (m->if_cost == 0)        m->if_cost = 1;    if (ip->if_cost != m->if_cost) {	ip->if_cost = m->if_cost;	new_lsa = true;    }    // Multicast forwarding enabled?    if (ip->if_mcfwd != m->mc_fwd) {	ip->if_mcfwd = m->mc_fwd;	mospf_clear_cache();	new_net_lsa = true;    }    // On Demand interface?    if (ip->if_demand != (m->demand != 0)) {	ip->if_demand = (m->demand != 0);	restart = true;    }    // Passive interface?    if (ip->if_passive != m->passive) {	ip->if_passive = m->passive;	restart = true;    }    // IGMP enabled?    if (ip->igmp_enabled != (m->igmp != 0)) {        ip->igmp_enabled = (m->igmp != 0);	restart = true;    }    // On Area change, must restart interface    if (new_ap != ip->if_area) {	if (ip->if_area) {	    ip->run_fsm(IFE_DOWN);	    ip->if_area->RemoveIfc(ip);	}	// Add to new area	ip->if_area = new_ap;	ip->anext = new_ap->a_ifcs;	new_ap->a_ifcs = ip;	if (sys->phy_operational(ip->if_phyint))	    ip->run_fsm(IFE_UP);    }    /* Otherwise,     * On certain changes, must restart interface:     * Change in demand status     */    else if (restart)	ip->restart();    /* Otherwise     * Change in DR priority causes DR election to be     * redone. Change in cost or IFIndex causes router-LSA     * to be regenerated.     */    else {	if (nbr_change)	    ip->run_fsm(IFE_NCHG);	if (new_lsa)	    new_ap->rl_orig();	if (new_net_lsa)	    ip->nl_orig(false);    }    ip->updated = true;    new_ap->updated = true;}/* Copy Interface info to CfgIfc structure */static void ifc_to_cfg(const SpfIfc& i, struct CfgIfc& msg){    msg.address = i.if_addr;    msg.phyint = i.if_phyint;    msg.mask = i.mask();    msg.mtu = i.mtu();    msg.IfIndex = i.if_index();    msg.area_id = i.area()->id();    msg.IfType = i.type();    msg.dr_pri = i.drpri();    msg.xmt_dly = i.xmt_delay();    msg.rxmt_int = i.rxmt_interval();    msg.if_cost = i.cost();    msg.hello_int = i.hello_int();    msg.dead_int = i.dead_int();    msg.poll_int = i.poll_int();    msg.auth_type = i.autype();    memcpy(msg.auth_key, i.passwd(), sizeof(msg.auth_key));    msg.mc_fwd = i.mcfwd();    msg.demand = i.demand();    msg.passive = i.passive();    msg.igmp = i.igmp();}/* Query Interface */bool OSPF::qryIfc(struct CfgIfc& msg, InAddr address, int phyint) const{    const SpfIfc *ip = find_ifc(address, phyint);    if (ip == 0) return false;    ifc_to_cfg(*ip, msg);    return true;}/* Get all interfaces */void OSPF::getIfcs(std::list<CfgIfc>& l) const{    IfcIterator iter(this);    SpfIfc* ip;    while((ip = iter.get_next())) {	CfgIfc msg;	ifc_to_cfg(*ip, msg);	l.push_back(msg);    }}/* Constructor for an OSPF interface. Set the identifiers * for an interface (address and physical interface), * set the area to NUL, and then initialize all of the * dynamic (non-config) values. */SpfIfc::SpfIfc(InAddr a, int phy): if_wtim(this), if_htim(this), if_actim(this){    if_addr = a;    if_phyint = phy;    if_area = 0;    if_keys = 0;    if_demand = false;    if_passive = 0;    igmp_enabled = false;    db_xsum = 0;    anext = 0;    if_dr = 0;    if_bdr = 0;    if_dr_p = 0;    if_state = IFS_DOWN;    if_nlst = 0;    if_nnbrs = 0;    if_nfull = 0;    if_helping = 0;    in_recv_update = false;    area_flood = false;    global_flood = false;    if_demand_helapse = 0;    // Virtual link parameters    if_tap = 0;		// Transit area    if_nbrid = 0;	// Configured neighbor ID    if_rmtaddr = 0;	// IP address of other end}/* Destructor for an interface. Declare the interface down, * remove from global and area lists, the free associated * keys and neighbors. */SpfIfc::~SpfIfc(){    SpfIfc **ipp;    SpfIfc *ip;    SpfNbr *np;    NbrIterator nbr_iter(this);    CryptK *key;    KeyIterator key_iter(this);    if (ospf->spflog(CFG_DEL_IFC, 5))	ospf->log(this);    // Remove cryptographic keys    while ((key = key_iter.get_next()))	delete key;    // Declare interface down    run_fsm(IFE_DOWN);    // Remove neighbors    while ((np = nbr_iter.get_next()))	delete np;    // Free from global list    for (ipp = &ospf->ifcs; (ip = *ipp) != 0; ipp = &ip->next) {	if (ip == this) {	    *ipp = next;	    break;	}    }    // Free from area list    if_area->RemoveIfc(this);    // Close physical interface    if (if_phyint != -1)	ospf->phy_detach(if_phyint, if_addr);}/* Return the physical interface type. */int SpfIfc::type() const{    return(if_type);}/* Return a printable string for each interface type */const char *iftypes(int iftype){    switch(iftype) {      case IFT_BROADCAST:	return("BCast");      case IFT_PP:	return("P-P");      case IFT_NBMA:	return("NBMA");      case IFT_P2MP:	return("P2MP");      case IFT_VL:	return("VL");      default:	break;    }    return("Unknown");}// Is the interface a virtual link?bool SpfIfc::is_virtual(){    return(if_type == IFT_VL);}// Can the interface support more than one neighbor?bool SpfIfc::is_multi_access(){    return(if_type != IFT_PP && if_type != IFT_VL);}// Return the transit area (0 if not a virtual link)SpfArea *SpfIfc::transit_area(){    return(if_tap);}// Return the endpoint of a virtual linkrtid_t *SpfIfc::vl_endpt(){    return(&if_nbrid);}/* Base functions that may be overriden for specific interface * types. */void SpfIfc::start_hellos(){    send_hello();    if_htim.start(if_hint*Timer::SECOND);}void SpfIfc::restart_hellos(){    if_htim.restart();}void SpfIfc::stop_hellos(){    if_htim.stop();}bool SpfIfc::elects_dr(){    return(false);}/* Trivial virtual functions for virtual links. *//* Trivial functions for interfaces which elect a Designated * Router. */bool DRIfc::elects_dr(){    return(true);}/* Trivial virtual functions for Broadcast interfaces. *//* Trivial virtual functions for NBMA interfaces. */void NBMAIfc::if_send(Pkt *pdesc, InAddr addr){    nonbroadcast_send(pdesc, addr);}void NBMAIfc::start_hellos(){    if (if_drpri)	ifa_nbr_start(1);}void NBMAIfc::restart_hellos(){    nonbroadcast_restart_hellos();}void NBMAIfc::stop_hellos(){    nonbroadcast_stop_hellos();}/* Trivial virtual functions for Point-to-MultiPoint interfaces. */void P2mPIfc::if_send(Pkt *pdesc, InAddr addr){    nonbroadcast_send(pdesc, addr);}void P2mPIfc::start_hellos(){    ifa_nbr_start(0);}void P2mPIfc::restart_hellos(){    nonbroadcast_restart_hellos();}void P2mPIfc::stop_hellos(){    nonbroadcast_stop_hellos();}/* Functions to manipulate loopback interfaces. */LoopIfc::LoopIfc(SpfArea *a, InAddr net, InMask mask) : SpfIfc(net, -1){    if_type = IFT_LOOPBK;    if_area = a;    if_mask = mask;    if_net = if_addr & if_mask;    if_state = IFS_LOOP;}LoopIfc::~LoopIfc(){    if_state = IFS_DOWN;}void LoopIfc::ifa_start(){}RtrLink *LoopIfc::rl_insert(RTRhdr *, RtrLink *){    return(0);}void LoopIfc::add_adj_to_cand(class PriQ &){}/* If an interface has not been mentioned in a reconfig, just * remove it. */void SpfIfc::clear_config(){    delete this;}/* Restart an interface. Generate the interface down event, * and if the interface is physically up, generate the * up event as well. */void SpfIfc::restart(){    // Declare interface down    run_fsm(IFE_DOWN);    if (sys->phy_operational(if_phyint))	run_fsm(IFE_UP);}/* Find an interface data structure given its IP address and, * optionally, its physical interface. * Only used for real interfaces, and not virtual links. */SpfIfc  *OSPF::find_ifc(uns32 xaddr, int phy) const{    IfcIterator iter(this);    SpfIfc *ip;    while ((ip = iter.get_next())) {	if (ip->is_virtual())	    continue;	if (phy != -1 && phy != ip->if_phyint)	    continue;	if (ip->if_addr == xaddr)	    break;    }    return(ip);}/* OSPF packet has been received on a physical interface. * Associate the packet with the correct OSPF interface, * as described in Section 8.2 of the OSPF specification. */SpfIfc *OSPF::find_ifc(Pkt *pdesc){    SpfPkt *spfpkt;    IfcIterator iter(this);    SpfIfc *ip;    InAddr ipsrc;    InAddr ipdst;    VLIfc *vif;    RTRrte *endpt;    SpfArea *tap;    ipsrc = ntoh32(pdesc->iphdr->i_src);    ipdst = ntoh32(pdesc->iphdr->i_dest);    spfpkt = pdesc->spfpkt;    tap = 0;    while ((ip = iter.get_next())) {	if (ip->is_virtual())	    continue;	// Save interface if dest matches interface	// address, for later virtual link processing	if (ipdst == ip->if_addr)	    tap = ip->if_area;	if (pdesc->phyint != -1 && ip->if_phyint != pdesc->phyint)	    continue;	else if (ip->if_area->a_id != ntoh32(spfpkt->p_aid))	    continue;	else if ((ip->is_multi_access() || pdesc->phyint == -1) &&		 (ipsrc & ip->mask()) != ip->net())	    continue;	else if (ipdst == AllDRouters || ipdst == AllSPFRouters)	    return(ip);	else if (ipdst == ip->if_addr)	    return(ip);    }    // Real interface not found    if (tap == 0) {        AreaIterator aiter(this);	SpfArea *a;	while ((a = aiter.get_next())) {	    HostAddr *loopbk;	    if ((loopbk = (HostAddr *) a->hosts.find(ipdst,0xffffffff)) &&		loopbk->r_cost == 0) {	        tap = a;		break;	    }	}    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -