예제 #1
0
void delete_pim_neighbor(void *arg)
{//删除一个邻居
	struct pim_neighbor *myentry,*temp,*pimneighbor;
	vifi_t vif;
	myentry=arg;

	vif=find_vif_direct(myentry->address);
	if(vif==0)
	{
		return;
	}
	for(pimneighbor=myvifs[vif].neighbor;pimneighbor!=NULL;pimneighbor=pimneighbor->next)
	{
		if(pimneighbor->address==myentry->address)
		{
			if(myvifs[vif].neighbor->address==myentry->address)
			{
				myvifs[vif].neighbor=NULL;
			}
			temp->next=pimneighbor->next;
			break;
		}
		temp=pimneighbor;
	}
	log(LOG_INFO,"Holdtime=0,delete this neighbor");
	refresh_mrt(vif,DEL_NEIGHBOR);
}
예제 #2
0
void receive_hello(u_int32 src,u_int32 dst,char *data,int length)
{//收到Hello报文
	vifi_t vif;
	struct pim_neighbor *pimneighbor;
	
	int holdtime;
	vif=find_vif_direct(src);
	if(valid_packet(src,data,length)==0)
	{
		return;
	
	}
	holdtime=get_hold_time(data,length);
	if(holdtime==-1)
	{
		log(LOG_INFO,"Get hold time error!");
	}
	log(LOG_INFO,"Receive PIM Hello message,get Hold time=%d from %s",holdtime,inet_fmt(src,s1));
	for(pimneighbor=myvifs[vif].neighbor;pimneighbor!=NULL;pimneighbor=pimneighbor->next)
	{
		if(pimneighbor->address==src)
		{
			if(holdtime==0)
			{
				delete_pim_neighbor(pimneighbor);
				return;
			}
			pimneighbor->holdtime=holdtime;
			if(pimneighbor->timeoutid!=-1)
			{
				timer_clearTimer(pimneighbor->timeoutid);
			}
			pimneighbor->timeoutid=timer_setTimer(holdtime,delete_pim_neighbor,pimneighbor);
			log(LOG_INFO,"Refresh hold time of neighbor %s to %d",inet_fmt(pimneighbor->address,s1),holdtime);
			return;
		}
	}
	add_pim_neighbor(src,holdtime,vif);
	return;
	//根据所得到的时间,采取相应的操作*/
}
예제 #3
0
파일: igmp_proto.c 프로젝트: atessmer/pimd
/*
 * Process an incoming host membership query
 */
void accept_membership_query(u_int32 src, u_int32 dst __attribute__((unused)), u_int32 group, int tmo)
{
    vifi_t vifi;
    struct uvif *v;

    /* Ignore my own membership query */
    if (local_address(src) != NO_VIF)
	return;

    /* TODO: modify for DVMRP?? */
    if ((vifi = find_vif_direct(src)) == NO_VIF) {
	IF_DEBUG(DEBUG_IGMP)
	    logit(LOG_INFO, 0,
		  "ignoring group membership query from non-adjacent host %s",
		  inet_fmt(src, s1, sizeof(s1)));
	return;
    }

    v = &uvifs[vifi];

    if ((tmo == 0 && !(v->uv_flags & VIFF_IGMPV1)) ||
	(tmo != 0 &&  (v->uv_flags & VIFF_IGMPV1))) {
	int i;

	/*
	 * Exponentially back-off warning rate
	 */
	i = ++v->uv_igmpv1_warn;
	while (i && !(i & 1))
	    i >>= 1;
	if (i == 1) {
	    logit(LOG_WARNING, 0, "%s %s on vif %d, %s",
		  tmo == 0 ? "Received IGMPv1 report from"
		  : "Received IGMPv2 report from",
		  inet_fmt(src, s1, sizeof(s1)),
		  vifi,
		  tmo == 0 ? "please configure vif for IGMPv1"
		  : "but I am configured for IGMPv1");
	}
    }
예제 #4
0
int valid_packet(u_int32 src,char *packet,int length)
{//检验包的校验和 源地址 接口等信息,确定该包是否有效,有效返回1,否则返回0
	vifi_t vif;
	struct myvif *myv;
	if(inet_cksum((u_int16 *)packet,length))
	{
		log(LOG_INFO,0,"Checking sum error!");
		return 0;
	}
	vif=find_vif_direct(src);
	if(vif==0)
	{
		//log(LOG_INFO,"Source address error!Don't handle!");
		return 0;
	}
	myv=&myvifs[vif];
	if(myv->is_active==0)
	{
		log(LOG_INFO,"Interface is not active!");
		return 0;
	}
	return 1;
}
예제 #5
0
파일: route.c 프로젝트: F0rth/pimd
/*
 * Set the iif, upstream router, preference and metric for the route
 * toward the source. Return TRUE is the route was found, othewise FALSE.
 * If srctype==PIM_IIF_SOURCE and if the source is directly connected
 * then the "upstream" is set to NULL. If srcentry==PIM_IIF_RP, then
 * "upstream" in case of directly connected "source" will be that "source"
 * (if it is also PIM router).,
 */
int set_incoming(srcentry_t *srcentry_ptr, int srctype)
{
    struct rpfctl rpfc;
    u_int32 source = srcentry_ptr->address;
    u_int32 neighbor_addr;
    struct uvif *v;
    pim_nbr_entry_t *n;

    /* Preference will be 0 if directly connected */
    srcentry_ptr->metric = 0;
    srcentry_ptr->preference = 0;

    if ((srcentry_ptr->incoming = local_address(source)) != NO_VIF) {
        /* The source is a local address */
        /* TODO: set the upstream to myself? */
        srcentry_ptr->upstream = (pim_nbr_entry_t *)NULL;
        return (TRUE);
    }

    if ((srcentry_ptr->incoming = find_vif_direct(source)) != NO_VIF) {
        /* The source is directly connected. Check whether we are
         * looking for real source or RP
         */
        if (srctype == PIM_IIF_SOURCE) {
            srcentry_ptr->upstream = (pim_nbr_entry_t *)NULL;
            return (TRUE);
        } else {
            /* PIM_IIF_RP */
            neighbor_addr = source;
        }
    } else {
        /* TODO: probably need to check the case if the iif is disabled */
        /* Use the lastest resource: the kernel unicast routing table */
        k_req_incoming(source, &rpfc);
        if ((rpfc.iif == NO_VIF) ||
            rpfc.rpfneighbor.s_addr == INADDR_ANY_N) {
            /* couldn't find a route */
            IF_DEBUG(DEBUG_PIM_MRT | DEBUG_RPF)
                logit(LOG_DEBUG, 0, "NO ROUTE found for %s",
                      inet_fmt(source, s1, sizeof(s1)));
            return FALSE;
        }
        srcentry_ptr->incoming = rpfc.iif;
        neighbor_addr = rpfc.rpfneighbor.s_addr;
        /* set the preference for sources that aren't directly connected. */
        v = &uvifs[srcentry_ptr->incoming];
        srcentry_ptr->preference = v->uv_local_pref;
        srcentry_ptr->metric = v->uv_local_metric;
    }

    /*
     * The upstream router must be a (PIM router) neighbor, otherwise we
     * are in big trouble ;-)
     */
    v = &uvifs[srcentry_ptr->incoming];
    for (n = v->uv_pim_neighbors; n != NULL; n = n->next) {
        if (ntohl(neighbor_addr) < ntohl(n->address))
            continue;
        if (neighbor_addr == n->address) {
            /*
             *The upstream router is found in the list of neighbors.
             * We are safe!
             */
            srcentry_ptr->upstream = n;
            IF_DEBUG(DEBUG_RPF)
                logit(LOG_DEBUG, 0,
                      "For src %s, iif is %d, next hop router is %s",
                      inet_fmt(source, s1, sizeof(s1)), srcentry_ptr->incoming,
                      inet_fmt(neighbor_addr, s2, sizeof(s2)));

            return TRUE;
        }
        else break;
    }

    /* TODO: control the number of messages! */
    logit(LOG_INFO, 0,
          "For src %s, iif is %d, next hop router is %s: NOT A PIM ROUTER",
          inet_fmt(source, s1, sizeof(s1)), srcentry_ptr->incoming,
          inet_fmt(neighbor_addr, s2, sizeof(s2)));
    srcentry_ptr->upstream = (pim_nbr_entry_t *)NULL;

    return FALSE;
}
예제 #6
0
파일: trace.c 프로젝트: CameronNemo/pimd
/*
 * Traceroute function which returns traceroute replies to the requesting
 * router. Also forwards the request to downstream routers.
 */
void accept_mtrace(u_int32 src, u_int32 dst, u_int32 group, char *data, u_int no, int datalen)
{
    u_char type;
    mrtentry_t *mrt;
    struct tr_query *qry;
    struct tr_resp  *resp;
    int vifi;
    char *p;
    u_int rcount;
    int errcode = TR_NO_ERR;
    int resptype;
    struct timeval tp;
    struct sioc_vif_req v_req;
#if 0
    /* TODO */
    struct sioc_sg_req sg_req;
#endif /* 0 */
    u_int32 parent_address = INADDR_ANY;

    /* Remember qid across invocations */
    static u_int32 oqid = 0;

    /* timestamp the request/response */
    gettimeofday(&tp, 0);

    /*
     * Check if it is a query or a response
     */
    if (datalen == QLEN) {
        type = QUERY;
        IF_DEBUG(DEBUG_TRACE)
            logit(LOG_DEBUG, 0, "Initial traceroute query rcvd from %s to %s",
                  inet_fmt(src, s1, sizeof(s1)), inet_fmt(dst, s2, sizeof(s2)));
    }
    else if ((datalen - QLEN) % RLEN == 0) {
        type = RESP;
        IF_DEBUG(DEBUG_TRACE)
            logit(LOG_DEBUG, 0, "In-transit traceroute query rcvd from %s to %s",
                  inet_fmt(src, s1, sizeof(s1)), inet_fmt(dst, s2, sizeof(s2)));
        if (IN_MULTICAST(ntohl(dst))) {
            IF_DEBUG(DEBUG_TRACE)
                logit(LOG_DEBUG, 0, "Dropping multicast response");
            return;
        }
    }
    else {
        logit(LOG_WARNING, 0, "%s from %s to %s",
              "Non decipherable traceroute request recieved",
              inet_fmt(src, s1, sizeof(s1)), inet_fmt(dst, s2, sizeof(s2)));
        return;
    }

    qry = (struct tr_query *)data;

    /*
     * if it is a packet with all reports filled, drop it
     */
    if ((rcount = (datalen - QLEN)/RLEN) == no) {
        IF_DEBUG(DEBUG_TRACE)
            logit(LOG_DEBUG, 0, "packet with all reports filled in");
        return;
    }

    IF_DEBUG(DEBUG_TRACE) {
        logit(LOG_DEBUG, 0, "s: %s g: %s d: %s ", inet_fmt(qry->tr_src, s1, sizeof(s1)),
              inet_fmt(group, s2, sizeof(s2)), inet_fmt(qry->tr_dst, s3, sizeof(s3)));
        logit(LOG_DEBUG, 0, "rttl: %d rd: %s", qry->tr_rttl,
              inet_fmt(qry->tr_raddr, s1, sizeof(s1)));
        logit(LOG_DEBUG, 0, "rcount:%d, qid:%06x", rcount, qry->tr_qid);
    }

    /* determine the routing table entry for this traceroute */
    mrt = find_route(qry->tr_src, group, MRTF_SG | MRTF_WC | MRTF_PMBR,
                     DONT_CREATE);
    IF_DEBUG(DEBUG_TRACE) {
        if (mrt != (mrtentry_t *)NULL) {
            if (mrt->upstream != (pim_nbr_entry_t *)NULL)
                parent_address = mrt->upstream->address;
            else
                parent_address = INADDR_ANY;
            logit(LOG_DEBUG, 0, "mrt parent vif: %d rtr: %s metric: %d",
                  mrt->incoming, inet_fmt(parent_address, s1, sizeof(s1)), mrt->metric);
/* TODO
   logit(LOG_DEBUG, 0, "mrt origin %s",
   RT_FMT(rt, s1));
*/
        } else {
            logit(LOG_DEBUG, 0, "...no route");
        }
    }

    /*
     * Query type packet - check if rte exists
     * Check if the query destination is a vif connected to me.
     * and if so, whether I should start response back
     */
    if (type == QUERY) {
        if (oqid == qry->tr_qid) {
            /*
             * If the multicast router is a member of the group being
             * queried, and the query is multicasted, then the router can
             * recieve multiple copies of the same query.  If we have already
             * replied to this traceroute, just ignore it this time.
             *
             * This is not a total solution, but since if this fails you
             * only get N copies, N <= the number of interfaces on the router,
             * it is not fatal.
             */
            IF_DEBUG(DEBUG_TRACE)
                logit(LOG_DEBUG, 0, "ignoring duplicate traceroute packet");
            return;
        }

        if (mrt == (mrtentry_t *)NULL) {
            IF_DEBUG(DEBUG_TRACE)
                logit(LOG_DEBUG, 0, "Mcast traceroute: no route entry %s",
                      inet_fmt(qry->tr_src, s1, sizeof(s1)));
            if (IN_MULTICAST(ntohl(dst)))
                return;
        }
        vifi = find_vif_direct(qry->tr_dst);

        if (vifi == NO_VIF) {
            /* The traceroute destination is not on one of my subnet vifs. */
            IF_DEBUG(DEBUG_TRACE)
                logit(LOG_DEBUG, 0, "Destination %s not an interface",
                      inet_fmt(qry->tr_dst, s1, sizeof(s1)));
            if (IN_MULTICAST(ntohl(dst)))
                return;
            errcode = TR_WRONG_IF;
        } else if (mrt != (mrtentry_t *)NULL && !VIFM_ISSET(vifi, mrt->oifs)) {
            IF_DEBUG(DEBUG_TRACE)
                logit(LOG_DEBUG, 0,
                      "Destination %s not on forwarding tree for src %s",
                      inet_fmt(qry->tr_dst, s1, sizeof(s1)), inet_fmt(qry->tr_src, s2, sizeof(s2)));
            if (IN_MULTICAST(ntohl(dst)))
                return;
            errcode = TR_WRONG_IF;
        }
    }
    else {
        /*
         * determine which interface the packet came in on
         * RESP packets travel hop-by-hop so this either traversed
         * a tunnel or came from a directly attached mrouter.
         */
        if ((vifi = find_vif_direct(src)) == NO_VIF) {
            IF_DEBUG(DEBUG_TRACE)
                logit(LOG_DEBUG, 0, "Wrong interface for packet");
            errcode = TR_WRONG_IF;
        }
    }

    /* Now that we've decided to send a response, save the qid */
    oqid = qry->tr_qid;

    IF_DEBUG(DEBUG_TRACE)
        logit(LOG_DEBUG, 0, "Sending traceroute response");

    /* copy the packet to the sending buffer */
    p = igmp_send_buf + IP_IGMP_HEADER_LEN + IGMP_MINLEN;

    bcopy(data, p, datalen);

    p += datalen;

    /*
     * If there is no room to insert our reply, coopt the previous hop
     * error indication to relay this fact.
     */
    if (p + sizeof(struct tr_resp) > igmp_send_buf + SEND_BUF_SIZE) {
        resp = (struct tr_resp *)p - 1;
        resp->tr_rflags = TR_NO_SPACE;
        mrt = NULL;
        goto sendit;
    }

    /*
     * fill in initial response fields
     */
    resp = (struct tr_resp *)p;
    memset(resp, 0, sizeof(struct tr_resp));
    datalen += RLEN;

    resp->tr_qarr    = htonl(((tp.tv_sec + JAN_1970) << 16) +
			     ((tp.tv_usec << 10) / 15625));
    resp->tr_rproto  = PROTO_PIM;
    resp->tr_outaddr = (vifi == NO_VIF) ? dst : uvifs[vifi].uv_lcl_addr;
    resp->tr_fttl    = (vifi == NO_VIF) ? 0   : uvifs[vifi].uv_threshold;
    resp->tr_rflags  = errcode;

    /*
     * obtain # of packets out on interface
     */
    v_req.vifi = vifi;
    if (vifi != NO_VIF && ioctl(udp_socket, SIOCGETVIFCNT, (char *)&v_req) >= 0)
        resp->tr_vifout  =  htonl(v_req.ocount);
    else
        resp->tr_vifout  =  0xffffffff;

    /*
     * fill in scoping & pruning information
     */
/* TODO */
#if 0
    if (mrt != (mrtentry_t *)NULL)
        for (gt = rt->rt_groups; gt; gt = gt->gt_next) {
            if (gt->gt_mcastgrp >= group)
                break;
        }
    else
        gt = NULL;

    if (gt && gt->gt_mcastgrp == group) {
        struct stable *st;

        for (st = gt->gt_srctbl; st; st = st->st_next)
            if (qry->tr_src == st->st_origin)
                break;

        sg_req.src.s_addr = qry->tr_src;
        sg_req.grp.s_addr = group;
        if (st && st->st_ctime != 0 &&
            ioctl(udp_socket, SIOCGETSGCNT, (char *)&sg_req) >= 0)
            resp->tr_pktcnt = htonl(sg_req.pktcnt + st->st_savpkt);
        else
            resp->tr_pktcnt = htonl(st ? st->st_savpkt : 0xffffffff);

        if (VIFM_ISSET(vifi, gt->gt_scope))
            resp->tr_rflags = TR_SCOPED;
        else if (gt->gt_prsent_timer)
            resp->tr_rflags = TR_PRUNED;
        else if (!VIFM_ISSET(vifi, gt->gt_grpmems))
            if (VIFM_ISSET(vifi, rt->rt_children) &&
                NBRM_ISSETMASK(uvifs[vifi].uv_nbrmap, rt->rt_subordinates)) /*XXX*/
                resp->tr_rflags = TR_OPRUNED;
            else
                resp->tr_rflags = TR_NO_FWD;
    } else {
        if (scoped_addr(vifi, group))
            resp->tr_rflags = TR_SCOPED;
        else if (rt && !VIFM_ISSET(vifi, rt->rt_children))
            resp->tr_rflags = TR_NO_FWD;
    }
#endif /* 0 */

    /*
     *  if no rte exists, set NO_RTE error
     */
    if (mrt == (mrtentry_t *)NULL) {
        src = dst;		/* the dst address of resp. pkt */
        resp->tr_inaddr   = 0;
        resp->tr_rflags   = TR_NO_RTE;
        resp->tr_rmtaddr  = 0;
    } else {
        /* get # of packets in on interface */
        v_req.vifi = mrt->incoming;
        if (ioctl(udp_socket, SIOCGETVIFCNT, (char *)&v_req) >= 0)
            resp->tr_vifin = htonl(v_req.icount);
        else
            resp->tr_vifin = 0xffffffff;

        /* TODO
           MASK_TO_VAL(rt->rt_originmask, resp->tr_smask);
        */
        src = uvifs[mrt->incoming].uv_lcl_addr;
        resp->tr_inaddr = src;
        if (mrt->upstream != (pim_nbr_entry_t *)NULL)
            parent_address = mrt->upstream->address;
        else
            parent_address = INADDR_ANY;

        resp->tr_rmtaddr = parent_address;
        if (!VIFM_ISSET(vifi, mrt->oifs)) {
            IF_DEBUG(DEBUG_TRACE)
                logit(LOG_DEBUG, 0, "Destination %s not on forwarding tree for src %s",
                      inet_fmt(qry->tr_dst, s1, sizeof(s1)), inet_fmt(qry->tr_src, s2, sizeof(s2)));
            resp->tr_rflags = TR_WRONG_IF;
        }
#if 0
        if (rt->rt_metric >= UNREACHABLE) {
            resp->tr_rflags = TR_NO_RTE;
            /* Hack to send reply directly */
            rt = NULL;
        }
#endif /* 0 */
    }

  sendit:
    /*
     * if metric is 1 or no. of reports is 1, send response to requestor
     * else send to upstream router.  If the upstream router can't handle
     * mtrace, set an error code and send to requestor anyway.
     */
    IF_DEBUG(DEBUG_TRACE)
        logit(LOG_DEBUG, 0, "rcount:%d, no:%d", rcount, no);

    if ((rcount + 1 == no) || (mrt == NULL) || (mrt->metric == 1)) {
        resptype = IGMP_MTRACE_RESP;
        dst = qry->tr_raddr;
    } else

#if 0   /* TODO */
    if (!can_mtrace(rt->rt_parent, rt->rt_gateway)) {
        dst = qry->tr_raddr;
        resp->tr_rflags = TR_OLD_ROUTER;
        resptype = IGMP_MTRACE_RESP;
    } else {
#endif  /* 0 */
        if (mrt->upstream != (pim_nbr_entry_t *)NULL)
            parent_address = mrt->upstream->address;
        else
            parent_address = INADDR_ANY;
        dst = parent_address;
        resptype = IGMP_MTRACE;
#if 0   /* TODO */
    }
#endif
    if (IN_MULTICAST(ntohl(dst))) {
	/*
	 * Send the reply on a known multicast capable vif.
	 * If we don't have one, we can't source any multicasts anyway.
	 */
	if (phys_vif != -1) {
	    IF_DEBUG(DEBUG_TRACE)
		logit(LOG_DEBUG, 0, "Sending reply to %s from %s",
		      inet_fmt(dst, s1, sizeof(s1)),
		      inet_fmt(uvifs[phys_vif].uv_lcl_addr, s2, sizeof(s2)));
	    k_set_ttl(igmp_socket, qry->tr_rttl);
	    send_igmp(igmp_send_buf, uvifs[phys_vif].uv_lcl_addr, dst,
		      resptype, no, group, datalen);
	    k_set_ttl(igmp_socket, 1);
	} else
	    logit(LOG_INFO, 0, "No enabled phyints -- %s",
		  "dropping traceroute reply");
    } else {
	IF_DEBUG(DEBUG_TRACE)
	    logit(LOG_DEBUG, 0, "Sending %s to %s from %s",
		  resptype == IGMP_MTRACE_RESP ?  "reply" : "request on",
		  inet_fmt(dst, s1, sizeof(s1)), inet_fmt(src, s2, sizeof(s2)));

	send_igmp(igmp_send_buf, src, dst, resptype, no, group, datalen);
    }
}
예제 #7
0
void receive_pim_graft_ack(u_int32 src,u_int32 dst,char *data,int length)
{//
	vifi_t vif;
	char *mydata;
	struct pim_join_prune_header *graft_header;
	struct pim_join_prune_group *graft_group_header;
	u_int32 unicast_address;
	struct encode_group_address group_address;
	struct encode_source_address *source_address;
	int num_groups;
	int join_number;
	int i,j;
	struct mrt *mymrt;

	vif=find_vif_direct(src);
	if(vif==0)
	{
		return;
	}
	if(valid_packet(src,data,length)==0)
	{
		return;
	}
	mydata=data+sizeof(struct pim)+sizeof(struct encode_unicast_option);
	graft_header=(struct pim_join_prune_header *)mydata;
	unicast_address=graft_header->upstream;
	num_groups=graft_header->num_groups;
	if(num_groups==0)
	{
		return;
	}

	mydata=mydata+sizeof(struct pim_join_prune_header);
	for(i=0;i<num_groups;i++)
	{
		graft_group_header=(struct pim_join_prune_group *)mydata;
		mydata=mydata+sizeof(struct pim_join_prune_group);
		group_address=graft_group_header->group_address;
		join_number=graft_group_header->join_number;
		if(!IN_MULTICAST(ntohl(group_address.group_address)))
		{
			mydata=mydata+(join_number)*sizeof(struct encode_source_address);
			continue;
		}
		for(j=0;j<join_number;j++)
		{
			source_address=(struct encode_source_address *)mydata;
			if(!inet_valid_host(source_address->source_address))
			{
				mydata=mydata+sizeof(struct encode_source_address);
				continue;
			}
			mymrt=find_sg(source_address->source_address,group_address.group_address);
			if(mymrt==NULL)
			{//没有该组播路由表项,则不处理
				mydata=mydata+sizeof(struct encode_source_address);
				continue;
			}
			if(mymrt->graft_timer_id!=0)
			{
				log(LOG_INFO,"Receive PIM Graft ack from %s to %s,Graft success",inet_fmt(src,s1),inet_fmt(src,s2));
				timer_clearTimer(mymrt->graft_timer_id);
				mymrt->graft_timer_id=0;
			}
		}
	}
}
예제 #8
0
void receive_pim_graft(u_int32 src,u_int32 dst,char *data,int length)
{//
	u_int32 unicast_address;
	struct encode_group_address group_address;
	struct encode_source_address *source_address;
	vifi_t vif;
	struct pim_neighbor neighbor;
	struct pim_join_prune_header *graft_header;
	struct pim_join_prune_group *graft_group_header;
	int i,j;
	int join_number;
	char *mydata,*temp;
	int num_groups;
	struct mrt *mymrt;

	temp=data;

	vif=find_vif_direct(src);
	if(vif==0)
	{
		return;
	}
	if(valid_packet(src,data,length)==0)
	{
		return;
	}
	mydata=data+sizeof(struct pim)+sizeof(struct encode_unicast_option);
	graft_header=(struct pim_join_prune_header *)mydata;
	unicast_address=graft_header->upstream;
	num_groups=graft_header->num_groups;
	if(num_groups==0)
	{
		return;
	}

	mydata=mydata+sizeof(struct pim_join_prune_header);
	for(i=0;i<num_groups;i++)
	{
		graft_group_header=(struct pim_join_prune_group *)mydata;
		mydata=mydata+sizeof(struct pim_join_prune_group);
		group_address=graft_group_header->group_address;
		join_number=ntohs(graft_group_header->join_number);
		if(!IN_MULTICAST(ntohl(group_address.group_address)))
		{
			mydata=mydata+(join_number)*sizeof(struct encode_source_address);
			continue;
		}
		for(j=0;j<join_number;j++)
		{
			source_address=(struct encode_source_address *)mydata;
			if(!inet_valid_host(source_address->source_address))
			{
				mydata=mydata+sizeof(struct encode_source_address);
				continue;
			}
			log(LOG_INFO,"Receive Graft form %s for group %s,Forwarding data in this interface",inet_fmt(source_address->source_address,s1),inet_fmt(group_address.group_address,s2));
			bcopy(temp,pim_send_buf+sizeof(struct ip),length);
			pimdm_output(pim_send_buf,myvifs[vif].address,src,PIM_GRAFT_ACK,length-sizeof(struct pim));
			mymrt=find_sg(source_address->source_address,group_address.group_address);
			if(mymrt==NULL)
			{//没有该组播路由表项,则不处理
				mydata=mydata+sizeof(struct encode_source_address);				
				continue;
			}
			
			if(mymrt->prune_delay_timer_id[vif]!=0)
			{
				timer_clearTimer(mymrt->prune_delay_timer_id[vif]);
				mymrt->prune_delay_timer_id[vif]=0;
			}
			if(mymrt->outvif[vif]==0)
			{
				mymrt->outvif[vif]=1;
				change_mfc(igmpsocket,mymrt->source,mymrt->group,mymrt->incoming);
				//bcopy(data,pim_send_buf+sizeof(struct ip),length);
			}
			//pimdm_output(pim_send_buf,myvifs[vif].address,src,PIM_GRAFT_ACK,length-sizeof(struct pim));
		}
		mydata=mydata+sizeof(struct encode_source_address);
	}
}
예제 #9
0
void receive_assert(u_int32 src,u_int32 dst,char *data,int length)
{//
	vifi_t vif;
	vifi_t *vifdata;
	u_int32 *unicast_address;
	struct encode_group_address *group_address;
	u_int32 source,group;
	struct mrt *mymrt;
	char *mydata;
	u_int32 *preference;
	u_int32 *metric;

	vif=find_vif_direct(src);
	if(vif==0)
	{
		return;
	}
	if(valid_packet(src,data,length)==0)
	{
		return;
	}
	mydata=data+sizeof(struct pim);
	group_address=(struct encode_group_address *)mydata;
	group=group_address->group_address;
	
	mydata=mydata+sizeof(struct encode_group_address)+sizeof(struct encode_unicast_option);
	unicast_address=(u_int32 *)mydata;
	source=*unicast_address;

	mydata=mydata+sizeof(u_int32);
	preference=(u_int32 *)mydata;

	mydata=mydata+sizeof(u_int32);
	metric=(u_int32 *)mydata;

	log(LOG_INFO,"Receive PIM Assert from %s to %s",inet_fmt(src,s1),inet_fmt(dst,s2));
	mymrt=find_sg(source,group);
	if(mymrt==NULL)
	{
		return;
	}
	if(vif==mymrt->incoming)
	{
		if(source==mymrt->upstream)
		{
			return;
		}
		else
		{
			if(assert_compare(mymrt->preference,mymrt->metric,mymrt->upstream,*preference,*metric,source)==1)
			{
				return;
			}
			else
			{
				log(LOG_INFO,"PIM Assert!:Change upstream!");
				mymrt->preference=*preference;
				mymrt->metric=*metric;
				mymrt->upstream=source;
				return;
			}
		}
	}
	else
	{
		if(mymrt->outvif[vif]==0)
		{
			return;
		}
		if(assert_compare(mymrt->preference,mymrt->metric,mymrt->upstream,*preference,*metric,source)==1)
		{
			pim_assert_output(source,group,vif,mymrt->preference,mymrt->metric);
			return;
		}
		else
		{
			vifdata=(vifi_t *)malloc(sizeof(vifi_t));
			*vifdata=vif;
			mymrt->prune_delay_timer_id[vif]=timer_setTimer(PIM_ASSERT_TIMER,active_forward,vifdata);
			//changeinterface();将该接口置为不转发状态
		}
	}
}
예제 #10
0
void receive_join_prune(u_int32 src,u_int32 dst,char *data,int length)
{//收到join或prune
	int unicast_address;
	struct encode_group_address group_address;
	struct encode_source_address *source_address;
	vifi_t vif;
	struct pim_neighbor neighbor;
	struct pim_join_prune_header *jp_header;
	struct pim_join_prune_group *jp_group_header;
	struct mrt *mymrt;
	char *mydata;
	int num_groups;
	int holdtime;
	int join_number;
	int prune_number;
	int i,j,k;

	vif=find_vif_direct(src);
	if(vif==0)
	{
		return;
	}
	if(valid_packet(src,data,length)==0)
	{
		return;
	}
	mydata=data+sizeof(struct pim)+sizeof(struct encode_unicast_option);
	jp_header=(struct pim_join_prune_header *)mydata;
	unicast_address=jp_header->upstream;
	num_groups=jp_header->num_groups;
	holdtime=jp_header->holdtime;
	if(num_groups==0)
	{
		return;
	}

	log(LOG_INFO,"Receive PIM Join/Prune from %s to %s",inet_fmt(src,s1),inet_fmt(dst,s2));
	mydata=mydata+sizeof(struct pim_join_prune_header);
	log(LOG_INFO,"Receive Upstream interface:%s",inet_fmt(unicast_address,s1));
	if((unicast_address!=myvifs[vif].address)&&(unicast_address!=INADDR_ANY_N))
	{
		//我不是这条消息的接收者
		//如果是join,如果此时我有延迟发送join消息的计划,则取消发送join的计划
		//如果是prune,此时我还要接收的话,延迟一段时间后发送join消息
		if(findneighbor(unicast_address,vif)==NULL)
		{//看接收方是不是我的PIM邻居
			return;
		}log(LOG_INFO,"Num of groups:%d",num_groups);
		for(i=0;i<num_groups;i++)
		{
			jp_group_header=(struct pim_join_prune_group *)mydata;
			mydata=mydata+sizeof(struct pim_join_prune_group);
			group_address=jp_group_header->group_address;
			join_number=ntohs(jp_group_header->join_number);
			prune_number=ntohs(jp_group_header->prune_number);
log(LOG_INFO,"Receive Group number:%d Join number:%d Prune number:%d",inet_fmt(group_address.group_address,s1),join_number,prune_number);
			if(!IN_MULTICAST(ntohl(group_address.group_address)))
			{
				mydata=mydata+(join_number+prune_number)*sizeof(struct encode_source_address);
				continue;
			}
			for(j=0;j<join_number;j++)
			{
				source_address=(struct encode_source_address *)mydata;
log(LOG_INFO,"Receive Source_address:%s",inet_fmt(source_address->source_address,s1));
				if(!inet_valid_host(source_address->source_address))
				{
					mydata=mydata+sizeof(struct encode_source_address);
					continue;
				}
				mymrt=find_sg(source_address->source_address,group_address.group_address);
				if(mymrt==NULL)
				{//没有该组播路由表项,则不处理
					mydata=mydata+sizeof(struct encode_source_address);
					continue;
				}
				if(mymrt->join_delay_timer_id!=0)
				{//如果有join延迟的话,取消置为0即可
					log(LOG_INFO,"Join form %s for %s,Canceling delay join",inet_fmt(source_address->source_address,s1),inet_fmt(group_address.group_address,s2));
					timer_clearTimer(mymrt->join_delay_timer_id);
					mymrt->join_delay_timer_id=0;
				}
				mydata=mydata+(join_number+prune_number)*sizeof(struct encode_source_address);
			}
			for(k=0;k<prune_number;k++)
			{
				source_address=(struct encode_source_address *)mydata;
log(LOG_INFO,"Receive Source_address:%s",inet_fmt(source_address->source_address,s1));
				if(!inet_valid_host(source_address->source_address))
				{
					mydata=mydata+sizeof(struct encode_source_address);
					continue;
				}
				mymrt=find_sg(source_address->source_address,group_address.group_address);
				if(mymrt==NULL)
				{//路由表是空的情况下,不处理
					mydata=mydata+sizeof(struct encode_source_address);
					continue;
				}
				if(mymrt->outnumber!=0)
				{
					if(mymrt->upstream!=mymrt->source)
					{
						log(LOG_INFO,"We are receiving Src %s Group %s,Scheduling and send Join",inet_fmt(source_address->source_address,s1),inet_fmt(group_address.group_address,s2));
						schedule_join(mymrt,unicast_address);
					}
					mydata=mydata+sizeof(struct encode_source_address);
					continue;
				}
				mydata=mydata+(join_number+prune_number)*sizeof(struct encode_source_address);
			}
		}
		return;
	}
	else
	{//我是Join/Prune报文的接收方
		//收到Join报文,取消我的延迟剪枝计时器
		//收到Prune报文,回送Prune报文,启动计时器,超时后剪枝
log(LOG_INFO,"Num of groups:%d",num_groups);
		for(i=0;i<num_groups;i++)
		{
			jp_group_header=(struct pim_join_prune_group *)mydata;
			mydata=mydata+sizeof(struct pim_join_prune_group);
			group_address=jp_group_header->group_address;
			join_number=ntohs(jp_group_header->join_number);
			prune_number=ntohs(jp_group_header->prune_number);
log(LOG_INFO,"Receive Group address:%s Join number:%d Prune number:%d",inet_fmt(group_address.group_address,s1),join_number,prune_number);
			if(!IN_MULTICAST(ntohl(group_address.group_address)))
			{
				mydata=mydata+(join_number+prune_number)*sizeof(struct encode_source_address);
				continue;
			}
			for(j=0;j<join_number;j++)
			{
				source_address=(struct encode_source_address *)mydata;
log(LOG_INFO,"Join Message,Receive Source_address:%s",inet_fmt(source_address->source_address,s1));
				if(!inet_valid_host(source_address->source_address))
				{
					mydata=mydata+sizeof(struct encode_source_address);
					continue;
				}
				mymrt=find_sg(source_address->source_address,group_address.group_address);
				if(mymrt==NULL)
				{//没有该组播路由表项,则不处理
					mydata=mydata+sizeof(struct encode_source_address);
					continue;
				}
				if(mymrt->prune_delay_timer_id[vif]!=0)
				{//如果有join延迟的话,取消置为0即可
					log(LOG_INFO,"Join form %s for %s,Canceling delay prune",inet_fmt(source_address->source_address,s1),inet_fmt(group_address.group_address,s2));
					timer_clearTimer(mymrt->prune_delay_timer_id[vif]);
					mymrt->prune_delay_timer_id[vif]=0;
				}
				mydata=mydata+(join_number+prune_number)*sizeof(struct encode_source_address);
			}
			for(k=0;k<prune_number;k++)
			{
				source_address=(struct encode_source_address *)mydata;
log(LOG_INFO,"Prune message,Receive Source_address:%s",inet_fmt(source_address->source_address,s1));
				if(!inet_valid_host(source_address->source_address))
				{
					mydata=mydata+sizeof(struct encode_source_address);
					continue;
				}
				mymrt=find_sg(source_address->source_address,group_address.group_address);
				if(mymrt==NULL)
				{//路由表是空的情况下,不处理
					mydata=mydata+sizeof(struct encode_source_address);
					continue;
				}
				if(mymrt->upstream!=mymrt->source)
				{
					log(LOG_INFO,"We are receiving Src %s Group %s,Scheduling and echo Prune",inet_fmt(source_address->source_address,s1),inet_fmt(group_address.group_address,s2));
					bcopy(data,pim_send_buf+sizeof(struct ip),length);
					if(pimdm_output(pim_send_buf,myvifs[vif].address,allpimrouters,PIM_JOIN_PRUNE,length-sizeof(struct pim))!=1)
					{
						log(LOG_INFO,"Echo Prune Packet error!");
					}
					schedule_prune(mymrt,vif,holdtime);
				}
				mydata=mydata+(join_number+prune_number)*sizeof(struct encode_source_address);
			}
		}
	}
	return;
}