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; 
}

xl2tpd源码分析相关推荐

  1. 【Golang源码分析】Go Web常用程序包gorilla/mux的使用与源码简析

    目录[阅读时间:约10分钟] 一.概述 二.对比: gorilla/mux与net/http DefaultServeMux 三.简单使用 四.源码简析 1.NewRouter函数 2.HandleF ...

  2. SpringBoot-web开发(四): SpringMVC的拓展、接管(源码分析)

    [SpringBoot-web系列]前文: SpringBoot-web开发(一): 静态资源的导入(源码分析) SpringBoot-web开发(二): 页面和图标定制(源码分析) SpringBo ...

  3. SpringBoot-web开发(二): 页面和图标定制(源码分析)

    [SpringBoot-web系列]前文: SpringBoot-web开发(一): 静态资源的导入(源码分析) 目录 一.首页 1. 源码分析 2. 访问首页测试 二.动态页面 1. 动态资源目录t ...

  4. SpringBoot-web开发(一): 静态资源的导入(源码分析)

    目录 方式一:通过WebJars 1. 什么是webjars? 2. webjars的使用 3. webjars结构 4. 解析源码 5. 测试访问 方式二:放入静态资源目录 1. 源码分析 2. 测 ...

  5. Yolov3Yolov4网络结构与源码分析

    Yolov3&Yolov4网络结构与源码分析 从2018年Yolov3年提出的两年后,在原作者声名放弃更新Yolo算法后,俄罗斯的Alexey大神扛起了Yolov4的大旗. 文章目录 论文汇总 ...

  6. ViewGroup的Touch事件分发(源码分析)

    Android中Touch事件的分发又分为View和ViewGroup的事件分发,View的touch事件分发相对比较简单,可参考 View的Touch事件分发(一.初步了解) View的Touch事 ...

  7. View的Touch事件分发(二.源码分析)

    Android中Touch事件的分发又分为View和ViewGroup的事件分发,先来看简单的View的touch事件分发. 主要分析View的dispatchTouchEvent()方法和onTou ...

  8. MyBatis原理分析之四:一次SQL查询的源码分析

    上回我们讲到Mybatis加载相关的配置文件进行初始化,这回我们讲一下一次SQL查询怎么进行的. 准备工作 Mybatis完成一次SQL查询需要使用的代码如下: Java代码   String res ...

  9. [转]slf4j + log4j原理实现及源码分析

    slf4j + log4j原理实现及源码分析 转载于:https://www.cnblogs.com/jasonzeng888/p/6051080.html

  10. Spark源码分析之七:Task运行(一)

    在Task调度相关的两篇文章<Spark源码分析之五:Task调度(一)>与<Spark源码分析之六:Task调度(二)>中,我们大致了解了Task调度相关的主要逻辑,并且在T ...

最新文章

  1. 使用createrepo自建yum源
  2. Java 14 可能带来什么新特性?
  3. C语言/C++中怎么表示8进制数或者16进制数?(8进制数用数字0开头,16进制数用0x或者0X开头)
  4. Quartz.NET总结(四)Quartz 远程调度
  5. [深度学习] DeepFM 介绍与Pytorch代码解释
  6. 网络第八和九章要点总结
  7. 人人都可做 AI 开发者,云知声 AI 开放平台重磅上线
  8. jeecms 数据被引用,不能删除。解决办法
  9. c语言规定学号长度,c语言第1-9章基本概念练习题ans(最全).docx
  10. 可道云 docker 群晖_利用群晖NAS同步文献
  11. XMLSpy使用流程
  12. 谷歌地图api根据经纬度查询地名php,在线查询经纬度 google map查询地名返回经纬度 geocode geocoder的完整实例 代码下载...
  13. 生活技巧:过日子学着点
  14. Python-Django毕业设计钓鱼爱好者交流平台(程序+Lw)
  15. UNIX 进程揭秘--进程的生命周期
  16. dxf怎么用cad打开?CAD技巧分享
  17. 三轴机械手结构化编程5轴伺服项目
  18. mysql区间算法_「五大常用算法」一文图解分治算法和思想
  19. shell 抓取页面信息 ip168查询 IP归属地
  20. UVA11400(dp)

热门文章

  1. excel导入数据库的两种方式(js前端+C#后台)
  2. Xcode断点调试技巧
  3. 发改委:大多数城市已经放开放宽落户限制
  4. Elasticsearch8.1基于CentOS7.9的单机安装
  5. java.io.EOFException: SSL peer shut down incorrectly jdk1.8不支持TSLv1.3问题解决
  6. C# .aspx网页获取RFID读卡器HTTP协议提交的访问文件Request获得卡号、机号,Response回应驱动读卡器显示响声
  7. mysql 编译 性能_Icc编译MySQL性能调研
  8. php 修改某个字段的值,如何修改数据库表中的某一个字段的值呢?
  9. C#程序保存dump文件
  10. matlab 时间坐标轴,科学网-matlab作图——横坐标为时间轴的二维图-李娜娜的博文...