- fixed poll emulation management
[vde.git] / vde-2 / vde_over_ns / vde_io.c
blob7f6b61b8a6802921fd7cf548c1243e731c0f16b5
1 /* ----------------------------------------------------------------------------
3 VDE_OVER_NS
4 (C) 2007 Daniele Lacamera
6 Derived from:
7 NSTX -- tunneling network-packets over DNS
9 (C) 2000 by Florian Heinz and Julien Oster
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License version 2, as
13 published by the Free Software Foundation.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 -------------------------------------------------------------------------- */
25 #include <sys/types.h>
26 #include <sys/ioctl.h>
27 #include <sys/time.h>
28 #include "compat/poll.h"
29 #include <sys/stat.h>
30 #include <sys/socket.h>
31 #include <net/if.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
34 #include <sys/socket.h>
35 #include <fcntl.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40 #include <errno.h>
41 #include <sysexits.h>
43 #include <config.h>
45 #include "fun.h"
47 #define MAXPKT 2000
50 static int ifd,ofd,nfd;
51 VDECONN *vconn = NULL;
53 void
54 init_vdesock(char *s)
56 struct vde_open_args open_args={.port=0,.group=NULL,.mode=0700};
57 if(s){
58 vconn = vde_open(s,"vde_over_ns",&open_args);
59 if(!vconn){
60 fprintf(stderr,"Fatal Error. Vdeplug %s: %s\n",s,strerror(errno));
61 exit(1);
63 ifd = ofd = vde_datafd(vconn);
64 return;
67 ifd = STDIN_FILENO, ofd = STDOUT_FILENO, nfd = -1;
70 void
71 open_ns(const char *ip)
73 struct sockaddr_in sock = { 0 };
75 fprintf(stderr, "Opening nameserver-socket... ");
76 if ((nfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
77 perror("failed!\nUnexpected error creating socket");
78 exit(EX_OSERR);
80 sock.sin_family = AF_INET;
81 sock.sin_port = htons(53);
82 sock.sin_addr.s_addr = inet_addr(ip);
83 if (connect(nfd, (struct sockaddr *)&sock,
84 sizeof(struct sockaddr_in))) {
85 perror("connect");
86 exit(EXIT_FAILURE);
88 fprintf(stderr, "Using nameserver %s\n", ip);
91 void
92 open_ns_bind(in_addr_t bindip)
94 struct sockaddr_in sock = { 0 };
96 fprintf(stderr, "Opening nameserver-socket... ");
97 if ((nfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
98 perror("failed!\nUnexpected error creating socket");
99 exit(EX_OSERR);
101 sock.sin_family = AF_INET;
102 sock.sin_port = htons(53);
104 sock.sin_addr.s_addr = bindip;
105 if (bind (nfd, (struct sockaddr *) &sock, sizeof(struct sockaddr_in))) {
106 fprintf(stderr, "failed!\n");
107 switch (errno) {
108 case EADDRINUSE:
109 fprintf(stderr, "Address is in use, please kill other processes "
110 "listening on UDP-Port 53 on %s\n",
111 bindip == INADDR_ANY ?
112 "all local IPs" : "the specified IP");
113 break;
114 case EACCES:
115 case EPERM:
116 fprintf(stderr, "Permission denied binding port 53. You generally "
117 "have to be root to bind privileged ports.\n");
118 break;
119 default:
120 fprintf(stderr, "Unexpected error: bind: %s\n", strerror(errno));
121 break;
123 exit(EXIT_FAILURE);
125 fprintf(stderr, "listening on 53/UDP\n");
128 struct nstxmsg *nstx_select (int timeout)
130 unsigned peerlen;
131 int c,pollret;
132 struct pollfd pfd[2];
133 static struct nstxmsg *ret = NULL;
134 u_int16_t vde_len;
135 pfd[0].fd=ifd;
136 pfd[1].fd=nfd;
137 pfd[0].events=pfd[1].events= POLLIN | POLLHUP;
138 for(;;){
139 pollret=poll(pfd,2,1000);
140 if(pollret<0){
141 perror("poll");
142 exit(1);
144 if (!ret)
145 ret = malloc(sizeof(struct nstxmsg));
146 if (pfd[0].revents&POLLIN) {
148 if(vconn!=NULL){
149 ret->len = vde_recv(vconn,ret->data,MAXPKT,0);
150 }else{
151 c=read(ifd,ret->data,2);
152 if(c<2)
153 return NULL;
154 vde_len=0;
155 vde_len+=((unsigned char)(ret->data[0]))<<8;
156 vde_len+=(unsigned char)(ret->data[1]);
158 ret->len=2;
159 while(ret->len < (vde_len + 2)){
160 ret->len += read(ifd, ret->data+ret->len, ((vde_len+2) - ret->len));
163 // fprintf(stderr,"Read %d.\n",vde_len);
165 ret->src = FROMTUN;
166 return ret;
170 if (pfd[1].revents&POLLIN) {
171 peerlen = sizeof(struct sockaddr_in);
172 ret->len = recvfrom(nfd, ret->data, MAXPKT, 0,
173 (struct sockaddr *) &ret->peer, &peerlen);
174 if(ret->len > 0){
176 #ifdef WITH_PKTDUMP
177 pktdump("/tmp/nstx/pkt.", *((unsigned short *)ret->data),
178 ret->data, ret->len, 0);
179 #endif
180 ret->src = FROMNS;
181 return ret;
185 return NULL;
190 void
191 send_vde(const char *data, size_t len)
193 static unsigned int outbuf[MAXPKT];
194 static int outp;
195 static u_int16_t outlen;
196 if(len<=0)
197 return;
198 if (vconn!=NULL){
199 vde_send(vconn,data,len,0);
200 return;
202 if(outp==0 && (len >=2) ){
203 outlen=2;
204 outlen+=(unsigned char)data[1];
205 outlen+=((unsigned char)(data[0]))<<8;
208 if(len>=outlen){
209 write(ofd,data,outlen);
210 send_vde(data+outlen,len-outlen);
211 return;
214 memcpy(outbuf+outp,data,len);
215 outp+=len;
216 if(outp>=outlen){
217 write(ofd,outbuf,outlen);
218 outp=0;
223 void
224 sendns (const char *data, size_t len, const struct sockaddr *peer)
226 if (peer)
227 sendto(nfd, data, len, 0, peer,
228 sizeof(struct sockaddr_in));
229 else
230 send(nfd, data, len, 0);
231 #ifdef WITH_PKTDUMP
232 pktdump("/tmp/nstx/pkt.", *((unsigned short *)data), data, len, 1);
233 #endif