Advertisement
Guest User

Untitled

a guest
Aug 22nd, 2023
41
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.53 KB | None | 0 0
  1. /*
  2. * /dev/config/tun network tunnel driver for BeOS
  3. * (c) 2003, mmu_man, [email protected]
  4. * licenced under MIT licence.
  5. */
  6. #include <Drivers.h>
  7. #include <KernelExport.h>
  8. #include <OS.h>
  9. #include <Select.h>
  10.  
  11. #include "BufferQueue.h"
  12. #include <net_buffer.h>
  13.  
  14. #include <condition_variable.h>
  15. #include <fcntl.h>
  16. #include <fs/select_sync_pool.h>
  17. #include <kernel.h>
  18. #include <net/if_tun.h>
  19. #include <stdbool.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <sys/param.h>
  23. #include <sys/types.h>
  24. #include <unistd.h>
  25.  
  26. // #define TUN_DRIVER_NAME "tun0"
  27. #define TAP_DRIVER_NAME "tap0"
  28. #define NET_TUN_MODULE_NAME "network/devices/tun/v1"
  29. #define BUFFER_QUEUE_MAX 30000
  30.  
  31. const char *device_names[] = {TAP_DRIVER_NAME, "misc/tun_interface", NULL};
  32.  
  33. int32 api_version = B_CUR_DRIVER_API_VERSION;
  34.  
  35. static net_buffer *create_filled_buffer(uint8* data, size_t bytes);
  36. static status_t get_packet_data(void* data, size_t* numbytes, net_buffer* buffer);
  37. static status_t retreive_packet(BufferQueue* queueToUse, void* data, size_t* numbytes);
  38.  
  39. status_t tun_open(const char* name, uint32 flags, void** cookie);
  40. status_t tun_close(void* cookie);
  41. status_t tun_free(void* cookie);
  42. status_t tun_ioctl(void* cookie, uint32 op, void* data, size_t len);
  43. status_t tun_read(void* cookie, off_t position, void* data, size_t * numbytes);
  44. status_t tun_write(void* cookie, off_t position, const void* data, size_t*numbytes);
  45. status_t tun_select(void* cookie, uint8 event, uint32 ref, selectsync* sync);
  46. status_t tun_deselect(void* cookie, uint8 event, selectsync* sync);
  47.  
  48. device_hooks tun_hooks = {
  49. tun_open,
  50. tun_close,
  51. tun_free,
  52. tun_ioctl,
  53. tun_read,
  54. tun_write,
  55. tun_select,
  56. tun_deselect,
  57. NULL,
  58. NULL};
  59.  
  60.  
  61. /**
  62. * @brief Represents the tun_struct data structure used for tun driver management.
  63. *
  64. * The `tun_struct` struct holds various semaphores and BufferQueue pointers
  65. * that are used for tun driver management and communication.
  66. *
  67. * @var name Name to distingush whatever side has opened the driver.
  68. * @var sendQueue A pointer to the BufferQueue used for sending data to the interface.
  69. * @var recvQueue A pointer to the BufferQueue used for receiving data from the interface.
  70. * @var readLock A pointer to a mutex lock that will be used for blocking tun_read.
  71. * @var readWait A pointer to a ConditionVariable that will be used for blocking tun_read.
  72. */
  73. typedef struct tun_struct {
  74. uint32_t name[3];
  75. unsigned long flags;
  76. BufferQueue* sendQueue;
  77. BufferQueue* recvQueue;
  78. ConditionVariable* readWait;
  79. mutex readLock;
  80. union {
  81. struct {
  82. select_sync_pool* select_pool;
  83. mutex selectLock;
  84. bool readable;
  85. bool writable;
  86. } app;
  87. };
  88. } tun_struct;
  89.  
  90. BufferQueue gAppQueue(BUFFER_QUEUE_MAX);
  91. BufferQueue gIntQueue(BUFFER_QUEUE_MAX);
  92. ConditionVariable gReadWait;
  93. select_sync_pool* gSelectPool = NULL;
  94. struct net_buffer_module_info *gBufferModule;
  95.  
  96.  
  97. /**
  98. * @brief Creates a new net_buffer and fills it with the specified data.
  99. *
  100. * This function creates a new net_buffer using the gBufferModule and fills it with the
  101. * data provided. The net_buffer must be later freed by calling gBufferModule->free().
  102. *
  103. * @param data Pointer to the byte stream data to be copied into the net_buffer.
  104. * @param bytes Number of bytes to copy from the data pointer.
  105. * @return A pointer to the newly created net_buffer if successful, NULL otherwise.
  106. */
  107. static net_buffer*
  108. create_filled_buffer(uint8* data, size_t bytes)
  109. {
  110. net_buffer* buffer = gBufferModule->create(256);
  111. if (buffer == NULL)
  112. return NULL;
  113. status_t status = gBufferModule->append(buffer, data, bytes);
  114. if (status != B_OK) {
  115. gBufferModule->free(buffer);
  116. return NULL;
  117. }
  118. return buffer;
  119. }
  120.  
  121.  
  122. /**
  123. * @brief Reads data from a net_buffer into a memory buffer.
  124. *
  125. * This function reads data from the specified net_buffer and stores it in the
  126. * provided memory buffer. The number of bytes to read is determined by the value
  127. * pointed to by numbytes.
  128. *
  129. * @param data A pointer to the memory buffer where the data will be stored.
  130. * @param numbytes A pointer to a size_t variable specifying the number of bytes
  131. * to read from the net_buffer. Upon return, this variable will
  132. * contain the actual number of bytes read.
  133. * @param buffer A pointer to the net_buffer from which to read the data.
  134. * @return status_t The status of the operation. B_OK if successful, an error code
  135. * otherwise.
  136. */
  137. static status_t
  138. get_packet_data(void* data, size_t* numbytes, net_buffer* buffer)
  139. {
  140. status_t status;
  141. status = gBufferModule->read(buffer, 0, data, *numbytes);
  142. if (status != B_OK) {
  143. dprintf("Failed reading data\n");
  144. gBufferModule->free(buffer);
  145. return status;
  146. }
  147. return B_OK;
  148. }
  149.  
  150.  
  151. /**
  152. * @brief Retrieve a packet from the specified BufferQueue.
  153. *
  154. * This function retrieves a packet from the specified BufferQueue and populates the data
  155. * buffer with the packet's content. The numbytes parameter will be updated with the size
  156. * of the retrieved packet data.
  157. *
  158. * @param queueToUse Pointer to the BufferQueue to retrieve the packet from.
  159. * @param data Pointer to the buffer that will hold the retrieved packet data.
  160. * @param numbytes Pointer to the size of the data buffer. Will be updated with the actual
  161. * size of the retrieved packet data.
  162. *
  163. * @return status_t Returns B_OK if the packet was successfully retrieved and the data
  164. * populated. Returns an appropriate error code otherwise.
  165. */
  166. static status_t
  167. retreive_packet(BufferQueue* queueToUse, void* data, size_t* numbytes)
  168. {
  169. net_buffer* buffer;
  170. status_t status = B_OK;
  171.  
  172. if (queueToUse->Used() > 0) {
  173. status = queueToUse->Get(*numbytes, true, &buffer);
  174. if (status != B_OK)
  175. return status;
  176. *numbytes = buffer->size;
  177. status = get_packet_data(data, numbytes, buffer);
  178. if (status != B_OK)
  179. return B_ERROR;
  180. status = B_OK;
  181. } else
  182. *numbytes = 0;
  183. return status;
  184. }
  185.  
  186.  
  187. static void
  188. tun_notify(tun_struct* tun)
  189. {
  190. // bool select_pool_check = tun->app.select_pool != NULL;
  191. bool readable = tun->recvQueue->Used() != 0;
  192. if (!tun->app.readable && readable) {
  193. dprintf("Check Read\n");
  194. notify_select_event_pool(tun->app.select_pool, B_SELECT_READ);
  195. }
  196. tun->app.readable = readable;
  197.  
  198. bool writable = tun->sendQueue->Used() != BUFFER_QUEUE_MAX;
  199. if (!tun->app.writable && writable) {
  200. dprintf("Check Write\n");
  201. notify_select_event_pool(tun->app.select_pool, B_SELECT_WRITE);
  202. }
  203. tun->app.writable = writable;
  204. }
  205.  
  206.  
  207. status_t
  208. init_hardware(void)
  209. {
  210. /* No Hardware */
  211. dprintf("tun:init_hardware()\n");
  212. return B_OK; // Need to change to B_ERROR
  213. }
  214.  
  215.  
  216. status_t
  217. init_driver(void)
  218. {
  219. /* Init driver */
  220. dprintf("tun:init_driver()\n");
  221. status_t status = get_module(NET_BUFFER_MODULE_NAME, (module_info**)&gBufferModule);
  222. if (status != B_OK) {
  223. dprintf("Getting BufferModule failed\n");
  224. return status;
  225. }
  226. return B_OK;
  227. }
  228.  
  229.  
  230. void uninit_driver(void)
  231. {
  232. dprintf("tun:uninit_driver()\n");
  233. put_module(NET_BUFFER_MODULE_NAME);
  234. }
  235.  
  236.  
  237. /**
  238. * @brief Opens the tun driver interface and sets up the driver for the interface.
  239. *
  240. * This function opens the tun driver interface, initializes necessary resources,
  241. * and sets up the driver for the interface operation.
  242. *
  243. * @param name The name of the tun driver interface.
  244. * @param flags Flags for the driver interface (if applicable).
  245. * @param cookie A pointer to a void pointer that will hold the tun_struct data
  246. * after the function call.
  247. *
  248. * @return Returns B_OK on success, or an appropriate error code on failure.
  249. */
  250. status_t
  251. tun_open(const char* name, uint32 flags, void** cookie)
  252. {
  253. /* Setup driver for interface here */
  254. tun_struct* tun = new tun_struct();
  255. memcpy(tun->name, "app", sizeof(tun->name));
  256. tun->sendQueue = &gIntQueue;
  257. tun->recvQueue = &gAppQueue;
  258. tun->readWait = &gReadWait;
  259. tun->flags = 0;
  260. mutex_init(&tun->readLock, "read_avail");
  261. mutex_init(&tun->app.selectLock, "select_lock");
  262. tun->app.readable = tun->recvQueue->Used() != 0;
  263. tun->app.writable = tun->sendQueue->Used() != BUFFER_QUEUE_MAX;
  264. tun->app.select_pool = gSelectPool;
  265. *cookie = static_cast<void*>(tun);
  266. return B_OK;
  267. }
  268.  
  269.  
  270. status_t
  271. tun_close(void* cookie)
  272. {
  273. /* Close interface here */
  274. tun_struct* tun = static_cast<tun_struct*>(cookie);
  275. tun->readWait->NotifyAll(B_ERROR);
  276. snooze(10); // Due to a lock timing issue, we sleep for 10ms
  277. return B_OK;
  278. }
  279.  
  280.  
  281. status_t
  282. tun_free(void* cookie)
  283. {
  284. tun_struct* tun = static_cast<tun_struct*>(cookie);
  285. delete tun;
  286. return B_OK;
  287. }
  288.  
  289.  
  290. status_t
  291. tun_ioctl(void* cookie, uint32 op, void* data, size_t len)
  292. {
  293. /* IOCTL for driver */
  294. tun_struct* tun = static_cast<tun_struct*>(cookie);
  295. // dprintf("%n: tun_ioctl | op = %" B_PRIu32 "\n", tun->name, op);
  296. switch (op) {
  297. case TUNSETIFF:
  298. memcpy(tun->name, "int", sizeof(tun->name));
  299. tun->sendQueue = &gAppQueue;
  300. tun->recvQueue = &gIntQueue;
  301. memset(&tun->app, 0, sizeof(tun->app));
  302. return B_OK;
  303. case B_SET_NONBLOCKING_IO:
  304. tun->flags |= B_SET_NONBLOCKING_IO;
  305. return B_OK;
  306. default:
  307. return B_DEV_INVALID_IOCTL;
  308. };
  309. return B_OK;
  310. }
  311.  
  312.  
  313. /**
  314. * @brief Reads data from the TUN device.
  315. *
  316. * This function reads data from the TUN device represented by the given `cookie` which
  317. * is casted to a tun_struct. The mutex within the tun variable will get locked, passed onto
  318. * the condition variable to wait if is anything in the recieve queue, retrieves the packet
  319. * from the receive queue, and unlocks the mutex when the operation is complete.
  320. *
  321. * @param cookie A pointer to a `tun_struct` representing the TUN interface/application.
  322. * @param position The position from where to read data (not used in this function).
  323. * @param data A pointer to a buffer where the read data will be stored.
  324. * @param numbytes On input, the number of bytes to read; on output, the number of bytes read
  325. * (see retreive_packet).
  326. *
  327. * @return A status code indicating the success or failure of the read operation.
  328. * B_OK if successful, an error code otherwise.
  329. */
  330. status_t
  331. tun_read(void* cookie, off_t position, void* data, size_t* numbytes)
  332. {
  333. tun_struct* tun = static_cast<tun_struct*>(cookie);
  334. status_t status;
  335. if (tun->flags & B_SET_NONBLOCKING_IO) {
  336. status = retreive_packet(tun->recvQueue, data, numbytes);
  337. if (status != B_OK)
  338. return -EAGAIN;
  339. tun_notify(tun);
  340. } else {
  341. mutex_lock(&tun->readLock);
  342. while (tun->recvQueue->Used() == 0) {
  343. status = tun->readWait->Wait(&tun->readLock, B_CAN_INTERRUPT);
  344. if (status != B_OK) {
  345. mutex_unlock(&tun->readLock);
  346. return status;
  347. }
  348. }
  349. status = retreive_packet(tun->recvQueue, data, numbytes);
  350. if (status != B_OK)
  351. return status;
  352. mutex_unlock(&tun->readLock);recv
  353. }
  354. return B_OK;
  355. }
  356.  
  357.  
  358. /**
  359. * @brief Write data to the TUN device.
  360. *
  361. * This function writes data to the TUN device BufferQueue specified by the given tun_struct
  362. * 'cookie' and notifies the condition variable for read to continue.
  363. *
  364. * @param cookie Pointer to the TUN device data (tun_struct).
  365. * @param position The offset position for writing (not used in this implementation).
  366. * @param data Pointer to the data to be written.
  367. * @param numbytes Pointer to the size of the data to be written. On output, it will
  368. * contain the actual number of bytes written.
  369. * @return status_t Returns B_OK if the write operation is successful,
  370. * or an appropriate error code if there is a failure.
  371. */
  372. status_t
  373. tun_write(void* cookie, off_t position, const void* data, size_t* numbytes)
  374. {
  375. tun_struct* tun = static_cast<tun_struct*>(cookie);
  376. size_t used = tun->sendQueue->Used();
  377. net_buffer* packet = NULL;
  378. // Buffer is full or will be so we have to drop the packet
  379. if ((used + *numbytes) >= BUFFER_QUEUE_MAX) {
  380. return B_WOULD_BLOCK;
  381. }
  382. packet = create_filled_buffer((uint8*)data, *numbytes);
  383. if (packet == NULL)
  384. return B_ERROR;
  385. tun->sendQueue->Add(packet);
  386. if (tun->flags & B_SET_NONBLOCKING_IO) {
  387. tun->readWait->NotifyAll();
  388. tun_notify(tun);
  389. }
  390. return B_OK;
  391. }
  392.  
  393.  
  394. status_t
  395. tun_select(void* cookie, uint8 event, uint32 ref, selectsync* sync)
  396. {
  397. tun_struct* tun = static_cast<tun_struct*>(cookie);
  398. mutex_lock(&tun->app.selectLock);
  399. // size_t readUsed = tun->recvQueue->Used();
  400. // size_t writeUsed = tun->sendQueue->Used();
  401. // bool wasReadable = readUsed != 0;
  402. // bool wasWritable = writeUsed != BUFFER_QUEUE_MAX;
  403.  
  404. if (event != B_SELECT_READ && event != B_SELECT_WRITE) {
  405. mutex_unlock(&tun->app.selectLock);
  406. return B_BAD_VALUE;
  407. }
  408. status_t status = add_select_sync_pool_entry(&tun->app.select_pool, sync, event);
  409. if (status != B_OK) {
  410. mutex_unlock(&tun->app.selectLock);
  411. return B_BAD_VALUE;
  412. }
  413.  
  414. if (event == B_SELECT_READ && tun->recvQueue->Used())
  415. notify_select_event(sync, event);
  416. if (event == B_SELECT_WRITE && (tun->sendQueue->Used() != BUFFER_QUEUE_MAX))
  417. notify_select_event(sync, event);
  418. mutex_unlock(&tun->app.selectLock);
  419. return B_OK;
  420. }
  421.  
  422.  
  423. status_t
  424. tun_deselect(void* cookie, uint8 event, selectsync* sync)
  425. {
  426. tun_struct* tun = static_cast<tun_struct*>(cookie);
  427. mutex_lock(&tun->app.selectLock);
  428. if (event != B_SELECT_READ && event != B_SELECT_WRITE) {
  429. mutex_unlock(&tun->app.selectLock);
  430. return B_BAD_VALUE;
  431. }
  432. status_t status = remove_select_sync_pool_entry(&tun->app.select_pool, sync, event);
  433. mutex_unlock(&tun->app.selectLock);
  434. return status;
  435. }
  436.  
  437.  
  438. const char**
  439. publish_devices()
  440. {
  441. /* Publish driver names to devfs */
  442. return device_names;
  443. }
  444.  
  445.  
  446. device_hooks*
  447. find_device(const char* name)
  448. {
  449. /* Find hooks for driver functions */
  450. return &tun_hooks;
  451. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement