/* answer a node status query */ void nbtd_query_status(struct nbt_name_socket *nbtsock, struct nbt_name_packet *packet, struct socket_address *src) { struct nbt_name *name; struct nbtd_iface_name *iname; struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, struct nbtd_interface); NBTD_ASSERT_PACKET(packet, src, packet->qdcount == 1); NBTD_ASSERT_PACKET(packet, src, packet->questions[0].question_type == NBT_QTYPE_STATUS); NBTD_ASSERT_PACKET(packet, src, packet->questions[0].question_class == NBT_QCLASS_IP); /* see if we have the requested name on this interface */ name = &packet->questions[0].name; iname = nbtd_find_iname(iface, name, NBT_NM_ACTIVE); if (iname == NULL) { DEBUG(7,("Node status query for %s from %s - not found on %s\n", nbt_name_string(packet, name), src->addr, iface->ip_address)); return; } nbtd_node_status_reply(nbtsock, packet, src, &iname->name, iface); }
/* handle incoming netlogon mailslot requests */ void nbtd_mailslot_netlogon_handler(struct dgram_mailslot_handler *dgmslot, struct nbt_dgram_packet *packet, struct socket_address *src) { NTSTATUS status = NT_STATUS_NO_MEMORY; struct nbtd_interface *iface = talloc_get_type(dgmslot->private_data, struct nbtd_interface); struct nbt_netlogon_packet *netlogon = talloc(dgmslot, struct nbt_netlogon_packet); struct nbtd_iface_name *iname; struct nbt_name *name = &packet->data.msg.dest_name; if (netlogon == NULL) goto failed; /* see if the we are listening on the destination netbios name */ iname = nbtd_find_iname(iface, name, 0); if (iname == NULL) { status = NT_STATUS_BAD_NETWORK_NAME; goto failed; } DEBUG(5,("netlogon request to %s from %s:%d\n", nbt_name_string(netlogon, name), src->addr, src->port)); status = dgram_mailslot_netlogon_parse_request(dgmslot, netlogon, packet, netlogon); if (!NT_STATUS_IS_OK(status)) goto failed; switch (netlogon->command) { case LOGON_PRIMARY_QUERY: nbtd_netlogon_getdc(dgmslot, iface, packet, src, netlogon); break; case LOGON_SAM_LOGON_REQUEST: nbtd_netlogon_samlogon(dgmslot, iface, packet, src, netlogon); break; default: DEBUG(2,("unknown netlogon op %d from %s:%d\n", netlogon->command, src->addr, src->port)); NDR_PRINT_DEBUG(nbt_netlogon_packet, netlogon); break; } talloc_free(netlogon); return; failed: DEBUG(2,("nbtd netlogon handler failed from %s:%d to %s - %s\n", src->addr, src->port, nbt_name_string(netlogon, name), nt_errstr(status))); talloc_free(netlogon); }
/* answer a name query */ void nbtd_request_query(struct nbt_name_socket *nbtsock, struct nbt_name_packet *packet, struct socket_address *src) { struct nbtd_iface_name *iname; struct nbt_name *name; struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, struct nbtd_interface); /* see if its a node status query */ if (packet->qdcount == 1 && packet->questions[0].question_type == NBT_QTYPE_STATUS) { nbtd_query_status(nbtsock, packet, src); return; } NBTD_ASSERT_PACKET(packet, src, packet->qdcount == 1); NBTD_ASSERT_PACKET(packet, src, packet->questions[0].question_type == NBT_QTYPE_NETBIOS); NBTD_ASSERT_PACKET(packet, src, packet->questions[0].question_class == NBT_QCLASS_IP); /* see if we have the requested name on this interface */ name = &packet->questions[0].name; iname = nbtd_find_iname(iface, name, 0); if (iname == NULL) { /* don't send negative replies to broadcast queries */ if (packet->operation & NBT_FLAG_BROADCAST) { return; } if (packet->operation & NBT_FLAG_RECURSION_DESIRED) { nbtd_winsserver_request(nbtsock, packet, src); return; } /* otherwise send a negative reply */ nbtd_negative_name_query_reply(nbtsock, packet, src); return; } /* * normally we should forward all queries with the * recursion desired flag to the wins server, but this * breaks are winsclient code, when doing mhomed registrations */ if (!(packet->operation & NBT_FLAG_BROADCAST) && (packet->operation & NBT_FLAG_RECURSION_DESIRED) && (iname->nb_flags & NBT_NM_GROUP) && lpcfg_wins_support(iface->nbtsrv->task->lp_ctx)) { nbtd_winsserver_request(nbtsock, packet, src); return; } /* if the name is not yet active and its a broadcast query then ignore it for now */ if (!(iname->nb_flags & NBT_NM_ACTIVE) && (packet->operation & NBT_FLAG_BROADCAST)) { DEBUG(7,("Query for %s from %s - name not active yet on %s\n", nbt_name_string(packet, name), src->addr, iface->ip_address)); return; } nbtd_name_query_reply(nbtsock, packet, src, &iname->name, iname->ttl, iname->nb_flags, nbtd_address_list(iface, packet)); }
static NTSTATUS nbtd_mailslot_netlogon_reply( struct nbtd_interface *iface, struct nbt_dgram_packet *packet, struct socket_address *src, TALLOC_CTX *mem_ctx, struct nbt_netlogon_response **presponse, char **preply_mailslot) { struct nbt_netlogon_packet *netlogon; struct nbt_name *dst_name = &packet->data.msg.dest_name; struct nbt_netlogon_response *response = NULL; struct nbtd_iface_name *iname; char *reply_mailslot = NULL; NTSTATUS status; /* see if the we are listening on the destination netbios name */ iname = nbtd_find_iname(iface, dst_name, 0); if (iname == NULL) { return NT_STATUS_BAD_NETWORK_NAME; } netlogon = talloc(mem_ctx, struct nbt_netlogon_packet); if (netlogon == NULL) { return NT_STATUS_NO_MEMORY; } status = dgram_mailslot_netlogon_parse_request(netlogon, packet, netlogon); if (!NT_STATUS_IS_OK(status)) { goto failed; } switch (netlogon->command) { case LOGON_PRIMARY_QUERY: status = nbtd_netlogon_getdc( iface->nbtsrv, &packet->data.msg.dest_name, netlogon, mem_ctx, &response, &reply_mailslot); break; case LOGON_SAM_LOGON_REQUEST: status = nbtd_netlogon_samlogon( iface->nbtsrv, &packet->data.msg.dest_name, src, netlogon, mem_ctx, &response, &reply_mailslot); break; default: DEBUG(2,("unknown netlogon op %d from %s:%d\n", netlogon->command, src->addr, src->port)); NDR_PRINT_DEBUG(nbt_netlogon_packet, netlogon); status = NT_STATUS_NOT_SUPPORTED; break; } if (!NT_STATUS_IS_OK(status)) { DBG_DEBUG("Calculating reply failed: %s\n", nt_errstr(status)); goto failed; } *presponse = response; *preply_mailslot = reply_mailslot; return NT_STATUS_OK; failed: TALLOC_FREE(reply_mailslot); TALLOC_FREE(netlogon); return status; }