1 /* 2 * netbios dial, read, write 3 */ 4 5 #include <u.h> 6 #include <libc.h> 7 #include <ctype.h> 8 #include <fcall.h> 9 #include <thread.h> 10 #include <9p.h> 11 #include "cifs.h" 12 13 enum { 14 MAXNBPKT = 8096, /* max netbios packet size */ 15 NBquery = 0, /* packet type - query */ 16 17 NBAdapterStatus = 0x21, /* get host interface info */ 18 NBInternet = 1, /* scope for info */ 19 20 NBmessage = 0x00, /* Netbios packet types */ 21 NBrequest = 0x81, 22 NBpositive, 23 NBnegative, 24 NBretarget, 25 NBkeepalive, 26 27 ISgroup = 0x8000, 28 }; 29 30 31 static char *NBerr[] = { 32 [0] "not listening on called name", 33 [1] "not listening for calling name", 34 [2] "called name not present", 35 [3] "insufficient resources", 36 [15] "unspecified error" 37 }; 38 39 40 static ulong 41 GL32(uchar **p) 42 { 43 ulong n; 44 45 n = *(*p)++; 46 n |= *(*p)++ << 8; 47 n |= *(*p)++ << 16; 48 n |= *(*p)++ << 24; 49 return n; 50 } 51 52 static ushort 53 GL16(uchar **p) 54 { 55 ushort n; 56 57 n = *(*p)++; 58 n |= *(*p)++ << 8; 59 return n; 60 } 61 62 void 63 Gmem(uchar **p, void *v, int n) 64 { 65 uchar *str = v; 66 67 while(n--) 68 *str++ = *(*p)++; 69 } 70 71 72 static ulong 73 GB32(uchar **p) 74 { 75 ulong n; 76 77 n = *(*p)++ << 24; 78 n |= *(*p)++ << 16; 79 n |= *(*p)++ << 8; 80 n |= *(*p)++; 81 return n; 82 } 83 84 static ushort 85 GB16(uchar **p) 86 { 87 ushort n; 88 89 n = *(*p)++ << 8; 90 n |= *(*p)++; 91 return n; 92 } 93 94 static uchar 95 G8(uchar **p) 96 { 97 return *(*p)++; 98 } 99 100 static void 101 PB16(uchar **p, uint n) 102 { 103 *(*p)++ = n >> 8; 104 *(*p)++ = n; 105 } 106 107 static void 108 P8(uchar **p, uint n) 109 { 110 *(*p)++ = n; 111 } 112 113 114 static void 115 nbname(uchar **p, char *name, char pad) 116 { 117 char c; 118 int i; 119 int done = 0; 120 121 *(*p)++ = 0x20; 122 for(i = 0; i < 16; i++) { 123 c = pad; 124 if(!done && name[i] == '\0') 125 done = 1; 126 if(!done) 127 c = toupper(name[i]); 128 *(*p)++ = ((uchar)c >> 4) + 'A'; 129 *(*p)++ = (c & 0xf) + 'A'; 130 } 131 *(*p)++ = 0; 132 } 133 134 int 135 calledname(char *host, char *name) 136 { 137 char *addr; 138 uchar buf[1024], *p; 139 static char tmp[20]; 140 int num, flg, svs, j, i, fd, trn; 141 142 trn = (getpid() ^ time(0)) & 0xffff; 143 if((addr = netmkaddr(host, "udp", "137")) == nil) 144 return -1; 145 146 if((fd = dial(addr, "137", 0, 0)) < 0) 147 return -1; 148 p = buf; 149 150 PB16(&p, trn); /* TRNid */ 151 P8(&p, 0); /* flags */ 152 P8(&p, 0x10); /* type */ 153 PB16(&p, 1); /* # questions */ 154 PB16(&p, 0); /* # answers */ 155 PB16(&p, 0); /* # authority RRs */ 156 PB16(&p, 0); /* # Aditional RRs */ 157 nbname(&p, "*", 0); 158 PB16(&p, NBAdapterStatus); 159 PB16(&p, NBInternet); 160 161 if(Debug && strstr(Debug, "dump")) 162 xd(nil, buf, p-buf); 163 164 if(write(fd, buf, p-buf) != p-buf) 165 return -1; 166 167 p = buf; 168 for(i = 0; i < 3; i++){ 169 memset(buf, 0, sizeof(buf)); 170 alarm(NBNSTOUT); 171 read(fd, buf, sizeof(buf)); 172 alarm(0); 173 if(GB16(&p) == trn) 174 break; 175 } 176 close(fd); 177 if(i >= 3) 178 return -1; 179 180 p = buf +56; 181 num = G8(&p); /* number of names */ 182 183 for(i = 0; i < num; i++){ 184 memset(tmp, 0, sizeof(tmp)); 185 Gmem(&p, tmp, 15); 186 svs = G8(&p); 187 flg = GB16(&p); 188 for(j = 14; j >= 0 && tmp[j] == ' '; j--) 189 tmp[j] = 0; 190 if(svs == 0 && !(flg & ISgroup)) 191 strcpy(name, tmp); 192 } 193 return 0; 194 } 195 196 197 int 198 nbtdial(char *addr, char *called, char *sysname) 199 { 200 char redir[20]; 201 uchar *p, *lenp, buf[1024]; 202 int type, len, err, fd, nkeepalive, nretarg; 203 204 nretarg = 0; 205 nkeepalive = 0; 206 Redial: 207 if((addr = netmkaddr(addr, "tcp", "139")) == nil || 208 (fd = dial(addr, 0, 0, 0)) < 0) 209 return -1; 210 211 memset(buf, 0, sizeof(buf)); 212 213 p = buf; 214 P8(&p, NBrequest); /* type */ 215 P8(&p, 0); /* flags */ 216 lenp = p; PB16(&p, 0); /* length placeholder */ 217 nbname(&p, called, ' '); /* remote NetBios name */ 218 nbname(&p, sysname, ' '); /* our machine name */ 219 PB16(&lenp, p-lenp -2); /* length re-write */ 220 221 if(Debug && strstr(Debug, "dump")) 222 xd(nil, buf, p-buf); 223 if(write(fd, buf, p-buf) != p-buf) 224 goto Error; 225 Reread: 226 p = buf; 227 memset(buf, 0, sizeof(buf)); 228 if(readn(fd, buf, 4) < 4) 229 goto Error; 230 231 type = G8(&p); 232 G8(&p); /* flags */ 233 len = GB16(&p); 234 235 if(readn(fd, buf +4, len -4) < len -4) 236 goto Error; 237 238 if(Debug && strstr(Debug, "dump")) 239 xd(nil, buf, len+4); 240 241 switch(type) { 242 case NBpositive: 243 return fd; 244 case NBnegative: 245 if(len < 1) { 246 werrstr("nbdial: bad error pkt"); 247 goto Error; 248 } 249 err = G8(&p); 250 if(err < 0 || err > nelem(NBerr) || NBerr[err] == nil) 251 werrstr("NBT: %d - unknown error", err); 252 else 253 werrstr("NBT: %s", NBerr[err]); 254 255 goto Error; 256 case NBkeepalive: 257 if(++nkeepalive >= 16){ 258 werrstr("nbdial: too many keepalives"); 259 goto Error; 260 } 261 goto Reread; 262 263 case NBretarget: 264 if(++nretarg >= 16) { 265 werrstr("nbdial: too many redirects"); 266 goto Error; 267 } 268 if(len < 4) { 269 werrstr("nbdial: bad redirect pkt"); 270 goto Error; 271 } 272 sprint(redir, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); 273 addr = redir; 274 goto Redial; 275 276 default: 277 werrstr("nbdial: 0x%x - unknown packet in netbios handshake", type); 278 goto Error; 279 } 280 Error: 281 close(fd); 282 return -1; 283 } 284 285 void 286 nbthdr(Pkt *p) 287 { 288 p->pos = p->buf; 289 memset(p->buf, 0xa5, MTU); 290 291 p8(p, NBmessage); /* type */ 292 p8(p, 0); /* flags */ 293 pb16(p, 0); /* length (filled in later) */ 294 } 295 296 int 297 nbtrpc(Pkt *p) 298 { 299 int len, got, type, nkeep; 300 301 len = p->pos - p->buf; 302 303 p->pos = p->buf +2; 304 pb16(p, len - NBHDRLEN); /* length */ 305 306 if(Debug && strstr(Debug, "dump")) 307 xd("tx", p->buf, len); 308 309 alarm(NBRPCTOUT); 310 if(write(p->s->fd, p->buf, len) != len){ 311 werrstr("nbtrpc: write failed - %r"); 312 alarm(0); 313 return -1; 314 } 315 316 nkeep = 0; 317 retry: 318 p->pos = p->buf; 319 memset(p->buf, 0xa5, MTU); 320 321 got = readn(p->s->fd, p->buf, NBHDRLEN); 322 323 if(got < NBHDRLEN){ 324 werrstr("nbtrpc: short read - %r"); 325 alarm(0); 326 return -1; 327 } 328 p->eop = p->buf + got; 329 330 type = g8(p); /* NBT type (session) */ 331 if(type == NBkeepalive){ 332 if(++nkeep > 16) { 333 werrstr("nbtrpc: too many keepalives (%d attempts)", nkeep); 334 alarm(0); 335 return -1; 336 } 337 goto retry; 338 } 339 340 g8(p); /* NBT flags (none) */ 341 342 len = gb16(p); /* NBT payload length */ 343 if((len +NBHDRLEN) > MTU){ 344 werrstr("nbtrpc: packet bigger than MTU, (%d > %d)", len, MTU); 345 alarm(0); 346 return -1; 347 } 348 349 got = readn(p->s->fd, p->buf +NBHDRLEN, len); 350 alarm(0); 351 352 if(Debug && strstr(Debug, "dump")) 353 xd("rx", p->buf, got +NBHDRLEN); 354 355 if(got < 0) 356 return -1; 357 p->eop = p->buf + got +NBHDRLEN; 358 return got+NBHDRLEN; 359 } 360 361 362 void 363 xd(char *str, void *buf, int n) 364 { 365 int fd, flg, flags2, cmd; 366 uint sum; 367 long err; 368 uchar *p, *end; 369 370 if(n == 0) 371 return; 372 373 p = buf; 374 end = (uchar *)buf +n; 375 376 if(Debug && strstr(Debug, "log") != nil){ 377 if((fd = open("pkt.log", ORDWR)) == -1) 378 return; 379 seek(fd, 0, 2); 380 fprint(fd, "%d ", 0); 381 while(p < end) 382 fprint(fd, "%02x ", *p++); 383 fprint(fd, "\n"); 384 close(fd); 385 return; 386 } 387 388 if(!str) 389 goto Raw; 390 391 p = (uchar *)buf + 4; 392 if(GL32(&p) == 0x424d53ff){ 393 buf = (uchar *)buf + 4; 394 n -= 4; 395 } 396 end = (uchar *)buf + n; 397 398 sum = 0; 399 p = buf; 400 while(p < end) 401 sum += *p++; 402 p = buf; 403 404 fprint(2, "%s : len=%ud sum=%d\n", str, n, sum); 405 406 fprint(2, "mag=0x%ulx ", GL32(&p)); 407 fprint(2, "cmd=0x%ux ", cmd = G8(&p)); 408 fprint(2, "err=0x%ulx ", err=GL32(&p)); 409 fprint(2, "flg=0x%02ux ", flg = G8(&p)); 410 fprint(2, "flg2=0x%04ux\n", flags2= GL16(&p)); 411 fprint(2, "dfs=%s\n", (flags2 & FL2_DFS)? "y": "n"); 412 413 fprint(2, "pidl=%ud ", GL16(&p)); 414 fprint(2, "res=%uld ", GL32(&p)); 415 fprint(2, "sid=%ud ", GL16(&p)); 416 fprint(2, "seq=0x%ux ", GL16(&p)); 417 fprint(2, "pad=%ud ", GL16(&p)); 418 419 fprint(2, "tid=%ud ", GL16(&p)); 420 fprint(2, "pid=%ud ", GL16(&p)); 421 fprint(2, "uid=%ud ", GL16(&p)); 422 fprint(2, "mid=%ud\n", GL16(&p)); 423 424 if(cmd == 0x32 && (flg & 0x80) == 0){ /* TRANS 2, TX */ 425 fprint(2, "words=%ud ", G8(&p)); 426 fprint(2, "totparams=%ud ", GL16(&p)); 427 fprint(2, "totdata=%ud ", GL16(&p)); 428 fprint(2, "maxparam=%ud ", GL16(&p)); 429 fprint(2, "maxdata=%ud\n", GL16(&p)); 430 fprint(2, "maxsetup=%ud ", G8(&p)); 431 fprint(2, "reserved=%ud ", G8(&p)); 432 fprint(2, "flags=%ud ", GL16(&p)); 433 fprint(2, "timeout=%uld\n", GL32(&p)); 434 fprint(2, "reserved=%ud ", GL16(&p)); 435 fprint(2, "paramcnt=%ud ", GL16(&p)); 436 fprint(2, "paramoff=%ud ", GL16(&p)); 437 fprint(2, "datacnt=%ud ", GL16(&p)); 438 fprint(2, "dataoff=%ud ", GL16(&p)); 439 fprint(2, "setupcnt=%ud ", G8(&p)); 440 fprint(2, "reserved=%ud\n", G8(&p)); 441 fprint(2, "trans2=0x%02x ", GL16(&p)); 442 fprint(2, "data-words=%d ", G8(&p)); 443 fprint(2, "padding=%d\n", G8(&p)); 444 } 445 if(cmd == 0x32 && (flg & 0x80) == 0x80){ /* TRANS 2, RX */ 446 fprint(2, "words=%ud ", G8(&p)); 447 fprint(2, "totparams=%ud ", GL16(&p)); 448 fprint(2, "totdata=%ud ", GL16(&p)); 449 fprint(2, "reserved=%ud ", GL16(&p)); 450 fprint(2, "paramcnt=%ud\n", GL16(&p)); 451 fprint(2, "paramoff=%ud ", GL16(&p)); 452 fprint(2, "paramdisp=%ud ", GL16(&p)); 453 fprint(2, "datacnt=%ud\n", GL16(&p)); 454 fprint(2, "dataoff=%ud ", GL16(&p)); 455 fprint(2, "datadisp=%ud ", GL16(&p)); 456 fprint(2, "setupcnt=%ud ", G8(&p)); 457 fprint(2, "reserved=%ud\n", G8(&p)); 458 } 459 if(err) 460 if(flags2 & FL2_NT_ERRCODES) 461 fprint(2, "err=%s\n", nterrstr(err)); 462 else 463 fprint(2, "err=%s\n", doserrstr(err)); 464 Raw: 465 fprint(2, "\n"); 466 for(; p < end; p++){ 467 if((p - (uchar *)buf) % 16 == 0) 468 fprint(2, "\n%06lx\t", p - (uchar *)buf); 469 if(isprint((char)*p)) 470 fprint(2, "%c ", (char )*p); 471 else 472 fprint(2, "%02ux ", *p); 473 } 474 fprint(2, "\n"); 475 } 476