fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/lib/tun.c *
7 * Created: 2004-12-15 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2004-2018 Hampa Hug <hampa@hampa.ch> *
9 *****************************************************************************/
10
11/*****************************************************************************
12 * This program is free software. You can redistribute it and / or modify it *
13 * under the terms of the GNU General Public License version 2 as published *
14 * by the Free Software Foundation. *
15 * *
16 * This program is distributed in the hope that it will be useful, but *
17 * WITHOUT ANY WARRANTY, without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
19 * Public License for more details. *
20 *****************************************************************************/
21
22
23#include <config.h>
24
25#include <lib/tun.h>
26
27#include <string.h>
28#include <unistd.h>
29
30#include <sys/ioctl.h>
31#include <sys/fcntl.h>
32#include <sys/types.h>
33#include <sys/poll.h>
34#include <sys/socket.h>
35
36#include <linux/if.h>
37#include <linux/if_tun.h>
38
39
40/*
41 * Flags: IFF_TUN - TUN device (no Ethernet headers)
42 * IFF_TAP - TAP device
43 *
44 * IFF_NO_PI - Do not provide packet information
45 */
46
47static
48int tuntap_open (const char *name, int tap)
49{
50 int fd;
51 struct ifreq req;
52
53 fd = open ("/dev/net/tun", O_RDWR);
54
55 if (fd < 0) {
56 return (-1);
57 }
58
59 memset (&req, 0, sizeof (req));
60
61 req.ifr_flags = (tap ? IFF_TAP : IFF_TUN) | IFF_NO_PI;
62 strncpy (req.ifr_name, name, IFNAMSIZ - 1);
63
64 if (ioctl (fd, TUNSETIFF, (void *) &req) < 0) {
65 close (fd);
66 return (-1);
67 }
68
69 return (fd);
70}
71
72int tun_open (const char *name)
73{
74 return (tuntap_open (name, 0));
75}
76
77int tap_open (const char *name)
78{
79 return (tuntap_open (name, 1));
80}
81
82void tun_close (int fd)
83{
84 close (fd);
85}
86
87int tun_set_packet (int fd, const void *buf, unsigned cnt)
88{
89 ssize_t r;
90
91 r = write (fd, buf, cnt);
92
93 if (r < 0) {
94 return (1);
95 }
96
97 if ((unsigned) r != cnt) {
98 return (1);
99 }
100
101 return (0);
102}
103
104int tun_get_packet (int fd, void *buf, unsigned *cnt)
105{
106 ssize_t r;
107
108 r = read (fd, buf, *cnt);
109 if (r < 0) {
110 return (1);
111 }
112
113 *cnt = (unsigned) r;
114
115 return (0);
116}
117
118int tun_check_packet (int fd)
119{
120 int r;
121 struct pollfd pfd[1];
122
123 pfd[0].fd = fd;
124 pfd[0].events = POLLIN;
125
126 r = poll (pfd, 1, 0);
127 if (r < 0) {
128 return (0);
129 }
130
131 if ((pfd[0].revents & POLLIN) == 0) {
132 return (0);
133 }
134
135 return (1);
136}
137