]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Add a listening port for linux for when we have configured an address and need to...
authorRoy Marples <roy@marples.name>
Thu, 21 Feb 2008 16:45:01 +0000 (16:45 +0000)
committerRoy Marples <roy@marples.name>
Thu, 21 Feb 2008 16:45:01 +0000 (16:45 +0000)
client.c
interface.c
interface.h
socket.c

index b7957f77f877e87c5421ef7b31a56a9a434aa5b1..2876f49115c266a2225d24fd9dabad9866f403d8 100644 (file)
--- a/client.c
+++ b/client.c
@@ -432,6 +432,12 @@ static bool do_socket (state_t *state, int mode)
 {
        if (state->interface->fd >= 0)
                close (state->interface->fd);
+#ifdef __linux
+       if (mode == SOCKET_CLOSED && state->interface->listen_fd >= 0) {
+               close (state->interface->listen_fd);
+               state->interface->listen_fd = -1;
+       }
+#endif
 
        state->interface->fd = -1; 
        if (mode == SOCKET_OPEN) 
index 1fd6f645efc323754c605645d0a1212e3af00c2e..1178382d93ce9b6da852ede8be3a72202c8a8733 100644 (file)
@@ -429,6 +429,9 @@ interface_t *read_interface (const char *ifname, _unused int metric)
 
        /* 0 is a valid fd, so init to -1 */
        iface->fd = -1;
+#ifdef __linux__
+       iface->listen_fd = -1;
+#endif
 
 exit:
        close (s);
index 3f42ef5cb73a2a44f5f13c6537645b5b7d01a1ca..8215d48f37ee95aaf38902febe167611652c085b 100644 (file)
@@ -120,6 +120,7 @@ typedef struct interface_t
        size_t buffer_length;
 
 #ifdef __linux__
+       int listen_fd;
        int socket_protocol;
 #endif
 
index a854f9404b6f7f4cc518875da065271472cd73ec..7ea05d05ce10efafdfa001950802876cf4230baf 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -451,10 +451,43 @@ int open_socket (interface_t *iface, int protocol)
        int fd;
        union sockunion {
                struct sockaddr sa;
+               struct sockaddr_in sin;
                struct sockaddr_ll sll;
                struct sockaddr_storage ss;
        } su;
        struct sock_fprog pf;
+       struct ifreq ifr;
+       int n = 1;
+
+       /* We need to bind to a port, otherwise Linux generate ICMP messages
+        * that cannot contect the port when we have an address.
+        * We don't actually use this fd at all, instead using our packet
+        * filter socket. */
+       if (iface->listen_fd == -1 &&
+           iface->previous_address.s_addr &&
+           ! IN_LINKLOCAL (iface->previous_address.s_addr))
+       {
+               if ((fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
+                       logger (LOG_ERR, "socket: %s", strerror (errno));
+               } else {
+                       memset (&su, 0, sizeof (su));
+                       su.sin.sin_family = AF_INET;
+                       su.sin.sin_port = htons (DHCP_CLIENT_PORT);
+                       su.sin.sin_addr = iface->previous_address;
+                       if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof (n)) == -1)
+                               logger (LOG_ERR, "SO_REUSEADDR: %s", strerror (errno));
+                       strncpy (ifr.ifr_name, iface->name, sizeof (ifr.ifr_name));
+                       if (setsockopt (fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof (ifr)) == -1)
+                               logger (LOG_ERR, "SO_SOBINDTODEVICE: %s", strerror (errno));
+                       if (bind (fd, &su.sa, sizeof (su)) == -1) {
+                               logger (LOG_ERR, "bind: %s", strerror (errno));
+                               close (fd);
+                       } else {
+                               iface->listen_fd = fd;
+                               close_on_exec (fd);
+                       }
+               }
+       }
 
        if ((fd = socket (PF_PACKET, SOCK_DGRAM, htons (protocol))) == -1) {
                logger (LOG_ERR, "socket: %s", strerror (errno));
@@ -491,8 +524,7 @@ int open_socket (interface_t *iface, int protocol)
                return (-1);
        }
 
-       if (bind (fd, &su.sa, sizeof (su)) == -1)
-       {
+       if (bind (fd, &su.sa, sizeof (su)) == -1) {
                logger (LOG_ERR, "bind: %s", strerror (errno));
                close (fd);
                return (-1);