/* receive an incoming request and dispatch it to the right place */ static void nbtd_request_handler(struct nbt_name_socket *nbtsock, struct nbt_name_packet *packet, struct socket_address *src) { struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, struct nbtd_interface); struct nbtd_server *nbtsrv = iface->nbtsrv; nbtsrv->stats.total_received++; /* see if its from one of our own interfaces - if so, then ignore it */ if (nbtd_self_packet_and_bcast(nbtsock, packet, src)) { DEBUG(10,("Ignoring bcast self packet from %s:%d\n", src->addr, src->port)); return; } switch (packet->operation & NBT_OPCODE) { case NBT_OPCODE_QUERY: nbtsrv->stats.query_count++; nbtd_request_query(nbtsock, packet, src); break; case NBT_OPCODE_REGISTER: case NBT_OPCODE_REFRESH: case NBT_OPCODE_REFRESH2: nbtsrv->stats.register_count++; nbtd_request_defense(nbtsock, packet, src); break; case NBT_OPCODE_RELEASE: case NBT_OPCODE_MULTI_HOME_REG: nbtsrv->stats.release_count++; nbtd_winsserver_request(nbtsock, packet, src); break; default: nbtd_bad_packet(packet, src, "Unexpected opcode"); break; } }
/* 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)); }