1
0
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:
Volker Lendecke 2011-01-04 18:34:38 +01:00
parent 77a9b0e265
commit a32f021d66
4 changed files with 198 additions and 91 deletions

View File

@ -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,

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}