orangepi構(gòu)建根文件系統(tǒng)

目錄結(jié)構(gòu)說明

一嗅定、基礎(chǔ)說明

1、環(huán)境介紹

2用踩、linux的根文件結(jié)構(gòu)

3渠退、瑞士軍刀busybox

4忙迁、busybox源碼準(zhǔn)備

二、靜態(tài)編譯并測試busybox

1智什、配置busybox靜態(tài)編譯選項(xiàng)

2动漾、編譯busybox

3、安裝busybox

4荠锭、測試busybox

三旱眯、動(dòng)態(tài)編譯并測試busybox

1、配置证九、編譯删豺、安裝busybox

2、測試busybox

四愧怜、構(gòu)建根文件系統(tǒng)

1呀页、根文件系統(tǒng)的目錄

2、具體創(chuàng)建步驟

3拥坛、寫成根文件系統(tǒng)創(chuàng)建腳本

五蓬蝶、無法解析域名

目錄結(jié)構(gòu)說明

一、基礎(chǔ)說明

1猜惋、環(huán)境介紹

?? 首先這里我們需要安裝一些基礎(chǔ)的編譯環(huán)境丸氛,安裝tftp服務(wù)器,安裝nfs服務(wù)器等著摔,這里我們可以參考文章《orangpione利用usb共享網(wǎng)絡(luò)(RNDIS)實(shí)現(xiàn)tftp加載內(nèi)核掛載到NFS根文件系統(tǒng)》中的環(huán)境準(zhǔn)備章節(jié)缓窜,自行安裝相關(guān)服務(wù),在這里不展開谍咆。后續(xù)的開發(fā)是基于tftp和nfs傳輸?shù)臈l件下進(jìn)行禾锤,如果沒有實(shí)現(xiàn)相關(guān)傳輸,也可以通過燒錄sd卡的形式進(jìn)行摹察。

2恩掷、linux的根文件結(jié)構(gòu)

目錄結(jié)構(gòu)

?? linux的根文件目錄遵循的FHS,而FHS是Filesystem Hierarchy Standard(文件系統(tǒng)層次化標(biāo)準(zhǔn))的縮寫供嚎,多數(shù)Linux版本采用這種文件組織形式螃成,類似于Windows操作系統(tǒng)中c盤的文件目錄,F(xiàn)HS采用樹形結(jié)構(gòu)組織文件查坪。FHS定義了系統(tǒng)中每個(gè)區(qū)域的用途寸宏、所需要的最小構(gòu)成的文件和目錄,同時(shí)還給出了例外處理與矛盾處理偿曙。
?? 這里如果我們想深入了解根文件系統(tǒng)的結(jié)構(gòu)氮凝,我們可以到下面的訪問網(wǎng)址https://refspecs.linuxfoundation.org/fhs.shtml,也可以從該網(wǎng)址下載具體的pdf說明文檔望忆,現(xiàn)在最新的文檔是3.0的版本罩阵,地址是https://refspecs.linuxfoundation.org/FHS_3.0/fhs-3.0.pdf竿秆,文檔中有各個(gè)目錄的具體介紹,這里不詳細(xì)介紹,后面我們制作根文件系統(tǒng)的時(shí)候,會(huì)對應(yīng)的說明

3阻肿、瑞士軍刀busybox

??BusyBox 是一個(gè)集成了三百多個(gè)最常用Linux命令和工具的軟件。BusyBox 包含了一些簡單的工具匪燕,例如ls、cat和echo等等喧笔,還包含了一些更大帽驯、更復(fù)雜的工具,例grep书闸、find尼变、mount以及telnet。有些人將 BusyBox 稱為 Linux 工具里的瑞士軍刀浆劲。簡單的說BusyBox就好像是個(gè)大工具箱嫌术,它集成壓縮了 Linux 的許多工具和命令,也包含了 Android 系統(tǒng)的自帶的shell牌借。簡單來說就是我們在linux系統(tǒng)中常用的命令都是可以從busybox里面編譯集成的度气,比如cp、mkdir走哺、ls、mv哲虾、rm丙躏、adduser、deluser等等

4束凑、busybox源碼準(zhǔn)備

  1. 新建目錄mkdir mkrootfs
  2. 進(jìn)入目錄mkrootfs晒旅,并且下載busybox源碼
    我們從碼云下載源碼,上面的busybox是github上的源碼鏡像汪诉,每天更新一次
    git clone https://gitee.com/mirrors/busyboxsource.git busybox废恋,源碼下載好后,我們在源碼的上層mul
  3. 在mkrootfs目錄下扒寄,新建腳本vi build.sh鱼鼓,這里主要是把busybox的編譯輸出到目錄bboxbuild目錄中,把busybox的安裝到目錄rootfs中该编。腳本的ARCH和CROSS_COMPILE定義了相關(guān)架構(gòu)和需要用到的工具鏈
#! /bin/bash
JOBNUM=4
NPWD=`realpath .`

export ARCH=arm
export CROSS_COMPILE=$NPWD/../gcc/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-

if [ $1_x == cp_x ];then
        echo $PWD
        cp $NPWD/rootfs/build/linux-custom/arch/arm/boot/zImage ~/tftp
        cp $NPWD/rootfs/build/linux-custom/arch/arm/boot/dts/sun8i-h3-orangepi-one.dtb ~/tftp
elif [ $1_x == busybox_x ];then
        cd $NPWD/../busybox
        echo $PWD
        mkdir -p $NPWD/bboxbuild
        if [ $2_x == install_x ];then
                mkdir -p $NPWD/rootfs
                make O=$NPWD/bboxbuild CONFIG_PREFIX=$NPWD/rootfs  $2 -j$JOBNUM
        else
                if [ $3_x == _x ];then
                        make O=$NPWD/bboxbuild $2 -j$JOBNUM
                else
                        make O=$NPWD/bboxbuild $2 $3
                fi
        fi
else
        echo "help"
fi

二迄本、靜態(tài)編譯并測試busybox

1、配置busybox靜態(tài)編譯選項(xiàng)

關(guān)于配置busybox這里我們可以根據(jù)自己的需求配置相關(guān)的小工具课竣,靜態(tài)編譯主要關(guān)注的選項(xiàng)是CONFIG_STATIC嘉赎,對應(yīng)于下圖Build static binary (no shared libs)置媳,執(zhí)行命令./build.sh busybox menuocnfig

static

2、編譯busybox

執(zhí)行./build.sh busybox對busybox進(jìn)行編譯公条,編譯完成后出現(xiàn)類似提示Static linking against glibc拇囊,這里是glibc還是uclibc,具體看工具鏈編譯時(shí)指定的c庫是什么

build static

3靶橱、安裝busybox

使用./build.sh busybox install安裝busybox到腳本目錄下的rootfs目錄寥袭,這是因?yàn)槲覀冊谀_本中指定了安裝目錄就是當(dāng)前的rootfs目錄,可以看到我們安裝的目錄rootfs抓韩,及其下方的

static rootfs

4纠永、測試busybox

這里測試我們通過之前文章的nfs根文件的映射進(jìn)行測試,由于我們之前創(chuàng)建的nfs文件系統(tǒng)時(shí)通過軟連接的方式進(jìn)行連接的谒拴,這里我們只需要把尝江,軟件重新制定到mkrootfs目錄下的rootfs文件夾即可
ln -snf mkrootfs/rootfs nfs把nfs連接重新連接到nfs根文件系統(tǒng)中,由于開發(fā)板的配置本來就是nfs根文件目錄英上,我們這里只需要重啟開發(fā)板就可以加載到nfs了

  1. can't run '/etc/init.d/rcS': No such file or directory 和 can't open /dev/tty2: No such file or directory 炭序,這里是因?yàn)閎usybox上電會(huì)先執(zhí)尋找 /etc/init.d/rcS腳本,但是因?yàn)槲覀兊母募到y(tǒng)只有busybox編譯出的東西苍日,沒有腳本也沒有終端設(shè)備目錄惭聂,我們可以先建立一個(gè)dev目錄在rootfs中,然后重啟開發(fā)板


    image.png
  2. 雖然還是提示can't run '/etc/init.d/rcS': No such file or directory相恃,但是很明顯辜纲,已經(jīng)進(jìn)入了一個(gè)可以使用的shell終端了,后續(xù)具體的配置在跟文件系統(tǒng)制作章節(jié)具體介紹拦耐,這里我們先研究動(dòng)態(tài)編譯busybox并加載測試


    image.png

三耕腾、動(dòng)態(tài)編譯并測試busybox

1、配置杀糯、編譯扫俺、安裝busybox

1、關(guān)于配置busybox這里我們可以根據(jù)自己的需求配置相關(guān)的小工具固翰,busybox的默認(rèn)配置就是動(dòng)態(tài)編譯狼纬,只要把CONFIG_STATIC選項(xiàng)去掉即可,對應(yīng)于Build static binary (no shared libs)骂际,執(zhí)行命令./build.sh busybox menuocnfig配置去掉CONFIG_STATIC選項(xiàng)
2疗琉、通過./build.sh busybox編譯動(dòng)態(tài)的busybox,這里會(huì)出現(xiàn)Trying libraries:表面是動(dòng)態(tài)連接到后面的庫

image.png

3歉铝、移除之前靜態(tài)的rootfssudo rm -r rootfs
4没炒、通過./build.sh busybox install安裝動(dòng)態(tài)的busybox到rootfs
5、在rootfs創(chuàng)建dev目錄mkdir -p rootfs/dev

2、測試busybox

這里的測試方法和前面介紹的動(dòng)態(tài)busybox一樣送火,我們先重啟開發(fā)板

  1. Kernel panic - not syncing: No working init found拳话,這里是因?yàn)槲覀兪褂昧藙?dòng)態(tài)連接,但是沒有把相應(yīng)的動(dòng)態(tài)庫放入根文件系統(tǒng)种吸,導(dǎo)致busybox運(yùn)行時(shí)沒有對應(yīng)的庫弃衍,同時(shí)我們可以看到,如果我們在沒有指定init的情況下坚俗,內(nèi)核會(huì)自動(dòng)的按照/sbin/init镜盯、/etc/init、/bin/init猖败、/bin/sh順序去查找初始程序并運(yùn)行


    image.png
  2. 加載動(dòng)態(tài)庫
  1. 通過readelf查找busybox的動(dòng)態(tài)庫arm-linux-gnueabihf-readelf -d rootfs/bin/busybox | grep NEEDED
    vencol@pcvencol:~/code/self$ arm-linux-gnueabihf-readelf -d rootfs/bin/busybox | grep NEEDED
    0x00000001 (NEEDED) Shared library: [libm.so.6]
    0x00000001 (NEEDED) Shared library: [libresolv.so.2]
    0x00000001 (NEEDED) Shared library: [libc.so.6]

2.通過objdump查找busybox的動(dòng)態(tài)庫arm-linux-gnueabihf-objdump -x rootfs/bin/busybox | grep NEEDED
vencol@pcvencol:~/code/self$ arm-linux-gnueabihf-objdump -x rootfs/bin/busybox | grep NEEDED
NEEDED libm.so.6
NEEDED libresolv.so.2
NEEDED libc.so.6

3.通過strings 查找busybox的動(dòng)態(tài)庫strings busybox | grep ^lib
vencol@pcvencol:~/code/self$ strings rootfs/bin/busybox | grep ^lib
libm.so.6
libresolv.so.2
libc.so.6
lib32
lib64

4.通過ldd查找速缆,但是這里交叉工具鏈中并沒有提供ldd工具,需要在開發(fā)板上執(zhí)行恩闻,因?yàn)橹鳈C(jī)架構(gòu)一般和開發(fā)板不同艺糜,所以才要交叉編譯

最后我們可以確定動(dòng)態(tài)庫如下,這里需要注意的是ld-linux-armhf.so.3和ld-2.25.so幢尚,因?yàn)檫@兩個(gè)庫是執(zhí)行時(shí)連接需要用到的庫破停,無論是從readlf、objdump還是string都沒有體現(xiàn)出來尉剩,很多小伙伴真慢,也是因?yàn)槿鄙俟ぞ哝湹倪@里動(dòng)態(tài)連接庫,導(dǎo)致動(dòng)態(tài)連接的時(shí)候失敗理茎,這個(gè)只能通過ldd才能體現(xiàn)出來黑界。但是幾乎所有通過交叉工具鏈動(dòng)態(tài)編譯的軟件,都會(huì)依賴這兩個(gè)庫皂林,所以朗鸠,如果不確定的時(shí)候就把他們都加到根文件的lib目錄吧。一般對應(yīng)的庫文件都會(huì)出現(xiàn)在交叉工具鏈了目錄下的arm-linux-gnueabihf/libc/lib路徑下

vencol@pcvencol:~/code/self$ ll rootfs/lib/
total 20816
drwxrwxr-x 2 vencol vencol     4096 Aug  1 05:55 ./
drwxrwxr-x 7 vencol vencol     4096 Aug  1 05:56 ../
-rwxr-xr-x 1 vencol vencol  1111436 Aug  1 05:55 ld-2.25.so*
lrwxrwxrwx 1 vencol vencol       10 Aug  1 05:55 ld-linux-armhf.so.3 -> ld-2.25.so*
-rwxr-xr-x 1 vencol vencol 13877292 Aug  1 05:55 libc-2.25.so*
lrwxrwxrwx 1 vencol vencol       12 Aug  1 05:55 libc.so.6 -> libc-2.25.so*
-rwxr-xr-x 1 vencol vencol  5948304 Aug  1 05:55 libm-2.25.so*
lrwxrwxrwx 1 vencol vencol       12 Aug  1 05:55 libm.so.6 -> libm-2.25.so*
-rwxr-xr-x 1 vencol vencol   359708 Aug  1 05:55 libresolv-2.25.so*
lrwxrwxrwx 1 vencol vencol       17 Aug  1 05:55 libresolv.so.2 -> libresolv-2.25.so*

添加了對應(yīng)庫后式撼,一般就可以成功加載了童社,但是返現(xiàn)動(dòng)態(tài)庫加載的根文件要比靜態(tài)鏈接的大的多求厕,這個(gè)是因?yàn)楝F(xiàn)在的軟件只有busybox著隆,后面工具軟件多了,肯定會(huì)使用動(dòng)態(tài)連接呀癣,可以根據(jù)需要適當(dāng)做精簡

四美浦、構(gòu)建根文件系統(tǒng)

1、根文件系統(tǒng)的目錄

這里目錄bin项栏、linuxrc浦辨、sbin、usr是我們用busybox生成的目錄沼沈,我們主要需要修改的目錄有dev流酬、etc和lib币厕,lib主要是需要拷貝庫文件,這里主要展開需要修改的文件

├── bin
├── dev
│   ├── console
│   ├── null
│   └── zero
├── etc
│   ├── fstab
│   ├── group
│   ├── hostname
│   ├── init.d
│   ├── inittab
│   ├── network
│   ├── passwd
│   ├── passwd-
│   └── profile
├── lib
├── linuxrc -> bin/busybox
├── mnt
├── proc
├── root
├── sbin
├── sys
├── tmp
├── usr
└── var

2芽腾、具體創(chuàng)建步驟

  1. 進(jìn)入根文件系統(tǒng)目錄旦装,創(chuàng)建文件系統(tǒng)的頂層目錄
    cd rootfs && mkdir -p dev etc mnt proc var tmp sys root lib
  2. 創(chuàng)建dev目錄相關(guān)設(shè)備
mknod dev/null c 1 3
mknod dev/zero c 1 5
mknod dev/console c 5 1
  1. 設(shè)置etc目錄相關(guān)配置

1.創(chuàng)建etc/inittab文件,該文件是系統(tǒng)啟動(dòng)后摊滔,按照上面的描述進(jìn)行啟動(dòng)的配置文件

::sysinit:/etc/init.d/rcS #系統(tǒng)啟動(dòng)腳本
::ctrlaltdel:/sbin/reboot #組合鍵Ctrl+Alt+Del組合鍵阴绢,重啟系統(tǒng)
::shutdown:/bin/umount -a -r #關(guān)機(jī)前umount所有掛載
ttyS0::askfirst:-/bin/sh #啟動(dòng)串口終端,如果需要登錄改為/bin/login
::shutdown:/etc/init.d/rcK #系統(tǒng)關(guān)機(jī)腳本
::shutdown:/sbin/swapoff -a
::shutdown:/bin/umount -a -r #關(guān)機(jī)前umount所有掛載

  1. 創(chuàng)建 etc/init.d目錄艰躺,并新建文件etc/init.d/rcS,并給文件執(zhí)行權(quán)限sudo chmod a+x etc/init.d/rcS

mount -a #首先掛載所有在fstab定義的內(nèi)容
mkdir /dev/pts
mount -t devpts devpts /dev/pts
/bin/hostname -F /etc/hostname
ifconfig usb0 up 192.168.137.2
route add default gw 192.168.137.1 usb0

  1. 創(chuàng)建 etc/init.d目錄呻袭,并新建文件etc/init.d/rcK,并給文件執(zhí)行權(quán)限sudo chmod a+x etc/init.d/rcK

ifconfig usb0 down

  1. 新建etc/fstab文件

proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
mdev /dev tmpfs defaults 0 0
none /tmp tmpfs defaults 0 0
none /var tmpfs defaults 0 0

  1. 新建etc/profile,其中的PS1參數(shù)可以參考網(wǎng)站做相應(yīng)修改https://blog.csdn.net/litao31415/article/details/50188243
USER="`id -un`"
LOGNAME=$USER #登錄之后使用用戶名顯示
HOSTNAME="rootfs_by_vencol"     #主機(jī)名
PS1="[\u@\h \w]# "      #終端顯示信息
if [ ! -z ${SSH_TTY} ]; then
   export PATH=/sbin:/usr/sbin:/bin:/usr/bin
fi
  1. 設(shè)置lib目錄
    lib目錄主要是庫文件和模塊文件的所在目錄腺兴,一般模塊文件可以通過源碼make modules_install安裝到lib目錄左电,這樣就可以不用拷貝模塊文件了,所以我們主要介紹的是拷貝libc含长,libc一般在工具鏈目錄下有券腔,比如我這里的工具鏈?zhǔn)莂rm-linux-gnueabihf。
cp -a arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib/ rootfs/lib
rm -f rootfs/lib/*.a
#去除符號表拘泞,節(jié)省空間纷纫,但是不能反匯編了
#${COMPILE_DIR}arm-none-linux-gnueabi-strip rootfs/lib/*
  1. 拷貝虛擬機(jī)上的/etc/group和/etc/passwd到rootfs/etc
    修改passwd為root:FMKTwEUCSZm9Q:0:0:root:/root:/bin/sh,即只保存與root相關(guān)項(xiàng)陪腌,而且最后改成/bin/sh
    修改group為root:x:0:root
    這樣登錄的時(shí)候就是用和虛擬機(jī)root用戶一樣的密碼登錄辱魁,如果不行,可以先修改/etc/init.d/rcS文件诗鸭,開機(jī)直接進(jìn)入shell染簇,在shell里面修改root用戶密碼,之后再修改/etc/init.d/rcS文件為開機(jī)login强岸。

3锻弓、寫成根文件系統(tǒng)創(chuàng)建腳本

#! /bin/bash
JOBNUM=4
NPWD=`realpath .`

#mkdir -p roottemp
cd rootfs
mkdir -p dev etc mnt proc var tmp sys root lib
sudo mknod dev/null c 1 3
sudo mknod dev/zero c 1 5
sudo mknod dev/console c 5 1

cat << EOF > etc/inittab
::sysinit:/etc/init.d/rcS #系統(tǒng)啟動(dòng)腳本
::ctrlaltdel:/sbin/reboot #組合鍵Ctrl+Alt+Del組合鍵,重啟系統(tǒng)
ttyS0::respawn:-/bin/login #啟動(dòng)串口終端蝌箍,如果需要登錄改為/bin/login
#ttyS0::askfirst:-/bin/login #啟動(dòng)串口終端青灼,如果需要登錄改為/bin/login
#ttyS0::askfirst:-/bin/sh #啟動(dòng)串口終端,如果需要登錄改為/bin/login

::shutdown:/etc/init.d/rcK #系統(tǒng)關(guān)機(jī)腳本
#::shutdown:/sbin/swapoff -a
::shutdown:/bin/umount -a -r #關(guān)機(jī)前umount所有掛載
EOF

mkdir -p etc/init.d
cat << EOF > etc/init.d/rcS
# !/bin/sh
mount -a #首先掛載所有在fstab定義的內(nèi)容
mkdir /dev/pts
mount -t devpts devpts /dev/pts
/bin/hostname -F /etc/hostname
ifconfig usb0 up 192.168.137.2
route add default gw 192.168.137.1 usb0
EOF
sudo chmod +x etc/init.d/rcS

cat << EOF > etc/init.d/rcK
# !/bin/sh
ifconfig usb0 down
EOF

cat << EOF > etc/fstab
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
mdev /dev tmpfs defaults 0 0
none /tmp tmpfs defaults 0 0
none /var tmpfs defaults 0 0
EOF

mkdir -p etc/network
cat << EOF > etc/network/interfaces
# interface file auto-generated by buildroot

auto lo
iface lo inet loopback

#auto eth0
#iface eth0 inet dhcp
#  pre-up /etc/network/nfs_check
#  wait-delay 15
#  hostname $(hostname)


auto usb0
iface usb0 inet static
pre-up /etc/network/nfs_check
address 192.168.137.2
netmask 255.255.255.0
gateway 192.168.137.1
#dns-nameservers 8.8.8.8 192.168.137.1 211.136.20.203
EOF

cat << EOF > etc/resolv.conf
nameserver 192.168.137.1
nameseverr 8.8.8.8
nameseverr 10.8.16.30
EOF

cat << EOF > etc/hostname
vencolfs
EOF

#cp -a $NPWD/../gcc/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib/ lib
#rm -f lib/*.a
#去除符號表妓盲,節(jié)省空間杂拨,但是不能反匯編了
#${COMPILE_DIR}arm-none-linux-gnueabi-strip rootfs/lib/*

#下面的是用戶相關(guān)的信息,自行修改
cat << EOF > etc/passwd
root:FMKTwEUCSZm9Q:0:0:root:/root:/bin/sh
EOF

cat << EOF > etc/group
root:x:0:
EOF

#cat << EOF > etc/shadow
#root:$6$B7gzTyFF$Zm2fC5EQYdqupH.BwccJv0YX4XingPOqsMcu1vlWC4AaKof4ycDGlXooMs2m5ZxfDPvjhDicnkt/PuGBDqZtD1:18316:0:99999:7:::
#EOF

cat << EOF > etc/profile
USER="`id -un`"
LOGNAME=$USER #登錄之后使用用戶名顯示
HOSTNAME="rootfs_by_vencol"     #主機(jī)名
#HOSTNAME='/bin/hostname'
PS1="[\u@\h \w]# "      #終端顯示信息

if [ ! -z ${SSH_TTY} ]; then
   export PATH=/sbin:/usr/sbin:/bin:/usr/bin
fi
EOF

五悯衬、無法解析域名

用了一段時(shí)間后發(fā)現(xiàn)弹沽,可以ping通ip但是無法DNS,經(jīng)過一番折騰后發(fā)現(xiàn),是因?yàn)闆]有支持DNS策橘,因?yàn)榫幾g出來的nslookup是可以解析域名的炸渡,但是直接ping卻是不行的

image.png

這里找到了兩個(gè)方案

  1. 安裝文章https://www.cnblogs.com/liangwode/p/5584099.html中說的,把busybox編譯成動(dòng)態(tài)連接丽已,同時(shí)添加相應(yīng)的庫文件偶摔,其中DNS需要用到的文件有:/lib/libnss_dns.so.2、/lib/libnss_files.so.2促脉、/lib/libresolv.so.2辰斋、/etc/resolv.conf、/etc/nsswitch.conf
  2. https://www.dazhuanlan.com/2020/01/06/5e12988c64495/這個(gè)文章中瘸味,提到添加route gateway宫仗,并把ip添加到/etc/resolv.conf文件中,但是實(shí)際使用失敗了旁仿,后來發(fā)現(xiàn)https://blog.csdn.net/u013625451/article/details/79007441這文章中提到了藕夫,busybox官網(wǎng)的說法是需要?jiǎng)討B(tài)庫
  3. 后來在下面的網(wǎng)址發(fā)現(xiàn)了解決方案,其思路是枯冈,在ip連接前毅贮,先自己模擬dns的協(xié)議,解析/etc/resolv.conf并向里面的服務(wù)器發(fā)送數(shù)據(jù)進(jìn)行dns解析尘奏。https://blog.csdn.net/bingyu9875/article/details/104684985

1滩褥、把下面的文件內(nèi)容,添加到busybox源碼的libbb/xconnect.c文件的開頭
2炫加、修改該文件中str2sockaddr函數(shù)中g(shù)etaddrinfo改為hgetaddrinfo瑰煎。

#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define oops(msg) { perror(msg); exit(1);}
#include<ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


void fillip(char* buffer, const char* ip);
char* name2ip(const char* name);
/**
 *  * head len: 12
 *   * query: ? + 4
 *    * total: strlen(query.buffer) + 16
 *     */
typedef struct{
        u_short txid;
        u_short flag;
        u_short question;
        u_short answer;
        u_short authority;
        u_short additional;
        char buffer[256];
        struct {
                u_short type;
                u_short cls;
        }query;
}dns_req;
/** length of resp: 12 */
typedef struct{
        u_short txid;
        u_short flag;
        u_short question;
        u_short answer;
        u_short authority;
        u_short addtional;
        char buffer[1024];
        struct{
                u_short name;
                u_short type;
                u_short cls;
                u_short live_l;
                u_short live_h;
                u_short len;
                struct in_addr addr;
        }resp;
}dns_res;

int hgetaddrinfo(const char *node, const char *service,
                const struct addrinfo *hints,
                struct addrinfo **res){
        /*    int rc = getaddrinfo(node,service,hints,res);
         *            if(rc == 0)//todo: != -> ==
         *                            return rc;
         *                                            */
        char *ip = name2ip(node);                               /// 如果 ping www.baidu.com
        return getaddrinfo(ip,service,hints,res);   /// 那么此時(shí) node 指向字符串 "www.baidu.com"
}

char *get_dns_name()
{
        /*
        static char buf[8]="8.8.8.8";
                return buf;
        */
        int fd;
        static char     buf[1024],*pstr,*pdns;

        fd = open("/etc/resolv.conf", O_RDWR);
        read(fd,buf,1020);
        pstr = strstr(buf,"nameserver");
        pstr += strlen("nameserver");
        while(!isdigit(*pstr)){
                pstr ++;
        }
        pdns = pstr;

        while(isdigit(*pstr) || (*pstr == '.') ){
                pstr ++;
        }
        *pstr = '\0';
        close(fd);
        return pdns;

}


char * name2ip(const char *node){
        struct sockaddr_in dns;
        dns_req req;
        dns_res res;
        int sockid, len, index;
                get_dns_name();
                char  dnsip[32];

                strcpy(dnsip,get_dns_name());

        sockid = socket(PF_INET, SOCK_DGRAM, 0);
        if(sockid == -1)
                oops("socket");
        memset((void*)&dns, 0, sizeof(dns));
        dns.sin_family = AF_INET;
        dns.sin_port = htons(53);
        dns.sin_addr.s_addr = inet_addr(dnsip);

        memset((void*)&req, 0, sizeof(req));
        req.txid = htons(0x4419);
        req.flag = htons(0x0100);
        req.question = htons(1);
        fillip(req.buffer,node);
        req.query.type=htons(1);
        req.query.cls=htons(1);
        memcpy(req.buffer+strlen(req.buffer)+1, (void*)(&req.query), sizeof(req.query));

        sendto(sockid, (void*)&req, strlen(req.buffer)+17, 0,
                        (struct sockaddr*)&dns, sizeof(dns));
        recvfrom(sockid, (void*)&res, sizeof(res), 0,
                        (struct sockaddr*)&dns, &len);
        index = strlen(res.buffer)+5;
        while(1){
                memcpy((void*)&(res.resp), res.buffer+index, 12);
                if(ntohs(res.resp.type)==1){
                        memcpy((void*)&(res.resp.addr), res.buffer+index+12, 4);
                        break;
                }
                index += ntohs(res.resp.len) + 12;
        }

        return inet_ntoa(res.resp.addr);
}

void fillip(char* buffer, const char* ip){
        int i,j=0;
        for(i = 0; ip[i] != 0; i ++){
                if(ip[i] != '.'){
                        buffer[i+1] = ip[i];
                }
                else{
                        buffer[j] = i - j;
                        j = i + 1;
                }
        }
        buffer[j] = i - j;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市俗孝,隨后出現(xiàn)的幾起案子酒甸,更是在濱河造成了極大的恐慌,老刑警劉巖赋铝,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件插勤,死亡現(xiàn)場離奇詭異,居然都是意外死亡革骨,警方通過查閱死者的電腦和手機(jī)农尖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來苛蒲,“玉大人卤橄,你說我怎么就攤上這事绿满”弁猓” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長漏健。 經(jīng)常有香客問我嚎货,道長,這世上最難降的妖魔是什么蔫浆? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任殖属,我火速辦了婚禮,結(jié)果婚禮上瓦盛,老公的妹妹穿的比我還像新娘洗显。我一直安慰自己,他們只是感情好原环,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布挠唆。 她就那樣靜靜地躺著,像睡著了一般嘱吗。 火紅的嫁衣襯著肌膚如雪玄组。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天谒麦,我揣著相機(jī)與錄音俄讹,去河邊找鬼。 笑死绕德,一個(gè)胖子當(dāng)著我的面吹牛患膛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播耻蛇,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼剩瓶,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了城丧?” 一聲冷哼從身側(cè)響起延曙,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎亡哄,沒想到半個(gè)月后枝缔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蚊惯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年愿卸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片截型。...
    茶點(diǎn)故事閱讀 38,716評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡趴荸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出宦焦,到底是詐尸還是另有隱情发钝,我是刑警寧澤顿涣,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站酝豪,受9級特大地震影響涛碑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜孵淘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一蒲障、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瘫证,春花似錦揉阎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至载萌,卻和暖如春惧财,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背扭仁。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工垮衷, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人乖坠。 一個(gè)月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓搀突,卻偏偏與公主長得像,于是被迫代替她去往敵國和親熊泵。 傳聞我的和親對象是個(gè)殘疾皇子仰迁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評論 2 350