Split DHCP code off into a separate source code file
[project/relayd.git] / main.c
diff --git a/main.c b/main.c
index 81cc84d..62d7c2b 100644 (file)
--- a/main.c
+++ b/main.c
@@ -329,7 +329,7 @@ static void recv_packet(struct uloop_fd *fd, unsigned int events)
        } 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;
@@ -344,86 +344,6 @@ static void forward_bcast_packet(struct relayd_interface *from_rif, void *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);
@@ -448,11 +368,11 @@ static void recv_bcast_packet(struct uloop_fd *fd, unsigned int events)
                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);
 }
 
@@ -535,6 +455,7 @@ static int init_interface(struct relayd_interface *rif)
 #endif
 
        uloop_fd_add(&rif->bcast_fd, ULOOP_READ | ULOOP_EDGE_TRIGGER);
+       relayd_add_interface_routes(rif);
        return 0;
 }
 
@@ -552,22 +473,26 @@ static int init_interfaces(void)
        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);
        }
 }
 
@@ -597,7 +522,8 @@ static void die(int signo)
         * 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);
 }
 
@@ -611,6 +537,7 @@ static int usage(const char *progname)
                        "       -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",
@@ -635,7 +562,7 @@ int main(int argc, char **argv)
        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;
@@ -661,6 +588,11 @@ int main(int argc, char **argv)
                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]);
@@ -683,16 +615,17 @@ int main(int argc, char **argv)
        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);