xref: /plan9/sys/src/cmd/aquarela/nbnsconv.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
1 #include <u.h>
2 #include <libc.h>
3 #include <ip.h>
4 #include <thread.h>
5 #include "netbios.h"
6 
7 void
nbnsmessagequestionfree(NbnsMessageQuestion ** qp)8 nbnsmessagequestionfree(NbnsMessageQuestion **qp)
9 {
10 	NbnsMessageQuestion *q = *qp;
11 	if (q) {
12 		free(q);
13 		*qp = nil;
14 	}
15 }
16 
17 void
nbnsmessageresourcefree(NbnsMessageResource ** rp)18 nbnsmessageresourcefree(NbnsMessageResource **rp)
19 {
20 	NbnsMessageResource *r = *rp;
21 	if (r) {
22 		free(r->rdata);
23 		free(r);
24 		*rp = nil;
25 	}
26 }
27 
28 static void
questionfree(NbnsMessageQuestion ** qp)29 questionfree(NbnsMessageQuestion **qp)
30 {
31 	while (*qp) {
32 		NbnsMessageQuestion *next = (*qp)->next;
33 		nbnsmessagequestionfree(qp);
34 		*qp = next;
35 	}
36 }
37 
38 static void
resourcefree(NbnsMessageResource ** rp)39 resourcefree(NbnsMessageResource **rp)
40 {
41 	while (*rp) {
42 		NbnsMessageResource *next = (*rp)->next;
43 		nbnsmessageresourcefree(rp);
44 		*rp = next;
45 	}
46 }
47 
48 void
nbnsmessagefree(NbnsMessage ** sp)49 nbnsmessagefree(NbnsMessage **sp)
50 {
51 	NbnsMessage *s = *sp;
52 	if (s) {
53 		questionfree(&s->q);
54 		resourcefree(&s->an);
55 		resourcefree(&s->ns);
56 		resourcefree(&s->ar);
57 		free(s);
58 		*sp = nil;
59 	}
60 }
61 
62 void
nbnsmessageaddquestion(NbnsMessage * s,NbnsMessageQuestion * q)63 nbnsmessageaddquestion(NbnsMessage *s, NbnsMessageQuestion *q)
64 {
65 	NbnsMessageQuestion **qp;
66 	for (qp = &s->q; *qp; qp = &(*qp)->next)
67 		;
68 	*qp = q;
69 }
70 
71 NbnsMessageQuestion *
nbnsmessagequestionnew(NbName name,ushort type,ushort class)72 nbnsmessagequestionnew(NbName name, ushort type, ushort class)
73 {
74 	NbnsMessageQuestion *q;
75 	q = mallocz(sizeof(*q), 1);
76 	if (q == nil)
77 		return nil;
78 	nbnamecpy(q->name, name);
79 	q->type = type;
80 	q->class = class;
81 	return q;
82 }
83 
84 NbnsMessageResource *
nbnsmessageresourcenew(NbName name,ushort type,ushort class,ulong ttl,int rdlength,uchar * rdata)85 nbnsmessageresourcenew(NbName name, ushort type, ushort class, ulong ttl, int rdlength, uchar *rdata)
86 {
87 	NbnsMessageResource *r;
88 	r= mallocz(sizeof(*r), 1);
89 	if (r == nil)
90 		return nil;
91 	nbnamecpy(r->name, name);
92 	r->type = type;
93 	r->class = class;
94 	r->ttl = ttl;
95 	r->rdlength = rdlength;
96 	if (rdlength) {
97 		r->rdata = malloc(rdlength);
98 		if (r->rdata == nil) {
99 			free(r);
100 			return nil;
101 		}
102 		memcpy(r->rdata, rdata, rdlength);
103 	}
104 	return r;
105 }
106 
107 void
nbnsmessageaddresource(NbnsMessageResource ** rp,NbnsMessageResource * r)108 nbnsmessageaddresource(NbnsMessageResource **rp, NbnsMessageResource *r)
109 {
110 	for (; *rp; rp = &(*rp)->next)
111 		;
112 	*rp = r;
113 }
114 
115 NbnsMessage *
nbnsmessagenew(void)116 nbnsmessagenew(void)
117 {
118 	return mallocz(sizeof(NbnsMessage), 1);
119 }
120 
121 static int
resourcedecode(NbnsMessageResource ** headp,int count,uchar * ap,uchar * pp,uchar * ep)122 resourcedecode(NbnsMessageResource **headp, int count, uchar *ap, uchar *pp, uchar *ep)
123 {
124 	uchar *p = pp;
125 	int i;
126 	for (i = 0; i < count; i++) {
127 		int n;
128 		NbnsMessageResource *r, **rp;
129 		r = mallocz(sizeof(NbnsMessageResource), 1);
130 		if (r == nil)
131 			return -1;
132 		for (rp = headp; *rp; rp = &(*rp)->next)
133 			;
134 		*rp = r;
135 		n = nbnamedecode(ap, p, ep, r->name);
136 		if (n == 0)
137 			return -1;
138 		p += n;
139 		if (p + 10 > ep)
140 			return -1;
141 		r->type = nhgets(p); p += 2;
142 		r->class = nhgets(p); p += 2;
143 		r->ttl = nhgetl(p); p += 4;
144 		r->rdlength = nhgets(p); p += 2;
145 //print("rdlength %d\n", r->rdlength);
146 		if (r->rdlength) {
147 			if (p + r->rdlength > ep)
148 				return -1;
149 			r->rdata = malloc(r->rdlength);
150 			if (r == nil)
151 				return -1;
152 			memcpy(r->rdata, p, r->rdlength);
153 			p += r->rdlength;
154 		}
155 	}
156 	return p - pp;
157 }
158 
159 NbnsMessage *
nbnsconvM2S(uchar * ap,int nap)160 nbnsconvM2S(uchar *ap, int nap)
161 {
162 	uchar *p, *ep;
163 	ushort qdcount, ancount, nscount, arcount, ctrl;
164 	int i;
165 	NbnsMessage *s;
166 	int n;
167 
168 	if (nap < 12)
169 		return nil;
170 	p = ap;
171 	ep = ap + nap;
172 	s = nbnsmessagenew();
173 	if (s == nil)
174 		return nil;
175 	s->id = nhgets(p); p+= 2;
176 	ctrl = nhgets(p); p += 2;
177 	qdcount = nhgets(p); p += 2;
178 	ancount = nhgets(p); p += 2;
179 	nscount = nhgets(p); p += 2;
180 	arcount = nhgets(p); p += 2;
181 	s->response = (ctrl & NbnsResponse) != 0;
182 	s->opcode = (ctrl >> NbnsOpShift) & NbnsOpMask;
183 	s->broadcast = (ctrl & NbnsFlagBroadcast) != 0;
184 	s->recursionavailable = (ctrl & NbnsFlagRecursionAvailable) != 0;
185 	s->recursiondesired = (ctrl & NbnsFlagRecursionDesired) != 0;
186 	s->truncation = (ctrl & NbnsFlagTruncation) != 0;
187 	s->authoritativeanswer = (ctrl & NbnsFlagAuthoritativeAnswer) != 0;
188 	s->rcode = s->response ? (ctrl & NbnsRcodeMask) : 0;
189 	for (i = 0; i < qdcount; i++) {
190 		int n;
191 		NbName nbname;
192 		NbnsMessageQuestion *q;
193 		ushort type, class;
194 		n = nbnamedecode(ap, p, ep, nbname);
195 		if (n == 0)
196 			goto fail;
197 		p += n;
198 		if (p + 4 > ep)
199 			goto fail;
200 		type = nhgets(p); p += 2;
201 		class = nhgets(p); p += 2;
202 		q = nbnsmessagequestionnew(nbname, type, class);
203 		if (q == nil)
204 			goto fail;
205 		nbnsmessageaddquestion(s, q);
206 	}
207 	n = resourcedecode(&s->an, ancount, ap, p, ep);
208 	if (n < 0)
209 		goto fail;
210 	p += n;
211 	n = resourcedecode(&s->ns, nscount, ap, p, ep);
212 	if (n < 0)
213 		goto fail;
214 	p += n;
215 	n = resourcedecode(&s->ar, arcount, ap, p, ep);
216 	if (n < 0)
217 		goto fail;
218 //print("arcount %d\n", arcount);
219 	return s;
220 fail:
221 	nbnsmessagefree(&s);
222 	return nil;
223 }
224 
225 static int
resourceencode(NbnsMessageResource * r,uchar * ap,uchar * ep)226 resourceencode(NbnsMessageResource *r, uchar *ap, uchar *ep)
227 {
228 	uchar *p = ap;
229 	for (; r; r = r->next) {
230 		int n = nbnameencode(p, ep, r->name);
231 		if (n == 0)
232 			return -1;
233 		p += n;
234 		if (p + 10 > ep)
235 			return -1;
236 		hnputs(p, r->type); p += 2;
237 		hnputs(p, r->class); p += 2;
238 		hnputl(p, r->ttl); p += 4;
239 		hnputs(p, r->rdlength); p += 2;
240 		if (p + r->rdlength > ep)
241 			return -1;
242 		memcpy(p, r->rdata, r->rdlength);
243 		p += r->rdlength;
244 	}
245 	return p - ap;
246 }
247 
248 int
nbnsconvS2M(NbnsMessage * s,uchar * ap,int nap)249 nbnsconvS2M(NbnsMessage *s, uchar *ap, int nap)
250 {
251 	uchar *p = ap;
252 	uchar *ep = ap + nap;
253 	ushort ctrl;
254 	NbnsMessageQuestion *q;
255 	NbnsMessageResource *r;
256 	int k;
257 	int n;
258 
259 	if (p + 12 > ep)
260 		return 0;
261 	hnputs(p, s->id); p+= 2;
262 	ctrl = (s->opcode & NbnsOpMask) << NbnsOpShift;
263 	if (s->response) {
264 		ctrl |= s->rcode & NbnsRcodeMask;
265 		ctrl |= NbnsResponse;
266 	}
267 	if (s->broadcast)
268 		ctrl |= NbnsFlagBroadcast;
269 	if (s->recursionavailable)
270 		ctrl |= NbnsFlagRecursionAvailable;
271 	if (s->recursiondesired)
272 		ctrl |= NbnsFlagRecursionDesired;
273 	if (s->truncation)
274 		ctrl |= NbnsFlagTruncation;
275 	if (s->authoritativeanswer)
276 		ctrl |= NbnsFlagAuthoritativeAnswer;
277 	hnputs(p, ctrl); p += 2;
278 	for (q = s->q, k = 0; q; k++, q = q->next)
279 		;
280 	hnputs(p, k); p += 2;
281 	for (r = s->an, k = 0; r; k++, r = r->next)
282 		;
283 	hnputs(p, k); p += 2;
284 	for (r = s->ns, k = 0; r; k++, r = r->next)
285 		;
286 	hnputs(p, k); p += 2;
287 	for (r = s->ar, k = 0; r; k++, r = r->next)
288 		;
289 	hnputs(p, k); p += 2;
290 	for (q = s->q; q; q = q->next) {
291 		int n = nbnameencode(p, ep, q->name);
292 		if (n == 0)
293 			return 0;
294 		p += n;
295 		if (p + 4 > ep)
296 			return 0;
297 		hnputs(p, q->type); p += 2;
298 		hnputs(p, q->class); p += 2;
299 	}
300 	n = resourceencode(s->an, p, ep);
301 	if (n < 0)
302 		return 0;
303 	p += n;
304 	n = resourceencode(s->ns, p, ep);
305 	if (n < 0)
306 		return 0;
307 	p += n;
308 	n = resourceencode(s->ar, p, ep);
309 	if (n < 0)
310 		return 0;
311 	p += n;
312 	return p - ap;
313 }
314 
315