热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

xl2tpd源码分析

1.软件版本:xl2tpd-devel-20151125.tar.gz2.源码框架:3.源码详解:xl2tpd源码的主函数非常简洁,具体代码如下:File:xl2tp
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 &#61; gconfig.listenaddr;
    l2tp_log (LOG_INFO, "Listening on IP address %s, port %d\n",
            inet_ntoa(listenaddr), gconfig.port);
    lac &#61; laclist;
    while (lac)
    {
        if (lac->autodial)
        {
#ifdef DEBUG_MAGIC
            l2tp_log (LOG_DEBUG, "%s: Autodialing &#39;%s&#39;\n", __FUNCTION__,
                    lac->entname[0] ? lac->entname : "(unnamed)");
#endif
            lac->active &#61; -1;
            switch_io &#61; 1;      /* If we&#39;re a LAC, autodials will be ICRQ&#39;s */
            magic_lac_dial (lac);
        }
        lac &#61; lac->next;
    }
}



     xl2tpd中调用函数init_args()来解析和处理命令行参数&#xff0c;其具体源码如下:


File:xl2tpd.c
-------------------------------------------------------------------------------------------
void init_args(int argc, char *argv[])
{
    int i&#61;0;

    gconfig.daemon&#61;1;               #NOTE: 以damon模式运行
    gconfig.syslog&#61;-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 &#61; 0;

    for (i &#61; 1; 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(&#43;&#43;i &#61;&#61; argc)
                usage();
            else
                strncpy(gconfig.configfile,argv[i],
                        sizeof(gconfig.configfile) - 1);
        }
        else if (! strncmp(argv[i],"-D",2)) {
            gconfig.daemon&#61;0;
        }
        else if (! strncmp(argv[i],"-l",2)) {
            gconfig.syslog&#61;1;
        }
        else if (! strncmp(argv[i],"-s",2)) {
            if(&#43;&#43;i &#61;&#61; argc)
                usage();
            else
                strncpy(gconfig.authfile,argv[i],
                        sizeof(gconfig.authfile) - 1);
        }
        else if (! strncmp(argv[i],"-p",2)) {
            if(&#43;&#43;i &#61;&#61; argc)
                usage();
            else
                strncpy(gconfig.pidfile,argv[i],
                        sizeof(gconfig.pidfile) - 1);
        }
        else if (! strncmp(argv[i],"-C",2)) {
            if(&#43;&#43;i &#61;&#61; 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 &#61; gconfig.daemon;
}



    xl2tpd中对配置文件的解释调用函数init_config()来完成&#xff0c;该函数原型如下:


File: file.c
----------------------------------------------------------------------------------------------------------------
int init_config ()
{
    FILE *f;
    int returnedValue;

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

    f &#61; fopen (gconfig.configfile, "r");
    if (!f) 
    {    
        f &#61; 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 &#61; parse_config (f); 
    fclose (f); 
    return (returnedValue);
    filerr[0] &#61; 0; 
}

推荐阅读
  • 本文介绍了在CentOS上安装Python2.7.2的详细步骤,包括下载、解压、编译和安装等操作。同时提供了一些注意事项,以及测试安装是否成功的方法。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • 安装mysqlclient失败解决办法
    本文介绍了在MAC系统中,使用django使用mysql数据库报错的解决办法。通过源码安装mysqlclient或将mysql_config添加到系统环境变量中,可以解决安装mysqlclient失败的问题。同时,还介绍了查看mysql安装路径和使配置文件生效的方法。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • 树莓派Linux基础(一):查看文件系统的命令行操作
    本文介绍了在树莓派上通过SSH服务使用命令行查看文件系统的操作,包括cd命令用于变更目录、pwd命令用于显示当前目录位置、ls命令用于显示文件和目录列表。详细讲解了这些命令的使用方法和注意事项。 ... [详细]
author-avatar
huangbaihao54
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有