diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-01-04 11:18:25 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-01-04 11:18:25 +0000 |
commit | a88b52ae2d2b3e1dadc32178edd3e540a92e3deb (patch) | |
tree | ccd3a0d3715a2628a2d9c729ff05aaa8088ef59a /src | |
parent | 3d7d5697cbc20ded49886a450937512b317f4d83 (diff) | |
download | gnunet-a88b52ae2d2b3e1dadc32178edd3e540a92e3deb.tar.gz gnunet-a88b52ae2d2b3e1dadc32178edd3e540a92e3deb.zip |
-finishing DNS parser, alas untested
Diffstat (limited to 'src')
-rw-r--r-- | src/dns/dnsparser.c | 137 |
1 files changed, 134 insertions, 3 deletions
diff --git a/src/dns/dnsparser.c b/src/dns/dnsparser.c index 8e2818fd8..2cd728f37 100644 --- a/src/dns/dnsparser.c +++ b/src/dns/dnsparser.c | |||
@@ -40,10 +40,102 @@ struct dns_header | |||
40 | uint16_t authority_rcount GNUNET_PACKED; // number of authority-records | 40 | uint16_t authority_rcount GNUNET_PACKED; // number of authority-records |
41 | uint16_t additional_rcount GNUNET_PACKED; // number of additional records | 41 | uint16_t additional_rcount GNUNET_PACKED; // number of additional records |
42 | }; | 42 | }; |
43 | |||
44 | struct query_line | ||
45 | { | ||
46 | uint16_t type GNUNET_PACKED; | ||
47 | uint16_t class GNUNET_PACKED; | ||
48 | }; | ||
49 | |||
50 | struct record_line | ||
51 | { | ||
52 | uint16_t type GNUNET_PACKED; | ||
53 | uint16_t class GNUNET_PACKED; | ||
54 | uint32_t ttl GNUNET_PACKED; | ||
55 | uint16_t data_len GNUNET_PACKED; | ||
56 | }; | ||
57 | |||
43 | GNUNET_NETWORK_STRUCT_END | 58 | GNUNET_NETWORK_STRUCT_END |
44 | 59 | ||
45 | 60 | ||
46 | /** | 61 | /** |
62 | * Parse name inside of a DNS query or record. | ||
63 | * | ||
64 | * @param udp_payload entire UDP payload | ||
65 | * @param udp_payload_length length of udp_payload | ||
66 | * @param off pointer to the offset of the name to parse in the udp_payload (to be | ||
67 | * incremented by the size of the name) | ||
68 | * @return name as 0-terminated C string on success, NULL if the payload is malformed | ||
69 | */ | ||
70 | static char * | ||
71 | parse_name (const char *udp_payload, | ||
72 | size_t udp_payload_length, | ||
73 | size_t *off) | ||
74 | { | ||
75 | const uint8_t *input = (const uint8_t *) udp_payload; | ||
76 | char *ret; | ||
77 | char *tmp; | ||
78 | char *xstr; | ||
79 | uint8_t len; | ||
80 | size_t xoff; | ||
81 | |||
82 | ret = GNUNET_strdup (""); | ||
83 | while (1) | ||
84 | { | ||
85 | if (*off == udp_payload_length) | ||
86 | goto error; | ||
87 | len = input[*off]; | ||
88 | if (0 == len) | ||
89 | break; | ||
90 | if (len < 64) | ||
91 | { | ||
92 | if (*off + 1 + len > udp_payload_length) | ||
93 | goto error; | ||
94 | GNUNET_asprintf (&tmp, | ||
95 | "%s%.*s.", | ||
96 | ret, | ||
97 | (int) len, | ||
98 | &udp_payload[*off + 1]); | ||
99 | GNUNET_free (ret); | ||
100 | ret = tmp; | ||
101 | off += 1 + len; | ||
102 | } | ||
103 | else if ((64 | 128) == (len & (64 | 128)) ) | ||
104 | { | ||
105 | /* pointer to string */ | ||
106 | if (*off + 1 > udp_payload_length) | ||
107 | goto error; | ||
108 | xoff = ((len - (64 | 128)) << 8) + input[*off+1]; | ||
109 | xstr = parse_name (udp_payload, | ||
110 | udp_payload_length, | ||
111 | &xoff); | ||
112 | GNUNET_asprintf (&tmp, | ||
113 | "%s%s.", | ||
114 | ret, | ||
115 | xstr); | ||
116 | GNUNET_free (ret); | ||
117 | GNUNET_free (xstr); | ||
118 | ret = tmp; | ||
119 | off += 2; | ||
120 | /* pointers always terminate names */ | ||
121 | break; | ||
122 | } | ||
123 | else | ||
124 | { | ||
125 | /* neither pointer nor inline string, not supported... */ | ||
126 | goto error; | ||
127 | } | ||
128 | } | ||
129 | if (0 < strlen(ret)) | ||
130 | ret[strlen(ret)-1] = '\0'; /* eat tailing '.' */ | ||
131 | return ret; | ||
132 | error: | ||
133 | GNUNET_free (ret); | ||
134 | return NULL; | ||
135 | } | ||
136 | |||
137 | |||
138 | /** | ||
47 | * Parse a DNS query entry. | 139 | * Parse a DNS query entry. |
48 | * | 140 | * |
49 | * @param udp_payload entire UDP payload | 141 | * @param udp_payload entire UDP payload |
@@ -59,7 +151,22 @@ parse_query (const char *udp_payload, | |||
59 | size_t *off, | 151 | size_t *off, |
60 | struct GNUNET_DNSPARSER_Query *q) | 152 | struct GNUNET_DNSPARSER_Query *q) |
61 | { | 153 | { |
62 | return GNUNET_SYSERR; | 154 | char *name; |
155 | struct query_line ql; | ||
156 | |||
157 | name = parse_name (udp_payload, | ||
158 | udp_payload_length, | ||
159 | off); | ||
160 | if (NULL == name) | ||
161 | return GNUNET_SYSERR; | ||
162 | q->name = name; | ||
163 | if (*off + sizeof (struct query_line) > udp_payload_length) | ||
164 | return GNUNET_SYSERR; | ||
165 | memcpy (&ql, &udp_payload[*off], sizeof (ql)); | ||
166 | *off += sizeof (ql); | ||
167 | q->type = ntohs (ql.type); | ||
168 | q->class = ntohs (ql.class); | ||
169 | return GNUNET_OK; | ||
63 | } | 170 | } |
64 | 171 | ||
65 | 172 | ||
@@ -79,11 +186,35 @@ parse_record (const char *udp_payload, | |||
79 | size_t *off, | 186 | size_t *off, |
80 | struct GNUNET_DNSPARSER_Record *r) | 187 | struct GNUNET_DNSPARSER_Record *r) |
81 | { | 188 | { |
82 | return GNUNET_SYSERR; | 189 | char *name; |
190 | struct record_line rl; | ||
191 | |||
192 | name = parse_name (udp_payload, | ||
193 | udp_payload_length, | ||
194 | off); | ||
195 | if (NULL == name) | ||
196 | return GNUNET_SYSERR; | ||
197 | r->name = name; | ||
198 | if (*off + sizeof (struct record_line) > udp_payload_length) | ||
199 | return GNUNET_SYSERR; | ||
200 | memcpy (&rl, &udp_payload[*off], sizeof (rl)); | ||
201 | *off += sizeof (rl); | ||
202 | r->type = ntohs (rl.type); | ||
203 | r->class = ntohs (rl.class); | ||
204 | r->expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, | ||
205 | ntohl (rl.ttl))); | ||
206 | r->data_len = ntohs (rl.data_len); | ||
207 | if (*off + r->data_len > udp_payload_length) | ||
208 | return GNUNET_SYSERR; | ||
209 | if (0 == r->data_len) | ||
210 | return GNUNET_OK; | ||
211 | r->data = GNUNET_malloc (r->data_len); | ||
212 | memcpy (r->data, &udp_payload[*off], r->data_len); | ||
213 | *off += r->data_len; | ||
214 | return GNUNET_OK; | ||
83 | } | 215 | } |
84 | 216 | ||
85 | 217 | ||
86 | |||
87 | /** | 218 | /** |
88 | * Parse a UDP payload of a DNS packet in to a nice struct for further | 219 | * Parse a UDP payload of a DNS packet in to a nice struct for further |
89 | * processing and manipulation. | 220 | * processing and manipulation. |