自己實現一個自動檢測網卡狀態,並設置 ip 地址
一、usb 網卡應該如何實現?
前文講了如何利用開源軟件 ifplugd 實現監測網口狀態變化,
ifplugd 的確可以實現監測網卡的狀態,並執行相應腳本,
但是有個前提,就是網口已經註冊到系統中,即用 ifconfig -a 能查看到
如何是 usb 網卡這種設備,在插入 usb 口之後網口設備纔會註冊,
使用過程中可能隨時會拔掉 usb 網卡,
那麼這種情況下,要想設置 usb 網卡,那麼就就需要修改 ifplugd 程序。
爲了方便大家理解,本文給大家講解如何自己實現一個簡化的程序 ethcheck,
可以實現自動監測網卡是否存在
rk3568 所有網口:
rk3568_r:/system # ifconfig -a
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope: Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 TX bytes:0
dummy0 Link encap:Ethernet HWaddr fa:85:6c:74:1b:7d
inet6 addr: fe80::f885:6cff:fe74:1b7d/64 Scope: Link
UP BROADCAST RUNNING NOARP MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 TX bytes:560
sit0 Link encap:IPv6-in-IPv4
NOARP MTU:1480 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 TX bytes:0
ip6tnl0 Link encap:UNSPEC
NOARP MTU:1452 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 TX bytes:0
eth1 Link encap:Ethernet HWaddr 5a:53:63:cf:dd:0b Driver rk_gmac-dwmac
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 TX bytes:0
Interrupt:51
ip_vti0 Link encap:UNSPEC
NOARP MTU:1480 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 TX bytes:0
eth0 Link encap:Ethernet HWaddr 5e:53:63:cf:dd:0b Driver rk_gmac-dwmac
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 TX bytes:0
Interrupt:38
ip6_vti0 Link encap:UNSPEC
NOARP MTU:1364 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 TX bytes:0
二、程序設計
0. 程序框圖
1. 設置程序爲守護進程
因爲該程序最終要在後臺執行,並且常駐內存,所以必須將該進程設置爲守護進程
關於守護進程的內容,請參考下面文章:
《搞懂進程組、會話、控制終端關係,才能明白守護進程幹嘛的?》
參考代碼如下:
void init_daemon(void)
{
int pid;
int i;
if(pid=fork())
exit(0);//是父進程,結束父進程?
else if(pid< 0)
exit(1);//fork失敗,退出?
//是第一子進程,後臺繼續執行?
setsid();//第一子進程成爲新的會話組長和進程組長?
//並與控制終端分離?
chdir("/tmp");//改變工作目錄到/tmp?
umask(0);//重設文件創建掩模?
for(i=0;i< NOFILE;++i)//關閉打開的文件描述符?
close(i);
return;
}
2. 確認制定網口是否存在?
要確認指定網口是否存在,主要通過/proc/net/dev
目錄下是否有該網口信息:
peng@ubuntu:~$ cat /proc/net/dev
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
lo: 26163 292 0 0 0 0 0 0 26163 292 0 0 0 0 0 0
eth0: 285444708 243273 0 0 0 0 0 0 91828270 88660 0 0 0 0 0 0
如何用 C 語言實現檢測指定網口,可以參考下面文章:
參考代碼:
static char * interface_name_cut (char *buf, char **name)
{
char *stat;
/* Skip white space. Line will include header spaces. */
while (*buf == ' ')
buf++;
*name = buf;
/* Cut interface name. */
stat = strrchr (buf, ':');
*stat++ = '\0';
return stat;
}
/*
return value:1 exist 0:no
*/
int check_interface_fromproc(char *interface)
{
FILE *fp;
char buf[PROCBUFSIZ];
struct interface *ifp;
char *name;
/* Open /proc/net/dev. */
fp = fopen (_PATH_PROC_NET_DEV, "r");
if (fp == NULL)
{
printf("open proc file error\n");
return -1;
}
/* Drop header lines. */
fgets (buf, PROCBUFSIZ, fp);
fgets (buf, PROCBUFSIZ, fp);
/* Only allocate interface structure. Other jobs will be done in
if_ioctl.c. */
while (fgets (buf, PROCBUFSIZ, fp) != NULL)
{
interface_name_cut (buf, &name);
if(strcmp(interface,name)==0)
return 1;
}
fclose(fp);
return 0;
}
3. 指定網口不存在
如果檢測網口不存在,則需要休眠,然後繼續監測/proc/net/dev
文件。
4. 如果指定網口存在
則獲取該網口的 IP 地址,然後比較是否是指定的 IP 地址
網卡 IP 地址的獲取,主要通過系統調用ioctl()
的 SIOCGIFADDR
命令實現
關於如何用 c 語言操作網卡,擦靠下面文章
《Linux 下 C 語言操作網卡的幾個代碼實例!特別實用》
參考代碼如下:
int getLocalIp(const char *eth, char *ip) {
struct ifreq ifr;
struct sockaddr_in sin;
int fd;
bzero(&ifr, sizeof(ifr));
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
return -1;
}
strcpy(ifr.ifr_name, eth);
if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) {
close(fd);
return -1;
}
memcpy(&sin, &ifr.ifr_addr, sizeof(sin));
snprintf(ip, IP_SIZE, "%s", inet_ntoa(sin.sin_addr));
close(fd);
return 0;
}
讀取的 ip 地址存放在參數ip
指向的內存中。
5. ip 地址相同
如果網卡地址與指定的 ip 地址相同,那麼不需要修改地址,休眠一段時間(根據實際操作的頻率設置時間), 然後再監測網口是否存在
6. IP 地址不相同
如果 ip 地址不相同,則需要修改 ip 地址,
執行我們提前設置好的腳本 if.sh 即可
#!/bin/bash
IPADDR=192.168.40.8
ETHPORT=eth1
echo "ethcheck set" $ETHPORT $IPADDR
echo $#
echo $0
echo $1
echo $2
if [ $# -eq 2 ];then
if [ $1 = $ETHPORT ];then
echo $ETHPORT
if [ $2 = "up" ];then
ifconfig $ETHPORT $IPADDR
sleep 1
ip rule add from all lookup main pref 9000
sleep 1
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -F
echo "set" $ETHPORT "done"
elif [ $2 = "down" ];then
echo "down"
elif [ $2 = "disable" ];then
echo "disable"
elif [ $2 = "error" ];then
echo "error"
fi
fi
fi
7. 設置爲開機啓動
要實現開機就自動運行 ifplugd,可以參考下面文章:
《安卓如何設置開機自動啓動某個程序?ramdisk + init.rc 給你搞定》
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/LaVPfsa2amLqp4PJdANjBw