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

📄 igmpproxy.c

📁 igmp proxy 实现源码
💻 C
字号:
/***  igmpproxy - IGMP proxy based multicast router **  Copyright (C) 2005 Johnny Egeland <johnny@rlo.org>****  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****----------------------------------------------------------------------------****  This software is derived work from the following software. The original**  source code has been modified from it's original state by the author**  of igmpproxy.****  smcroute 0.92 - Copyright (C) 2001 Carsten Schill <carsten@cschill.de>**  - Licensed under the GNU General Public License, version 2**  **  mrouted 3.9-beta3 - COPYRIGHT 1989 by The Board of Trustees of **  Leland Stanford Junior University.**  - Original license can be found in the "doc/mrouted-LINCESE" file.***//***   igmpproxy.c - The main file for the IGMP proxy application.**   February 2005 - Johnny Egeland*/#include "defs.h"#include "version.h"#include "build.h"// Constantsstatic const char Version[] = "igmpproxy, Version " VERSION ", Build" BUILD "\n""Copyright 2005 by Johnny Egeland <johnny@rlo.org>\n""Distributed under the GNU GENERAL PUBLIC LICENSE, Version 2 - check GPL.txt\n""\n";static const char Usage[] = "usage: igmpproxy [-h] [-d] [-c <configfile>]\n""\n" "   -h   Display this help screen\n""   -c   Specify a location for the config file (default is '/etc/igmpproxy.conf').\n""   -d   Run in debug mode. Does not fork deamon, and output all logmessages on stderr.\n""\n";// Local function Prototypesstatic void signalHandler(int);int     igmpProxyInit();void    igmpProxyCleanUp();void    igmpProxyRun();// Global vars...static int sighandled = 0;#define	GOT_SIGINT	0x01#define	GOT_SIGHUP	0x02#define	GOT_SIGUSR1	0x04#define	GOT_SIGUSR2	0x08// The upstream VIF indexint         upStreamVif;   /***   Program main method. Is invoked when the program is started*   on commandline. The number of commandline arguments, and a*   pointer to the arguments are recieved on the line...*/    int main( int ArgCn, const char *ArgVc[] ) {    int debugMode = 0;    // Set the default config Filepath...    char* configFilePath = IGMPPROXY_CONFIG_FILEPATH;    // Display version     fputs( Version, stderr );    // Parse the commandline options and setup basic settings..    int i = 1;    while (i < ArgCn) {        if ( strlen(ArgVc[i]) > 1 && ArgVc[i][0] == '-') {            switch ( ArgVc[i][1] ) {            case 'h':                fputs( Usage, stderr );                exit( 0 );            case 'd':                Log2Stderr = LOG_DEBUG;                /*            case 'v':                // Enable debug mode...                if (Log2Stderr < LOG_INFO) {                    Log2Stderr = LOG_INFO;                }                */                debugMode = 1;                break;            case 'c':                // Get new filepath...                if (i + 1 < ArgCn && ArgVc[i+1][0] != '-') {                    configFilePath = ArgVc[i+1];                    i++;                } else {                    log(LOG_ERR, 0, "Missing config file path after -c option.");                }                break;            }        }        i++;    }    // Chech that we are root    if (geteuid() != 0) {    	fprintf(stderr, "igmpproxy: must be root\n");    	exit(1);    }    // Write debug notice with file path...    IF_DEBUG log(LOG_DEBUG, 0, "Searching for config file at '%s'" , configFilePath);    do {        // Loads the config file...        if( ! loadConfig( configFilePath ) ) {            log(LOG_ERR, 0, "Unable to load config file...");            break;        }            // Initializes the deamon.        if ( !igmpProxyInit() ) {            log(LOG_ERR, 0, "Unable to initialize IGMPproxy.");            break;        }                // If not in debug mode, fork and detatch from terminal.        if ( ! debugMode ) {                IF_DEBUG log( LOG_DEBUG, 0, "Starting daemon mode.");                // Only daemon goes past this line...            if (fork()) exit(0);                // Detach deamon from terminal            if ( close( 0 ) < 0 || close( 1 ) < 0 || close( 2 ) < 0                  || open( "/dev/null", 0 ) != 0 || dup2( 0, 1 ) < 0 || dup2( 0, 2 ) < 0                 || setpgrp() < 0               ) {                log( LOG_ERR, errno, "failed to detach deamon" );            }        }                // Go to the main loop.        igmpProxyRun();            // Clean up        igmpProxyCleanUp();    } while ( FALSE );    // Inform that we are exiting.    log(LOG_INFO, 0, "Shutdown complete....");    exit(0);}/***   Handles the initial startup of the daemon.*/int igmpProxyInit() {    struct sigaction sa;    int Err;    sa.sa_handler = signalHandler;    sa.sa_flags = 0;    /* Interrupt system calls */    sigemptyset(&sa.sa_mask);    sigaction(SIGTERM, &sa, NULL);    sigaction(SIGINT, &sa, NULL);    // Loads configuration for Physical interfaces...    buildIfVc();            // Configures IF states and settings    configureVifs();    switch ( Err = enableMRouter() ) {    case 0: break;    case EADDRINUSE: log( LOG_ERR, EADDRINUSE, "MC-Router API already in use" ); break;    default: log( LOG_ERR, Err, "MRT_INIT failed" );    }    /* create VIFs for all IP, non-loop interfaces     */    {        unsigned Ix;        struct IfDesc *Dp;        int     vifcount = 0;        upStreamVif = -1;        for ( Ix = 0; Dp = getIfByIx( Ix ); Ix++ ) {            if ( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) ) {                if(Dp->state == IF_STATE_UPSTREAM) {                    if(upStreamVif == -1) {                        upStreamVif = Ix;                    } else {                        log(LOG_ERR, 0, "Vif #%d was already upstream. Cannot set VIF #%d as upstream as well.",                            upStreamVif, Ix);                    }                }                addVIF( Dp );                vifcount++;            }        }        // If there is only one VIF, or no defined upstream VIF, we send an error.        if(vifcount < 2 || upStreamVif < 0) {            log(LOG_ERR, 0, "There must be at least 2 Vif's where one is upstream.");        }    }          // Initialize IGMP    initIgmp();    // Initialize Routing table    initRouteTable();    // Initialize timer    callout_init();    return 1;}/***   Clean up all on exit...*/void igmpProxyCleanUp() {    log( LOG_DEBUG, 0, "clean handler called" );        free_all_callouts();    // No more timeouts.    clearAllRoutes();       // Remove all routes.    disableMRouter();       // Disable the multirout API}/***   Main daemon loop.*/void igmpProxyRun() {    // Get the config.    //struct Config *config = getCommonConfig();    // Set some needed values.    register int recvlen;    int     MaxFD, Rt, secs;    fd_set  ReadFDS;    int     dummy = 0;    struct  timeval  curtime, lasttime, difftime, tv;     // The timeout is a pointer in order to set it to NULL if nessecary.    struct  timeval  *timeout = &tv;    // Initialize timer vars    difftime.tv_usec = 0;    gettimeofday(&curtime, NULL);    lasttime = curtime;    // First thing we send a membership query in downstream VIF's...    sendGeneralMembershipQuery();    // Loop until the end...    for (;;) {        // Process signaling...        if (sighandled) {            if (sighandled & GOT_SIGINT) {                sighandled &= ~GOT_SIGINT;                log(LOG_NOTICE, 0, "Got a interupt signal. Exiting.");                break;            }        }        // Prepare timeout...        secs = timer_nextTimer();        if(secs == -1) {            timeout = NULL;        } else {            timeout->tv_usec = 0;            timeout->tv_sec = secs;        }        // Prepare for select.        MaxFD = MRouterFD;        FD_ZERO( &ReadFDS );        FD_SET( MRouterFD, &ReadFDS );        // wait for input        Rt = select( MaxFD +1, &ReadFDS, NULL, NULL, timeout );        // log and ignore failures        if( Rt < 0 ) {            log( LOG_WARNING, errno, "select() failure" );            continue;        }        else if( Rt > 0 ) {            // Read IGMP request, and handle it...            if( FD_ISSET( MRouterFD, &ReadFDS ) ) {                    recvlen = recvfrom(MRouterFD, recv_buf, RECV_BUF_SIZE,                                   0, NULL, &dummy);                if (recvlen < 0) {                    if (errno != EINTR) log(LOG_ERR, errno, "recvfrom");                    continue;                }                                acceptIgmp(recvlen);            }        }        // At this point, we can handle timeouts...        do {            /*             * If the select timed out, then there's no other             * activity to account for and we don't need to             * call gettimeofday.             */            if (Rt == 0) {                curtime.tv_sec = lasttime.tv_sec + secs;                curtime.tv_usec = lasttime.tv_usec;                Rt = -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);    }}/* * Signal handler.  Take note of the fact that the signal arrived * so that the main loop can take care of it. */static void signalHandler(int sig) {    switch (sig) {    case SIGINT:    case SIGTERM:        sighandled |= GOT_SIGINT;        break;        /* XXX: Not in use.        case SIGHUP:            sighandled |= GOT_SIGHUP;            break;            case SIGUSR1:            sighandled |= GOT_SIGUSR1;            break;            case SIGUSR2:            sighandled |= GOT_SIGUSR2;            break;        */    }}

⌨️ 快捷键说明

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