65810c211894ca01e9fbca86dad7c792e3758906
[tinc] / tnl / test.c
1 /*
2     test.c -- tunnel test
3
4     Copyright (C) 2003-2004 Guus Sliepen <guus@tinc-vpn.org>,
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20     $Id: tnl.c 1379 2004-03-27 11:59:31Z guus $
21 */
22
23 #include "system.h"
24
25 #include <gnutls/gnutls.h>
26 #include <gnutls/x509.h>
27
28 #include "logger/logger.h"
29 #include "support/avl.h"
30 #include "support/sockaddr.h"
31 #include "support/xalloc.h"
32 #include "tnl/tnl.h"
33
34 static const int addressfamily = AF_UNSPEC;
35 static const int socktype = SOCK_STREAM;
36 static const int protocol = IPPROTO_TCP;
37
38 bool server_recv_meta(struct tnl *tnl, const void *buf, int len) {
39         const char *in = buf;
40         char out[len];
41
42         for(int i = 0; i < len; i++) {
43                 if(isupper(in[i]))
44                         out[i] = tolower(in[i]);
45                 else if(islower(in[i]))
46                         out[i] = toupper(in[i]);
47                 else
48                         out[i] = in[i];
49         }
50
51         tnl->send_meta(tnl, out, len);
52
53         return true;
54 }
55
56 bool server_accept(struct tnl *tnl) {
57         logger(LOG_INFO, _("Got connection from %s"), tnl->remote.id);
58         tnl->recv_meta = server_recv_meta;
59         return true;
60 }
61
62 void server(char *port) {
63         struct addrinfo *ai, hint = {0};
64         int err;
65         tnl_listen_t *listen = clear(new(listen));
66
67         hint.ai_family = addressfamily;
68         hint.ai_socktype = socktype;
69         hint.ai_protocol = protocol;
70         hint.ai_flags = AI_PASSIVE;
71
72         err = getaddrinfo(NULL, port, &hint, &ai);
73
74         if(err || !ai) {
75                 logger(LOG_WARNING, _("Error looking up port %s: %s"), port, gai_strerror(err));
76                 return;
77         }
78
79         if(sizeof listen->local.address < ai->ai_addrlen) {
80                 logger(LOG_ERR, "%d < %d!", sizeof listen->local.address, ai->ai_addrlen);
81                 return;
82         }
83
84         memcpy(&listen->local.address, ai->ai_addr, ai->ai_addrlen);
85         listen->local.id = xstrdup("CommonA");
86         listen->type = socktype;
87         listen->protocol = protocol;
88         listen->accept = server_accept;
89
90         logger(LOG_DEBUG, "Nu ga ik iets doen hoor");
91         if(!tnl_ep_set_x509_credentials(&listen->local, "server_key", "server_cert", "trust", NULL)) {
92                 logger(LOG_ERR, "Couldn't set X.509 credentials!");
93                 return;
94         }
95
96         if(!tnl_listen(listen)) {
97                 logger(LOG_ERR, _("Could not listen!"));
98                 return;
99         }
100 }
101
102 bool client_stdin_handler(fd_t *fd) {
103         tnl_t *tnl = fd->data;
104         char buf[1024];
105         int len;
106
107         len = read(fd->fd, buf, sizeof buf);
108
109         if(len <= 0) {
110                 gnutls_bye(tnl->session, GNUTLS_SHUT_WR);
111                 fd_del(fd);
112                 return false;
113         }
114         
115         tnl->send_meta(tnl, buf, len);
116
117         return true;
118 }
119
120 bool client_recv_meta(struct tnl *tnl, const void *buf, int len) {
121         write(1, buf, len);
122         return true;
123 }
124
125 bool client_error(tnl_t *tnl, int err) {
126         exit(err);
127 }
128
129 bool client_accept(tnl_t *tnl) {
130         fd_t *fd;
131
132         logger(LOG_INFO, _("Connected to %s"), tnl->remote.id);
133         tnl->recv_meta = client_recv_meta;
134
135         clear(new(fd));
136         fd->fd = 0;
137         fd->read = client_stdin_handler;
138         fd->data = tnl;
139         fd_add(fd);
140
141         return true;
142 }
143
144 void client(char *host, char *port) {
145         struct addrinfo *ai, hint = {0};
146         int err;
147         static tnl_t *tnl;
148
149         hint.ai_family = addressfamily;
150         hint.ai_socktype = socktype;
151
152         err = getaddrinfo(host, port, &hint, &ai);
153
154         if(err || !ai) {
155                 logger(LOG_WARNING, _("Error looking up %s port %s: %s"), host, port, gai_strerror(err));
156                 return;
157         }
158
159         clear(new(tnl));
160         memcpy(&tnl->remote.address, ai->ai_addr, ai->ai_addrlen);
161         tnl->local.id = xstrdup("CommonB");
162         tnl->remote.id = xstrdup("CommonA");
163         tnl->type = socktype;
164         tnl->protocol = protocol;
165         tnl->accept = client_accept;
166         tnl->error = client_error;
167
168         if(!tnl_ep_set_x509_credentials(&tnl->local, "client_key", "client_cert", "trust", NULL)) {
169                 logger(LOG_ERR, "Couldn't set credentials!");
170                 return;
171         }
172
173         if(!tnl_connect(tnl)) {
174                 logger(LOG_ERR, _("Could not connect to server!"));
175                 return;
176         }
177 }
178
179 int main(int argc, char **argv) {
180         gnutls_global_init();
181         gnutls_global_init_extra();
182
183         fd_init();
184         logger_init(argv[0], LOGGER_MODE_NULL);
185
186         if(argc > 2)
187                 client(argv[1], argv[2]);
188         else if(argc > 1)
189                 server(argv[1]);
190         else {
191                 logger(LOG_ERR, "Usage: %s [host] port\n", argv[0]);
192                 return 1;
193         }
194
195         fd_run();
196
197         return 0;
198 }