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