nmbd_winsserver.c
来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 2,043 行 · 第 1/5 页
C
2,043 行
/* Unix SMB/CIFS implementation. NBT netbios routines and daemon - version 2 Copyright (C) Jeremy Allison 1994-2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "includes.h"#define WINS_LIST "wins.dat"#define WINS_VERSION 1/**************************************************************************** Change the wins owner address in the record.*****************************************************************************/static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip){ if (namerec==NULL) return; namerec->data.wins_ip=wins_ip;}/**************************************************************************** Create the wins flags based on the nb flags and the input value.*****************************************************************************/static void update_wins_flag(struct name_record *namerec, int flags){ if (namerec==NULL) return; namerec->data.wins_flags=0x0; /* if it's a group, it can be a normal or a special one */ if (namerec->data.nb_flags & NB_GROUP) { if (namerec->name.name_type==0x1C) { namerec->data.wins_flags|=WINS_SGROUP; } else { if (namerec->data.num_ips>1) { namerec->data.wins_flags|=WINS_SGROUP; } else { namerec->data.wins_flags|=WINS_NGROUP; } } } else { /* can be unique or multi-homed */ if (namerec->data.num_ips>1) { namerec->data.wins_flags|=WINS_MHOMED; } else { namerec->data.wins_flags|=WINS_UNIQUE; } } /* the node type are the same bits */ namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK; /* the static bit is elsewhere */ if (namerec->data.death_time == PERMANENT_TTL) { namerec->data.wins_flags|=WINS_STATIC; } /* and add the given bits */ namerec->data.wins_flags|=flags; DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: 0x%d, flags: 0x%x, winsflags: 0x%x\n", namerec->data.nb_flags, (int)namerec->data.death_time, flags, namerec->data.wins_flags));}/**************************************************************************** Return the general ID value and increase it if requested.*****************************************************************************/static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update){ /* * it's kept as a static here, to prevent people from messing * with the value directly */ static SMB_BIG_UINT general_id = 1; DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id)); *current_id = general_id; if (update) { general_id++; }}/**************************************************************************** Possibly call the WINS hook external program when a WINS change is made.*****************************************************************************/static void wins_hook(const char *operation, struct name_record *namerec, int ttl){ pstring command; char *cmd = lp_wins_hook(); char *p, *namestr; int i; if (!cmd || !*cmd) return; for (p=namerec->name.name; *p; p++) { if (!(isalnum((int)*p) || strchr_m("._-",*p))) { DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name))); return; } } /* Use the name without the nametype (and scope) appended */ namestr = nmb_namestr(&namerec->name); if ((p = strchr(namestr, '<'))) { *p = 0; } p = command; p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d", cmd, operation, namestr, namerec->name.name_type, ttl); for (i=0;i<namerec->data.num_ips;i++) { p += slprintf(p, sizeof(command) - (p-command) -1, " %s", inet_ntoa(namerec->data.ip[i])); } DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name))); smbrun(command, NULL);}/****************************************************************************Determine if this packet should be allocated to the WINS server.*****************************************************************************/BOOL packet_is_for_wins_server(struct packet_struct *packet){ struct nmb_packet *nmb = &packet->packet.nmb; /* Only unicast packets go to a WINS server. */ if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True)) { DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n")); return False; } /* Check for node status requests. */ if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY) { return False; } switch(nmb->header.opcode) { /* * A WINS server issues WACKS, not receives them. */ case NMB_WACK_OPCODE: DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n")); return False; /* * A WINS server only processes registration and * release requests, not responses. */ case NMB_NAME_REG_OPCODE: case NMB_NAME_MULTIHOMED_REG_OPCODE: case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */ case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */ if(nmb->header.response) { DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n")); return False; } break; case NMB_NAME_RELEASE_OPCODE: if(nmb->header.response) { DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n")); return False; } break; /* * Only process unicast name queries with rd = 1. */ case NMB_NAME_QUERY_OPCODE: if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired) { DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n")); return False; } break; } return True;}/****************************************************************************Utility function to decide what ttl to give a register/refresh request.*****************************************************************************/static int get_ttl_from_packet(struct nmb_packet *nmb){ int ttl = nmb->additional->ttl; if (ttl < lp_min_wins_ttl()) { ttl = lp_min_wins_ttl(); } if (ttl > lp_max_wins_ttl()) { ttl = lp_max_wins_ttl(); } return ttl;}/****************************************************************************Load or create the WINS database.*****************************************************************************/BOOL initialise_wins(void){ time_t time_now = time(NULL); XFILE *fp; pstring line; if(!lp_we_are_a_wins_server()) { return True; } add_samba_names_to_subnet(wins_server_subnet); if((fp = x_fopen(lock_path(WINS_LIST),O_RDONLY,0)) == NULL) { DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n", WINS_LIST, strerror(errno) )); return True; } while (!x_feof(fp)) { pstring name_str, ip_str, ttl_str, nb_flags_str; unsigned int num_ips; pstring name; struct in_addr *ip_list; int type = 0; int nb_flags; int ttl; const char *ptr; char *p; BOOL got_token; BOOL was_ip; int i; unsigned int hash; int version; /* Read a line from the wins.dat file. Strips whitespace from the beginning and end of the line. */ if (!fgets_slash(line,sizeof(pstring),fp)) continue; if (*line == '#') continue; if (strncmp(line,"VERSION ", 8) == 0) { if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 || version != WINS_VERSION) { DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line)); x_fclose(fp); return True; } continue; } ptr = line; /* * Now we handle multiple IP addresses per name we need * to iterate over the line twice. The first time to * determine how many IP addresses there are, the second * time to actually parse them into the ip_list array. */ if (!next_token(&ptr,name_str,NULL,sizeof(name_str))) { DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line )); continue; } if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str))) { DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line )); continue; } /* * Determine the number of IP addresses per line. */ num_ips = 0; do { got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str)); was_ip = False; if(got_token && strchr(ip_str, '.')) { num_ips++; was_ip = True; } } while( got_token && was_ip); if(num_ips == 0) { DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line )); continue; } if(!got_token) { DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line )); continue; } /* Allocate the space for the ip_list. */ if((ip_list = SMB_MALLOC_ARRAY( struct in_addr, num_ips)) == NULL) { DEBUG(0,("initialise_wins: Malloc fail !\n")); return False; } /* Reset and re-parse the line. */ ptr = line; next_token(&ptr,name_str,NULL,sizeof(name_str)); next_token(&ptr,ttl_str,NULL,sizeof(ttl_str)); for(i = 0; i < num_ips; i++) { next_token(&ptr, ip_str, NULL, sizeof(ip_str)); ip_list[i] = *interpret_addr2(ip_str); } next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str)); /* * Deal with SELF or REGISTER name encoding. Default is REGISTER * for compatibility with old nmbds. */ if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') { DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line)); SAFE_FREE(ip_list); continue; } if(nb_flags_str[strlen(nb_flags_str)-1] == 'R') { nb_flags_str[strlen(nb_flags_str)-1] = '\0'; } /* Netbios name. # divides the name from the type (hex): netbios#xx */ pstrcpy(name,name_str); if((p = strchr(name,'#')) != NULL) { *p = 0; sscanf(p+1,"%x",&type); } /* Decode the netbios flags (hex) and the time-to-live (in seconds). */ sscanf(nb_flags_str,"%x",&nb_flags); sscanf(ttl_str,"%d",&ttl); /* add all entries that have 60 seconds or more to live */ if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) { if(ttl != PERMANENT_TTL) { ttl -= time_now; } DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n", name, type, ttl, inet_ntoa(ip_list[0]), nb_flags)); (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags, ttl, REGISTER_NAME, num_ips, ip_list ); } else { DEBUG(4, ("initialise_wins: not adding name (ttl problem) " "%s#%02x ttl = %d first IP %s flags = %2x\n", name, type, ttl, inet_ntoa(ip_list[0]), nb_flags)); } SAFE_FREE(ip_list); } x_fclose(fp); return True;}/****************************************************************************Send a WINS WACK (Wait ACKnowledgement) response.**************************************************************************/static void send_wins_wack_response(int ttl, struct packet_struct *p){ struct nmb_packet *nmb = &p->packet.nmb; unsigned char rdata[2]; rdata[0] = rdata[1] = 0; /* Taken from nmblib.c - we need to send back almost identical bytes from the requesting packet header. */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?