1 /* packet packing and unpacking */ 2 #include <u.h> 3 #include <libc.h> 4 #include <ctype.h> 5 #include "cifs.h" 6 7 void * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 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 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 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 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 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 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 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 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 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 374 g8(Pkt *p) 375 { 376 if(p->pos + 1 > p->eop) 377 return 0; 378 return (uint)*p->pos++; 379 } 380 381 long 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 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 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 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