summaryrefslogtreecommitdiff
path: root/source4/nbt_server/interfaces.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2005-02-02 10:29:50 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:09:28 -0500
commit77cdd7c0ff182f77b1edb032f8d8cd172bdff7ce (patch)
tree45672dee8ae3b030d2e0fada04b9da3d8ae06b3b /source4/nbt_server/interfaces.c
parent96f02f7403a94e0b674e57cfd50f91cf763c7c5c (diff)
downloadsamba-77cdd7c0ff182f77b1edb032f8d8cd172bdff7ce.tar.gz
samba-77cdd7c0ff182f77b1edb032f8d8cd172bdff7ce.tar.bz2
samba-77cdd7c0ff182f77b1edb032f8d8cd172bdff7ce.zip
r5171: added support for "bind interfaces only" in nbtd. The solution was to
bind twice on each interface, once using the broadcast address and once using the specific IP. We then only listen on the wildcard address if we don't have "bind interface only" set. This also happens to simplify the code that finds the right interface for an incoming request. (This used to be commit b3edf17281c5d82abb40dab817bf2de43f9f6c3f)
Diffstat (limited to 'source4/nbt_server/interfaces.c')
-rw-r--r--source4/nbt_server/interfaces.c125
1 files changed, 68 insertions, 57 deletions
diff --git a/source4/nbt_server/interfaces.c b/source4/nbt_server/interfaces.c
index 303802e2cd..8c5566c819 100644
--- a/source4/nbt_server/interfaces.c
+++ b/source4/nbt_server/interfaces.c
@@ -25,6 +25,23 @@
#include "nbt_server/nbt_server.h"
#include "smbd/service_task.h"
+
+/*
+ receive an incoming request and dispatch it to the right place
+*/
+static void nbt_request_handler(struct nbt_name_socket *nbtsock,
+ struct nbt_name_packet *packet,
+ const char *src_address, int src_port)
+{
+ switch (packet->operation & NBT_OPCODE) {
+ case NBT_OPCODE_QUERY:
+ nbt_request_query(nbtsock, packet, src_address, src_port);
+ break;
+ }
+}
+
+
+
/*
find a registered name on an interface
*/
@@ -43,56 +60,24 @@ struct nbt_iface_name *nbt_find_iname(struct nbt_interface *iface, struct nbt_na
}
/*
- see if a src address matches an interface
-*/
-static BOOL nbt_iface_match(struct nbt_interface *iface, const char *src_address)
-{
- struct ipv4_addr ip1, ip2, mask;
- ip1 = interpret_addr2(iface->ip_address);
- ip2 = interpret_addr2(src_address);
- mask = interpret_addr2(iface->netmask);
- return same_net(ip1, ip2, mask);
-}
-
-
-/*
- find the appropriate interface for a incoming packet. If a local interface isn't
- found then the general broadcast interface is used
-*/
-struct nbt_interface *nbt_iface_find(struct nbt_name_socket *nbtsock, const char *src_address)
-{
- struct nbt_interface *iface = talloc_get_type(nbtsock->incoming.private, struct nbt_interface);
- struct nbt_server *nbtsrv = iface->nbtsrv;
-
- /* it might have been received by one of our specific bound
- addresses */
- if (iface != nbtsrv->bcast_interface) {
- return iface;
- }
-
- /* it came in on our broadcast interface - try to find a match */
- for (iface=nbtsrv->interfaces;iface;iface=iface->next) {
- if (nbt_iface_match(iface, src_address)) {
- return iface;
- }
- }
-
- /* it didn't match any specific interface - use our general broadcast interface */
- return nbtsrv->bcast_interface;
-}
-
-
-/*
start listening on the given address
*/
static NTSTATUS nbt_add_socket(struct nbt_server *nbtsrv,
- const char *bind_address,
const char *address,
const char *bcast,
const char *netmask)
{
struct nbt_interface *iface;
NTSTATUS status;
+ struct nbt_name_socket *bcast_nbtsock;
+
+ /*
+ we actually create two sockets. One listens on the broadcast address
+ for the interface, and the other listens on our specific address. This
+ allows us to run with "bind interfaces only" while still receiving
+ broadcast addresses, and also simplifies matching incoming requests
+ to interfaces
+ */
iface = talloc(nbtsrv, struct nbt_interface);
NT_STATUS_HAVE_NO_MEMORY(iface);
@@ -103,10 +88,25 @@ static NTSTATUS nbt_add_socket(struct nbt_server *nbtsrv,
iface->netmask = talloc_steal(iface, netmask);
iface->names = NULL;
+ if (strcmp(netmask, "0.0.0.0") != 0) {
+ bcast_nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
+ NT_STATUS_HAVE_NO_MEMORY(iface->ip_address);
+
+ status = socket_listen(bcast_nbtsock->sock, bcast, lp_nbt_port(), 0, 0);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("Failed to bind to %s:%d - %s\n",
+ bcast, lp_nbt_port(), nt_errstr(status)));
+ talloc_free(iface);
+ return status;
+ }
+
+ nbt_set_incoming_handler(bcast_nbtsock, nbt_request_handler, iface);
+ }
+
iface->nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx);
NT_STATUS_HAVE_NO_MEMORY(iface->ip_address);
- status = socket_listen(iface->nbtsock->sock, bind_address, lp_nbt_port(), 0, 0);
+ status = socket_listen(iface->nbtsock->sock, address, lp_nbt_port(), 0, 0);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("Failed to bind to %s:%d - %s\n",
address, lp_nbt_port(), nt_errstr(status)));
@@ -114,8 +114,11 @@ static NTSTATUS nbt_add_socket(struct nbt_server *nbtsrv,
return status;
}
+ /* we need to be able to send broadcasts out */
socket_set_option(iface->nbtsock->sock, "SO_BROADCAST", "1");
+ nbt_set_incoming_handler(iface->nbtsock, nbt_request_handler, iface);
+
if (strcmp(netmask, "0.0.0.0") == 0) {
DLIST_ADD(nbtsrv->bcast_interface, iface);
} else {
@@ -135,29 +138,37 @@ NTSTATUS nbt_startup_interfaces(struct nbt_server *nbtsrv)
int i;
TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv);
NTSTATUS status;
- const char *primary_address;
- /* the primary address is the address we will return for non-WINS queries
- not made on a specific interface */
- if (num_interfaces > 0) {
- primary_address = talloc_strdup(tmp_ctx, sys_inet_ntoa(*iface_n_ip(0)));
- } else {
- primary_address = sys_inet_ntoa(interpret_addr2(lp_netbios_name()));
- }
+ /* if we are allowing incoming packets from any address, then
+ we also need to bind to the wildcard address */
+ if (!lp_bind_interfaces_only()) {
+ const char *primary_address;
+
+ /* the primary address is the address we will return
+ for non-WINS queries not made on a specific
+ interface */
+ if (num_interfaces > 0) {
+ primary_address = sys_inet_ntoa(*iface_n_ip(0));
+ } else {
+ primary_address = sys_inet_ntoa(interpret_addr2(
+ lp_netbios_name()));
+ }
+ primary_address = talloc_strdup(tmp_ctx, primary_address);
+ NT_STATUS_HAVE_NO_MEMORY(primary_address);
- status = nbt_add_socket(nbtsrv,
- "0.0.0.0",
- primary_address,
- talloc_strdup(tmp_ctx, "255.255.255.255"),
- talloc_strdup(tmp_ctx, "0.0.0.0"));
- NT_STATUS_NOT_OK_RETURN(status);
+ status = nbt_add_socket(nbtsrv,
+ primary_address,
+ talloc_strdup(tmp_ctx, "255.255.255.255"),
+ talloc_strdup(tmp_ctx, "0.0.0.0"));
+ NT_STATUS_NOT_OK_RETURN(status);
+ }
for (i=0; i<num_interfaces; i++) {
const char *address = talloc_strdup(tmp_ctx, sys_inet_ntoa(*iface_n_ip(i)));
const char *bcast = talloc_strdup(tmp_ctx, sys_inet_ntoa(*iface_n_bcast(i)));
const char *netmask = talloc_strdup(tmp_ctx, sys_inet_ntoa(*iface_n_netmask(i)));
- status = nbt_add_socket(nbtsrv, address, address, bcast, netmask);
+ status = nbt_add_socket(nbtsrv, address, bcast, netmask);
NT_STATUS_NOT_OK_RETURN(status);
}