|
@@ -498,6 +498,7 @@ udp_to_dhcp ( struct udp_connection *conn ) {
|
498
|
498
|
* @v rc Return status code
|
499
|
499
|
*/
|
500
|
500
|
static void dhcp_done ( struct dhcp_session *dhcp, int rc ) {
|
|
501
|
+
|
501
|
502
|
/* Free up options if we failed */
|
502
|
503
|
if ( rc != 0 ) {
|
503
|
504
|
if ( dhcp->options ) {
|
|
@@ -506,9 +507,15 @@ static void dhcp_done ( struct dhcp_session *dhcp, int rc ) {
|
506
|
507
|
}
|
507
|
508
|
}
|
508
|
509
|
|
|
510
|
+ /* Stop retry timer */
|
|
511
|
+ stop_timer ( &dhcp->timer );
|
|
512
|
+
|
509
|
513
|
/* Close UDP connection */
|
510
|
514
|
udp_close ( &dhcp->udp );
|
511
|
515
|
|
|
516
|
+ /* Release reference on net device */
|
|
517
|
+ ref_del ( &dhcp->netdev_ref );
|
|
518
|
+
|
512
|
519
|
/* Mark async operation as complete */
|
513
|
520
|
async_done ( &dhcp->aop, rc );
|
514
|
521
|
}
|
|
@@ -689,6 +696,19 @@ static struct udp_operations dhcp_udp_operations = {
|
689
|
696
|
.newdata = dhcp_newdata,
|
690
|
697
|
};
|
691
|
698
|
|
|
699
|
+/**
|
|
700
|
+ * Forget reference to net_device
|
|
701
|
+ *
|
|
702
|
+ * @v ref Persistent reference
|
|
703
|
+ */
|
|
704
|
+static void dhcp_forget_netdev ( struct reference *ref ) {
|
|
705
|
+ struct dhcp_session *dhcp
|
|
706
|
+ = container_of ( ref, struct dhcp_session, netdev_ref );
|
|
707
|
+
|
|
708
|
+ /* Kill DHCP session immediately */
|
|
709
|
+ dhcp_done ( dhcp, -ENETUNREACH );
|
|
710
|
+}
|
|
711
|
+
|
692
|
712
|
/**
|
693
|
713
|
* Initiate DHCP on a network interface
|
694
|
714
|
*
|
|
@@ -714,6 +734,10 @@ struct async_operation * start_dhcp ( struct dhcp_session *dhcp ) {
|
714
|
734
|
goto out;
|
715
|
735
|
}
|
716
|
736
|
|
|
737
|
+ /* Add persistent reference to net device */
|
|
738
|
+ dhcp->netdev_ref.forget = dhcp_forget_netdev;
|
|
739
|
+ ref_add ( &dhcp->netdev_ref, &dhcp->netdev->references );
|
|
740
|
+
|
717
|
741
|
/* Proof of concept: just send a single DHCPDISCOVER */
|
718
|
742
|
dhcp_send_request ( dhcp );
|
719
|
743
|
|