nmbd_winsserver.c
来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 2,043 行 · 第 1/5 页
C
2,043 行
*/ if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) { DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \a dns lookup - removing it.\n", nmb_namestr(question) )); remove_name_from_namelist( subrec, namerec ); namerec = NULL; } /* * Reject if the name exists and is not a REGISTER_NAME. * (ie. Don't allow any static names to be overwritten. */ if((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) { DEBUG( 3, ( "wins_process_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; } /* * Special policy decisions based on MS documentation. * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255. * 2). All unique names ending in 0x1d are ignored, although a positive response is sent. */ /* * A group name is always added as the local broadcast address, except * for group names ending in 0x1c. * Group names with type 0x1c are registered with individual IP addresses. */ if(registering_group_name && (question->name_type != 0x1c)) { from_ip = *interpret_addr2("255.255.255.255"); } /* * Ignore all attempts to register a unique 0x1d name, although return success. */ if(!registering_group_name && (question->name_type == 0x1d)) { DEBUG(3,("wins_process_name_registration_request: Ignoring request \to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) )); send_wins_name_registration_response(0, ttl, p); return; } /* * Next two cases are the 'if statement' mentioned above. */ if((namerec != NULL) && NAME_GROUP(namerec)) { if(registering_group_name) { /* * If we are adding a group name, the name exists and is also a group entry just add this * IP address to it and update the ttl. */ DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n", inet_ntoa(from_ip), nmb_namestr(question) )); /* * Check the ip address is not already in the group. */ if(!find_ip_in_name_record(namerec, from_ip)) { add_ip_to_name_record(namerec, from_ip); /* we need to update the record for replication */ get_global_id_and_update(&namerec->data.id, True); /* * if the record is a replica, we must change * the wins owner to us to make the replication updates * it on the other wins servers. * And when the partner will receive this record, * it will update its own record. */ update_wins_owner(namerec, our_fake_ip); } update_name_ttl(namerec, ttl); wins_hook("refresh", namerec, ttl); send_wins_name_registration_response(0, ttl, p); return; } else { /* * If we are adding a unique name, the name exists in the WINS db * and is a group name then reject the registration. * * explanation: groups have a higher priority than unique names. */ DEBUG(3,("wins_process_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 ) { pull_ascii_nstring(name, sizeof(name), namerec->name.name); } else { name[0] = '\0'; } if( is_myname(name) ) { if(!ismyip(from_ip)) { DEBUG(3,("wins_process_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 - update the ttl. */ update_name_ttl(namerec, ttl); wins_hook("refresh", namerec, ttl); send_wins_name_registration_response(0, ttl, p); return; } } /* * If the name exists and it is a unique registration and the registering IP * is the same as the (single) already registered IP then just update the ttl. * * But not if the record is an active replica. IF it's a replica, it means it can be * the same client which has moved and not yet expired. So we don't update * the ttl in this case and go beyond to do a WACK and query the old client */ if( !registering_group_name && (namerec != NULL) && (namerec->data.num_ips == 1) && ip_equal( namerec->data.ip[0], from_ip ) && ip_equal(namerec->data.wins_ip, our_fake_ip) ) { update_name_ttl( namerec, ttl ); wins_hook("refresh", namerec, ttl); send_wins_name_registration_response( 0, ttl, p ); return; } /* * Finally if the name exists do a query to the registering machine * to see if they still claim to have 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. */ pull_ascii_nstring(name, sizeof(name), question->name); query_name_from_wins_server( *namerec->data.ip, name, question->name_type, wins_register_query_success, wins_register_query_fail, userdata ); return; } /* * Name did not exist - add it. */ pull_ascii_nstring(name, sizeof(name), question->name); add_name_to_subnet( subrec, name, 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 a mutihomed name query success to the machine that requested the multihomed name registration. We have a locked pointer to the original packet stashed away in the userdata pointer.************************************************************************/static void wins_multihomed_register_query_success(struct subnet_record *subrec, struct userdata_struct *userdata, struct nmb_name *question_name, struct in_addr ip, struct res_rec *answers){ struct packet_struct *orig_reg_packet; struct nmb_packet *nmb; struct name_record *namerec = NULL; struct in_addr from_ip; int ttl; struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); nmb = &orig_reg_packet->packet.nmb; putip((char *)&from_ip,&nmb->additional->rdata[2]); ttl = get_ttl_from_packet(nmb); /* * We want to just add the new IP, as we now know the requesting * machine claims to own it. But we can't just do that as an arbitary * amount of time may have taken place between the name query * request and this response. So we check that * the name still exists and is in the same state - if so * we just add the extra IP and update the ttl. */ namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME); if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) ) { DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \a subsequent IP address.\n", nmb_namestr(question_name) )); send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); orig_reg_packet->locked = False; free_packet(orig_reg_packet); return; } if(!find_ip_in_name_record(namerec, from_ip)) { add_ip_to_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); update_name_ttl(namerec, ttl); wins_hook("add", namerec, ttl); send_wins_name_registration_response(0, ttl, orig_reg_packet); orig_reg_packet->locked = False; free_packet(orig_reg_packet);}/*********************************************************************** Deal with a name registration request query failure to a client that owned the name. We have a locked pointer to the original packet stashed away in the userdata pointer.************************************************************************/static void wins_multihomed_register_query_fail(struct subnet_record *subrec, struct response_record *rrec, struct nmb_name *question_name, int rcode){ struct userdata_struct *userdata = rrec->userdata; struct packet_struct *orig_reg_packet; memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) )); send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); orig_reg_packet->locked = False; free_packet(orig_reg_packet); return;}/*********************************************************************** Deal with a multihomed name registration request to a WINS server. These cannot be group name registrations.***********************************************************************/void wins_process_multihomed_name_registration_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); int ttl = get_ttl_from_packet(nmb); struct name_record *namerec = NULL; struct in_addr from_ip; BOOL group = (nb_flags & NB_GROUP) ? True : False; struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); unstring qname; 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_multihomed_name_registration_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)); return; } /* * Only unique names should be registered multihomed. */ if(group) { DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); return; } DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) )); /* * Deal with policy regarding 0x1d names. */ if(question->name_type == 0x1d) { DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) )); send_wins_name_registration_response(0, ttl, p); return; } /* * See if the name already exists. */ namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); /* * if the record exists but NOT in active state, * consider it dead. */ if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) { DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question))); remove_name_from_namelist(subrec, namerec); namerec = NULL; } /* * Deal with the case where the name found was a dns entry. * Remove it as we now have a NetBIOS client registering the * name. */ if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) { DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \- removing it.\n", nmb_namestr(question) )); remove_name_from_namelist( subrec, namerec); namerec = NULL; } /* * Reject if the name exists and is not a REGISTER_NAME. * (ie. Don't allow any static names to be overwritten. */ if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) ) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?