Ver código fonte

[DHCP] Treat empty fields in DHCP packets as non-existent.

This avoids confusing other code by insisting that we have e.g. a
filename consisting of 128 zero bytes.
tags/v0.9.4
Michael Brown 16 anos atrás
pai
commit
7a4e212fe2
1 arquivos alterados com 48 adições e 10 exclusões
  1. 48
    10
      src/net/dhcppkt.c

+ 48
- 10
src/net/dhcppkt.c Ver arquivo

@@ -32,6 +32,30 @@
32 32
  *
33 33
  */
34 34
 
35
+/**
36
+ * Calculate used length of an IPv4 field within a DHCP packet
37
+ *
38
+ * @v data		Field data
39
+ * @v len		Length of field
40
+ * @ret used		Used length of field
41
+ */
42
+static size_t used_len_ipv4 ( const void *data, size_t len __unused ) {
43
+	const struct in_addr *in = data;
44
+
45
+	return ( in->s_addr ? sizeof ( *in ) : 0 );
46
+}
47
+
48
+/**
49
+ * Calculate used length of a string field within a DHCP packet
50
+ *
51
+ * @v data		Field data
52
+ * @v len		Length of field
53
+ * @ret used		Used length of field
54
+ */
55
+static size_t used_len_string ( const void *data, size_t len ) {
56
+	return strnlen ( data, len );
57
+}
58
+
35 59
 /** A dedicated field within a DHCP packet */
36 60
 struct dhcp_packet_field {
37 61
 	/** Settings tag number */
@@ -40,25 +64,34 @@ struct dhcp_packet_field {
40 64
 	uint16_t offset;
41 65
 	/** Length of field */
42 66
 	uint16_t len;
67
+	/** Calculate used length of field
68
+	 *
69
+	 * @v data	Field data
70
+	 * @v len	Length of field
71
+	 * @ret used	Used length of field
72
+	 */
73
+	size_t ( * used_len ) ( const void *data, size_t len );
43 74
 };
44 75
 
45 76
 /** Declare a dedicated field within a DHCP packet
46 77
  *
47 78
  * @v _tag		Settings tag number
48 79
  * @v _field		Field name
80
+ * @v _used_len		Function to calculate used length of field
49 81
  */
50
-#define DHCP_PACKET_FIELD( _tag, _field ) {				\
82
+#define DHCP_PACKET_FIELD( _tag, _field, _used_len ) {			\
51 83
 		.tag = (_tag),						\
52 84
 		.offset = offsetof ( struct dhcphdr, _field ),		\
53 85
 		.len = sizeof ( ( ( struct dhcphdr * ) 0 )->_field ),	\
86
+		.used_len = _used_len,					\
54 87
 	}
55 88
 
56 89
 /** Dedicated fields within a DHCP packet */
57 90
 static struct dhcp_packet_field dhcp_packet_fields[] = {
58
-	DHCP_PACKET_FIELD ( DHCP_EB_YIADDR, yiaddr ),
59
-	DHCP_PACKET_FIELD ( DHCP_EB_SIADDR, siaddr ),
60
-	DHCP_PACKET_FIELD ( DHCP_TFTP_SERVER_NAME, sname ),
61
-	DHCP_PACKET_FIELD ( DHCP_BOOTFILE_NAME, file ),
91
+	DHCP_PACKET_FIELD ( DHCP_EB_YIADDR, yiaddr, used_len_ipv4 ),
92
+	DHCP_PACKET_FIELD ( DHCP_EB_SIADDR, siaddr, used_len_ipv4 ),
93
+	DHCP_PACKET_FIELD ( DHCP_TFTP_SERVER_NAME, sname, used_len_string ),
94
+	DHCP_PACKET_FIELD ( DHCP_BOOTFILE_NAME, file, used_len_string ),
62 95
 };
63 96
 
64 97
 /**
@@ -138,14 +171,19 @@ int dhcppkt_store ( struct dhcp_packet *dhcppkt, unsigned int tag,
138 171
 int dhcppkt_fetch ( struct dhcp_packet *dhcppkt, unsigned int tag,
139 172
 		    void *data, size_t len ) {
140 173
 	struct dhcp_packet_field *field;
174
+	void *field_data;
175
+	size_t field_len;
141 176
 	
142 177
 	/* If this is a special field, return it */
143 178
 	if ( ( field = find_dhcp_packet_field ( tag ) ) != NULL ) {
144
-		if ( len > field->len )
145
-			len = field->len;
146
-		memcpy ( data,
147
-			 dhcp_packet_field ( dhcppkt->dhcphdr, field ), len );
148
-		return field->len;
179
+		field_data = dhcp_packet_field ( dhcppkt->dhcphdr, field );
180
+		field_len = field->used_len ( field_data, field->len );
181
+		if ( ! field_len )
182
+			return -ENOENT;
183
+		if ( len > field_len )
184
+			len = field_len;
185
+		memcpy ( data, field_data, len );
186
+		return field_len;
149 187
 	}
150 188
 
151 189
 	/* Otherwise, use the generic options block */

Carregando…
Cancelar
Salvar