1 /* packet packing and unpacking */
2 #include <u.h>
3 #include <libc.h>
4 #include <ctype.h>
5 #include "cifs.h"
6
7 void *
pmem(Pkt * p,void * v,int len)8 pmem(Pkt *p, void *v, int len)
9 {
10 uchar *str = v;
11 void *s = p->pos;
12
13 if(!len || !v)
14 return s;
15 while(len--)
16 *p->pos++ = *str++;
17 return s;
18 }
19
20 void *
ppath(Pkt * p,char * str)21 ppath(Pkt *p, char *str)
22 {
23 char c;
24 Rune r;
25 void *s = p->pos;
26
27 if(!str)
28 return s;
29
30 if(p->s->caps & CAP_UNICODE){
31 if(((p->pos - p->buf) % 2) != 0) /* pad to even offset */
32 p8(p, 0);
33 while(*str){
34 str += chartorune(&r, str);
35 if(r == L'/')
36 r = L'\\';
37 pl16(p, r);
38 }
39 pl16(p, 0);
40 } else {
41 while((c = *str++) != 0){
42 if(c == '/')
43 c = '\\';
44 *p->pos++ = c;
45 }
46 *p->pos++ = 0;
47 }
48 return s;
49 }
50
51 void *
pstr(Pkt * p,char * str)52 pstr(Pkt *p, char *str)
53 {
54 void *s = p->pos;
55 Rune r;
56
57 if(!str)
58 return s;
59
60 if(p->s->caps & CAP_UNICODE){
61 if(((p->pos - p->buf) % 2) != 0)
62 p8(p, 0); /* pad to even offset */
63 while(*str){
64 str += chartorune(&r, str);
65 pl16(p, r);
66 }
67 pl16(p, 0);
68 } else {
69 while(*str)
70 *p->pos++ = *str++;
71 *p->pos++ = 0;
72 }
73 return s;
74 }
75
76 void *
pascii(Pkt * p,char * str)77 pascii(Pkt *p, char *str)
78 {
79 void *s = p->pos;
80
81 while(*str)
82 *p->pos++ = *str++;
83 *p->pos++ = 0;
84 return s;
85 }
86
87
88 void *
pl64(Pkt * p,uvlong n)89 pl64(Pkt *p, uvlong n)
90 {
91 void *s = p->pos;
92
93 *p->pos++ = n;
94 *p->pos++ = n >> 8;
95 *p->pos++ = n >> 16;
96 *p->pos++ = n >> 24;
97 *p->pos++ = n >> 32;
98 *p->pos++ = n >> 40;
99 *p->pos++ = n >> 48;
100 *p->pos++ = n >> 56;
101 return s;
102 }
103
104 void *
pb32(Pkt * p,uint n)105 pb32(Pkt *p, uint n)
106 {
107 void *s = p->pos;
108
109 *p->pos++ = n >> 24;
110 *p->pos++ = n >> 16;
111 *p->pos++ = n >> 8;
112 *p->pos++ = n;
113 return s;
114 }
115
116 void *
pl32(Pkt * p,uint n)117 pl32(Pkt *p, uint n)
118 {
119 void *s = p->pos;
120
121 *p->pos++ = n;
122 *p->pos++ = n >> 8;
123 *p->pos++ = n >> 16;
124 *p->pos++ = n >> 24;
125 return s;
126 }
127
128 void *
pb16(Pkt * p,uint n)129 pb16(Pkt *p, uint n)
130 {
131 void *s = p->pos;
132
133 *p->pos++ = n >> 8;
134 *p->pos++ = n;
135 return s;
136 }
137
138 void *
pl16(Pkt * p,uint n)139 pl16(Pkt *p, uint n)
140 {
141 void *s = p->pos;
142
143 *p->pos++ = n;
144 *p->pos++ = n >> 8;
145 return s;
146 }
147
148 void *
p8(Pkt * p,uint n)149 p8(Pkt *p, uint n)
150 {
151 void *s = p->pos;
152
153 *p->pos++ = n;
154 return s;
155 }
156
157 /*
158 * Encode a Netbios name
159 */
160 void *
pname(Pkt * p,char * name,char pad)161 pname(Pkt *p, char *name, char pad)
162 {
163 int i, done = 0;
164 char c;
165 void *s = p->pos;
166
167 *p->pos++ = ' ';
168 for(i = 0; i < 16; i++) {
169 c = pad;
170 if(!done && name[i] == '\0')
171 done = 1;
172 if(!done)
173 c = islower(name[i])? toupper(name[i]): name[i];
174 *p->pos++ = ((uchar)c >> 4) + 'A';
175 *p->pos++ = (c & 0xf) + 'A';
176 }
177 *p->pos++ = '\0';
178 return s;
179 }
180
181 void *
pvtime(Pkt * p,uvlong n)182 pvtime(Pkt *p, uvlong n)
183 {
184 void *s = p->pos;
185
186 n += 11644473600LL;
187 n *= 10000000LL;
188
189 pl32(p, n);
190 pl32(p, n >> 32);
191 return s;
192 }
193
194 void *
pdatetime(Pkt * p,long utc)195 pdatetime(Pkt *p, long utc)
196 {
197 void *s = p->pos;
198 Tm *tm = localtime(utc);
199 int t = tm->hour << 11 | tm->min << 5 | (tm->sec / 2);
200 int d = (tm->year - 80) << 9 | (tm->mon + 1) << 5 | tm->mday;
201
202 /*
203 * bug in word swapping in Win95 requires this
204 */
205 if(p->s->caps & CAP_NT_SMBS){
206 pl16(p, d);
207 pl16(p, t);
208 } else{
209 pl16(p, t);
210 pl16(p, d);
211 }
212 return s;
213 }
214
215
216 void
gmem(Pkt * p,void * v,int n)217 gmem(Pkt *p, void *v, int n)
218 {
219 uchar *str = v;
220
221 if(!n || !v)
222 return;
223 while(n-- && p->pos < p->eop)
224 *str++ = *p->pos++;
225 }
226
227 /*
228 * note len is the length of the source string in
229 * in runes or bytes, in ASCII mode this is also the size
230 * of the output buffer but this is not so in Unicode mode!
231 */
232 void
gstr(Pkt * p,char * str,int n)233 gstr(Pkt *p, char *str, int n)
234 {
235 int i;
236 Rune r;
237
238 if(!n || !str)
239 return;
240
241 if(p->s->caps & CAP_UNICODE){
242 i = 0;
243 while(*p->pos && n && p->pos < p->eop){
244 r = gl16(p);
245 i += runetochar(str +i, &r);
246 n -= 2;
247 }
248 *(str + i) = 0;
249
250 while(*p->pos && p->pos < p->eop)
251 gl16(p);
252 /*
253 * some versions of windows terminate a rune string
254 * with a single nul so we do a dangerous hack...
255 */
256 if(p->pos[1])
257 g8(p);
258 else
259 gl16(p);
260 } else {
261 while(*p->pos && n-- && p->pos < p->eop)
262 *str++ = *p->pos++;
263 *str = 0;
264 while(*p->pos++ && p->pos < p->eop)
265 continue;
266 }
267 }
268
269 void
gascii(Pkt * p,char * str,int n)270 gascii(Pkt *p, char *str, int n)
271 {
272 if(!n || !str)
273 return;
274
275 while(*p->pos && n-- && p->pos < p->eop)
276 *str++ = *p->pos++;
277 *str = 0;
278 while(*p->pos++ && p->pos < p->eop)
279 continue;
280 }
281
282
283 uvlong
gl64(Pkt * p)284 gl64(Pkt *p)
285 {
286 uvlong n;
287
288 if(p->pos + 8 > p->eop)
289 return 0;
290
291 n = (uvlong)*p->pos++;
292 n |= (uvlong)*p->pos++ << 8;
293 n |= (uvlong)*p->pos++ << 16;
294 n |= (uvlong)*p->pos++ << 24;
295 n |= (uvlong)*p->pos++ << 32;
296 n |= (uvlong)*p->pos++ << 40;
297 n |= (uvlong)*p->pos++ << 48;
298 n |= (uvlong)*p->pos++ << 56;
299 return n;
300 }
301
302 uvlong
gb48(Pkt * p)303 gb48(Pkt *p)
304 {
305 uvlong n;
306
307 if(p->pos + 6 > p->eop)
308 return 0;
309
310 n = (uvlong)*p->pos++ << 40;
311 n |= (uvlong)*p->pos++ << 24;
312 n |= (uvlong)*p->pos++ << 32;
313 n |= (uvlong)*p->pos++ << 16;
314 n |= (uvlong)*p->pos++ << 8;
315 n |= (uvlong)*p->pos++;
316 return n;
317 }
318
319 uint
gb32(Pkt * p)320 gb32(Pkt *p)
321 {
322 uint n;
323
324 if(p->pos + 4 > p->eop)
325 return 0;
326
327 n = (uint)*p->pos++ << 24;
328 n |= (uint)*p->pos++ << 16;
329 n |= (uint)*p->pos++ << 8;
330 n |= (uint)*p->pos++;
331 return n;
332 }
333
334 uint
gl32(Pkt * p)335 gl32(Pkt *p)
336 {
337 uint n;
338
339 if(p->pos + 4 > p->eop)
340 return 0;
341
342 n = (uint)*p->pos++;
343 n |= (uint)*p->pos++ << 8;
344 n |= (uint)*p->pos++ << 16;
345 n |= (uint)*p->pos++ << 24;
346 return n;
347 }
348
349 uint
gb16(Pkt * p)350 gb16(Pkt *p)
351 {
352 uint n;
353
354 if(p->pos + 2 > p->eop)
355 return 0;
356 n = (uint)*p->pos++ << 8;
357 n |= (uint)*p->pos++;
358 return n;
359 }
360
361 uint
gl16(Pkt * p)362 gl16(Pkt *p)
363 {
364 uint n;
365
366 if(p->pos + 2 > p->eop)
367 return 0;
368 n = (uint)*p->pos++;
369 n |= (uint)*p->pos++ << 8;
370 return n;
371 }
372
373 uint
g8(Pkt * p)374 g8(Pkt *p)
375 {
376 if(p->pos + 1 > p->eop)
377 return 0;
378 return (uint)*p->pos++;
379 }
380
381 long
gdatetime(Pkt * p)382 gdatetime(Pkt *p)
383 {
384 Tm tm;
385 uint d, t;
386
387 if(p->pos + 4 > p->eop)
388 return 0;
389
390 /*
391 * bug in word swapping in Win95 requires this
392 */
393 if(p->s->caps & CAP_NT_SMBS){
394 d = gl16(p);
395 t = gl16(p);
396 }else{
397 t = gl16(p);
398 d = gl16(p);
399 }
400
401 tm.year = 80 + (d >> 9);
402 tm.mon = ((d >> 5) & 017) - 1;
403 tm.mday = d & 037;
404 tm.zone[0] = 0;
405 tm.tzoff = p->s->tz;
406
407 tm.hour = t >> 11;
408 tm.min = (t >> 5) & 63;
409 tm.sec = (t & 31) << 1;
410
411 return tm2sec(&tm);
412 }
413
414 long
gvtime(Pkt * p)415 gvtime(Pkt *p)
416 {
417 uvlong vl;
418
419 if(p->pos + 8 > p->eop)
420 return 0;
421
422 vl = (uvlong)gl32(p);
423 vl |= (uvlong)gl32(p) << 32;
424
425 vl /= 10000000LL;
426 vl -= 11644473600LL;
427 return vl;
428 }
429
430 void
gconv(Pkt * p,int conv,char * str,int n)431 gconv(Pkt *p, int conv, char *str, int n)
432 {
433 int off;
434 uchar *pos;
435
436 off = gl32(p) & 0xffff;
437 if(off == 0 || p->tdata - conv + off > p->eop){
438 memset(str, 0, n);
439 return;
440 }
441
442 pos = p->pos;
443 p->pos = p->tdata - conv + off;
444 gascii(p, str, n);
445 p->pos = pos;
446 }
447
448 void
goff(Pkt * p,uchar * base,char * str,int n)449 goff(Pkt *p, uchar *base, char *str, int n)
450 {
451 int off;
452 uchar *pos;
453
454 off = gl16(p);
455 if(off == 0 || base + off > p->eop){
456 memset(str, 0, n);
457 return;
458 }
459 pos = p->pos;
460 p->pos = base + off;
461 gstr(p, str, n);
462 p->pos = pos;
463 }
464