【问题标题】:creating a TUN network device with AX.25 encapsulation使用 AX.25 封装创建 TUN 网络设备
【发布时间】:2016-05-31 06:58:41
【问题描述】:

我正在尝试创建一个采用 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 (=error)。

我也尝试过直接使用 TUNSETIFF ioctl 设置硬件地址,但这似乎被忽略了。

有什么想法吗?

【问题讨论】:

    标签: c linux sockets tun


    【解决方案1】:

    我认为问题在于“ifr.ifr_flags = IFF_TUN” 如果您计划创建 TAP 设备,请使用 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;

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

    【讨论】:

    • 认为重点是直接做一个bpq设备。以正常方式获取 bpq 帧。零后跟没有 fcs 的 ax25 数据包。现在似乎还可以通过将辅助 bpq 设备添加到分接设备来工作(以前没有)。但随后会产生原始以太网 II 帧。不是零 格式...无论如何,也许侵入kissattach 的规定是获得ax.25 接口的一种不那么肮脏的方式。至少这些只是一个接口并导致文件描述符;)
    【解决方案2】:

    从那以后我就听说 tun 设备根本不支持 ax25。

    【讨论】:

      【解决方案3】:

      顺便说一句,我尝试了其他方法:只需打开以太网封装的 Tap 设备并将其启动,强制 bpq 将其视为以太网端口,并为其提供 bpq ax.25“辅助接口”不起作用。 bpq 别名接口上的数据包永远不会进入 tap 设备的文件描述符。

      但只是更改 Tap 设备上的封装似乎可以正常工作。

      ax.25 在 linux 中处理“更大的设置”无论如何都被破坏了。进程无法通过不同的呼号连接到同一台机器内的其他进程,当有三脚架免费站点的人死亡时,一半的文档丢失或变成了 hudini,等等。所以现在最好只是“在用户空间中解决它”。我们稍后会修复内核堆栈:P 整个事情似乎是由在同一张桌子上的计算机上只有 1 个收发器和 1 个终端程序的人制作的:P

      【讨论】:

      • 奇怪的事情:使用 bpq 别名接口时,点击“以太网”接口上的 read() 确实返回。只是它没有任何有效载荷。
      • 它们现在“有点”似乎可以工作......只是在启动了 tap 设备的关联 bpq 设备后,您可以读取和写入以太网 II 帧:DST-MAC SRC-MAC $08 $FF AX25LENGTH( LSB-MSB)+5 AX25DST(长度和第一次 ax25 调用之间没有任何关系)而实际的 bpq 格式是:0(零) AX25DST bpq 内部数据包上的前导 0 似乎是某种“接吻命令字节”之类的东西。不要与长度 + 5 的 MSB 中通常也为零(但不总是)混淆
      • 也不知道为什么在以太网帧类型之后和实际原始数据包数据之前的有效载荷长度是+5。但在内核中也是如此。 (以太网 II 具有最小的有效负载大小,并且本身没有长度字段,因此必须以某种方式传输实际的有效负载长度 - 但是 +5 的东西到底是从哪里来的;)
      • 请注意,对于 dst/src 调用,实际的 ax.25 最小数据包大小为 2*7 字节,并且比以太网 II 最小有效负载少 1 个控制字节。这就是它有 16 位长度字段的原因。
      【解决方案4】:

      目前似乎无法让它发挥作用。 尽管 tun/tap 属于“通用”,但其中似乎有 2 个错误妨碍了它:(对于 TAP。使用 TUN 完全不可能设置硬件地址,因为没有)。

      1:在硬件地址结构中,似乎有一些东西随机覆盖了 ssid(以太网 MAC 为 6 个字节,AX.25 地址为 7 个字节(6 个呼号,1 个 ssid + 标志),尽管之前它似乎一直工作正常将 SSID 设置为 8 ;)

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

      /etc/ax25/axports 就我们而言已经过时了,但其他程序仍在使用它,而不是扫描所有接口,这可能是由于过去获取没有 ipv4 的接口的接口列表时出现问题,并期待它匹配一个呼号+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)
      

      注意呼号中未要求的 -8 SSID。 显然,TAP 不适用于以太网以外的其他框架。

      还要注意 TUN/TAP 中实际但不太严重的错误 #3...IFF_BROADCAST 标志在 ifconfig 中可见...在 AX.25 接口上无法将其关闭...最重要的是 ;) (现在为什么 AX.25 接口甚至有可能将 ipv4-ish 的东西打开为“广播”;)

      【讨论】:

        【解决方案5】:

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

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

        不管它是否适用于 tun 而不是 tap

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

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

        使用任何应该支持的协议系列打开一个套接字(PF_PACKET 可以正常工作,至少对于 root 而言,并在 ifr 名称字段设置为已创建的分接头(tun?)设备的名称的情况下执行 ioctls

        然后再次关闭套接字。在 Tap 设备上的操作过程中不需要它,除了配置它。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-08-09
          • 1970-01-01
          • 2016-09-19
          • 1970-01-01
          相关资源
          最近更新 更多