nmbd_winsserver.c
来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 2,043 行 · 第 1/5 页
C
2,043 行
DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \to register name %s. Name already exists in WINS with source type %d.\n", nmb_namestr(question), namerec->data.source )); send_wins_name_registration_response(RFS_ERR, 0, p); return; } /* * Reject if the name exists and is a GROUP name and is active. */ if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec)) { DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \already exists in WINS as a GROUP name.\n", nmb_namestr(question) )); send_wins_name_registration_response(RFS_ERR, 0, p); return; } /* * From here on down we know that if the name exists in the WINS db it is * a unique name, not a group name. */ /* * If the name exists and is one of our names then check the * registering IP address. If it's not one of ours then automatically * reject without doing the query - we know we will reject it. */ if((namerec != NULL) && (is_myname(namerec->name.name)) ) { if(!ismyip(from_ip)) { DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) )); send_wins_name_registration_response(RFS_ERR, 0, p); return; } else { /* * It's one of our names and one of our IP's. Ensure the IP is in the record and * update the ttl. Update the version ID to force replication. */ update_name_ttl(namerec, ttl); if(!find_ip_in_name_record(namerec, from_ip)) { get_global_id_and_update(&namerec->data.id, True); update_wins_owner(namerec, our_fake_ip); update_wins_flag(namerec, WINS_ACTIVE); add_ip_to_name_record(namerec, from_ip); } wins_hook("refresh", namerec, ttl); send_wins_name_registration_response(0, ttl, p); return; } } /* * If the name exists and is active, check if the IP address is already registered * to that name. If so then update the ttl and reply success. */ if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec)) { update_name_ttl(namerec, ttl); /* * If it's a replica, we need to become the wins owner * to force the replication */ if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) { get_global_id_and_update(&namerec->data.id, True); update_wins_owner(namerec, our_fake_ip); update_wins_flag(namerec, WINS_ACTIVE); } wins_hook("refresh", namerec, ttl); send_wins_name_registration_response(0, ttl, p); return; } /* * If the name exists do a query to the owner * to see if they still want the name. */ if(namerec != NULL) { long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1]; struct userdata_struct *userdata = (struct userdata_struct *)ud; /* * First send a WACK to the registering machine. */ send_wins_wack_response(60, p); /* * When the reply comes back we need the original packet. * Lock this so it won't be freed and then put it into * the userdata structure. */ p->locked = True; userdata = (struct userdata_struct *)ud; userdata->copy_fn = NULL; userdata->free_fn = NULL; userdata->userdata_len = sizeof(struct packet_struct *); memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) ); /* * Use the new call to send a query directly to an IP address. * This sends the query directly to the IP address, and ensures * the recursion desired flag is not set (you were right Luke :-). * This function should *only* be called from the WINS server * code. JRA. * * Note that this packet is sent to the current owner of the name, * not the person who sent the packet */ pull_ascii_nstring( qname, sizeof(qname), question->name); query_name_from_wins_server( namerec->data.ip[0], qname, question->name_type, wins_multihomed_register_query_success, wins_multihomed_register_query_fail, userdata ); return; } /* * Name did not exist - add it. */ pull_ascii_nstring( qname, sizeof(qname), question->name); add_name_to_subnet( subrec, qname, question->name_type, nb_flags, ttl, REGISTER_NAME, 1, &from_ip); if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) { get_global_id_and_update(&namerec->data.id, True); update_wins_owner(namerec, our_fake_ip); update_wins_flag(namerec, WINS_ACTIVE); wins_hook("add", namerec, ttl); } send_wins_name_registration_response(0, ttl, p);}/*********************************************************************** Deal with the special name query for *<1b>.***********************************************************************/ static void process_wins_dmb_query_request(struct subnet_record *subrec, struct packet_struct *p){ struct name_record *namerec = NULL; char *prdata; int num_ips; /* * Go through all the ACTIVE names in the WINS db looking for those * ending in <1b>. Use this to calculate the number of IP * addresses we need to return. */ num_ips = 0; for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) { if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b ) num_ips += namerec->data.num_ips; } if(num_ips == 0) { /* * There are no 0x1b names registered. Return name query fail. */ send_wins_name_query_response(NAM_ERR, p, NULL); return; } if((prdata = (char *)SMB_MALLOC( num_ips * 6 )) == NULL) { DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n")); return; } /* * Go through all the names again in the WINS db looking for those * ending in <1b>. Add their IP addresses into the list we will * return. */ num_ips = 0; for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) { if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) { int i; for(i = 0; i < namerec->data.num_ips; i++) { set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags); putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]); num_ips++; } } } /* * Send back the reply containing the IP list. */ reply_netbios_packet(p, /* Packet to reply to. */ 0, /* Result code. */ WINS_QUERY, /* nmbd type code. */ NMB_NAME_QUERY_OPCODE, /* opcode. */ lp_min_wins_ttl(), /* ttl. */ prdata, /* data to send. */ num_ips*6); /* data length. */ SAFE_FREE(prdata);}/****************************************************************************Send a WINS name query response.**************************************************************************/void send_wins_name_query_response(int rcode, struct packet_struct *p, struct name_record *namerec){ char rdata[6]; char *prdata = rdata; int reply_data_len = 0; int ttl = 0; int i; memset(rdata,'\0',6); if(rcode == 0) { ttl = (namerec->data.death_time != PERMANENT_TTL) ? namerec->data.death_time - p->timestamp : lp_max_wins_ttl(); /* Copy all known ip addresses into the return data. */ /* Optimise for the common case of one IP address so we don't need a malloc. */ if( namerec->data.num_ips == 1 ) { prdata = rdata; } else { if((prdata = (char *)SMB_MALLOC( namerec->data.num_ips * 6 )) == NULL) { DEBUG(0,("send_wins_name_query_response: malloc fail !\n")); return; } } for(i = 0; i < namerec->data.num_ips; i++) { set_nb_flags(&prdata[i*6],namerec->data.nb_flags); putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]); } sort_query_replies(prdata, i, p->ip); reply_data_len = namerec->data.num_ips * 6; } reply_netbios_packet(p, /* Packet to reply to. */ rcode, /* Result code. */ WINS_QUERY, /* nmbd type code. */ NMB_NAME_QUERY_OPCODE, /* opcode. */ ttl, /* ttl. */ prdata, /* data to send. */ reply_data_len); /* data length. */ if(prdata != rdata) { SAFE_FREE(prdata); }}/*********************************************************************** Deal with a name query.***********************************************************************/void wins_process_name_query_request(struct subnet_record *subrec, struct packet_struct *p){ struct nmb_packet *nmb = &p->packet.nmb; struct nmb_name *question = &nmb->question.question_name; struct name_record *namerec = NULL; unstring qname; DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n", nmb_namestr(question), inet_ntoa(p->ip) )); /* * Special name code. If the queried name is *<1b> then search * the entire WINS database and return a list of all the IP addresses * registered to any <1b> name. This is to allow domain master browsers * to discover other domains that may not have a presence on their subnet. */ pull_ascii_nstring(qname, sizeof(qname), question->name); if(strequal( qname, "*") && (question->name_type == 0x1b)) { process_wins_dmb_query_request( subrec, p); return; } namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); if(namerec != NULL) { /* * If the name is not anymore in active state then reply not found. * it's fair even if we keep it in the cache for days. */ if (!WINS_STATE_ACTIVE(namerec)) { DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n", nmb_namestr(question) )); send_wins_name_query_response(NAM_ERR, p, namerec); return; } /* * If it's a DNSFAIL_NAME then reply name not found. */ if( namerec->data.source == DNSFAIL_NAME ) { DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n", nmb_namestr(question) )); send_wins_name_query_response(NAM_ERR, p, namerec); return; } /* * If the name has expired then reply name not found. */ if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < p->timestamp) ) { DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n", nmb_namestr(question) )); send_wins_name_query_response(NAM_ERR, p, namerec); return; } DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n", nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) )); send_wins_name_query_response(0, p, namerec); return; } /* * Name not found in WINS - try a dns query if it's a 0x20 name. */ if(lp_dns_proxy() && ((question->name_type == 0x20) || question->name_type == 0)) { DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n", nmb_namestr(question) )); queue_dns_query(p, question, &namerec); return; } /* * Name not found - return error. */ send_wins_name_query_response(NAM_ERR, p, NULL);}/****************************************************************************Send a WINS name release response.**************************************************************************/static void send_wins_name_release_response(int rcode, struct packet_struct *p){ struct nmb_packet *nmb = &p->packet.nmb; char rdata[6]; memcpy(&rdata[0], &nmb->additional->rdata[0], 6); reply_netbios_packet(p, /* Packet to reply to. */ rcode, /* Result code. */ NMB_REL, /* nmbd type code. */ NMB_NAME_RELEASE_OPCODE, /* opcode. */ 0, /* ttl. */ rdata, /* data to send. */ 6); /* data length. */}/*********************************************************************** Deal with a name release.***********************************************************************/void wins_process_name_release_request(struct subnet_record *subrec, struct packet_struct *p){ struct nmb_packet *nmb = &p->packet.nmb; struct nmb_name *question = &nmb->question.question_name; BOOL bcast = nmb->header.nm_flags.bcast; uint16 nb_flags = get_nb_flags(nmb->additional->rdata); struct name_record *namerec = NULL; struct in_addr from_ip; BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;; putip((char *)&from_ip,&nmb->additional->rdata[2]); if(bcast) { /* * We should only get unicast name registration packets here. * Anyone trying to register broadcast should not be going to a WINS * server. Log an error here. */ DEBUG(0,("wins_process_name_release_request: broadcast name registration request \received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?