浏览代码

[dhcp] Verify DHCP server source port

Verifying server ID and DHCP transaction ID is insufficient to
differentiate between DHCPACK and ProxyDHCPACK when the DHCP server and
Proxy DHCP server are the same machine.
tags/v0.9.4
Michael Brown 16 年前
父节点
当前提交
6f39dfe6c0
共有 1 个文件被更改,包括 45 次插入16 次删除
  1. 45
    16
      src/net/udp/dhcp.c

+ 45
- 16
src/net/udp/dhcp.c 查看文件

@@ -865,51 +865,76 @@ static void dhcp_rx_proxydhcpack ( struct dhcp_session *dhcp,
865 865
  * Receive new data
866 866
  *
867 867
  * @v xfer 		Data transfer interface
868
- * @v data		Received data
869
- * @v len		Length of received data
868
+ * @v iobuf		I/O buffer
869
+ * @v meta		Transfer metadata
870 870
  * @ret rc		Return status code
871 871
  */
872
-static int dhcp_deliver_raw ( struct xfer_interface *xfer,
873
-			      const void *data, size_t len ) {
872
+static int dhcp_deliver_iob ( struct xfer_interface *xfer,
873
+			      struct io_buffer *iobuf,
874
+			      struct xfer_metadata *meta ) {
874 875
 	struct dhcp_session *dhcp =
875 876
 		container_of ( xfer, struct dhcp_session, xfer );
877
+	struct sockaddr_tcpip *st_src;
878
+	unsigned int src_port;
876 879
 	struct dhcp_settings *dhcpset;
877 880
 	struct dhcphdr *dhcphdr;
878 881
 	uint8_t msgtype = 0;
882
+	int rc = 0;
883
+
884
+	/* Sanity checks */
885
+	if ( ! meta ) {
886
+		DBGC ( dhcp, "DHCP %p received packet without metadata\n",
887
+		       dhcp );
888
+		rc = -EINVAL;
889
+		goto err_no_meta;
890
+	}
891
+	if ( ! meta->src ) {
892
+		DBGC ( dhcp, "DHCP %p received packet without source port\n",
893
+		       dhcp );
894
+		rc = -EINVAL;
895
+		goto err_no_src;
896
+	}
897
+	st_src = ( struct sockaddr_tcpip * ) meta->src;
898
+	src_port = st_src->st_port;
879 899
 
880 900
 	/* Convert packet into a DHCP settings block */
881
-	dhcpset = dhcpset_create ( data, len );
901
+	dhcpset = dhcpset_create ( iobuf->data, iob_len ( iobuf ) );
882 902
 	if ( ! dhcpset ) {
883 903
 		DBGC ( dhcp, "DHCP %p could not store DHCP packet\n", dhcp );
884
-		return -ENOMEM;
904
+		rc = -ENOMEM;
905
+		goto err_dhcpset_create;
885 906
 	}
886 907
 	dhcphdr = dhcpset->dhcppkt.dhcphdr;
887 908
 
888 909
 	/* Identify message type */
889 910
 	dhcppkt_fetch ( &dhcpset->dhcppkt, DHCP_MESSAGE_TYPE, &msgtype,
890 911
 			sizeof ( msgtype ) );
891
-	DBGC ( dhcp, "DHCP %p received %s %p\n",
892
-	       dhcp, dhcp_msgtype_name ( msgtype ), dhcpset );
912
+	DBGC ( dhcp, "DHCP %p received %s %p from port %d\n", dhcp,
913
+	       dhcp_msgtype_name ( msgtype ), dhcpset, ntohs ( src_port ) );
893 914
 
894 915
 	/* Check for matching transaction ID */
895 916
 	if ( dhcphdr->xid != dhcp_xid ( dhcp->netdev ) ) {
896 917
 		DBGC ( dhcp, "DHCP %p received %s %p has bad transaction ID\n",
897 918
 		       dhcp, dhcp_msgtype_name ( msgtype ), dhcpset );
898
-		goto out;
919
+		rc = -EINVAL;
920
+		goto err_xid;
899 921
 	};
900 922
 
901 923
 	/* Handle packet based on current state */
902 924
 	switch ( dhcp->state ) {
903 925
 	case DHCP_STATE_DISCOVER:
904
-		if ( msgtype == DHCPOFFER )
926
+		if ( ( msgtype == DHCPOFFER ) &&
927
+		     ( src_port == htons ( BOOTPS_PORT ) ) )
905 928
 			dhcp_rx_dhcpoffer ( dhcp, dhcpset );
906 929
 		break;
907 930
 	case DHCP_STATE_REQUEST:
908
-		if ( msgtype == DHCPACK )
931
+		if ( ( msgtype == DHCPACK ) &&
932
+		     ( src_port == htons ( BOOTPS_PORT ) ) )
909 933
 			dhcp_rx_dhcpack ( dhcp, dhcpset );
910 934
 		break;
911 935
 	case DHCP_STATE_PROXYREQUEST:
912
-		if ( msgtype == DHCPACK )
936
+		if ( ( msgtype == DHCPACK ) &&
937
+		     ( src_port == htons ( PROXYDHCP_PORT ) ) )
913 938
 			dhcp_rx_proxydhcpack ( dhcp, dhcpset );
914 939
 		break;
915 940
 	default:
@@ -917,9 +942,13 @@ static int dhcp_deliver_raw ( struct xfer_interface *xfer,
917 942
 		break;
918 943
 	}
919 944
 
920
- out:
945
+ err_xid:
921 946
 	dhcpset_put ( dhcpset );
922
-	return 0;
947
+ err_dhcpset_create:
948
+ err_no_src:
949
+ err_no_meta:
950
+	free_iob ( iobuf );
951
+	return rc;
923 952
 }
924 953
 
925 954
 /** DHCP data transfer interface operations */
@@ -928,8 +957,8 @@ static struct xfer_interface_operations dhcp_xfer_operations = {
928 957
 	.vredirect	= xfer_vopen,
929 958
 	.window		= unlimited_xfer_window,
930 959
 	.alloc_iob	= default_xfer_alloc_iob,
931
-	.deliver_iob	= xfer_deliver_as_raw,
932
-	.deliver_raw	= dhcp_deliver_raw,
960
+	.deliver_iob	= dhcp_deliver_iob,
961
+	.deliver_raw	= xfer_deliver_as_iob,
933 962
 };
934 963
 
935 964
 /**

正在加载...
取消
保存