Exemplo n.º 1
0
void network_interface::receive_dao(struct in6_addr from,
                                    struct in6_addr ip6_to,
                                    const  time_t now,
                                    const u_char *dat, const int dao_len)
{
    unsigned int dat_len = dao_len;
    debug->info("  processing dao(%u)",dao_len);

    struct nd_rpl_dao *dao = (struct nd_rpl_dao *)dat;
    unsigned char *dat2 = (unsigned char *)(dao+1);
    dat_len -= sizeof(struct nd_rpl_dao);

    if(this->packet_too_short("dao", dao_len, sizeof(*dao))) return;

    dagid_t dagid;
    char dagid_str[16*6];
    dagid[0]=0;
    if(RPL_DAO_D(dao->rpl_flags)) {
        memcpy(&dagid, dat2, DAGID_LEN);
	dag_network::format_dagid(dagid_str, dat2);
        dat2 += DAGID_LEN;
	dat_len -= DAGID_LEN;
    }

    debug->info_more(" [instance:%u,daoseq:%u,%sdagid:%s]\n",
                dao->rpl_instanceid,
                dao->rpl_daoseq,
                RPL_DAO_K(dao->rpl_flags) ? "dao-ack," : "",
                dagid_str[0] ? dagid_str : "<elided>");

    /* XXX if rpl_instanceid is 0, then we are using a default DAG? */

    /* find the relevant DAG */
    /* if watching, then we find_or_make, which returns us an
     * inactive DAO.  This might be used to watch a network for RPL
     * activity.
     */
    class dag_network *dn;
    if(watching) {
	dn = dag_network::find_or_make_by_dagid(dagid,
						this->debug,
						watching);
    } else {
	dn = dag_network::find_by_dagid(dagid);
    }

    if(dn) {
	/* and process it */
	dn->receive_dao(this, from, ip6_to, now, dao, dat2, dat_len);
    } else {
	dag_network::globalStats[PS_DAO_PACKET_IGNORED]++;
    }
}
Exemplo n.º 2
0
/*
 * Process an incoming DAG Advertisement Object.
 * the DAO is the upward announcement.
 *
 */
void dag_network::receive_dao(network_interface *iface,
                              struct in6_addr from,
                              struct in6_addr ip6_to,
                              const time_t    now,
                              const struct nd_rpl_dao *dao,
                              unsigned char *data, int dao_len)
{
    /* it has already been checked to be at least sizeof(*dio) */
    //int dao_payload_len = dao_len - sizeof(*dao);

    /* increment stat of number of packets processed */
    this->mStats[PS_PACKET_RECEIVED]++;
    this->mStats[PS_DAO_PACKET_RECEIVED]++;

    /* validate this packet, if possible */
    bool secure = this->check_security(dao, dao_len);

    rpl_node *peer;

    /* find the node entry from this source IP, and update seen time */
    /* this will create the node if it does not already exist! */
    if((peer = this->update_child(iface, from, ip6_to, now)) == NULL) {
        return;
    }

    if(mActive == false) {
	this->mStats[PS_PACKETS_WATCHED]++;
	return;
    }

    /* look for the suboptions, process them */
    rpl_dao decoded_dao(data, dao_len, this);
    unsigned int addrcount = 0;

    struct rpl_dao_target *rpltarget;
    while((rpltarget = decoded_dao.rpltarget()) != NULL) {
        char addrfound[SUBNETTOT_BUF];
        unsigned char v6bytes[16];
        int prefixbytes = ((rpltarget->rpl_dao_prefixlen+7) / 8);
        ip_subnet prefix;
        prefix.maskbits = rpltarget->rpl_dao_prefixlen;
        memset(v6bytes, 0, 16);
        memcpy(v6bytes, rpltarget->rpl_dao_prefix, prefixbytes);
        initaddr(v6bytes, 16, AF_INET6, &prefix.addr);

        addrcount++;

        subnettot(&prefix, 0, addrfound, sizeof(addrfound));


        /* need to look at dag_members, and see if the child node already
         * exists, and add if not
         */
        debug->verbose("  recv DAO rpltarget re: network %s, target %s (added)\n",
                       addrfound, peer->node_name());

        add_childnode(peer, iface, prefix);
    }
    maybe_send_dao();

    /* now send a DAO-ACK back this the node, using the interface it arrived on, if asked to. */
    if(RPL_DAO_K(dao->rpl_flags)) {
        debug->verbose("sending DAOACK about %u networks, to %s\n",
                       addrcount, peer->node_name());
        iface->send_daoack(*peer, *this, dao->rpl_daoseq);
    }

    /* increment stat of number of packets processed */
    this->mStats[PS_PACKET_PROCESSED]++;
}