Browse Source

[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 17 years ago
parent
commit
7a4e212fe2
1 changed files with 48 additions and 10 deletions
  1. 48
    10
      src/net/dhcppkt.c

+ 48
- 10
src/net/dhcppkt.c View File

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
 /** A dedicated field within a DHCP packet */
59
 /** A dedicated field within a DHCP packet */
36
 struct dhcp_packet_field {
60
 struct dhcp_packet_field {
37
 	/** Settings tag number */
61
 	/** Settings tag number */
40
 	uint16_t offset;
64
 	uint16_t offset;
41
 	/** Length of field */
65
 	/** Length of field */
42
 	uint16_t len;
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
 /** Declare a dedicated field within a DHCP packet
76
 /** Declare a dedicated field within a DHCP packet
46
  *
77
  *
47
  * @v _tag		Settings tag number
78
  * @v _tag		Settings tag number
48
  * @v _field		Field name
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
 		.tag = (_tag),						\
83
 		.tag = (_tag),						\
52
 		.offset = offsetof ( struct dhcphdr, _field ),		\
84
 		.offset = offsetof ( struct dhcphdr, _field ),		\
53
 		.len = sizeof ( ( ( struct dhcphdr * ) 0 )->_field ),	\
85
 		.len = sizeof ( ( ( struct dhcphdr * ) 0 )->_field ),	\
86
+		.used_len = _used_len,					\
54
 	}
87
 	}
55
 
88
 
56
 /** Dedicated fields within a DHCP packet */
89
 /** Dedicated fields within a DHCP packet */
57
 static struct dhcp_packet_field dhcp_packet_fields[] = {
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
 int dhcppkt_fetch ( struct dhcp_packet *dhcppkt, unsigned int tag,
171
 int dhcppkt_fetch ( struct dhcp_packet *dhcppkt, unsigned int tag,
139
 		    void *data, size_t len ) {
172
 		    void *data, size_t len ) {
140
 	struct dhcp_packet_field *field;
173
 	struct dhcp_packet_field *field;
174
+	void *field_data;
175
+	size_t field_len;
141
 	
176
 	
142
 	/* If this is a special field, return it */
177
 	/* If this is a special field, return it */
143
 	if ( ( field = find_dhcp_packet_field ( tag ) ) != NULL ) {
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
 	/* Otherwise, use the generic options block */
189
 	/* Otherwise, use the generic options block */

Loading…
Cancel
Save