Send connman mailing list submissions to
[email protected]
To subscribe or unsubscribe via the World Wide Web, visit
https://lists.01.org/mailman/listinfo/connman
or, via email, send a message with subject or body 'help' to
[email protected]
You can reach the person managing the list at
[email protected]
When replying, please edit your Subject line so it is more specific
than "Re: Contents of connman digest..."
Today's Topics:
1. [PATCH] gdhcp: use opened listening socket to send DHCP renew
request (Feng Wang)
2. [PATCH] gdhcp: use opened listening socket to send DHCP renew
request (Feng Wang)
----------------------------------------------------------------------
Message: 1
Date: Fri, 29 Jan 2016 16:47:16 -0800
From: Feng Wang <[email protected]>
To: [email protected]
Subject: [PATCH] gdhcp: use opened listening socket to send DHCP renew
request
Message-ID: <[email protected]>
DHCP Renew Failure:
When connmand doing DHCP renew, we found out sometimes the DHCP ACK was lost.
But the DHCP ACK packet was received in the IP layer. The tcpdump shows the
packet,
but the packet isn't passed to the glib and connmand.
Failure Reason:
The packet was routed to the wrong socket. Connmand created 2 sockets to do
the DHCP renew.
One is for listening the received DHCP ACK(dhcp_l3_socket), the other is to
transmit the
DHCP request(dhcp_send_kernel_packet). The transmit socket is closed
immediately when the
request is transmitted. Normally, the socket is closed before DHCP ACK is
received, so the
DHCP ACK is routed to the listening socket. But when adding some debug
information in the kernel,
we found in some cases, the socket was closed after DHCP ACK arrived. In this
case, the packet
was routed to the transmitting socket, because it has a better match result.
But the connmand
only listen on the listening socket, and this packet was dropped when the
socket was closed.
Proposed Fix:
Use one socket to listen and transmit similar to NTP implementation. When
doing the DHCP renew,
use the listening socket to transmit request. The new code will create a new
socket if no socket
opened(current code) in the DHCP release case, else it will use existing socket
in the DHCP renew case.
I attached the patch in the next email.
------------------------------
Message: 2
Date: Fri, 29 Jan 2016 16:47:34 -0800
From: Feng Wang <[email protected]>
To: [email protected]
Subject: [PATCH] gdhcp: use opened listening socket to send DHCP renew
request
Message-ID: <[email protected]>
It fix DHCP ACK lost issue when doing DHCP renewal.
When doing DHCP renew, 2 sockets are opened. One is for
listening DHCP ACK, the other is for transmitting DHCP request
which is closed immediately after transmitting is done. But in
some cases, the socket is closed after the DHCP ACK is received.
The kernel will route the packet to the transmitting socket
because it has a better match result(dst ip/port etc). And the
packet was dropped when the socket was closed.
---
gdhcp/client.c | 6 ++++--
gdhcp/common.c | 60 +++++++++++++++++++++++++++++++++++-----------------------
gdhcp/common.h | 2 +-
3 files changed, 41 insertions(+), 27 deletions(-)
diff --git a/gdhcp/client.c b/gdhcp/client.c
index 3bf8cb2..ad587b1 100644
--- a/gdhcp/client.c
+++ b/gdhcp/client.c
@@ -502,7 +502,8 @@ static int send_request(GDHCPClient *dhcp_client)
if (dhcp_client->state == RENEWING)
return dhcp_send_kernel_packet(&packet,
dhcp_client->requested_ip, CLIENT_PORT,
- dhcp_client->server_ip, SERVER_PORT);
+ dhcp_client->server_ip, SERVER_PORT,
+ dhcp_client->listener_sockfd);
return dhcp_send_raw_packet(&packet, INADDR_ANY, CLIENT_PORT,
INADDR_BROADCAST, SERVER_PORT,
@@ -526,7 +527,8 @@ static int send_release(GDHCPClient *dhcp_client,
dhcp_add_option_uint32(&packet, DHCP_SERVER_ID, server);
return dhcp_send_kernel_packet(&packet, ciaddr, CLIENT_PORT,
- server, SERVER_PORT);
+ server, SERVER_PORT,
+ dhcp_client->listener_sockfd);
}
static gboolean ipv4ll_probe_timeout(gpointer dhcp_data);
diff --git a/gdhcp/common.c b/gdhcp/common.c
index f3d4677..f0a9aa6 100644
--- a/gdhcp/common.c
+++ b/gdhcp/common.c
@@ -626,44 +626,56 @@ int dhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt,
int dhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt,
uint32_t source_ip, int source_port,
- uint32_t dest_ip, int dest_port)
+ uint32_t dest_ip, int dest_port, int fd)
{
struct sockaddr_in client;
- int fd, n, opt = 1;
+ int n, opt = 1;
enum {
DHCP_SIZE = sizeof(struct dhcp_packet) -
EXTEND_FOR_BUGGY_SERVERS,
};
- fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
- if (fd < 0)
- return -errno;
+ if (fd < 0) {
+ /* no socket opened, open a new socket to tx the packet and
close it */
+ fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
+ if (fd < 0)
+ return -errno;
+
+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+
+ memset(&client, 0, sizeof(client));
+ client.sin_family = AF_INET;
+ client.sin_port = htons(source_port);
+ client.sin_addr.s_addr = htonl(source_ip);
+ if (bind(fd, (struct sockaddr *) &client, sizeof(client)) < 0) {
+ close(fd);
+ return -errno;
+ }
- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+ memset(&client, 0, sizeof(client));
+ client.sin_family = AF_INET;
+ client.sin_port = htons(dest_port);
+ client.sin_addr.s_addr = htonl(dest_ip);
+ if (connect(fd, (struct sockaddr *) &client, sizeof(client)) <
0) {
+ close(fd);
+ return -errno;
+ }
- memset(&client, 0, sizeof(client));
- client.sin_family = AF_INET;
- client.sin_port = htons(source_port);
- client.sin_addr.s_addr = htonl(source_ip);
- if (bind(fd, (struct sockaddr *) &client, sizeof(client)) < 0) {
- close(fd);
- return -errno;
- }
+ n = write(fd, dhcp_pkt, DHCP_SIZE);
- memset(&client, 0, sizeof(client));
- client.sin_family = AF_INET;
- client.sin_port = htons(dest_port);
- client.sin_addr.s_addr = htonl(dest_ip);
- if (connect(fd, (struct sockaddr *) &client, sizeof(client)) < 0) {
close(fd);
- return -errno;
+ } else {
+ /* Using existed socket to transmit the packet */
+ memset(&client, 0, sizeof(client));
+ client.sin_family = AF_INET;
+ client.sin_port = htons(dest_port);
+ client.sin_addr.s_addr = htonl(dest_ip);
+
+ n = sendto(fd, dhcp_pkt, DHCP_SIZE, MSG_DONTWAIT,
+ (struct sockaddr *) &client, sizeof(client));
}
- n = write(fd, dhcp_pkt, DHCP_SIZE);
-
- close(fd);
-
if (n < 0)
return -errno;
diff --git a/gdhcp/common.h b/gdhcp/common.h
index 75abc18..b92d214 100644
--- a/gdhcp/common.h
+++ b/gdhcp/common.h
@@ -209,7 +209,7 @@ int dhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt,
int dhcpv6_send_packet(int index, struct dhcpv6_packet *dhcp_pkt, int len);
int dhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt,
uint32_t source_ip, int source_port,
- uint32_t dest_ip, int dest_port);
+ uint32_t dest_ip, int dest_port, int fd);
int dhcp_l3_socket(int port, const char *interface, int family);
int dhcp_recv_l3_packet(struct dhcp_packet *packet, int fd);
int dhcpv6_recv_l3_packet(struct dhcpv6_packet **packet, unsigned char *buf,
--
2.7.0.rc3.207.g0ac5344
------------------------------
Subject: Digest Footer
_______________________________________________
connman mailing list
[email protected]
https://lists.01.org/mailman/listinfo/connman
------------------------------
End of connman Digest, Vol 3, Issue 25
**************************************