diff --git a/source3/nmbd/nmbd_winsserver.c b/source3/nmbd/nmbd_winsserver.c index 0a5b1c8..74af30f 100644 --- a/source3/nmbd/nmbd_winsserver.c +++ b/source3/nmbd/nmbd_winsserver.c @@ -1250,6 +1250,79 @@ to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) )); */ if(!find_ip_in_name_record(namerec, from_ip)) { + /* + * Need to emulate the behaviour of Windows, as + * described in: + * http://lists.samba.org/archive/samba-technical/2001-October/016236.html + * (is there an MS reference for this + * somewhere?) because if the 1c list gets over + * 86 entries, the reply packet is too big + * (rdata>576 bytes) so no reply is sent. + * + * Keep only the "latest" 25 records, while + * ensuring that the PDC (0x1b) is never removed + * We do this by removing the first entry that + * isn't the 1b entry for the same name, + * on the grounds that insertion is at the end + * of the list, so the oldest entries are at + * the start. + * + */ + while(namerec->data.num_ips>=25) { + struct name_record *name1brec = NULL; + + DEBUG(3,("wins_process_name_registration_request: " + "More than 25 IPs already in " + "the list. Looking for a 1b " + "record\n")); + + /* Use the same processing as a 1b name + * query. */ + wins_delete_all_tmp_in_memory_records(); + fetch_all_active_wins_1b_names(); + + /* Per the above, find the 1b record, and then remove the first IP that isn't the same */ + for(name1brec = subrec->namelist; + name1brec; + name1brec = name1brec->next ) { + if( WINS_STATE_ACTIVE(name1brec) && + name1brec->name.name_type == 0x1b) { + DEBUG(3,("wins_process_name_registration_request: " + "Found the #1b record " + "with ip %s\n", + inet_ntoa(name1brec->data.ip[0]))); + break; + } + } + if(!name1brec) { + DEBUG(3,("wins_process_name_registration_request: " + "Didn't find a #1b name record. " + "Removing the first available " + "entry %s\n", + inet_ntoa(namerec->data.ip[0]))); + remove_ip_from_name_record(namerec, namerec->data.ip[0]); + wins_hook("delete", namerec, 0); + } else { + int i; + for(i=0; idata.num_ips; i++) { + /* The name1brec should only have + * the single IP address in it, + * so we only check against the first one*/ + if(!ip_equal_v4( namerec->data.ip[i], name1brec->data.ip[0])) { + /* The i'th entry isn't the 1b address; delete it */ + DEBUG(3,("wins_process_name_registration_request: " + "Entry at %d is not the #1b address. " + "About to remove it\n", + i)); + remove_ip_from_name_record(namerec, namerec->data.ip[i]); + wins_hook("delete", namerec, 0); + break; + } + } + } + } + /* The list is guaranteed to be < 25 entries now + * - safe to add a new one */ 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);