|
@@ -79,11 +79,11 @@ static struct profiler ipv4_rx_profiler __profiler = { .name = "ipv4.rx" };
|
79
|
79
|
* @v address IPv4 address
|
80
|
80
|
* @v netmask Subnet mask
|
81
|
81
|
* @v gateway Gateway address (if any)
|
82
|
|
- * @ret miniroute Routing table entry, or NULL
|
|
82
|
+ * @ret rc Return status code
|
83
|
83
|
*/
|
84
|
|
-static struct ipv4_miniroute * __malloc
|
85
|
|
-add_ipv4_miniroute ( struct net_device *netdev, struct in_addr address,
|
86
|
|
- struct in_addr netmask, struct in_addr gateway ) {
|
|
84
|
+static int add_ipv4_miniroute ( struct net_device *netdev,
|
|
85
|
+ struct in_addr address, struct in_addr netmask,
|
|
86
|
+ struct in_addr gateway ) {
|
87
|
87
|
struct ipv4_miniroute *miniroute;
|
88
|
88
|
|
89
|
89
|
DBGC ( netdev, "IPv4 add %s", inet_ntoa ( address ) );
|
|
@@ -96,7 +96,7 @@ add_ipv4_miniroute ( struct net_device *netdev, struct in_addr address,
|
96
|
96
|
miniroute = malloc ( sizeof ( *miniroute ) );
|
97
|
97
|
if ( ! miniroute ) {
|
98
|
98
|
DBGC ( netdev, "IPv4 could not add miniroute\n" );
|
99
|
|
- return NULL;
|
|
99
|
+ return -ENOMEM;
|
100
|
100
|
}
|
101
|
101
|
|
102
|
102
|
/* Record routing information */
|
|
@@ -114,7 +114,7 @@ add_ipv4_miniroute ( struct net_device *netdev, struct in_addr address,
|
114
|
114
|
list_add ( &miniroute->list, &ipv4_miniroutes );
|
115
|
115
|
}
|
116
|
116
|
|
117
|
|
- return miniroute;
|
|
117
|
+ return 0;
|
118
|
118
|
}
|
119
|
119
|
|
120
|
120
|
/**
|
|
@@ -812,33 +812,69 @@ const struct setting gateway_setting __setting ( SETTING_IP, gateway ) = {
|
812
|
812
|
};
|
813
|
813
|
|
814
|
814
|
/**
|
815
|
|
- * Create IPv4 routing table based on configured settings
|
|
815
|
+ * Send gratuitous ARP, if applicable
|
816
|
816
|
*
|
|
817
|
+ * @v netdev Network device
|
|
818
|
+ * @v address IPv4 address
|
|
819
|
+ * @v netmask Subnet mask
|
|
820
|
+ * @v gateway Gateway address (if any)
|
817
|
821
|
* @ret rc Return status code
|
818
|
822
|
*/
|
819
|
|
-static int ipv4_create_routes ( void ) {
|
820
|
|
- struct ipv4_miniroute *miniroute;
|
821
|
|
- struct ipv4_miniroute *tmp;
|
|
823
|
+static int ipv4_gratuitous_arp ( struct net_device *netdev,
|
|
824
|
+ struct in_addr address,
|
|
825
|
+ struct in_addr netmask __unused,
|
|
826
|
+ struct in_addr gateway __unused ) {
|
|
827
|
+ int rc;
|
|
828
|
+
|
|
829
|
+ /* Do nothing if network device already has this IPv4 address */
|
|
830
|
+ if ( ipv4_has_addr ( netdev, address ) )
|
|
831
|
+ return 0;
|
|
832
|
+
|
|
833
|
+ /* Transmit gratuitous ARP */
|
|
834
|
+ DBGC ( netdev, "IPv4 sending gratuitous ARP for %s via %s\n",
|
|
835
|
+ inet_ntoa ( address ), netdev->name );
|
|
836
|
+ if ( ( rc = arp_tx_request ( netdev, &ipv4_protocol, &address,
|
|
837
|
+ &address ) ) != 0 ) {
|
|
838
|
+ DBGC ( netdev, "IPv4 could not transmit gratuitous ARP: %s\n",
|
|
839
|
+ strerror ( rc ) );
|
|
840
|
+ /* Treat failures as non-fatal */
|
|
841
|
+ }
|
|
842
|
+
|
|
843
|
+ return 0;
|
|
844
|
+}
|
|
845
|
+
|
|
846
|
+/**
|
|
847
|
+ * Process IPv4 network device settings
|
|
848
|
+ *
|
|
849
|
+ * @v apply Application method
|
|
850
|
+ * @ret rc Return status code
|
|
851
|
+ */
|
|
852
|
+static int ipv4_settings ( int ( * apply ) ( struct net_device *netdev,
|
|
853
|
+ struct in_addr address,
|
|
854
|
+ struct in_addr netmask,
|
|
855
|
+ struct in_addr gateway ) ) {
|
822
|
856
|
struct net_device *netdev;
|
823
|
857
|
struct settings *settings;
|
824
|
858
|
struct in_addr address = { 0 };
|
825
|
859
|
struct in_addr netmask = { 0 };
|
826
|
860
|
struct in_addr gateway = { 0 };
|
|
861
|
+ int rc;
|
827
|
862
|
|
828
|
|
- /* Delete all existing routes */
|
829
|
|
- list_for_each_entry_safe ( miniroute, tmp, &ipv4_miniroutes, list )
|
830
|
|
- del_ipv4_miniroute ( miniroute );
|
831
|
|
-
|
832
|
|
- /* Create a route for each configured network device */
|
|
863
|
+ /* Process settings for each network device */
|
833
|
864
|
for_each_netdev ( netdev ) {
|
|
865
|
+
|
|
866
|
+ /* Get network device settings */
|
834
|
867
|
settings = netdev_settings ( netdev );
|
|
868
|
+
|
835
|
869
|
/* Get IPv4 address */
|
836
|
870
|
address.s_addr = 0;
|
837
|
871
|
fetch_ipv4_setting ( settings, &ip_setting, &address );
|
838
|
872
|
if ( ! address.s_addr )
|
839
|
873
|
continue;
|
|
874
|
+
|
840
|
875
|
/* Get subnet mask */
|
841
|
876
|
fetch_ipv4_setting ( settings, &netmask_setting, &netmask );
|
|
877
|
+
|
842
|
878
|
/* Calculate default netmask, if necessary */
|
843
|
879
|
if ( ! netmask.s_addr ) {
|
844
|
880
|
if ( IN_IS_CLASSA ( address.s_addr ) ) {
|
|
@@ -849,18 +885,42 @@ static int ipv4_create_routes ( void ) {
|
849
|
885
|
netmask.s_addr = INADDR_NET_CLASSC;
|
850
|
886
|
}
|
851
|
887
|
}
|
|
888
|
+
|
852
|
889
|
/* Get default gateway, if present */
|
853
|
890
|
fetch_ipv4_setting ( settings, &gateway_setting, &gateway );
|
854
|
|
- /* Configure route */
|
855
|
|
- miniroute = add_ipv4_miniroute ( netdev, address,
|
856
|
|
- netmask, gateway );
|
857
|
|
- if ( ! miniroute )
|
858
|
|
- return -ENOMEM;
|
|
891
|
+
|
|
892
|
+ /* Apply settings */
|
|
893
|
+ if ( ( rc = apply ( netdev, address, netmask, gateway ) ) != 0 )
|
|
894
|
+ return rc;
|
859
|
895
|
}
|
860
|
896
|
|
861
|
897
|
return 0;
|
862
|
898
|
}
|
863
|
899
|
|
|
900
|
+/**
|
|
901
|
+ * Create IPv4 routing table based on configured settings
|
|
902
|
+ *
|
|
903
|
+ * @ret rc Return status code
|
|
904
|
+ */
|
|
905
|
+static int ipv4_create_routes ( void ) {
|
|
906
|
+ struct ipv4_miniroute *miniroute;
|
|
907
|
+ struct ipv4_miniroute *tmp;
|
|
908
|
+ int rc;
|
|
909
|
+
|
|
910
|
+ /* Send gratuitous ARPs for any new IPv4 addresses */
|
|
911
|
+ ipv4_settings ( ipv4_gratuitous_arp );
|
|
912
|
+
|
|
913
|
+ /* Delete all existing routes */
|
|
914
|
+ list_for_each_entry_safe ( miniroute, tmp, &ipv4_miniroutes, list )
|
|
915
|
+ del_ipv4_miniroute ( miniroute );
|
|
916
|
+
|
|
917
|
+ /* Create a route for each configured network device */
|
|
918
|
+ if ( ( rc = ipv4_settings ( add_ipv4_miniroute ) ) != 0 )
|
|
919
|
+ return rc;
|
|
920
|
+
|
|
921
|
+ return 0;
|
|
922
|
+}
|
|
923
|
+
|
864
|
924
|
/** IPv4 settings applicator */
|
865
|
925
|
struct settings_applicator ipv4_settings_applicator __settings_applicator = {
|
866
|
926
|
.apply = ipv4_create_routes,
|