Beispiel #1
0
/**
*   Sends a group specific member report query until the 
*   group times out...
*/
static void sendGroupSpecificMemberQuery(void *argument) {
    struct  Config  *conf = getCommonConfig();

    // Cast argument to correct type...
    GroupVifDesc   *gvDesc = (GroupVifDesc*) argument;

    if(gvDesc->started) {
        // If aging returns false, we don't do any further action...
        if(!lastMemberGroupAge(gvDesc->group)) {
            return;
        }
    } else {
        gvDesc->started = 1;
    }

    // Send a group specific membership query...
    sendIgmp(gvDesc->vifAddr, gvDesc->group, 
             IGMP_MEMBERSHIP_QUERY,
             conf->lastMemberQueryInterval * IGMP_TIMER_SCALE, 
             gvDesc->group, 0);

    my_log(LOG_DEBUG, 0, "Sent membership query from %s to %s. Delay: %d",
        inetFmt(gvDesc->vifAddr,s1), inetFmt(gvDesc->group,s2),
        conf->lastMemberQueryInterval);

    // Set timeout for next round...
    timer_setTimer(conf->lastMemberQueryInterval, sendGroupSpecificMemberQuery, gvDesc);

}
Beispiel #2
0
void schedule_join(struct mrt *mymrt,u_int32 dst)
{//设置join计时器
	struct pim_join_data *joindata;
	joindata=(struct pim_join_data *)malloc(sizeof(struct pim_join_data));
	joindata->source=mymrt->source;
	joindata->group=mymrt->group;
	joindata->destination=dst;
	mymrt->join_delay_timer_id=timer_setTimer(1,send_join,joindata);
}
/**
*   Sends a general membership query on downstream VIFs
*/
void sendGeneralMembershipQuery() {
    struct  Config  *conf = getCommonConfig();
    struct  IfDesc  *Dp;
    unsigned        Ix;

#ifdef RALINK_ESW_SUPPORT
    clear_all_entries_report();
#endif

    // Loop through all downstream vifs...
    for ( Ix = 0; (Dp = getIfByIx(Ix)); Ix++ ) {
        if ( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) ) {
            if(Dp->state == IF_STATE_DOWNSTREAM) {
                // Send the membership query...
                sendIgmp(Dp->InAdr.s_addr, allhosts_group,
                         IGMP_MEMBERSHIP_QUERY,
                         conf->queryResponseInterval * IGMP_TIMER_SCALE, 0, 0);
                my_log(LOG_DEBUG, 0,
			"Sent membership query from %s to %s. Delay: %d",
			inetFmt(Dp->InAdr.s_addr,s1),
			inetFmt(allhosts_group,s2),
			conf->queryResponseInterval);
            }
        }
    }

    // Install timer for aging active routes.
    timer_setTimer(conf->queryResponseInterval, ageActiveRoutes, NULL);

    // Install timer for next general query...
    if(conf->startupQueryCount>0) {
        // Use quick timer...
        timer_setTimer(conf->startupQueryInterval, sendGeneralMembershipQuery, NULL);
        // Decrease startup counter...
        conf->startupQueryCount--;
    } 
    else {
        // Use slow timer...
        timer_setTimer(conf->queryInterval, sendGeneralMembershipQuery, NULL);
    }


}
Beispiel #4
0
void plan_graft(void *arg)
{//
	struct mrt *mymrt,*thismrt,*mrtdata;
	mymrt=(struct mrt *)arg;
	thismrt=find_sg(mymrt->source,mymrt->group);
	if(mymrt->upstream==mymrt->source)
	{
		return;
	}
	if(thismrt!=NULL)
	{
		pim_graft_output(mymrt);
		mymrt->graft_timer_id=timer_setTimer(PIM_GRAFT_TIMER,plan_graft,mymrt);
	}
}
Beispiel #5
0
void schedule_prune(struct mrt *mrtdata,vifi_t vif,int holdtime)
{//设置prune计时器
	struct pim_prune_data *prunedata;
	struct mrt *mymrt;
	
	mymrt=mrtdata;
	prunedata=(struct pim_prune_data *)malloc(sizeof(struct pim_prune_data));
	prunedata->source=mymrt->source;
	prunedata->group=mymrt->group;
	prunedata->destination=mymrt->upstream;
	prunedata->vif=vif;
	prunedata->holdtime=holdtime;
	mymrt->prune_delay_timer_id[vif]=timer_setTimer(PIM_PRUNE_DELAY,set_prune,prunedata);

	log(LOG_INFO,"schedule_prune!!!");
}
Beispiel #6
0
void add_pim_neighbor(u_int32 src,int holdtime,vifi_t thevif)
{//添加一个邻居
	vifi_t vif;
	vif=thevif;
	struct pim_neighbor *newentry;
	
	newentry=(struct pim_neighbor *)malloc(sizeof(struct pim_neighbor));
	newentry->next=myvifs[vif].neighbor;
	newentry->address=src;
	newentry->holdtime=holdtime;
	newentry->timeoutid=timer_setTimer(holdtime,delete_pim_neighbor,newentry);

	myvifs[vif].neighbor=newentry;
	log(LOG_INFO,"It's a new neighbor,add this neighbor on vif %s",myvifs[vif].name);
	refresh_mrt(vif,ADD_NEIGHBOR);/*1 add 0 delete*/
}
Beispiel #7
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;
	//根据所得到的时间,采取相应的操作*/
}
Beispiel #8
0
void pim_hello_output(void *arg)
{//给定Holdtime,发送一条PIM的Hello报文
	struct pim_hello_output_data *hello_data;//参考实验指导书
	struct pim_hello_header *option;
	char *mydata;
	short *hold_time;
	int length;
	
	hello_data=(struct pim_hello_output_data *)arg;
	mydata=(char *)(pim_send_buf+sizeof(struct ip)+sizeof(struct pim));

	option=(struct pim_hello_header *)mydata;
	option->option_type=htons(1);
	option->option_length=htons(2);

	mydata=mydata+sizeof(struct pim_hello_header);
	hold_time=(short *)mydata;
	*hold_time=htons(hello_data->holdtime);

	length=sizeof(struct pim_hello_header)+sizeof(short);

	
	if(hello_data->regular==1)
	
	{
		
		timer_setTimer(PIM_HELLO_PERIOD,pim_hello_output,hello_data);
	
	}
	if(pimdm_output(pim_send_buf,myvifs[hello_data->vif].address,allpimrouters,PIM_HELLO,length)!=1)
	{
		log(LOG_INFO,"Send Pim Hello Packet On %s(%s) Error!",myvifs[hello_data->vif].name,inet_fmt(myvifs[hello_data->vif].address,s1));
	}
	else
	{
		log(LOG_INFO,"Send Pim Hello Packet On %s(%s) Success!",myvifs[hello_data->vif].name,inet_fmt(myvifs[hello_data->vif].address,s1));
	
	}
	return;
}
Beispiel #9
0
void set_prune(void *data)
{//在prune计时器超时后,执行操作
	struct pim_prune_data *prunedata;
	struct mrt *mymrt;
	log(LOG_INFO,"Begin Prune");
	prunedata=(struct pim_prune_data *)data;
	mymrt=find_sg(prunedata->source,prunedata->group);
	log(LOG_INFO,"Prune source:%s Group:%s",inet_fmt(prunedata->source,s1),inet_fmt(prunedata->group,s2));
	if(mymrt==NULL)
	{
		return;
	}
	else
	{
		mymrt->prune_delay_timer_id[prunedata->vif]=0;
		mymrt->outvif[prunedata->vif]=0;
		change_mfc(igmpsocket,mymrt->source,mymrt->group,mymrt->incoming);
		check_pim_state(DEL_LEAF);
		log(LOG_INFO,"miss,handle set the prune");
		mymrt->prune_timer_id[prunedata->vif]=timer_setTimer(5,prune_time_out,prunedata);
	}
}
Beispiel #10
0
int main(int argc, char *argv[])
{
    int foreground = 0, do_syslog = 1;
    fd_set fds;
    int nfds, fd, n = -1, i, ch;
    struct sigaction sa;
    struct option long_options[] = {
	{ "config",        1, 0, 'f' },
	{ "no-fallback",   0, 0, 500 },
	{ "disable-vifs",  0, 0, 'N' },
	{ "foreground",    0, 0, 'n' },
	{ "help",          0, 0, 'h' },
	{ "ident",         1, 0, 'I' },
	{ "loglevel",      1, 0, 'l' },
	{ "pidfile",       1, 0, 'P' },
	{ "syslog",        0, 0, 's' },
	{ "table-id",      1, 0, 't' },
	{ "version",       0, 0, 'v' },
	{ NULL, 0, 0, 0 }
    };

    snprintf(versionstring, sizeof (versionstring), "pimd version %s", PACKAGE_VERSION);

    prognm = ident = progname(argv[0]);
    while ((ch = getopt_long(argc, argv, "d:f:hI:l:nNP:rst:v", long_options, NULL)) != EOF) {
	const char *errstr;

	switch (ch) {
	    case 'd':
		{
		    char *p,*q;
		    size_t i, len;
		    struct debugname *d;

		    debug = 0;
		    p = optarg;
		    q = NULL;
		    while (p) {
			q = strchr(p, ',');
			if (q)
			    *q++ = '\0';
			len = strlen(p);
			for (i = 0, d = debugnames; i < ARRAY_LEN(debugnames); i++, d++) {
			    if (len >= d->nchars && strncmp(d->name, p, len) == 0)
				break;
			}

			if (i == ARRAY_LEN(debugnames))
			    return usage(1);

			debug |= d->level;
			p = q;
		    }
		}
		break;

	    case 'f':
		config_file = optarg;
		break;

	    case 500:
		no_fallback = 1;
		break;

	    case 'h':
		return usage(0);

	    case 'I':	/* --ident=NAME */
		ident = optarg;
		break;

	    case 'l':
		loglevel = loglvl(optarg);
		if (-1 == loglevel)
		    return usage(1);
		break;

	    case 'n':
		do_syslog--;
		foreground = 1;
		break;

	    case 'N':
		do_vifs = 0;
		break;

	    case 'P':	/* --pidfile=NAME */
		pid_file = strdup(optarg);
		break;

	    case 'r':
		retry_forever++;
		break;

	    case 's':
		do_syslog++;
		break;

	    case 't':
		mrt_table_id = strtonum(optarg, 0, 999999999, &errstr);
		if (errstr) {
		    fprintf(stderr, "Table ID %s!\n", errstr);
		    return usage(1);
		}
		break;

	    case 'v':
		printf("%s\n", versionstring);
		return 0;

	    default:
		return usage(1);
	}
    }

    argc -= optind;
    if (argc > 0)
	return usage(1);

    if (geteuid() != 0)
	errx(1, "Need root privileges to start.");

    compose_paths();
    setlinebuf(stderr);

    if (debug != 0) {
	struct debugname *d;
	char c;
	int tmpd = debug;

	fprintf(stderr, "debug level 0x%lx ", debug);
	c = '(';
	for (d = debugnames; d < debugnames + ARRAY_LEN(debugnames); d++) {
	    if ((tmpd & d->level) == d->level) {
		tmpd &= ~d->level;
		fprintf(stderr, "%c%s", c, d->name);
		c = ',';
	    }
	}
	fprintf(stderr, ")\n");
    }

    if (!debug && !foreground) {
	/* Detach from the terminal */
	haveterminal = 0;
	if (fork())
	    exit(0);

	close(STDIN_FILENO);
	close(STDOUT_FILENO);
	close(STDERR_FILENO);

	fd = open("/dev/null", O_RDWR, 0);
	if (fd >= 0) {
	    dup2(fd, STDIN_FILENO);
	    dup2(fd, STDOUT_FILENO);
	    dup2(fd, STDERR_FILENO);
	    close(fd);
	}
#ifdef SYSV
	setpgrp();
#else
#ifdef TIOCNOTTY
	fd = open("/dev/tty", 2);
	if (fd >= 0) {
	    (void)ioctl(fd, TIOCNOTTY, (char *)0);
	    close(fd);
	}
#else
	if (setsid() < 0)
	    perror("setsid");
#endif /* TIOCNOTTY */
#endif /* SYSV */
    } /* End of child process code */

    /*
     * Create directory for runtime files
     */
    if (-1 == mkdir(_PATH_PIMD_RUNDIR, 0755) && errno != EEXIST)
	err(1, "Failed creating %s directory for runtime files", _PATH_PIMD_RUNDIR);

    /*
     * Setup logging
     */
    log_init(haveterminal && do_syslog > 0);
    logit(LOG_NOTICE, 0, "%s starting ...", versionstring);

    do_randomize();

    callout_init();
    init_igmp();
    init_pim();
    init_routesock(); /* Both for Linux netlink and BSD routing socket */
    init_pim_mrt();
    init_timers();
    ipc_init();

    /* Start up the log rate-limiter */
    resetlogging(NULL);

    /* TODO: check the kernel DVMRP/MROUTED/PIM support version */

    init_vifs();
    init_rp_and_bsr();   /* Must be after init_vifs() */
    add_static_rp();	 /* Must be after init_vifs() */
#ifdef RSRR
    rsrr_init();
#endif /* RSRR */

    sa.sa_handler = handle_signals;
    sa.sa_flags = 0;	/* Interrupt system calls */
    sigemptyset(&sa.sa_mask);
    sigaction(SIGALRM, &sa, NULL);
    sigaction(SIGHUP, &sa, NULL);
    sigaction(SIGTERM, &sa, NULL);
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGUSR1, &sa, NULL);
    sigaction(SIGUSR2, &sa, NULL);

    IF_DEBUG(DEBUG_IF)
	dump_vifs(stderr);
    IF_DEBUG(DEBUG_PIM_MRT)
	dump_pim_mrt(stderr);

    /* schedule first timer interrupt */
    timer_setTimer(TIMER_INTERVAL, timer, NULL);

    if (pidfile(pid_file))
	warn("Cannot create pidfile");

    /*
     * Main receive loop.
     */
    while (1) {
	if (check_signals())
	    break;

	FD_ZERO(&fds);
	for (i = 0, nfds = 0; i < nhandlers; i++) {
	    FD_SET(ihandlers[i].fd, &fds);
	    if (ihandlers[i].fd >= nfds)
		nfds = ihandlers[i].fd + 1;
	}

	n = select(nfds, &fds, NULL, NULL, timeout(n));
	if (n < 0) {
	    if (errno != EINTR) /* SIGALRM is expected */
		logit(LOG_WARNING, errno, "select failed");
	    continue;
	}

	for (i = 0; n > 0 && i < nhandlers; i++) {
	    if (FD_ISSET(ihandlers[i].fd, &fds))
		ihandlers[i].func(ihandlers[i].fd);
	}
    }

    logit(LOG_NOTICE, 0, "%s exiting.", versionstring);
    cleanup();
    exit(0);
}
Beispiel #11
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();将该接口置为不转发状态
		}
	}
}
Beispiel #12
0
int main(int argc, char *argv[])
{	
    int dummy, dummysigalrm, foreground = 0;
    struct timeval tv, difftime, curtime, lasttime, *timeout;
    fd_set rfds, readers;
    int nfds, n, i, secs, ch;
    struct sigaction sa;
    time_t boottime;
    struct option long_options[] = {
	{"config", 1, 0, 'c'},
	{"debug", 2, 0, 'd'},
	{"foreground", 0, 0, 'f'},
	{"disable-vifs", 0, 0, 'N'},
	{"help", 0, 0, 'h'},
	{"version", 0, 0, 'v'},
	{"quit-daemon", 0, 0, 'q'},
	{"reload-config", 0, 0, 'l'},
	{"show-routes", 0, 0, 'r'},
	/* {"show-cache", 0, 0, 'i'}, */
	/* {"show-debug", 0, 0, 'p'}, */
	{0, 0, 0, 0}
    };
    
    snprintf(versionstring, sizeof (versionstring), "pimd version %s", todaysversion);

    while ((ch = getopt_long (argc, argv, "c:d::fhlNP::vqr", long_options, NULL)) != EOF) {
	switch (ch) {
	    case 'c':
		configfilename = optarg;
		break;

	    case 'd':
		if (!optarg) {
		    debug = DEBUG_DEFAULT;
		} else {
		    char *p,*q;
		    size_t i, len;
		    struct debugname *d;

		    debug = 0;
		    p = optarg; q = NULL;
		    while (p) {
			q = strchr(p, ',');
			if (q)
			    *q++ = '\0';
			len = strlen(p);
			for (i = 0, d = debugnames; i < ARRAY_LEN(debugnames); i++, d++)
			    if (len >= d->nchars && strncmp(d->name, p, len) == 0)
				break;

			if (i == ARRAY_LEN(debugnames))
			    return usage();

			debug |= d->level;
			p = q;
		    }
		}
		break;

	    case 'f':
		foreground = 1;
		break;

	    case 'h':
		return usage();

	    case 'l':
		killshow(SIGHUP, NULL);
		return 0;

	    case 'N':
		disable_all_by_default = 1;
		break;

	    case 'P':
#ifdef SNMP
		if (!optarg)
		    dest_port = DEFAULT_PORT;
		else {
		    dest_port = strtonum(optarg, 1, 65535, &errstr);
		    if (errstr) {
			warnx("destination port %s", errstr);
			dest_port = DEFAULT_PORT;
		    }
		}
#else
		warnx("SNMP support missing, please feel free to submit a patch.");
#endif
		break;

	    case 'v':
		printf("%s\n", versionstring);
		return 0;

	    case 'q':
		killshow(SIGTERM, NULL);
		return 0;

	    case 'r':
		killshow(SIGUSR1, _PATH_PIMD_DUMP);
		return 0;
#if 0 /* XXX: TODO */
	    case 'i':
		killshow(SIGUSR2, _PATH_PIMD_CACHE);
		return 0;

	    case 'p':
		killshow(SIGQUIT, NULL);
		return 0;
#endif
	    default:
		return usage();
	}
    }

    argc -= optind;
    argv += optind;

    if (argc > 0) {
	return usage();
    }

    if (geteuid() != 0) {
	fprintf(stderr, "%s: must be root\n", __progname);
	exit(1);
    }
    setlinebuf(stderr);

    if (debug != 0) {
	struct debugname *d;
	char c;
	int tmpd = debug;

	fprintf(stderr, "debug level 0x%lx ", debug);
	c = '(';
	for (d = debugnames; d < debugnames + ARRAY_LEN(debugnames); d++) {
	    if ((tmpd & d->level) == d->level) {
		tmpd &= ~d->level;
		fprintf(stderr, "%c%s", c, d->name);
		c = ',';
	    }
	}
	fprintf(stderr, ")\n");
    }
    
    /*
     * Create directory for runtime files
     */
    mkdir(_PATH_PIMD_RUNDIR, 0755);

    /*
     * Setup logging
     */
#ifdef LOG_DAEMON
    (void)openlog("pimd", LOG_PID, LOG_DAEMON);
    (void)setlogmask(LOG_UPTO(LOG_NOTICE));
#else
    (void)openlog("pimd", LOG_PID);
#endif /* LOG_DAEMON */

    logit(LOG_DEBUG, 0, "%s starting", versionstring);

    do_randomize();
    time(&boottime);
    
    /* Start up the log rate-limiter */
    resetlogging(NULL);

    callout_init();
    init_igmp();
    init_pim();
#ifdef HAVE_ROUTING_SOCKETS
    init_routesock();
#endif /* HAVE_ROUTING_SOCKETS */
    init_pim_mrt();
    init_timers();
    
    /* TODO: check the kernel DVMRP/MROUTED/PIM support version */
    
#ifdef SNMP
    if (i = snmp_init())
	return i;
#endif /* SNMP */
    init_vifs();
    init_rp_and_bsr();   /* Must be after init_vifs() */
    
#ifdef RSRR
    rsrr_init();
#endif /* RSRR */
    
    sa.sa_handler = handler;
    sa.sa_flags = 0;	/* Interrupt system calls */
    sigemptyset(&sa.sa_mask);
    sigaction(SIGALRM, &sa, NULL);
    sigaction(SIGHUP, &sa, NULL);
    sigaction(SIGTERM, &sa, NULL);
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGUSR1, &sa, NULL);
    sigaction(SIGUSR2, &sa, NULL);
    
    FD_ZERO(&readers);
    FD_SET(igmp_socket, &readers);
    nfds = igmp_socket + 1;
    for (i = 0; i < nhandlers; i++) {
	FD_SET(ihandlers[i].fd, &readers);
	if (ihandlers[i].fd >= nfds)
	    nfds = ihandlers[i].fd + 1;
    }
    
    IF_DEBUG(DEBUG_IF)
	dump_vifs(stderr);
    IF_DEBUG(DEBUG_PIM_MRT)
	dump_pim_mrt(stderr);
    
    /* schedule first timer interrupt */
    timer_setTimer(TIMER_INTERVAL, timer, NULL);
    
    if (!debug && !foreground) {
	/* Detach from the terminal */
	haveterminal = 0;
	if (fork())
	    exit(0);
	(void)close(0);
	(void)close(1);
	(void)close(2);
	(void)open("/", 0);
	(void)dup2(0, 1);
	(void)dup2(0, 2);
#ifdef SYSV
	(void)setpgrp();
#else 
#ifdef TIOCNOTTY
	n = open("/dev/tty", 2);
	if (n >= 0) {
	    (void)ioctl(n, TIOCNOTTY, (char *)0);
	    (void)close(n);
	}
#else
	if (setsid() < 0)
	    perror("setsid");
#endif /* TIOCNOTTY */
#endif /* SYSV */
    } /* End of child process code */
    
    if (pidfile(NULL)) {
	warn("Cannot create pidfile");
    }

    /*
     * Main receive loop.
     */
    dummy = 0;
    dummysigalrm = SIGALRM;
    difftime.tv_usec = 0;
    gettimeofday(&curtime, NULL);
    lasttime = curtime;
    while (1) {
	memcpy(&rfds, &readers, sizeof(rfds));
	secs = timer_nextTimer();
	if (secs == -1)
	    timeout = NULL;
	else {
	    timeout = &tv;
	    timeout->tv_sec = secs;
	   timeout->tv_usec = 0;
        }

        if (boottime) {
           time_t n;

           time(&n);
           if (n > boottime + 15) {
              struct rp_hold *rph = g_rp_hold;

              while(rph) {
                 add_rp_grp_entry(&cand_rp_list, &grp_mask_list,
                                  rph->address, 1, (u_int16)0xffffff, rph->group, rph->mask,
                                  curr_bsr_hash_mask, curr_bsr_fragment_tag);
                 rph = rph->next;
              }
              boottime = 0;
           }
        }
	
	if (sighandled) {
	    if (sighandled & GOT_SIGINT) {
		sighandled &= ~GOT_SIGINT;
		break;
	    }
	    if (sighandled & GOT_SIGHUP) {
		sighandled &= ~GOT_SIGHUP;
		restart(SIGHUP);
		
		/* reconstruct readers and nfds */
		FD_ZERO(&readers);
		FD_SET(igmp_socket, &readers);
		nfds = igmp_socket + 1;
		for (i = 0; i < nhandlers; i++) {
		    FD_SET(ihandlers[i].fd, &readers);
		    if (ihandlers[i].fd >= nfds)
			nfds = ihandlers[i].fd + 1;
		}
		memcpy(&rfds, &readers, sizeof(rfds));
	    }
	    if (sighandled & GOT_SIGUSR1) {
		sighandled &= ~GOT_SIGUSR1;
		fdump(SIGUSR1);
	    }
	    if (sighandled & GOT_SIGUSR2) {
		sighandled &= ~GOT_SIGUSR2;
		cdump(SIGUSR2);
	    }
	    if (sighandled & GOT_SIGALRM) {
		sighandled &= ~GOT_SIGALRM;
		timer(&dummysigalrm);
	    }
	}
	if ((n = select(nfds, &rfds, NULL, NULL, timeout)) < 0) {
	    if (errno != EINTR) /* SIGALRM is expected */
		logit(LOG_WARNING, errno, "select failed");
	    continue;
	}
	if (n > 0) {
	    /* TODO: shall check first igmp_socket for better performance? */
	    for (i = 0; i < nhandlers; i++) {
		if (FD_ISSET(ihandlers[i].fd, &rfds)) {
		    (*ihandlers[i].func)(ihandlers[i].fd, &rfds);
		}
	    }
	}
    
	/*
	 * Handle timeout queue.
	 *
	 * If select + packet processing took more than 1 second,
	 * or if there is a timeout pending, age the timeout queue.
	 *
	 * If not, collect usec in difftime to make sure that the
	 * time doesn't drift too badly.
	 *
	 * If the timeout handlers took more than 1 second,
	 * age the timeout queue again.  XXX This introduces the
	 * potential for infinite loops!
	 */
	do {
	    /*
	     * If the select timed out, then there's no other
	     * activity to account for and we don't need to
	     * call gettimeofday.
	     */
	    if (n == 0) {
		curtime.tv_sec = lasttime.tv_sec + secs;
		curtime.tv_usec = lasttime.tv_usec;
		n = -1;	/* don't do this next time through the loop */
	    } else
		gettimeofday(&curtime, NULL);
	    difftime.tv_sec = curtime.tv_sec - lasttime.tv_sec;
	    difftime.tv_usec += curtime.tv_usec - lasttime.tv_usec;
	    while (difftime.tv_usec >= 1000000) {
		difftime.tv_sec++;
		difftime.tv_usec -= 1000000;
	    }
	    if (difftime.tv_usec < 0) {
		difftime.tv_sec--;
		difftime.tv_usec += 1000000;
	    }
	    lasttime = curtime;
	    if (secs == 0 || difftime.tv_sec > 0)
		age_callout_queue(difftime.tv_sec);
	    secs = -1;
	} while (difftime.tv_sec > 0);
    } /* Main loop */

    logit(LOG_NOTICE, 0, "%s exiting", versionstring);
    cleanup();
    exit(0);
}
Beispiel #13
0
int main(int argc, char *argv[])
{
    register int recvlen;
    socklen_t dummy;
    struct timeval tv, difftime, curtime, lasttime, *timeout;
    int foreground = 0;
    fd_set rfds, readers;
    int nfds, n, i, secs, ch;
    struct sigaction sa;

    while ((ch = getopt(argc, argv, "fh")) != EOF) {
        switch (ch) {
        case 'f':
            foreground = 1;
            break;

        case 'h':
            usage();
            break;

        default:
            usage();
        }
    }

    argc -= optind;
    argv += optind;

    if (argc > 0)
        usage();

    if (geteuid() != 0) {
        fprintf(stderr, "%s: must be root\n", __progname);
        exit(1);
    }
    setlinebuf(stderr);

    callout_init();
    init_igmp();

    init_vifs();

    sa.sa_handler = handler;
    sa.sa_flags = 0;	/* Interrupt system calls */
    sigemptyset(&sa.sa_mask);
    sigaction(SIGHUP, &sa, NULL);
    sigaction(SIGTERM, &sa, NULL);
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGUSR1, &sa, NULL);
    sigaction(SIGUSR2, &sa, NULL);

    FD_ZERO(&readers);
    if (igmp_socket >= (int)FD_SETSIZE)
        logit("Descriptor too big");
    FD_SET(igmp_socket, &readers);
    nfds = igmp_socket + 1;
    for (i = 0; i < nhandlers; i++) {
        if (ihandlers[i].fd >= (int)FD_SETSIZE)
            logit("Descriptor too big");
        FD_SET(ihandlers[i].fd, &readers);
        if (ihandlers[i].fd >= nfds)
            nfds = ihandlers[i].fd + 1;
    }

    timer_setTimer(TIMER_INTERVAL, timer, NULL);

    if (!foreground) {
        /* Detach from the terminal */
        haveterminal = 0;
        if (fork())
            exit(0);
        (void)close(0);
        (void)close(1);
        (void)close(2);
        (void)open("/", 0);
        (void)dup2(0, 1);
        (void)dup2(0, 2);
    }

    /*
     * Main receive loop.
     */
    dummy = 0;
    difftime.tv_usec = 0;
    gettimeofday(&curtime, NULL);
    lasttime = curtime;
    for(;;) {
        memmove	((char *)&rfds,	(char *)&readers, sizeof(rfds));
        secs = timer_nextTimer();
        if (secs == -1)
            timeout = NULL;
        else {
            timeout = &tv;
            timeout->tv_sec = secs;
            timeout->tv_usec = 0;
        }
        if (sighandled) {
            if (sighandled & GOT_SIGINT) {
                sighandled &= ~GOT_SIGINT;
                break;
            }
        }
        if ((n = select(nfds, &rfds, NULL, NULL, timeout)) < 0) {
            if (errno != EINTR)
                logit("select failed");
            continue;
        }

        if (n > 0) {
            if (FD_ISSET(igmp_socket, &rfds)) {
                recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE, 0, NULL, &dummy);
                if (recvlen < 0) {
                    if (errno != EINTR) logit("recvfrom");
                    continue;
                }
                accept_igmp(recvlen);
            }

            for (i = 0; i < nhandlers; i++) {
                if (FD_ISSET(ihandlers[i].fd, &rfds)) {
                    (*ihandlers[i].func)(ihandlers[i].fd, &rfds);
                }
            }
        }

        /*
         * Handle timeout queue.
         *
         * If select + packet processing took more than 1 second,
         * or if there is a timeout pending, age the timeout queue.
         *
         * If not, collect usec in difftime to make sure that the
         * time doesn't drift too badly.
         *
         * If the timeout handlers took more than 1 second,
         * age the timeout queue again.  XXX This introduces the
         * potential for infinite loops!
         */
        do {
            /*
             * If the select timed out, then there's no other
             * activity to account for and we don't need to
             * call gettimeofday.
             */
            if (n == 0) {
                curtime.tv_sec = lasttime.tv_sec + secs;
                curtime.tv_usec = lasttime.tv_usec;
                n = -1;	/* don't do this next time through the loop */
            } else
                gettimeofday(&curtime, NULL);
            difftime.tv_sec = curtime.tv_sec - lasttime.tv_sec;
            difftime.tv_usec += curtime.tv_usec - lasttime.tv_usec;
            while (difftime.tv_usec > 1000000) {
                difftime.tv_sec++;
                difftime.tv_usec -= 1000000;
            }
            if (difftime.tv_usec < 0) {
                difftime.tv_sec--;
                difftime.tv_usec += 1000000;
            }
            lasttime = curtime;
            if (secs == 0 || difftime.tv_sec > 0)
                age_callout_queue(difftime.tv_sec);
            secs = -1;
        } while (difftime.tv_sec > 0);
    }
    cleanup();
    exit(0);
}
Beispiel #14
0
static void timer(void UNUSED *arg)
{
    query_groups();

    timer_setTimer(TIMER_INTERVAL, timer, NULL);
}