2009-06-16 41 views
13

Tôi đang gặp khó khăn trong việc tìm ra vấn đề này - Tôi đang cố viết một chương trình tương tác với trình điều khiển đường hầm Linux. Ở cấp độ rất cơ bản, tôi chỉ muốn tạo một ứng dụng có khả năng truyền dữ liệu qua một đường hầm mạng. Tuy nhiên, tôi hoàn toàn thua lỗ như thế nào để thiết lập đúng trình điều khiển đường hầm để thực hiện điều này.Làm thế nào để giao tiếp với trình điều khiển vi điều khiển Linux

Tôi đang phát triển trên Ubuntu 9.04 và tôi đã tải mô-đun hạt nhân trình điều khiển đường hầm.

Có thiết bị /dev/net/tun, tuy nhiên không có thiết bị /dev/tunX. Tôi không thể tạo ra những thiết bị sử dụng ifconfig - bất cứ khi nào tôi chạy /sbin/ifconfig tun0 up, ví dụ, tôi nhận được lỗi sau:

tun0: ERROR while getting interface flags: No such device.

Nếu tôi cố gắng nhìn vào thiết bị /dev/net/tun, các lỗi sau được trình bày:

cat: /dev/net/tun: File descriptor in bad state.

Cố gắng mở /dev/tunX thông qua một chương trình nhỏ, về cơ bản, đơn giản

tun_fd = open("/dev/tun0", O_RDWR) 

Retu rns -1: ứng dụng đang chạy dưới dạng root và vẫn không thể mở thiết bị đường hầm này. Có thể mở /dev/net/tun, tuy nhiên điều này dường như không tạo ra thiết bị /dev/tunX mới để sử dụng thay thế.

Vì vậy, tóm lại - làm cách nào để viết một ứng dụng muốn sử dụng trình điều khiển đường hầm Linux? Mọi thông tin chi tiết sẽ được đánh giá cao.

Cảm ơn; ~ Robert

Trả lời

13

Đọc /usr/src/linux/Documentation/networking/tuntap.txt.

Bạn được yêu cầu phải open thiết bị /dev/net/tun. ioctl tiếp theo trên fd mở sẽ tạo giao diện mạng tun0 (hoặc bất kỳ thứ gì bạn muốn đặt tên). Các giao diện mạng của Linux không tương ứng với bất kỳ thiết bị /dev/* nào.

+0

@rmrobins; bạn đã làm gì để thực sự làm việc này? Tôi tin rằng tôi có một vấn đề rất giống với câu hỏi ban đầu của bạn. Tôi có thiết bị/dev/net/tun hiển thị, nhưng việc mở này không tạo ra giao diện mạng. Tôi đã cố gắng sử dụng các ví dụ br_select.c và br_sigio.c. – simon

+0

Như đã đề cập ở trên, mở/dev/net/tun. Sau đó, một ioctl sẽ được sử dụng để tạo ra giao diện thực tế. Các ioctl được gọi là TUNSETIFF, và đối số là loại struct ifreq. Cờ của ifreq struct nên được đặt thành IFF_TUN. Khi ioctl đã trở lại, trường ifr_name của ifreq struct sẽ được thiết lập với tên của giao diện đã mở. Hi vọng điêu nay co ich! – rmrobins

0

Xem http://vtun.cvs.sourceforge.net/viewvc/vtun/tun/examples/ để biết các ví dụ hoạt động.

+2

Tôi đã dành rất nhiều thời gian xem các ví dụ này, tuy nhiên chúng thực sự không hoạt động! Họ cố gắng trực tiếp mở các thiết bị/dev/tunX, không chính xác (như được hiển thị bởi liên kết được cung cấp một cách tạm thời). Điều này thực sự gây ra nhiều sự nhầm lẫn của tôi. – rmrobins

10

Không có /dev/tunX tệp thiết bị. Thay vào đó, bạn mở /dev/net/tun và định cấu hình nó qua ioctl() thành "điểm" thành tun0. Để hiển thị quy trình cơ bản, tôi sẽ tạo giao diện TUN bằng công cụ dòng lệnh ip tun tap và sau đó hiển thị mã C để đọc từ thiết bị TUN đó. Vì vậy, để tạo giao diện điều khiển qua dòng lệnh:

sudo ip tuntap add mode tun dev tun0 
ip addr add 10.0.0.0/24 dev tun0 # give it an ip 
ip link set dev tun0 up # bring the if up 
ip route get 10.0.0.2 # check that packets to 10.0.0.x are going through tun0 
ping 10.0.0.2 # leave this running in another shell to be able to see the effect of the next example 

Bây giờ chúng tôi đã tạo tun0.Để đọc/ghi các gói đến giao diện này từ chương trình không gian người dùng, bạn cần tương tác với tệp thiết bị /dev/net/tun bằng cách sử dụng ioctl(). Dưới đây là ví dụ sẽ đọc các gói đến giao diện tun0 và in kích thước:

#include <fcntl.h> /* O_RDWR */ 
#include <string.h> /* memset(), memcpy() */ 
#include <stdio.h> /* perror(), printf(), fprintf() */ 
#include <stdlib.h> /* exit(), malloc(), free() */ 
#include <sys/ioctl.h> /* ioctl() */ 

/* includes for struct ifreq, etc */ 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <linux/if.h> 
#include <linux/if_tun.h> 

int tun_open(char *devname) 
{ 
    struct ifreq ifr; 
    int fd, err; 

    if ((fd = open("/dev/net/tun", O_RDWR)) == -1) { 
     perror("open /dev/net/tun");exit(1); 
    } 
    memset(&ifr, 0, sizeof(ifr)); 
    ifr.ifr_flags = IFF_TUN; 
    strncpy(ifr.ifr_name, devname, IFNAMSIZ); // devname = "tun0" or "tun1", etc 

    /* ioctl will use ifr.if_name as the name of TUN 
    * interface to open: "tun0", etc. */ 
    if ((err = ioctl(fd, TUNSETIFF, (void *) &ifr)) == -1) { 
    perror("ioctl TUNSETIFF");close(fd);exit(1); 
    } 

    /* After the ioctl call the fd is "connected" to tun device specified 
    * by devname ("tun0", "tun1", etc)*/ 

    return fd; 
} 


int main(int argc, char *argv[]) 
{ 
    int fd, nbytes; 
    char buf[1600]; 

    fd = tun_open("tun0"); /* devname = ifr.if_name = "tun0" */ 
    printf("Device tun0 opened\n"); 
    while(1) { 
    nbytes = read(fd, buf, sizeof(buf)); 
    printf("Read %d bytes from tun0\n", nbytes); 
    } 
    return 0; 
} 
Các vấn đề liên quan