netbios.c 8.8 KB

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