1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-30 03:19:02 +00:00
Files
nmap/libdnet-stripped/src/tun-linux.c
2008-09-19 06:12:25 +00:00

116 lines
2.0 KiB
C

/*
* tun-linux.c
*
* Universal TUN/TAP driver, in Linux 2.4+
* /usr/src/linux/Documentation/networking/tuntap.txt
*
* Copyright (c) 2001 Dug Song <dugsong@monkey.org>
*
* $Id: tun-linux.c 612 2005-09-12 02:18:06Z dugsong $
*/
#include "config.h"
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "dnet.h"
struct tun {
int fd;
intf_t *intf;
struct ifreq ifr;
};
tun_t *
tun_open(struct addr *src, struct addr *dst, int mtu)
{
tun_t *tun;
struct intf_entry ifent;
if ((tun = calloc(1, sizeof(*tun))) == NULL)
return (NULL);
if ((tun->fd = open("/dev/net/tun", O_RDWR, 0)) < 0 ||
(tun->intf = intf_open()) == NULL)
return (tun_close(tun));
tun->ifr.ifr_flags = IFF_TUN;
if (ioctl(tun->fd, TUNSETIFF, (void *) &tun->ifr) < 0)
return (tun_close(tun));
memset(&ifent, 0, sizeof(ifent));
strlcpy(ifent.intf_name, tun->ifr.ifr_name, sizeof(ifent.intf_name));
ifent.intf_flags = INTF_FLAG_UP|INTF_FLAG_POINTOPOINT;
ifent.intf_addr = *src;
ifent.intf_dst_addr = *dst;
ifent.intf_mtu = mtu;
if (intf_set(tun->intf, &ifent) < 0)
return (tun_close(tun));
return (tun);
}
const char *
tun_name(tun_t *tun)
{
return (tun->ifr.ifr_name);
}
int
tun_fileno(tun_t *tun)
{
return (tun->fd);
}
ssize_t
tun_send(tun_t *tun, const void *buf, size_t size)
{
struct iovec iov[2];
uint32_t type = ETH_TYPE_IP;
iov[0].iov_base = &type;
iov[0].iov_len = sizeof(type);
iov[1].iov_base = (void *)buf;
iov[1].iov_len = size;
return (writev(tun->fd, iov, 2));
}
ssize_t
tun_recv(tun_t *tun, void *buf, size_t size)
{
struct iovec iov[2];
uint32_t type;
iov[0].iov_base = &type;
iov[0].iov_len = sizeof(type);
iov[1].iov_base = (void *)buf;
iov[1].iov_len = size;
return (readv(tun->fd, iov, 2) - sizeof(type));
}
tun_t *
tun_close(tun_t *tun)
{
if (tun->fd > 0)
close(tun->fd);
if (tun->intf != NULL)
intf_close(tun->intf);
free(tun);
return (NULL);
}