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

📄 spfifc.c

📁 BCAST Implementation for NS2
💻 C
📖 第 1 页 / 共 2 页
字号:
    if (ntoh32(spfpkt->p_aid) != BACKBONE || tap == 0)	return(0);    // Check instead for virtual link    // Start with endpoint, and see whether a virtual links    // is configured for the particular transit area    endpt = tap->find_abr(ntoh32(spfpkt->srcid));    if (endpt && (vif = endpt->VL))	return(vif);    return(0);}/* Find the interface to which a configured neighbor * attaches. */SpfIfc *OSPF::find_nbr_ifc(InAddr nbr_addr) const{    IfcIterator iter(this);    SpfIfc *ip;    while ((ip = iter.get_next())) {	if (!ip->is_multi_access())	    continue;	if ((nbr_addr & ip->mask()) == ip->net())	    return(ip);    }    return(0);}/* Add or delete an MD5 key. Interface must already be present. */void OSPF::cfgAuKey(struct CfgAuKey *m, int status){    SpfIfc *ip;    CryptK *key;    CryptK **prevk;    if (!(ip = find_ifc(m->address, m->phyint)))	return;    // Search for current key    for (prevk = &ip->if_keys; (key = *prevk); prevk = &key->link) {	if (key->key_id == m->key_id)	    break;    }    // If delete, free to heap    if (status == DELETE_ITEM) {	if (key) {	    *prevk = key->link;	    delete key;	}	return;    }    // Add or modify key    // If new, allocate and link into list of keys    if (!key) {	key = new CryptK(m->key_id);	key->ip = ip;	key->link = ip->if_keys;	ip->if_keys = key;    }    // Copy in new data    memcpy(key->key, m->auth_key, 16);    key->start_accept		 = m->start_accept;    key->stop_accept		 = m->stop_accept;    key->stop_accept_specified	 = m->stop_accept_specified;    key->start_generate		 = m->start_generate;    key->stop_generate		 = m->stop_generate;    key->stop_generate_specified = m->stop_generate_specified;    key->updated = true;}/* Transfer key data to CfgAuKey structure/ */static void key_to_cfg(const CryptK& key, CfgAuKey& msg){    msg.address	= key.interface()->if_addr;    msg.phyint	= key.interface()->if_phyint;    msg.key_id	= key.id();    memcpy(msg.auth_key, key.key_data(), sizeof(msg.auth_key));    msg.start_accept		= key.accept_start();    msg.stop_accept		= key.accept_stop();    msg.stop_accept_specified	= key.stop_accept_set();    msg.start_generate		= key.generate_start();    msg.stop_generate		= key.generate_stop();    msg.stop_generate_specified = key.stop_generate_set();}/* Get key. */bool OSPF::qryAuKey(struct CfgAuKey& msg,		    byte	     key_id,		    InAddr	     address,		    int		     phyint) const{    SpfIfc* ip = find_ifc(address, phyint);    if (ip == 0) return false;    CryptK *key;    CryptK **prevk;    // Search for current key    for (prevk = &ip->if_keys; (key = *prevk); prevk = &key->link) {	if (key->key_id == key_id) {	    key_to_cfg(*key, msg);	    return true;	}    }    return false;}/* Get all keys associated with interface. */void OSPF::getAuKeys(std::list<CfgAuKey>& l,		     InAddr	     address,		     int	     phyint) const{    SpfIfc* ip = find_ifc(address, phyint);    if (ip == 0) return;    CryptK *key;    CryptK **prevk;    for (prevk = &ip->if_keys; (key = *prevk); prevk = &key->link) {	CfgAuKey msg;	key_to_cfg(*key, msg);	l.push_back(msg);    }}/* Key has not been mentioned in the reconfig, so delete it. */void CryptK::clear_config(){    CryptK *ptr;    CryptK **prevk;    for (prevk = &ip->if_keys; (ptr = *prevk); prevk = &ptr->link) {	if (ptr == this)	    break;    }    if (ptr)	*prevk = link;    delete this;}/* Add the authentication fields to a packet that is to * be transmitted. Returns whether the packet needs to * be checksummed. */void SpfIfc::generate_message(Pkt *pdesc){    SpfPkt *spfpkt;    int length;    spfpkt = pdesc->spfpkt;    length = ntoh16(spfpkt->plen);    spfpkt->xsum = 0;    spfpkt->autype = hton16(if_autype);    memset(spfpkt->un.aubytes, 0, 8);    switch (if_autype) {      case AUT_NONE:	// No authentication	if (!pdesc->xsummed)	    spfpkt->xsum = ~incksum((uns16 *) spfpkt, length);        else	    spfpkt->xsum = ~incksum((uns16 *) spfpkt, sizeof(SpfPkt),				    pdesc->body_xsum);	break;      case AUT_PASSWD:	// Simple cleartext password	if (!pdesc->xsummed)	    spfpkt->xsum = ~incksum((uns16 *) spfpkt, length);        else	    spfpkt->xsum = ~incksum((uns16 *) spfpkt, sizeof(SpfPkt),				    pdesc->body_xsum);	memcpy(spfpkt->un.aubytes, if_passwd, 8);	break;      case AUT_CRYPT:	// Cryptographic authentication (e.g., MD5)	md5_generate(pdesc);	break;      default:	sys->halt(HALT_AUTYPE, "Bad authtype on transmit");    }}/* Set the MD5 authentication fields in a packet that we * are going to transmit. * Bumps Pkt::dptr by the size of the digest, so the digest * will be included as part of the IP packet. */void SpfIfc::md5_generate(Pkt *pdesc){    SpfPkt *spfpkt;    int	length;    CryptK *key;    KeyIterator key_iter(this);    byte digest[16];    MD5_CTX context;    CryptK *best_key;    byte *spfend;    SPFtime now;    spfpkt = pdesc->spfpkt;    length = ntoh16(spfpkt->plen);    spfend = ((byte *) spfpkt) + length;    best_key = 0;    // Locate correct key    now = sys_etime;    while ((key = key_iter.get_next())) {	if (time_less(now, key->start_generate))	    continue;	if (key->stop_generate_specified &&	    !time_less(now, key->stop_generate))	    continue;	if (!best_key ||	    time_less(best_key->start_generate, key->start_generate))	    best_key = key;    }    if (!best_key)	return;    // Set MD5 parameters    spfpkt->un.crypt.crypt_mbz = 0;    spfpkt->un.crypt.keyid = best_key->key_id;    spfpkt->un.crypt.audlen = 16;    spfpkt->un.crypt.seqno = hton32(now.sec);    // Calculate digest with our secret key    memcpy(spfend, best_key->key, 16);    MD5_Init(&context);    MD5_Update(&context, (byte *) spfpkt, length + 16);    MD5_Final(digest, &context);    // Append digest to end of packet    memcpy(spfend, digest, 16);    // Make sure that we transmit digest    pdesc->dptr += 16;}/* Authenticate the packet. * Coming into this routine, pdesc->end points to the * end of the encapsulating IP packet. After * authentication, end is adjusted to be the end of * the OSPF packet. */int SpfIfc::verify(Pkt *pdesc, SpfNbr *np){    SpfPkt *spfpkt;    byte *spfend;    spfpkt = pdesc->spfpkt;    if (ntoh16(spfpkt->autype) != if_autype)	return(false);    spfend = ((byte *) spfpkt) + ntoh16(spfpkt->plen);    switch (if_autype) {      case AUT_NONE:	// No authentication	if (incksum((uns16 *) spfpkt, ntoh16(spfpkt->plen)) != 0)	    return(false);	break;      case AUT_PASSWD:	// Simple cleartext password	if (memcmp(spfpkt->un.aubytes, if_passwd, 8) != 0)	    return(false);        memset(spfpkt->un.aubytes, 0, 8);	if (incksum((uns16 *) spfpkt, ntoh16(spfpkt->plen)) != 0)	    return(false);	break;      case AUT_CRYPT:	// Cryptographic authentication (e.g., MD5)	if (!md5_verify(pdesc, np))	    return(false);	break;      default:	return(false);    }    // Packet authenticates    // Strip IP trailer    pdesc->end = spfend;    return(true);}/* Verify the cryptographic authentication for a received * packet. First locate the key based on the Key ID. Then, * check for replays by verifying the sequence number. * Finally, run the cryptographic hash using our secret key, * and check that the generated digest matches the one appended * to the received packet. * Packet checksum is not used when we're doing cryptographic * authentication. */int SpfIfc::md5_verify(Pkt *pdesc, SpfNbr *np){    SpfPkt *spfpkt;    byte *spfend;    CryptK *key;    KeyIterator key_iter(this);    byte saved_digest[16];    byte digest[16];    MD5_CTX context;    SPFtime now;    spfpkt = pdesc->spfpkt;    spfend = ((byte *) spfpkt) + ntoh16(spfpkt->plen);    // Check that digest actually appended    if ((spfend + 16) > pdesc->end)	return(false);    // Locate correct key    now = sys_etime;    while ((key = key_iter.get_next())) {	if (time_less(now, key->start_accept))	    continue;	if (key->stop_accept_specified &&	    !time_less(now, key->stop_accept))	    continue;	if (key->key_id == spfpkt->un.crypt.keyid)	    break;    }    if (!key)	return(false);    // Verify sequence number of live nighbors    if (np != 0 && np->state() > NBS_ATTEMPT)	if (np->md5_seqno > ntoh32(spfpkt->un.crypt.seqno))	    return(false);    // Save received digest    memcpy(saved_digest, spfend, 16);    // Calculate digest with our secret key    memcpy(spfend, key->key, 16);    MD5_Init(&context);    MD5_Update(&context, (byte *) spfpkt, ntoh16(spfpkt->plen) + 16);    MD5_Final(digest, &context);    // Compare to saved copy    if (memcmp(digest, saved_digest, 16) != 0)	return(false);    // Save sequence number    if (np)	np->md5_seqno = ntoh32(spfpkt->un.crypt.seqno);    return(true);}/* Find the neighbor representing the source of the received * OSPF packet. Identified by IP source address. Overriden * by point-to-point interfaces and virtual links, where neighbor * is identified by Router ID in the received OSPF header. */SpfNbr *SpfIfc::find_nbr(InAddr addr, rtid_t){    NbrIterator iter(this);    SpfNbr *np;    while ((np = iter.get_next())) {	if (np->addr() == addr)	    break;    }    return(np);}/* On point-to-point and virtual links, the neighbor is * identified by its OSPF Router ID. */SpfNbr *PPIfc::find_nbr(InAddr, rtid_t id){    NbrIterator iter(this);    SpfNbr *np;    while ((np = iter.get_next())) {	if (np->id() == id)	    break;    }    return(np);}/* Upon receiving a Hello, may set the neighbor's Router ID * or IP address, or neither, depending on interface type. */// Set router ID on multi-access interfacesvoid SpfIfc::set_id_or_addr(SpfNbr *np, rtid_t _id, InAddr){    np->n_id = _id;}// Set IP address on point-to-point interfacesvoid PPIfc::set_id_or_addr(SpfNbr *np, rtid_t, InAddr _addr){    np->n_addr = _addr;}/* Functions that multicast OSPF packets out the given interface * types. * Unicast packets are handled by SpfIfc::nbr_send(). *//* Generic multicast send function, used by broadcast and point-to-point * interfaces. Simply send the IP packet out the correct * physical interface, specifying the next hop or multicast * address. */void SpfIfc::if_send(Pkt *pdesc, InAddr addr){    InPkt *pkt;    if (!pdesc->iphdr)	return;    finish_pkt(pdesc, addr);    pkt = pdesc->iphdr;    if (pkt->i_src != 0) {	if (ospf->spflog(LOG_TXPKT, 1)) {	    ospf->log(pdesc);	    ospf->log(this);	}    sys->sendpkt(pkt, if_phyint);    }    else if (ospf->spflog(ERR_NOADDR, 5)) {	    ospf->log(pdesc);	    ospf->log(this);	}    ospf->ospf_freepkt(pdesc);}/* Send a multicast packet out a point-to-point link. Packet is * always sent to the AllSPFRouters address. */void PPIfc::if_send(Pkt *pdesc, InAddr){    if (!pdesc->iphdr)	return;    SpfIfc::if_send(pdesc, AllSPFRouters);}/* Send a multicast packet out a virtual link. Packet is sent directly * to the IP address of the other end of the link. */void VLIfc::if_send(Pkt *pdesc, InAddr){    InPkt *pkt;    if (!pdesc->iphdr)	return;        finish_pkt(pdesc, if_rmtaddr);    pkt = pdesc->iphdr;    if (ospf->spflog(LOG_TXPKT, 1)) {	ospf->log(pdesc);	ospf->log(this);    }    sys->sendpkt(pkt);    ospf->ospf_freepkt(pdesc);}/* Send the multicast packet out an NBMA or ptmp interface. Packet is sent * separately to each neighbor. This function is only called * by flooding (Hellos have a separate function), and so packets * are only sent to those neighbors in states Exchange or greater. */void SpfIfc::nonbroadcast_send(Pkt *pdesc, InAddr addr){    InPkt *pkt;    SpfNbr *np;    NbrIterator nbrIter(this);    if (!pdesc->iphdr)	return;    finish_pkt(pdesc, addr);    pkt = pdesc->iphdr;    while ((np = nbrIter.get_next())) {	if (np->state() < NBS_EXCH)	    continue;	if (ospf->spflog(LOG_TXPKT, 1)) {	    ospf->log(pdesc);	    ospf->log(np);	}	sys->sendpkt(pkt, if_phyint, np->addr());    }    ospf->ospf_freepkt(pdesc);}/* Hello interval has changed. Restart the hello timer on each * of a non-broadcast networks nighbors. Using restart, we don't * have to worry about whether we should be sending them a hello * or not. */void SpfIfc::nonbroadcast_restart_hellos(){    NbrIterator iter(this);    SpfNbr *np;    while ((np = iter.get_next()))	np->nbr_fsm(NBE_EVAL);}/* Interface has gone down. Stop sending Hellos to all * neighbors. */void SpfIfc::nonbroadcast_stop_hellos(){    NbrIterator iter(this);    SpfNbr *np;    while ((np = iter.get_next()))	np->n_htim.stop();}/* If OSPF::PPAdjLimit is non-zero, we limit the number * of point-to-point links which will become adjacent * to a particular neighbor. If the "enlist" parameter * is true, and there are insufficient adjacencies, we * add all the 2-Way point-to-point interfaces to the * pending adjacency list, since we don't know which * ones we will be able to advance. */bool SpfIfc::more_adjacencies_needed(rtid_t){    return(true);}bool VLIfc::more_adjacencies_needed(rtid_t){    return(true);}bool PPIfc::more_adjacencies_needed(rtid_t nbr_id){    PPAdjAggr *adjaggr;    if (ospf->PPAdjLimit == 0)        return(true);    if (!(adjaggr = (PPAdjAggr *)if_area->AdjAggr.find(nbr_id, 0)))        return(true);    return ((ospf->my_id() >nbr_id) && (adjaggr->n_adjs< ospf->PPAdjLimit));}

⌨️ 快捷键说明

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