udhcp源码剖析(二)——DHCP服务器重要的数据结构

程序=算法+数据结构,数据结构是了解DHCP服务器的代码的重要途径。通过分析DHCP服务器的主要数据结构,可以深入了解DHCP服务器的工作流程和实现原理。

dhcpMessage

定义在packet.h的struct dhcpMessage是DHCP报文的格式,包括了协议中所定义的所有DHCP报文所定义的内容,如下所示。

struct dhcpMessage {
    u_int8_t op;
    u_int8_t htype;
    u_int8_t hlen;
    u_int8_t hops;
    u_int32_t xid;
    u_int16_t secs;
    u_int16_t flags;
    u_int32_t ciaddr;
    u_int32_t yiaddr;
    u_int32_t siaddr;
    u_int32_t giaddr;
    u_int8_t chaddr[16];
    u_int8_t sname[64];
    u_int8_t file[128];
    u_int32_t cookie;
    u_int8_t options[308]; /* 312 - cookie */ 
};

Struct中的数据主要是根据RFC2131定义的,RFC中的定义如下,在32位机中采用4字节对齐。

FIELD OCTETS DESCRIPTION
op 1 Message op code / message type. 1 = BOOTREQUEST, 2 = BOOTREPLY
htype 1 Hardware address type, see ARP section in “Assigned Numbers” RFC; e.g., ’1’ = 10mb ethernet.
hlen 1 Hardware address length (e.g. ’6’ for 10mb ethernet).
hops 1 Client sets to zero, optionally used by relay agents when booting via a relay agent.
xid 4 Transaction ID, a random number chosen by the client, used by the client and server to associate messages and responses between a client and a server.
secs 2 Filled in by client, seconds elapsed since client began address acquisition or renewal process.
flags 2 Flags (see figure 2).
ciaddr 4 Client IP address; only filled in if client is in BOUND, RENEW or REBINDING state and can respond to ARP requests.
yiaddr 4 ’your’ (client) IP address.
siaddr 4 IP address of next server to use in bootstrap; returned in DHCPOFFER, DHCPACK by server.
giaddr 4 Relay agent IP address, used in booting via a relay agent.
chaddr 16 Client hardware address.
sname 64 Optional server host name, null terminated string.
file 128 Boot file name, null terminated string; “generic” name or null in DHCPDISCOVER, fully qualified directory-path name in DHCPOFFER.
options var Optional parameters field. See the options documents for a list of defined options.

options字段(包含cookie)的最大长度是312(308+4),包含三类信息,

  • DHCP_PADDING,填充字节
  • DHCP_END,选项结束字节
  • 选项信息(code(1 Byte)+length(1 Byte)+value(1~306 Byte)

Options允许厂商定义选项(Vendor-specific Area),已提供更多的设定信息,如network,gateway,DNS等。其长度可变,同事可携带多个选项。其选项信息的格式CLV完全兼容BOOTP。RFC2132文档给出所有支持选项的OPT_CODE,和可以确定长度的OPT_LEN的值

Server_config_t

Server_config_t在dhcpd.h中定义,贯穿整个server程序。该struct的字段基本都在定义时备注。

struct server_config_t {
    u_int32_t server;       // Our IP, in network order 
    u_int32_t start;        /* Start address of leases, network order,DHCP地址池起始地址,网络字节序 */
    u_int32_t end;          /* End of leases, network order ,DHCP地址池终止地址,网络字节序*/
    struct option_set *options; /* List of DHCP options loaded from the config file */
    char *interface;        /* The name of the interface to use */
    int ifindex;            /* Index number of the interface to use */
    unsigned char arp[6];       /* Our arp address */
    unsigned long lease;        /* lease time in seconds (host order) */
    unsigned long max_leases;   /* maximum number of leases (including reserved address) */
    char remaining;         /* should the lease file be interpreted as lease time remaining, or as the time the lease expires */
    unsigned long auto_time;    /* how long should udhcpd wait before writing a config file. if this is zero, it will only write one on SIGUSR1 */
    unsigned long decline_time;     /* how long an address is reserved if a client returns a decline message */
    unsigned long conflict_time;    /* how long an arp conflict offender is leased for */
    unsigned long offer_time;   /* how long an offered address is reserved */
    unsigned long min_lease;    /* minimum lease a client can request*/
    char *lease_file;
    char *pidfile;
    char *notify_file;      /* What to run whenever leases are written */
    u_int32_t siaddr;       /* next server bootp option */
    char *sname;            /* bootp server name */
    char *boot_file;        /* bootp boot file option */
    struct static_lease *static_leases; /* List of ip/mac pairs to assign static leases */
};  

server_config_t中有几个比较重要或复杂的成员:

  • Start和end:分别表示DHCP地址池的起始地址和终止地址
  • option_set:选项集合,从配置文件载入的DHCP选项的集合。根据dhcpMessage报文里的选项字段填写赋值。集合里每个节点是一个选项信息,数据根据CLV方式组织,通过链表将一个一个节点链接起来。
struct option_set {
    unsigned char *data;        //CLV方式组织
    struct option_set *next;
};
  • remaining:lease值被解释为剩下的lease时间(true,default,主要针对无法再重启后保持时间的嵌入式系统而言),还是lease超时的绝对时刻(false)
  • lease和max_leases:设定的租约时间(单位秒,主机字节序)和最大允许的租约数目。
  • auto_time、decline_time、conflict_time和offer_time:
  • auto_time:在写一个config文件之前需要等待的时间,如果为0,则将只在接收SIGUSR1信号时写。
  • decline_time:在客户端返回一个decline消息后,地址被保留的时间。Server发送OFFER报文给客户端提供一个IP,client检测IP已被使用或其他原因拒绝使用该IP,发送DECLINE报文,server接收到该报文后,把IP添加到动态租赁数组,租赁期就是decline_time,对应MAC为blank_chaddr(实际值全为0),表示该IP在decline_time内不可用,黑户。
  • conflict_time:一个ARP冲突offender被租用的时间。Serve在IP地址池找到一个free IP是,检测到该IP已被使用,则会把IP添加到动态租赁数组,租期就是conflict_time。(即检测到IP冲突后,该检测结果有效的时间——自己的理解)
  • offer_time:服务器发送完OFFER之后,在接收到REQUEST之前,提供的地址在动态租赁表里被保留的时间,默认是60s,在接收到REQUEST之后,会把租赁时间修改为请求的租赁时间。
  • struct static_lease *static_leases:用于分配静态租约的IP/MAC对的列表。因为DHCP允许手动配置IP,所以server端通过该结构管理手动配置的IP。
struct static_lease {
    struct static_lease *next;
    uint8_t *mac;
    uint32_t *ip;
};

在dhcpd.c文件中声明了一个struct server_config_t的全局变量server_config,该变量参与了server对于client的基本所有响应和配置。
2.1.3 struct dhcpOfferedAddr
server对于租赁出去的IP的管理基于该结构

struct dhcpOfferedAddr {
    u_int8_t chaddr[16];    /* client’s mac address */
    u_int32_t yiaddr;       /* leased IP address by client, network order */
    u_int32_t expires;  /* lease time for lease IP address, host order */
    char hostname[64];
};

Expires是未来的一个时间点,从1970年1月1日零时开始到租赁到期时刻的秒数,使用uint32_t声明,主机字节序存储。
在dhcpd.c里定义一个指向struct dhcpOfferedAddr的全局指针变量leases,leases指向的数组大小由dhcpOfferedAddr结构体大小和max_leases大小决定。

leases = malloc(sizeof(struct dhcpOfferedAddr) * server_config.max_leases);

你可能感兴趣的:(linux,通讯协议,C语言)