2 vnd.c -- virtual network device management
4 Copyright (C) 2003-2004 Guus Sliepen <guus@tinc-vpn.org>,
5 2003-2004 Ivo Timmermans <ivo@tinc-vpn.org>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include <linux/if_tun.h>
29 #include "logger/logger.h"
30 #include "support/xalloc.h"
34 vnd_t *vnd_new(void) {
37 return clear(new(vnd));
40 void vnd_free(vnd_t *vnd) {
41 replace(vnd->device, NULL);
42 replace(vnd->interface, NULL);
43 replace(vnd->description, NULL);
47 void vnd_set(vnd_t *vnd, char *device, char *interface, vnd_mode_t mode, vnd_handler_t recv) {
48 replace(vnd->device, device);
49 replace(vnd->interface, interface);
54 static bool vnd_send(vnd_t *vnd, const void *buf, int len) {
57 result = write(vnd->fd.fd, buf, len);
59 if(result == len || result < 0 && (errno == EINTR || errno == EAGAIN)) {
60 logger(LOG_INFO, _("vnd: wrote packet of %d bytes to %s"), len, vnd->description);
64 logger(LOG_INFO, _("vnd: error writing packet of %d bytes to %s: %s"), len, vnd->description, strerror(errno));
69 static bool vnd_recv_handler(fd_t *fd) {
70 vnd_t *vnd = fd->data;
76 len = read(fd->fd, buf, sizeof buf);
79 logger(LOG_INFO, _("vnd: read packet of %d bytes from %s"), len, vnd->description);
80 return vnd->recv(vnd, buf, len);
83 if(len < 0 && (errno == EINTR || errno == EAGAIN))
86 logger(LOG_ERR, _("vnd: error reading packet from %s: %s"), vnd->description, strerror(errno));
91 bool vnd_open(vnd_t *vnd) {
92 struct ifreq ifr = {0};
95 vnd->device = xstrdup("/dev/net/tun");
97 vnd->fd.fd = open(vnd->device, O_RDWR | O_NONBLOCK);
100 logger(LOG_ERR, _("vnd: could not open %s: %s"), vnd->device, strerror(errno));
104 if(vnd->mode == VND_MODE_TUN)
105 ifr.ifr_flags = IFF_TUN;
107 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
110 strncpy(ifr.ifr_name, vnd->interface, IFNAMSIZ);
112 if(!ioctl(vnd->fd.fd, TUNSETIFF, &ifr)) {
114 free(vnd->interface);
115 vnd->interface = xstrdup(ifr.ifr_name);
117 logger(LOG_ERR, _("vnd: %s is not a Linux tun/tap device"), vnd->device);
124 vnd->send = vnd_send;
125 vnd->fd.read = vnd_recv_handler;
129 free(vnd->description);
131 asprintf(&vnd->description, "Linux tun/tap device %s (interface %s)", vnd->device, vnd->interface);
133 if(!fd_add(&vnd->fd))
136 logger(LOG_INFO, _("vnd: opened %s"), vnd->description);
141 bool vnd_close(vnd_t *vnd) {
146 logger(LOG_INFO, _("vnd: closed %s"), vnd->description);