mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
s3: Make node_status_query use /tmp/.nmbd/unexpected
This commit is contained in:
parent
77a9b0e265
commit
a32f021d66
@ -2699,12 +2699,18 @@ bool saf_store( const char *domain, const char *servername );
|
||||
bool saf_join_store( const char *domain, const char *servername );
|
||||
bool saf_delete( const char *domain );
|
||||
char *saf_fetch( const char *domain );
|
||||
NTSTATUS node_status_query(int fd,
|
||||
struct nmb_name *name,
|
||||
const struct sockaddr_storage *to_ss,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct node_status **names,
|
||||
int *num_names,
|
||||
struct tevent_req *node_status_query_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct nmb_name *name,
|
||||
const struct sockaddr_storage *addr);
|
||||
NTSTATUS node_status_query_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
|
||||
struct node_status **pnode_status,
|
||||
int *pnum_names,
|
||||
struct node_status_extra *extra);
|
||||
NTSTATUS node_status_query(TALLOC_CTX *mem_ctx, struct nmb_name *name,
|
||||
const struct sockaddr_storage *addr,
|
||||
struct node_status **pnode_status,
|
||||
int *pnum_names,
|
||||
struct node_status_extra *extra);
|
||||
bool name_status_find(const char *q_name,
|
||||
int q_type,
|
||||
|
@ -690,29 +690,54 @@ static bool send_packet_request(struct packet_struct *p)
|
||||
structures holding the returned names or NULL if the query failed.
|
||||
**************************************************************************/
|
||||
|
||||
NTSTATUS node_status_query(int fd,
|
||||
struct nmb_name *name,
|
||||
const struct sockaddr_storage *to_ss,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct node_status **names,
|
||||
int *num_names,
|
||||
struct node_status_extra *extra)
|
||||
struct node_status_query_state {
|
||||
struct sockaddr_storage my_addr;
|
||||
struct sockaddr_storage addr;
|
||||
uint8_t buf[1024];
|
||||
ssize_t buflen;
|
||||
struct packet_struct *packet;
|
||||
};
|
||||
|
||||
static int node_status_query_state_destructor(
|
||||
struct node_status_query_state *s);
|
||||
static bool node_status_query_validator(struct packet_struct *p,
|
||||
void *private_data);
|
||||
static void node_status_query_done(struct tevent_req *subreq);
|
||||
|
||||
struct tevent_req *node_status_query_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct nmb_name *name,
|
||||
const struct sockaddr_storage *addr)
|
||||
{
|
||||
bool found=False;
|
||||
int retries = 2;
|
||||
int retry_time = 2000;
|
||||
struct timespec tp;
|
||||
struct tevent_req *req, *subreq;
|
||||
struct node_status_query_state *state;
|
||||
struct packet_struct p;
|
||||
struct packet_struct *p2;
|
||||
struct nmb_packet *nmb = &p.packet.nmb;
|
||||
struct node_status *ret;
|
||||
struct sockaddr_in *in_addr;
|
||||
|
||||
req = tevent_req_create(mem_ctx, &state,
|
||||
struct node_status_query_state);
|
||||
if (req == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
talloc_set_destructor(state, node_status_query_state_destructor);
|
||||
|
||||
if (addr->ss_family != AF_INET) {
|
||||
/* Can't do node status to IPv6 */
|
||||
tevent_req_nterror(req, NT_STATUS_INVALID_ADDRESS);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
state->addr = *addr;
|
||||
in_addr = (struct sockaddr_in *)(void *)&state->addr;
|
||||
in_addr->sin_port = htons(NMB_PORT);
|
||||
|
||||
if (!interpret_string_addr(&state->my_addr, lp_socket_address(),
|
||||
AI_NUMERICHOST|AI_PASSIVE)) {
|
||||
zero_sockaddr(&state->my_addr);
|
||||
}
|
||||
|
||||
ZERO_STRUCT(p);
|
||||
|
||||
if (to_ss->ss_family != AF_INET) {
|
||||
/* Can't do node status to IPv6 */
|
||||
return NT_STATUS_INVALID_ADDRESS;
|
||||
}
|
||||
nmb->header.name_trn_id = generate_trn_id();
|
||||
nmb->header.opcode = 0;
|
||||
nmb->header.response = false;
|
||||
@ -730,62 +755,152 @@ NTSTATUS node_status_query(int fd,
|
||||
nmb->question.question_type = 0x21;
|
||||
nmb->question.question_class = 0x1;
|
||||
|
||||
p.ip = ((const struct sockaddr_in *)to_ss)->sin_addr;
|
||||
#if DEBUG_UNEXPECTED
|
||||
p.ip = in_addr->sin_addr;
|
||||
p.port = NMB_PORT;
|
||||
p.recv_fd = -1;
|
||||
p.send_fd = fd;
|
||||
p.send_fd = -1;
|
||||
p.timestamp = time(NULL);
|
||||
p.packet_type = NMB_PACKET;
|
||||
|
||||
clock_gettime_mono(&tp);
|
||||
{
|
||||
pid_t nmbd_pid = pidfile_pid("nmbd");
|
||||
|
||||
if (!send_packet_request(&p))
|
||||
return NT_STATUS_NOT_FOUND;
|
||||
|
||||
retries--;
|
||||
|
||||
while (1) {
|
||||
struct timespec tp2;
|
||||
clock_gettime_mono(&tp2);
|
||||
if (nsec_time_diff(&tp2,&tp)/1000000 > retry_time) {
|
||||
if (!retries)
|
||||
break;
|
||||
if (!found && !send_packet_request(&p))
|
||||
return NT_STATUS_NOT_FOUND;
|
||||
clock_gettime_mono(&tp);
|
||||
retries--;
|
||||
}
|
||||
|
||||
if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
|
||||
struct nmb_packet *nmb2 = &p2->packet.nmb;
|
||||
debug_nmb_packet(p2);
|
||||
|
||||
if (nmb2->header.opcode != 0 ||
|
||||
nmb2->header.nm_flags.bcast ||
|
||||
nmb2->header.rcode ||
|
||||
!nmb2->header.ancount ||
|
||||
nmb2->answers->rr_type != 0x21) {
|
||||
/* XXXX what do we do with this? could be a
|
||||
redirect, but we'll discard it for the
|
||||
moment */
|
||||
free_packet(p2);
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = parse_node_status(
|
||||
mem_ctx, &nmb2->answers->rdata[0], num_names,
|
||||
extra);
|
||||
free_packet(p2);
|
||||
|
||||
if (ret == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
*names = ret;
|
||||
return NT_STATUS_OK;
|
||||
if (nmbd_pid) {
|
||||
struct messaging_context *msg_ctx = messaging_init(
|
||||
state, procid_self(), ev);
|
||||
/* Try nmbd. */
|
||||
messaging_send_buf(msg_ctx,
|
||||
pid_to_procid(nmbd_pid),
|
||||
MSG_SEND_PACKET,
|
||||
(uint8_t *)&p,
|
||||
sizeof(struct packet_struct));
|
||||
TALLOC_FREE(msg_ctx);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return NT_STATUS_IO_TIMEOUT;
|
||||
state->buflen = build_packet((char *)state->buf, sizeof(state->buf),
|
||||
&p);
|
||||
if (state->buflen == 0) {
|
||||
tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
|
||||
DEBUG(10, ("build_packet failed\n"));
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
subreq = nb_trans_send(state, ev, &state->my_addr, addr, false,
|
||||
state->buf, state->buflen,
|
||||
NMB_PACKET, nmb->header.name_trn_id,
|
||||
node_status_query_validator, NULL);
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
DEBUG(10, ("nb_trans_send failed\n"));
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(10, 0))) {
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
tevent_req_set_callback(subreq, node_status_query_done, req);
|
||||
return req;
|
||||
}
|
||||
|
||||
static bool node_status_query_validator(struct packet_struct *p,
|
||||
void *private_data)
|
||||
{
|
||||
struct nmb_packet *nmb = &p->packet.nmb;
|
||||
debug_nmb_packet(p);
|
||||
|
||||
if (nmb->header.opcode != 0 ||
|
||||
nmb->header.nm_flags.bcast ||
|
||||
nmb->header.rcode ||
|
||||
!nmb->header.ancount ||
|
||||
nmb->answers->rr_type != 0x21) {
|
||||
/*
|
||||
* XXXX what do we do with this? could be a redirect,
|
||||
* but we'll discard it for the moment
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int node_status_query_state_destructor(
|
||||
struct node_status_query_state *s)
|
||||
{
|
||||
if (s->packet != NULL) {
|
||||
free_packet(s->packet);
|
||||
s->packet = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void node_status_query_done(struct tevent_req *subreq)
|
||||
{
|
||||
struct tevent_req *req = tevent_req_callback_data(
|
||||
subreq, struct tevent_req);
|
||||
struct node_status_query_state *state = tevent_req_data(
|
||||
req, struct node_status_query_state);
|
||||
NTSTATUS status;
|
||||
|
||||
status = nb_trans_recv(subreq, &state->packet);
|
||||
TALLOC_FREE(subreq);
|
||||
if (tevent_req_nterror(req, status)) {
|
||||
return;
|
||||
}
|
||||
tevent_req_done(req);
|
||||
}
|
||||
|
||||
NTSTATUS node_status_query_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
|
||||
struct node_status **pnode_status,
|
||||
int *pnum_names,
|
||||
struct node_status_extra *extra)
|
||||
{
|
||||
struct node_status_query_state *state = tevent_req_data(
|
||||
req, struct node_status_query_state);
|
||||
struct node_status *node_status;
|
||||
int num_names;
|
||||
NTSTATUS status;
|
||||
|
||||
if (tevent_req_is_nterror(req, &status)) {
|
||||
return status;
|
||||
}
|
||||
node_status = parse_node_status(
|
||||
mem_ctx, &state->packet->packet.nmb.answers->rdata[0],
|
||||
&num_names, extra);
|
||||
if (node_status == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
*pnode_status = node_status;
|
||||
*pnum_names = num_names;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
NTSTATUS node_status_query(TALLOC_CTX *mem_ctx, struct nmb_name *name,
|
||||
const struct sockaddr_storage *addr,
|
||||
struct node_status **pnode_status,
|
||||
int *pnum_names,
|
||||
struct node_status_extra *extra)
|
||||
{
|
||||
TALLOC_CTX *frame = talloc_stackframe();
|
||||
struct tevent_context *ev;
|
||||
struct tevent_req *req;
|
||||
NTSTATUS status = NT_STATUS_NO_MEMORY;
|
||||
|
||||
ev = tevent_context_init(frame);
|
||||
if (ev == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
req = node_status_query_send(ev, ev, name, addr);
|
||||
if (req == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
if (!tevent_req_poll_ntstatus(req, ev, &status)) {
|
||||
goto fail;
|
||||
}
|
||||
status = node_status_query_recv(req, mem_ctx, pnode_status,
|
||||
pnum_names, extra);
|
||||
fail:
|
||||
TALLOC_FREE(frame);
|
||||
return status;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -804,7 +919,6 @@ bool name_status_find(const char *q_name,
|
||||
struct node_status *addrs = NULL;
|
||||
struct nmb_name nname;
|
||||
int count, i;
|
||||
int sock;
|
||||
bool result = false;
|
||||
NTSTATUS status;
|
||||
|
||||
@ -835,15 +949,10 @@ bool name_status_find(const char *q_name,
|
||||
zero_sockaddr(&ss);
|
||||
}
|
||||
|
||||
sock = open_socket_in(SOCK_DGRAM, 0, 3, &ss, True);
|
||||
if (sock == -1)
|
||||
goto done;
|
||||
|
||||
/* W2K PDC's seem not to respond to '*'#0. JRA */
|
||||
make_nmb_name(&nname, q_name, q_type);
|
||||
status = node_status_query(sock, &nname, to_ss, talloc_tos(),
|
||||
status = node_status_query(talloc_tos(), &nname, to_ss,
|
||||
&addrs, &count, NULL);
|
||||
close(sock);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto done;
|
||||
}
|
||||
|
@ -106,8 +106,7 @@ static char *query_flags(int flags)
|
||||
Do a node status query.
|
||||
****************************************************************************/
|
||||
|
||||
static void do_node_status(int fd,
|
||||
const char *name,
|
||||
static void do_node_status(const char *name,
|
||||
int type,
|
||||
struct sockaddr_storage *pss)
|
||||
{
|
||||
@ -122,7 +121,7 @@ static void do_node_status(int fd,
|
||||
print_sockaddr(addr, sizeof(addr), pss);
|
||||
d_printf("Looking up status of %s\n",addr);
|
||||
make_nmb_name(&nname, name, type);
|
||||
status = node_status_query(fd, &nname, pss, talloc_tos(),
|
||||
status = node_status_query(talloc_tos(), &nname, pss,
|
||||
&addrs, &count, &extra);
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
for (i=0;i<count;i++) {
|
||||
@ -218,8 +217,7 @@ static bool query_one(const char *lookup, unsigned int lookup_type)
|
||||
was valid - ie. name_query returned true.
|
||||
*/
|
||||
if (find_status) {
|
||||
do_node_status(ServerFD, lookup,
|
||||
lookup_type, &ip_list[j]);
|
||||
do_node_status(lookup, lookup_type, &ip_list[j]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -339,7 +337,7 @@ int main(int argc,char *argv[])
|
||||
ip = interpret_addr2(lookup);
|
||||
in_addr_to_sockaddr_storage(&ss, ip);
|
||||
fstrcpy(lookup,"*");
|
||||
do_node_status(ServerFD, lookup, lookup_type, &ss);
|
||||
do_node_status(lookup, lookup_type, &ss);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -73,23 +73,17 @@ static int wins_lookup_open_socket_in(void)
|
||||
static struct node_status *lookup_byaddr_backend(TALLOC_CTX *mem_ctx,
|
||||
const char *addr, int *count)
|
||||
{
|
||||
int fd;
|
||||
struct sockaddr_storage ss;
|
||||
struct nmb_name nname;
|
||||
struct node_status *result;
|
||||
NTSTATUS status;
|
||||
|
||||
fd = wins_lookup_open_socket_in();
|
||||
if (fd == -1)
|
||||
return NULL;
|
||||
|
||||
make_nmb_name(&nname, "*", 0);
|
||||
if (!interpret_string_addr(&ss, addr, AI_NUMERICHOST)) {
|
||||
return NULL;
|
||||
}
|
||||
status = node_status_query(fd, &nname, &ss, mem_ctx,
|
||||
status = node_status_query(mem_ctx, &nname, &ss,
|
||||
&result, count, NULL);
|
||||
close(fd);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return NULL;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user