# 網路程式設計 AF_NETLINK ###### tags: `linux` `AF_NETLINK` `network programming` <style> .blue { color: blue; } .bgblue { color: blue; font-size: 24px; font-weight: bold; } .red { color: red; font-size: 24px; font-weight: bold; } h1 {text-align: center;} </style> Author: WhoAmI Date: 20230522 E-mail: kccddb@gmail.com Copyright: CC BY-NC-SA --- ![](https://i.imgur.com/PC1b71k.jpg) user space 與 kernel Space 透過 Netlink Socket, [getsockopt, setsockopt - get and set options on sockets](https://linux.die.net/man/2/setsockopt) 溝通, e.g., iproute2, tc, iptables, udev 等 (Linux 最好用 ip route 而不要用 route! 用 ip addr ...) 偵測 斷線 也不要用 ping, 例如 PPP, PPPoE 最好透過 netlink socket. [Kernel Korner - Why and How to Use Netlink Socket, by Kevin Kaichuan He on January 5, 2005](https://www.linuxjournal.com/article/7356) [How to use netlink socket to communicate with a kernel module?](https://stackoverflow.com/questions/3299386/how-to-use-netlink-socket-to-communicate-with-a-kernel-module/3334782) [Monitoring Linux networking state using netlink Oleg Kutkov / February 14, 2018](https://olegkutkov.me/2018/02/14/monitoring-linux-networking-state-using-netlink/) ![](https://i.imgur.com/6X4S8ND.jpg) ![](https://i.imgur.com/yw3B00L.jpg) [Netfilter Architecture](https://www.netfilter.org/documentation/HOWTO/netfilter-hacking-HOWTO-3.html) ![](https://i.imgur.com/85KouvH.jpg) iptables 是 user space 軟體用來設定網路核心的工具程式 Netflter 才是真正 Linux 網路核心部分 **了解 Netflter Architecture 更能了解 Linux 網路核心的運作! 了解網路核心運作後, iptables 的使用就可靠自己練習 iptables 的用法** https://www.netfilter.org/ netfilter.org is home to the software of the packet filtering framework inside the Linux 2.4.x and later kernel series. Software commonly associated with netfilter.org is iptables. HOWTO https://www.netfilter.org/documentation/index.html#documentation-howto e.g., Linux 2.4 Packet Filtering HOWTO Ubuntu Iptables is a firewall, installed by default on all official Ubuntu distributions (Ubuntu, Kubuntu, Xubuntu). https://help.ubuntu.com/community/IptablesHowTo Source NAT/Masquerading/Destination NAT [Linux 2.4 NAT HOWTO](https://www.netfilter.org/documentation/HOWTO//NAT-HOWTO.html#toc1) iptables 基本使用 [THE BEGINNER’S GUIDE TO IPTABLES, THE LINUX FIREWALL BY KORBIN BROWN FEBRUARY 6, 2014, 12:34PM EDT](https://www.howtogeek.com/177621/the-beginners-guide-to-iptables-the-linux-firewall/) ![](https://i.imgur.com/yvVwY7l.jpg) ```c= /* * route detect * */ #include <asm/types.h> #include <sys/socket.h> #include <unistd.h> #include <err.h> #include <stdio.h> #include <netinet/in.h> #include <linux/netlink.h> #include <linux/rtnetlink.h> #if 0 //#define MYPROTO NETLINK_ARPD #define MYMGRP RTMGRP_NEIGH // if you want the above you'll find that the kernel must be compiled with CONFIG_ARPD, and // that you need MYPROTO=NETLINK_ROUTE, since the kernel arp code {re,ab}uses rtnl (NETLINK_ROUTE) #else #define MYPROTO NETLINK_ROUTE #define MYMGRP (RTMGRP_IPV4_ROUTE|RTMGRP_IPV4_IFADDR) #endif #define WARN_IF(EXP) \ do { if (EXP) \ fprintf (stderr, "Warning: " #EXP "\n"); } \ while (0) struct msgnames_t { int id; char *msg; } typenames[] = { #define MSG(x) { x, #x } MSG(RTM_NEWLINK), MSG(RTM_DELLINK), MSG(RTM_NEWADDR), MSG(RTM_DELADDR), MSG(RTM_NEWROUTE), MSG(RTM_DELROUTE), MSG(RTM_GETROUTE), #undef MSG {0,0} }; char *lookup_name(struct msgnames_t *db,int id) { static char name[512]; struct msgnames_t *msgnamesiter; for(msgnamesiter=db;msgnamesiter->msg;++msgnamesiter) { if (msgnamesiter->id == id) break; } if (msgnamesiter->msg) { return msgnamesiter->msg; } snprintf(name,sizeof(name),"#%i",id); return name; } int open_netlink() { int sock = socket(AF_NETLINK,SOCK_RAW,MYPROTO); //int sock = socket(AF_ROUTE,SOCK_RAW,MYPROTO); struct sockaddr_nl addr; memset((void *)&addr, 0, sizeof(addr)); if (sock<0) return sock; addr.nl_family = AF_NETLINK; addr.nl_pid = getpid(); addr.nl_groups = MYMGRP; if (bind(sock,(struct sockaddr *)&addr,sizeof(addr))<0) return -1; return sock; } int read_event(int sock) { struct sockaddr_nl nladdr; struct msghdr msg; struct iovec iov[2]; struct nlmsghdr nlh; char buffer[65536]; int ret; int i=0; iov[0].iov_base = (void *)&nlh; iov[0].iov_len = sizeof(nlh); iov[1].iov_base = (void *)buffer; iov[1].iov_len = sizeof(buffer); msg.msg_name = (void *)&(nladdr); msg.msg_namelen = sizeof(nladdr); msg.msg_iov = iov; msg.msg_iovlen = sizeof(iov)/sizeof(iov[0]); ret=recvmsg(sock, &msg, 0); i++; if (ret<0) { return ret; } ///printf("%s\n",CMSG_DATA((struct cmsghdr *)msg.msg_control)); if(nlh.nlmsg_type==RTM_DELADDR){ printf("%d[DEL ADDR %d]\n",i,nlh.nlmsg_type); } printf("Type: %i (%s)\n",(nlh.nlmsg_type),lookup_name(typenames,nlh.nlmsg_type)); printf("Flag:"); #if 0 #define FLAG(x) if (nlh.nlmsg_type & x) printf(" %s",#x) FLAG(NLM_F_REQUEST); FLAG(NLM_F_MULTI); FLAG(NLM_F_ACK); FLAG(NLM_F_ECHO); FLAG(NLM_F_REPLACE); FLAG(NLM_F_EXCL); FLAG(NLM_F_CREATE); FLAG(NLM_F_APPEND); #undef FLAG #endif printf("\n"); printf("Seq : %i\n",nlh.nlmsg_seq); printf("Pid : %i\n",nlh.nlmsg_pid); printf("\n"); return 0; } int main(int argc, char *argv[]) { int nls = open_netlink(); if (nls<0) { err(1,"netlink"); } while (1) read_event(nls); return 0; } ``` ![](https://i.imgur.com/Ur6T3Nl.gif)