/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* packet packing and unpacking */#include <u.h>#include <libc.h>#include <ctype.h>#include "cifs.h" void *pmem(Pkt *p, void *v, int len){ uchar *str = v; void *s = p->pos; if(!len || !v) return s; while(len--) *p->pos++ = *str++; return s;} void *ppath(Pkt *p, char *str){ char c; Rune r; void *s = p->pos; if(!str) return s; if(p->s->caps & CAP_UNICODE){ if(((p->pos - p->buf) % 2) != 0) /* pad to even offset */ p8(p, 0); while(*str){ str += chartorune(&r, str); if(r == L'/') r = L'\\'; pl16(p, r); } pl16(p, 0); } else { while((c = *str++) != 0){ if(c == '/') c = '\\'; *p->pos++ = c; } *p->pos++ = 0; } return s;} void *pstr(Pkt *p, char *str){ void *s = p->pos; Rune r; if(!str) return s; if(p->s->caps & CAP_UNICODE){ if(((p->pos - p->buf) % 2) != 0) p8(p, 0); /* pad to even offset */ while(*str){ str += chartorune(&r, str); pl16(p, r); } pl16(p, 0); } else { while(*str) *p->pos++ = *str++; *p->pos++ = 0; } return s;} void *pascii(Pkt *p, char *str){ void *s = p->pos; while(*str) *p->pos++ = *str++; *p->pos++ = 0; return s;} void *pl64(Pkt *p, uvlong n){ void *s = p->pos; *p->pos++ = n; *p->pos++ = n >> 8; *p->pos++ = n >> 16; *p->pos++ = n >> 24; *p->pos++ = n >> 32; *p->pos++ = n >> 40; *p->pos++ = n >> 48; *p->pos++ = n >> 56; return s;} void *pb32(Pkt *p, uint n){ void *s = p->pos; *p->pos++ = n >> 24; *p->pos++ = n >> 16; *p->pos++ = n >> 8; *p->pos++ = n; return s;} void *pl32(Pkt *p, uint n){ void *s = p->pos; *p->pos++ = n; *p->pos++ = n >> 8; *p->pos++ = n >> 16; *p->pos++ = n >> 24; return s;} void *pb16(Pkt *p, uint n){ void *s = p->pos; *p->pos++ = n >> 8; *p->pos++ = n; return s;} void *pl16(Pkt *p, uint n){ void *s = p->pos; *p->pos++ = n; *p->pos++ = n >> 8; return s;} void *p8(Pkt *p, uint n){ void *s = p->pos; *p->pos++ = n; return s;} /* * Encode a Netbios name */void *pname(Pkt *p, char *name, char pad){ int i, done = 0; char c; void *s = p->pos; *p->pos++ = ' '; for(i = 0; i < 16; i++) { c = pad; if(!done && name[i] == '\0') done = 1; if(!done) c = islower(name[i])? toupper(name[i]): name[i]; *p->pos++ = ((uchar)c >> 4) + 'A'; *p->pos++ = (c & 0xf) + 'A'; } *p->pos++ = '\0'; return s;} void *pvtime(Pkt *p, uvlong n){ void *s = p->pos; n += 11644473600LL; n *= 10000000LL; pl32(p, n); pl32(p, n >> 32); return s;} void *pdatetime(Pkt *p, long utc){ void *s = p->pos; Tm *tm = localtime(utc); int t = tm->hour << 11 | tm->min << 5 | (tm->sec / 2); int d = (tm->year - 80) << 9 | (tm->mon + 1) << 5 | tm->mday; /* * bug in word swapping in Win95 requires this */ if(p->s->caps & CAP_NT_SMBS){ pl16(p, d); pl16(p, t); } else{ pl16(p, t); pl16(p, d); } return s;} voidgmem(Pkt *p, void *v, int n){ uchar *str = v; if(!n || !v) return; while(n-- && p->pos < p->eop) *str++ = *p->pos++;} /* * note len is the length of the source string in * in runes or bytes, in ASCII mode this is also the size * of the output buffer but this is not so in Unicode mode! */voidgstr(Pkt *p, char *str, int n){ int i; Rune r; if(!n || !str) return; if(p->s->caps & CAP_UNICODE){ i = 0; while(*p->pos && n && p->pos < p->eop){ r = gl16(p); i += runetochar(str +i, &r); n -= 2; } *(str + i) = 0; while(*p->pos && p->pos < p->eop) gl16(p); /* * some versions of windows terminate a rune string * with a single nul so we do a dangerous hack... */ if(p->pos[1]) g8(p); else gl16(p); } else { while(*p->pos && n-- && p->pos < p->eop) *str++ = *p->pos++; *str = 0; while(*p->pos++ && p->pos < p->eop) continue; }} voidgascii(Pkt *p, char *str, int n){ if(!n || !str) return; while(*p->pos && n-- && p->pos < p->eop) *str++ = *p->pos++; *str = 0; while(*p->pos++ && p->pos < p->eop) continue;} uvlonggl64(Pkt *p){ uvlong n; if(p->pos + 8 > p->eop) return 0; n = (uvlong)*p->pos++; n |= (uvlong)*p->pos++ << 8; n |= (uvlong)*p->pos++ << 16; n |= (uvlong)*p->pos++ << 24; n |= (uvlong)*p->pos++ << 32; n |= (uvlong)*p->pos++ << 40; n |= (uvlong)*p->pos++ << 48; n |= (uvlong)*p->pos++ << 56; return n;} uvlonggb48(Pkt *p){ uvlong n; if(p->pos + 6 > p->eop) return 0; n = (uvlong)*p->pos++ << 40; n |= (uvlong)*p->pos++ << 24; n |= (uvlong)*p->pos++ << 32; n |= (uvlong)*p->pos++ << 16; n |= (uvlong)*p->pos++ << 8; n |= (uvlong)*p->pos++; return n;} uintgb32(Pkt *p){ uint n; if(p->pos + 4 > p->eop) return 0; n = (uint)*p->pos++ << 24; n |= (uint)*p->pos++ << 16; n |= (uint)*p->pos++ << 8; n |= (uint)*p->pos++; return n;} uintgl32(Pkt *p){ uint n; if(p->pos + 4 > p->eop) return 0; n = (uint)*p->pos++; n |= (uint)*p->pos++ << 8; n |= (uint)*p->pos++ << 16; n |= (uint)*p->pos++ << 24; return n;} uintgb16(Pkt *p){ uint n; if(p->pos + 2 > p->eop) return 0; n = (uint)*p->pos++ << 8; n |= (uint)*p->pos++; return n;} uintgl16(Pkt *p){ uint n; if(p->pos + 2 > p->eop) return 0; n = (uint)*p->pos++; n |= (uint)*p->pos++ << 8; return n;} uintg8(Pkt *p){ if(p->pos + 1 > p->eop) return 0; return (uint)*p->pos++;} longgdatetime(Pkt *p){ Tm tm; uint d, t; if(p->pos + 4 > p->eop) return 0; /* * bug in word swapping in Win95 requires this */ if(p->s->caps & CAP_NT_SMBS){ d = gl16(p); t = gl16(p); }else{ t = gl16(p); d = gl16(p); } tm.year = 80 + (d >> 9); tm.mon = ((d >> 5) & 017) - 1; tm.mday = d & 037; tm.zone[0] = 0; tm.tzoff = p->s->tz; tm.hour = t >> 11; tm.min = (t >> 5) & 63; tm.sec = (t & 31) << 1; return tm2sec(&tm);} longgvtime(Pkt *p){ uvlong vl; if(p->pos + 8 > p->eop) return 0; vl = (uvlong)gl32(p); vl |= (uvlong)gl32(p) << 32; vl /= 10000000LL; vl -= 11644473600LL; return vl;} voidgconv(Pkt *p, int conv, char *str, int n){ int off; uchar *pos; off = gl32(p) & 0xffff; if(off == 0 || p->tdata - conv + off > p->eop){ memset(str, 0, n); return; } pos = p->pos; p->pos = p->tdata - conv + off; gascii(p, str, n); p->pos = pos;} voidgoff(Pkt *p, uchar *base, char *str, int n){ int off; uchar *pos; off = gl16(p); if(off == 0 || base + off > p->eop){ memset(str, 0, n); return; } pos = p->pos; p->pos = base + off; gstr(p, str, n); p->pos = pos;}
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
/* packet packing and unpacking */
#include <u.h>
#include <libc.h>
#include <ctype.h>
#include "cifs.h"
void *
pmem(Pkt *p, void *v, int len)
{
uchar *str = v;
void *s = p->pos;
if(!len || !v)
return s;
while(len--)
*p->pos++ = *str++;
return s;
}
void *
ppath(Pkt *p, char *str)
{
char c;
Rune r;
void *s = p->pos;
if(!str)
return s;
if(p->s->caps & CAP_UNICODE){
if(((p->pos - p->buf) % 2) != 0) /* pad to even offset */
p8(p, 0);
while(*str){
str += chartorune(&r, str);
if(r == L'/')
r = L'\\';
pl16(p, r);
}
pl16(p, 0);
} else {
while((c = *str++) != 0){
if(c == '/')
c = '\\';
*p->pos++ = c;
}
*p->pos++ = 0;
}
return s;
}
void *
pstr(Pkt *p, char *str)
{
void *s = p->pos;
Rune r;
if(!str)
return s;
if(p->s->caps & CAP_UNICODE){
if(((p->pos - p->buf) % 2) != 0)
p8(p, 0); /* pad to even offset */
while(*str){
str += chartorune(&r, str);
pl16(p, r);
}
pl16(p, 0);
} else {
while(*str)
*p->pos++ = *str++;
*p->pos++ = 0;
}
return s;
}
void *
pascii(Pkt *p, char *str)
{
void *s = p->pos;
while(*str)
*p->pos++ = *str++;
*p->pos++ = 0;
return s;
}
void *
pl64(Pkt *p, uvlong n)
{
void *s = p->pos;
*p->pos++ = n;
*p->pos++ = n >> 8;
*p->pos++ = n >> 16;
*p->pos++ = n >> 24;
*p->pos++ = n >> 32;
*p->pos++ = n >> 40;
*p->pos++ = n >> 48;
*p->pos++ = n >> 56;
return s;
}
void *
pb32(Pkt *p, uint n)
{
void *s = p->pos;
*p->pos++ = n >> 24;
*p->pos++ = n >> 16;
*p->pos++ = n >> 8;
*p->pos++ = n;
return s;
}
void *
pl32(Pkt *p, uint n)
{
void *s = p->pos;
*p->pos++ = n;
*p->pos++ = n >> 8;
*p->pos++ = n >> 16;
*p->pos++ = n >> 24;
return s;
}
void *
pb16(Pkt *p, uint n)
{
void *s = p->pos;
*p->pos++ = n >> 8;
*p->pos++ = n;
return s;
}
void *
pl16(Pkt *p, uint n)
{
void *s = p->pos;
*p->pos++ = n;
*p->pos++ = n >> 8;
return s;
}
void *
p8(Pkt *p, uint n)
{
void *s = p->pos;
*p->pos++ = n;
return s;
}
/*
* Encode a Netbios name
*/
void *
pname(Pkt *p, char *name, char pad)
{
int i, done = 0;
char c;
void *s = p->pos;
*p->pos++ = ' ';
for(i = 0; i < 16; i++) {
c = pad;
if(!done && name[i] == '\0')
done = 1;
if(!done)
c = islower(name[i])? toupper(name[i]): name[i];
*p->pos++ = ((uchar)c >> 4) + 'A';
*p->pos++ = (c & 0xf) + 'A';
}
*p->pos++ = '\0';
return s;
}
void *
pvtime(Pkt *p, uvlong n)
{
void *s = p->pos;
n += 11644473600LL;
n *= 10000000LL;
pl32(p, n);
pl32(p, n >> 32);
return s;
}
void *
pdatetime(Pkt *p, long utc)
{
void *s = p->pos;
Tm *tm = localtime(utc);
int t = tm->hour << 11 | tm->min << 5 | (tm->sec / 2);
int d = (tm->year - 80) << 9 | (tm->mon + 1) << 5 | tm->mday;
/*
* bug in word swapping in Win95 requires this
*/
if(p->s->caps & CAP_NT_SMBS){
pl16(p, d);
pl16(p, t);
} else{
pl16(p, t);
pl16(p, d);
}
return s;
}
void
gmem(Pkt *p, void *v, int n)
{
uchar *str = v;
if(!n || !v)
return;
while(n-- && p->pos < p->eop)
*str++ = *p->pos++;
}
/*
* note len is the length of the source string in
* in runes or bytes, in ASCII mode this is also the size
* of the output buffer but this is not so in Unicode mode!
*/
void
gstr(Pkt *p, char *str, int n)
{
int i;
Rune r;
if(!n || !str)
return;
if(p->s->caps & CAP_UNICODE){
i = 0;
while(*p->pos && n && p->pos < p->eop){
r = gl16(p);
i += runetochar(str +i, &r);
n -= 2;
}
*(str + i) = 0;
while(*p->pos && p->pos < p->eop)
gl16(p);
/*
* some versions of windows terminate a rune string
* with a single nul so we do a dangerous hack...
*/
if(p->pos[1])
g8(p);
else
gl16(p);
} else {
while(*p->pos && n-- && p->pos < p->eop)
*str++ = *p->pos++;
*str = 0;
while(*p->pos++ && p->pos < p->eop)
continue;
}
}
void
gascii(Pkt *p, char *str, int n)
{
if(!n || !str)
return;
while(*p->pos && n-- && p->pos < p->eop)
*str++ = *p->pos++;
*str = 0;
while(*p->pos++ && p->pos < p->eop)
continue;
}
uvlong
gl64(Pkt *p)
{
uvlong n;
if(p->pos + 8 > p->eop)
return 0;
n = (uvlong)*p->pos++;
n |= (uvlong)*p->pos++ << 8;
n |= (uvlong)*p->pos++ << 16;
n |= (uvlong)*p->pos++ << 24;
n |= (uvlong)*p->pos++ << 32;
n |= (uvlong)*p->pos++ << 40;
n |= (uvlong)*p->pos++ << 48;
n |= (uvlong)*p->pos++ << 56;
return n;
}
uvlong
gb48(Pkt *p)
{
uvlong n;
if(p->pos + 6 > p->eop)
return 0;
n = (uvlong)*p->pos++ << 40;
n |= (uvlong)*p->pos++ << 24;
n |= (uvlong)*p->pos++ << 32;
n |= (uvlong)*p->pos++ << 16;
n |= (uvlong)*p->pos++ << 8;
n |= (uvlong)*p->pos++;
return n;
}
uint
gb32(Pkt *p)
{
uint n;
if(p->pos + 4 > p->eop)
return 0;
n = (uint)*p->pos++ << 24;
n |= (uint)*p->pos++ << 16;
n |= (uint)*p->pos++ << 8;
n |= (uint)*p->pos++;
return n;
}
uint
gl32(Pkt *p)
{
uint n;
if(p->pos + 4 > p->eop)
return 0;
n = (uint)*p->pos++;
n |= (uint)*p->pos++ << 8;
n |= (uint)*p->pos++ << 16;
n |= (uint)*p->pos++ << 24;
return n;
}
uint
gb16(Pkt *p)
{
uint n;
if(p->pos + 2 > p->eop)
return 0;
n = (uint)*p->pos++ << 8;
n |= (uint)*p->pos++;
return n;
}
uint
gl16(Pkt *p)
{
uint n;
if(p->pos + 2 > p->eop)
return 0;
n = (uint)*p->pos++;
n |= (uint)*p->pos++ << 8;
return n;
}
uint
g8(Pkt *p)
{
if(p->pos + 1 > p->eop)
return 0;
return (uint)*p->pos++;
}
long
gdatetime(Pkt *p)
{
Tm tm;
uint d, t;
if(p->pos + 4 > p->eop)
return 0;
/*
* bug in word swapping in Win95 requires this
*/
if(p->s->caps & CAP_NT_SMBS){
d = gl16(p);
t = gl16(p);
}else{
t = gl16(p);
d = gl16(p);
}
tm.year = 80 + (d >> 9);
tm.mon = ((d >> 5) & 017) - 1;
tm.mday = d & 037;
tm.zone[0] = 0;
tm.tzoff = p->s->tz;
tm.hour = t >> 11;
tm.min = (t >> 5) & 63;
tm.sec = (t & 31) << 1;
return tm2sec(&tm);
}
long
gvtime(Pkt *p)
{
uvlong vl;
if(p->pos + 8 > p->eop)
return 0;
vl = (uvlong)gl32(p);
vl |= (uvlong)gl32(p) << 32;
vl /= 10000000LL;
vl -= 11644473600LL;
return vl;
}
void
gconv(Pkt *p, int conv, char *str, int n)
{
int off;
uchar *pos;
off = gl32(p) & 0xffff;
if(off == 0 || p->tdata - conv + off > p->eop){
memset(str, 0, n);
return;
}
pos = p->pos;
p->pos = p->tdata - conv + off;
gascii(p, str, n);
p->pos = pos;
}
void
goff(Pkt *p, uchar *base, char *str, int n)
{
int off;
uchar *pos;
off = gl16(p);
if(off == 0 || base + off > p->eop){
memset(str, 0, n);
return;
}
pos = p->pos;
p->pos = base + off;
gstr(p, str, n);
p->pos = pos;
}