]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Move ipv4 specific code out of net.c and into ipv4.c
authorRoy Marples <roy@marples.name>
Mon, 4 Feb 2013 11:03:08 +0000 (11:03 +0000)
committerRoy Marples <roy@marples.name>
Mon, 4 Feb 2013 11:03:08 +0000 (11:03 +0000)
arp.c
dhcp.c
dhcpcd.c
if-linux.c
if-options.c
ipv4.c
ipv4.h
lpf.c
net.c
net.h

diff --git a/arp.c b/arp.c
index 9bf1a59786fb7593735a88f25053376e4fb454bc..d61053a49c25db4f99455bbfd4723d07ae5b5dbd 100644 (file)
--- a/arp.c
+++ b/arp.c
@@ -72,7 +72,7 @@ arp_send(const struct interface *ifp, int op, in_addr_t sip, in_addr_t tip)
        memcpy(p, &tip, sizeof(tip));
        p += sizeof(tip);
        len = p - arp_buffer;
-       retval = send_raw_packet(ifp, ETHERTYPE_ARP, arp_buffer, len);
+       retval = ipv4_sendrawpacket(ifp, ETHERTYPE_ARP, arp_buffer, len);
        return retval;
 }
 
@@ -121,7 +121,7 @@ arp_packet(void *arg)
        state = D_STATE(ifp);
        state->fail.s_addr = 0;
        for(;;) {
-               bytes = get_raw_packet(ifp, ETHERTYPE_ARP,
+               bytes = ipv4_getrawpacket(ifp, ETHERTYPE_ARP,
                    arp_buffer, sizeof(arp_buffer), NULL);
                if (bytes == 0 || bytes == -1)
                        return;
@@ -210,7 +210,7 @@ arp_announce(void *arg)
        if (state->new == NULL)
                return;
        if (state->arp_fd == -1) {
-               open_socket(ifp, ETHERTYPE_ARP);
+               ipv4_opensocket(ifp, ETHERTYPE_ARP);
                eloop_event_add(state->arp_fd, arp_packet, ifp);
        }
        if (++state->claims < ANNOUNCE_NUM)     
@@ -268,7 +268,7 @@ arp_probe(void *arg)
                addr.s_addr = state->addr.s_addr;
 
        if (state->arp_fd == -1) {
-               open_socket(ifp, ETHERTYPE_ARP);
+               ipv4_opensocket(ifp, ETHERTYPE_ARP);
                eloop_event_add(state->arp_fd, arp_packet, ifp);
        }
        if (state->probes == 0) {
diff --git a/dhcp.c b/dhcp.c
index f217073d9069f72fb7593e3d7ff89908288bbb74..3d4da3b0f3f4bc54699bccb6da023147ef8728fd 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
 #  include <linux/rtnetlink.h>
 #endif
 
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#define __FAVOR_BSD /* Nasty glibc hack so we can use BSD semantics for UDP */
+#include <netinet/udp.h>
+#undef __FAVOR_BSD
+
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
 #include <syslog.h>
@@ -199,6 +206,14 @@ static const char *dhcp_params[] = {
        NULL
 };
 
+struct udp_dhcp_packet
+{
+       struct ip ip;
+       struct udphdr udp;
+       struct dhcp_message dhcp;
+};
+static const size_t udp_dhcp_len = sizeof(struct udp_dhcp_packet);
+
 static int dhcp_open(struct interface *);
 
 void
@@ -474,7 +489,7 @@ decode_rfc3442_rt(int dl, const uint8_t *data)
        while (p < e) {
                cidr = *p++;
                if (cidr > 32) {
-                       free_routes(routes);
+                       ipv4_freeroutes(routes);
                        errno = EINVAL;
                        return NULL;
                }
@@ -1143,7 +1158,7 @@ configure_env(char **env, const char *prefix, const struct dhcp_message *dhcp,
                addr.s_addr = dhcp->yiaddr ? dhcp->yiaddr : dhcp->ciaddr;
                setvar(&ep, prefix, "ip_address", inet_ntoa(addr));
                if (get_option_addr(&net, dhcp, DHO_SUBNETMASK) == -1) {
-                       net.s_addr = get_netmask(addr.s_addr);
+                       net.s_addr = ipv4_getnetmask(addr.s_addr);
                        setvar(&ep, prefix, "subnet_mask", inet_ntoa(net));
                }
                snprintf(cidr, sizeof(cidr), "%d", inet_ntocidr(net));
@@ -1200,7 +1215,7 @@ get_lease(struct dhcp_lease *lease, const struct dhcp_message *dhcp)
        else
                lease->addr.s_addr = dhcp->ciaddr;
        if (get_option_addr(&lease->net, dhcp, DHO_SUBNETMASK) == -1)
-               lease->net.s_addr = get_netmask(lease->addr.s_addr);
+               lease->net.s_addr = ipv4_getnetmask(lease->addr.s_addr);
        if (get_option_addr(&lease->brd, dhcp, DHO_BROADCAST) == -1)
                lease->brd.s_addr = lease->addr.s_addr | ~lease->net.s_addr;
        if (get_option_uint32(&lease->leasetime, dhcp, DHO_LEASETIME) == 0) {
@@ -1282,6 +1297,141 @@ dhcp_close(struct interface *ifp)
        state->interval = 0;
 }
 
+static int
+dhcp_openudp(struct interface *iface)
+{
+       int s;
+       struct sockaddr_in sin;
+       int n;
+       struct dhcp_state *state;
+#ifdef SO_BINDTODEVICE
+       struct ifreq ifr;
+       char *p;
+#endif
+
+       if ((s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
+           return -1;
+
+       n = 1;
+       if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) == -1)
+           goto eexit;
+#ifdef SO_BINDTODEVICE
+       memset(&ifr, 0, sizeof(ifr));
+       strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
+       /* We can only bind to the real device */
+       p = strchr(ifr.ifr_name, ':');
+       if (p)
+           *p = '\0';
+       if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, &ifr,
+                   sizeof(ifr)) == -1)
+           goto eexit;
+#endif
+       /* As we don't use this socket for receiving, set the
+        *       * receive buffer to 1 */
+       n = 1;
+       if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) == -1)
+           goto eexit;
+       state = D_STATE(iface);
+       memset(&sin, 0, sizeof(sin));
+       sin.sin_family = AF_INET;
+       sin.sin_port = htons(DHCP_CLIENT_PORT);
+       sin.sin_addr.s_addr = state->addr.s_addr;
+       if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) == -1)
+           goto eexit;
+
+       state->udp_fd = s;
+       set_cloexec(s);
+       return 0;
+
+eexit:
+       close(s);
+       return -1;
+}
+
+static ssize_t
+dhcp_sendpacket(const struct interface *iface, struct in_addr to,
+    const uint8_t *data, ssize_t len)
+{
+       struct sockaddr_in sin;
+
+       memset(&sin, 0, sizeof(sin));
+       sin.sin_family = AF_INET;
+       sin.sin_addr.s_addr = to.s_addr;
+       sin.sin_port = htons(DHCP_SERVER_PORT);
+       return sendto(D_CSTATE(iface)->udp_fd, data, len, 0,
+           (struct sockaddr *)&sin, sizeof(sin));
+}
+
+static uint16_t
+checksum(const void *data, uint16_t len)
+{
+       const uint8_t *addr = data;
+       uint32_t sum = 0;
+
+       while (len > 1) {
+               sum += addr[0] * 256 + addr[1];
+               addr += 2;
+               len -= 2;
+       }
+
+       if (len == 1)
+               sum += *addr * 256;
+
+       sum = (sum >> 16) + (sum & 0xffff);
+       sum += (sum >> 16);
+
+       sum = htons(sum);
+
+       return ~sum;
+}
+
+static ssize_t
+dhcp_makeudppacket(uint8_t **p, const uint8_t *data, size_t length,
+       struct in_addr source, struct in_addr dest)
+{
+       struct udp_dhcp_packet *udpp;
+       struct ip *ip;
+       struct udphdr *udp;
+
+       udpp = xzalloc(sizeof(*udpp));
+       ip = &udpp->ip;
+       udp = &udpp->udp;
+
+       /* OK, this is important :)
+        * We copy the data to our packet and then create a small part of the
+        * ip structure and an invalid ip_len (basically udp length).
+        * We then fill the udp structure and put the checksum
+        * of the whole packet into the udp checksum.
+        * Finally we complete the ip structure and ip checksum.
+        * If we don't do the ordering like so then the udp checksum will be
+        * broken, so find another way of doing it! */
+
+       memcpy(&udpp->dhcp, data, length);
+
+       ip->ip_p = IPPROTO_UDP;
+       ip->ip_src.s_addr = source.s_addr;
+       if (dest.s_addr == 0)
+           ip->ip_dst.s_addr = INADDR_BROADCAST;
+       else
+           ip->ip_dst.s_addr = dest.s_addr;
+
+       udp->uh_sport = htons(DHCP_CLIENT_PORT);
+       udp->uh_dport = htons(DHCP_SERVER_PORT);
+       udp->uh_ulen = htons(sizeof(*udp) + length);
+       ip->ip_len = udp->uh_ulen;
+       udp->uh_sum = checksum(udpp, sizeof(*udpp));
+
+       ip->ip_v = IPVERSION;
+       ip->ip_hl = sizeof(*ip) >> 2;
+       ip->ip_id = arc4random() & UINT16_MAX;
+       ip->ip_ttl = IPDEFTTL;
+       ip->ip_len = htons(sizeof(*ip) + sizeof(*udp) + length);
+       ip->ip_sum = checksum(ip, sizeof(*ip));
+
+       *p = (uint8_t *)udpp;
+       return sizeof(*ip) + sizeof(*udp) + length;
+}
+
 static void
 send_message(struct interface *iface, int type,
     void (*callback)(void *))
@@ -1341,14 +1491,14 @@ send_message(struct interface *iface, int type,
        else
                to.s_addr = 0;
        if (to.s_addr && to.s_addr != INADDR_BROADCAST) {
-               r = send_packet(iface, to, (uint8_t *)dhcp, len);
+               r = dhcp_sendpacket(iface, to, (uint8_t *)dhcp, len);
                if (r == -1) {
-                       syslog(LOG_ERR, "%s: send_packet: %m", iface->name);
+                       syslog(LOG_ERR, "%s: dhcp_sendpacket: %m", iface->name);
                        dhcp_close(iface);
                }
        } else {
-               len = make_udp_packet(&udp, (uint8_t *)dhcp, len, from, to);
-               r = send_raw_packet(iface, ETHERTYPE_IP, udp, len);
+               len = dhcp_makeudppacket(&udp, (uint8_t *)dhcp, len, from, to);
+               r = ipv4_sendrawpacket(iface, ETHERTYPE_IP, udp, len);
                free(udp);
                /* If we failed to send a raw packet this normally means
                 * we don't have the ability to work beneath the IP layer
@@ -1657,7 +1807,6 @@ dhcp_bind(void *arg)
        }
 }
 
-
 static void
 dhcp_timeout(void *arg)
 {
@@ -1699,7 +1848,7 @@ handle_3rdparty(struct interface *ifp)
        if (ifo->req_addr.s_addr != INADDR_ANY)
                return 0;
 
-       if (get_address(ifp->name, &addr, &net, &dst) == 1)
+       if (ipv4_getaddress(ifp->name, &addr, &net, &dst) == 1)
                ipv4_handleifa(RTM_NEWADDR, ifp->name, &addr, &net, &dst);
        else {
                syslog(LOG_INFO,
@@ -1812,7 +1961,6 @@ dhcp_reboot(struct interface *ifp, int oldopts)
                dhcp_request(ifp);
 }
 
-
 void
 dhcp_drop(struct interface *iface, const char *reason)
 {
@@ -2042,7 +2190,7 @@ dhcp_handle(struct interface *iface, struct dhcp_message **dhcpp,
                /* If the interface already has the address configured
                 * then we can't ARP for duplicate detection. */
                addr.s_addr = state->offer->yiaddr;
-               if (has_address(iface->name, &addr, NULL) != 1) {
+               if (ipv4_hasaddress(iface->name, &addr, NULL) != 1) {
                        state->claims = 0;
                        state->probes = 0;
                        state->conflicts = 0;
@@ -2055,6 +2203,67 @@ dhcp_handle(struct interface *iface, struct dhcp_message **dhcpp,
        dhcp_bind(iface);
 }
 
+static ssize_t
+get_udp_data(const uint8_t **data, const uint8_t *udp)
+{
+    struct udp_dhcp_packet p;
+
+    memcpy(&p, udp, sizeof(p));
+    *data = udp + offsetof(struct udp_dhcp_packet, dhcp);
+    return ntohs(p.ip.ip_len) - sizeof(p.ip) - sizeof(p.udp);
+}
+
+static int
+valid_udp_packet(const uint8_t *data, size_t data_len, struct in_addr *from,
+    int noudpcsum)
+{
+       struct udp_dhcp_packet p;
+       uint16_t bytes, udpsum;
+
+       if (data_len < sizeof(p.ip)) {
+               if (from)
+                       from->s_addr = INADDR_ANY;
+               errno = EINVAL;
+               return -1;
+       }
+       memcpy(&p, data, MIN(data_len, sizeof(p)));
+       if (from)
+               from->s_addr = p.ip.ip_src.s_addr;
+       if (data_len > sizeof(p)) {
+               errno = EINVAL;
+               return -1;
+       }
+       if (checksum(&p.ip, sizeof(p.ip)) != 0) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       bytes = ntohs(p.ip.ip_len);
+       if (data_len < bytes) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       if (noudpcsum == 0) {
+               udpsum = p.udp.uh_sum;
+               p.udp.uh_sum = 0;
+               p.ip.ip_hl = 0;
+               p.ip.ip_v = 0;
+               p.ip.ip_tos = 0;
+               p.ip.ip_len = p.udp.uh_ulen;
+               p.ip.ip_id = 0;
+               p.ip.ip_off = 0;
+               p.ip.ip_ttl = 0;
+               p.ip.ip_sum = 0;
+               if (udpsum && checksum(&p, bytes) != udpsum) {
+                       errno = EINVAL;
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
 static void
 dhcp_handlepacket(void *arg)
 {
@@ -2072,7 +2281,7 @@ dhcp_handlepacket(void *arg)
        if (packet == NULL)
                packet = xmalloc(udp_dhcp_len);
        for(;;) {
-               bytes = get_raw_packet(iface, ETHERTYPE_IP,
+               bytes = ipv4_getrawpacket(iface, ETHERTYPE_IP,
                    packet, udp_dhcp_len, &partialcsum);
                if (bytes == 0 || bytes == -1)
                        break;
@@ -2151,7 +2360,7 @@ dhcp_open(struct interface *ifp)
 
        state = D_STATE(ifp);
        if (state->raw_fd == -1) {
-               if ((r = open_socket(ifp, ETHERTYPE_IP)) == -1)
+               if ((r = ipv4_opensocket(ifp, ETHERTYPE_IP)) == -1)
                        syslog(LOG_ERR, "%s: %s: %m", __func__, ifp->name);
                else
                        eloop_event_add(state->raw_fd, dhcp_handlepacket, ifp);
@@ -2162,8 +2371,8 @@ dhcp_open(struct interface *ifp)
            (state->new->cookie == htonl(MAGIC_COOKIE) ||
            ifp->options->options & DHCPCD_INFORM))
        {
-               if (open_udp_socket(ifp) == -1 && errno != EADDRINUSE) {
-                       syslog(LOG_ERR, "%s: open_udp_socket: %m", ifp->name);
+               if (dhcp_openudp(ifp) == -1 && errno != EADDRINUSE) {
+                       syslog(LOG_ERR, "%s: dhcp_openudp: %m", ifp->name);
                        r = -1;
                }
        }
index 9f8779e91912b1dd20b94cc182d1a202f34e676f..6f9e32a411e6d7e797d02362e5a8295ed590d187 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -1091,8 +1091,8 @@ main(int argc, char **argv)
                        syslog(LOG_ERR, "control_start: %m");
        }
 
-       if (init_sockets() == -1) {
-               syslog(LOG_ERR, "init_socket: %m");
+       if (open_sockets() == -1) {
+               syslog(LOG_ERR, "open_sockets: %m");
                exit(EXIT_FAILURE);
        }
        if (if_options->options & DHCPCD_LINK) {
index 34248d0c8b86c1aff92dd92c79f63a5e9b42274d..606a5aabe4e4c18da92e045322d40341f0c6fc77 100644 (file)
@@ -126,7 +126,7 @@ _open_link_socket(struct sockaddr_nl *nl)
 }
 
 int
-init_sockets(void)
+open_sockets(void)
 {
        if ((socket_afnet = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
                return -1;
index 5d319350da07752ccfe0b9d6a7f9902d87dc85a1..89f0b051fe1f87ad3b9e3659036663821acd86ed 100644 (file)
@@ -45,7 +45,7 @@
 #include "dhcp.h"
 #include "dhcp6.h"
 #include "if-options.h"
-#include "net.h"
+#include "ipv4.h"
 #include "platform.h"
 
 unsigned long long options = 0;
@@ -334,7 +334,7 @@ parse_addr(struct in_addr *addr, struct in_addr *net, const char *arg)
        if (p != NULL)
                *--p = '/';
        else if (net != NULL)
-               net->s_addr = get_netmask(addr->s_addr);
+               net->s_addr = ipv4_getnetmask(addr->s_addr);
        return 0;
 }
 
@@ -974,7 +974,7 @@ free_options(struct if_options *ifo)
                                free(ifo->config[i++]);
                        free(ifo->config);
                }
-               free_routes(ifo->routes);
+               ipv4_freeroutes(ifo->routes);
                free(ifo->arping);
                free(ifo->blacklist);
                free(ifo->fallback);
diff --git a/ipv4.c b/ipv4.c
index e2170acfa71d13b92f1fbf58aefbf95cfe87fdcf..eee8ec4a96bd4c0f52d85def7c892db922c03904 100644 (file)
--- a/ipv4.c
+++ b/ipv4.c
@@ -35,6 +35,7 @@
 
 #include <ctype.h>
 #include <errno.h>
+#include <ifaddrs.h>
 #include <stdlib.h>
 #include <string.h>
 #include <syslog.h>
 #include "net.h"
 #include "script.h"
 
+int socket_afnet = -1;
+
 static struct rt *routes;
 
+int
+inet_ntocidr(struct in_addr address)
+{
+       int cidr = 0;
+       uint32_t mask = htonl(address.s_addr);
+
+       while (mask) {
+               cidr++;
+               mask <<= 1;
+       }
+       return cidr;
+}
+
+int
+inet_cidrtoaddr(int cidr, struct in_addr *addr)
+{
+       int ocets;
+
+       if (cidr < 1 || cidr > 32) {
+               errno = EINVAL;
+               return -1;
+       }
+       ocets = (cidr + 7) / 8;
+
+       addr->s_addr = 0;
+       if (ocets > 0) {
+               memset(&addr->s_addr, 255, (size_t)ocets - 1);
+               memset((unsigned char *)&addr->s_addr + (ocets - 1),
+                   (256 - (1 << (32 - cidr) % 8)), 1);
+       }
+
+       return 0;
+}
+
+uint32_t
+ipv4_getnetmask(uint32_t addr)
+{
+       uint32_t dst;
+
+       if (addr == 0)
+               return 0;
+
+       dst = htonl(addr);
+       if (IN_CLASSA(dst))
+               return ntohl(IN_CLASSA_NET);
+       if (IN_CLASSB(dst))
+               return ntohl(IN_CLASSB_NET);
+       if (IN_CLASSC(dst))
+               return ntohl(IN_CLASSC_NET);
+
+       return 0;
+}
+
+int
+ipv4_doaddress(const char *ifname,
+    struct in_addr *addr, struct in_addr *net, struct in_addr *dst, int act)
+{
+       struct ifaddrs *ifaddrs, *ifa;
+       const struct sockaddr_in *a, *n, *d;
+       int retval;
+
+       if (getifaddrs(&ifaddrs) == -1)
+               return -1;
+
+       retval = 0;
+       for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
+               if (ifa->ifa_addr == NULL ||
+                   ifa->ifa_addr->sa_family != AF_INET ||
+                   strcmp(ifa->ifa_name, ifname) != 0)
+                       continue;
+               a = (const struct sockaddr_in *)(void *)ifa->ifa_addr;
+               n = (const struct sockaddr_in *)(void *)ifa->ifa_netmask;
+               if (ifa->ifa_flags & IFF_POINTOPOINT)
+                       d = (const struct sockaddr_in *)(void *)
+                           ifa->ifa_dstaddr;
+               else
+                       d = NULL;
+               if (act == 1) {
+                       addr->s_addr = a->sin_addr.s_addr;
+                       net->s_addr = n->sin_addr.s_addr;
+                       if (dst) {
+                               if (ifa->ifa_flags & IFF_POINTOPOINT)
+                                       dst->s_addr = d->sin_addr.s_addr;
+                               else
+                                       dst->s_addr = INADDR_ANY;
+                       }
+                       retval = 1;
+                       break;
+               }
+               if (addr->s_addr == a->sin_addr.s_addr &&
+                   (net == NULL || net->s_addr == n->sin_addr.s_addr))
+               {
+                       retval = 1;
+                       break;
+               }
+       }
+       freeifaddrs(ifaddrs);
+       return retval;
+}
+
+void
+ipv4_freeroutes(struct rt *rts)
+{
+       struct rt *r;
+
+       while (rts) {
+               r = rts->next;
+               free(rts);
+               rts = r;
+       }
+}
+
 static struct rt *
 find_route(struct rt *rts, const struct rt *r, struct rt **lrt,
     const struct rt *srt)
@@ -127,7 +242,7 @@ n_route(struct rt *rt)
                return -1;
 
        desc_route("adding", rt);
-       if (!add_route(rt))
+       if (!ipv4_addroute(rt))
                return 0;
        if (errno == EEXIST) {
                s = D_CSTATE(rt->iface);
@@ -139,7 +254,7 @@ n_route(struct rt *rt)
                else
                        return -1;
        }
-       syslog(LOG_ERR, "%s: add_route: %m", rt->iface->name);
+       syslog(LOG_ERR, "%s: ipv4_addroute: %m", rt->iface->name);
        return -1;
 }
 
@@ -156,10 +271,10 @@ c_route(struct rt *ort, struct rt *nrt)
        /* We delete and add the route so that we can change metric.
         * This also has the nice side effect of flushing ARP entries so
         * we don't have to do that manually. */
-       del_route(ort);
-       if (!add_route(nrt))
+       ipv4_deleteroute(ort);
+       if (!ipv4_addroute(nrt))
                return 0;
-       syslog(LOG_ERR, "%s: add_route: %m", nrt->iface->name);
+       syslog(LOG_ERR, "%s: ipv4_addroute: %m", nrt->iface->name);
        return -1;
 }
 
@@ -169,9 +284,9 @@ d_route(struct rt *rt)
        int retval;
 
        desc_route("deleting", rt);
-       retval = del_route(rt);
+       retval = ipv4_deleteroute(rt);
        if (retval != 0 && errno != ENOENT && errno != ESRCH)
-               syslog(LOG_ERR,"%s: del_route: %m", rt->iface->name);
+               syslog(LOG_ERR,"%s: ipv4_deleteroute: %m", rt->iface->name);
        return retval;
 }
 
@@ -187,7 +302,7 @@ get_subnet_route(struct dhcp_message *dhcp)
                addr = dhcp->ciaddr;
        /* Ensure we have all the needed values */
        if (get_option_addr(&net, dhcp, DHO_SUBNETMASK) == -1)
-               net.s_addr = get_netmask(addr);
+               net.s_addr = ipv4_getnetmask(addr);
        if (net.s_addr == INADDR_BROADCAST || net.s_addr == INADDR_ANY)
                return NULL;
        rt = malloc(sizeof(*rt));
@@ -382,7 +497,7 @@ ipv4_buildroutes(void)
                        nrs = rt;
                        rt = lrt; /* When we loop this makes lrt correct */
                }
-               free_routes(dnr);
+               ipv4_freeroutes(dnr);
        }
 
        /* Remove old routes we used to manage */
@@ -391,7 +506,7 @@ ipv4_buildroutes(void)
                        d_route(rt);
        }
 
-       free_routes(routes);
+       ipv4_freeroutes(routes);
        routes = nrs;
 }
 
@@ -409,7 +524,7 @@ delete_address(struct interface *iface)
                return 0;
        syslog(LOG_DEBUG, "%s: deleting IP address %s/%d",
            iface->name, inet_ntoa(state->addr), inet_ntocidr(state->net));
-       retval = del_address(iface, &state->addr, &state->net);
+       retval = ipv4_deleteaddress(iface, &state->addr, &state->net);
        if (retval == -1 && errno != EADDRNOTAVAIL) 
                syslog(LOG_ERR, "del_address: %m");
        state->addr.s_addr = 0;
@@ -448,16 +563,16 @@ ipv4_applyaddr(void *arg)
 
        /* This also changes netmask */
        if (!(ifo->options & DHCPCD_INFORM) ||
-           !has_address(ifp->name, &lease->addr, &lease->net))
+           !ipv4_hasaddress(ifp->name, &lease->addr, &lease->net))
        {
                syslog(LOG_DEBUG, "%s: adding IP address %s/%d",
                    ifp->name, inet_ntoa(lease->addr),
                    inet_ntocidr(lease->net));
-               if (add_address(ifp,
+               if (ipv4_addaddress(ifp,
                        &lease->addr, &lease->net, &lease->brd) == -1 &&
                    errno != EEXIST)
                {
-                       syslog(LOG_ERR, "%s: add_address: %m", __func__);
+                       syslog(LOG_ERR, "%s: ipv4_addaddress: %m", __func__);
                        return;
                }
        }
@@ -477,7 +592,7 @@ ipv4_applyaddr(void *arg)
                rt->iface = ifp;
                rt->metric = 0;
                if (!find_route(routes, rt, NULL, NULL))
-                       del_route(rt);
+                       ipv4_deleteroute(rt);
                free(rt);
        }
 
diff --git a/ipv4.h b/ipv4.h
index a13f4478c0c0068e138e246f9202cd4e7809cc9c..574222fb704d7868ab00337ff5975ffad5f683f2 100644 (file)
--- a/ipv4.h
+++ b/ipv4.h
 #ifndef IPV4_H
 #define IPV4_H
 
-#include "net.h"
+#include "dhcpcd.h"
+
+struct rt {
+       struct in_addr dest;
+       struct in_addr net;
+       struct in_addr gate;
+       const struct interface *iface;
+       int metric;
+       struct in_addr src;
+       struct rt *next;
+};
+
+int inet_ntocidr(struct in_addr);
+int inet_cidrtoaddr(int, struct in_addr *);
+uint32_t ipv4_getnetmask(uint32_t);
 
 void ipv4_buildroutes(void);
 void ipv4_applyaddr(void *);
@@ -36,4 +50,31 @@ int ipv4_routedeleted(const struct rt *);
 
 void ipv4_handleifa(int, const char *,
     struct in_addr *, struct in_addr *, struct in_addr *);
+
+int ipv4_doaddress(const char *,
+    struct in_addr *, struct in_addr *, struct in_addr *, int);
+int if_address(const struct interface *,
+    const struct in_addr *, const struct in_addr *,
+    const struct in_addr *, int);
+#define ipv4_addaddress(iface, addr, net, brd)                               \
+       if_address(iface, addr, net, brd, 1)
+#define ipv4_deleteaddress(iface, addr, net)                                 \
+       if_address(iface, addr, net, NULL, -1)
+#define ipv4_hasaddress(iface, addr, net)                                    \
+       ipv4_doaddress(iface, addr, net, NULL, 0)
+#define ipv4_getaddress(iface, addr, net, dst)                               \
+       ipv4_doaddress(iface, addr, net, dst, 1)
+
+int if_route(const struct rt *rt, int);
+#define ipv4_addroute(rt) if_route(rt, 1)
+#define ipv4_changeroute(rt) if_route(rt, 0)
+#define ipv4_deleteroute(rt) if_route(rt, -1)
+#define del_src_route(rt) i_route(rt, -2);
+void ipv4_freeroutes(struct rt *);
+
+int ipv4_opensocket(struct interface *, int);
+ssize_t ipv4_sendrawpacket(const struct interface *,
+    int, const void *, ssize_t);
+ssize_t ipv4_getrawpacket(struct interface *, int, void *, ssize_t, int *);
+
 #endif
diff --git a/lpf.c b/lpf.c
index 4c98ade9d71e20073a06155d81e5866f853d4dd5..407ef4a87cac159bbaf1899ce212e6c3ee005cb3 100644 (file)
--- a/lpf.c
+++ b/lpf.c
@@ -54,7 +54,7 @@
 #include "config.h"
 #include "common.h"
 #include "dhcp.h"
-#include "net.h"
+#include "ipv4.h"
 #include "bpf-filter.h"
 
 /* Broadcast address for IPoIB */
@@ -65,7 +65,7 @@ static const uint8_t ipv4_bcast_addr[] = {
 };
 
 int
-open_socket(struct interface *ifp, int protocol)
+ipv4_opensocket(struct interface *ifp, int protocol)
 {
        int s;
        union sockunion {
@@ -128,7 +128,7 @@ eexit:
 }
 
 ssize_t
-send_raw_packet(const struct interface *ifp, int protocol,
+ipv4_sendrawpacket(const struct interface *ifp, int protocol,
     const void *data, ssize_t len)
 {
        const struct dhcp_state *state;
@@ -160,7 +160,7 @@ send_raw_packet(const struct interface *ifp, int protocol,
 }
 
 ssize_t
-get_raw_packet(struct interface *ifp, int protocol,
+ipv4_getrawpacket(struct interface *ifp, int protocol,
     void *data, ssize_t len, int *partialcsum)
 {
        struct iovec iov = {
diff --git a/net.c b/net.c
index 11662a2b94f71f07625692fb19b4f35d19ef4e68..0eed069985fdca818465a9082d421467cc92d634 100644 (file)
--- a/net.c
+++ b/net.c
 
 #include <sys/types.h>
 #include <sys/ioctl.h>
-#include <sys/param.h>
 #include <sys/socket.h>
-#include <sys/time.h>
 
-#include <arpa/inet.h>
 #include <net/if.h>
 #include <net/if_arp.h>
 #ifdef AF_LINK
 #  include <net/if_dl.h>
 #  include <net/if_types.h>
 #endif
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#define __FAVOR_BSD /* Nasty glibc hack so we can use BSD semantics for UDP */
-#include <netinet/udp.h>
-#undef __FAVOR_BSD
 #ifdef AF_PACKET
 #  include <netpacket/packet.h>
 #endif
 #include "if-options.h"
 #include "ipv6rs.h"
 #include "net.h"
-#include "signals.h"
 
 static char hwaddr_buffer[(HWADDR_LEN * 3) + 1 + 1024];
 
-int socket_afnet = -1;
-
-int
-inet_ntocidr(struct in_addr address)
-{
-       int cidr = 0;
-       uint32_t mask = htonl(address.s_addr);
-
-       while (mask) {
-               cidr++;
-               mask <<= 1;
-       }
-       return cidr;
-}
-
-int
-inet_cidrtoaddr(int cidr, struct in_addr *addr)
-{
-       int ocets;
-
-       if (cidr < 1 || cidr > 32) {
-               errno = EINVAL;
-               return -1;
-       }
-       ocets = (cidr + 7) / 8;
-
-       addr->s_addr = 0;
-       if (ocets > 0) {
-               memset(&addr->s_addr, 255, (size_t)ocets - 1);
-               memset((unsigned char *)&addr->s_addr + (ocets - 1),
-                   (256 - (1 << (32 - cidr) % 8)), 1);
-       }
-
-       return 0;
-}
-
-uint32_t
-get_netmask(uint32_t addr)
-{
-       uint32_t dst;
-
-       if (addr == 0)
-               return 0;
-
-       dst = htonl(addr);
-       if (IN_CLASSA(dst))
-               return ntohl(IN_CLASSA_NET);
-       if (IN_CLASSB(dst))
-               return ntohl(IN_CLASSB_NET);
-       if (IN_CLASSC(dst))
-               return ntohl(IN_CLASSC_NET);
-
-       return 0;
-}
-
 char *
 hwaddr_ntoa(const unsigned char *hwaddr, size_t hwlen)
 {
@@ -485,53 +420,6 @@ discover_interfaces(int argc, char * const *argv)
        return ifs;
 }
 
-int
-do_address(const char *ifname,
-    struct in_addr *addr, struct in_addr *net, struct in_addr *dst, int act)
-{
-       struct ifaddrs *ifaddrs, *ifa;
-       const struct sockaddr_in *a, *n, *d;
-       int retval;
-
-       if (getifaddrs(&ifaddrs) == -1)
-               return -1;
-
-       retval = 0;
-       for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
-               if (ifa->ifa_addr == NULL ||
-                   ifa->ifa_addr->sa_family != AF_INET ||
-                   strcmp(ifa->ifa_name, ifname) != 0)
-                       continue;
-               a = (const struct sockaddr_in *)(void *)ifa->ifa_addr;
-               n = (const struct sockaddr_in *)(void *)ifa->ifa_netmask;
-               if (ifa->ifa_flags & IFF_POINTOPOINT)
-                       d = (const struct sockaddr_in *)(void *)
-                           ifa->ifa_dstaddr;
-               else
-                       d = NULL;
-               if (act == 1) {
-                       addr->s_addr = a->sin_addr.s_addr;
-                       net->s_addr = n->sin_addr.s_addr;
-                       if (dst) {
-                               if (ifa->ifa_flags & IFF_POINTOPOINT)
-                                       dst->s_addr = d->sin_addr.s_addr;
-                               else
-                                       dst->s_addr = INADDR_ANY;
-                       }
-                       retval = 1;
-                       break;
-               }
-               if (addr->s_addr == a->sin_addr.s_addr &&
-                   (net == NULL || net->s_addr == n->sin_addr.s_addr))
-               {
-                       retval = 1;
-                       break;
-               }
-       }
-       freeifaddrs(ifaddrs);
-       return retval;
-}
-
 int
 do_mtu(const char *ifname, short int mtu)
 {
@@ -546,221 +434,3 @@ do_mtu(const char *ifname, short int mtu)
                return -1;
        return ifr.ifr_mtu;
 }
-
-void
-free_routes(struct rt *routes)
-{
-       struct rt *r;
-
-       while (routes) {
-               r = routes->next;
-               free(routes);
-               routes = r;
-       }
-}
-
-int
-open_udp_socket(struct interface *iface)
-{
-       int s;
-       struct sockaddr_in sin;
-       int n;
-       struct dhcp_state *state;
-#ifdef SO_BINDTODEVICE
-       struct ifreq ifr;
-       char *p;
-#endif
-
-       if ((s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
-               return -1;
-
-       n = 1;
-       if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) == -1)
-               goto eexit;
-#ifdef SO_BINDTODEVICE
-       memset(&ifr, 0, sizeof(ifr));
-       strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
-       /* We can only bind to the real device */
-       p = strchr(ifr.ifr_name, ':');
-       if (p)
-               *p = '\0';
-       if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, &ifr,
-               sizeof(ifr)) == -1)
-               goto eexit;
-#endif
-       /* As we don't use this socket for receiving, set the
-        * receive buffer to 1 */
-       n = 1;
-       if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) == -1)
-               goto eexit;
-       state = D_STATE(iface);
-       memset(&sin, 0, sizeof(sin));
-       sin.sin_family = AF_INET;
-       sin.sin_port = htons(DHCP_CLIENT_PORT);
-       sin.sin_addr.s_addr = state->addr.s_addr;
-       if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) == -1)
-               goto eexit;
-
-       state->udp_fd = s;
-       set_cloexec(s);
-       return 0;
-
-eexit:
-       close(s);
-       return -1;
-}
-
-ssize_t
-send_packet(const struct interface *iface, struct in_addr to,
-    const uint8_t *data, ssize_t len)
-{
-       struct sockaddr_in sin;
-
-       memset(&sin, 0, sizeof(sin));
-       sin.sin_family = AF_INET;
-       sin.sin_addr.s_addr = to.s_addr;
-       sin.sin_port = htons(DHCP_SERVER_PORT);
-       return sendto(D_CSTATE(iface)->udp_fd, data, len, 0,
-           (struct sockaddr *)&sin, sizeof(sin));
-}
-
-struct udp_dhcp_packet
-{
-       struct ip ip;
-       struct udphdr udp;
-       struct dhcp_message dhcp;
-};
-const size_t udp_dhcp_len = sizeof(struct udp_dhcp_packet);
-
-static uint16_t
-checksum(const void *data, uint16_t len)
-{
-       const uint8_t *addr = data;
-       uint32_t sum = 0;
-
-       while (len > 1) {
-               sum += addr[0] * 256 + addr[1];
-               addr += 2;
-               len -= 2;
-       }
-
-       if (len == 1)
-               sum += *addr * 256;
-
-       sum = (sum >> 16) + (sum & 0xffff);
-       sum += (sum >> 16);
-
-       sum = htons(sum);
-
-       return ~sum;
-}
-
-ssize_t
-make_udp_packet(uint8_t **packet, const uint8_t *data, size_t length,
-    struct in_addr source, struct in_addr dest)
-{
-       struct udp_dhcp_packet *udpp;
-       struct ip *ip;
-       struct udphdr *udp;
-
-       udpp = xzalloc(sizeof(*udpp));
-       ip = &udpp->ip;
-       udp = &udpp->udp;
-
-       /* OK, this is important :)
-        * We copy the data to our packet and then create a small part of the
-        * ip structure and an invalid ip_len (basically udp length).
-        * We then fill the udp structure and put the checksum
-        * of the whole packet into the udp checksum.
-        * Finally we complete the ip structure and ip checksum.
-        * If we don't do the ordering like so then the udp checksum will be
-        * broken, so find another way of doing it! */
-
-       memcpy(&udpp->dhcp, data, length);
-
-       ip->ip_p = IPPROTO_UDP;
-       ip->ip_src.s_addr = source.s_addr;
-       if (dest.s_addr == 0)
-               ip->ip_dst.s_addr = INADDR_BROADCAST;
-       else
-               ip->ip_dst.s_addr = dest.s_addr;
-
-       udp->uh_sport = htons(DHCP_CLIENT_PORT);
-       udp->uh_dport = htons(DHCP_SERVER_PORT);
-       udp->uh_ulen = htons(sizeof(*udp) + length);
-       ip->ip_len = udp->uh_ulen;
-       udp->uh_sum = checksum(udpp, sizeof(*udpp));
-
-       ip->ip_v = IPVERSION;
-       ip->ip_hl = sizeof(*ip) >> 2;
-       ip->ip_id = arc4random() & UINT16_MAX;
-       ip->ip_ttl = IPDEFTTL;
-       ip->ip_len = htons(sizeof(*ip) + sizeof(*udp) + length);
-       ip->ip_sum = checksum(ip, sizeof(*ip));
-
-       *packet = (uint8_t *)udpp;
-       return sizeof(*ip) + sizeof(*udp) + length;
-}
-
-ssize_t
-get_udp_data(const uint8_t **data, const uint8_t *udp)
-{
-       struct udp_dhcp_packet packet;
-
-       memcpy(&packet, udp, sizeof(packet));
-       *data = udp + offsetof(struct udp_dhcp_packet, dhcp);
-       return ntohs(packet.ip.ip_len) -
-           sizeof(packet.ip) -
-           sizeof(packet.udp);
-}
-
-int
-valid_udp_packet(const uint8_t *data, size_t data_len, struct in_addr *from,
-    int noudpcsum)
-{
-       struct udp_dhcp_packet packet;
-       uint16_t bytes, udpsum;
-
-       if (data_len < sizeof(packet.ip)) {
-               if (from)
-                       from->s_addr = INADDR_ANY;
-               errno = EINVAL;
-               return -1;
-       }
-       memcpy(&packet, data, MIN(data_len, sizeof(packet)));
-       if (from)
-               from->s_addr = packet.ip.ip_src.s_addr;
-       if (data_len > sizeof(packet)) {
-               errno = EINVAL;
-               return -1;
-       }
-       if (checksum(&packet.ip, sizeof(packet.ip)) != 0) {
-               errno = EINVAL;
-               return -1;
-       }
-
-       bytes = ntohs(packet.ip.ip_len);
-       if (data_len < bytes) {
-               errno = EINVAL;
-               return -1;
-       }
-
-       if (noudpcsum == 0) {
-               udpsum = packet.udp.uh_sum;
-               packet.udp.uh_sum = 0;
-               packet.ip.ip_hl = 0;
-               packet.ip.ip_v = 0;
-               packet.ip.ip_tos = 0;
-               packet.ip.ip_len = packet.udp.uh_ulen;
-               packet.ip.ip_id = 0;
-               packet.ip.ip_off = 0;
-               packet.ip.ip_ttl = 0;
-               packet.ip.ip_sum = 0;
-               if (udpsum && checksum(&packet, bytes) != udpsum) {
-                       errno = EINVAL;
-                       return -1;
-               }
-       }
-
-       return 0;
-}
diff --git a/net.h b/net.h
index 0d1475a0d1017d4224f01ef74408b1a3df842542..cf52e7dac80b3c05703f400ff7bc680ae9614909 100644 (file)
--- a/net.h
+++ b/net.h
 # define IN_LINKLOCAL(addr) ((addr & IN_CLASSB_NET) == LINKLOCAL_ADDR)
 #endif
 
-struct rt {
-       struct in_addr dest;
-       struct in_addr net;
-       struct in_addr gate;
-       const struct interface *iface;
-       int metric;
-       struct in_addr src;
-       struct rt *next;
-};
-
 extern int socket_afnet;
 
-uint32_t get_netmask(uint32_t);
+int open_sockets(void);
+
 char *hwaddr_ntoa(const unsigned char *, size_t);
 size_t hwaddr_aton(unsigned char *, const char *);
 
@@ -112,34 +103,10 @@ int do_mtu(const char *, short int);
 #define get_mtu(iface) do_mtu(iface, 0)
 #define set_mtu(iface, mtu) do_mtu(iface, mtu)
 
-int inet_ntocidr(struct in_addr);
-int inet_cidrtoaddr(int, struct in_addr *);
-
 int up_interface(struct interface *);
 int if_conf(struct interface *);
 int if_init(struct interface *);
 
-int do_address(const char *,
-    struct in_addr *, struct in_addr *, struct in_addr *, int);
-int if_address(const struct interface *,
-    const struct in_addr *, const struct in_addr *,
-    const struct in_addr *, int);
-#define add_address(iface, addr, net, brd)                                   \
-       if_address(iface, addr, net, brd, 1)
-#define del_address(iface, addr, net)                                        \
-       if_address(iface, addr, net, NULL, -1)
-#define has_address(iface, addr, net)                                        \
-       do_address(iface, addr, net, NULL, 0)
-#define get_address(iface, addr, net, dst)                                   \
-       do_address(iface, addr, net, dst, 1)
-
-int if_route(const struct rt *rt, int);
-#define add_route(rt) if_route(rt, 1)
-#define change_route(rt) if_route(rt, 0)
-#define del_route(rt) if_route(rt, -1)
-#define del_src_route(rt) if_route(rt, -2);
-void free_routes(struct rt *);
-
 int if_address6(const struct interface *, const struct ipv6_addr *, int);
 #define add_address6(ifp, a) if_address6(ifp, a, 1)
 #define del_address6(ifp, a) if_address6(ifp, a, -1)
@@ -150,21 +117,6 @@ int if_route6(const struct rt6 *rt, int);
 #define del_route6(rt) if_route6(rt, -1)
 #define del_src_route6(rt) if_route6(rt, -2);
 
-int open_udp_socket(struct interface *);
-extern const size_t udp_dhcp_len;
-ssize_t make_udp_packet(uint8_t **, const uint8_t *, size_t,
-    struct in_addr, struct in_addr);
-ssize_t get_udp_data(const uint8_t **, const uint8_t *);
-int valid_udp_packet(const uint8_t *, size_t, struct in_addr *, int);
-
-int open_socket(struct interface *, int);
-ssize_t send_packet(const struct interface *, struct in_addr, 
-    const uint8_t *, ssize_t);
-ssize_t send_raw_packet(const struct interface *, int,
-    const void *, ssize_t);
-ssize_t get_raw_packet(struct interface *, int, void *, ssize_t, int *);
-
-int init_sockets(void);
 int open_link_socket(void);
 int manage_link(int);
 int carrier_status(struct interface *);