/* return a count of the number of IPs for a particular tag, including dead ones */ unsigned wins_srv_count_tag(const char *tag) { const char **list; int i, count=0; /* if we are a wins server then we always just talk to ourselves */ if (lp_we_are_a_wins_server()) { return 1; } list = lp_wins_server_list(); if (!list || !list[0]) { return 0; } /* find the first live one for this tag */ for (i=0; list[i]; i++) { struct tagged_ip t_ip; parse_ip(&t_ip, list[i]); if (strcmp(tag, t_ip.tag) == 0) { count++; } } return count; }
/* register a name with our WINS servers */ void nbtd_winsclient_register(struct nbtd_iface_name *iname) { struct nbtd_interface *iface = iname->iface; struct nbt_name_register_wins io; struct composite_context *c; /* setup a wins name register request */ io.in.name = iname->name; io.in.wins_port = lp_nbt_port(iname->iface->nbtsrv->task->lp_ctx); io.in.wins_servers = lp_wins_server_list(iname->iface->nbtsrv->task->lp_ctx); io.in.addresses = nbtd_address_list(iface, iname); io.in.nb_flags = iname->nb_flags; io.in.ttl = iname->ttl; if (!io.in.addresses) { return; } c = nbt_name_register_wins_send(wins_socket(iface), &io); if (c == NULL) { talloc_free(io.in.addresses); return; } talloc_steal(c, io.in.addresses); c->async.fn = nbtd_wins_register_handler; c->async.private_data = iname; }
/* setup our listening sockets on the configured network interfaces */ NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv, struct loadparm_context *lp_ctx, struct interface *ifaces) { int num_interfaces = iface_count(ifaces); int i; TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv); NTSTATUS status; /* if we are allowing incoming packets from any address, then we also need to bind to the wildcard address */ if (!lp_bind_interfaces_only(lp_ctx)) { 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 = iface_n_ip(ifaces, 0); } else { primary_address = inet_ntoa(interpret_addr2( lp_netbios_name(lp_ctx))); } primary_address = talloc_strdup(tmp_ctx, primary_address); NT_STATUS_HAVE_NO_MEMORY(primary_address); status = nbtd_add_socket(nbtsrv, lp_ctx, "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); } for (i=0; i<num_interfaces; i++) { const char *bcast = iface_n_bcast(ifaces, i); const char *address, *netmask; /* we can't assume every interface is broadcast capable */ if (bcast == NULL) continue; address = talloc_strdup(tmp_ctx, iface_n_ip(ifaces, i)); bcast = talloc_strdup(tmp_ctx, bcast); netmask = talloc_strdup(tmp_ctx, iface_n_netmask(ifaces, i)); status = nbtd_add_socket(nbtsrv, lp_ctx, address, address, bcast, netmask); NT_STATUS_NOT_OK_RETURN(status); } if (lp_wins_server_list(lp_ctx)) { status = nbtd_add_wins_socket(nbtsrv); NT_STATUS_NOT_OK_RETURN(status); } talloc_free(tmp_ctx); return NT_STATUS_OK; }
/* return the IP of the currently active wins server for the given tag, or the zero IP otherwise */ struct in_addr wins_srv_ip_tag(const char *tag, struct in_addr src_ip) { const char **list; int i; struct tagged_ip t_ip; /* if we are a wins server then we always just talk to ourselves */ if (lp_we_are_a_wins_server()) { struct in_addr loopback_ip; loopback_ip.s_addr = htonl(INADDR_LOOPBACK); return loopback_ip; } list = lp_wins_server_list(); if (!list || !list[0]) { struct in_addr ip; zero_ip_v4(&ip); return ip; } /* find the first live one for this tag */ for (i=0; list[i]; i++) { parse_ip(&t_ip, list[i]); if (strcmp(tag, t_ip.tag) != 0) { /* not for the right tag. Move along */ continue; } if (!wins_srv_is_dead(t_ip.ip, src_ip)) { fstring src_name; fstrcpy(src_name, inet_ntoa(src_ip)); DEBUG(6,("Current wins server for tag '%s' with source %s is %s\n", tag, src_name, inet_ntoa(t_ip.ip))); return t_ip.ip; } } /* they're all dead - try the first one until they revive */ for (i=0; list[i]; i++) { parse_ip(&t_ip, list[i]); if (strcmp(tag, t_ip.tag) != 0) { continue; } return t_ip.ip; } /* this can't happen?? */ zero_ip_v4(&t_ip.ip); return t_ip.ip; }
static int do_global_checks(void) { int ret = 0; SMB_STRUCT_STAT st; if (lp_security() >= SEC_DOMAIN && !lp_encrypted_passwords()) { fprintf(stderr, "ERROR: in 'security=domain' mode the 'encrypt passwords' parameter must always be set to 'true'.\n"); ret = 1; } if (lp_wins_support() && lp_wins_server_list()) { fprintf(stderr, "ERROR: both 'wins support = true' and 'wins server = <server list>' \ cannot be set in the smb.conf file. nmbd will abort with this setting.\n"); ret = 1; }
/* return the total number of wins servers, dead or not */ unsigned wins_srv_count(void) { const char **list; int count = 0; if (lp_we_are_a_wins_server()) { /* simple - just talk to ourselves */ return 1; } list = lp_wins_server_list(); for (count=0; list && list[count]; count++) /* nop */ ; return count; }
bool wins_server_tag_ips(const char *tag, TALLOC_CTX *mem_ctx, struct in_addr **pservers, int *pnum_servers) { const char **list; int i, num_servers; struct in_addr *servers; list = lp_wins_server_list(); if ((list == NULL) || (list[0] == NULL)) { return false; } num_servers = 0; for (i=0; list[i] != NULL; i++) { struct tagged_ip t_ip; parse_ip(&t_ip, list[i]); if (strcmp(tag, t_ip.tag) == 0) { num_servers += 1; } } servers = talloc_array(mem_ctx, struct in_addr, num_servers); if (servers == NULL) { return false; } num_servers = 0; for (i=0; list[i] != NULL; i++) { struct tagged_ip t_ip; parse_ip(&t_ip, list[i]); if (strcmp(tag, t_ip.tag) == 0) { servers[num_servers] = t_ip.ip; num_servers += 1; } } *pnum_servers = num_servers; *pservers = servers; return true; }
static int do_global_checks(void) { int ret = 0; SMB_STRUCT_STAT st; const char *socket_options; if (lp_security() >= SEC_DOMAIN && !lp_encrypt_passwords()) { fprintf(stderr, "ERROR: in 'security=domain' mode the " "'encrypt passwords' parameter must always be " "set to 'true'.\n\n"); ret = 1; } if (lp_we_are_a_wins_server() && lp_wins_server_list()) { fprintf(stderr, "ERROR: both 'wins support = true' and " "'wins server = <server list>' cannot be set in " "the smb.conf file. nmbd will abort with this " "setting.\n\n"); ret = 1; } if (strequal(lp_workgroup(), lp_netbios_name())) { fprintf(stderr, "WARNING: 'workgroup' and 'netbios name' " "must differ.\n\n"); } if (!directory_exist_stat(lp_lock_directory(), &st)) { fprintf(stderr, "ERROR: lock directory %s does not exist\n\n", lp_lock_directory()); ret = 1; } else if ((st.st_ex_mode & 0777) != 0755) { fprintf(stderr, "WARNING: lock directory %s should have " "permissions 0755 for browsing to work\n\n", lp_lock_directory()); } if (!directory_exist_stat(lp_state_directory(), &st)) { fprintf(stderr, "ERROR: state directory %s does not exist\n\n", lp_state_directory()); ret = 1; } else if ((st.st_ex_mode & 0777) != 0755) { fprintf(stderr, "WARNING: state directory %s should have " "permissions 0755 for browsing to work\n\n", lp_state_directory()); } if (!directory_exist_stat(lp_cache_directory(), &st)) { fprintf(stderr, "ERROR: cache directory %s does not exist\n\n", lp_cache_directory()); ret = 1; } else if ((st.st_ex_mode & 0777) != 0755) { fprintf(stderr, "WARNING: cache directory %s should have " "permissions 0755 for browsing to work\n\n", lp_cache_directory()); } if (!directory_exist_stat(lp_pid_directory(), &st)) { fprintf(stderr, "ERROR: pid directory %s does not exist\n\n", lp_pid_directory()); ret = 1; } if (lp_passdb_expand_explicit()) { fprintf(stderr, "WARNING: passdb expand explicit = yes is " "deprecated\n\n"); } /* * Socket options. */ socket_options = lp_socket_options(); if (socket_options != NULL && (strstr(socket_options, "SO_SNDBUF") || strstr(socket_options, "SO_RCVBUF") || strstr(socket_options, "SO_SNDLOWAT") || strstr(socket_options, "SO_RCVLOWAT"))) { fprintf(stderr, "WARNING: socket options = %s\n" "This warning is printed because you set one of the\n" "following options: SO_SNDBUF, SO_RCVBUF, SO_SNDLOWAT,\n" "SO_RCVLOWAT\n" "Modern server operating systems are tuned for\n" "high network performance in the majority of situations;\n" "when you set 'socket options' you are overriding those\n" "settings.\n" "Linux in particular has an auto-tuning mechanism for\n" "buffer sizes (SO_SNDBUF, SO_RCVBUF) that will be\n" "disabled if you specify a socket buffer size. This can\n" "potentially cripple your TCP/IP stack.\n\n" "Getting the 'socket options' correct can make a big\n" "difference to your performance, but getting them wrong\n" "can degrade it by just as much. As with any other low\n" "level setting, if you must make changes to it, make\n " "small changes and test the effect before making any\n" "large changes.\n\n", socket_options); } /* * Password server sanity checks. */ if((lp_security() >= SEC_DOMAIN) && !*lp_password_server()) { const char *sec_setting; if(lp_security() == SEC_DOMAIN) sec_setting = "domain"; else if(lp_security() == SEC_ADS) sec_setting = "ads"; else sec_setting = ""; fprintf(stderr, "ERROR: The setting 'security=%s' requires the " "'password server' parameter be set to the " "default value * or a valid password server.\n\n", sec_setting ); ret = 1; } if((lp_security() >= SEC_DOMAIN) && (strcmp(lp_password_server(), "*") != 0)) { const char *sec_setting; if(lp_security() == SEC_DOMAIN) sec_setting = "domain"; else if(lp_security() == SEC_ADS) sec_setting = "ads"; else sec_setting = ""; fprintf(stderr, "WARNING: The setting 'security=%s' should NOT " "be combined with the 'password server' " "parameter.\n" "(by default Samba will discover the correct DC " "to contact automatically).\n\n", sec_setting ); } /* * Password chat sanity checks. */ if(lp_security() == SEC_USER && lp_unix_password_sync()) { /* * Check that we have a valid lp_passwd_program() if not using pam. */ #ifdef WITH_PAM if (!lp_pam_password_change()) { #endif if((lp_passwd_program(talloc_tos()) == NULL) || (strlen(lp_passwd_program(talloc_tos())) == 0)) { fprintf(stderr, "ERROR: the 'unix password sync' " "parameter is set and there is no valid " "'passwd program' parameter.\n\n"); ret = 1; } else { const char *passwd_prog; char *truncated_prog = NULL; const char *p; passwd_prog = lp_passwd_program(talloc_tos()); p = passwd_prog; next_token_talloc(talloc_tos(), &p, &truncated_prog, NULL); if (truncated_prog && access(truncated_prog, F_OK) == -1) { fprintf(stderr, "ERROR: the 'unix password sync' " "parameter is set and the " "'passwd program' (%s) cannot be " "executed (error was %s).\n\n", truncated_prog, strerror(errno)); ret = 1; } } #ifdef WITH_PAM } #endif if(lp_passwd_chat(talloc_tos()) == NULL) { fprintf(stderr, "ERROR: the 'unix password sync' parameter is " "set and there is no valid 'passwd chat' " "parameter.\n\n"); ret = 1; } if ((lp_passwd_program(talloc_tos()) != NULL) && (strlen(lp_passwd_program(talloc_tos())) > 0)) { /* check if there's a %u parameter present */ if(strstr_m(lp_passwd_program(talloc_tos()), "%u") == NULL) { fprintf(stderr, "ERROR: the 'passwd program' (%s) " "requires a '%%u' parameter.\n\n", lp_passwd_program(talloc_tos())); ret = 1; } } /* * Check that we have a valid script and that it hasn't * been written to expect the old password. */ if(lp_encrypt_passwords()) { if(strstr_m( lp_passwd_chat(talloc_tos()), "%o")!=NULL) { fprintf(stderr, "ERROR: the 'passwd chat' script [%s] " "expects to use the old plaintext " "password via the %%o substitution. With " "encrypted passwords this is not " "possible.\n\n", lp_passwd_chat(talloc_tos()) ); ret = 1; } } } if (strlen(lp_winbind_separator()) != 1) { fprintf(stderr, "ERROR: the 'winbind separator' parameter must " "be a single character.\n\n"); ret = 1; } if (*lp_winbind_separator() == '+') { fprintf(stderr, "'winbind separator = +' might cause problems " "with group membership.\n\n"); } if (lp_algorithmic_rid_base() < BASE_RID) { /* Try to prevent admin foot-shooting, we can't put algorithmic rids below 1000, that's the 'well known RIDs' on NT */ fprintf(stderr, "'algorithmic rid base' must be equal to or " "above %lu\n\n", BASE_RID); } if (lp_algorithmic_rid_base() & 1) { fprintf(stderr, "'algorithmic rid base' must be even.\n\n"); } #ifndef HAVE_DLOPEN if (lp_preload_modules()) { fprintf(stderr, "WARNING: 'preload modules = ' set while loading " "plugins not supported.\n\n"); } #endif if (!lp_passdb_backend()) { fprintf(stderr, "ERROR: passdb backend must have a value or be " "left out\n\n"); } if (lp_os_level() > 255) { fprintf(stderr, "WARNING: Maximum value for 'os level' is " "255!\n\n"); } if (strequal(lp_dos_charset(), "UTF8") || strequal(lp_dos_charset(), "UTF-8")) { fprintf(stderr, "ERROR: 'dos charset' must not be UTF8\n\n"); ret = 1; } return ret; }