当前位置: 首页 > 工具软件 > xl2tpd > 使用案例 >

xl2tpd源码分析

罗渝
2023-12-01
1.软件版本:
       xl2tpd-devel-20151125.tar.gz

2.源码框架:

3.源码详解:

 
    xl2tpd源码的主函数非常简洁,具体代码如下:
File:xl2tpd.c
---------------------------------------------------------------------------------------
int main (int argc, char *argv[])
{
    init(argc,argv);           #NOTE:主要用于处理参数解析和配置文件解析
    dial_no_tmp = calloc (128, sizeof (char));
    network_thread ();
    return 0;
}

    在查看参数解析之前,我们先看看该应用程序的帮助:
# xl2tpd --help
xl2tpd version:  xl2tpd-1.3.6
Usage: xl2tpd [-c configfile ] [-s secrec_file] [-p pid_file] [-C control_file] [-D] [-l] [-v, --version]

    在分析源码之前,我们首先了解相关配置的数据结构。对xl2tpd而言,配置数据结构分为3部分,LNS配置,LAC配置,GLOBAL配置。
这些配置分别对应一个数据结构:
File: file.h
-------------------------------------------------------------------------------------
struct global
{
    unsigned int listenaddr;     /* IP address to bind to */ 
    int port;                           /* Port number to listen to */
    char authfile[STRLEN];      /* File containing authentication info */
    char altauthfile[STRLEN];   /* File containing authentication info */
    char configfile[STRLEN];    /* File containing configuration info */
    char altconfigfile[STRLEN]; /* File containing configuration info */
    char pidfile[STRLEN];        /* File containing the pid number*/
    char controlfile[STRLEN];   /* Control file name (named pipe) */
    int daemon;                      /* Use daemon mode? */
    int syslog;                        /* Use syslog for logging? */
    int accesscontrol;              /* Use access control? */
    int forceuserspace;           /* Force userspace? */
    int packet_dump;             /* Dump (print) all packets? */
    int debug_avp;                /* Print AVP debugging info? */
    int debug_network;          /* Print network debugging info? */
    int debug_tunnel;            /* Print tunnel debugging info? */
    int debug_state;              /* Print FSM debugging info? */
    int ipsecsaref;
    int sarefnum;               /* Value of IPSEC_REFINFO used by kernel (we used to pick 22, but 2.6.36+ took that, so now we pick 30)
                                       * Changed in SAref patch in openswan 2.6.36 for linux 2.6.36+ 
                                       */
};

struct lns
{
    struct lns *next;
    int exclusive;                   /* Only one tunnel per host? */
    int active;                       /* Is this actively in use? */
    unsigned int localaddr;     /* Local IP for PPP connections */
    int tun_rws;                    /* Receive window size (tunnel) */
    int call_rws;                    /* Call rws */
    int rxspeed;                    /* Tunnel rx speed */
    int txspeed;                    /* Tunnel tx speed */
    int hbit;                         /* Permit hidden AVP's? */
    int lbit;                          /* Use the length field? */
    int challenge;                 /* Challenge authenticate the peer? */
    int authpeer;                  /* Authenticate our peer? */
    int authself;                   /* Authenticate ourselves? */
    char authname[STRLEN];      /* Who we authenticate as */
    char peername[STRLEN];      /* Force peer name to this */
    char hostname[STRLEN];      /* Hostname to report */
    char entname[STRLEN];       /* Name of this entry */
    struct iprange *lacs;         /* Hosts permitted to connect */
    struct iprange *range;      /* Range of IP's we provide */
    int assign_ip;                  /* Do we actually provide IP addresses? */
    int passwdauth;              /* Authenticate by passwd file? (or PAM) */
    int pap_require;              /* Require PAP auth for PPP */
    int chap_require;            /* Require CHAP auth for PPP */
    int pap_refuse;              /* Refuse PAP authentication for us */
    int chap_refuse;            /* Refuse CHAP authentication for us */
    int idle;                        /* Idle timeout in seconds */
    unsigned int pridns;       /* Primary DNS server */
    unsigned int secdns;      /* Secondary DNS server */
    unsigned int priwins;      /* Primary WINS server */
    unsigned int secwins;     /* Secondary WINS server */
    int proxyarp;                 /* Use proxy-arp? */
    int proxyauth;               /* Allow proxy authentication? */
    int debug;                    /* Debug PPP? */
    int pass_peer;              /* Pass peer IP to pppd as ipparam? */
    char pppoptfile[STRLEN];    /* File containing PPP options */
    struct tunnel *t;                 /* Tunnel of this, if it's ready */
};

struct lac
{
    struct lac *next;
    struct host *lns;           /* LNS's we can connect to */
    struct schedule_entry *rsched;
    int tun_rws;                /* Receive window size (tunnel) */
    int call_rws;               /* Call rws */
    int rxspeed;                /* Tunnel rx speed */
    int txspeed;                /* Tunnel tx speed */
    int active;                 /* Is this connection in active use? */
    int hbit;                   /* Permit hidden AVP's? */
    int lbit;                   /* Use the length field? */
    int challenge;              /* Challenge authenticate the peer? */
    unsigned int localaddr;     /* Local IP address */
    unsigned int remoteaddr;    /* Force remote address to this */
    char authname[STRLEN];      /* Who we authenticate as */
    char password[STRLEN];      /* Password to authenticate with */
    char peername[STRLEN];      /* Force peer name to this */
    char hostname[STRLEN];      /* Hostname to report */
    char entname[STRLEN];       /* Name of this entry */
    int authpeer;               /* Authenticate our peer? */
    int authself;               /* Authenticate ourselves? */
    int pap_require;            /* Require PAP auth for PPP */
    int chap_require;           /* Require CHAP auth for PPP */
    int pap_refuse;             /* Refuse PAP authentication for us */
    int chap_refuse;            /* Refuse CHAP authentication for us */
    int idle;                   /* Idle timeout in seconds */
    int autodial;               /* Try to dial immediately? */
    int defaultroute;           /* Use as default route? */
    int redial;                 /* Redial if disconnected */
    int rmax;                   /* Maximum # of consecutive redials */
    int rtries;                 /* # of tries so far */
    int rtimeout;               /* Redial every this many # of seconds */
    int pass_peer;              /* Pass peer IP to pppd as ipparam? */
    char pppoptfile[STRLEN];    /* File containing PPP options */
    int debug;
    struct tunnel *t;           /* Our tunnel */
    struct call *c;             /* Our call */
};





    init()参数及配置解析具体源码如下:
File: xl2tpd.c
-----------------------------------------------------------------------------------------
void init (int argc,char *argv[])
{
    struct lac *lac;
    struct in_addr listenaddr;
    struct utsname uts; 

    init_args (argc,argv);             #NOTE:命令行参数初始化
    srand( time(NULL) );
    rand_source = 0; 
    init_addr ();
    if (init_config ())
    {    
        l2tp_log (LOG_CRIT, "%s: Unable to load config file\n", __FUNCTION__);
        exit (1); 
    }    
    if (uname (&uts)<0)
    {    
        l2tp_log (LOG_CRIT, "%s : Unable to determine host system\n",
                __FUNCTION__);
        exit (1); 
    }
    init_tunnel_list (&tunnels);
    if (init_network ())
        exit (1); 

    if (gconfig.daemon)
        daemonize ();

    consider_pidfile();

    signal (SIGTERM, &sigterm_handler);
    signal (SIGINT, &sigint_handler);
    signal (SIGCHLD, &sigchld_handler);
    signal (SIGUSR1, &sigusr1_handler);
    signal (SIGHUP, &sighup_handler);
    signal (SIGPIPE, SIG_IGN);
    init_scheduler ();

    unlink(gconfig.controlfile);
    mkfifo (gconfig.controlfile, 0600);

    open_controlfd();
    l2tp_log (LOG_INFO, "xl2tpd version " SERVER_VERSION " started on %s PID:%d\n",
            hostname, getpid ());
    l2tp_log (LOG_INFO,
            "Written by Mark Spencer, Copyright (C) 1998, Adtran, Inc.\n");
    l2tp_log (LOG_INFO, "Forked by Scott Balmos and David Stipp, (C) 2001\n");
    l2tp_log (LOG_INFO, "Inherited by Jeff McAdams, (C) 2002\n");
    l2tp_log (LOG_INFO, "Forked again by Xelerance (www.xelerance.com) (C) 2006\n");
    listenaddr.s_addr = gconfig.listenaddr;
    l2tp_log (LOG_INFO, "Listening on IP address %s, port %d\n",
            inet_ntoa(listenaddr), gconfig.port);
    lac = laclist;
    while (lac)
    {
        if (lac->autodial)
        {
#ifdef DEBUG_MAGIC
            l2tp_log (LOG_DEBUG, "%s: Autodialing '%s'\n", __FUNCTION__,
                    lac->entname[0] ? lac->entname : "(unnamed)");
#endif
            lac->active = -1;
            switch_io = 1;      /* If we're a LAC, autodials will be ICRQ's */
            magic_lac_dial (lac);
        }
        lac = lac->next;
    }
}

     xl2tpd中调用函数init_args()来解析和处理命令行参数,其具体源码如下:
File:xl2tpd.c
-------------------------------------------------------------------------------------------
void init_args(int argc, char *argv[])
{
    int i=0;

    gconfig.daemon=1;               #NOTE: 以damon模式运行
    gconfig.syslog=-1;                #NOTE: 关闭syslog
    memset(gconfig.altauthfile,0,STRLEN);
    memset(gconfig.altconfigfile,0,STRLEN);
    memset(gconfig.authfile,0,STRLEN);
    memset(gconfig.configfile,0,STRLEN);
    memset(gconfig.pidfile,0,STRLEN);
    memset(gconfig.controlfile,0,STRLEN);
    strncpy(gconfig.altauthfile,ALT_DEFAULT_AUTH_FILE,                   #NOTE:  #define ALT_DEFAULT_AUTH_FILE "/etc/l2tpd/l2tp-secrets"   file.h
            sizeof(gconfig.altauthfile) - 1);
    strncpy(gconfig.altconfigfile,ALT_DEFAULT_CONFIG_FILE,              #NOTE:  #define ALT_DEFAULT_CONFIG_FILE "/etc/l2tp/l2tpd.conf"   file.h
            sizeof(gconfig.altconfigfile) - 1);
    strncpy(gconfig.authfile,DEFAULT_AUTH_FILE,            #NOTE: #ifndef DEFAULT_AUTH_FILE  #define DEFAULT_AUTH_FILE "/etc/xl2tpd/l2tp-secrets"  #endif   file.h
            sizeof(gconfig.authfile) - 1);
    strncpy(gconfig.configfile,DEFAULT_CONFIG_FILE,      #NOTE: #ifndef DEFAULT_CONFIG_FILE #define DEFAULT_CONFIG_FILE "/etc/xl2tpd/xl2tpd.conf" #endif  file.h
            sizeof(gconfig.configfile) - 1);
    strncpy(gconfig.pidfile,DEFAULT_PID_FILE,                #NOTE: #define DEFAULT_PID_FILE "/var/run/xl2tpd.pid"  file.h
            sizeof(gconfig.pidfile) - 1);
    strncpy(gconfig.controlfile,CONTROL_PIPE,                #NOTE:#define CONTROL_PIPE "/var/run/xl2tpd/l2tp-control" l2tp.h
            sizeof(gconfig.controlfile) - 1);
    gconfig.ipsecsaref = 0;

    for (i = 1; i < argc; i++) {
        if ((! strncmp(argv[i],"--version",9))
                || (! strncmp(argv[i],"-v",2))) {
            printf("\nxl2tpd version:  %s\n",SERVER_VERSION);
            exit(1);
        }

        if(! strncmp(argv[i],"-c",2)) {
            if(++i == argc)
                usage();
            else
                strncpy(gconfig.configfile,argv[i],
                        sizeof(gconfig.configfile) - 1);
        }
        else if (! strncmp(argv[i],"-D",2)) {
            gconfig.daemon=0;
        }
        else if (! strncmp(argv[i],"-l",2)) {
            gconfig.syslog=1;
        }
        else if (! strncmp(argv[i],"-s",2)) {
            if(++i == argc)
                usage();
            else
                strncpy(gconfig.authfile,argv[i],
                        sizeof(gconfig.authfile) - 1);
        }
        else if (! strncmp(argv[i],"-p",2)) {
            if(++i == argc)
                usage();
            else
                strncpy(gconfig.pidfile,argv[i],
                        sizeof(gconfig.pidfile) - 1);
        }
        else if (! strncmp(argv[i],"-C",2)) {
            if(++i == argc)
                usage();
            else
                strncpy(gconfig.controlfile,argv[i],
                        sizeof(gconfig.controlfile) - 1);
        }
        else {
            usage();
        }
    }

    /*
     * defaults to syslog if no log facility was explicitly
     * specified and we are about to daemonize
     */
    if (gconfig.syslog < 0)
        gconfig.syslog = gconfig.daemon;
}

    xl2tpd中对配置文件的解释调用函数init_config()来完成,该函数原型如下:
File: file.c
----------------------------------------------------------------------------------------------------------------
int init_config ()
{
    FILE *f;
    int returnedValue;

    gconfig.port = UDP_LISTEN_PORT;            #NOTE: #define UDP_LISTEN_PORT  1701    l2ttp.h
    gconfig.sarefnum = IP_IPSEC_REFINFO; /* default use the latest we know */
    gconfig.listenaddr = htonl(INADDR_ANY);  #NOTE: 默认监听所有的IP地址
    gconfig.debug_avp = 0; 
    gconfig.debug_network = 0; 
    gconfig.packet_dump = 0; 
    gconfig.debug_tunnel = 0; 
    gconfig.debug_state = 0; 
    lnslist = NULL;
    laclist = NULL;
    deflac = (struct lac *) calloc (1, sizeof (struct lac));

    f = fopen (gconfig.configfile, "r");
    if (!f) 
    {    
        f = fopen (gconfig.altconfigfile, "r");
        if (f)
        {
             l2tp_log (LOG_WARNING, "%s: Using old style config files %s and %s\n",
                __FUNCTION__, gconfig.altconfigfile, gconfig.altauthfile);
            strncpy (gconfig.authfile, gconfig.altauthfile, 
                sizeof (gconfig.authfile));
        }
        else
        {
            l2tp_log (LOG_CRIT, "%s: Unable to open config file %s or %s\n",
                 __FUNCTION__, gconfig.configfile, gconfig.altconfigfile);
            return -1;
        }

    }    
    returnedValue = parse_config (f); 
    fclose (f); 
    return (returnedValue);
    filerr[0] = 0; 
}
 类似资料: