VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/slirp/libalias/alias_dns.c@ 23462

最後變更 在這個檔案從23462是 23155,由 vboxsync 提交於 16 年 前

NAT: alias_dns doesn't require dtom any more, update of
corresponded mbufs happens on LibAliasIn exits

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 7.6 KB
 
1#ifndef RT_OS_WINDOWS
2# include <netdb.h>
3#endif
4# include <iprt/ctype.h>
5# include <iprt/assert.h>
6# include <slirp.h>
7# include "alias.h"
8# include "alias_local.h"
9# include "alias_mod.h"
10
11#define DNS_CONTROL_PORT_NUMBER 53
12/* see RFC 1035(4.1.1) */
13union dnsmsg_header
14{
15 struct {
16 uint16_t id;
17 uint16_t rd:1;
18 uint16_t tc:1;
19 uint16_t aa:1;
20 uint16_t opcode:4;
21 uint16_t qr:1;
22 uint16_t rcode:4;
23 uint16_t Z:3;
24 uint16_t ra:1;
25 uint16_t qdcount;
26 uint16_t ancount;
27 uint16_t nscount;
28 uint16_t arcount;
29 } X;
30 uint16_t raw[5];
31};
32struct dnsmsg_answer
33{
34 uint16_t name;
35 uint16_t type;
36 uint16_t class;
37 uint16_t ttl[2];
38 uint16_t rdata_len;
39 uint8_t rdata[1]; /*depends on value at rdata_len */
40};
41
42/* see RFC 1035(4.1) */
43static int dns_alias_handler(PNATState pData, int type);
44static void cstr2qstr(char *cstr, char *qstr);
45static void qstr2cstr(char *qstr, char *cstr);
46
47static int
48fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah)
49{
50
51 if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL)
52 return (-1);
53 fprintf(stderr, "NAT:%s: ah(dport: %hd, sport: %hd) oaddr:%R[IP4] aaddr:%R[IP4]\n",
54 __FUNCTION__, ntohs(*ah->dport), ntohs(*ah->sport),
55 &ah->oaddr, &ah->aaddr);
56 if ( (ntohs(*ah->dport) == DNS_CONTROL_PORT_NUMBER
57 || ntohs(*ah->sport) == DNS_CONTROL_PORT_NUMBER)
58 && (ah->oaddr->s_addr == htonl(ntohl(la->special_addr.s_addr)|CTL_DNS)))
59 return (0);
60 return (-1);
61}
62
63static void doanswer(struct libalias *la, union dnsmsg_header *hdr,char *qname, struct ip *pip, struct hostent *h)
64{
65 int i;
66 if (h == NULL)
67 {
68 hdr->X.qr = 1; /*response*/
69 hdr->X.aa = 1;
70 hdr->X.rd = 1;
71 hdr->X.rcode = 3;
72 }
73 else
74 {
75 char *query;
76 char *answers;
77 uint16_t off;
78 char **cstr;
79 char *c;
80 uint16_t packet_len = 0;
81 uint16_t addr_off = (uint16_t)~0;
82
83#if 0
84 /*here is no compressed names+answers + new query*/
85 m_inc(m, h->h_length * sizeof(struct dnsmsg_answer) + strlen(qname) + 2 * sizeof(uint16_t));
86#endif
87 packet_len = (pip->ip_hl << 2) + sizeof(struct udphdr) + sizeof(union dnsmsg_header)
88 + strlen(qname) + 2 * sizeof(uint16_t); /* ip + udp + header + query */
89 query = (char *)&hdr[1];
90
91 strcpy(query, qname);
92 query += strlen(qname);
93 query ++;
94
95 *(uint16_t *)query = htons(1);
96 ((uint16_t *)query)[1] = htons(1);
97 answers = (char *)&((uint16_t *)query)[2];
98
99 off = (char *)&hdr[1] - (char *)hdr;
100 off |= (0x3 << 14);
101 /*add aliases */
102 cstr = h->h_aliases;
103 while(*cstr)
104 {
105 uint16_t len;
106 struct dnsmsg_answer *ans = (struct dnsmsg_answer *)answers;
107 ans->name = htons(off);
108 ans->type = htons(5); /*CNAME*/
109 ans->class = htons(1);
110 *(uint32_t *)ans->ttl = htonl(3600); /* 1h */
111 c = (addr_off == (uint16_t)~0?h->h_name : *cstr);
112 len = strlen(c) + 2;
113 ans->rdata_len = htons(len);
114 ans->rdata[len - 1] = 0;
115 cstr2qstr(c, (char *)ans->rdata);
116 off = (char *)&ans->rdata - (char *)hdr;
117 off |= (0x3 << 14);
118 if (addr_off == (uint16_t)~0)
119 addr_off = off;
120 answers = (char *)&ans[1] + len - 2; /* note: 1 symbol already counted */
121 packet_len += sizeof(struct dnsmsg_answer) + len - 2;
122 hdr->X.ancount++;
123 cstr++;
124 }
125 /*add addresses */
126
127 for(i = 0; i < h->h_length && h->h_addr_list[i] != NULL; ++i)
128 {
129 struct dnsmsg_answer *ans = (struct dnsmsg_answer *)answers;
130
131 ans->name = htons(off);
132 ans->type = htons(1);
133 ans->class = htons(1);
134 *(uint32_t *)ans->ttl = htonl(3600); /* 1h */
135 ans->rdata_len = htons(4); /* IPv4 */
136 *(uint32_t *)ans->rdata = *(uint32_t *)h->h_addr_list[i];
137 answers = (char *)&ans[1] + 2;
138 packet_len += sizeof(struct dnsmsg_answer) + 3;
139 hdr->X.ancount++;
140 }
141 hdr->X.qr = 1; /*response*/
142 hdr->X.aa = 1;
143 hdr->X.rd = 1;
144 hdr->X.ra = 1;
145 hdr->X.rcode = 0;
146 HTONS(hdr->X.ancount);
147 /*don't forget update m_len*/
148 pip->ip_len = htons(packet_len);
149 }
150}
151static int
152protohandler(struct libalias *la, struct ip *pip, struct alias_data *ah)
153{
154 int i;
155 /*Parse dns request */
156 char *qw_qname = NULL;
157 uint16_t *qw_qtype = NULL;
158 uint16_t *qw_qclass = NULL;
159 struct hostent *h = NULL;
160 char *cname[255]; /* ??? */
161
162 struct udphdr *udp = NULL;
163 union dnsmsg_header *hdr = NULL;
164 udp = (struct udphdr *)ip_next(pip);
165 hdr = (union dnsmsg_header *)udp_next(udp);
166
167 if (hdr->X.qr == 1)
168 return 0; /* this is respose*/
169
170 qw_qname = (char *)&hdr[1];
171 Assert((ntohs(hdr->X.qdcount) == 1));
172
173 for (i = 0; i < ntohs(hdr->X.qdcount); ++i)
174 {
175 qw_qtype = (uint16_t *)(qw_qname + strlen(qw_qname) + 1);
176 qw_qclass = &qw_qtype[1];
177 fprintf(stderr, "qname:%s qtype:%hd qclass:%hd\n",
178 qw_qname, ntohs(*qw_qtype), ntohs(*qw_qclass));
179 }
180 qstr2cstr(qw_qname, (char *)cname);
181 h = gethostbyname((char *)cname);
182 fprintf(stderr, "cname:%s\n", cname);
183 doanswer(la, hdr, qw_qname, pip, h);
184 /*we've chenged size and conten of udp, to avoid double csum calcualtion
185 *will assign to zero
186 */
187 udp->uh_sum = 0;
188 udp->uh_ulen = ntohs(htons(pip->ip_len) - (pip->ip_hl << 2));
189 pip->ip_sum = 0;
190 pip->ip_sum = LibAliasInternetChecksum(la, (uint16_t *)pip, pip->ip_hl << 2);
191 return (0);
192}
193/*
194 * qstr is z-string with -dot- replaced with \count to next -dot-
195 * e.g. ya.ru is \02ya\02ru
196 * Note: it's assumed that caller allocates buffer for cstr
197 */
198static void qstr2cstr(char *qname, char *cname)
199{
200 char *q = qname;
201 char *c = cname;
202 while(*q != 0)
203 {
204 if (isalpha(*q) || isdigit(*q))
205 {
206 *c = *q;
207 c++;
208 }
209 else if (c != &cname[0])
210 {
211 *c = '.';
212 c++;
213 }
214 q++;
215 }
216 q = 0;
217}
218/*
219 *
220 */
221static void cstr2qstr(char *cstr, char *qstr)
222{
223 char *c, *pc, *q;
224 c = cstr;
225 q = qstr;
226 while(*c != 0)
227 {
228 /* a the begining or at -dot- position */
229 if (*c == '.' || (c == cstr && q == qstr))
230 {
231 if (c != cstr) c++;
232 pc = strchr(c, '.');
233 *q = pc != NULL ? (pc - c) : strlen(c);
234 q++;
235 continue;
236 }
237 (*q) = (*c); /*direct copy*/
238 q++;
239 c++;
240 }
241 q = 0;
242}
243
244
245int
246dns_alias_load(PNATState pData)
247{
248 return dns_alias_handler(pData, MOD_LOAD);
249}
250
251int
252dns_alias_unload(PNATState pData)
253{
254 return dns_alias_handler(pData, MOD_UNLOAD);
255}
256
257#define handlers pData->dns_module
258static int
259dns_alias_handler(PNATState pData, int type)
260{
261 int error;
262 if (handlers == NULL)
263 handlers = RTMemAllocZ(2 * sizeof(struct proto_handler));
264 handlers[0].pri = 20;
265 handlers[0].dir = IN;
266 handlers[0].proto = UDP;
267 handlers[0].fingerprint = &fingerprint;
268 handlers[0].protohandler = &protohandler;
269 handlers[1].pri = EOH;
270
271 switch (type) {
272 case MOD_LOAD:
273 error = 0;
274 LibAliasAttachHandlers(pData, handlers);
275 break;
276 case MOD_UNLOAD:
277 error = 0;
278 LibAliasDetachHandlers(pData, handlers);
279 RTMemFree(handlers);
280 handlers = NULL;
281 break;
282 default:
283 error = EINVAL;
284 }
285 return (error);
286}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette