在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            博客專欄

            EEPW首頁 > 博客 > Busybox udhcpc:自動識別ip配置以及流程解析

            Busybox udhcpc:自動識別ip配置以及流程解析

            發(fā)布人:電子禪石 時間:2023-05-06 來源:工程師 發(fā)布文章

            udhcpc來自于Busybox,基于DHCP服務(wù),達到自動配置IP的功能。

            下面分別介紹如何配置udhcpc,以及udhcpc是如何達到自動配置IP功能的。

            1. 配置udhcpc1.1 配置kernel支持DHCP

            進入Networking -> Networking options -> TCP/IP networking,選擇IP: DHCP support。


            1.2 配置udhcpc

            進入Networking Utilities -> udhcpc (DHCP client)。



            1.3 啟動udhcpc

            在/etc/init.d/rcS中啟動udhcpc。

             #
             # To config network
             #
            udhcpc
            1.4 udhcpc使用說明

            復(fù)制代碼

            BusyBox v1.27.2 (2020-08-25 12:39:58 CST) multi-call binary.
            
            Usage: udhcpc [-fbqRB] [-a[MSEC]] [-t N] [-T SEC] [-A SEC/-n]
                    [-i IFACE] [-s PROG] [-p PIDFILE]
                    [-oC] [-r IP] [-V VENDOR] [-F NAME] [-x OPT:VAL]... [-O OPT]...        -i,--interface IFACE    Interface to use (default eth0)        -s,--script PROG        Run PROG at DHCP events (default /usr/share/udhcpc/default.script)        -p,--pidfile FILE       Create pidfile        -B,--broadcast          Request broadcast replies        -t,--retries N          Send up to N discover packets (default 3)        -T,--timeout SEC        Pause between packets (default 3)        -A,--tryagain SEC       Wait if lease is not obtained (default 20)        -n,--now                Exit if lease is not obtained        -q,--quit               Exit after obtaining lease        -R,--release            Release IP on exit        -f,--foreground         Run in foreground        -b,--background         Background if lease is not obtained        -S,--syslog             Log to syslog too        -a[MSEC],--arping[=MSEC] Validate offered address with ARP ping        -r,--request IP         Request this IP address        -o,--no-default-options Don't request any options (unless -O is given)
                    -O,--request-option OPT Request option OPT from server (cumulative)        -x OPT:VAL              Include option OPT in sent packets (cumulative)
                                            Examples of string, numeric, and hex byte opts:                                -x hostname:bbox - option 12
                                            -x lease:3600 - option 51 (lease time)                                -x 0x3d:0100BEEFC0FFEE - option 61 (client id)        -F,--fqdn NAME          Ask server to update DNS mapping for NAME        -V,--vendorclass VENDOR Vendor identifier (default 'udhcp VERSION')        -C,--clientid-none      Don't send MAC as client identifierSignals:
                    USR1    Renew lease
                    USR2    Release lease

            復(fù)制代碼

            2. 流程解析

            整個udhcpc的框架是可執(zhí)行文件udhcpc、腳本文件/usr/share/udhcpc/default.script、DNS配置文件/etc/resolv.conf。

            入口是udhcpc,然后udhcpc調(diào)用shell腳本default.script中的deconfig/leasefail/bound/renew/nak等選項,resolv.conf存放DNS配置文件。

            2.1 Kernel DHCP相關(guān)

            DHCP在內(nèi)核中是IP Autocofig dispatcher一部分,入口在ip_auto_config()。

            內(nèi)核負責(zé)將udhcpc發(fā)送的DHCP請求通過對應(yīng)的網(wǎng)絡(luò)設(shè)備發(fā)送出去,并將接受到的數(shù)據(jù)解析返回給udhcpc。

            復(fù)制代碼

            static int __init ip_auto_config(void)
            {...    if (ic_myaddr == NONE ||...
                    ic_first_dev->next) {
            #ifdef IPCONFIG_DYNAMIC        if (ic_dynamic() < 0) {
                        ic_close_devs();...        }#else /* !DYNAMIC */...#endif /* IPCONFIG_DYNAMIC */
                } else {...
                }...
            }static int __init ic_dynamic(void)
            {...#ifdef IPCONFIG_BOOTP    if (do_bootp)
                    ic_bootp_init();------------------------初始化DHCP/BOOTP相關(guān),主要是注冊處理從服務(wù)器接收到的DHCP/BOOTP回復(fù)。#endif#ifdef IPCONFIG_RARP    if (do_rarp)
                    ic_rarp_init();#endif...    for (;;) {
            #ifdef IPCONFIG_BOOTP        if (do_bootp && (d->able & IC_BOOTP))
                        ic_bootp_send_if(d, jiffies - start_jiffies);---發(fā)送DHCP/BOOTP請求到d網(wǎng)絡(luò)設(shè)備。#endif...        if (!d->next) {
                        jiff = jiffies + timeout;            while (time_before(jiffies, jiff) && !ic_got_reply)
                            schedule_timeout_uninterruptible(1);
                    }
            #ifdef IPCONFIG_DHCP        /* DHCP isn't done until we get a DHCPACK. */
                    if ((ic_got_reply & IC_BOOTP) &&
                        (ic_proto_enabled & IC_USE_DHCP) &&
                        ic_dhcp_msgtype != DHCPACK) {
                        ic_got_reply = 0;            /* continue on device that got the reply */
                        d = ic_dev;
                        pr_cont(",");            continue;
                    }#endif /* IPCONFIG_DHCP */...
                }...
            }

            復(fù)制代碼

             

            ic_bootp_send_if()通過d指定的網(wǎng)絡(luò)設(shè)備發(fā)送socket DHCP/BOOTP請求。

            復(fù)制代碼

            /*
             *  Send DHCP/BOOTP request to single interface. */static void __init ic_bootp_send_if(struct ic_device *d, unsigned long jiffies_diff)
            {    struct net_device *dev = d->dev;    struct sk_buff *skb;    struct bootp_pkt *b;    struct iphdr *h;    int hlen = LL_RESERVED_SPACE(dev);    int tlen = dev->needed_tailroom;    /* Allocate packet */
                skb = alloc_skb(sizeof(struct bootp_pkt) + hlen + tlen + 15,
                        GFP_KERNEL);--------------------------分配skb,下面逐漸填充內(nèi)容。    if (!skb)        return;
                skb_reserve(skb, hlen);
                b = (struct bootp_pkt *) skb_put(skb, sizeof(struct bootp_pkt));
                memset(b, 0, sizeof(struct bootp_pkt));    /* Construct IP header */
                skb_reset_network_header(skb);
                h = ip_hdr(skb);
                h->version = 4;
                h->ihl = 5;
                h->tot_len = htons(sizeof(struct bootp_pkt));
                h->frag_off = htons(IP_DF);
                h->ttl = 64;
                h->protocol = IPPROTO_UDP;
                h->daddr = htonl(INADDR_BROADCAST);
                h->check = ip_fast_csum((unsigned char *) h, h->ihl);    /* Construct UDP header */
                b->udph.source = htons(68);
                b->udph.dest = htons(67);
                b->udph.len = htons(sizeof(struct bootp_pkt) - sizeof(struct iphdr));    /* UDP checksum not calculated -- explicitly allowed in BOOTP RFC */
            
                /* Construct DHCP/BOOTP header */
                b->op = BOOTP_REQUEST;    if (dev->type < 256) /* check for false types */
                    b->htype = dev->type;    else if (dev->type == ARPHRD_FDDI)
                    b->htype = ARPHRD_ETHER;    else {
                    pr_warn("Unknown ARP type 0x%04x for device %s\n", dev->type,
                        dev->name);
                    b->htype = dev->type; /* can cause undefined behavior */
                }    /* server_ip and your_ip address are both already zero per RFC2131 */
                b->hlen = dev->addr_len;
                memcpy(b->hw_addr, dev->dev_addr, dev->addr_len);
                b->secs = htons(jiffies_diff / HZ);
                b->xid = d->xid;    /* add DHCP options or BOOTP extensions */#ifdef IPCONFIG_DHCP    if (ic_proto_enabled & IC_USE_DHCP)
                    ic_dhcp_init_options(b->exten, d);---------構(gòu)建DHCP附加內(nèi)容。    else#endif
                    ic_bootp_init_ext(b->exten);    /* Chain packet down the line... */
                skb->dev = dev;
                skb->protocol = htons(ETH_P_IP);    if (dev_hard_header(skb, dev, ntohs(skb->protocol),
                            dev->broadcast, dev->dev_addr, skb->len) < 0) {
                    kfree_skb(skb);
                    printk("E");        return;
                }    if (dev_queue_xmit(skb) < 0)-------------------發(fā)送skb。
                    printk("E");
            }

            復(fù)制代碼

             

            2.2 udhcpc解析

            和DHCP服務(wù)交互的狀態(tài)如下:

            復(fù)制代碼

            /* initial state: (re)start DHCP negotiation */#define INIT_SELECTING  0/* discover was sent, DHCPOFFER reply received */#define REQUESTING      1/* select/renew was sent, DHCPACK reply received */#define BOUND           2/* half of lease passed, want to renew it by sending unicast renew requests */#define RENEWING        3/* renew requests were not answered, lease is almost over, send broadcast renew */#define REBINDING       4/* manually requested renew (SIGUSR1) */#define RENEW_REQUESTED 5/* release, possibly manually requested (SIGUSR2) */#define RELEASED        6

            復(fù)制代碼

            udhcpc遵循DHCP協(xié)議和DHCP服務(wù)器進行交互,通過狀態(tài)機來解析從DHCP服務(wù)器獲取的packet。

            復(fù)制代碼

             udhcpc_main( argc UNUSED_PARAM,  ** (udhcp_read_interface(client_config.& =...     pollfd pfds[== timeout -= 
                     (tv > == poll(pfds, , tv < INT_MAX/ ? tv *  (retval < 
                             (errno ==+= (unsigned)monotonic_sec() -
                     (retval ==              (udhcp_read_interface(client_config.& ret0; =  (!discover_retries || packet_num < (packet_num == ==++ BB_MMU /* -b is not supported on NOMMU */                 (opt & OPT_b) { = ((opt & ~OPT_b) |
                             (opt & OPT_n) { = ==  (packet_num < =++=== ; 
                         RENEW_REQUESTED:  (timeout > >>= =
                        
                             (timeout >  >>= == ; 
                            = =; 
            
                    
                     (listen_mode == LISTEN_NONE || !pfds[; 
                         (listen_mode === udhcp_recv_kernel_packet(&= udhcp_recv_raw_packet(& (len == -+= (unsigned)monotonic_sec() - (len <  (packet.xid !=
                     (packet.hlen != 
                     || memcmp(packet.chaddr, client_config.client_mac, ) != 
                        log1(); 
                        = udhcp_get_option(& (message ==
                         (*message ==*= = udhcp_get_option(& (!=== = =  (*message ==*= udhcp_get_option(& (!=  * =
                                 (lease_seconds < =  (lease_seconds >  / =  / 
                            ===&packet, state == REQUESTING ?  : = (unsigned)monotonic_sec() -= lease_seconds /  ((unsigned)timeout <= already_waited_sec = = (opt & OPT_q) { 
                                &= ~ BB_MMU /* NOMMU case backgrounded earlier */                 (!(opt &= ((opt & ~OPT_b) |
                            
                            
            
                            ;  (*message ==
                             (server_addr != *= udhcp_get_option(& (!
                                         (svid !=, &packet,  (state !=); == ; = = = = 
                     (opt & OPT_R) =

            復(fù)制代碼

            udhcp_run_script()是udhcpc和default.script的接口,通過udhcp_run_script()即可調(diào)用其中一部分腳本。

            復(fù)制代碼

            /* Call a script with a par file and env vars */static void udhcp_run_script(struct dhcp_packet *packet, const char *name)
            {    char **envp, **curr;    char *argv[3];
            
                envp = fill_envp(packet);----------將options以及packet中的內(nèi)容導(dǎo)出到shell環(huán)境變量中,下面執(zhí)行shell的過程中使用。    /* call script */
                log1("executing %s %s", client_config.script, name);
                argv[0] = (char*) client_config.script;
                argv[1] = (char*) name;
                argv[2] = NULL;
                spawn_and_wait(argv);    for (curr = envp; *curr; curr++) {
                    log2(" %s", *curr);
                    bb_unsetenv_and_free(*curr);
                }
                free(envp);
            }/* put all the parameters into the environment */static char **fill_envp(struct dhcp_packet *packet)
            {    int envc;    int i;    char **envp, **curr;    const char *opt_name;
                uint8_t *temp;
                uint8_t overload = 0;#define BITMAP unsigned#define BBITS (sizeof(BITMAP) * 8)#define BMASK(i) (1 << (i & (sizeof(BITMAP) * 8 - 1)))#define FOUND_OPTS(i) (found_opts[(unsigned)i / BBITS])
                BITMAP found_opts[256 / BBITS];
            
                memset(found_opts, 0, sizeof(found_opts));    /* We need 6 elements for:
                 * "interface=IFACE"
                 * "ip=N.N.N.N" from packet->yiaddr
                 * "siaddr=IP" from packet->siaddr_nip (unless 0)
                 * "boot_file=FILE" from packet->file (unless overloaded)
                 * "sname=SERVER_HOSTNAME" from packet->sname (unless overloaded)
                 * terminating NULL     */
                envc = 6;    /* +1 element for each option, +2 for subnet option: */
                if (packet) {        /* note: do not search for "pad" (0) and "end" (255) options *///TODO: change logic to scan packet _once_
                    for (i = 1; i < 255; i++) {
                        temp = udhcp_get_option(packet, i);            if (temp) {                if (i == DHCP_OPTION_OVERLOAD)
                                overload |= *temp;                else if (i == DHCP_SUBNET)
                                envc++; /* for $mask */
                            envc++;                /*if (i != DHCP_MESSAGE_TYPE)*/
                            FOUND_OPTS(i) |= BMASK(i);
                        }
                    }
                }
                curr = envp = xzalloc(sizeof(envp[0]) * envc);    *curr = xasprintf("interface=%s", client_config.interface);
                putenv(*curr++);    if (!packet)        return envp;    /* Most important one: yiaddr as $ip */
                *curr = xmalloc(sizeof("ip=255.255.255.255"));
                sprint_nip(*curr, "ip=", (uint8_t *) &packet->yiaddr);
                putenv(*curr++);    if (packet->siaddr_nip) {        /* IP address of next server to use in bootstrap */
                    *curr = xmalloc(sizeof("siaddr=255.255.255.255"));
                    sprint_nip(*curr, "siaddr=", (uint8_t *) &packet->siaddr_nip);
                    putenv(*curr++);
                }    if (!(overload & FILE_FIELD) && packet->file[0]) {        /* watch out for invalid packets */
                    *curr = xasprintf("boot_file=%."DHCP_PKT_FILE_LEN_STR"s", packet->file);
                    putenv(*curr++);
                }    if (!(overload & SNAME_FIELD) && packet->sname[0]) {        /* watch out for invalid packets */
                    *curr = xasprintf("sname=%."DHCP_PKT_SNAME_LEN_STR"s", packet->sname);
                    putenv(*curr++);
                }    /* Export known DHCP options */
                opt_name = dhcp_option_strings;
                i = 0;    while (*opt_name) {
                    uint8_t code = dhcp_optflags[i].code;
                    BITMAP *found_ptr = &FOUND_OPTS(code);
                    BITMAP found_mask = BMASK(code);        if (!(*found_ptr & found_mask))            goto next;        *found_ptr &= ~found_mask; /* leave only unknown options */
                    temp = udhcp_get_option(packet, code);        *curr = xmalloc_optname_optval(temp, &dhcp_optflags[i], opt_name);---將optname和value導(dǎo)出到shell環(huán)境變量中。
                    putenv(*curr++);        if (code == DHCP_SUBNET) {            /* Subnet option: make things like "$ip/$mask" possible */
                        uint32_t subnet;
                        move_from_unaligned32(subnet, temp);            *curr = xasprintf("mask=%u", mton(subnet));
                        putenv(*curr++);
                    }
             next:
                    opt_name += strlen(opt_name) + 1;
                    i++;
                }...    return envp;
            }

            復(fù)制代碼

             2.3 default.script腳本解析

            default.script是udhcpc的延伸,方便靈活的實現(xiàn)udhcpc的功能。

            復(fù)制代碼

            #!/bin/sh
            
            # udhcpc script edited by Tim Riker <[email protected]>[ -z "$1" ] && echo "Error: should be called from udhcpc" && exit 1RESOLV_CONF="/etc/resolv.conf"[ -e $RESOLV_CONF ] || touch $RESOLV_CONF
            [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"[ -n "$subnet" ] && NETMASK="netmask $subnet"case "$1" in    deconfig)        /sbin/ifconfig $interface up        /sbin/ifconfig $interface 0.0.0.0--------------------$interface是udhcpc指定的,首先up啟動設(shè)備;然后配置一個默認0.0.0.0地址。
            
                    # drop info from this interface
                    # resolv.conf may be a symlink to /tmp/, so take care
                    TMPFILE=$(mktemp)
                    grep -vE "# $interface\$" $RESOLV_CONF > $TMPFILE
                    cat $TMPFILE > $RESOLV_CONF
                    rm -f $TMPFILE        if [ -x /usr/sbin/avahi-autoipd ]; then            /usr/sbin/avahi-autoipd -k $interface
                    fi
                    ;;    leasefail|nak)        if [ -x /usr/sbin/avahi-autoipd ]; then            /usr/sbin/avahi-autoipd -wD $interface --no-chroot
                    fi
                    ;;    renew|bound)        if [ -x /usr/sbin/avahi-autoipd ]; then            /usr/sbin/avahi-autoipd -k $interface
                    fi        /sbin/ifconfig $interface $ip $BROADCAST $NETMASK-----------根據(jù)udhcpc獲取的interface/ip/BROADCASR/NETMASK,通過ifconfig配置到interface的設(shè)備。        if [ -n "$router" ] ; then
                        echo "deleting routers"
                        while route del default gw 0.0.0.0 dev $interface 2> /dev/null; do
                            :
                        done            for i in $router ; do
                            route add default gw $i dev $interface--------------router不為空的情況下,先刪除默認路由,重新建立路由。
                        done
                    fi
            
                    # drop info from this interface
                    # resolv.conf may be a symlink to /tmp/, so take care
                    TMPFILE=$(mktemp)
                    grep -vE "# $interface\$" $RESOLV_CONF > $TMPFILE
                    cat $TMPFILE > $RESOLV_CONF
                    rm -f $TMPFILE
            
                    # prefer rfc3359 domain search list (option 119) if available        if [ -n "$search" ]; then
                        search_list=$search
                    elif [ -n "$domain" ]; then
                        search_list=$domain
                    fi
            
                    [ -n "$search_list" ] &&
                        echo "search $search_list # $interface" >> $RESOLV_CONF        for i in $dns ; do
                        echo adding dns $i
                        echo "nameserver $i # $interface" >> $RESOLV_CONF--------更新dns信息到/etc/resolv.conf中。
                    done
                    ;;
            esac
            
            HOOK_DIR="$0.d"for hook in "${HOOK_DIR}/"*; do
                [ -f "${hook}" -a -x "${hook}" ] || continue
                "${hook}" "${@}"done
            
            exit 0

            復(fù)制代碼

             2.4 運行實例log 

             運行l(wèi)og如下:

            復(fù)制代碼

            [2020-08-26 19:16:08] udhcpc: started, v1.27.2[2020-08-26 19:16:08] udhcpc: sending discover-------------------------------------發(fā)送DHCPDISCOVER到DHCP服務(wù)器,服務(wù)器會返回一個可用IP地址。[2020-08-26 19:16:10] udhcpc: sending select for 192.168.33.184--------------------發(fā)送DHCPREQUEST到DHCP服務(wù)器,是對DPCPOFFER的響應(yīng)。[2020-08-26 19:16:10] udhcpc: lease of 192.168.33.184 obtained, lease time 86400---此時已經(jīng)經(jīng)過DHCP服務(wù)器分配IP,IP地址為192.168.33.184。然后調(diào)用default.script的bound或renew。[2020-08-26 19:16:10] deleting routers---------------------------------------------default.script中刪除路由。
            [2020-08-26 19:16:10] adding dns 192.168.33.1--------------------------------------配置DNS。

            復(fù)制代碼

            3. DHCP協(xié)議

            參考:《Dynamic Host Configuration Protocol

            其中《3.1 Client-server interaction - allocating a network address》介紹了如何分配一個IP地址的流程。

            復(fù)制代碼

               Message         Use   -------         ---
            
               DHCPDISCOVER -  Client broadcast to locate available servers.
            
               DHCPOFFER    -  Server to client in response to DHCPDISCOVER with
                               offer of configuration parameters.
            
               DHCPREQUEST  -  Client message to servers either (a) requesting
                               offered parameters from one server and implicitly
                               declining offers from all others, (b) confirming
                               correctness of previously allocated address after,
                               e.g., system reboot, or (c) extending the lease on a
                               particular network address.
            
               DHCPACK      -  Server to client with configuration parameters,
                               including committed network address.
            
               DHCPNAK      -  Server to client indicating client's notion of network
                               address is incorrect (e.g., client has moved to new
                               subnet) or client's lease as expired
               DHCPDECLINE  -  Client to server indicating network address is already                   in use.
            
               DHCPRELEASE  -  Client to server relinquishing network address and
                               cancelling remaining lease.
            
               DHCPINFORM   -  Client to server, asking only for local configuration
                               parameters; client already has externally configured
                               network address.
            
                                      Table 2:  DHCP messages
            
                            Server          Client          Server
                        (not selected)                    (selected)
            
                              v               v               v                  |               |               |
                              |     Begins initialization     |
                              |               |               |
                              | _____________/|\____________  |
                              |/DHCPDISCOVER | DHCPDISCOVER  \|
                              |               |               |
                          Determines          |          Determines
                         configuration        |         configuration                  |               |               |
                              |\             |  ____________/ |
                              | \________    | /DHCPOFFER     |
                              | DHCPOFFER\   |/               |
                              |           \  |                |
                              |       Collects replies        |
                              |             \|                |
                              |     Selects configuration     |
                              |               |               |
                              | _____________/|\____________  |
                              |/ DHCPREQUEST  |  DHCPREQUEST\ |
                              |               |               |
                              |               |     Commits configuration                  |               |               |
                              |               | _____________/|
                              |               |/ DHCPACK      |
                              |               |               |
                              |    Initialization complete    |
                              |               |               |
                              .               .               .
                              .               .               .                  |               |               |
                              |      Graceful shutdown        |
                              |               |               |
                              |               |\ ____________ |
                              |               | DHCPRELEASE  \|
                              |               |               |
                              |               |        Discards lease                  |               |               |
                              v               v               v
                 Figure 3: Timeline diagram of messages exchanged between DHCP
                           client and servers when allocating a new network address

            復(fù)制代碼

             

            4. 小結(jié)

            整個自動配置IP功能,需要Kernel支持DHCP、udhcpc、default.script。

            在rcS中啟動udhcpc,默認使用default.script腳本已達到自動配置ip、route等。

            聯(lián)系方式:[email protected]


            *博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權(quán)請聯(lián)系工作人員刪除。



            關(guān)鍵詞: udhcpc

            技術(shù)專區(qū)

            關(guān)閉