netbios.c 9.1 KB

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