1/* 2 Unix SMB/CIFS implementation. 3 4 NBT interface handling 5 6 Copyright (C) Andrew Tridgell 2005 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20*/ 21 22#include "includes.h" 23#include "../lib/util/dlinklist.h" 24#include "nbt_server/nbt_server.h" 25#include "smbd/service_task.h" 26#include "lib/socket/socket.h" 27#include "nbt_server/wins/winsserver.h" 28#include "nbt_server/dgram/proto.h" 29#include "system/network.h" 30#include "lib/socket/netif.h" 31#include "param/param.h" 32 33 34/* 35 receive an incoming request and dispatch it to the right place 36*/ 37static void nbtd_request_handler(struct nbt_name_socket *nbtsock, 38 struct nbt_name_packet *packet, 39 struct socket_address *src) 40{ 41 struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, 42 struct nbtd_interface); 43 struct nbtd_server *nbtsrv = iface->nbtsrv; 44 45 nbtsrv->stats.total_received++; 46 47 /* see if its from one of our own interfaces - if so, then ignore it */ 48 if (nbtd_self_packet_and_bcast(nbtsock, packet, src)) { 49 DEBUG(10,("Ignoring bcast self packet from %s:%d\n", src->addr, src->port)); 50 return; 51 } 52 53 switch (packet->operation & NBT_OPCODE) { 54 case NBT_OPCODE_QUERY: 55 nbtsrv->stats.query_count++; 56 nbtd_request_query(nbtsock, packet, src); 57 break; 58 59 case NBT_OPCODE_REGISTER: 60 case NBT_OPCODE_REFRESH: 61 case NBT_OPCODE_REFRESH2: 62 nbtsrv->stats.register_count++; 63 nbtd_request_defense(nbtsock, packet, src); 64 break; 65 66 case NBT_OPCODE_RELEASE: 67 case NBT_OPCODE_MULTI_HOME_REG: 68 nbtsrv->stats.release_count++; 69 nbtd_winsserver_request(nbtsock, packet, src); 70 break; 71 72 default: 73 nbtd_bad_packet(packet, src, "Unexpected opcode"); 74 break; 75 } 76} 77 78static void nbtd_unexpected_handler(struct nbt_name_socket *nbtsock, 79 struct nbt_name_packet *packet, 80 struct socket_address *src) 81{ 82 struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, 83 struct nbtd_interface); 84 struct nbtd_server *nbtsrv = iface->nbtsrv; 85 struct nbtd_interface *i; 86 struct nbt_name_request *req = NULL; 87 88 nbtsrv->stats.total_received++; 89 90 DEBUG(10,("unexpected from src[%s] on interface[%p] %s/%s\n", 91 src->addr, iface, iface->ip_address, iface->netmask)); 92 93 /* try the broadcast interface */ 94 if (nbtsrv->bcast_interface) { 95 i = nbtsrv->bcast_interface; 96 req = idr_find(i->nbtsock->idr, packet->name_trn_id); 97 } 98 99 /* try the wins server client interface */ 100 if (!req && nbtsrv->wins_interface && nbtsrv->wins_interface->nbtsock) { 101 i = nbtsrv->wins_interface; 102 req = idr_find(i->nbtsock->idr, packet->name_trn_id); 103 } 104 105 /* try all other interfaces... */ 106 if (!req) { 107 for (i = nbtsrv->interfaces; i; i = i->next) { 108 if (i == iface) { 109 continue; 110 } 111 req = idr_find(i->nbtsock->idr, packet->name_trn_id); 112 if (req) break; 113 } 114 } 115 116 if (!req) { 117 DEBUG(10,("unexpected from src[%s] unable to redirected\n", src->addr)); 118 return; 119 } 120 121 DEBUG(10,("unexpected from src[%s] redirected to interface[%p] %s/%s\n", 122 src->addr, i, i->ip_address, i->netmask)); 123 124 /* 125 * redirect the incoming response to the socket 126 * we sent the matching request 127 */ 128 nbt_name_socket_handle_response_packet(req, packet, src); 129} 130 131/* 132 find a registered name on an interface 133*/ 134struct nbtd_iface_name *nbtd_find_iname(struct nbtd_interface *iface, 135 struct nbt_name *name, 136 uint16_t nb_flags) 137{ 138 struct nbtd_iface_name *iname; 139 for (iname=iface->names;iname;iname=iname->next) { 140 if (iname->name.type == name->type && 141 strcmp(name->name, iname->name.name) == 0 && 142 ((iname->nb_flags & nb_flags) == nb_flags)) { 143 return iname; 144 } 145 } 146 return NULL; 147} 148 149/* 150 start listening on the given address 151*/ 152static NTSTATUS nbtd_add_socket(struct nbtd_server *nbtsrv, 153 struct loadparm_context *lp_ctx, 154 const char *bind_address, 155 const char *address, 156 const char *bcast, 157 const char *netmask) 158{ 159 struct nbtd_interface *iface; 160 NTSTATUS status; 161 struct socket_address *bcast_address; 162 struct socket_address *unicast_address; 163 164 DEBUG(6,("nbtd_add_socket(%s, %s, %s, %s)\n", bind_address, address, bcast, netmask)); 165 166 /* 167 we actually create two sockets. One listens on the broadcast address 168 for the interface, and the other listens on our specific address. This 169 allows us to run with "bind interfaces only" while still receiving 170 broadcast addresses, and also simplifies matching incoming requests 171 to interfaces 172 */ 173 174 iface = talloc(nbtsrv, struct nbtd_interface); 175 NT_STATUS_HAVE_NO_MEMORY(iface); 176 177 iface->nbtsrv = nbtsrv; 178 iface->bcast_address = talloc_steal(iface, bcast); 179 iface->ip_address = talloc_steal(iface, address); 180 iface->netmask = talloc_steal(iface, netmask); 181 iface->names = NULL; 182 iface->wack_queue = NULL; 183 184 if (strcmp(netmask, "0.0.0.0") != 0) { 185 struct nbt_name_socket *bcast_nbtsock; 186 187 /* listen for broadcasts on port 137 */ 188 bcast_nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx, lp_iconv_convenience(nbtsrv->task->lp_ctx)); 189 if (!bcast_nbtsock) { 190 talloc_free(iface); 191 return NT_STATUS_NO_MEMORY; 192 } 193 194 bcast_address = socket_address_from_strings(bcast_nbtsock, bcast_nbtsock->sock->backend_name, 195 bcast, lp_nbt_port(lp_ctx)); 196 if (!bcast_address) { 197 talloc_free(iface); 198 return NT_STATUS_NO_MEMORY; 199 } 200 201 status = socket_listen(bcast_nbtsock->sock, bcast_address, 0, 0); 202 if (!NT_STATUS_IS_OK(status)) { 203 DEBUG(0,("Failed to bind to %s:%d - %s\n", 204 bcast, lp_nbt_port(lp_ctx), nt_errstr(status))); 205 talloc_free(iface); 206 return status; 207 } 208 talloc_free(bcast_address); 209 210 nbt_set_incoming_handler(bcast_nbtsock, nbtd_request_handler, iface); 211 } 212 213 /* listen for unicasts on port 137 */ 214 iface->nbtsock = nbt_name_socket_init(iface, nbtsrv->task->event_ctx, 215 lp_iconv_convenience(nbtsrv->task->lp_ctx)); 216 if (!iface->nbtsock) { 217 talloc_free(iface); 218 return NT_STATUS_NO_MEMORY; 219 } 220 221 unicast_address = socket_address_from_strings(iface->nbtsock, 222 iface->nbtsock->sock->backend_name, 223 bind_address, lp_nbt_port(lp_ctx)); 224 225 status = socket_listen(iface->nbtsock->sock, unicast_address, 0, 0); 226 if (!NT_STATUS_IS_OK(status)) { 227 DEBUG(0,("Failed to bind to %s:%d - %s\n", 228 bind_address, lp_nbt_port(lp_ctx), nt_errstr(status))); 229 talloc_free(iface); 230 return status; 231 } 232 talloc_free(unicast_address); 233 234 nbt_set_incoming_handler(iface->nbtsock, nbtd_request_handler, iface); 235 nbt_set_unexpected_handler(iface->nbtsock, nbtd_unexpected_handler, iface); 236 237 /* also setup the datagram listeners */ 238 status = nbtd_dgram_setup(iface, bind_address); 239 if (!NT_STATUS_IS_OK(status)) { 240 DEBUG(0,("Failed to setup dgram listen on %s - %s\n", 241 bind_address, nt_errstr(status))); 242 talloc_free(iface); 243 return status; 244 } 245 246 if (strcmp(netmask, "0.0.0.0") == 0) { 247 DLIST_ADD(nbtsrv->bcast_interface, iface); 248 } else { 249 DLIST_ADD(nbtsrv->interfaces, iface); 250 } 251 252 return NT_STATUS_OK; 253} 254 255/* 256 setup a socket for talking to our WINS servers 257*/ 258static NTSTATUS nbtd_add_wins_socket(struct nbtd_server *nbtsrv) 259{ 260 struct nbtd_interface *iface; 261 262 iface = talloc_zero(nbtsrv, struct nbtd_interface); 263 NT_STATUS_HAVE_NO_MEMORY(iface); 264 265 iface->nbtsrv = nbtsrv; 266 267 DLIST_ADD(nbtsrv->wins_interface, iface); 268 269 return NT_STATUS_OK; 270} 271 272 273/* 274 setup our listening sockets on the configured network interfaces 275*/ 276NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv, struct loadparm_context *lp_ctx, 277 struct interface *ifaces) 278{ 279 int num_interfaces = iface_count(ifaces); 280 int i; 281 TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv); 282 NTSTATUS status; 283 284 /* if we are allowing incoming packets from any address, then 285 we also need to bind to the wildcard address */ 286 if (!lp_bind_interfaces_only(lp_ctx)) { 287 const char *primary_address; 288 289 /* the primary address is the address we will return 290 for non-WINS queries not made on a specific 291 interface */ 292 if (num_interfaces > 0) { 293 primary_address = iface_n_ip(ifaces, 0); 294 } else { 295 primary_address = inet_ntoa(interpret_addr2( 296 lp_netbios_name(lp_ctx))); 297 } 298 primary_address = talloc_strdup(tmp_ctx, primary_address); 299 NT_STATUS_HAVE_NO_MEMORY(primary_address); 300 301 status = nbtd_add_socket(nbtsrv, 302 lp_ctx, 303 "0.0.0.0", 304 primary_address, 305 talloc_strdup(tmp_ctx, "255.255.255.255"), 306 talloc_strdup(tmp_ctx, "0.0.0.0")); 307 NT_STATUS_NOT_OK_RETURN(status); 308 } 309 310 for (i=0; i<num_interfaces; i++) { 311 const char *bcast = iface_n_bcast(ifaces, i); 312 const char *address, *netmask; 313 314 /* we can't assume every interface is broadcast capable */ 315 if (bcast == NULL) continue; 316 317 address = talloc_strdup(tmp_ctx, iface_n_ip(ifaces, i)); 318 bcast = talloc_strdup(tmp_ctx, bcast); 319 netmask = talloc_strdup(tmp_ctx, iface_n_netmask(ifaces, i)); 320 321 status = nbtd_add_socket(nbtsrv, lp_ctx, 322 address, address, bcast, netmask); 323 NT_STATUS_NOT_OK_RETURN(status); 324 } 325 326 if (lp_wins_server_list(lp_ctx)) { 327 status = nbtd_add_wins_socket(nbtsrv); 328 NT_STATUS_NOT_OK_RETURN(status); 329 } 330 331 talloc_free(tmp_ctx); 332 333 return NT_STATUS_OK; 334} 335 336 337/* 338 form a list of addresses that we should use in name query replies 339 we always place the IP in the given interface first 340*/ 341const char **nbtd_address_list(struct nbtd_interface *iface, TALLOC_CTX *mem_ctx) 342{ 343 struct nbtd_server *nbtsrv = iface->nbtsrv; 344 const char **ret = NULL; 345 struct nbtd_interface *iface2; 346 bool is_loopback = false; 347 348 if (iface->ip_address) { 349 is_loopback = iface_same_net(iface->ip_address, "127.0.0.1", "255.0.0.0"); 350 ret = str_list_add(ret, iface->ip_address); 351 } 352 353 for (iface2=nbtsrv->interfaces;iface2;iface2=iface2->next) { 354 if (iface2 == iface) continue; 355 356 if (!iface2->ip_address) continue; 357 358 if (!is_loopback) { 359 if (iface_same_net(iface2->ip_address, "127.0.0.1", "255.0.0.0")) { 360 continue; 361 } 362 } 363 364 ret = str_list_add(ret, iface2->ip_address); 365 } 366 367 talloc_steal(mem_ctx, ret); 368 369 return ret; 370} 371 372 373/* 374 find the interface to use for sending a outgoing request 375*/ 376struct nbtd_interface *nbtd_find_request_iface(struct nbtd_server *nbtd_server, 377 const char *address, bool allow_bcast_iface) 378{ 379 struct nbtd_interface *cur; 380 381 /* try to find a exact match */ 382 for (cur=nbtd_server->interfaces;cur;cur=cur->next) { 383 if (iface_same_net(address, cur->ip_address, cur->netmask)) { 384 DEBUG(10,("find interface for dst[%s] ip: %s/%s (iface[%p])\n", 385 address, cur->ip_address, cur->netmask, cur)); 386 return cur; 387 } 388 } 389 390 /* no exact match, if we have the broadcast interface, use that */ 391 if (allow_bcast_iface && nbtd_server->bcast_interface) { 392 cur = nbtd_server->bcast_interface; 393 DEBUG(10,("find interface for dst[%s] ip: %s/%s (bcast iface[%p])\n", 394 address, cur->ip_address, cur->netmask, cur)); 395 return cur; 396 } 397 398 /* fallback to first interface */ 399 cur = nbtd_server->interfaces; 400 DEBUG(10,("find interface for dst[%s] ip: %s/%s (default iface[%p])\n", 401 address, cur->ip_address, cur->netmask, cur)); 402 return cur; 403} 404 405/* 406 * find the interface to use for sending a outgoing reply 407 */ 408struct nbtd_interface *nbtd_find_reply_iface(struct nbtd_interface *iface, 409 const char *address, bool allow_bcast_iface) 410{ 411 struct nbtd_server *nbtd_server = iface->nbtsrv; 412 413 /* first try to use the given interfacel when it's not the broadcast one */ 414 if (iface != nbtd_server->bcast_interface) { 415 return iface; 416 } 417 418 return nbtd_find_request_iface(nbtd_server, address, allow_bcast_iface); 419} 420