zswself 发表于 2006-7-23 15:25:51

universal tun/tap driver 写入问题

打开tun设备;
配置tun(/sbin/ifconfig tun0 10.8.0.2 pointopoint 10.8.0.1 mtu 1500)
执行 ifconfig 显示配置后的网卡信息;
向tun写入一个ping包.

在RedHat下运行无事;在uClinux下运行,写IP包时程序死。程序与运行结果见下,谁能帮忙???

程序:
#include <sys/ioctl.h>
#include <fcntl.h>
#include <stdio.h>
#include <linux/if_tun.h>
#include <net/if.h>
#include <stdarg.h>

/* Path to ifconfig tool */
#define IFCONFIG_PATH "/sbin/ifconfig"

void set_nonblock (int fd);
int open_tun (const char *dev, char **actual);
int openvpn_snprintf(char *str, size_t size, const char *format, ...);

int
main (void)
{
        char *actualname = NULL;
        char command_line;
        char *ifconfig_local = "10.8.0.2";
        char *ifconfig_remote = "10.8.0.1";
        int tun_mtu = 1500;
                // 10.8.0.1 ping 10.8.0.2 的一个ping 包
        char packet[] = {0x45,0x00,0x00,0x3c,0x75,0xb5,0x00,0x00,0x80,0x01,
                0xb0,0xf9,0x0a,0x08,0x00,0x01,0x0a,0x08,0x00,0x02,
                0x08,0x00,0x1e,0x5c,0x03,0x00,0x2c,0x00,0x61,0x62,
                0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,
                0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,
                0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69};
        const int packetlen = sizeof(packet)/sizeof(char);
        int tuntapfd;
        int i;

        tuntapfd = open_tun ("tun", &actualname);
        openvpn_snprintf (command_line, sizeof (command_line),
                          IFCONFIG_PATH " %s %s pointopoint %s mtu %d",
                          actualname,
                          ifconfig_local,
                          ifconfig_remote,
                          tun_mtu
                          );
        printf ("%s\n", command_line);
        system (command_line);//执行command
        system ("ifconfig");
        for (i=0; i<packetlen; i++)
        {
                printf ("0x%.2x,", packet);
        }
        printf ("\n");
        write (tuntapfd, packet, packetlen); //向tun写入ping包
        free (actualname);
        return 0;
}

int open_tun (const char *dev, char **actual)
{
struct ifreq ifr;
int fd;

char *device = "/dev/tun"; //uClinux下tun设备的路径
//char *device = "/dev/net/tun"; //RedHat下tun设备的路径
int size;

if ((fd = open (device, O_RDWR)) < 0) //创建描述符
{
    printf ("Cannot open TUN/TAP dev %s\n", device);
    exit();
}
memset (&ifr, 0, sizeof (ifr));
ifr.ifr_flags = IFF_NO_PI;
if (!strncmp (dev, "tun", 3)) {
      ifr.ifr_flags |= IFF_TUN;
}
else if (!strncmp (dev, "tap", 3)) {
      ifr.ifr_flags |= IFF_TAP;
}
else {
    printf ("I don't recognize device %s as a TUN or TAP device\n",dev);
    exit();
}
if (strlen (dev) > 3) //unit number specified?
    strncpy (ifr.ifr_name, dev, IFNAMSIZ);
if (ioctl (fd, TUNSETIFF, (void *) &ifr) < 0) //打开虚拟网卡
{
    printf ("Cannot ioctl TUNSETIFF %s\n", dev);
    exit();
}
set_nonblock (fd);
printf ("TUN/TAP device %s opened\n", ifr.ifr_name);
size = strlen(ifr.ifr_name)+1;
*actual = (char *) malloc (size);
memcpy (*actual, ifr.ifr_name, size);
return fd;
}

/* Set a file descriptor to non-blocking */
void
set_nonblock (int fd)
{
if (fcntl (fd, F_SETFL, O_NONBLOCK) < 0)
    printf ("Set file descriptor to non-blocking mode failed\n");
}

/*
* This is necessary due to certain buggy implementations of snprintf,
* that don't guarantee null termination for size > 0.
*/
int openvpn_snprintf(char *str, size_t size, const char *format, ...)
{
va_list arglist;
int ret = 0;
if (size > 0)
    {
      va_start (arglist, format);
      ret = vsnprintf (str, size, format, arglist);
      va_end (arglist);
      str = 0;
    }
return ret;
}

RedHat下运行结果:
TUN/TAP device tun0 opened
/sbin/ifconfig tun0 10.8.0.2 pointopoint 10.8.0.1 mtu 1500
eth0      Link encap:EthernetHWaddr 00:0C:6E:B8:14:1C
          inet addr:192.168.0.1Bcast:192.168.255.255Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICASTMTU:1500Metric:1
          RX packets:5751317 errors:0 dropped:0 overruns:0 frame:0
          TX packets:192457 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100
          RX bytes:2313894496 (2206.7 Mb)TX bytes:82363908 (78.5 Mb)
          Interrupt:10

lo      Link encap:Local Loopback
          inet addr:127.0.0.1Mask:255.0.0.0
          UP LOOPBACK RUNNINGMTU:16436Metric:1
          RX packets:11332180 errors:0 dropped:0 overruns:0 frame:0
          TX packets:11332180 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:775516557 (739.5 Mb)TX bytes:775516557 (739.5 Mb)

tun0      Link encap:Point-to-Point Protocol
          inet addr:10.8.0.2P-t-P:10.8.0.1Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICASTMTU:1500Metric: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:10
          RX bytes:0 (0.0 b)TX bytes:0 (0.0 b)

0x45,0x00,0x00,0x3c,0x75,0xffffffb5,0x00,0x00,0xffffff80,0x01,0xffffffb0,
0xfffffff9,0x0a,0x08,0x00,0x01,0x0a,0x08,0x00,0x02,0x08,0x00,0x1e,
0x5c,0x03,0x00,0x2c,0x00,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,
0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,
0x76,0x77,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,

uClinux下运行结果:
TUN/TAP device tun0 opened
/sbin/ifconfig tun0 10.8.0.2 pointopoint 10.8.0.1 mtu 1500
eth0      Link encap:EthernetHWaddr 00:40:95:36:35:34
          inet addr:192.168.0.5Bcast:192.168.0.255Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICASTMTU:1500Metric:1
          RX packets:438 errors:0 dropped:0 overruns:0 frame:0
          TX packets:90 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          Interrupt:17

lo      Link encap:Local Loopback
          inet addr:127.0.0.1Mask:255.0.0.0
          UP LOOPBACK RUNNINGMTU:16436Metric:1
          RX packets:12 errors:0 dropped:0 overruns:0 frame:0
          TX packets:12 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0

tun0      Link encap:UNSPECHWaddr 62-00-AC-DE-62-00-00-00-00-00-00-00-00-00-00-00
          inet addr:10.8.0.2P-t-P:10.8.0.1Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICASTMTU:1500Metric: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:10

0x45,0x00,0x00,0x3c,0x75,0xb5,0x00,0x00,0x80,0x01,0xb0,0xf9,0x0a,
0x08,0x00,0x01,0x0a,0x08,0x00,0x02,0x08,0x00,0x1e,0x5c,0x03,0x00,
0x2c,0x00,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,
0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x61,
0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,
Unhandled fault: alignment exception (13) at 0x00000001
fault-common.c(97): start_code=0x610040, start_stack=0x61ff90)
Internal error: Oops: 0
CPU: 0
pc : [<000a9240>]    lr : [<0078e662>]    Not tainted
sp : 00759e58ip : 0078e662fp : 00759e88
r10: 002741a0r9 : 00000a71r8 : 00759ed8
r7 : 0029b880r6 : 002d8440r5 : 002d8440r4 : 00000005
r3 : 00000045r2 : 0000003cr1 : 00000014r0 : 00000005
Flags: nzCvIRQs onFIQs onMode SVC_32Segment kernel
Control: 0
Process uctun (pid: 24, stackpage=00759000)
Stack:
00759e40:                   0078e662 000a924020000013 ffffffff 00759e84 00759e68
00759e60: 0007b644 0007b074 00000010 002d844000000000 00000008 00000000 00759ea4
00759e80: 00759e8c 00098da8 000a90e4 002e782c002741cc 002741ac 00759ed4 00759ea8
00759ea0: 00098eb4 00098b48 00000040 00274290002741cc 002741a0 002741bc 00000a71
00759ec0: 60000013 00284f14 00759f00 00759ed800099034 00098e1c 0000012c 00274090
00759ee0: 00000001 fffffffb 00284b60 0000000000274080 00759f2c 00759f04 0001ffc0
00759f00: 00098fac 002d8440 002e7800 0000003c0000003c 0078e662 00000004 00759f6c
00759f20: 00759f3c 00759f30 00020078 0001ff1800759f68 00759f40 00090730 00020074
00759f40: 00080000 0000003c 000113a0 ffffffea00000000 0061fe10 006165c4 00759f80
00759f60: 00759f6c 0009077c 000905b4 0061fe4c00000000 00759fac 00759f84 00030f18
00759f80: 00090768 000152b0 000150f8 0000000000000000 0061ffa4 00758000 00014b00
00759fa0: 00000000 00759fb0 00014960 00030e4c00000000 00015194 00000003 0061fe10
00759fc0: 0000003c 0061fe10 00000000 000000000061ffa4 00000001 0061ff9c 00000000
00759fe0: 006165c4 0061fdf4 0061fdf8 0061fde4006101c4 0061259c 60000010 00000003
Backtrace:
Function entered at [<000a90d4>] from [<00098da8>]
r7 = 00000000r6 = 00000008r5 = 00000000r4 = 002D8440
Function entered at [<00098b38>] from [<00098eb4>]
r6 = 002741ACr5 = 002741CCr4 = 002E782C
Function entered at [<00098e0c>] from [<00099034>]
Function entered at [<00098f9c>] from [<0001ffc0>]
Function entered at [<0001ff08>] from [<00020078>]
Function entered at [<00020064>] from [<00090730>]
Function entered at [<000905a4>] from [<0009077c>]
Function entered at [<00090758>] from [<00030f18>]
Function entered at [<00030e3c>] from [<00014960>]
r8 = 00014B00r7 = 00758000r6 = 0061FFA4r5 = 00000000
r4 = 00000000
Code: e203400f e1a00004 (e49c2004) e49c1004 e2400005
Kernel panic: Aiee, killing interrupt handler

In interrupt handler - not syncing


运行结果不同之处:
1.tun 网卡信息
Redhat
tun0      Link encap:Point-to-Point Protocol
uClinux
tun0      Link encap:UNSPECHWaddr 62-00-AC-DE-62-00-00-00-00-00-00-00-00-00-00-00
2. 打印输出的IP包
RedHat下,以1开头的字节加上了ffff.
3. RedHat下未死,uClinux下死。

这是为什么????

zswself 发表于 2006-7-24 09:25:47

有人在uClinux下用过universal tun/tap

没有人在uClinux下用过universal tun/tap driver吗?

lumit-support-1 发表于 2006-7-27 20:08:08

没有用过,不太清楚

zswself 发表于 2006-8-18 08:37:58

问题解决

从网上搜到一篇文章,http://lkml.org/lkml/2005/3/18/146,照此修改tun.c, 问题解决。内容如下:

Hi!

This patch fixes an alignment-problem in tun_get_user: Only
ethernet-frames need to be headed by 2 bytes (due to their size of 14
bytes), IP-frames should not be touched. The patch changes
tun_get_user to reserve 2 bytes of the skb for TUN_TAP_DEVs and 0
bytes otherwise.

Ciao,
Sven

--- linux-2.6.11.2/drivers/net/tun.c        2005-03-09 09:11:32.000000000 +0100
+++ mylinux-2.6.11.2/drivers/net/tun.c        2005-03-18 18:19:02.906871952 +0100
@@ -226,7 +226,7 @@ static __inline__ ssize_t tun_get_user(s
{
        struct tun_pi pi = { 0, __constant_htons(ETH_P_IP) };
        struct sk_buff *skb;
-        size_t len = count;
+        size_t len = count, align = 0;

        if (!(tun->flags & TUN_NO_PI)) {
                if ((len -= sizeof(pi)) > len)
@@ -235,13 +235,17 @@ static __inline__ ssize_t tun_get_user(s
                if(memcpy_fromiovec((void *)&pi, iv, sizeof(pi)))
                        return -EFAULT;
        }
+
+        if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV)
+                align = NET_IP_ALIGN;

-        if (!(skb = alloc_skb(len + 2, GFP_KERNEL))) {
+        if (!(skb = alloc_skb(len + align, GFP_KERNEL))) {
                tun->stats.rx_dropped++;
                return -ENOMEM;
        }

-        skb_reserve(skb, 2);
+        if (align)
+                skb_reserve(skb, align);
        if (memcpy_fromiovec(skb_put(skb, len), iv, len))
                return -EFAULT;

-
页: [1]
查看完整版本: universal tun/tap driver 写入问题