} while (1);
}
-static void forward_bcast_packet(struct relayd_interface *from_rif, void *packet, int len)
+void relayd_forward_bcast_packet(struct relayd_interface *from_rif, void *packet, int len)
{
struct relayd_interface *rif;
struct ether_header *eth = packet;
}
}
-static uint16_t
-chksum(uint16_t sum, const uint8_t *data, uint16_t len)
-{
- const uint8_t *last;
- uint16_t t;
-
- last = data + len - 1;
-
- while(data < last) {
- t = (data[0] << 8) + data[1];
- sum += t;
- if(sum < t)
- sum++;
- data += 2;
- }
-
- if(data == last) {
- t = (data[0] << 8) + 0;
- sum += t;
- if(sum < t)
- sum++;
- }
-
- return sum;
-}
-
-static bool forward_dhcp_packet(struct relayd_interface *rif, void *data, int len)
-{
- struct ip_packet *pkt = data;
- struct udphdr *udp;
- struct dhcp_header *dhcp;
- int udplen;
- uint16_t sum;
-
- if (pkt->eth.ether_type != htons(ETH_P_IP))
- return false;
-
- if (pkt->iph.version != 4)
- return false;
-
- if (pkt->iph.protocol != IPPROTO_UDP)
- return false;
-
- udp = (void *) ((char *) &pkt->iph + (pkt->iph.ihl << 2));
- dhcp = (void *) (udp + 1);
-
- udplen = ntohs(udp->len);
- if (udplen > len - ((char *) udp - (char *) data))
- return false;
-
- if (udp->dest != htons(67) && udp->source != htons(67))
- return false;
-
- if (dhcp->op != 1 && dhcp->op != 2)
- return false;
-
- if (!forward_dhcp)
- return true;
-
- if (dhcp->op == 2)
- relayd_refresh_host(rif, pkt->eth.ether_shost, (void *) &pkt->iph.saddr);
-
- DPRINTF(2, "%s: handling DHCP %s\n", rif->ifname, (dhcp->op == 1 ? "request" : "response"));
-
- dhcp->flags |= htons(DHCP_FLAG_BROADCAST);
-
- udp->check = 0;
- sum = udplen + IPPROTO_UDP;
- sum = chksum(sum, (void *) &pkt->iph.saddr, 8);
- sum = chksum(sum, (void *) udp, udplen);
- if (sum == 0)
- sum = 0xffff;
-
- udp->check = htons(~sum);
-
- forward_bcast_packet(rif, data, len);
-
- return true;
-}
-
static void recv_bcast_packet(struct uloop_fd *fd, unsigned int events)
{
struct relayd_interface *rif = container_of(fd, struct relayd_interface, bcast_fd);
if (!forward_bcast && !forward_dhcp)
continue;
- if (forward_dhcp_packet(rif, pktbuf, pktlen))
+ if (relayd_handle_dhcp_packet(rif, pktbuf, pktlen, forward_dhcp))
continue;
if (forward_bcast)
- forward_bcast_packet(rif, pktbuf, pktlen);
+ relayd_forward_bcast_packet(rif, pktbuf, pktlen);
} while (1);
}
#endif
uloop_fd_add(&rif->bcast_fd, ULOOP_READ | ULOOP_EDGE_TRIGGER);
+ relayd_add_interface_routes(rif);
return 0;
}
return 0;
}
-static void del_interface(struct relayd_interface *rif)
+static void cleanup_hosts(void)
{
- struct relayd_host *host, *htmp;
+ struct relayd_interface *rif;
+ struct relayd_host *host, *tmp;
- list_for_each_entry_safe(host, htmp, &rif->hosts, list) {
- del_host(host);
+ list_for_each_entry(rif, &interfaces, list) {
+ list_for_each_entry_safe(host, tmp, &rif->hosts, list) {
+ del_host(host);
+ }
}
- free(rif);
}
-static void cleanup_interfaces(void)
+static void free_interfaces(void)
{
struct relayd_interface *rif, *rtmp;
list_for_each_entry_safe(rif, rtmp, &interfaces, list) {
- del_interface(rif);
+ relayd_del_interface_routes(rif);
+ list_del(&rif->list);
+ free(rif);
}
}
* When we hit SIGTERM, clean up interfaces directly, so that we
* won't leave our routing in an invalid state.
*/
- cleanup_interfaces();
+ cleanup_hosts();
+ free_interfaces();
exit(1);
}
" -I <ifname> Same as -i, except with ARP cache and host route management\n"
" You need to specify at least two interfaces\n"
" -t <timeout> Host entry expiry timeout\n"
+ " -T <table> Set routing table number for automatically added routes\n"
" -B Enable broadcast forwarding\n"
" -D Enable DHCP forwarding\n"
"\n",
forward_bcast = 0;
uloop_init();
- while ((ch = getopt(argc, argv, "I:i:t:BDd")) != -1) {
+ while ((ch = getopt(argc, argv, "I:i:t:BDdT:")) != -1) {
switch(ch) {
case 'I':
managed = true;
case 'D':
forward_dhcp = 1;
break;
+ case 'T':
+ route_table = atoi(optarg);
+ if (route_table <= 0)
+ return usage(argv[0]);
+ break;
case '?':
default:
return usage(argv[0]);
signal(SIGUSR1, die);
signal(SIGUSR2, die);
- if (init_interfaces() < 0)
+ if (relayd_rtnl_init() < 0)
return 1;
- if (relayd_rtnl_init() < 0)
+ if (init_interfaces() < 0)
return 1;
uloop_run();
uloop_done();
- cleanup_interfaces();
+ cleanup_hosts();
+ free_interfaces();
relayd_rtnl_done();
close(inet_sock);