Update documents.
[tinc] / src / rt.c
1 /*
2     rt.c -- routing
3
4     Copyright (C) 2003-2004 Guus Sliepen <guus@tinc-vpn.org>,
5                   2003-2004 Ivo Timmermans <ivo@tinc-vpn.org>
6
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21     $Id$
22 */
23
24 #include "system.h"
25
26 #include "cfg/cfg.h"
27 #include "rt/edge.h"
28 #include "rt/node.h"
29 #include "rt/rt.h"
30 #include "rt/subnet.h"
31 #include "support/xalloc.h"
32 #include "tnl/tnl.h"
33 #include "vnd/vnd.h"
34 #include "tincd.h"
35
36 vnd_t *rt_vnd = NULL;
37 int rt_af = AF_UNSPEC;
38 int rt_macexpire = 600;
39 int rt_maxtimeout = 900;
40 rt_mode_t rt_mode = RT_MODE_ROUTER;
41 bool rt_priorityinheritance = false;
42 bool rt_hostnames = false;
43 bool rt_overwrite_mac = false;
44
45 avl_tree_t *rt_tnls;
46 avl_tree_t *rt_listeners;
47
48 static bool rt_tnl_accept(tnl_t *t) {
49         
50 }
51
52 static bool rt_vnd_recv(vnd_t *vnd, const void *buf, int len) {
53         route(myself, buf, len);
54 }
55
56 static bool rt_tnl_recv_packet(tnl_t *tnl, const void *buf, int len) {
57         edge_t *edge = tnl->data;
58         route(edge->to, buf, len);
59 }
60
61 static bool rt_tnl_recv_meta(tnl_t *tnl, const void *buf, int len) {
62 }
63
64 static void rt_outgoing(char *name) {
65         tnl_t *tnl;
66
67         clear(new(tnl));
68         
69 }
70
71 bool rt_init(void) {
72         char *bindtoaddress = NULL;
73         char *bindtointerface = NULL;
74         char *device = NULL;
75         char *iface = NULL;
76         char *port = NULL;
77         cfg_t *cfg;
78         subnet_t *subnet;
79         struct addrinfo hint, *ai, *aip;
80         int err;
81         int listeners;
82         char *connectto = NULL;
83         
84         cfg_choice_t mode_choice[] = {
85                 {"Router", RT_MODE_ROUTER},
86                 {"Switch", RT_MODE_SWITCH},
87                 {"Hub", RT_MODE_HUB},
88         };
89
90         cfg_choice_t af_choice[] = {
91                 {"IPv4", AF_INET},
92                 {"IPv6", AF_INET6},
93                 {"Any", AF_UNSPEC},
94         };
95
96         logger(LOG_INFO, _("rt: initialising"));
97
98         if(!subnet_init() || !node_init() || !edge_init())
99                 return false;
100
101         rt_tnls = avl_tree_new(NULL, NULL);
102         rt_listeners = avl_tree_new(NULL, NULL);
103
104         /* Read main configuration */
105
106         if(!cfg_get_choice(tinc_cfg, "AddressFamily", af_choice, AF_UNSPEC, &rt_af)
107                         || !cfg_get_string(tinc_cfg, "BindToAddress", NULL, &bindtoaddress)
108                         || !cfg_get_string(tinc_cfg, "BindToInterface", NULL, &bindtointerface)
109                         || !cfg_get_string(tinc_cfg, "Device", "/dev/net/tun", &device)
110                         || !cfg_get_bool(tinc_cfg, "Hostnames", false, &rt_hostnames)
111                         || !cfg_get_string(tinc_cfg, "Interface", tinc_netname, &iface)
112                         || !cfg_get_period(tinc_cfg, "MACExpire", 600, &rt_macexpire)
113                         || !cfg_get_period(tinc_cfg, "MaxTimeout", 3600, &rt_maxtimeout)
114                         || !cfg_get_choice(tinc_cfg, "Mode", mode_choice, RT_MODE_ROUTER, &rt_mode)
115                         || !cfg_get_bool(tinc_cfg, "PriorityInheritance", false, &rt_priorityinheritance))
116                 return false;
117
118         /* Read host configuration for myself */
119         
120         if(!cfg_get_string(myself->cfg, "Port", "655", &port))
121                 return false;
122
123         for(cfg = cfg_get(myself->cfg, "Subnet"); cfg; cfg = cfg_get_next(myself->cfg, cfg)) {
124                 if(!cfg_subnet(cfg, &subnet))
125                         return false;
126
127                 subnet->owner = myself;
128                 subnet_add(subnet);
129         }
130
131         /* Open the virtual network device */
132
133         clear(new(rt_vnd));
134         
135         replace(rt_vnd->device, device);
136         replace(rt_vnd->interface, iface);
137         
138         rt_vnd->mode = (rt_mode == RT_MODE_ROUTER) ? VND_MODE_TUN : VND_MODE_TAP;
139         rt_vnd->recv = rt_vnd_recv;
140
141         if(!vnd_open(rt_vnd)) {
142                 vnd_free(rt_vnd);
143                 return false;
144         }
145         
146         /* Create listening sockets */
147
148         hint.ai_family = rt_af;
149         hint.ai_socktype = SOCK_STREAM;
150         hint.ai_protocol = IPPROTO_TCP;
151         hint.ai_flags = AI_PASSIVE;
152
153         err = getaddrinfo(bindtoaddress, port, &hint, &ai);
154
155         if(err || !ai) {
156                 logger(LOG_ERR, _("rt: system call '%s' failed: %s"), "getaddrinfo", gai_strerror(err));
157                 return false;
158         }
159
160         listeners = 0;
161
162         for(aip = ai; aip; aip = aip->ai_next) {
163                 tnl_listen_t *listener;
164                 
165                 clear(new(listener));
166                 listener->local.address = *(struct sockaddr_storage *)aip->ai_addr;
167                 listener->local.id = myself->name;
168                 listener->type = SOCK_STREAM;
169                 listener->protocol = IPPROTO_TCP;
170                 // listener->local.cred = ...;
171                 listener->accept = rt_tnl_accept;
172
173                 if(tnl_listen(listener))
174                         listeners++;
175         }
176
177         freeaddrinfo(ai);
178
179         if(!listeners) {
180                 logger(LOG_ERR, _("rt: unable to create any listening socket!"));
181                 return false;
182         }
183
184         /* Setup outgoing connections */
185
186         for(cfg = cfg_get(tinc_cfg, "ConnectTo"); cfg; cfg = cfg_get_next(tinc_cfg, cfg)) {
187                 if(!cfg_string(cfg, NULL, &connectto))
188                         return false;
189
190                 if(!node_validname(connectto)) {
191                         logger(LOG_ERR, _("rt: invalid name for outgoing connection in %s line %d"), cfg->file, cfg->line);
192                         free(connectto);
193                         continue;
194                 }
195
196                 rt_outgoing(connectto);
197         }
198
199         return true;
200 }
201
202 bool rt_exit(void) {
203         edge_exit();
204         node_exit();
205         subnet_exit();
206
207         logger(LOG_INFO, _("rt: exitting"));
208 }
209
210