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