1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
|
/* tun.c system tunnel driver interface
*
* $Id: tun.c,v 1.3 1995/03/19 17:21:06 bdale Exp $
*
* Copyright 1991, Michael Westerhof, Sun Microsystems, Inc.
* This software may be freely used, distributed, or modified, providing
* this header is not removed.
*
*/
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netdb.h>
#include <fcntl.h>
#include <memory.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <syslog.h>
#include <unistd.h>
#include "ipip.h"
#ifndef FNDELAY
#define FNDELAY O_NDELAY
#endif
extern int errno;
#define IF_NAME "tun" /* for use with the error checking macros */
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* open and initialize the IO interface. Return -1 for error.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
int tun_open(ifp)
struct interface *ifp;
{
CK_IFNULL(ifp);
CK_IFTYPE(ifp,IF_TYPE_TUN);
if((ifp->status & IF_STAT_OPEN)) return 1;
ifp->fd = open(ifp->devname, O_RDWR);
if (ifp->fd<0) {
PERR(ifp->devname);
return -1;
}
if (fcntl(ifp->fd, F_SETFL, FNDELAY) < 0) {
PERR("setting non-blocking I/O on tunnel device");
return -1;
}
ifp->status = IF_STAT_OPEN;
return 1;
}
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Read data from the specified interface. Return a complete IP datagram.
* If the packet is not complete, then don't return anything.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
int tun_read(ifp, m)
struct interface *ifp;
struct message *m;
{
int n;
CK_IFNULL(ifp);
CK_IFTYPE(ifp,IF_TYPE_TUN);
CK_IFOPEN(ifp);
CK_MNULL(m);
n = read(ifp->fd, (char *)m->msg, MAX_SIZE);
if(n<0){
m->length = 0;
if(errno==EINTR)return 0;
if(errno==EWOULDBLOCK)return 0;
PERR("read from tunnel device");
return -1;
}
m->length = n;
return n;
}
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* write data from to the specified interface. Return as soon as possible.
* The buffer provided will be a complete IP datagram.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
int tun_send(ifp, m)
struct interface *ifp; /* the interface */
struct message *m; /* the message */
{
int n;
CK_IFNULL(ifp);
CK_IFTYPE(ifp,IF_TYPE_TUN);
CK_IFOPEN(ifp);
CK_MNULL(m);
if(m->length<=0)return 0;
n = write(ifp->fd, (char *)m->msg, m->length);
if(n<0){
if(errno==EINTR)return 0;
if(errno==EWOULDBLOCK){ /* should never happen :-) */
ifp->out_overruns++;
return 0;
}
PERR("write to tunnel device");
return -1;
}
if(n < m->length)ifp->out_overruns++;
return n;
}
|