trans.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  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. #include <u.h>
  10. #include <libc.h>
  11. #include <fcall.h>
  12. #include <thread.h>
  13. #include <9p.h>
  14. #include "cifs.h"
  15. #include "remsmb.h"
  16. #include "apinums.h"
  17. static Pkt *
  18. thdr(Session *s, Share *sp)
  19. {
  20. Pkt *p;
  21. p = cifshdr(s, sp, SMB_COM_TRANSACTION);
  22. p->tbase = pl16(p, 0); /* 0 Total parameter bytes to be sent, filled later */
  23. pl16(p, 0); /* 2 Total data bytes to be sent, filled later */
  24. pl16(p, 64); /* 4 Max parameter to return */
  25. pl16(p, MTU - T2HDRLEN - 128); /* 6 Max data to return */
  26. pl16(p, 1); /* 8 Max setup count to return */
  27. pl16(p, 0); /* 10 Flags */
  28. pl32(p, 1000); /* 12 Timeout (ms) */
  29. pl16(p, 0); /* 16 Reserved */
  30. pl16(p, 0); /* 18 Parameter count, filled later */
  31. pl16(p, 0); /* 20 Parameter offset, filled later */
  32. pl16(p, 0); /* 22 Data count, filled later */
  33. pl16(p, 0); /* 24 Data offset, filled later */
  34. pl16(p, 0); /* 26 Setup count (in words) */
  35. pbytes(p); /* end of cifs words section */
  36. return p;
  37. }
  38. static void
  39. ptparam(Pkt *p)
  40. {
  41. uint8_t *pos;
  42. if(((p->pos - p->tbase) % 2) != 0)
  43. p8(p, 0); /* pad to word boundry */
  44. pos = p->pos;
  45. p->pos = p->tbase + 20;
  46. pl16(p, pos - p->buf - NBHDRLEN); /* param offset */
  47. p->tparam = p->pos = pos;
  48. }
  49. static void
  50. ptdata(Pkt *p)
  51. {
  52. uint8_t *pos = p->pos;
  53. assert(p->tparam != 0);
  54. if(((p->pos - p->tbase) % 2) != 0)
  55. p8(p, 0); /* pad to word boundry */
  56. p->pos = p->tbase + 0;
  57. pl16(p, pos - p->tparam); /* total param count */
  58. p->pos = p->tbase + 18;
  59. pl16(p, pos - p->tparam); /* param count */
  60. p->pos = p->tbase + 24;
  61. pl16(p, pos - p->buf - NBHDRLEN); /* data offset */
  62. p->tdata = p->pos = pos;
  63. }
  64. static int
  65. trpc(Pkt *p)
  66. {
  67. int got;
  68. uint8_t *pos = p->pos;
  69. assert(p->tbase != 0);
  70. assert(p->tdata != 0);
  71. p->pos = p->tbase + 2;
  72. pl16(p, pos - p->tdata); /* total data count */
  73. p->pos = p->tbase + 22;
  74. pl16(p, pos - p->tdata); /* data count */
  75. p->pos = pos;
  76. if((got = cifsrpc(p)) == -1)
  77. return -1;
  78. gl16(p); /* Total parameter count */
  79. gl16(p); /* Total data count */
  80. gl16(p); /* Reserved */
  81. gl16(p); /* Parameter count in this buffer */
  82. p->tparam = p->buf + NBHDRLEN + gl16(p); /* Parameter offset */
  83. gl16(p); /* Parameter displacement */
  84. gl16(p); /* Data count (this buffer); */
  85. p->tdata = p->buf + NBHDRLEN + gl16(p); /* Data offset */
  86. gl16(p); /* Data displacement */
  87. g8(p); /* Setup count */
  88. g8(p); /* Reserved */
  89. return got;
  90. }
  91. static void
  92. gtparam(Pkt *p)
  93. {
  94. p->pos = p->tparam;
  95. }
  96. static void
  97. gtdata(Pkt *p)
  98. {
  99. p->pos = p->tdata;
  100. }
  101. int
  102. RAPshareenum(Session *s, Share *sp, Share **ent)
  103. {
  104. int ngot = 0, err, navail, nret;
  105. char tmp[1024];
  106. Pkt *p;
  107. Share *q;
  108. p = thdr(s, sp);
  109. pstr(p, "\\PIPE\\LANMAN");
  110. ptparam(p);
  111. pl16(p, API_WShareEnum);
  112. pascii(p, REMSmb_NetShareEnum_P); /* request descriptor */
  113. pascii(p, REMSmb_share_info_0); /* reply descriptor */
  114. pl16(p, 0); /* detail level */
  115. pl16(p, MTU - 200); /* receive buffer length */
  116. ptdata(p);
  117. if(trpc(p) == -1){
  118. free(p);
  119. return -1;
  120. }
  121. gtparam(p);
  122. err = gl16(p); /* error code */
  123. gl16(p); /* rx buffer offset */
  124. nret = gl16(p); /* number of entries returned */
  125. navail = gl16(p); /* number of entries available */
  126. if(err && err != RAP_ERR_MOREINFO){
  127. werrstr("%s", raperrstr(err));
  128. free(p);
  129. return -1;
  130. }
  131. if(ngot == 0){
  132. *ent = emalloc9p(sizeof(Share) * navail);
  133. memset(*ent, 0, sizeof(Share) * navail);
  134. }
  135. q = *ent + ngot;
  136. for (; ngot < navail && nret--; ngot++){
  137. gmem(p, tmp, 13); /* name */
  138. tmp[13] = 0;
  139. q->name = estrdup9p(tmp);
  140. q++;
  141. }
  142. if(ngot < navail)
  143. fprint(2, "%s: %d/%d - share list incomplete\n", argv0, ngot, navail);
  144. free(p);
  145. return ngot;
  146. }
  147. int
  148. RAPshareinfo(Session *s, Share *sp, char *share, Shareinfo2 *si2p)
  149. {
  150. int conv, err;
  151. char tmp[1024];
  152. Pkt *p;
  153. p = thdr(s, sp);
  154. pstr(p, "\\PIPE\\LANMAN");
  155. ptparam(p);
  156. pl16(p, API_WShareGetInfo);
  157. pascii(p, REMSmb_NetShareGetInfo_P); /* request descriptor */
  158. pascii(p, REMSmb_share_info_2); /* reply descriptor */
  159. pascii(p, share);
  160. pl16(p, 1); /* detail level */
  161. pl16(p, MTU - 200); /* receive buffer length */
  162. ptdata(p);
  163. if(trpc(p) == -1){
  164. free(p);
  165. return -1;
  166. }
  167. gtparam(p);
  168. err = gl16(p); /* error code */
  169. conv = gl16(p); /* rx buffer offset */
  170. gl16(p); /* number of entries returned */
  171. gl16(p); /* number of entries available */
  172. if(err){
  173. werrstr("%s", raperrstr(err));
  174. free(p);
  175. return -1;
  176. }
  177. memset(si2p, 0, sizeof(Shareinfo2));
  178. gmem(p, tmp, 13);
  179. tmp[13] = 0;
  180. g8(p); /* padding */
  181. si2p->name = estrdup9p(tmp);
  182. si2p->type = gl16(p);
  183. gconv(p, conv, tmp, sizeof tmp);
  184. si2p->comment = estrdup9p(tmp);
  185. gl16(p); /* comment offset high (unused) */
  186. si2p->perms = gl16(p);
  187. si2p->maxusrs = gl16(p);
  188. si2p->activeusrs = gl16(p);
  189. gconv(p, conv, tmp, sizeof tmp);
  190. si2p->path = estrdup9p(tmp);
  191. gl16(p); /* path offset high (unused) */
  192. gmem(p, tmp, 9);
  193. tmp[9] = 0;
  194. si2p->passwd = estrdup9p(tmp);
  195. free(p);
  196. return 0;
  197. }
  198. /*
  199. * Tried to split sessionenum into two passes, one getting the names
  200. * of the connected workstations and the other collecting the detailed info,
  201. * however API_WSessionGetInfo doesn't seem to work agains win2k3 for infolevel
  202. * ten and infolevel one and two are priviledged calls. This means this code
  203. * will work for small numbers of sessions agains win2k3 and fail for samba 3.0
  204. * as it supports info levels zero and two only.
  205. */
  206. int
  207. RAPsessionenum(Session *s, Share *sp, Sessinfo **sip)
  208. {
  209. int ngot = 0, conv, err, navail, nret;
  210. char tmp[1024];
  211. Pkt *p;
  212. Sessinfo *q;
  213. p = thdr(s, sp);
  214. pstr(p, "\\PIPE\\LANMAN");
  215. ptparam(p);
  216. pl16(p, API_WSessionEnum);
  217. pascii(p, REMSmb_NetSessionEnum_P); /* request descriptor */
  218. pascii(p, REMSmb_session_info_10); /* reply descriptor */
  219. pl16(p, 10); /* detail level */
  220. pl16(p, MTU - 200); /* receive buffer length */
  221. ptdata(p);
  222. if(trpc(p) == -1){
  223. free(p);
  224. return -1;
  225. }
  226. gtparam(p);
  227. err = gl16(p); /* error code */
  228. conv = gl16(p); /* rx buffer offset */
  229. nret = gl16(p); /* number of entries returned */
  230. navail = gl16(p); /* number of entries available */
  231. if(err && err != RAP_ERR_MOREINFO){
  232. werrstr("%s", raperrstr(err));
  233. free(p);
  234. return -1;
  235. }
  236. if(ngot == 0){
  237. *sip = emalloc9p(sizeof(Sessinfo) * navail);
  238. memset(*sip, 0, sizeof(Sessinfo) * navail);
  239. }
  240. q = *sip + ngot;
  241. while(nret-- != 0){
  242. gconv(p, conv, tmp, sizeof tmp);
  243. q->wrkstn = estrdup9p(tmp);
  244. gconv(p, conv, tmp, sizeof tmp);
  245. q->user = estrdup9p(tmp);
  246. q->sesstime = gl32(p);
  247. q->idletime = gl32(p);
  248. ngot++;
  249. q++;
  250. }
  251. if(ngot < navail)
  252. fprint(2, "warning: %d/%d - session list incomplete\n", ngot, navail);
  253. free(p);
  254. return ngot;
  255. }
  256. int
  257. RAPgroupenum(Session *s, Share *sp, Namelist **nlp)
  258. {
  259. int ngot, err, navail, nret;
  260. char tmp[1024];
  261. Pkt *p;
  262. Namelist *q;
  263. ngot = 0;
  264. p = thdr(s, sp);
  265. pstr(p, "\\PIPE\\LANMAN");
  266. ptparam(p);
  267. pl16(p, API_WGroupEnum);
  268. pascii(p, REMSmb_NetGroupEnum_P); /* request descriptor */
  269. pascii(p, REMSmb_group_info_0); /* reply descriptor */
  270. pl16(p, 0); /* detail level */
  271. pl16(p, MTU - 200); /* receive buffer length */
  272. ptdata(p);
  273. if(trpc(p) == -1){
  274. free(p);
  275. return -1;
  276. }
  277. gtparam(p);
  278. err = gl16(p); /* error code */
  279. gl16(p); /* rx buffer offset */
  280. nret = gl16(p); /* number of entries returned */
  281. navail = gl16(p); /* number of entries available */
  282. if(err && err != RAP_ERR_MOREINFO){
  283. werrstr("%s", raperrstr(err));
  284. free(p);
  285. return -1;
  286. }
  287. *nlp = emalloc9p(sizeof(Namelist) * navail);
  288. memset(*nlp, 0, sizeof(Namelist) * navail);
  289. q = *nlp + ngot;
  290. while(ngot < navail && nret--){
  291. gmem(p, tmp, 21);
  292. tmp[21] = 0;
  293. q->name = estrdup9p(tmp);
  294. ngot++;
  295. q++;
  296. if(p->pos >= p->eop) /* Windows seems to lie somtimes */
  297. break;
  298. }
  299. free(p);
  300. return ngot;
  301. }
  302. int
  303. RAPgroupusers(Session *s, Share *sp, char *group, Namelist **nlp)
  304. {
  305. int ngot, err, navail, nret;
  306. char tmp[1024];
  307. Pkt *p;
  308. Namelist *q;
  309. ngot = 0;
  310. p = thdr(s, sp);
  311. pstr(p, "\\PIPE\\LANMAN");
  312. ptparam(p);
  313. pl16(p, API_WGroupGetUsers);
  314. pascii(p, REMSmb_NetGroupGetUsers_P); /* request descriptor */
  315. pascii(p, REMSmb_user_info_0); /* reply descriptor */
  316. pascii(p, group); /* group name for list */
  317. pl16(p, 0); /* detail level */
  318. pl16(p, MTU - 200); /* receive buffer length */
  319. ptdata(p);
  320. if(trpc(p) == -1){
  321. free(p);
  322. return -1;
  323. }
  324. gtparam(p);
  325. err = gl16(p); /* error code */
  326. gl16(p); /* rx buffer offset */
  327. nret = gl16(p); /* number of entries returned */
  328. navail = gl16(p); /* number of entries available */
  329. if(err && err != RAP_ERR_MOREINFO){
  330. werrstr("%s", raperrstr(err));
  331. free(p);
  332. return -1;
  333. }
  334. *nlp = emalloc9p(sizeof(Namelist) * navail);
  335. memset(*nlp, 0, sizeof(Namelist) * navail);
  336. q = *nlp + ngot;
  337. while(ngot < navail && nret--){
  338. gmem(p, tmp, 21);
  339. tmp[21] = 0;
  340. q->name = estrdup9p(tmp);
  341. ngot++;
  342. q++;
  343. if(p->pos >= p->eop) /* Windows seems to lie somtimes */
  344. break;
  345. }
  346. free(p);
  347. return ngot;
  348. }
  349. int
  350. RAPuserenum(Session *s, Share *sp, Namelist **nlp)
  351. {
  352. int ngot, err, navail, nret;
  353. char tmp[1024];
  354. Pkt *p;
  355. Namelist *q;
  356. ngot = 0;
  357. p = thdr(s, sp);
  358. pstr(p, "\\PIPE\\LANMAN");
  359. ptparam(p);
  360. pl16(p, API_WUserEnum);
  361. pascii(p, REMSmb_NetUserEnum_P); /* request descriptor */
  362. pascii(p, REMSmb_user_info_0); /* reply descriptor */
  363. pl16(p, 0); /* detail level */
  364. pl16(p, MTU - 200); /* receive buffer length */
  365. ptdata(p);
  366. if(trpc(p) == -1){
  367. free(p);
  368. return -1;
  369. }
  370. gtparam(p);
  371. err = gl16(p); /* error code */
  372. gl16(p); /* rx buffer offset */
  373. nret = gl16(p); /* number of entries returned */
  374. navail = gl16(p); /* number of entries available */
  375. if(err && err != RAP_ERR_MOREINFO){
  376. werrstr("%s", raperrstr(err));
  377. free(p);
  378. return -1;
  379. }
  380. *nlp = emalloc9p(sizeof(Namelist) * navail);
  381. memset(*nlp, 0, sizeof(Namelist) * navail);
  382. q = *nlp + ngot;
  383. while(ngot < navail && nret--){
  384. gmem(p, tmp, 21);
  385. tmp[21] = 0;
  386. q->name = estrdup9p(tmp);
  387. ngot++;
  388. q++;
  389. if(p->pos >= p->eop) /* Windows seems to lie somtimes */
  390. break;
  391. }
  392. free(p);
  393. return ngot;
  394. }
  395. int
  396. RAPuserenum2(Session *s, Share *sp, Namelist **nlp)
  397. {
  398. int ngot, resume, err, navail, nret;
  399. char tmp[1024];
  400. Pkt *p;
  401. Namelist *q;
  402. ngot = 0;
  403. resume = 0;
  404. more:
  405. p = thdr(s, sp);
  406. pstr(p, "\\PIPE\\LANMAN");
  407. ptparam(p);
  408. pl16(p, API_WUserEnum2);
  409. pascii(p, REMSmb_NetUserEnum2_P); /* request descriptor */
  410. pascii(p, REMSmb_user_info_0); /* reply descriptor */
  411. pl16(p, 0); /* detail level */
  412. pl16(p, MTU - 200); /* receive buffer length */
  413. pl32(p, resume); /* resume key to allow multiple fetches */
  414. ptdata(p);
  415. if(trpc(p) == -1){
  416. free(p);
  417. return -1;
  418. }
  419. gtparam(p);
  420. err = gl16(p); /* error code */
  421. gl16(p); /* rx buffer offset */
  422. resume = gl32(p); /* resume key returned */
  423. nret = gl16(p); /* number of entries returned */
  424. navail = gl16(p); /* number of entries available */
  425. if(err && err != RAP_ERR_MOREINFO){
  426. werrstr("%s", raperrstr(err));
  427. free(p);
  428. return -1;
  429. }
  430. if(ngot == 0){
  431. *nlp = emalloc9p(sizeof(Namelist) * navail);
  432. memset(*nlp, 0, sizeof(Namelist) * navail);
  433. }
  434. q = *nlp + ngot;
  435. while(ngot < navail && nret--){
  436. gmem(p, tmp, 21);
  437. tmp[21] = 0;
  438. q->name = estrdup9p(tmp);
  439. ngot++;
  440. q++;
  441. if(p->pos >= p->eop) /* Windows seems to lie somtimes */
  442. break;
  443. }
  444. free(p);
  445. if(ngot < navail)
  446. goto more;
  447. return ngot;
  448. }
  449. int
  450. RAPuserinfo(Session *s, Share *sp, char *user, Userinfo *uip)
  451. {
  452. int conv, err;
  453. char tmp[1024];
  454. Pkt *p;
  455. p = thdr(s, sp);
  456. pstr(p, "\\PIPE\\LANMAN");
  457. ptparam(p);
  458. pl16(p, API_WUserGetInfo);
  459. pascii(p, REMSmb_NetUserGetInfo_P); /* request descriptor */
  460. pascii(p, REMSmb_user_info_10); /* reply descriptor */
  461. pascii(p, user); /* username */
  462. pl16(p, 10); /* detail level */
  463. pl16(p, MTU - 200); /* receive buffer length */
  464. ptdata(p);
  465. if(trpc(p) == -1){
  466. free(p);
  467. return -1;
  468. }
  469. gtparam(p);
  470. err = gl16(p); /* error code */
  471. conv = gl16(p); /* rx buffer offset */
  472. gl16(p); /* number of entries returned */
  473. gl16(p); /* number of entries available */
  474. if(err && err != RAP_ERR_MOREINFO){
  475. werrstr("%s", raperrstr(err));
  476. free(p);
  477. return -1;
  478. }
  479. gmem(p, tmp, 21);
  480. tmp[21] = 0;
  481. uip->user = estrdup9p(tmp);
  482. g8(p); /* padding */
  483. gconv(p, conv, tmp, sizeof tmp);
  484. uip->comment = estrdup9p(tmp);
  485. gconv(p, conv, tmp, sizeof tmp);
  486. uip->user_comment = estrdup9p(tmp);
  487. gconv(p, conv, tmp, sizeof tmp);
  488. uip->fullname = estrdup9p(tmp);
  489. free(p);
  490. return 0;
  491. }
  492. /*
  493. * This works agains win2k3 but fails
  494. * against XP with the undocumented error 71/0x47
  495. */
  496. int
  497. RAPServerenum2(Session *s, Share *sp, char *workgroup, int type,
  498. int *more,
  499. Serverinfo **si)
  500. {
  501. int ngot = 0, conv, err, nret, navail;
  502. char tmp[1024];
  503. Pkt *p;
  504. Serverinfo *q;
  505. p = thdr(s, sp);
  506. pstr(p, "\\PIPE\\LANMAN");
  507. ptparam(p);
  508. pl16(p, API_NetServerEnum2);
  509. pascii(p, REMSmb_NetServerEnum2_P); /* request descriptor */
  510. pascii(p, REMSmb_server_info_1); /* reply descriptor */
  511. pl16(p, 1); /* detail level */
  512. pl16(p, MTU - 200); /* receive buffer length */
  513. pl32(p, type);
  514. pascii(p, workgroup);
  515. ptdata(p);
  516. if(trpc(p) == -1){
  517. free(p);
  518. return -1;
  519. }
  520. gtparam(p);
  521. err = gl16(p); /* error code */
  522. conv = gl16(p); /* rx buffer offset */
  523. nret = gl16(p); /* number of entries returned */
  524. navail = gl16(p); /* number of entries available */
  525. if(err && err != RAP_ERR_MOREINFO){
  526. werrstr("%s", raperrstr(err));
  527. free(p);
  528. return -1;
  529. }
  530. *si = emalloc9p(sizeof(Serverinfo) * navail);
  531. memset(*si, 0, sizeof(Serverinfo) * navail);
  532. q = *si;
  533. for (; nret-- != 0 && ngot < navail; ngot++){
  534. gmem(p, tmp, 16);
  535. tmp[16] = 0;
  536. q->name = estrdup9p(tmp);
  537. q->major = g8(p);
  538. q->minor = g8(p);
  539. q->type = gl32(p);
  540. gconv(p, conv, tmp, sizeof tmp);
  541. q->comment = estrdup9p(tmp);
  542. q++;
  543. }
  544. free(p);
  545. *more = err == RAP_ERR_MOREINFO;
  546. return ngot;
  547. }
  548. int
  549. RAPServerenum3(Session *s, Share *sp, char *workgroup, int type, int last,
  550. Serverinfo *si)
  551. {
  552. int conv, err, ngot, nret, navail;
  553. char *first, tmp[1024];
  554. Pkt *p;
  555. Serverinfo *q;
  556. ngot = last +1;
  557. first = si[last].name;
  558. more:
  559. p = thdr(s, sp);
  560. pstr(p, "\\PIPE\\LANMAN");
  561. ptparam(p);
  562. pl16(p, API_NetServerEnum3);
  563. pascii(p, REMSmb_NetServerEnum3_P); /* request descriptor */
  564. pascii(p, REMSmb_server_info_1); /* reply descriptor */
  565. pl16(p, 1); /* detail level */
  566. pl16(p, MTU - 200); /* receive buffer length */
  567. pl32(p, type);
  568. pascii(p, workgroup);
  569. pascii(p, first);
  570. ptdata(p);
  571. if(trpc(p) == -1){
  572. free(p);
  573. return -1;
  574. }
  575. gtparam(p);
  576. err = gl16(p); /* error code */
  577. conv = gl16(p); /* rx buffer offset */
  578. nret = gl16(p); /* number of entries returned */
  579. navail = gl16(p); /* number of entries available */
  580. if(err && err != RAP_ERR_MOREINFO){
  581. werrstr("%s", raperrstr(err));
  582. free(p);
  583. return -1;
  584. }
  585. if(nret < 2){ /* paranoia */
  586. free(p);
  587. return ngot;
  588. }
  589. q = si+ngot;
  590. while(nret-- != 0 && ngot < navail){
  591. gmem(p, tmp, 16);
  592. tmp[16] = 0;
  593. q->name = estrdup9p(tmp);
  594. q->major = g8(p);
  595. q->minor = g8(p);
  596. q->type = gl32(p);
  597. gconv(p, conv, tmp, sizeof tmp);
  598. tmp[sizeof tmp - 1] = 0;
  599. q->comment = estrdup9p(tmp);
  600. if(strcmp(first, tmp) == 0){ /* 1st one thru _may_ be a repeat */
  601. free(q->name);
  602. free(q->comment);
  603. continue;
  604. }
  605. ngot++;
  606. q++;
  607. }
  608. free(p);
  609. if(ngot < navail)
  610. goto more;
  611. return ngot;
  612. }
  613. /* Only the Administrator has permission to do this */
  614. int
  615. RAPFileenum2(Session *s, Share *sp, char *user, char *path,
  616. Fileinfo **fip)
  617. {
  618. int conv, err, ngot, resume, nret, navail;
  619. char tmp[1024];
  620. Pkt *p;
  621. Fileinfo *q;
  622. ngot = 0;
  623. resume = 0;
  624. more:
  625. p = thdr(s, sp);
  626. pstr(p, "\\PIPE\\LANMAN");
  627. ptparam(p);
  628. pl16(p, API_WFileEnum2);
  629. pascii(p, REMSmb_NetFileEnum2_P); /* request descriptor */
  630. pascii(p, REMSmb_file_info_1); /* reply descriptor */
  631. pascii(p, path);
  632. pascii(p, user);
  633. pl16(p, 1); /* detail level */
  634. pl16(p, MTU - 200); /* receive buffer length */
  635. pl32(p, resume); /* resume key */
  636. /* FIXME: maybe the padding and resume key are the wrong way around? */
  637. pl32(p, 0); /* padding ? */
  638. ptdata(p);
  639. if(trpc(p) == -1){
  640. free(p);
  641. return -1;
  642. }
  643. gtparam(p);
  644. err = gl16(p); /* error code */
  645. conv = gl16(p); /* rx buffer offset */
  646. resume = gl32(p); /* resume key returned */
  647. nret = gl16(p); /* number of entries returned */
  648. navail = gl16(p); /* number of entries available */
  649. if(err && err != RAP_ERR_MOREINFO){
  650. werrstr("%s", raperrstr(err));
  651. free(p);
  652. return -1;
  653. }
  654. if(nret < 2){ /* paranoia */
  655. free(p);
  656. return ngot;
  657. }
  658. if(ngot == 0){
  659. *fip = emalloc9p(sizeof(Fileinfo) * navail);
  660. memset(*fip, 0, sizeof(Fileinfo) * navail);
  661. }
  662. q = *fip + ngot;
  663. for(; nret-- && ngot < navail; ngot++){
  664. q->ident = gl16(p);
  665. q->perms = gl16(p);
  666. q->locks = gl16(p);
  667. gconv(p, conv, tmp, sizeof tmp);
  668. tmp[sizeof tmp - 1] = 0;
  669. q->path = estrdup9p(tmp);
  670. gconv(p, conv, tmp, sizeof tmp);
  671. tmp[sizeof tmp - 1] = 0;
  672. q->user = estrdup9p(tmp);
  673. q++;
  674. }
  675. free(p);
  676. if(ngot < navail)
  677. goto more;
  678. return ngot;
  679. }