]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
We should send packets to a specific IP over the udp socket so we don't broadcast...
authorRoy Marples <roy@marples.name>
Sun, 20 Apr 2008 19:02:19 +0000 (19:02 +0000)
committerRoy Marples <roy@marples.name>
Sun, 20 Apr 2008 19:02:19 +0000 (19:02 +0000)
bpf.c
client.c
dhcp.c
dhcpcd.8.in
dhcpcd.conf.5
net.c
net.h
socket.c

diff --git a/bpf.c b/bpf.c
index e419cb40f82361bb39b79b3898444b85a52606ce..da75a3151f42ecc13897213211d0332e14ad069f 100644 (file)
--- a/bpf.c
+++ b/bpf.c
@@ -122,8 +122,8 @@ eexit:
 }
 
 ssize_t
-send_packet(const struct interface *iface, int type,
-           const unsigned char *data, ssize_t len)
+send_raw_packet(const struct interface *iface, int type,
+               const unsigned char *data, ssize_t len)
 {
        struct iovec iov[2];
        struct ether_header hw;
index ae28023023b9523599fd968e722af6ea0ebde81e..48d17ac7b47f433a4d6a4c4db2e679af71daa023 100644 (file)
--- a/client.c
+++ b/client.c
@@ -601,10 +601,12 @@ send_message(struct if_state *state, int type, const struct options *options)
        struct dhcp_message *dhcp;
        uint8_t *udp;
        ssize_t len;
-       ssize_t retval;
+       ssize_t r;
        struct in_addr from;
        struct in_addr to;
 
+       logger(LOG_DEBUG, "sending %s with xid 0x%x",
+              get_dhcp_op(type), state->xid);
        state->last_type = type;
        state->last_sent = uptime();
        len = make_message(&dhcp, state->interface, &state->lease, state->xid,
@@ -614,15 +616,19 @@ send_message(struct if_state *state, int type, const struct options *options)
                to.s_addr = state->lease.server.s_addr;
        else
                to.s_addr = 0;
-       len = make_udp_packet(&udp, (uint8_t *)dhcp, len, from, to);
-       free(dhcp);
-       logger(LOG_DEBUG, "sending %s with xid 0x%x",
-               get_dhcp_op(type), state->xid);
-       retval = send_packet(state->interface, ETHERTYPE_IP, udp, len);
-       if (retval == -1)
-               logger(LOG_ERR, "send_packet: %s", strerror(errno));
-       free(udp);
-       return retval;
+       if (to.s_addr) {
+               r = send_packet(state->interface, to, (uint8_t *)dhcp, len);
+               if (r == -1)
+                       logger(LOG_ERR, "send_packet: %s", strerror(errno));
+       } else {
+               len = make_udp_packet(&udp, (uint8_t *)dhcp, len, from, to);
+               free(dhcp);
+               r = send_raw_packet(state->interface, ETHERTYPE_IP, udp, len);
+               if (r == -1)
+                       logger(LOG_ERR, "send_raw_packet: %s", strerror(errno));
+               free(udp);
+       }
+       return r;
 }
 
 static void
@@ -809,7 +815,8 @@ handle_timeout(struct if_state *state, const struct options *options)
 
                do_socket(state, SOCKET_CLOSED);
 
-               if (options->options & DHCPCD_INFORM)
+               if (options->options & DHCPCD_INFORM ||
+                   options->options & DHCPCD_TEST)
                        return -1;
 
                if (state->options & DHCPCD_IPV4LL ||
diff --git a/dhcp.c b/dhcp.c
index ebd3284b1b1a31b0cb15e4fe50cdf7b9447dbdc9..820f3dd50c070b685b4e46da63976dcae1fee7d1 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -696,8 +696,8 @@ make_message(struct dhcp_message **message,
             uint32_t xid, uint8_t type, const struct options *options)
 {
        struct dhcp_message *dhcp;
-       uint8_t *m;
-       uint8_t *p;
+       uint8_t *d, *m, *p;
+       const char *c;
        uint8_t *n_params = NULL;
        size_t l;
        time_t up = uptime() - iface->start_uptime;
@@ -826,8 +826,9 @@ make_message(struct dhcp_message **message,
                        } else {
                                /* Draft IETF DHC-FQDN option (81) */
                                *p++ = DHCP_FQDN;
-                               *p++ = (l = strlen(options->hostname)) + 3;
-                               /* Flags: 0000NEOS
+                               *p++ = strlen(options->hostname) + 5;
+                               /*
+                                * Flags: 0000NEOS
                                 * S: 1 => Client requests Server to update
                                 *         a RR in DNS as well as PTR
                                 * O: 1 => Server indicates to client that
@@ -836,11 +837,20 @@ make_message(struct dhcp_message **message,
                                 * N: 1 => Client requests Server to not
                                 *         update DNS
                                 */
-                               *p++ = options->fqdn & 0x9;
+                               *p++ = (options->fqdn & 0x9) | 0x4;
                                *p++ = 0; /* from server for PTR RR */
                                *p++ = 0; /* from server for A RR if S=1 */
-                               memcpy(p, options->hostname, l);
-                               p += l;
+                               c = options->hostname;
+                               d = p++;
+                               while (*c) {
+                                       if (*c == '.') {
+                                               *d = p - d - 1;
+                                               d = p++;
+                                       } else
+                                               *p++ = (uint8_t) *c;
+                                       c++;
+                               }
+                               *p ++ = 0;
                        }
                }
 
index d187e8f809add18260ea902c7bb56bb9fbdf97e4..8ff4f6053ea2e1d4a94c20961996f0409c6a13dc 100644 (file)
@@ -132,7 +132,9 @@ You can use this option to specify the
 sent, or an empty string to
 stop any
 .Ar hostname
-from being sent.
+from being sent. If
+.Ar hostname
+is an FQDN (ie, contains a .) then it will be encoded as such.
 .It Fl i , -classid Ar classid
 Override the DHCP vendor
 .Ar classid
index 9b95fba144f49cfdda80ffb76772b82eb2f4058b..9befff3ae505237dad94dac21a04b3cb6b024cce 100644 (file)
@@ -46,7 +46,14 @@ from the server. It can be a variable to be used in
 or the numerical value. You can specify more seperated by commas, spaces or
 more option lines.
 .It Ic hostname Ar name
-Sends specified hostname to the DHCP server so it can be registered in DNS.
+Sends specified
+.Ar hostname 
+o the DHCP server so it can be registered in DNS. If
+.Ar hostname
+if a FQDN (ie, contains a .) then it will be encoded a such.
+.It Ic fqdn Op none | ptr | both
+none disables FQDN encoding, ptr just asks the DHCP server to update the PTR
+record of the host in DNS whereas both also updates the A record.
 .It Ic leasetime Ar seconds
 Request a leasetime of
 .Ar seconds .
diff --git a/net.c b/net.c
index 10661956732be3f46f78303ca6d521614f21a9fa..467cdf7e3d3b3f6e11bda9ea4293dfbc17649b91 100644 (file)
--- a/net.c
+++ b/net.c
@@ -443,6 +443,23 @@ eexit:
         return -1;
 }
 
+ssize_t
+send_packet(const struct interface *iface, struct in_addr to,
+           const uint8_t *data, ssize_t len)
+{
+       union sockunion {
+               struct sockaddr sa;
+               struct sockaddr_in sin;
+       } su;
+
+       memset(&su, 0, sizeof(su));
+       su.sin.sin_family = AF_INET;
+       su.sin.sin_addr.s_addr = to.s_addr;
+       su.sin.sin_port = htons(DHCP_SERVER_PORT);
+
+       return sendto(iface->udp_fd, data, len, 0, &su.sa, sizeof(su));
+}
+
 struct udp_dhcp_packet
 {
        struct ip ip;
@@ -648,8 +665,8 @@ send_arp(const struct interface *iface, int op, struct in_addr sip,
        }
        memcpy(ar_tpa(arp), &tip, (size_t)arp->ar_pln);
 
-       retval = send_packet(iface, ETHERTYPE_ARP,
-                            (unsigned char *) arp, arphdr_len(arp));
+       retval = send_raw_packet(iface, ETHERTYPE_ARP,
+                                (uint8_t *)arp, arphdr_len(arp));
        if (retval == -1)
                logger(LOG_ERR,"send_packet: %s", strerror(errno));
        free(arp);
diff --git a/net.h b/net.h
index d767a9ee7c21f6f4e82a90a50c47d06884dc15d2..ef968e18fd464f299eb0f6b2f42a84c878fd3ced 100644 (file)
--- a/net.h
+++ b/net.h
@@ -166,8 +166,10 @@ int valid_udp_packet(uint8_t *);
 void setup_packet_filters(void);
 #endif
 int open_socket(struct interface *, int);
-ssize_t send_packet(const 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 uint8_t *, ssize_t);
 ssize_t get_packet(const struct interface *, uint8_t *,
                   uint8_t *, ssize_t *, ssize_t *);
 
index 97a24be4db48d3b01abbcf5ff79ed21f84fa29c9..54d2706dbb48db1b3c6e2fe51a73b8c370a227a5 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -141,8 +141,8 @@ eexit:
 }
 
 ssize_t
-send_packet(const struct interface *iface, int type,
-           const uint8_t *data, ssize_t len)
+send_raw_packet(const struct interface *iface, int type,
+               const uint8_t *data, ssize_t len)
 {
        union sockunion {
                struct sockaddr sa;
@@ -153,12 +153,10 @@ send_packet(const struct interface *iface, int type,
        memset(&su, 0, sizeof(su));
        su.sll.sll_family = AF_PACKET;
        su.sll.sll_protocol = htons(type);
-
        if (!(su.sll.sll_ifindex = if_nametoindex(iface->name))) {
                errno = ENOENT;
                return -1;
        }
-
        su.sll.sll_hatype = htons(iface->family);
        su.sll.sll_halen = iface->hwlen;
        if (iface->family == ARPHRD_INFINIBAND)
@@ -167,7 +165,7 @@ send_packet(const struct interface *iface, int type,
        else
                memset(&su.sll.sll_addr, 0xff, iface->hwlen);
 
-       return sendto(iface->fd, data, len,0,&su.sa,sizeof(su));
+       return sendto(iface->fd, data, len, 0, &su.sa, sizeof(su));
 }
 
 /* Linux has no need for the buffer as we can read as much as we want.