route.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /*
  2. route.c -- routing
  3. Copyright (C) 2000-2002 Ivo Timmermans <itimmermans@bigfoot.com>,
  4. 2000-2002 Guus Sliepen <guus@sliepen.warande.net>
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. $Id: route.c,v 1.1.2.22 2002/02/10 21:57:54 guus Exp $
  17. */
  18. #include "config.h"
  19. #if defined(HAVE_FREEBSD) || defined(HAVE_OPENBSD)
  20. #include <sys/param.h>
  21. #endif
  22. #include <sys/socket.h>
  23. #include <netinet/in.h>
  24. #if defined(HAVE_SOLARIS) || defined(HAVE_OPENBSD)
  25. #include <net/if.h>
  26. #define ETHER_ADDR_LEN 6
  27. #else
  28. #include <net/ethernet.h>
  29. #endif
  30. #include <netinet/if_ether.h>
  31. #include <utils.h>
  32. #include <xalloc.h>
  33. #include <syslog.h>
  34. #include <string.h>
  35. #include <avl_tree.h>
  36. #include "net.h"
  37. #include "connection.h"
  38. #include "subnet.h"
  39. #include "route.h"
  40. #include "protocol.h"
  41. #include "device.h"
  42. #include "system.h"
  43. int routing_mode = RMODE_ROUTER;
  44. subnet_t mymac;
  45. void learn_mac(mac_t *address)
  46. {
  47. subnet_t *subnet;
  48. avl_node_t *node;
  49. connection_t *c;
  50. cp
  51. subnet = lookup_subnet_mac(address);
  52. /* If we don't know this MAC address yet, store it */
  53. if(!subnet || subnet->owner!=myself)
  54. {
  55. if(debug_lvl >= DEBUG_TRAFFIC)
  56. syslog(LOG_INFO, _("Learned new MAC address %hx:%hx:%hx:%hx:%hx:%hx"),
  57. address->x[0], address->x[1], address->x[2], address->x[3], address->x[4], address->x[5]);
  58. subnet = new_subnet();
  59. subnet->type = SUBNET_MAC;
  60. memcpy(&subnet->net.mac.address, address, sizeof(mac_t));
  61. subnet_add(myself, subnet);
  62. /* And tell all other tinc daemons it's our MAC */
  63. for(node = connection_tree->head; node; node = node->next)
  64. {
  65. c = (connection_t *)node->data;
  66. if(c->status.active)
  67. send_add_subnet(c, subnet);
  68. }
  69. }
  70. }
  71. node_t *route_mac(vpn_packet_t *packet)
  72. {
  73. subnet_t *subnet;
  74. cp
  75. /* Learn source address */
  76. learn_mac((mac_t *)(&packet->data[6]));
  77. /* Lookup destination address */
  78. subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
  79. if(subnet)
  80. return subnet->owner;
  81. else
  82. return NULL;
  83. }
  84. node_t *route_ipv4(vpn_packet_t *packet)
  85. {
  86. ipv4_t dest;
  87. subnet_t *subnet;
  88. cp
  89. #ifdef HAVE_SOLARIS
  90. /* The other form gives bus errors on a SparcStation 20. */
  91. dest = ((packet->data[30] * 0x100 + packet->data[31]) * 0x100 + packet->data[32]) * 0x100 + packet->data[33];
  92. #else
  93. dest = ntohl(*((unsigned long*)(&packet->data[30])));
  94. #endif
  95. cp
  96. subnet = lookup_subnet_ipv4(&dest);
  97. cp
  98. if(!subnet)
  99. {
  100. if(debug_lvl >= DEBUG_TRAFFIC)
  101. {
  102. syslog(LOG_WARNING, _("Cannot route packet: unknown destination address %d.%d.%d.%d"),
  103. packet->data[30], packet->data[31], packet->data[32], packet->data[33]);
  104. }
  105. return NULL;
  106. }
  107. cp
  108. return subnet->owner;
  109. }
  110. node_t *route_ipv6(vpn_packet_t *packet)
  111. {
  112. subnet_t *subnet;
  113. cp
  114. subnet = lookup_subnet_ipv6((ipv6_t *)&packet->data[38]);
  115. cp
  116. if(!subnet)
  117. {
  118. if(debug_lvl >= DEBUG_TRAFFIC)
  119. {
  120. syslog(LOG_WARNING, _("Cannot route packet: unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"),
  121. ntohs(*(short unsigned int *)&packet->data[38]),
  122. ntohs(*(short unsigned int *)&packet->data[40]),
  123. ntohs(*(short unsigned int *)&packet->data[42]),
  124. ntohs(*(short unsigned int *)&packet->data[44]),
  125. ntohs(*(short unsigned int *)&packet->data[46]),
  126. ntohs(*(short unsigned int *)&packet->data[48]),
  127. ntohs(*(short unsigned int *)&packet->data[50]),
  128. ntohs(*(short unsigned int *)&packet->data[52]));
  129. }
  130. return NULL;
  131. }
  132. cp
  133. return subnet->owner;
  134. }
  135. void route_arp(vpn_packet_t *packet)
  136. {
  137. struct ether_arp *arp;
  138. subnet_t *subnet;
  139. unsigned char ipbuf[4];
  140. ipv4_t dest;
  141. cp
  142. /* First, snatch the source address from the ARP packet */
  143. memcpy(mymac.net.mac.address.x, packet->data + 6, 6);
  144. /* This routine generates replies to ARP requests.
  145. You don't need to set NOARP flag on the interface anymore (which is broken on FreeBSD).
  146. Most of the code here is taken from choparp.c by Takamichi Tateoka (tree@mma.club.uec.ac.jp)
  147. */
  148. arp = (struct ether_arp *)(packet->data + 14);
  149. /* Check if this is a valid ARP request */
  150. if(ntohs(arp->arp_hrd) != ARPHRD_ETHER ||
  151. ntohs(arp->arp_pro) != ETHERTYPE_IP ||
  152. (int) (arp->arp_hln) != ETHER_ADDR_LEN ||
  153. (int) (arp->arp_pln) != 4 ||
  154. ntohs(arp->arp_op) != ARPOP_REQUEST )
  155. {
  156. if(debug_lvl > DEBUG_TRAFFIC)
  157. {
  158. syslog(LOG_WARNING, _("Cannot route packet: received unknown type ARP request"));
  159. }
  160. return;
  161. }
  162. /* Check if the IP address exists on the VPN */
  163. dest = ntohl(*((unsigned long*)(arp->arp_tpa)));
  164. subnet = lookup_subnet_ipv4(&dest);
  165. if(!subnet)
  166. {
  167. if(debug_lvl >= DEBUG_TRAFFIC)
  168. {
  169. syslog(LOG_WARNING, _("Cannot route packet: ARP request for unknown address %d.%d.%d.%d"),
  170. arp->arp_tpa[0], arp->arp_tpa[1], arp->arp_tpa[2], arp->arp_tpa[3]);
  171. }
  172. return;
  173. }
  174. /* Check if it is for our own subnet */
  175. if(subnet->owner == myself)
  176. return; /* silently ignore */
  177. memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */
  178. packet->data[ETHER_ADDR_LEN*2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
  179. memcpy(ipbuf, arp->arp_tpa, 4); /* save protocol addr */
  180. memcpy(arp->arp_tpa, arp->arp_spa, 4); /* swap destination and source protocol address */
  181. memcpy(arp->arp_spa, ipbuf, 4); /* ... */
  182. memcpy(arp->arp_tha, arp->arp_sha, 10); /* set target hard/proto addr */
  183. memcpy(arp->arp_sha, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* add fake source hard addr */
  184. arp->arp_op = htons(ARPOP_REPLY);
  185. write_packet(packet);
  186. cp
  187. }
  188. void route_outgoing(vpn_packet_t *packet)
  189. {
  190. unsigned short int type;
  191. node_t *n;
  192. cp
  193. /* FIXME: multicast? */
  194. switch(routing_mode)
  195. {
  196. case RMODE_ROUTER:
  197. type = ntohs(*((unsigned short*)(&packet->data[12])));
  198. switch(type)
  199. {
  200. case 0x0800:
  201. n = route_ipv4(packet);
  202. break;
  203. case 0x86DD:
  204. n = route_ipv6(packet);
  205. break;
  206. case 0x0806:
  207. route_arp(packet);
  208. return;
  209. default:
  210. if(debug_lvl >= DEBUG_TRAFFIC)
  211. {
  212. syslog(LOG_WARNING, _("Cannot route packet: unknown type %hx"), type);
  213. }
  214. return;
  215. }
  216. if(n)
  217. send_packet(n, packet);
  218. break;
  219. case RMODE_SWITCH:
  220. n = route_mac(packet);
  221. if(n)
  222. send_packet(n, packet);
  223. else
  224. broadcast_packet(myself, packet);
  225. break;
  226. case RMODE_HUB:
  227. broadcast_packet(myself, packet);
  228. break;
  229. }
  230. }
  231. void route_incoming(node_t *source, vpn_packet_t *packet)
  232. {
  233. switch(routing_mode)
  234. {
  235. case RMODE_ROUTER:
  236. memcpy(packet->data, mymac.net.mac.address.x, 6); /* Override destination address to make the kernel accept it */
  237. write_packet(packet);
  238. break;
  239. case RMODE_SWITCH:
  240. {
  241. subnet_t *subnet;
  242. subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
  243. if(subnet)
  244. {
  245. if(subnet->owner == myself)
  246. write_packet(packet);
  247. else
  248. send_packet(subnet->owner, packet);
  249. }
  250. else
  251. {
  252. broadcast_packet(source, packet);
  253. write_packet(packet);
  254. }
  255. }
  256. break;
  257. case RMODE_HUB:
  258. broadcast_packet(source, packet); /* Spread it on */
  259. write_packet(packet);
  260. break;
  261. }
  262. }