Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : async implementation of WINBINDD_WINS_BYNAME
4 : Copyright (C) Volker Lendecke 2011
5 :
6 : This program is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include "includes.h"
21 : #include "winbindd.h"
22 : #include "libsmb/namequery.h"
23 : #include "librpc/gen_ndr/ndr_winbind_c.h"
24 : #include "libsmb/nmblib.h"
25 : #include "lib/util/string_wrappers.h"
26 :
27 : struct winbindd_wins_byname_state {
28 : struct tevent_context *ev;
29 : struct winbindd_request *request;
30 : struct sockaddr_storage *addrs;
31 : size_t num_addrs;
32 : };
33 :
34 : static void winbindd_wins_byname_wins_done(struct tevent_req *subreq);
35 : static void winbindd_wins_byname_bcast_done(struct tevent_req *subreq);
36 :
37 4 : struct tevent_req *winbindd_wins_byname_send(TALLOC_CTX *mem_ctx,
38 : struct tevent_context *ev,
39 : struct winbindd_cli_state *cli,
40 : struct winbindd_request *request)
41 : {
42 0 : struct tevent_req *req, *subreq;
43 0 : struct winbindd_wins_byname_state *state;
44 :
45 4 : req = tevent_req_create(mem_ctx, &state,
46 : struct winbindd_wins_byname_state);
47 4 : if (req == NULL) {
48 0 : return NULL;
49 : }
50 4 : state->ev = ev;
51 4 : state->request = request;
52 :
53 : /* Ensure null termination */
54 4 : request->data.winsreq[sizeof(request->data.winsreq)-1]='\0';
55 :
56 4 : D_NOTICE("[%s (%u)] Winbind external command WINS_BYNAME start.\n"
57 : "Resolving wins byname for '%s'.\n",
58 : cli->client_name,
59 : (unsigned int)cli->pid,
60 : request->data.winsreq);
61 :
62 4 : subreq = resolve_wins_send(state, ev, state->request->data.winsreq,
63 : 0x20);
64 4 : if (tevent_req_nomem(subreq, req)) {
65 0 : return tevent_req_post(req, ev);
66 : }
67 4 : tevent_req_set_callback(subreq, winbindd_wins_byname_wins_done, req);
68 4 : return req;
69 : }
70 :
71 4 : static void winbindd_wins_byname_wins_done(struct tevent_req *subreq)
72 : {
73 4 : struct tevent_req *req = tevent_req_callback_data(
74 : subreq, struct tevent_req);
75 4 : struct winbindd_wins_byname_state *state = tevent_req_data(
76 : req, struct winbindd_wins_byname_state);
77 0 : NTSTATUS status;
78 :
79 4 : status = resolve_wins_recv(subreq, talloc_tos(), &state->addrs,
80 : &state->num_addrs, NULL);
81 4 : TALLOC_FREE(subreq);
82 4 : if (NT_STATUS_IS_OK(status)) {
83 0 : tevent_req_done(req);
84 0 : return;
85 : }
86 4 : subreq = name_resolve_bcast_send(state, state->ev,
87 4 : state->request->data.winsreq, 0x20);
88 4 : if (tevent_req_nomem(subreq, req)) {
89 0 : return;
90 : }
91 4 : tevent_req_set_callback(subreq, winbindd_wins_byname_bcast_done, req);
92 : }
93 :
94 4 : static void winbindd_wins_byname_bcast_done(struct tevent_req *subreq)
95 : {
96 4 : struct tevent_req *req = tevent_req_callback_data(
97 : subreq, struct tevent_req);
98 4 : struct winbindd_wins_byname_state *state = tevent_req_data(
99 : req, struct winbindd_wins_byname_state);
100 0 : NTSTATUS status;
101 :
102 4 : status = name_resolve_bcast_recv(subreq, talloc_tos(), &state->addrs,
103 : &state->num_addrs);
104 4 : TALLOC_FREE(subreq);
105 4 : if (tevent_req_nterror(req, status)) {
106 0 : return;
107 : }
108 4 : tevent_req_done(req);
109 : }
110 :
111 4 : NTSTATUS winbindd_wins_byname_recv(struct tevent_req *req,
112 : struct winbindd_response *presp)
113 : {
114 4 : struct winbindd_wins_byname_state *state = tevent_req_data(
115 : req, struct winbindd_wins_byname_state);
116 0 : char *response;
117 0 : NTSTATUS status;
118 0 : size_t i;
119 :
120 4 : if (tevent_req_is_nterror(req, &status)) {
121 0 : return status;
122 : }
123 :
124 4 : response = talloc_strdup(talloc_tos(), "");
125 4 : if (response == NULL) {
126 0 : return NT_STATUS_NO_MEMORY;
127 : }
128 :
129 4 : D_NOTICE("Winbind external command WINS_BYNAME end.\n"
130 : "Received %zu address(es).\n",
131 : state->num_addrs);
132 8 : for (i=0; i<state->num_addrs; i++) {
133 0 : char addr[INET6_ADDRSTRLEN];
134 4 : print_sockaddr(addr, sizeof(addr), &state->addrs[i]);
135 4 : D_NOTICE("%zu: %s\n", i, addr);
136 4 : talloc_asprintf_addbuf(
137 : &response, "%s%s", addr,
138 4 : i < (state->num_addrs-1) ? " " : "");
139 : }
140 :
141 4 : talloc_asprintf_addbuf(
142 4 : &response, "\t%s\n", state->request->data.winsreq);
143 4 : if (response == NULL) {
144 0 : return NT_STATUS_NO_MEMORY;
145 : }
146 :
147 4 : if (talloc_get_size(response) > sizeof(presp->data.winsresp)) {
148 0 : TALLOC_FREE(response);
149 0 : return NT_STATUS_MARSHALL_OVERFLOW;
150 : }
151 4 : fstrcpy(presp->data.winsresp, response);
152 4 : TALLOC_FREE(response);
153 4 : return NT_STATUS_OK;
154 : }
|