xref: /plan9/sys/src/cmd/cifs/pack.c (revision 671dfc474d1a5bcbeda8be1356d2abfa05b91489)
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