diff options
Diffstat (limited to 'src/vpn/gnunet-dns-parser.c')
-rw-r--r-- | src/vpn/gnunet-dns-parser.c | 271 |
1 files changed, 143 insertions, 128 deletions
diff --git a/src/vpn/gnunet-dns-parser.c b/src/vpn/gnunet-dns-parser.c index e26638141..70551af52 100644 --- a/src/vpn/gnunet-dns-parser.c +++ b/src/vpn/gnunet-dns-parser.c | |||
@@ -11,29 +11,33 @@ | |||
11 | * @returns The offset of the first unparsed byte (the byte right behind the name) | 11 | * @returns The offset of the first unparsed byte (the byte right behind the name) |
12 | */ | 12 | */ |
13 | static unsigned int | 13 | static unsigned int |
14 | parse_dns_name(char* d, const unsigned char* src, unsigned short idx) {/*{{{*/ | 14 | parse_dns_name (char *d, const unsigned char *src, unsigned short idx) |
15 | char* dest = d; | 15 | { /*{{{ */ |
16 | 16 | char *dest = d; | |
17 | int len = src[idx++]; | 17 | |
18 | while (len != 0) | 18 | int len = src[idx++]; |
19 | { | 19 | |
20 | if (len & 0xC0) | 20 | while (len != 0) |
21 | { /* Compressed name, offset in this and the next octet */ | 21 | { |
22 | unsigned short offset = ((len & 0x3F) << 8) | src[idx++]; | 22 | if (len & 0xC0) |
23 | parse_dns_name(dest, src, offset - 12); /* 12 for the Header of the DNS-Packet, idx starts at 0 which is 12 bytes from the start of the packet */ | 23 | { /* Compressed name, offset in this and the next octet */ |
24 | return idx; | 24 | unsigned short offset = ((len & 0x3F) << 8) | src[idx++]; |
25 | } | 25 | |
26 | memcpy(dest, src+idx, len); | 26 | parse_dns_name (dest, src, offset - 12); /* 12 for the Header of the DNS-Packet, idx starts at 0 which is 12 bytes from the start of the packet */ |
27 | idx += len; | 27 | return idx; |
28 | dest += len; | 28 | } |
29 | *dest = '.'; | 29 | memcpy (dest, src + idx, len); |
30 | dest++; | 30 | idx += len; |
31 | len = src[idx++]; | 31 | dest += len; |
32 | }; | 32 | *dest = '.'; |
33 | *dest = 0; | 33 | dest++; |
34 | 34 | len = src[idx++]; | |
35 | return idx; | 35 | }; |
36 | *dest = 0; | ||
37 | |||
38 | return idx; | ||
36 | } | 39 | } |
40 | |||
37 | /*}}}*/ | 41 | /*}}}*/ |
38 | 42 | ||
39 | /** | 43 | /** |
@@ -46,116 +50,127 @@ parse_dns_name(char* d, const unsigned char* src, unsigned short idx) {/*{{{*/ | |||
46 | * @returns The offset of the first unparsed byte (the byte right behind the last record) | 50 | * @returns The offset of the first unparsed byte (the byte right behind the last record) |
47 | */ | 51 | */ |
48 | static unsigned short | 52 | static unsigned short |
49 | parse_dns_record(unsigned char* data, /*{{{*/ | 53 | parse_dns_record (unsigned char *data, /*{{{ */ |
50 | struct dns_record** dst, | 54 | struct dns_record **dst, |
51 | unsigned short count, | 55 | unsigned short count, unsigned short idx) |
52 | unsigned short idx) { | 56 | { |
53 | int i; | 57 | int i; |
54 | unsigned short _idx; | 58 | unsigned short _idx; |
55 | for (i = 0; i < count; i++) { | 59 | |
56 | dst[i] = GNUNET_malloc(sizeof(struct dns_record)); | 60 | for (i = 0; i < count; i++) |
57 | dst[i]->name = alloca(255); // see RFC1035, no name can be longer than this. | 61 | { |
58 | char* name = dst[i]->name; | 62 | dst[i] = GNUNET_malloc (sizeof (struct dns_record)); |
59 | 63 | dst[i]->name = alloca (255); // see RFC1035, no name can be longer than this. | |
60 | _idx = parse_dns_name(name, data, idx); | 64 | char *name = dst[i]->name; |
61 | dst[i]->namelen = _idx - idx; | 65 | |
62 | 66 | _idx = parse_dns_name (name, data, idx); | |
63 | dst[i]->name = GNUNET_malloc(dst[i]->namelen); | 67 | dst[i]->namelen = _idx - idx; |
64 | memcpy(dst[i]->name, name, dst[i]->namelen); | 68 | |
65 | 69 | dst[i]->name = GNUNET_malloc (dst[i]->namelen); | |
66 | idx = _idx; | 70 | memcpy (dst[i]->name, name, dst[i]->namelen); |
67 | 71 | ||
68 | dst[i]->type = *((unsigned short*)(data+idx)); | 72 | idx = _idx; |
69 | idx += 2; | 73 | |
70 | dst[i]->class = *((unsigned short*)(data+idx)); | 74 | dst[i]->type = *((unsigned short *) (data + idx)); |
71 | idx += 2; | 75 | idx += 2; |
72 | dst[i]->ttl = *((unsigned int*)(data+idx)); | 76 | dst[i]->class = *((unsigned short *) (data + idx)); |
73 | idx += 4; | 77 | idx += 2; |
74 | dst[i]->data_len = *((unsigned short*)(data+idx)); | 78 | dst[i]->ttl = *((unsigned int *) (data + idx)); |
75 | idx += 2; | 79 | idx += 4; |
76 | dst[i]->data = GNUNET_malloc(ntohs(dst[i]->data_len)); | 80 | dst[i]->data_len = *((unsigned short *) (data + idx)); |
77 | memcpy(dst[i]->data, data+idx, ntohs(dst[i]->data_len)); | 81 | idx += 2; |
78 | idx += ntohs(dst[i]->data_len); | 82 | dst[i]->data = GNUNET_malloc (ntohs (dst[i]->data_len)); |
79 | } | 83 | memcpy (dst[i]->data, data + idx, ntohs (dst[i]->data_len)); |
80 | return idx; | 84 | idx += ntohs (dst[i]->data_len); |
81 | }/*}}}*/ | 85 | } |
86 | return idx; | ||
87 | } /*}}} */ | ||
82 | 88 | ||
83 | /** | 89 | /** |
84 | * Parse a raw DNS-Packet into an usable struct | 90 | * Parse a raw DNS-Packet into an usable struct |
85 | */ | 91 | */ |
86 | struct dns_pkt_parsed* | 92 | struct dns_pkt_parsed * |
87 | parse_dns_packet(struct dns_pkt* pkt) {/*{{{*/ | 93 | parse_dns_packet (struct dns_pkt *pkt) |
88 | struct dns_pkt_parsed* ppkt = GNUNET_malloc(sizeof(struct dns_pkt_parsed)); | 94 | { /*{{{ */ |
89 | memcpy(&ppkt->s, &pkt->s, sizeof pkt->s); | 95 | struct dns_pkt_parsed *ppkt = GNUNET_malloc (sizeof (struct dns_pkt_parsed)); |
90 | 96 | ||
91 | unsigned short qdcount = ntohs(ppkt->s.qdcount); | 97 | memcpy (&ppkt->s, &pkt->s, sizeof pkt->s); |
92 | unsigned short ancount = ntohs(ppkt->s.ancount); | 98 | |
93 | unsigned short nscount = ntohs(ppkt->s.nscount); | 99 | unsigned short qdcount = ntohs (ppkt->s.qdcount); |
94 | unsigned short arcount = ntohs(ppkt->s.arcount); | 100 | unsigned short ancount = ntohs (ppkt->s.ancount); |
95 | 101 | unsigned short nscount = ntohs (ppkt->s.nscount); | |
96 | ppkt->queries = GNUNET_malloc(qdcount*sizeof(struct dns_query*)); | 102 | unsigned short arcount = ntohs (ppkt->s.arcount); |
97 | ppkt->answers = GNUNET_malloc(ancount*sizeof(struct dns_record*)); | 103 | |
98 | ppkt->nameservers = GNUNET_malloc(nscount*sizeof(struct dns_record*)); | 104 | ppkt->queries = GNUNET_malloc (qdcount * sizeof (struct dns_query *)); |
99 | ppkt->additional = GNUNET_malloc(arcount*sizeof(struct dns_record*)); | 105 | ppkt->answers = GNUNET_malloc (ancount * sizeof (struct dns_record *)); |
100 | 106 | ppkt->nameservers = GNUNET_malloc (nscount * sizeof (struct dns_record *)); | |
101 | unsigned short idx = 0, _idx; /* This keeps track how far we have parsed the data */ | 107 | ppkt->additional = GNUNET_malloc (arcount * sizeof (struct dns_record *)); |
102 | 108 | ||
103 | /* Parse the Query */ | 109 | unsigned short idx = 0, _idx; /* This keeps track how far we have parsed the data */ |
104 | int i; | 110 | |
105 | for (i = 0; i < qdcount; i++) | 111 | /* Parse the Query */ |
106 | { /*{{{*/ | 112 | int i; |
107 | ppkt->queries[i] = GNUNET_malloc(sizeof(struct dns_query)); | 113 | |
108 | char* name = alloca(255); /* see RFC1035, it can't be more than this. */ | 114 | for (i = 0; i < qdcount; i++) |
109 | 115 | { /*{{{ */ | |
110 | _idx = parse_dns_name(name, pkt->data, idx); | 116 | ppkt->queries[i] = GNUNET_malloc (sizeof (struct dns_query)); |
111 | ppkt->queries[i]->namelen = _idx - idx; | 117 | char *name = alloca (255); /* see RFC1035, it can't be more than this. */ |
112 | idx = _idx; | 118 | |
113 | 119 | _idx = parse_dns_name (name, pkt->data, idx); | |
114 | ppkt->queries[i]->name = GNUNET_malloc(ppkt->queries[i]->namelen); | 120 | ppkt->queries[i]->namelen = _idx - idx; |
115 | memcpy(ppkt->queries[i]->name, name, ppkt->queries[i]->namelen); | 121 | idx = _idx; |
116 | 122 | ||
117 | ppkt->queries[i]->qtype = *((unsigned short*)(pkt->data+idx)); | 123 | ppkt->queries[i]->name = GNUNET_malloc (ppkt->queries[i]->namelen); |
118 | idx += 2; | 124 | memcpy (ppkt->queries[i]->name, name, ppkt->queries[i]->namelen); |
119 | ppkt->queries[i]->qclass = *((unsigned short*)(pkt->data+idx)); | 125 | |
120 | idx += 2; | 126 | ppkt->queries[i]->qtype = *((unsigned short *) (pkt->data + idx)); |
121 | } | 127 | idx += 2; |
122 | /*}}}*/ | 128 | ppkt->queries[i]->qclass = *((unsigned short *) (pkt->data + idx)); |
123 | idx = parse_dns_record(pkt->data, ppkt->answers, ancount, idx); | 129 | idx += 2; |
124 | idx = parse_dns_record(pkt->data, ppkt->nameservers, nscount, idx); | 130 | } |
125 | idx = parse_dns_record(pkt->data, ppkt->additional, arcount, idx); | 131 | /*}}} */ |
126 | return ppkt; | 132 | idx = parse_dns_record (pkt->data, ppkt->answers, ancount, idx); |
127 | }/*}}}*/ | 133 | idx = parse_dns_record (pkt->data, ppkt->nameservers, nscount, idx); |
134 | idx = parse_dns_record (pkt->data, ppkt->additional, arcount, idx); | ||
135 | return ppkt; | ||
136 | } /*}}} */ | ||
128 | 137 | ||
129 | void | 138 | void |
130 | free_parsed_dns_packet(struct dns_pkt_parsed* ppkt) { | 139 | free_parsed_dns_packet (struct dns_pkt_parsed *ppkt) |
131 | unsigned short qdcount = ntohs(ppkt->s.qdcount); | 140 | { |
132 | unsigned short ancount = ntohs(ppkt->s.ancount); | 141 | unsigned short qdcount = ntohs (ppkt->s.qdcount); |
133 | unsigned short nscount = ntohs(ppkt->s.nscount); | 142 | unsigned short ancount = ntohs (ppkt->s.ancount); |
134 | unsigned short arcount = ntohs(ppkt->s.arcount); | 143 | unsigned short nscount = ntohs (ppkt->s.nscount); |
135 | 144 | unsigned short arcount = ntohs (ppkt->s.arcount); | |
136 | int i; | 145 | |
137 | for (i = 0; i < qdcount; i++) { | 146 | int i; |
138 | GNUNET_free(ppkt->queries[i]->name); | 147 | |
139 | GNUNET_free(ppkt->queries[i]); | 148 | for (i = 0; i < qdcount; i++) |
140 | } | 149 | { |
141 | GNUNET_free(ppkt->queries); | 150 | GNUNET_free (ppkt->queries[i]->name); |
142 | for (i = 0; i < ancount; i++) { | 151 | GNUNET_free (ppkt->queries[i]); |
143 | GNUNET_free(ppkt->answers[i]->name); | 152 | } |
144 | GNUNET_free(ppkt->answers[i]->data); | 153 | GNUNET_free (ppkt->queries); |
145 | GNUNET_free(ppkt->answers[i]); | 154 | for (i = 0; i < ancount; i++) |
146 | } | 155 | { |
147 | GNUNET_free(ppkt->answers); | 156 | GNUNET_free (ppkt->answers[i]->name); |
148 | for (i = 0; i < nscount; i++) { | 157 | GNUNET_free (ppkt->answers[i]->data); |
149 | GNUNET_free(ppkt->nameservers[i]->name); | 158 | GNUNET_free (ppkt->answers[i]); |
150 | GNUNET_free(ppkt->nameservers[i]->data); | 159 | } |
151 | GNUNET_free(ppkt->nameservers[i]); | 160 | GNUNET_free (ppkt->answers); |
152 | } | 161 | for (i = 0; i < nscount; i++) |
153 | GNUNET_free(ppkt->nameservers); | 162 | { |
154 | for (i = 0; i < arcount; i++) { | 163 | GNUNET_free (ppkt->nameservers[i]->name); |
155 | GNUNET_free(ppkt->additional[i]->name); | 164 | GNUNET_free (ppkt->nameservers[i]->data); |
156 | GNUNET_free(ppkt->additional[i]->data); | 165 | GNUNET_free (ppkt->nameservers[i]); |
157 | GNUNET_free(ppkt->additional[i]); | 166 | } |
158 | } | 167 | GNUNET_free (ppkt->nameservers); |
159 | GNUNET_free(ppkt->additional); | 168 | for (i = 0; i < arcount; i++) |
160 | GNUNET_free(ppkt); | 169 | { |
170 | GNUNET_free (ppkt->additional[i]->name); | ||
171 | GNUNET_free (ppkt->additional[i]->data); | ||
172 | GNUNET_free (ppkt->additional[i]); | ||
173 | } | ||
174 | GNUNET_free (ppkt->additional); | ||
175 | GNUNET_free (ppkt); | ||
161 | } | 176 | } |