使用AX.25封装创建TUN网络设备

时间:2014-03-17 20:53:06

标签: c linux sockets tun

我尝试使用AX.25封装创建TUN网络设备。 有效的是: - 创建设备 - 将其封装设置为ax25

无法正常工作的是设置硬件地址。这在ax.25通信中至关重要,因为它用于唯一地寻址节点。

首先我创建了TUN设备:

    struct ifreq ifr = { 0 };

    const char *clone_dev = "/dev/net/tun";
    if ((fd = open(clone_dev, O_RDWR)) == -1)
            error_exit(true, "Failed opening %s for tun device %s", clone_dev, dev_name);

    ifr.ifr_flags = IFF_TUN;

    strncpy(ifr.ifr_name, dev_name, IFNAMSIZ);

    if (ioctl(fd, TUNSETIFF, (void *)&ifr) == -1)
            error_exit(true, "Failed creating tun device %s", dev_name);

这导致:

root@travelmate:/home/folkert# ifconfig bla
bla       Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          POINTOPOINT NOARP 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:500 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

然后我将接口设置为AX.25封装:

    if (ioctl(fd, TUNSETLINK, ARPHRD_AX25) == -1)
            error_exit(true, "Failed setting tun device %s to ARPHRD_AX25", dev_name);

这导致:

root@travelmate:/home/folkert# ifconfig bla
bla       Link encap:AMPR AX.25  HWaddr   
          POINTOPOINT NOARP 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:500 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

然后是设置硬件地址的问题。 硬件地址是一个字符串,如: FH1GOU-1 首先,您需要将此地址的每个字节向右移一位。然后,ioctl-magic。 这总是失败。我还尝试过只创建一个tun-device,然后在其上调用ifconfig,这会导致一个"不支持"错误。 它当然可能是因为根本不可能在tun设备上设置ax.25硬件地址,但为什么可以设置ax.25封装?

    struct sockaddr *sa = &ifr.ifr_ifru.ifru_addr;

    struct sockaddr_ax25 *sap25 = (struct sockaddr_ax25 *)sa;
    memset(sap25, 0x00, sizeof(struct sockaddr_ax25));

    // tried AF_AX25 as well
    sa->sa_family = ARPHRD_AX25;

    char *min = strchr(hwaddr, '-');
    *min = 0x00;

    unsigned int hwaddr_len = strlen(hwaddr);

    char *call_str = sap25->sax25_call.ax25_call;

    unsigned int main_addr_size = sizeof(ax25_address) - 1;
    for(unsigned int idx=0; idx<main_addr_size; idx++)
    {
            int c = idx < hwaddr_len ? toupper(hwaddr[idx]) : ' ';

            call_str[idx] = (c << 1) & 0xfe;
    }

    if (min)
            call_str[main_addr_size] = (atoi(min + 1) << 1) & 0xfe;
    else
            call_str[main_addr_size] = 0x00;

    free(hwaddr);

    printf("%d\n", ioctl(fd, SIOCSIFHWADDR, &ifr));

最后一行,即ioctl,始终打印-1(=错误)。

我还尝试使用TUNSETIFF ioctl直接设置hw-address,但这似乎被忽略了。

有什么想法吗?

5 个答案:

答案 0 :(得分:1)

我认为问题出在&#34; ifr.ifr_flags = IFF_TUN&#34; 如果您计划使用ifr.ifr_flags = IFF_TAP |来创建TAP设备IFF_NO_PI;

不确定这是否对您有帮助。

答案 1 :(得分:1)

从那时起我就听说过tun设备根本就不支持ax25。

答案 2 :(得分:1)

btw我试过的其他东西:只需打开一个以太网封装的分接设备并将其启动,强制bpq将其视为以太网端口,为其提供bpq ax.25&#39;辅助接口&#39;不起作用。 bpq别名接口上的数据包永远不会进入tap设备的文件描述符。

但只是更改点击设备上的封装似乎工作正常。

ax.25处理更大的设置&#39;无论如何,在linux中都被打破了。进程无法连接到不同呼号上同一台机器内的其他进程,当有三脚架免费站点的人员死亡时,一半文档丢失或进入hudini等等。所以确实最好只是&#39;在用户空间中解决这个问题&#39;目前。我们稍后会修复内核堆栈:P整个事情似乎是由同一桌面上只有1个tranceiver和1个终端程序的人做出的:P

答案 3 :(得分:0)

只需使用点击设备(如果你不想要它就剥离数据包的最终硬件层)并且它工作正常。 (编辑:使它 - 随机 - 工作正常,只设置呼号位,然后由于上一个答案中描述的一些错误,甚至停止工作;)

root@user-X551MA:/home/user# ifconfig cb3rob0
cb3rob0   Link encap:AMPR AX.25  HWaddr CB3ROB 

无论是为tun工作而不是点击

请注意,TAP设备本身作为文件句柄打开。 (open()) 为了设置硬件地址(=callsign),您需要创建一个临时的NETWORK SOCKET HANDLE(socket()

你还需要一个套接字句柄调出接口(IFF_UP | IFF_RUNNING)禁用广播和arp并将mtu设置为更多'AX.25ish',例如256而不是1500默认值。

打开一个包含任何所谓支持的协议族的套接字(PF_PACKET工作正常,至少对于root并在ifoc名称字段设置为已创建的tap(tun?)设备名称的情况下执行ioctls

之后再次关闭套接字。除了配置之外,在点击设备上操作时不需要它。

答案 4 :(得分:0)

现在似乎不可能让这个工作起来。 虽然tun / tap属于'通用',但它似乎有2个错误:(对于TAP。使用TUN,完全不可能设置硬件地址,因为没有)。

1:在硬件地址结构中似乎有一些随机覆盖ssid的东西(以太网mac是6个字节,AX.25地址是7个字节(6个呼号,1个ssid +标志)尽管看起来工作正常但它现在不断将SSID设置为8;)

2:即使忽略第一个bug,read()也不会在将封装设置为AMPR AX.25并使用axcall或linpac发送一些数据后返回任何数据 (由于第一个bug,axcall'随机'抱怨无法将端口链接到某些/ etc / ax25 / axports条目。)

就我们而言,

/ etc / ax25 / axports已经过时了,但是其他程序仍在使用它,而不是扫描所有接口,可能是因为过去没有获得ipv4的接口接口列表的问题,并期待它匹配callign + ssid,它随机找不到......

下面的代码 - 应该根据tun / tap声称的'通用'以及它确实在BPQ和KISS接口上正确设置呼号这一事实,而不是TAP接口上的最后一个字节。

   #include<sys/types.h>
   #include<sys/stat.h>
   #include<fcntl.h>
   #include<sys/ioctl.h>
   #include<sys/socket.h>
   #include<linux/if_tun.h>
   #include<net/if_arp.h>
   #include<net/if.h>
   #include<string.h>
   #include<unistd.h>

   #define AXALEN 7

   int ax25tapcreate(char *tempdev,void *tempcall,int tempflags){
   struct ifreq tempifr;
   int tempfile;
   int tempsock;
   char *tempclonedev="/dev/net/tun";
   if((tempfile=open(tempclonedev,O_RDWR|O_SYNC))<0)return(-1);
   bzero(&tempifr,sizeof(tempifr));
   tempifr.ifr_flags=tempflags;
   if(*tempdev)strncpy(tempifr.ifr_name,tempdev,IFNAMSIZ-1);
   if(ioctl(tempfile,TUNSETIFF,&tempifr)<0){close(tempfile);return(-1);};
   if(ioctl(tempfile,TUNSETLINK,ARPHRD_AX25)==-1){close(tempfile);return(-1);};
   if(ioctl(tempfile,TUNSETPERSIST,0)<0){close(tempfile);return(-1);};

   tempsock=socket(PF_PACKET,SOCK_DGRAM,0);

   bzero(&tempifr,sizeof(tempifr));
   strncpy(tempifr.ifr_name,tempdev,IFNAMSIZ-1);
   bcopy(tempcall,&tempifr.ifr_hwaddr.sa_data,AXALEN);
   tempifr.ifr_hwaddr.sa_family=ARPHRD_AX25;
   if(ioctl(tempsock,SIOCSIFHWADDR,&tempifr)!=0){close(tempsock)close(tempfile);return(-1);};

   bzero(&tempifr,sizeof(tempifr));
   strncpy(tempifr.ifr_name,tempdev,IFNAMSIZ-1);
   tempifr.ifr_mtu=256;
   if(ioctl(tempsock,SIOCSIFMTU,&tempifr<0){close(tempsock);close(tempfile);return(-1);};

   bzero(&tempifr,sizeof(tempifr));
   strncpy(tempifr.ifr_name,tempdev,IFNAMSIZ-1);
   tempifr.ifr_flags=IFF_UP|IFF_RUNNING;
   if(ioctl(tempsock,SIOCSIFFLAGS,&tempifr<0){close(tempsock);close(tempfile);return(-1);};
   close(tempsock);

   return(tempfile);
   };

   //###EXAMPLECODE

   #include<stdio.h>
   #include<stdlib.h>
   #include<stdint.h>
   int main(){
   int fd;
   int n;
   int size;
   uint8_t call[AXALEN];
   call[0]=('C'<<1)&0xFE;
   call[1]=('B'<<1)&0xFE;
   call[2]=('3'<<1)&0xFE;
   call[3]=('R'<<1)&0xFE;
   call[4]=('O'<<1)&0xFE;
   call[5]=('B'<<1)&0xFE;
   call[6]=(4<<1)&0xFE;
   fd=ax25tapcreate("cb3rob0",&call,IFF_TAP);
   if(fd>0){printf("SUCCEEDED: %d\n",fd);system("ifconfig cb3rob0");};
   if(fd<0)exit(1);
   unsigned char buffer[10];
   while(1){
   size=read(fd,&buffer,sizeof(buffer));
   if(size>1)for(n=0;n<size;n++)printf("%02X ",buffer[n]);printf("\n---\n");
   if(size<0)exit(1);
   };//while1
   };

但是...无论如何都不会起作用......现在......

    root@user-TW100-E5:/home/user# ./tapcreate 
    SUCCEEDED: 3
    cb3rob0   Link encap:AMPR AX.25  HWaddr CB3ROB-8  
              UP BROADCAST RUNNING  MTU:256  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 (0.0 B)  TX bytes:0 (0.0 B)

注意callign中未保留的-8 SSID。 显然TAP不是用于其他框架而不是以太网。

还注意到TUN / TAP中的实际但不太严重的错误#3 ... IFF_BROADCAST标志在ifconfig中可见...在AX.25接口上无法将其关闭...所有的事情;)(现在为什么AX.25界面甚至有可能将某些内容改为ipv4-ish作为'广播';)