PageRenderTime 67ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 0ms

/libcli/nbt/nameregister.c

https://gitlab.com/miztake/samba
C | 514 lines | 364 code | 82 blank | 68 comment | 65 complexity | 28fbb62fa226d68d6fa66d9793558dbb MD5 | raw file
  1. /*
  2. Unix SMB/CIFS implementation.
  3. send out a name registration request
  4. Copyright (C) Andrew Tridgell 2005
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "includes.h"
  17. #include <tevent.h>
  18. #include "../libcli/nbt/libnbt.h"
  19. #include "../libcli/nbt/nbt_proto.h"
  20. #include "lib/socket/socket.h"
  21. #include "librpc/gen_ndr/ndr_nbt.h"
  22. #include "../lib/util/tevent_ntstatus.h"
  23. /*
  24. send a nbt name registration request
  25. */
  26. struct nbt_name_request *nbt_name_register_send(struct nbt_name_socket *nbtsock,
  27. struct nbt_name_register *io)
  28. {
  29. struct nbt_name_request *req;
  30. struct nbt_name_packet *packet;
  31. struct socket_address *dest;
  32. packet = talloc_zero(nbtsock, struct nbt_name_packet);
  33. if (packet == NULL) return NULL;
  34. packet->qdcount = 1;
  35. packet->arcount = 1;
  36. if (io->in.multi_homed) {
  37. packet->operation = NBT_OPCODE_MULTI_HOME_REG;
  38. } else {
  39. packet->operation = NBT_OPCODE_REGISTER;
  40. }
  41. if (io->in.broadcast) {
  42. packet->operation |= NBT_FLAG_BROADCAST;
  43. }
  44. if (io->in.register_demand) {
  45. packet->operation |= NBT_FLAG_RECURSION_DESIRED;
  46. }
  47. packet->questions = talloc_array(packet, struct nbt_name_question, 1);
  48. if (packet->questions == NULL) goto failed;
  49. packet->questions[0].name = io->in.name;
  50. packet->questions[0].question_type = NBT_QTYPE_NETBIOS;
  51. packet->questions[0].question_class = NBT_QCLASS_IP;
  52. packet->additional = talloc_array(packet, struct nbt_res_rec, 1);
  53. if (packet->additional == NULL) goto failed;
  54. packet->additional[0].name = io->in.name;
  55. packet->additional[0].rr_type = NBT_QTYPE_NETBIOS;
  56. packet->additional[0].rr_class = NBT_QCLASS_IP;
  57. packet->additional[0].ttl = io->in.ttl;
  58. packet->additional[0].rdata.netbios.length = 6;
  59. packet->additional[0].rdata.netbios.addresses = talloc_array(packet->additional,
  60. struct nbt_rdata_address, 1);
  61. if (packet->additional[0].rdata.netbios.addresses == NULL) goto failed;
  62. packet->additional[0].rdata.netbios.addresses[0].nb_flags = io->in.nb_flags;
  63. packet->additional[0].rdata.netbios.addresses[0].ipaddr =
  64. talloc_strdup(packet->additional, io->in.address);
  65. if (packet->additional[0].rdata.netbios.addresses[0].ipaddr == NULL) goto failed;
  66. dest = socket_address_from_strings(packet, nbtsock->sock->backend_name,
  67. io->in.dest_addr, io->in.dest_port);
  68. if (dest == NULL) goto failed;
  69. req = nbt_name_request_send(nbtsock, nbtsock, dest, packet,
  70. io->in.timeout, io->in.retries, false);
  71. if (req == NULL) goto failed;
  72. talloc_free(packet);
  73. return req;
  74. failed:
  75. talloc_free(packet);
  76. return NULL;
  77. }
  78. /*
  79. wait for a registration reply
  80. */
  81. _PUBLIC_ NTSTATUS nbt_name_register_recv(struct nbt_name_request *req,
  82. TALLOC_CTX *mem_ctx, struct nbt_name_register *io)
  83. {
  84. NTSTATUS status;
  85. struct nbt_name_packet *packet;
  86. status = nbt_name_request_recv(req);
  87. if (!NT_STATUS_IS_OK(status) ||
  88. req->num_replies == 0) {
  89. talloc_free(req);
  90. return status;
  91. }
  92. packet = req->replies[0].packet;
  93. io->out.reply_from = talloc_steal(mem_ctx, req->replies[0].dest->addr);
  94. if (packet->ancount != 1 ||
  95. packet->answers[0].rr_type != NBT_QTYPE_NETBIOS ||
  96. packet->answers[0].rr_class != NBT_QCLASS_IP) {
  97. talloc_free(req);
  98. return NT_STATUS_INVALID_NETWORK_RESPONSE;
  99. }
  100. io->out.rcode = packet->operation & NBT_RCODE;
  101. io->out.name = packet->answers[0].name;
  102. if (packet->answers[0].rdata.netbios.length < 6) {
  103. talloc_free(req);
  104. return NT_STATUS_INVALID_NETWORK_RESPONSE;
  105. }
  106. io->out.reply_addr = talloc_steal(mem_ctx,
  107. packet->answers[0].rdata.netbios.addresses[0].ipaddr);
  108. talloc_steal(mem_ctx, io->out.name.name);
  109. talloc_steal(mem_ctx, io->out.name.scope);
  110. talloc_free(req);
  111. return NT_STATUS_OK;
  112. }
  113. /*
  114. synchronous name registration request
  115. */
  116. _PUBLIC_ NTSTATUS nbt_name_register(struct nbt_name_socket *nbtsock,
  117. TALLOC_CTX *mem_ctx, struct nbt_name_register *io)
  118. {
  119. struct nbt_name_request *req = nbt_name_register_send(nbtsock, io);
  120. return nbt_name_register_recv(req, mem_ctx, io);
  121. }
  122. /*
  123. a 4 step broadcast registration. 3 lots of name registration requests, followed by
  124. a name registration demand
  125. */
  126. struct nbt_name_register_bcast_state {
  127. struct nbt_name_socket *nbtsock;
  128. struct nbt_name_register io;
  129. };
  130. static void nbt_name_register_bcast_handler(struct nbt_name_request *subreq);
  131. /*
  132. the async send call for a 4 stage name registration
  133. */
  134. _PUBLIC_ struct tevent_req *nbt_name_register_bcast_send(TALLOC_CTX *mem_ctx,
  135. struct tevent_context *ev,
  136. struct nbt_name_socket *nbtsock,
  137. struct nbt_name_register_bcast *io)
  138. {
  139. struct tevent_req *req;
  140. struct nbt_name_register_bcast_state *state;
  141. struct nbt_name_request *subreq;
  142. req = tevent_req_create(mem_ctx, &state,
  143. struct nbt_name_register_bcast_state);
  144. if (req == NULL) {
  145. return NULL;
  146. }
  147. state->io.in.name = io->in.name;
  148. state->io.in.dest_addr = io->in.dest_addr;
  149. state->io.in.dest_port = io->in.dest_port;
  150. state->io.in.address = io->in.address;
  151. state->io.in.nb_flags = io->in.nb_flags;
  152. state->io.in.register_demand = false;
  153. state->io.in.broadcast = true;
  154. state->io.in.multi_homed = false;
  155. state->io.in.ttl = io->in.ttl;
  156. state->io.in.timeout = 1;
  157. state->io.in.retries = 2;
  158. state->nbtsock = nbtsock;
  159. subreq = nbt_name_register_send(nbtsock, &state->io);
  160. if (tevent_req_nomem(subreq, req)) {
  161. return tevent_req_post(req, ev);
  162. }
  163. subreq->async.fn = nbt_name_register_bcast_handler;
  164. subreq->async.private_data = req;
  165. return req;
  166. }
  167. static void nbt_name_register_bcast_handler(struct nbt_name_request *subreq)
  168. {
  169. struct tevent_req *req =
  170. talloc_get_type_abort(subreq->async.private_data,
  171. struct tevent_req);
  172. struct nbt_name_register_bcast_state *state =
  173. tevent_req_data(req,
  174. struct nbt_name_register_bcast_state);
  175. NTSTATUS status;
  176. status = nbt_name_register_recv(subreq, state, &state->io);
  177. if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
  178. if (state->io.in.register_demand == true) {
  179. tevent_req_done(req);
  180. return;
  181. }
  182. /* the registration timed out - good, send the demand */
  183. state->io.in.register_demand = true;
  184. state->io.in.retries = 0;
  185. subreq = nbt_name_register_send(state->nbtsock, &state->io);
  186. if (tevent_req_nomem(subreq, req)) {
  187. return;
  188. }
  189. subreq->async.fn = nbt_name_register_bcast_handler;
  190. subreq->async.private_data = req;
  191. return;
  192. }
  193. if (!NT_STATUS_IS_OK(status)) {
  194. tevent_req_nterror(req, status);
  195. return;
  196. }
  197. DEBUG(3,("Name registration conflict from %s for %s with ip %s - rcode %d\n",
  198. state->io.out.reply_from,
  199. nbt_name_string(state, &state->io.out.name),
  200. state->io.out.reply_addr,
  201. state->io.out.rcode));
  202. tevent_req_nterror(req, NT_STATUS_CONFLICTING_ADDRESSES);
  203. }
  204. /*
  205. broadcast 4 part name register - recv
  206. */
  207. _PUBLIC_ NTSTATUS nbt_name_register_bcast_recv(struct tevent_req *req)
  208. {
  209. NTSTATUS status;
  210. if (tevent_req_is_nterror(req, &status)) {
  211. tevent_req_received(req);
  212. return status;
  213. }
  214. tevent_req_received(req);
  215. return NT_STATUS_OK;
  216. }
  217. /*
  218. broadcast 4 part name register - sync interface
  219. */
  220. NTSTATUS nbt_name_register_bcast(struct nbt_name_socket *nbtsock,
  221. struct nbt_name_register_bcast *io)
  222. {
  223. TALLOC_CTX *frame = talloc_stackframe();
  224. struct tevent_context *ev;
  225. struct tevent_req *subreq;
  226. NTSTATUS status;
  227. /*
  228. * TODO: create a temporary event context
  229. */
  230. ev = nbtsock->event_ctx;
  231. subreq = nbt_name_register_bcast_send(frame, ev, nbtsock, io);
  232. if (subreq == NULL) {
  233. talloc_free(frame);
  234. return NT_STATUS_NO_MEMORY;
  235. }
  236. if (!tevent_req_poll(subreq, ev)) {
  237. status = map_nt_error_from_unix_common(errno);
  238. talloc_free(frame);
  239. return status;
  240. }
  241. status = nbt_name_register_bcast_recv(subreq);
  242. if (!NT_STATUS_IS_OK(status)) {
  243. talloc_free(frame);
  244. return status;
  245. }
  246. TALLOC_FREE(frame);
  247. return NT_STATUS_OK;
  248. }
  249. /*
  250. a wins name register with multiple WINS servers and multiple
  251. addresses to register. Try each WINS server in turn, until we get a
  252. reply for each address
  253. */
  254. struct nbt_name_register_wins_state {
  255. struct nbt_name_socket *nbtsock;
  256. struct nbt_name_register io;
  257. char **wins_servers;
  258. uint16_t wins_port;
  259. char **addresses;
  260. uint32_t address_idx;
  261. };
  262. static void nbt_name_register_wins_handler(struct nbt_name_request *subreq);
  263. /*
  264. the async send call for a multi-server WINS register
  265. */
  266. _PUBLIC_ struct tevent_req *nbt_name_register_wins_send(TALLOC_CTX *mem_ctx,
  267. struct tevent_context *ev,
  268. struct nbt_name_socket *nbtsock,
  269. struct nbt_name_register_wins *io)
  270. {
  271. struct tevent_req *req;
  272. struct nbt_name_register_wins_state *state;
  273. struct nbt_name_request *subreq;
  274. req = tevent_req_create(mem_ctx, &state,
  275. struct nbt_name_register_wins_state);
  276. if (req == NULL) {
  277. return NULL;
  278. }
  279. if (io->in.wins_servers == NULL) {
  280. tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
  281. return tevent_req_post(req, ev);
  282. }
  283. if (io->in.wins_servers[0] == NULL) {
  284. tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
  285. return tevent_req_post(req, ev);
  286. }
  287. if (io->in.addresses == NULL) {
  288. tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
  289. return tevent_req_post(req, ev);
  290. }
  291. if (io->in.addresses[0] == NULL) {
  292. tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
  293. return tevent_req_post(req, ev);
  294. }
  295. state->wins_port = io->in.wins_port;
  296. state->wins_servers = str_list_copy(state, io->in.wins_servers);
  297. if (tevent_req_nomem(state->wins_servers, req)) {
  298. return tevent_req_post(req, ev);
  299. }
  300. state->addresses = str_list_copy(state, io->in.addresses);
  301. if (tevent_req_nomem(state->addresses, req)) {
  302. return tevent_req_post(req, ev);
  303. }
  304. state->io.in.name = io->in.name;
  305. state->io.in.dest_addr = state->wins_servers[0];
  306. state->io.in.dest_port = state->wins_port;
  307. state->io.in.address = io->in.addresses[0];
  308. state->io.in.nb_flags = io->in.nb_flags;
  309. state->io.in.broadcast = false;
  310. state->io.in.register_demand = false;
  311. state->io.in.multi_homed = (io->in.nb_flags & NBT_NM_GROUP)?false:true;
  312. state->io.in.ttl = io->in.ttl;
  313. state->io.in.timeout = 3;
  314. state->io.in.retries = 2;
  315. state->nbtsock = nbtsock;
  316. state->address_idx = 0;
  317. subreq = nbt_name_register_send(nbtsock, &state->io);
  318. if (tevent_req_nomem(subreq, req)) {
  319. return tevent_req_post(req, ev);
  320. }
  321. subreq->async.fn = nbt_name_register_wins_handler;
  322. subreq->async.private_data = req;
  323. return req;
  324. }
  325. /*
  326. state handler for WINS multi-homed multi-server name register
  327. */
  328. static void nbt_name_register_wins_handler(struct nbt_name_request *subreq)
  329. {
  330. struct tevent_req *req =
  331. talloc_get_type_abort(subreq->async.private_data,
  332. struct tevent_req);
  333. struct nbt_name_register_wins_state *state =
  334. tevent_req_data(req,
  335. struct nbt_name_register_wins_state);
  336. NTSTATUS status;
  337. status = nbt_name_register_recv(subreq, state, &state->io);
  338. if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
  339. /* the register timed out - try the next WINS server */
  340. state->wins_servers++;
  341. if (state->wins_servers[0] == NULL) {
  342. tevent_req_nterror(req, status);
  343. return;
  344. }
  345. state->address_idx = 0;
  346. state->io.in.dest_addr = state->wins_servers[0];
  347. state->io.in.dest_port = state->wins_port;
  348. state->io.in.address = state->addresses[0];
  349. subreq = nbt_name_register_send(state->nbtsock, &state->io);
  350. if (tevent_req_nomem(subreq, req)) {
  351. return;
  352. }
  353. subreq->async.fn = nbt_name_register_wins_handler;
  354. subreq->async.private_data = req;
  355. return;
  356. }
  357. if (!NT_STATUS_IS_OK(status)) {
  358. tevent_req_nterror(req, status);
  359. return;
  360. }
  361. if (state->io.out.rcode == 0 &&
  362. state->addresses[state->address_idx+1] != NULL) {
  363. /* register our next address */
  364. state->io.in.address = state->addresses[++(state->address_idx)];
  365. subreq = nbt_name_register_send(state->nbtsock, &state->io);
  366. if (tevent_req_nomem(subreq, req)) {
  367. return;
  368. }
  369. subreq->async.fn = nbt_name_register_wins_handler;
  370. subreq->async.private_data = req;
  371. return;
  372. }
  373. tevent_req_done(req);
  374. }
  375. /*
  376. multi-homed WINS name register - recv side
  377. */
  378. _PUBLIC_ NTSTATUS nbt_name_register_wins_recv(struct tevent_req *req,
  379. TALLOC_CTX *mem_ctx,
  380. struct nbt_name_register_wins *io)
  381. {
  382. struct nbt_name_register_wins_state *state =
  383. tevent_req_data(req,
  384. struct nbt_name_register_wins_state);
  385. NTSTATUS status;
  386. if (tevent_req_is_nterror(req, &status)) {
  387. tevent_req_received(req);
  388. return status;
  389. }
  390. io->out.wins_server = talloc_move(mem_ctx, &state->wins_servers[0]);
  391. io->out.rcode = state->io.out.rcode;
  392. tevent_req_received(req);
  393. return NT_STATUS_OK;
  394. }
  395. /*
  396. multi-homed WINS register - sync interface
  397. */
  398. _PUBLIC_ NTSTATUS nbt_name_register_wins(struct nbt_name_socket *nbtsock,
  399. TALLOC_CTX *mem_ctx,
  400. struct nbt_name_register_wins *io)
  401. {
  402. TALLOC_CTX *frame = talloc_stackframe();
  403. struct tevent_context *ev;
  404. struct tevent_req *subreq;
  405. NTSTATUS status;
  406. /*
  407. * TODO: create a temporary event context
  408. */
  409. ev = nbtsock->event_ctx;
  410. subreq = nbt_name_register_wins_send(frame, ev, nbtsock, io);
  411. if (subreq == NULL) {
  412. talloc_free(frame);
  413. return NT_STATUS_NO_MEMORY;
  414. }
  415. if (!tevent_req_poll(subreq, ev)) {
  416. status = map_nt_error_from_unix_common(errno);
  417. talloc_free(frame);
  418. return status;
  419. }
  420. status = nbt_name_register_wins_recv(subreq, mem_ctx, io);
  421. if (!NT_STATUS_IS_OK(status)) {
  422. talloc_free(frame);
  423. return status;
  424. }
  425. TALLOC_FREE(frame);
  426. return NT_STATUS_OK;
  427. }