Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2373881
  • 博文数量: 298
  • 博客积分: 7876
  • 博客等级: 准将
  • 技术积分: 5500
  • 用 户 组: 普通用户
  • 注册时间: 2011-02-23 13:39
文章存档

2013年(2)

2012年(142)

2011年(154)

分类: 系统运维

2011-04-07 14:57:43

17Unix路由套接字

 

注:所以文章红色字体代表需要特别注意和有问题还未解决的地方,蓝色字体表示需要注意的地方

 

1.     本文所介绍的程序平台

由于linux下面路由套接字接口与unix下面不一致 所以一下内容没有验证。

2.  路由套接字

Uinx系统集成了路由的功能,它包含相应的路由数据库可提供路由信息,用户可以使用命令方式来增加、修改、删除路由表中的项目,也可以只查看路由表中的信息。除此外,应用程序可以使用路由套接字实现对路由表的读/写操作。应用程序通过写操作把消息发送给路由子系统以增加或删除路由:通过读操作接收从路由子系统发送来的路由信息。

在实际应用中,路由的修改常常是由网络管理员通过系统命令来完成的,而应用程序一般只需要系统提供路由信息。

 

3.  创建路由套接字

3.1格式:

int sockfd;

sockfd=socket(AF_ROUTE,SOCK_RAW,0);

通信域为AF_ROUTE,它只能支持原始套接字,只有超级用户才能创建这个套接字

 

3.2 读写路由套接字

创建路由套接字后,与其他套接字一样,可以调用read()或者write()函数进行读写,但是由于系统内核是根据应用程序写入的消息来完成对路由信息的提供和修改的,因此,与其他套接字不同,写入和读出的数据都是有固定的格式的,例如:为了增加路由消息类型为RTM_ADD;为了获取路由,消息类型为RTM_GET;

路由套接字在里面定义了相应的消息类型,主要包括:

RTM_ADD增加路由

RTM_DELETE删除路由

RTM_CHANG改变路由

RTM_GET获取路由

RTM_MISS查询路由失败

 

3.2 通过路由套接字发送和接收的消息结构:

通过路由套接**换的结构有3个类型,分别如下:

struct  rt_msghdr {                 //from net/route.h

       u_short          rtm_msglen;   // to skip over non-understood messages

       u_char           rtm_version;   //future binary compatibility

       u_char           rtm_type;              //message type

       u_short          rtm_index;      //index for associated ifp

       int                  rtm_flags;       //flags, incl. kern &message, e.g. , DONE

       int                  rtm_addrs;      //bitmask indentifying sockaddrs in msg

       pid_t              rtm_pid;         // identify sender

       int                  rtm_seq;         // for sender to identify action

       int                  rtm_errno;      // why failed

       int                  rtm_use;         // from rtentry

       u_long            rtm_inits;        // which metrics we are initializing

       struct      rt_metrics       rtm_rmx;    //metrics themselves

};

 

struct  if_msghdr {                    // from net/if.h

       u_short          ifm_msglen;           // to skip over non-understood messages

       u_char           ifm_version;          // future binary compatibility

       u_char           ifm_type;               // message type

       int                  ifam_addrs;           // like rtm_addrs

       int                  ifam_flags;            // value of ifa_flags

       u_short          ifam_index;            // index for associated ifp

       int                  ifam_metric;          // value of ifa_metric

};

 

struct    ifa_msghdr {      //from net/if.h

       u_short   ifam_msglen;         // to skip over non-understood messages

       u_char    ifam_version;         // future binary compatibility

       u_char    ifam_type;             // message type

       int           ifam_addrs;           // like rtm_addrs

       int           ifam_flags;            // value of ifa_flags

       u_short   ifam_index;            // index for associated ifp

       int           ifam_metric;          // value of ifa_metric

};

 

每个结构有相同的三个成员,本消息的长度, 版本和类型。类型是表一所示的第一列中的

常值之一。长度成员允许应用进程跳过不理解的消息类型。

rtm_addrs, ifm_addrsifam_addrs3个成员是数位掩码(bitmask),指明本消息后跟的套

接口地址结构是8个可能选择中的那几个。下表给出了在中定义的可用于逻辑或成数位掩码的各个常值及具体数值。

数位掩码

数组下标

 

套接口地址结构包含

常值

数值

常值

数字

RTA_DST

RTA_GATEWAY

RTA_NETMASK

RTA_GENMASK

RTA_IFP

RTA_IFA

RTA_AUTHOR

RTA_BRD

0x01

0x02

0x04

0x08

0x10

0x20

0x40

0x80

RTAX_DST

RTAX_GATEWAY

RTAX_NETMASK

RTAX_GENMASK

RTAX_IFP

RTAX_IFA

RTAX_AUTHOR

FTAX_BRD

0

1

2

3

4

5

6

7

目的地址

网关地址

网络掩码

克隆掩码

接口名字

接口地址

重定向原创者

广播或点到点目的地址

 

 

RTAX_MAX

8

最大元素数目

 

 

当存在多个套接口地址结构时,它们总是按照表中所示顺序排列。

 

3.3 路由套接字实例(注意该实例未验证)

 

n      #include

n      #include

n      #include

n      #include

n      #include

n      #include

n      #include

n      #include

n      #include

n      void cp_rtaddrs(int,sockaddr_in *,sockaddr_in **); /*此函数用于将收到的套接字地址拷入套接字地址数据rt_info中。*/

n      #define BUFLEN (sizeof(rt_msghdr)+512)  /*消息缓冲区的长度*/

n      #define SEQ 1234  /*消息序号*/

n      int main(int argc,char **argv)

n      {

n        int sockfd;

n        char *buf;

n        pit_t pid;

n        ssize_t  n;

n        struct rt_msghdr *rtm;

n        struct sockaddr_in *sa, *rt_info[RTA_NUMBITS];

n        struct sockaddr_in *sin;

n        if(argc!=2){

n         printf("usage:%s\n",argv[0]);

n         exit(0);

n        }

n        sockfd=socket(AF_ROUTE,SOCK_RAW,0); /*创建路由套接字*/

n        if(sockfd==-1){

n          perror("socket error");

n          exit(1);

n         }

n      buf=(char*) calloc(1,BUFLEN); /*分配缓冲区*/

n        rtm=(rt_msghdr*)buf;

n        rtm->rtm_msglen=sizeof(rt_msghdr)+sizeof(sockaddr_in); /*消息长度*/

n        rtm->rtm_version=RTM_VERSION;  /*版本号*/

n        rtm->rtm_type=RTM_GET;   /* 消息类型*/

n        rtm->rtm_addrs=RTA_DST;  /*位屏蔽字*/

n        rtm->rtm_pid=pid=getpid();  /*进程号*/

n        rtm->rtm_seq=SEQ;   /*序号*/

n        sin=(sockaddr_in *) (rtm+1); /*将目的地址填入跟在消息头后的套接字地址项中。*/

n        sin->sin_family=AF_INET;

n        inet_pton(AF_INET,argv[1],&sin->sin_addr);

n        write(sockfd,rtm,rtm->rtm_msglen); /*发送RTM_GET消息给路由套接字*/

n      /*通个循环读取路由套接字中的消息,直到读到类型为RTM_GET、序号为SEQ、进程ID为当前进程ID的消息,表明该消息是所发消息的回应。*/

n      do {

n      n=read(sockfd,rtm,BUFLEN);

n        }while(rtm->rtm_type!=RTM_GET||rtm->rtm_seq!=SEQ||rtm->rtm_pid!=pid);

n        sa=(sockaddr_in*) (rtm+1);

n        cp_rtaddrs(rtm->rtm_addrs,sa,rt_info); /*将读取的套接字地址拷入数组rt_info中。*/

n        if((sa=rt_info[RTA_DST])!=NULL)   /*如果存在目的地址项*/

n        printf("dest:%s\n",inet_ntoa(sa->sin_addr));

n      if((sa=rt_info[RTA_GATEWAY])!=NULL)   /*如果存在网关地址项*/

n        printf("gateway:%s\n",inet_ntoa(sa->sin_addr));

n        

n      if((sa=rt_info[RTA_NETMASK])!=NULL)   /*如果存在网络掩码地址项*/

n        printf("netmask:%s\n",inet_ntoa(sa->sin_addr));

n        exit(0);

n      }

n      /*以下函数实现依次检查位屏蔽字,如果某项存在,则拷入对应项目,否则填入NULL*/

n      void cp_rtaddrs(int addrs,struct sockaddr_in *sa,struct sockaddr_in **rt_info)

n      {

n      int i;

n      for(i=0;i

n           if(addrs&(1<

n              rt_info[i]=sa;

n              sa++;

n           }

n           else

n              rt_info[i]=NULL;

n      }

n      }

 

阅读(4870) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~