Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <ip.h>
4
#include <thread.h>
5
#include "netbios.h"
6
 
7
void
8
nbnsmessagequestionfree(NbnsMessageQuestion **qp)
9
{
10
	NbnsMessageQuestion *q = *qp;
11
	if (q) {
12
		free(q);
13
		*qp = nil;
14
	}
15
}
16
 
17
void
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
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
39
resourcefree(NbnsMessageResource **rp)
40
{
41
	while (*rp) {
42
		NbnsMessageResource *next = (*rp)->next;
43
		nbnsmessageresourcefree(rp);
44
		*rp = next;
45
	}
46
}
47
 
48
void
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
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 *
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 *
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
108
nbnsmessageaddresource(NbnsMessageResource **rp, NbnsMessageResource *r)
109
{
110
	for (; *rp; rp = &(*rp)->next)
111
		;
112
	*rp = r;
113
}
114
 
115
NbnsMessage *
116
nbnsmessagenew(void)
117
{
118
	return mallocz(sizeof(NbnsMessage), 1);
119
}
120
 
121
static int
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 *
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
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
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