summaryrefslogtreecommitdiffstats
path: root/src/net/udp/dhcp.c
diff options
context:
space:
mode:
authorMichael Brown2007-01-04 04:42:28 +0100
committerMichael Brown2007-01-04 04:42:28 +0100
commit7fafa8925800f3b6caf4983efd731b0c680caa49 (patch)
tree97d46520e772119f21f034a166b0319064888853 /src/net/udp/dhcp.c
parentAdded missing #include (diff)
downloadipxe-7fafa8925800f3b6caf4983efd731b0c680caa49.tar.gz
ipxe-7fafa8925800f3b6caf4983efd731b0c680caa49.tar.xz
ipxe-7fafa8925800f3b6caf4983efd731b0c680caa49.zip
A DHCP session holds a persistent reference to a network device
Diffstat (limited to 'src/net/udp/dhcp.c')
-rw-r--r--src/net/udp/dhcp.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c
index f8107777..59dc8071 100644
--- a/src/net/udp/dhcp.c
+++ b/src/net/udp/dhcp.c
@@ -498,6 +498,7 @@ udp_to_dhcp ( struct udp_connection *conn ) {
* @v rc Return status code
*/
static void dhcp_done ( struct dhcp_session *dhcp, int rc ) {
+
/* Free up options if we failed */
if ( rc != 0 ) {
if ( dhcp->options ) {
@@ -506,9 +507,15 @@ static void dhcp_done ( struct dhcp_session *dhcp, int rc ) {
}
}
+ /* Stop retry timer */
+ stop_timer ( &dhcp->timer );
+
/* Close UDP connection */
udp_close ( &dhcp->udp );
+ /* Release reference on net device */
+ ref_del ( &dhcp->netdev_ref );
+
/* Mark async operation as complete */
async_done ( &dhcp->aop, rc );
}
@@ -690,6 +697,19 @@ static struct udp_operations dhcp_udp_operations = {
};
/**
+ * Forget reference to net_device
+ *
+ * @v ref Persistent reference
+ */
+static void dhcp_forget_netdev ( struct reference *ref ) {
+ struct dhcp_session *dhcp
+ = container_of ( ref, struct dhcp_session, netdev_ref );
+
+ /* Kill DHCP session immediately */
+ dhcp_done ( dhcp, -ENETUNREACH );
+}
+
+/**
* Initiate DHCP on a network interface
*
* @v dhcp DHCP session
@@ -714,6 +734,10 @@ struct async_operation * start_dhcp ( struct dhcp_session *dhcp ) {
goto out;
}
+ /* Add persistent reference to net device */
+ dhcp->netdev_ref.forget = dhcp_forget_netdev;
+ ref_add ( &dhcp->netdev_ref, &dhcp->netdev->references );
+
/* Proof of concept: just send a single DHCPDISCOVER */
dhcp_send_request ( dhcp );