2017-05-29 94 views
1

我試圖在Java中與Linux tun驅動程序接口,因爲它在這裏解釋。帶有JNI的ioctl():破損的文件描述符

How to interface with the Linux tun driver

但因爲你不能調用的ioctl()用java,我現在用的是Java本地接口。只要我不在相同的文件中讀寫,它工作的很好。

如果我這樣做,我得到這個例外,我會通過翻譯「的FileDescriptor處於斷開狀態」:

java.io.IOException: Le descripteur du fichier est dans un mauvais état 
    at java.io.FileOutputStream.writeBytes(Native Method) 
    at java.io.FileOutputStream.write(FileOutputStream.java:326) 
    at WriterThread.main(WriterThread.java:54) 

這裏是Java代碼:

public static void main(String[] arg){ 
     File tunFile = new File("/dev/net/tun"); 
     FileOutputStream outStream; 
     FileInputStream inStream; 

     try { 

      inStream = new FileInputStream(tunFile); 
      outStream = new FileOutputStream(tunFile); 
      FileDescriptor fd = inStream.getFD(); 

      //getting the file descriptor 

      Field f = fd.getClass().getDeclaredField("fd"); 
      f.setAccessible(true); 
      int descriptor = f.getInt(fd); 


      //use of Java Native Interface 
      new TestOuvertureFichier().ioctl(descriptor); 

      while(true){ 
       System.out.println("reading"); 
       byte[] bytes = new byte[500]; 
       int l = 0; 
       l = inStream.read(bytes); 

       //the problem seems to come from here 
       outStream.write(bytes,0,l); 

      } 

     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

    } 

這裏C代碼:

JNIEXPORT void JNICALL Java_TestOuvertureFichier_ioctl(JNIEnv *env,jobject obj, jint descriptor){ 
     struct ifreq ifr; 
     memset(&ifr, 0, sizeof(ifr)); 
     ifr.ifr_flags = IFF_TUN; 
     strncpy(ifr.ifr_name, "tun0", IFNAMSIZ); 
     int err; 

     if ((err = ioctl(descriptor, TUNSETIFF, (void *) &ifr)) == -1) { 
      perror("ioctl TUNSETIFF");exit(1); 
     } 
     return; 
} 
+0

'新FileOutputStream(...)'一定會嘗試創建一個新文件。嘗試使用* one *'RandomAccessFile'而不是兩個文件流。 – EJP

回答

0

文件描述符創建FileInputStreamFileOutputStream對象時不被​​調用創建但是。這意味着你的代碼打開兩次/ dev/net/tun文件(創建兩個不同的文件描述符)。

inStream = new FileInputStream(tunFile); 
outStream = new FileOutputStream(tunFile); 

因此,讀寫控制僅應用於inStream,而不是outStream。 嘗試創建FileOutputStream,同時使用與FileInputStream相同的文件描述符。

outStream = new FileOutputStream(inStream.getFD());  

編輯:FileInputStream很可能會打開一個只讀的FD。正如Jayte所建議的,最好先創建一個RandomAccessFile,然後用它來創建這兩個數據流。

0

注意bytes應至少interfac的MTU大小e,例如1500字節。每次調用時,tun fd上的read()都會讀取完整的數據包。

在寫入tun設備之前,您應該操縱IP頭,尤其是接收到的數據包的源地址和目標地址。

1

G. Fiedler是對的,讀取應該至少與接口MTU一樣大,寫入不應超過MTU。除此之外,我會檢查:

  • 在嘗試讀取或寫入,界面了(IP地址添加XXXX/XX開發TUN0,IP鏈路集TUN0高達)
  • 您打開tun設備只能使用一次,例如使用RandomAccessFile。在這裏,我不確定inStream和outStream是否具有相同的文件描述符。