AF_ROUTE 路由套接字

更新时间:
2024-05-13
下载文档

AF_ROUTE 路由套接字

在 SylixOS 中,路由套接字为开发者提供了增加、删除、修改路由的方法,使用路由套接字的方法与其他协议的使用方法类似,创建完 socket 套接字后就可以通过相应的 ioctl 命令对路由进行操作。另外,AF_ROUTE 路由套接字还可以实时检查路由变化信息及其网卡变化信息等,使用路由套接字监控路由信息时,调用 read 函数会阻塞,直到路由信息发生改变,路由信息发生改变有多种情况,包括插拔网线、开启或者关闭接口以及添加或者删除路由等等都可以引起路由信息的变动。

在这里仅仅举了添加路由时 read 会及时的返回该路由的所有详细信息,需要注意的是指针之间的转换。

#include <stdio.h>
#include <unistd.h>
#include <net/route.h>
#include <string.h>
#include <socket.h>
struct  rtm_type_parse {
    u_char      rtm_type;
    void      (*func)(void *);
};
#define NAMESIZE   2048
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x)  (sizeof(x) / sizeof((x)[0]))
#endif
#define ROUND_UP(x, align)  (size_t)(((size_t)(x) +  (align - 1)) & ~(align - 1))
#define SO_ROUND_UP(len)    ROUND_UP(len, sizeof(size_t))
#define SA_ROUND_UP(x)      SO_ROUND_UP(((struct sockaddr *)(x))->sa_len)
#define SA_NEXT(t, x)       (t)((PCHAR)(x) + SA_ROUND_UP(x))
#define SET_TAG() printf("--------------------------------------------------------------\n")
char  *num2family[] = {
       [0] = "AF_UNSPEC",
       [1] = "AF_UNIX",
       [2] = "AF_INET",
       [10] = "AF_INET6",
       [16] = "AF_ROUTE",
       [17] = "AF_PACKET",
       [18] = "AF_LINK"
};
int main (int argc, char **argv)
{
    int                  iSock;
    ssize_t              iRet;
    char                 rBuf[NAMESIZE];
    struct rt_msghdr    *pMy;
    struct sockaddr_in  *psockaddrin;
    void                *p;
    int                  bits = 0;
    iSock = socket(AF_ROUTE, SOCK_RAW, 0);
    if (iSock < 0) {
      fprintf(stdout, "fail to socket\n");
      return (-1);
    }
    printf("iSock is %d\n", iSock);
    printf("rtentry count is %d\n", (int )sizeof(struct rt_msghdr));
    pMy = (struct rt_msghdr *)rBuf;
    printf("here is 1\n");
    iRet = read(iSock, rBuf, NAMESIZE);
    if (iRet < 0) {
        fprintf(stdout, "fail to read\n");
        return (-1);
    }
    if (pMy->rtm_type == RTM_ADD) {
        if ((pMy->rtm_type != RTM_ADD) ||
            (pMy->rtm_version != RTM_VERSION)) {
            printf("<%s> type[%x] mismatch.\n", "RTM_GET", pMy->rtm_type);
        }
        SET_TAG();
        printf("<%s> rtm_msglen = %d.\n", "RTM_GET", pMy->rtm_msglen);
        printf("<%s> rtm_version = %d.\n", "RTM_GET", pMy->rtm_version);
        printf("<%s> rtm_pid = %d.\n", "RTM_GET", pMy->rtm_pid);
        printf("<%s> rtm_seq = %d.\n", "RTM_GET", pMy->rtm_seq);
        printf("<%s> rtm_errno = %d.\n", "RTM_GET", pMy->rtm_errno);
        printf("<%s> rtm_use = %d.\n", "RTM_GET", pMy->rtm_use);
        printf("<%s> rtm_inits = %lu.\n", "RTM_GET", pMy->rtm_inits);
        SET_TAG();
        p = (void *)(pMy + 1);
        psockaddrin = (struct sockaddr_in *)p;
        if (pMy->rtm_addrs & RTA_DST) {
            psockaddrin = (struct sockaddr_in *)p;
            printf("<%s> <RTA_DST> net family: %s\n", "RTM_GET", num2family[psockaddrin->sin_family]);
            printf("<%s> <RTA_DST> net port: %d\n", "RTM_GET", ntohs(psockaddrin->sin_port));
            printf("<%s> <RTA_DST> dest addr: %s\n", "RTM_GET", inet_ntoa(psockaddrin->sin_addr));
            bits++;
            SET_TAG();
        }
        if (pMy->rtm_addrs & RTA_GATEWAY) {
            if (bits > 0) {
                psockaddrin = SA_NEXT(struct sockaddr_in *, psockaddrin);
            } else {
                psockaddrin = (struct sockaddr_in *)p;
            }
            printf("<%s> <RTA_GATEWAY> net family: %s\n", "RTM_GET", num2family[psockaddrin->sin_family]);
            printf("<%s> <RTA_GATEWAY> net port: %d\n", "RTM_GET", ntohs(psockaddrin->sin_port));
            printf("<%s> <RTA_GATEWAY> dest addr: %s\n", "RTM_GET", inet_ntoa(psockaddrin->sin_addr));
            bits++;
            SET_TAG();
        }
        if (pMy->rtm_addrs & RTA_NETMASK) {
            if (bits > 0) {
                psockaddrin = SA_NEXT(struct sockaddr_in *, psockaddrin);
            } else {
                psockaddrin = (struct sockaddr_in *)p;
            }
            printf("<%s> <RTA_NETMASK> net family: %s\n", "RTM_GET", num2family[psockaddrin->sin_family]);
            printf("<%s> <RTA_NETMASK> net port: %d\n", "RTM_GET", ntohs(psockaddrin->sin_port));
            printf("<%s> <RTA_NETMASK> dest addr: %s\n", "RTM_GET", inet_ntoa(psockaddrin->sin_addr));
            bits++;
            SET_TAG();
        }
    } else {
        fprintf(stdout, "you need to add others\n");
        return (-1);
    }
    return (0);
}

在 SylixOS Shell 下运行程序,结果显示如下:

在一个终端执行程序,read 会进入阻塞状态;

# ./AF_ROUTE
iSock is 3
rtentry count is 152
here is 1

直到在另一个终端添加路由:

#  route add -host 123.123.123.123 mask 255.0.0.0 123.0.0.1 dev en1

上个终端才会输出该路由的所有信息:

iSock is 3
rtentry count is 152
here is 1
--------------------------------------------------------------
<RTM_GET> rtm_msglen = 272.
<RTM_GET> rtm_version = 5.
<RTM_GET> rtm_pid = 0.
<RTM_GET> rtm_seq = 0.
<RTM_GET> rtm_errno = 0.
<RTM_GET> rtm_use = 0.
<RTM_GET> rtm_inits = 0.
--------------------------------------------------------------
<RTM_GET> <RTA_DST> net family: AF_INET
<RTM_GET> <RTA_DST> net port: 24931
<RTM_GET> <RTA_DST> dest addr: 123.123.123.123
--------------------------------------------------------------
<RTM_GET> <RTA_GATEWAY> net family: AF_INET
<RTM_GET> <RTA_GATEWAY> net port: 28769
<RTM_GET> <RTA_GATEWAY> dest addr: 123.0.0.1
--------------------------------------------------------------
<RTM_GET> <RTA_NETMASK> net family: AF_INET
<RTM_GET> <RTA_NETMASK> net port: 29754
<RTM_GET> <RTA_NETMASK> dest addr: 255.0.0.0
--------------------------------------------------------------
文档内容是否对您有所帮助?
有帮助
没帮助