4 Copyright (C) 2003-2004 Guus Sliepen <guus@tinc-vpn.org>,
5 2003-2004 Ivo Timmermans <ivo@tinc-vpn.org>
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.
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.
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.
30 #include "rt/subnet.h"
31 #include "support/xalloc.h"
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;
46 avl_tree_t *rt_listeners;
48 static bool rt_tnl_accept(tnl_t *t) {
52 static bool rt_vnd_recv(vnd_t *vnd, const void *buf, int len) {
53 route(myself, buf, len);
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);
61 static bool rt_tnl_recv_meta(tnl_t *tnl, const void *buf, int len) {
64 static void rt_outgoing(char *name) {
72 char *bindtoaddress = NULL;
73 char *bindtointerface = NULL;
79 struct addrinfo hint, *ai, *aip;
82 char *connectto = NULL;
84 cfg_choice_t mode_choice[] = {
85 {"Router", RT_MODE_ROUTER},
86 {"Switch", RT_MODE_SWITCH},
90 cfg_choice_t af_choice[] = {
96 logger(LOG_INFO, _("rt: initialising"));
98 if(!subnet_init() || !node_init() || !edge_init())
101 rt_tnls = avl_tree_new(NULL, NULL);
102 rt_listeners = avl_tree_new(NULL, NULL);
104 /* Read main configuration */
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))
118 /* Read host configuration for myself */
120 if(!cfg_get_string(myself->cfg, "Port", "655", &port))
123 for(cfg = cfg_get(myself->cfg, "Subnet"); cfg; cfg = cfg_get_next(myself->cfg, cfg)) {
124 if(!cfg_subnet(cfg, &subnet))
127 subnet->owner = myself;
131 /* Open the virtual network device */
135 replace(rt_vnd->device, device);
136 replace(rt_vnd->interface, iface);
138 rt_vnd->mode = (rt_mode == RT_MODE_ROUTER) ? VND_MODE_TUN : VND_MODE_TAP;
139 rt_vnd->recv = rt_vnd_recv;
141 if(!vnd_open(rt_vnd)) {
146 /* Create listening sockets */
148 hint.ai_family = rt_af;
149 hint.ai_socktype = SOCK_STREAM;
150 hint.ai_protocol = IPPROTO_TCP;
151 hint.ai_flags = AI_PASSIVE;
153 err = getaddrinfo(bindtoaddress, port, &hint, &ai);
156 logger(LOG_ERR, _("rt: system call '%s' failed: %s"), "getaddrinfo", gai_strerror(err));
162 for(aip = ai; aip; aip = aip->ai_next) {
163 tnl_listen_t *listener;
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;
173 if(tnl_listen(listener))
180 logger(LOG_ERR, _("rt: unable to create any listening socket!"));
184 /* Setup outgoing connections */
186 for(cfg = cfg_get(tinc_cfg, "ConnectTo"); cfg; cfg = cfg_get_next(tinc_cfg, cfg)) {
187 if(!cfg_string(cfg, NULL, &connectto))
190 if(!node_validname(connectto)) {
191 logger(LOG_ERR, _("rt: invalid name for outgoing connection in %s line %d"), cfg->file, cfg->line);
196 rt_outgoing(connectto);
207 logger(LOG_INFO, _("rt: exitting"));