diff options
author | Jeremy Allison <jra@samba.org> | 2003-08-27 01:25:01 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2003-08-27 01:25:01 +0000 |
commit | 84ae44678a6c59c999bc1023fdd9b7ad87f4ec18 (patch) | |
tree | 60283db67c436454854bc0c074dae5726a17a6c9 /source | |
parent | e855dc8c9115fa11d315eb34d57722ff612daa11 (diff) | |
download | samba-84ae44678a6c59c999bc1023fdd9b7ad87f4ec18.tar.gz samba-84ae44678a6c59c999bc1023fdd9b7ad87f4ec18.tar.xz samba-84ae44678a6c59c999bc1023fdd9b7ad87f4ec18.zip |
Fix the character set handling properly in nmbd. Also fix bug where
iconv wasn't re-initialised on reading of "charset" parameters. This
caused workgroup name to be set incorrectly if it contained an
extended character.
Jeremy.
Diffstat (limited to 'source')
-rw-r--r-- | source/libsmb/nmblib.c | 3 | ||||
-rw-r--r-- | source/nmbd/asyncdns.c | 73 | ||||
-rw-r--r-- | source/nmbd/nmbd.c | 3 | ||||
-rw-r--r-- | source/nmbd/nmbd_elections.c | 1 | ||||
-rw-r--r-- | source/nmbd/nmbd_incomingrequests.c | 606 | ||||
-rw-r--r-- | source/nmbd/nmbd_lmhosts.c | 91 | ||||
-rw-r--r-- | source/nmbd/nmbd_logonnames.c | 195 | ||||
-rw-r--r-- | source/nmbd/nmbd_mynames.c | 184 | ||||
-rw-r--r-- | source/nmbd/nmbd_namelistdb.c | 800 | ||||
-rw-r--r-- | source/nmbd/nmbd_namequery.c | 410 | ||||
-rw-r--r-- | source/nmbd/nmbd_nameregister.c | 28 | ||||
-rw-r--r-- | source/nmbd/nmbd_nodestatus.c | 68 | ||||
-rw-r--r-- | source/nmbd/nmbd_packets.c | 2499 | ||||
-rw-r--r-- | source/nmbd/nmbd_processlogon.c | 813 | ||||
-rw-r--r-- | source/nmbd/nmbd_responserecordsdb.c | 318 | ||||
-rw-r--r-- | source/nmbd/nmbd_sendannounce.c | 765 | ||||
-rw-r--r-- | source/nmbd/nmbd_serverlistdb.c | 520 | ||||
-rw-r--r-- | source/nmbd/nmbd_subnetdb.c | 395 | ||||
-rw-r--r-- | source/nmbd/nmbd_synclists.c | 29 | ||||
-rw-r--r-- | source/nmbd/nmbd_winsproxy.c | 260 | ||||
-rw-r--r-- | source/nmbd/nmbd_winsserver.c | 2649 | ||||
-rw-r--r-- | source/nmbd/nmbd_workgroupdb.c | 357 | ||||
-rw-r--r-- | source/param/loadparm.c | 15 |
23 files changed, 5337 insertions, 5745 deletions
diff --git a/source/libsmb/nmblib.c b/source/libsmb/nmblib.c index 23eac9ad7cc..ff38245435d 100644 --- a/source/libsmb/nmblib.c +++ b/source/libsmb/nmblib.c @@ -825,8 +825,7 @@ void make_nmb_name( struct nmb_name *n, const char *name, int type) memset( (char *)n, '\0', sizeof(struct nmb_name) ); push_ascii(n->name, name, sizeof(n->name), STR_TERMINATE|STR_UPPER); n->name_type = (unsigned int)type & 0xFF; - StrnCpy( n->scope, global_scope(), 63 ); - strupper_m( n->scope ); + push_ascii(n->scope, global_scope(), 64, STR_TERMINATE); } /******************************************************************* diff --git a/source/nmbd/asyncdns.c b/source/nmbd/asyncdns.c index c86ee69a097..6d5d487b112 100644 --- a/source/nmbd/asyncdns.c +++ b/source/nmbd/asyncdns.c @@ -26,26 +26,25 @@ static struct name_record *add_dns_result(struct nmb_name *question, struct in_addr addr) { - int name_type = question->name_type; - char *qname = question->name; - + int name_type = question->name_type; + nstring qname; + + pull_ascii_nstring(qname, question->name); - if (!addr.s_addr) { - /* add the fail to WINS cache of names. give it 1 hour in the cache */ - DEBUG(3,("add_dns_result: Negative DNS answer for %s\n", qname)); - (void)add_name_to_subnet( wins_server_subnet, qname, name_type, - NB_ACTIVE, 60*60, DNSFAIL_NAME, 1, &addr ); - return( NULL ); - } - - /* add it to our WINS cache of names. give it 2 hours in the cache */ - DEBUG(3,("add_dns_result: DNS gave answer for %s of %s\n", qname, inet_ntoa(addr))); - - return( add_name_to_subnet( wins_server_subnet, qname, name_type, - NB_ACTIVE, 2*60*60, DNS_NAME, 1, &addr ) ); -} + if (!addr.s_addr) { + /* add the fail to WINS cache of names. give it 1 hour in the cache */ + DEBUG(3,("add_dns_result: Negative DNS answer for %s\n", qname)); + (void)add_name_to_subnet( wins_server_subnet, qname, name_type, + NB_ACTIVE, 60*60, DNSFAIL_NAME, 1, &addr ); + return( NULL ); + } + /* add it to our WINS cache of names. give it 2 hours in the cache */ + DEBUG(3,("add_dns_result: DNS gave answer for %s of %s\n", qname, inet_ntoa(addr))); + return( add_name_to_subnet( wins_server_subnet, qname, name_type, + NB_ACTIVE, 2*60*60, DNS_NAME, 1, &addr ) ); +} #ifndef SYNC_DNS @@ -70,6 +69,7 @@ static struct packet_struct *dns_current; return the fd used to gather async dns replies. This is added to the select loop ****************************************************************************/ + int asyncdns_fd(void) { return fd_in; @@ -110,7 +110,7 @@ static void asyncdns_process(void) static void sig_term(int sig) { - _exit(0); + _exit(0); } /*************************************************************************** @@ -224,10 +224,10 @@ void run_dns_queue(void) if (query_current(&r)) { DEBUG(3,("DNS calling send_wins_name_query_response\n")); in_dns = 1; - if(namerec == NULL) - send_wins_name_query_response(NAM_ERR, dns_current, NULL); - else - send_wins_name_query_response(0,dns_current,namerec); + if(namerec == NULL) + send_wins_name_query_response(NAM_ERR, dns_current, NULL); + else + send_wins_name_query_response(0,dns_current,namerec); in_dns = 0; } @@ -245,10 +245,10 @@ void run_dns_queue(void) if (nmb_name_equal(question, &r.name)) { DEBUG(3,("DNS calling send_wins_name_query_response\n")); in_dns = 1; - if(namerec == NULL) - send_wins_name_query_response(NAM_ERR, p, NULL); - else - send_wins_name_query_response(0,p,namerec); + if(namerec == NULL) + send_wins_name_query_response(NAM_ERR, p, NULL); + else + send_wins_name_query_response(0,p,namerec); in_dns = 0; p->locked = False; @@ -269,7 +269,8 @@ void run_dns_queue(void) if (dns_queue) { dns_current = dns_queue; dns_queue = dns_queue->next; - if (dns_queue) dns_queue->prev = NULL; + if (dns_queue) + dns_queue->prev = NULL; dns_current->next = NULL; if (!write_child(dns_current)) { @@ -277,12 +278,12 @@ void run_dns_queue(void) return; } } - } /*************************************************************************** queue a DNS query ****************************************************************************/ + BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question, struct name_record **n) { @@ -315,11 +316,14 @@ BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question, /*************************************************************************** we use this when we can't do async DNS lookups ****************************************************************************/ + BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question, struct name_record **n) { - char *qname = question->name; struct in_addr dns_ip; + nstring qname; + + pull_ascii_nstring(qname, question->name); DEBUG(3,("DNS search for %s - ", nmb_namestr(question))); @@ -332,18 +336,19 @@ BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question, BlockSignals(True, SIGTERM); *n = add_dns_result(question, dns_ip); - if(*n == NULL) - send_wins_name_query_response(NAM_ERR, p, NULL); - else - send_wins_name_query_response(0, p, *n); + if(*n == NULL) + send_wins_name_query_response(NAM_ERR, p, NULL); + else + send_wins_name_query_response(0, p, *n); return False; } /*************************************************************************** With sync dns there is no child to kill on SIGTERM. ****************************************************************************/ + void kill_async_dns_child(void) { - return; + return; } #endif diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c index c33011a4177..25ba07c8a7a 100644 --- a/source/nmbd/nmbd.c +++ b/source/nmbd/nmbd.c @@ -231,7 +231,8 @@ static BOOL reload_interfaces(time_t t) DEBUG(2,("Found new interface %s\n", inet_ntoa(iface->ip))); subrec = make_normal_subnet(iface); - if (subrec) register_my_workgroup_one_subnet(subrec); + if (subrec) + register_my_workgroup_one_subnet(subrec); } } diff --git a/source/nmbd/nmbd_elections.c b/source/nmbd/nmbd_elections.c index 09ab9ee7835..d4d6da081a6 100644 --- a/source/nmbd/nmbd_elections.c +++ b/source/nmbd/nmbd_elections.c @@ -51,6 +51,7 @@ static void send_election_dgram(struct subnet_record *subrec, const char *workgr p += 13; fstrcpy(srv_name, server_name); strupper_m(srv_name); + /* The following call does UNIX -> DOS charset conversion. */ pstrcpy_base(p, srv_name, outbuf); p = skip_string(p,1); diff --git a/source/nmbd/nmbd_incomingrequests.c b/source/nmbd/nmbd_incomingrequests.c index a3faf5e1046..dd999fbdf77 100644 --- a/source/nmbd/nmbd_incomingrequests.c +++ b/source/nmbd/nmbd_incomingrequests.c @@ -3,7 +3,7 @@ NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 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 @@ -33,18 +33,18 @@ Send a name release response. static void send_name_release_response(int rcode, struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - char rdata[6]; + struct nmb_packet *nmb = &p->packet.nmb; + char rdata[6]; - memcpy(&rdata[0], &nmb->additional->rdata[0], 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. */ + 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. */ } /**************************************************************************** @@ -55,76 +55,74 @@ Ignore it if it's not one of our names. void process_name_release_request(struct subnet_record *subrec, struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - struct in_addr owner_ip; - struct nmb_name *question = &nmb->question.question_name; - BOOL bcast = nmb->header.nm_flags.bcast; - uint16 nb_flags = get_nb_flags(nmb->additional->rdata); - BOOL group = (nb_flags & NB_GROUP) ? True : False; - struct name_record *namerec; - int rcode = 0; + struct nmb_packet *nmb = &p->packet.nmb; + struct in_addr owner_ip; + struct nmb_name *question = &nmb->question.question_name; + nstring qname; + BOOL bcast = nmb->header.nm_flags.bcast; + uint16 nb_flags = get_nb_flags(nmb->additional->rdata); + BOOL group = (nb_flags & NB_GROUP) ? True : False; + struct name_record *namerec; + int rcode = 0; - putip((char *)&owner_ip,&nmb->additional->rdata[2]); + putip((char *)&owner_ip,&nmb->additional->rdata[2]); - if(!bcast) - { - /* We should only get broadcast name release packets here. - Anyone trying to release unicast should be going to a WINS - server. If the code gets here, then either we are not a wins - server and they sent it anyway, or we are a WINS server and - the request was malformed. Either way, log an error here. - and send an error reply back. - */ - DEBUG(0,("process_name_release_request: unicast name release request \ + if(!bcast) { + /* We should only get broadcast name release packets here. + Anyone trying to release unicast should be going to a WINS + server. If the code gets here, then either we are not a wins + server and they sent it anyway, or we are a WINS server and + the request was malformed. Either way, log an error here. + and send an error reply back. + */ + DEBUG(0,("process_name_release_request: unicast name release request \ received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n", - nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name)); + nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name)); - send_name_release_response(FMT_ERR, p); - return; - } + send_name_release_response(FMT_ERR, p); + return; + } - DEBUG(3,("process_name_release_request: Name release on name %s, \ + DEBUG(3,("process_name_release_request: Name release on name %s, \ subnet %s from owner IP %s\n", - nmb_namestr(&nmb->question.question_name), - subrec->subnet_name, inet_ntoa(owner_ip))); + nmb_namestr(&nmb->question.question_name), + subrec->subnet_name, inet_ntoa(owner_ip))); - /* If someone is releasing a broadcast group name, just ignore it. */ - if( group && !ismyip(owner_ip) ) - return; - - /* - * Code to work around a bug in FTP OnNet software NBT implementation. - * They do a broadcast name release for WORKGROUP<0> and WORKGROUP<1e> - * names and *don't set the group bit* !!!!! - */ - - if( !group && !ismyip(owner_ip) && strequal(question->name, lp_workgroup()) && - ((question->name_type == 0x0) || (question->name_type == 0x1e))) - { - DEBUG(6,("process_name_release_request: FTP OnNet bug workaround. Ignoring \ + /* If someone is releasing a broadcast group name, just ignore it. */ + if( group && !ismyip(owner_ip) ) + return; + + /* + * Code to work around a bug in FTP OnNet software NBT implementation. + * They do a broadcast name release for WORKGROUP<0> and WORKGROUP<1e> + * names and *don't set the group bit* !!!!! + */ + + pull_ascii_nstring(qname, question->name); + if( !group && !ismyip(owner_ip) && strequal(qname, lp_workgroup()) && + ((question->name_type == 0x0) || (question->name_type == 0x1e))) { + DEBUG(6,("process_name_release_request: FTP OnNet bug workaround. Ignoring \ group release name %s from IP %s on subnet %s with no group bit set.\n", - nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name )); - return; - } - - namerec = find_name_on_subnet(subrec, &nmb->question.question_name, FIND_ANY_NAME); - - /* We only care about someone trying to release one of our names. */ - if( namerec - && ( (namerec->data.source == SELF_NAME) - || (namerec->data.source == PERMANENT_NAME) ) ) - { - rcode = ACT_ERR; - DEBUG(0, ("process_name_release_request: Attempt to release name %s from IP %s \ + nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name )); + return; + } + + namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); + + /* We only care about someone trying to release one of our names. */ + if( namerec && ( (namerec->data.source == SELF_NAME) + || (namerec->data.source == PERMANENT_NAME) ) ) { + rcode = ACT_ERR; + DEBUG(0, ("process_name_release_request: Attempt to release name %s from IP %s \ on subnet %s being rejected as it is one of our names.\n", - nmb_namestr(&nmb->question.question_name), inet_ntoa(owner_ip), subrec->subnet_name)); - } + nmb_namestr(&nmb->question.question_name), inet_ntoa(owner_ip), subrec->subnet_name)); + } - if(rcode == 0) - return; + if(rcode == 0) + return; - /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */ - send_name_release_response(rcode, p); + /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */ + send_name_release_response(rcode, p); } /**************************************************************************** @@ -133,18 +131,18 @@ Send a name registration response. static void send_name_registration_response(int rcode, int ttl, struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - char rdata[6]; + struct nmb_packet *nmb = &p->packet.nmb; + char rdata[6]; - memcpy(&rdata[0], &nmb->additional->rdata[0], 6); + memcpy(&rdata[0], &nmb->additional->rdata[0], 6); - reply_netbios_packet(p, /* Packet to reply to. */ - rcode, /* Result code. */ - NMB_REG, /* nmbd type code. */ - NMB_NAME_REG_OPCODE, /* opcode. */ - ttl, /* ttl. */ - rdata, /* data to send. */ - 6); /* data length. */ + reply_netbios_packet(p, /* Packet to reply to. */ + rcode, /* Result code. */ + NMB_REG, /* nmbd type code. */ + NMB_NAME_REG_OPCODE, /* opcode. */ + ttl, /* ttl. */ + rdata, /* data to send. */ + 6); /* data length. */ } /**************************************************************************** @@ -154,38 +152,34 @@ Process a name refresh request on a broadcast subnet. void process_name_refresh_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; - struct in_addr from_ip; + struct nmb_packet *nmb = &p->packet.nmb; + struct nmb_name *question = &nmb->question.question_name; + BOOL bcast = nmb->header.nm_flags.bcast; + struct in_addr from_ip; - putip((char *)&from_ip,&nmb->additional->rdata[2]); - - if(!bcast) - { - /* We should only get broadcast name refresh packets here. - Anyone trying to refresh unicast should be going to a WINS - server. If the code gets here, then either we are not a wins - server and they sent it anyway, or we are a WINS server and - the request was malformed. Either way, log an error here. - and send an error reply back. - */ - DEBUG(0,("process_name_refresh_request: unicast name registration request \ + putip((char *)&from_ip,&nmb->additional->rdata[2]); + + if(!bcast) { + /* We should only get broadcast name refresh packets here. + Anyone trying to refresh unicast should be going to a WINS + server. If the code gets here, then either we are not a wins + server and they sent it anyway, or we are a WINS server and + the request was malformed. Either way, log an error here. + and send an error reply back. + */ + DEBUG(0,("process_name_refresh_request: unicast name registration request \ received for name %s from IP %s on subnet %s.\n", - nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - DEBUG(0,("Error - should be sent to WINS server\n")); + nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); + DEBUG(0,("Error - should be sent to WINS server\n")); - send_name_registration_response(FMT_ERR, 0, p); - return; - } + send_name_registration_response(FMT_ERR, 0, p); + return; + } - /* Just log a message. We really don't care about broadcast name - refreshes. */ + /* Just log a message. We really don't care about broadcast name refreshes. */ - DEBUG(3,("process_name_refresh_request: Name refresh for name %s \ + DEBUG(3,("process_name_refresh_request: Name refresh for name %s \ IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - } /**************************************************************************** @@ -195,92 +189,83 @@ Process a name registration request on a broadcast subnet. void process_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); - BOOL group = (nb_flags & NB_GROUP) ? True : False; - struct name_record *namerec = NULL; - int ttl = nmb->additional->ttl; - struct in_addr from_ip; + 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); + BOOL group = (nb_flags & NB_GROUP) ? True : False; + struct name_record *namerec = NULL; + int ttl = nmb->additional->ttl; + struct in_addr from_ip; - putip((char *)&from_ip,&nmb->additional->rdata[2]); + putip((char *)&from_ip,&nmb->additional->rdata[2]); - if(!bcast) - { - /* We should only get broadcast name registration packets here. - Anyone trying to register unicast should be going to a WINS - server. If the code gets here, then either we are not a wins - server and they sent it anyway, or we are a WINS server and - the request was malformed. Either way, log an error here. - and send an error reply back. - */ - DEBUG(0,("process_name_registration_request: unicast name registration request \ + if(!bcast) { + /* We should only get broadcast name registration packets here. + Anyone trying to register unicast should be going to a WINS + server. If the code gets here, then either we are not a wins + server and they sent it anyway, or we are a WINS server and + the request was malformed. Either way, log an error here. + and send an error reply back. + */ + DEBUG(0,("process_name_registration_request: unicast name registration request \ received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n", - nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); + nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - send_name_registration_response(FMT_ERR, 0, p); - return; - } + send_name_registration_response(FMT_ERR, 0, p); + return; + } - DEBUG(3,("process_name_registration_request: Name registration for name %s \ + DEBUG(3,("process_name_registration_request: Name registration for name %s \ IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - /* See if the name already exists. */ - namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); + /* See if the name already exists. */ + namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); - /* - * If the name being registered exists and is a WINS_PROXY_NAME - * then delete the WINS proxy name entry so we don't reply erroneously - * later to queries. - */ - - if((namerec != NULL) && (namerec->data.source == WINS_PROXY_NAME)) - { - remove_name_from_namelist( subrec, namerec ); - namerec = NULL; - } - - if (!group) - { - /* Unique name. */ - - if( (namerec != NULL) - && ( (namerec->data.source == SELF_NAME) - || (namerec->data.source == PERMANENT_NAME) - || NAME_GROUP(namerec) ) ) - { - /* No-one can register one of Samba's names, nor can they - register a name that's a group name as a unique name */ - - send_name_registration_response(ACT_ERR, 0, p); - return; - } - else if(namerec != NULL) - { - /* Update the namelist record with the new information. */ - namerec->data.ip[0] = from_ip; - update_name_ttl(namerec, ttl); - - DEBUG(3,("process_name_registration_request: Updated name record %s \ + /* + * If the name being registered exists and is a WINS_PROXY_NAME + * then delete the WINS proxy name entry so we don't reply erroneously + * later to queries. + */ + + if((namerec != NULL) && (namerec->data.source == WINS_PROXY_NAME)) { + remove_name_from_namelist( subrec, namerec ); + namerec = NULL; + } + + if (!group) { + /* Unique name. */ + + if( (namerec != NULL) + && ( (namerec->data.source == SELF_NAME) + || (namerec->data.source == PERMANENT_NAME) + || NAME_GROUP(namerec) ) ) { + /* No-one can register one of Samba's names, nor can they + register a name that's a group name as a unique name */ + + send_name_registration_response(ACT_ERR, 0, p); + return; + } else if(namerec != NULL) { + /* Update the namelist record with the new information. */ + namerec->data.ip[0] = from_ip; + update_name_ttl(namerec, ttl); + + DEBUG(3,("process_name_registration_request: Updated name record %s \ with IP %s on subnet %s\n",nmb_namestr(&namerec->name),inet_ntoa(from_ip), subrec->subnet_name)); - return; - } - } - else - { - /* Group name. */ - - if( (namerec != NULL) - && !NAME_GROUP(namerec) - && ( (namerec->data.source == SELF_NAME) - || (namerec->data.source == PERMANENT_NAME) ) ) - { - /* Disallow group names when we have a unique name. */ - send_name_registration_response(ACT_ERR, 0, p); - return; - } - } + return; + } + } else { + /* Group name. */ + + if( (namerec != NULL) + && !NAME_GROUP(namerec) + && ( (namerec->data.source == SELF_NAME) + || (namerec->data.source == PERMANENT_NAME) ) ) { + /* Disallow group names when we have a unique name. */ + send_name_registration_response(ACT_ERR, 0, p); + return; + } + } } /**************************************************************************** @@ -290,147 +275,150 @@ We put our own names first, then in alphabetical order. static int status_compare(char *n1,char *n2) { - int l1,l2,l3; - - /* It's a bit tricky because the names are space padded */ - for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++) ; - for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++) ; - l3 = strlen(global_myname()); - - if ((l1==l3) && strncmp(n1,global_myname(),l3) == 0 && - (l2!=l3 || strncmp(n2,global_myname(),l3) != 0)) - return -1; - - if ((l2==l3) && strncmp(n2,global_myname(),l3) == 0 && - (l1!=l3 || strncmp(n1,global_myname(),l3) != 0)) - return 1; - - return memcmp(n1,n2,18); + nstring name1, name2; + int l1,l2,l3; + + pull_ascii_nstring(name1, n1); + pull_ascii_nstring(name2, n2); + n1 = name1; + n2 = name2; + + /* It's a bit tricky because the names are space padded */ + for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++) + ; + for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++) + ; + l3 = strlen(global_myname()); + + if ((l1==l3) && strncmp(n1,global_myname(),l3) == 0 && + (l2!=l3 || strncmp(n2,global_myname(),l3) != 0)) + return -1; + + if ((l2==l3) && strncmp(n2,global_myname(),l3) == 0 && + (l1!=l3 || strncmp(n1,global_myname(),l3) != 0)) + return 1; + + return memcmp(n1,n2,sizeof(nstring)); } - /**************************************************************************** Process a node status query ****************************************************************************/ void process_node_status_request(struct subnet_record *subrec, struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - char *qname = nmb->question.question_name.name; - int ques_type = nmb->question.question_name.name_type; - char rdata[MAX_DGRAM_SIZE]; - char *countptr, *buf, *bufend, *buf0; - int names_added,i; - struct name_record *namerec; - - DEBUG(3,("process_node_status_request: status request for name %s from IP %s on \ -subnet %s.\n", nmb_namestr(&nmb->question.question_name), inet_ntoa(p->ip), - subrec->subnet_name)); - - if((namerec = find_name_on_subnet(subrec, &nmb->question.question_name, - FIND_SELF_NAME)) == 0) - { - DEBUG(1,("process_node_status_request: status request for name %s from IP %s on \ + struct nmb_packet *nmb = &p->packet.nmb; + nstring qname; + int ques_type = nmb->question.question_name.name_type; + char rdata[MAX_DGRAM_SIZE]; + char *countptr, *buf, *bufend, *buf0; + int names_added,i; + struct name_record *namerec; + + pull_ascii_nstring(qname, nmb->question.question_name.name); + + DEBUG(3,("process_node_status_request: status request for name %s from IP %s on \ +subnet %s.\n", nmb_namestr(&nmb->question.question_name), inet_ntoa(p->ip), subrec->subnet_name)); + + if((namerec = find_name_on_subnet(subrec, &nmb->question.question_name, FIND_SELF_NAME)) == 0) { + DEBUG(1,("process_node_status_request: status request for name %s from IP %s on \ subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name), - inet_ntoa(p->ip), subrec->subnet_name)); + inet_ntoa(p->ip), subrec->subnet_name)); - return; - } + return; + } - /* this is not an exact calculation. the 46 is for the stats buffer - and the 60 is to leave room for the header etc */ - bufend = &rdata[MAX_DGRAM_SIZE] - (18 + 46 + 60); - countptr = buf = rdata; - buf += 1; - buf0 = buf; - - names_added = 0; - - namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); - - while (buf < bufend) - { - if( (namerec->data.source == SELF_NAME) - || (namerec->data.source == PERMANENT_NAME) ) - { - int name_type = namerec->name.name_type; - - if (!strequal(namerec->name.name,"*") && - !strequal(namerec->name.name,"__SAMBA__") && - (name_type < 0x1b || name_type >= 0x20 || - ques_type < 0x1b || ques_type >= 0x20 || - strequal(qname, namerec->name.name))) - { - /* Start with the name. */ - memset(buf,'\0',18); - slprintf(buf, 17, "%-15.15s",namerec->name.name); - strupper_m(buf); - - /* Put the name type and netbios flags in the buffer. */ - buf[15] = name_type; - set_nb_flags( &buf[16],namerec->data.nb_flags ); - buf[16] |= NB_ACTIVE; /* all our names are active */ - - buf += 18; - - names_added++; - } - } - - /* Remove duplicate names. */ - if (names_added > 1) { - qsort( buf0, names_added, 18, QSORT_CAST status_compare ); - } - - for( i=1; i < names_added ; i++ ) - { - if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0) - { - names_added--; - if (names_added == i) - break; - memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i)); - i--; - } - } - - buf = buf0 + 18*names_added; - - namerec = (struct name_record *)ubi_trNext( namerec ); - - if (!namerec) - { - /* End of the subnet specific name list. Now - add the names on the unicast subnet . */ - struct subnet_record *uni_subrec = unicast_subnet; - - if (uni_subrec != subrec) - { - subrec = uni_subrec; - namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); - } - } - if (!namerec) - break; - - } + /* this is not an exact calculation. the 46 is for the stats buffer + and the 60 is to leave room for the header etc */ + bufend = &rdata[MAX_DGRAM_SIZE] - (18 + 46 + 60); + countptr = buf = rdata; + buf += 1; + buf0 = buf; + + names_added = 0; + + namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); + + while (buf < bufend) { + if( (namerec->data.source == SELF_NAME) || (namerec->data.source == PERMANENT_NAME) ) { + int name_type = namerec->name.name_type; + nstring name; + + pull_ascii_nstring(name, namerec->name.name); + strupper_m(name); + if (!strequal(name,"*") && + !strequal(name,"__SAMBA__") && + (name_type < 0x1b || name_type >= 0x20 || + ques_type < 0x1b || ques_type >= 0x20 || + strequal(qname, name))) { + /* Start with the name. */ + nstring tmp_name; + memset(tmp_name,'\0',sizeof(tmp_name)); + snprintf(tmp_name, sizeof(tmp_name), "%-15.15s",name); + push_ascii_nstring(buf, tmp_name); + + /* Put the name type and netbios flags in the buffer. */ + + buf[15] = name_type; + set_nb_flags( &buf[16],namerec->data.nb_flags ); + buf[16] |= NB_ACTIVE; /* all our names are active */ + + buf += 18; + + names_added++; + } + } + + /* Remove duplicate names. */ + if (names_added > 1) { + qsort( buf0, names_added, 18, QSORT_CAST status_compare ); + } + + for( i=1; i < names_added ; i++ ) { + if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0) { + names_added--; + if (names_added == i) + break; + memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i)); + i--; + } + } + + buf = buf0 + 18*names_added; + + namerec = (struct name_record *)ubi_trNext( namerec ); + + if (!namerec) { + /* End of the subnet specific name list. Now + add the names on the unicast subnet . */ + struct subnet_record *uni_subrec = unicast_subnet; + + if (uni_subrec != subrec) { + subrec = uni_subrec; + namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); + } + } + if (!namerec) + break; + + } - SCVAL(countptr,0,names_added); + SCVAL(countptr,0,names_added); - /* We don't send any stats as they could be used to attack - the protocol. */ - memset(buf,'\0',46); + /* We don't send any stats as they could be used to attack + the protocol. */ + memset(buf,'\0',46); - buf += 46; + buf += 46; - /* Send a NODE STATUS RESPONSE */ - reply_netbios_packet(p, /* Packet to reply to. */ - 0, /* Result code. */ - NMB_STATUS, /* nmbd type code. */ - NMB_NAME_QUERY_OPCODE, /* opcode. */ - 0, /* ttl. */ - rdata, /* data to send. */ - PTR_DIFF(buf,rdata)); /* data length. */ + /* Send a NODE STATUS RESPONSE */ + reply_netbios_packet(p, /* Packet to reply to. */ + 0, /* Result code. */ + NMB_STATUS, /* nmbd type code. */ + NMB_NAME_QUERY_OPCODE, /* opcode. */ + 0, /* ttl. */ + rdata, /* data to send. */ + PTR_DIFF(buf,rdata)); /* data length. */ } diff --git a/source/nmbd/nmbd_lmhosts.c b/source/nmbd/nmbd_lmhosts.c index 3c067d8ed4e..b14e13f3a47 100644 --- a/source/nmbd/nmbd_lmhosts.c +++ b/source/nmbd/nmbd_lmhosts.c @@ -28,50 +28,46 @@ /**************************************************************************** Load a lmhosts file. ****************************************************************************/ + void load_lmhosts_file(char *fname) { - pstring name; - int name_type; - struct in_addr ipaddr; - XFILE *fp = startlmhosts( fname ); - - if (!fp) { - DEBUG(2,("load_lmhosts_file: Can't open lmhosts file %s. Error was %s\n", - fname, strerror(errno))); - return; - } + pstring name; + int name_type; + struct in_addr ipaddr; + XFILE *fp = startlmhosts( fname ); + + if (!fp) { + DEBUG(2,("load_lmhosts_file: Can't open lmhosts file %s. Error was %s\n", + fname, strerror(errno))); + return; + } - while (getlmhostsent(fp, name, &name_type, &ipaddr) ) - { - struct subnet_record *subrec = NULL; - enum name_source source = LMHOSTS_NAME; - - /* We find a relevent subnet to put this entry on, then add it. */ - /* Go through all the broadcast subnets and see if the mask matches. */ - for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - if(same_net(ipaddr, subrec->bcast_ip, subrec->mask_ip)) - break; - } + while (getlmhostsent(fp, name, &name_type, &ipaddr) ) { + struct subnet_record *subrec = NULL; + enum name_source source = LMHOSTS_NAME; + + /* We find a relevent subnet to put this entry on, then add it. */ + /* Go through all the broadcast subnets and see if the mask matches. */ + for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + if(same_net(ipaddr, subrec->bcast_ip, subrec->mask_ip)) + break; + } - /* If none match add the name to the remote_broadcast_subnet. */ - if(subrec == NULL) - subrec = remote_broadcast_subnet; - - if(name_type == -1) - { - /* Add the (0) and (0x20) names directly into the namelist for this subnet. */ - (void)add_name_to_subnet(subrec,name,0x00,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr); - (void)add_name_to_subnet(subrec,name,0x20,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr); - } - else - { - /* Add the given name type to the subnet namelist. */ - (void)add_name_to_subnet(subrec,name,name_type,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr); - } - } + /* If none match add the name to the remote_broadcast_subnet. */ + if(subrec == NULL) + subrec = remote_broadcast_subnet; + + if(name_type == -1) { + /* Add the (0) and (0x20) names directly into the namelist for this subnet. */ + (void)add_name_to_subnet(subrec,name,0x00,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr); + (void)add_name_to_subnet(subrec,name,0x20,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr); + } else { + /* Add the given name type to the subnet namelist. */ + (void)add_name_to_subnet(subrec,name,name_type,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr); + } + } - endlmhosts(fp); + endlmhosts(fp); } /**************************************************************************** @@ -82,17 +78,16 @@ void load_lmhosts_file(char *fname) BOOL find_name_in_lmhosts(struct nmb_name *nmbname, struct name_record **namerecp) { - struct name_record *namerec; + struct name_record *namerec; - *namerecp = NULL; + *namerecp = NULL; - if((namerec = find_name_on_subnet(remote_broadcast_subnet, nmbname, - FIND_ANY_NAME))==NULL) - return False; + if((namerec = find_name_on_subnet(remote_broadcast_subnet, nmbname, FIND_ANY_NAME))==NULL) + return False; - if(!NAME_IS_ACTIVE(namerec) || (namerec->data.source != LMHOSTS_NAME)) - return False; + if(!NAME_IS_ACTIVE(namerec) || (namerec->data.source != LMHOSTS_NAME)) + return False; - *namerecp = namerec; - return True; + *namerecp = namerec; + return True; } diff --git a/source/nmbd/nmbd_logonnames.c b/source/nmbd/nmbd_logonnames.c index b73586aa453..f79fc56f7bd 100644 --- a/source/nmbd/nmbd_logonnames.c +++ b/source/nmbd/nmbd_logonnames.c @@ -3,7 +3,7 @@ NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 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 @@ -29,38 +29,40 @@ extern uint16 samba_nb_type; /* Samba's NetBIOS type. */ /**************************************************************************** Fail to become a Logon server on a subnet. - ****************************************************************************/ +****************************************************************************/ + static void become_logon_server_fail(struct subnet_record *subrec, struct response_record *rrec, struct nmb_name *fail_name) { - struct work_record *work = find_workgroup_on_subnet(subrec, fail_name->name); - struct server_record *servrec; - - if(!work) - { - DEBUG(0,("become_logon_server_fail: Error - cannot find \ -workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name)); - return; - } - - if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) - { - DEBUG(0,("become_logon_server_fail: Error - cannot find server %s \ + nstring failname; + struct work_record *work; + struct server_record *servrec; + + pull_ascii_nstring(failname, fail_name->name); + work = find_workgroup_on_subnet(subrec, failname); + if(!work) { + DEBUG(0,("become_logon_server_fail: Error - cannot find \ +workgroup %s on subnet %s\n", failname, subrec->subnet_name)); + return; + } + + if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) { + DEBUG(0,("become_logon_server_fail: Error - cannot find server %s \ in workgroup %s on subnet %s\n", - global_myname(), fail_name->name, subrec->subnet_name)); - work->log_state = LOGON_NONE; - return; - } + global_myname(), failname, subrec->subnet_name)); + work->log_state = LOGON_NONE; + return; + } - /* Set the state back to LOGON_NONE. */ - work->log_state = LOGON_NONE; + /* Set the state back to LOGON_NONE. */ + work->log_state = LOGON_NONE; - servrec->serv.type &= ~SV_TYPE_DOMAIN_CTRL; + servrec->serv.type &= ~SV_TYPE_DOMAIN_CTRL; - DEBUG(0,("become_logon_server_fail: Failed to become a domain master for \ + DEBUG(0,("become_logon_server_fail: Failed to become a domain master for \ workgroup %s on subnet %s. Couldn't register name %s.\n", - work->work_group, subrec->subnet_name, nmb_namestr(fail_name))); + work->work_group, subrec->subnet_name, nmb_namestr(fail_name))); } @@ -74,49 +76,51 @@ static void become_logon_server_success(struct subnet_record *subrec, uint16 nb_flags, int ttl, struct in_addr registered_ip) { - struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name); - struct server_record *servrec; - - if(!work) - { - DEBUG(0,("become_logon_server_success: Error - cannot find \ -workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name)); - return; - } - - if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) - { - DEBUG(0,("become_logon_server_success: Error - cannot find server %s \ + nstring reg_name; + struct work_record *work; + struct server_record *servrec; + + pull_ascii_nstring(reg_name, registered_name->name); + work = find_workgroup_on_subnet( subrec, reg_name); + if(!work) { + DEBUG(0,("become_logon_server_success: Error - cannot find \ +workgroup %s on subnet %s\n", reg_name, subrec->subnet_name)); + return; + } + + if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) { + DEBUG(0,("become_logon_server_success: Error - cannot find server %s \ in workgroup %s on subnet %s\n", - global_myname(), registered_name->name, subrec->subnet_name)); - work->log_state = LOGON_NONE; - return; - } - - /* Set the state in the workgroup structure. */ - work->log_state = LOGON_SRV; /* Become domain master. */ - - /* Update our server status. */ - servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MEMBER); - /* To allow Win95 policies to load we need to set type domain - controller. - */ - servrec->serv.type |= SV_TYPE_DOMAIN_CTRL; - - /* Tell the namelist writer to write out a change. */ - subrec->work_changed = True; - - /* - * Add the WORKGROUP<1C> name to the UNICAST subnet with the IP address - * for this subnet so we will respond to queries on this name. - */ - { - struct nmb_name nmbname; - make_nmb_name(&nmbname,lp_workgroup(),0x1c); - insert_permanent_name_into_unicast(subrec, &nmbname, 0x1c); - } - - DEBUG(0,("become_logon_server_success: Samba is now a logon server \ + global_myname(), reg_name, subrec->subnet_name)); + work->log_state = LOGON_NONE; + return; + } + + /* Set the state in the workgroup structure. */ + work->log_state = LOGON_SRV; /* Become domain master. */ + + /* Update our server status. */ + servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MEMBER); + /* To allow Win95 policies to load we need to set type domain + controller. + */ + servrec->serv.type |= SV_TYPE_DOMAIN_CTRL; + + /* Tell the namelist writer to write out a change. */ + subrec->work_changed = True; + + /* + * Add the WORKGROUP<1C> name to the UNICAST subnet with the IP address + * for this subnet so we will respond to queries on this name. + */ + + { + struct nmb_name nmbname; + make_nmb_name(&nmbname,lp_workgroup(),0x1c); + insert_permanent_name_into_unicast(subrec, &nmbname, 0x1c); + } + + DEBUG(0,("become_logon_server_success: Samba is now a logon server \ for workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name)); } @@ -128,45 +132,42 @@ for workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name)); static void become_logon_server(struct subnet_record *subrec, struct work_record *work) { - DEBUG(2,("become_logon_server: Atempting to become logon server for workgroup %s \ + DEBUG(2,("become_logon_server: Atempting to become logon server for workgroup %s \ on subnet %s\n", work->work_group,subrec->subnet_name)); - DEBUG(3,("become_logon_server: go to first stage: register %s<1c> name\n", - work->work_group)); - work->log_state = LOGON_WAIT; + DEBUG(3,("become_logon_server: go to first stage: register %s<1c> name\n", + work->work_group)); + work->log_state = LOGON_WAIT; - register_name(subrec, work->work_group,0x1c,samba_nb_type|NB_GROUP, - become_logon_server_success, - become_logon_server_fail, NULL); + register_name(subrec, work->work_group,0x1c,samba_nb_type|NB_GROUP, + become_logon_server_success, + become_logon_server_fail, NULL); } /***************************************************************************** Add the internet group <1c> logon names by unicast and broadcast. ****************************************************************************/ + void add_logon_names(void) { - struct subnet_record *subrec; - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup()); - - if (work && (work->log_state == LOGON_NONE)) - { - struct nmb_name nmbname; - make_nmb_name(&nmbname,lp_workgroup(),0x1c); - - if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "add_domain_logon_names:\n" ); - dbgtext( "Attempting to become logon server " ); - dbgtext( "for workgroup %s ", lp_workgroup() ); - dbgtext( "on subnet %s\n", subrec->subnet_name ); - } - become_logon_server(subrec, work); - } - } - } + struct subnet_record *subrec; + + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) { + struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup()); + + if (work && (work->log_state == LOGON_NONE)) { + struct nmb_name nmbname; + make_nmb_name(&nmbname,lp_workgroup(),0x1c); + + if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL) { + if( DEBUGLVL( 0 ) ) { + dbgtext( "add_domain_logon_names:\n" ); + dbgtext( "Attempting to become logon server " ); + dbgtext( "for workgroup %s ", lp_workgroup() ); + dbgtext( "on subnet %s\n", subrec->subnet_name ); + } + become_logon_server(subrec, work); + } + } + } } diff --git a/source/nmbd/nmbd_mynames.c b/source/nmbd/nmbd_mynames.c index dd668218395..f02fbe1640f 100644 --- a/source/nmbd/nmbd_mynames.c +++ b/source/nmbd/nmbd_mynames.c @@ -3,7 +3,7 @@ NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 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 @@ -27,20 +27,21 @@ extern uint16 samba_nb_type; /* Samba's NetBIOS type. */ /**************************************************************************** Fail funtion when registering my netbios names. - **************************************************************************/ +**************************************************************************/ static void my_name_register_failed(struct subnet_record *subrec, struct response_record *rrec, struct nmb_name *nmbname) { - DEBUG(0,("my_name_register_failed: Failed to register my name %s on subnet %s.\n", - nmb_namestr(nmbname), subrec->subnet_name)); + DEBUG(0,("my_name_register_failed: Failed to register my name %s on subnet %s.\n", + nmb_namestr(nmbname), subrec->subnet_name)); } /**************************************************************************** Add my workgroup and my given names to one subnet Also add the magic Samba names. - **************************************************************************/ +**************************************************************************/ + void register_my_workgroup_one_subnet(struct subnet_record *subrec) { int i; @@ -84,111 +85,104 @@ Exiting.\n", lp_workgroup(), subrec->subnet_name)); static void insert_refresh_name_into_unicast( struct subnet_record *subrec, struct nmb_name *nmbname, uint16 nb_type ) { - struct name_record *namerec; - - if (!we_are_a_wins_client()) { - insert_permanent_name_into_unicast(subrec, nmbname, nb_type); - return; - } - - if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL) - { - /* The name needs to be created on the unicast subnet. */ - (void)add_name_to_subnet( unicast_subnet, nmbname->name, - nmbname->name_type, nb_type, - MIN(lp_max_ttl(), MAX_REFRESH_TIME), SELF_NAME, 1, &subrec->myip); - } - else - { - /* The name already exists on the unicast subnet. Add our local - IP for the given broadcast subnet to the name. */ - add_ip_to_name_record( namerec, subrec->myip); - } + struct name_record *namerec; + + if (!we_are_a_wins_client()) { + insert_permanent_name_into_unicast(subrec, nmbname, nb_type); + return; + } + + if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL) { + nstring name; + pull_ascii_nstring(name, nmbname->name); + /* The name needs to be created on the unicast subnet. */ + (void)add_name_to_subnet( unicast_subnet, name, + nmbname->name_type, nb_type, + MIN(lp_max_ttl(), MAX_REFRESH_TIME), SELF_NAME, 1, &subrec->myip); + } else { + /* The name already exists on the unicast subnet. Add our local + IP for the given broadcast subnet to the name. */ + add_ip_to_name_record( namerec, subrec->myip); + } } /**************************************************************************** Add my workgroup and my given names to the subnet lists. Also add the magic Samba names. - **************************************************************************/ +**************************************************************************/ BOOL register_my_workgroup_and_names(void) { - struct subnet_record *subrec; - int i; - - for(subrec = FIRST_SUBNET; - subrec; - subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - register_my_workgroup_one_subnet(subrec); - } - - /* We still need to add the magic Samba - names and the netbios names to the unicast subnet directly. This is - to allow unicast node status requests and queries to still work - in a broadcast only environment. */ - - add_samba_names_to_subnet(unicast_subnet); - - for (i=0; my_netbios_names(i); i++) - { - for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - /* - * Ensure all the IP addresses are added if we are multihomed. - */ - struct nmb_name nmbname; - - make_nmb_name(&nmbname, my_netbios_names(i),0x20); - insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type); - - make_nmb_name(&nmbname, my_netbios_names(i),0x3); - insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type); - - make_nmb_name(&nmbname, my_netbios_names(i),0x0); - insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type); - } - } - - /* - * Add the WORKGROUP<0> and WORKGROUP<1e> group names to the unicast subnet - * also for the same reasons. - */ - - for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - /* - * Ensure all the IP addresses are added if we are multihomed. - */ - struct nmb_name nmbname; - - make_nmb_name(&nmbname, lp_workgroup(), 0x0); - insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type|NB_GROUP); - - make_nmb_name(&nmbname, lp_workgroup(), 0x1e); - insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type|NB_GROUP); - } - - /* - * We need to add the Samba names to the remote broadcast subnet, - * as NT 4.x does directed broadcast requests to the *<0x0> name. - */ - add_samba_names_to_subnet(remote_broadcast_subnet); - - return True; + struct subnet_record *subrec; + int i; + + for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) { + register_my_workgroup_one_subnet(subrec); + } + + /* We still need to add the magic Samba + names and the netbios names to the unicast subnet directly. This is + to allow unicast node status requests and queries to still work + in a broadcast only environment. */ + + add_samba_names_to_subnet(unicast_subnet); + + for (i=0; my_netbios_names(i); i++) { + for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + /* + * Ensure all the IP addresses are added if we are multihomed. + */ + struct nmb_name nmbname; + + make_nmb_name(&nmbname, my_netbios_names(i),0x20); + insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type); + + make_nmb_name(&nmbname, my_netbios_names(i),0x3); + insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type); + + make_nmb_name(&nmbname, my_netbios_names(i),0x0); + insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type); + } + } + + /* + * Add the WORKGROUP<0> and WORKGROUP<1e> group names to the unicast subnet + * also for the same reasons. + */ + + for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + /* + * Ensure all the IP addresses are added if we are multihomed. + */ + struct nmb_name nmbname; + + make_nmb_name(&nmbname, lp_workgroup(), 0x0); + insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type|NB_GROUP); + + make_nmb_name(&nmbname, lp_workgroup(), 0x1e); + insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type|NB_GROUP); + } + + /* + * We need to add the Samba names to the remote broadcast subnet, + * as NT 4.x does directed broadcast requests to the *<0x0> name. + */ + + add_samba_names_to_subnet(remote_broadcast_subnet); + + return True; } /**************************************************************************** Remove all the names we registered. **************************************************************************/ + void release_wins_names(void) { struct subnet_record *subrec = unicast_subnet; struct name_record *namerec, *nextnamerec; - for (namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); - namerec; - namerec = nextnamerec) { + for (namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); namerec; namerec = nextnamerec) { nextnamerec = (struct name_record *)ubi_trNext( namerec ); if( (namerec->data.source == SELF_NAME) && !NAME_IS_DEREGISTERING(namerec) ) @@ -199,12 +193,14 @@ void release_wins_names(void) /******************************************************************* Refresh our registered names with WINS - ******************************************************************/ +******************************************************************/ + void refresh_my_names(time_t t) { struct name_record *namerec; - if (wins_srv_count() < 1) return; + if (wins_srv_count() < 1) + return; for (namerec = (struct name_record *)ubi_trFirst(unicast_subnet->namelist); namerec; diff --git a/source/nmbd/nmbd_namelistdb.c b/source/nmbd/nmbd_namelistdb.c index 3f6d2f3b643..d1c9afd6081 100644 --- a/source/nmbd/nmbd_namelistdb.c +++ b/source/nmbd/nmbd_namelistdb.c @@ -3,7 +3,7 @@ NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 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 @@ -26,152 +26,149 @@ uint16 samba_nb_type = 0; /* samba's NetBIOS name type */ -/* ************************************************************************** ** - * Set Samba's NetBIOS name type. - * ************************************************************************** ** - */ +/************************************************************************** + Set Samba's NetBIOS name type. +***************************************************************************/ + void set_samba_nb_type(void) - { - if( lp_wins_support() || wins_srv_count() ) - samba_nb_type = NB_HFLAG; /* samba is a 'hybrid' node type. */ - else - samba_nb_type = NB_BFLAG; /* samba is broadcast-only node type. */ - } /* set_samba_nb_type */ - -/* ************************************************************************** ** - * Convert a NetBIOS name to upper case. - * ************************************************************************** ** - */ +{ + if( lp_wins_support() || wins_srv_count() ) + samba_nb_type = NB_HFLAG; /* samba is a 'hybrid' node type. */ + else + samba_nb_type = NB_BFLAG; /* samba is broadcast-only node type. */ +} + +/*************************************************************************** + Convert a NetBIOS name to upper case. +***************************************************************************/ + static void upcase_name( struct nmb_name *target, struct nmb_name *source ) - { - int i; - - if( NULL != source ) - (void)memcpy( target, source, sizeof( struct nmb_name ) ); - - strupper_m( target->name ); - strupper_m( target->scope ); - - /* fudge... We're using a byte-by-byte compare, so we must be sure that - * unused space doesn't have garbage in it. - */ - for( i = strlen( target->name ); i < sizeof( target->name ); i++ ) - target->name[i] = '\0'; - for( i = strlen( target->scope ); i < sizeof( target->scope ); i++ ) - target->scope[i] = '\0'; - } /* upcase_name */ - -/* ************************************************************************** ** - * Add a new or overwrite an existing namelist entry. - * ************************************************************************** ** - */ +{ + int i; + nstring targ; + fstring scope; + + if( NULL != source ) + memcpy( target, source, sizeof( struct nmb_name ) ); + + pull_ascii_nstring(targ, target->name); + strupper_m( targ ); + push_ascii_nstring( target->name, targ); + + pull_ascii(scope, target->scope, 64, -1, STR_TERMINATE); + strupper_m( scope ); + push_ascii(target->scope, scope, 64, STR_TERMINATE); + + /* fudge... We're using a byte-by-byte compare, so we must be sure that + * unused space doesn't have garbage in it. + */ + + for( i = strlen( target->name ); i < sizeof( target->name ); i++ ) + target->name[i] = '\0'; + for( i = strlen( target->scope ); i < sizeof( target->scope ); i++ ) + target->scope[i] = '\0'; +} + +/************************************************************************** + Add a new or overwrite an existing namelist entry. +***************************************************************************/ + static void update_name_in_namelist( struct subnet_record *subrec, struct name_record *namerec ) - { - struct name_record *oldrec = NULL; - - (void)ubi_trInsert( subrec->namelist, namerec, &(namerec->name), &oldrec ); - if( oldrec ) - { - SAFE_FREE( oldrec->data.ip ); - SAFE_FREE( oldrec ); - } - } /* update_name_in_namelist */ - -/* ************************************************************************** ** - * Remove a name from the namelist. - * ************************************************************************** ** - */ -void remove_name_from_namelist( struct subnet_record *subrec, - struct name_record *namerec ) - { - (void)ubi_trRemove( subrec->namelist, namerec ); +{ + struct name_record *oldrec = NULL; - SAFE_FREE(namerec->data.ip); + ubi_trInsert( subrec->namelist, namerec, &(namerec->name), &oldrec ); + if( oldrec ) { + SAFE_FREE( oldrec->data.ip ); + SAFE_FREE( oldrec ); + } +} - ZERO_STRUCTP(namerec); - SAFE_FREE(namerec); +/************************************************************************** + Remove a name from the namelist. +***************************************************************************/ + +void remove_name_from_namelist( struct subnet_record *subrec, + struct name_record *namerec ) +{ + ubi_trRemove( subrec->namelist, namerec ); + SAFE_FREE(namerec->data.ip); + ZERO_STRUCTP(namerec); + SAFE_FREE(namerec); + subrec->namelist_changed = True; +} - subrec->namelist_changed = True; - } /* remove_name_from_namelist */ +/************************************************************************** + Find a name in a subnet. +**************************************************************************/ -/* ************************************************************************** ** - * Find a name in a subnet. - * ************************************************************************** ** - */ struct name_record *find_name_on_subnet( struct subnet_record *subrec, struct nmb_name *nmbname, BOOL self_only ) - { - struct nmb_name uc_name[1]; - struct name_record *name_ret; - - upcase_name( uc_name, nmbname ); - name_ret = (struct name_record *)ubi_trFind( subrec->namelist, uc_name ); - if( name_ret ) - { - /* Self names only - these include permanent names. */ - if( self_only - && (name_ret->data.source != SELF_NAME) - && (name_ret->data.source != PERMANENT_NAME) ) - { - DEBUG( 9, - ( "find_name_on_subnet: on subnet %s - self name %s NOT FOUND\n", - subrec->subnet_name, nmb_namestr(nmbname) ) ); - return( NULL ); - } - DEBUG( 9, ("find_name_on_subnet: on subnet %s - found name %s source=%d\n", - subrec->subnet_name, nmb_namestr(nmbname), name_ret->data.source) ); - return( name_ret ); - } - DEBUG( 9, - ( "find_name_on_subnet: on subnet %s - name %s NOT FOUND\n", - subrec->subnet_name, nmb_namestr(nmbname) ) ); - return( NULL ); - } /* find_name_on_subnet */ - -/* ************************************************************************** ** - * Find a name over all known broadcast subnets. - * ************************************************************************** ** - */ +{ + struct nmb_name uc_name[1]; + struct name_record *name_ret; + + upcase_name( uc_name, nmbname ); + name_ret = (struct name_record *)ubi_trFind( subrec->namelist, uc_name ); + if( name_ret ) { + /* Self names only - these include permanent names. */ + if( self_only && (name_ret->data.source != SELF_NAME) && (name_ret->data.source != PERMANENT_NAME) ) { + DEBUG( 9, ( "find_name_on_subnet: on subnet %s - self name %s NOT FOUND\n", + subrec->subnet_name, nmb_namestr(nmbname) ) ); + return( NULL ); + } + + DEBUG( 9, ("find_name_on_subnet: on subnet %s - found name %s source=%d\n", + subrec->subnet_name, nmb_namestr(nmbname), name_ret->data.source) ); + return( name_ret ); + } + + DEBUG( 9, ( "find_name_on_subnet: on subnet %s - name %s NOT FOUND\n", + subrec->subnet_name, nmb_namestr(nmbname) ) ); + return( NULL ); +} + +/************************************************************************** + Find a name over all known broadcast subnets. +************************************************************************/ + struct name_record *find_name_for_remote_broadcast_subnet( struct nmb_name *nmbname, BOOL self_only ) - { - struct subnet_record *subrec; - struct name_record *namerec = NULL; - - for( subrec = FIRST_SUBNET; - subrec; - subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) ) - { - if( NULL != (namerec = find_name_on_subnet(subrec, nmbname, self_only)) ) - break; - } - - return( namerec ); - } /* find_name_for_remote_broadcast_subnet */ +{ + struct subnet_record *subrec; + struct name_record *namerec = NULL; + + for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) ) { + if( NULL != (namerec = find_name_on_subnet(subrec, nmbname, self_only)) ) + break; + } + + return( namerec ); +} -/* ************************************************************************** ** - * Update the ttl of an entry in a subnet name list. - * ************************************************************************** ** - */ +/************************************************************************** + Update the ttl of an entry in a subnet name list. +***************************************************************************/ + void update_name_ttl( struct name_record *namerec, int ttl ) { - time_t time_now = time(NULL); + time_t time_now = time(NULL); - if( namerec->data.death_time != PERMANENT_TTL ) - namerec->data.death_time = time_now + ttl; + if( namerec->data.death_time != PERMANENT_TTL ) + namerec->data.death_time = time_now + ttl; - namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME); + namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME); + + namerec->subnet->namelist_changed = True; +} - namerec->subnet->namelist_changed = True; -} /* update_name_ttl */ +/************************************************************************** + Add an entry to a subnet name list. +***********************************************************************/ -/* ************************************************************************** ** - * Add an entry to a subnet name list. - * ************************************************************************** ** - */ struct name_record *add_name_to_subnet( struct subnet_record *subrec, const char *name, int type, @@ -181,70 +178,66 @@ struct name_record *add_name_to_subnet( struct subnet_record *subrec, int num_ips, struct in_addr *iplist) { - struct name_record *namerec; - time_t time_now = time(NULL); + struct name_record *namerec; + time_t time_now = time(NULL); - namerec = (struct name_record *)malloc( sizeof(*namerec) ); - if( NULL == namerec ) - { - DEBUG( 0, ( "add_name_to_subnet: malloc fail.\n" ) ); - return( NULL ); - } + namerec = (struct name_record *)malloc( sizeof(*namerec) ); + if( NULL == namerec ) { + DEBUG( 0, ( "add_name_to_subnet: malloc fail.\n" ) ); + return( NULL ); + } - memset( (char *)namerec, '\0', sizeof(*namerec) ); - namerec->data.ip = (struct in_addr *)malloc( sizeof(struct in_addr) - * num_ips ); - if( NULL == namerec->data.ip ) - { - DEBUG( 0, ( "add_name_to_subnet: malloc fail when creating ip_flgs.\n" ) ); + memset( (char *)namerec, '\0', sizeof(*namerec) ); + namerec->data.ip = (struct in_addr *)malloc( sizeof(struct in_addr) * num_ips ); + if( NULL == namerec->data.ip ) { + DEBUG( 0, ( "add_name_to_subnet: malloc fail when creating ip_flgs.\n" ) ); + ZERO_STRUCTP(namerec); + SAFE_FREE(namerec); + return NULL; + } - ZERO_STRUCTP(namerec); - SAFE_FREE(namerec); - return NULL; - } + namerec->subnet = subrec; - namerec->subnet = subrec; + make_nmb_name(&namerec->name, name, type); + upcase_name(&namerec->name, NULL ); - make_nmb_name(&namerec->name, name, type); - upcase_name(&namerec->name, NULL ); + /* Enter the name as active. */ + namerec->data.nb_flags = nb_flags | NB_ACTIVE; + namerec->data.wins_flags = WINS_ACTIVE; - /* Enter the name as active. */ - namerec->data.nb_flags = nb_flags | NB_ACTIVE; - namerec->data.wins_flags = WINS_ACTIVE; + /* If it's our primary name, flag it as so. */ + if( strequal( my_netbios_names(0), name ) ) + namerec->data.nb_flags |= NB_PERM; - /* If it's our primary name, flag it as so. */ - if( strequal( my_netbios_names(0), name ) ) - namerec->data.nb_flags |= NB_PERM; + /* Copy the IPs. */ + namerec->data.num_ips = num_ips; + memcpy( (namerec->data.ip), iplist, num_ips * sizeof(struct in_addr) ); - /* Copy the IPs. */ - namerec->data.num_ips = num_ips; - memcpy( (namerec->data.ip), iplist, num_ips * sizeof(struct in_addr) ); + /* Data source. */ + namerec->data.source = source; - /* Data source. */ - namerec->data.source = source; + /* Setup the death_time and refresh_time. */ + if( ttl == PERMANENT_TTL ) + namerec->data.death_time = PERMANENT_TTL; + else + namerec->data.death_time = time_now + ttl; - /* Setup the death_time and refresh_time. */ - if( ttl == PERMANENT_TTL ) - namerec->data.death_time = PERMANENT_TTL; - else - namerec->data.death_time = time_now + ttl; + namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME); - namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME); + /* Now add the record to the name list. */ + update_name_in_namelist( subrec, namerec ); - /* Now add the record to the name list. */ - update_name_in_namelist( subrec, namerec ); - - DEBUG( 3, ( "add_name_to_subnet: Added netbios name %s with first IP %s \ + DEBUG( 3, ( "add_name_to_subnet: Added netbios name %s with first IP %s \ ttl=%d nb_flags=%2x to subnet %s\n", - nmb_namestr( &namerec->name ), - inet_ntoa( *iplist ), - ttl, - (unsigned int)nb_flags, - subrec->subnet_name ) ); + nmb_namestr( &namerec->name ), + inet_ntoa( *iplist ), + ttl, + (unsigned int)nb_flags, + subrec->subnet_name ) ); - subrec->namelist_changed = True; + subrec->namelist_changed = True; - return(namerec); + return(namerec); } /******************************************************************* @@ -258,14 +251,17 @@ void standard_success_register(struct subnet_record *subrec, struct nmb_name *nmbname, uint16 nb_flags, int ttl, struct in_addr registered_ip) { - struct name_record *namerec; - - namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME ); - if( NULL == namerec ) - (void)add_name_to_subnet( subrec, nmbname->name, nmbname->name_type, - nb_flags, ttl, SELF_NAME, 1, ®istered_ip ); - else - update_name_ttl( namerec, ttl ); + struct name_record *namerec; + + namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME ); + if( NULL == namerec ) { + nstring name; + pull_ascii_nstring(name, nmbname->name); + add_name_to_subnet( subrec, name, nmbname->name_type, + nb_flags, ttl, SELF_NAME, 1, ®istered_ip ); + } else { + update_name_ttl( namerec, ttl ); + } } /******************************************************************* @@ -279,17 +275,16 @@ void standard_fail_register( struct subnet_record *subrec, struct response_record *rrec, struct nmb_name *nmbname ) { - struct name_record *namerec; + struct name_record *namerec; - namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME ); + namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME ); - DEBUG( 0, ( "standard_fail_register: Failed to register/refresh name %s \ -on subnet %s\n", - nmb_namestr(nmbname), subrec->subnet_name) ); + DEBUG( 0, ( "standard_fail_register: Failed to register/refresh name %s \ +on subnet %s\n", nmb_namestr(nmbname), subrec->subnet_name) ); - /* Remove the name from the subnet. */ - if( namerec ) - remove_name_from_namelist(subrec, namerec); + /* Remove the name from the subnet. */ + if( namerec ) + remove_name_from_namelist(subrec, namerec); } /******************************************************************* @@ -298,13 +293,13 @@ on subnet %s\n", static void remove_nth_ip_in_record( struct name_record *namerec, int ind) { - if( ind != namerec->data.num_ips ) - memmove( (char *)(&namerec->data.ip[ind]), - (char *)(&namerec->data.ip[ind+1]), - ( namerec->data.num_ips - ind - 1) * sizeof(struct in_addr) ); + if( ind != namerec->data.num_ips ) + memmove( (char *)(&namerec->data.ip[ind]), + (char *)(&namerec->data.ip[ind+1]), + ( namerec->data.num_ips - ind - 1) * sizeof(struct in_addr) ); - namerec->data.num_ips--; - namerec->subnet->namelist_changed = True; + namerec->data.num_ips--; + namerec->subnet->namelist_changed = True; } /******************************************************************* @@ -313,13 +308,13 @@ static void remove_nth_ip_in_record( struct name_record *namerec, int ind) BOOL find_ip_in_name_record( struct name_record *namerec, struct in_addr ip ) { - int i; + int i; - for(i = 0; i < namerec->data.num_ips; i++) - if(ip_equal( namerec->data.ip[i], ip)) - return True; + for(i = 0; i < namerec->data.num_ips; i++) + if(ip_equal( namerec->data.ip[i], ip)) + return True; - return False; + return False; } /******************************************************************* @@ -328,30 +323,26 @@ BOOL find_ip_in_name_record( struct name_record *namerec, struct in_addr ip ) void add_ip_to_name_record( struct name_record *namerec, struct in_addr new_ip ) { - struct in_addr *new_list; + struct in_addr *new_list; - /* Don't add one we already have. */ - if( find_ip_in_name_record( namerec, new_ip ) ) - return; + /* Don't add one we already have. */ + if( find_ip_in_name_record( namerec, new_ip ) ) + return; - new_list = (struct in_addr *)malloc( (namerec->data.num_ips + 1) - * sizeof(struct in_addr) ); - if( NULL == new_list ) - { - DEBUG(0,("add_ip_to_name_record: Malloc fail !\n")); - return; - } - - memcpy( (char *)new_list, - (char *)namerec->data.ip, - namerec->data.num_ips * sizeof(struct in_addr) ); - new_list[namerec->data.num_ips] = new_ip; - - SAFE_FREE(namerec->data.ip); - namerec->data.ip = new_list; - namerec->data.num_ips += 1; - - namerec->subnet->namelist_changed = True; + new_list = (struct in_addr *)malloc( (namerec->data.num_ips + 1) * sizeof(struct in_addr) ); + if( NULL == new_list ) { + DEBUG(0,("add_ip_to_name_record: Malloc fail !\n")); + return; + } + + memcpy( (char *)new_list, (char *)namerec->data.ip, namerec->data.num_ips * sizeof(struct in_addr) ); + new_list[namerec->data.num_ips] = new_ip; + + SAFE_FREE(namerec->data.ip); + namerec->data.ip = new_list; + namerec->data.num_ips += 1; + + namerec->subnet->namelist_changed = True; } /******************************************************************* @@ -361,16 +352,16 @@ void add_ip_to_name_record( struct name_record *namerec, struct in_addr new_ip ) void remove_ip_from_name_record( struct name_record *namerec, struct in_addr remove_ip ) { - /* Try and find the requested ip address - remove it. */ - int i; - int orig_num = namerec->data.num_ips; - - for(i = 0; i < orig_num; i++) - if( ip_equal( remove_ip, namerec->data.ip[i]) ) - { - remove_nth_ip_in_record( namerec, i); - break; - } + /* Try and find the requested ip address - remove it. */ + int i; + int orig_num = namerec->data.num_ips; + + for(i = 0; i < orig_num; i++) { + if( ip_equal( remove_ip, namerec->data.ip[i]) ) { + remove_nth_ip_in_record( namerec, i); + break; + } + } } /******************************************************************* @@ -384,85 +375,67 @@ void standard_success_release( struct subnet_record *subrec, struct nmb_name *nmbname, struct in_addr released_ip ) { - struct name_record *namerec; - - namerec = find_name_on_subnet( subrec, nmbname, FIND_ANY_NAME ); - - if( namerec == NULL ) - { - DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \ -on subnet %s. Name was not found on subnet.\n", - nmb_namestr(nmbname), - inet_ntoa(released_ip), - subrec->subnet_name) ); - return; - } - else - { - int orig_num = namerec->data.num_ips; - - remove_ip_from_name_record( namerec, released_ip ); - - if( namerec->data.num_ips == orig_num ) - DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \ -on subnet %s. This ip is not known for this name.\n", - nmb_namestr(nmbname), - inet_ntoa(released_ip), - subrec->subnet_name ) ); - } - - if( namerec->data.num_ips == 0 ) - remove_name_from_namelist( subrec, namerec ); + struct name_record *namerec; + + namerec = find_name_on_subnet( subrec, nmbname, FIND_ANY_NAME ); + if( namerec == NULL ) { + DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \ +on subnet %s. Name was not found on subnet.\n", nmb_namestr(nmbname), inet_ntoa(released_ip), + subrec->subnet_name) ); + return; + } else { + int orig_num = namerec->data.num_ips; + + remove_ip_from_name_record( namerec, released_ip ); + + if( namerec->data.num_ips == orig_num ) + DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \ +on subnet %s. This ip is not known for this name.\n", nmb_namestr(nmbname), inet_ntoa(released_ip), subrec->subnet_name ) ); + } + + if( namerec->data.num_ips == 0 ) + remove_name_from_namelist( subrec, namerec ); } /******************************************************************* Expires old names in a subnet namelist. - ******************************************************************/ +******************************************************************/ void expire_names_on_subnet(struct subnet_record *subrec, time_t t) { - struct name_record *namerec; - struct name_record *next_namerec; - - for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); - namerec; - namerec = next_namerec ) - { - next_namerec = (struct name_record *)ubi_trNext( namerec ); - if( (namerec->data.death_time != PERMANENT_TTL) - && (namerec->data.death_time < t) ) - { - if( namerec->data.source == SELF_NAME ) - { - DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF \ -name %s\n", - subrec->subnet_name, nmb_namestr(&namerec->name) ) ); - namerec->data.death_time += 300; - namerec->subnet->namelist_changed = True; - continue; - } - DEBUG(3,("expire_names_on_subnet: Subnet %s - removing expired name %s\n", - subrec->subnet_name, nmb_namestr(&namerec->name))); + struct name_record *namerec; + struct name_record *next_namerec; + + for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); namerec; namerec = next_namerec ) { + next_namerec = (struct name_record *)ubi_trNext( namerec ); + if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) { + if( namerec->data.source == SELF_NAME ) { + DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF \ +name %s\n", subrec->subnet_name, nmb_namestr(&namerec->name) ) ); + namerec->data.death_time += 300; + namerec->subnet->namelist_changed = True; + continue; + } + + DEBUG(3,("expire_names_on_subnet: Subnet %s - removing expired name %s\n", + subrec->subnet_name, nmb_namestr(&namerec->name))); - remove_name_from_namelist( subrec, namerec ); - } - } + remove_name_from_namelist( subrec, namerec ); + } + } } /******************************************************************* Expires old names in all subnet namelists. - ******************************************************************/ +******************************************************************/ void expire_names(time_t t) { - struct subnet_record *subrec; - - for( subrec = FIRST_SUBNET; - subrec; - subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec) ) - { - expire_names_on_subnet( subrec, t ); - } + struct subnet_record *subrec; + + for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec) ) { + expire_names_on_subnet( subrec, t ); + } } /**************************************************************************** @@ -475,46 +448,39 @@ void expire_names(time_t t) void add_samba_names_to_subnet( struct subnet_record *subrec ) { - struct in_addr *iplist = &subrec->myip; - int num_ips = 1; - - /* These names are added permanently (ttl of zero) and will NOT be - refreshed. */ - - if( (subrec == unicast_subnet) - || (subrec == wins_server_subnet) - || (subrec == remote_broadcast_subnet) ) - { - struct subnet_record *bcast_subrecs; - int i; - /* Create an IP list containing all our known subnets. */ - - num_ips = iface_count(); - iplist = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr) ); - if( NULL == iplist ) - { - DEBUG(0,("add_samba_names_to_subnet: Malloc fail !\n")); - return; - } - - for( bcast_subrecs = FIRST_SUBNET, i = 0; - bcast_subrecs; - bcast_subrecs = NEXT_SUBNET_EXCLUDING_UNICAST(bcast_subrecs), i++ ) - iplist[i] = bcast_subrecs->myip; - - } - - (void)add_name_to_subnet(subrec,"*",0x0,samba_nb_type, PERMANENT_TTL, - PERMANENT_NAME, num_ips, iplist); - (void)add_name_to_subnet(subrec,"*",0x20,samba_nb_type,PERMANENT_TTL, - PERMANENT_NAME, num_ips, iplist); - (void)add_name_to_subnet(subrec,"__SAMBA__",0x20,samba_nb_type,PERMANENT_TTL, - PERMANENT_NAME, num_ips, iplist); - (void)add_name_to_subnet(subrec,"__SAMBA__",0x00,samba_nb_type,PERMANENT_TTL, - PERMANENT_NAME, num_ips, iplist); - - if(iplist != &subrec->myip) - SAFE_FREE(iplist); + struct in_addr *iplist = &subrec->myip; + int num_ips = 1; + + /* These names are added permanently (ttl of zero) and will NOT be refreshed. */ + + if( (subrec == unicast_subnet) || (subrec == wins_server_subnet) || (subrec == remote_broadcast_subnet) ) { + struct subnet_record *bcast_subrecs; + int i; + + /* Create an IP list containing all our known subnets. */ + + num_ips = iface_count(); + iplist = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr) ); + if( NULL == iplist ) { + DEBUG(0,("add_samba_names_to_subnet: Malloc fail !\n")); + return; + } + + for( bcast_subrecs = FIRST_SUBNET, i = 0; bcast_subrecs; bcast_subrecs = NEXT_SUBNET_EXCLUDING_UNICAST(bcast_subrecs), i++ ) + iplist[i] = bcast_subrecs->myip; + } + + add_name_to_subnet(subrec,"*",0x0,samba_nb_type, PERMANENT_TTL, + PERMANENT_NAME, num_ips, iplist); + add_name_to_subnet(subrec,"*",0x20,samba_nb_type,PERMANENT_TTL, + PERMANENT_NAME, num_ips, iplist); + add_name_to_subnet(subrec,"__SAMBA__",0x20,samba_nb_type,PERMANENT_TTL, + PERMANENT_NAME, num_ips, iplist); + add_name_to_subnet(subrec,"__SAMBA__",0x00,samba_nb_type,PERMANENT_TTL, + PERMANENT_NAME, num_ips, iplist); + + if(iplist != &subrec->myip) + SAFE_FREE(iplist); } /**************************************************************************** @@ -524,68 +490,65 @@ void add_samba_names_to_subnet( struct subnet_record *subrec ) static void dump_subnet_namelist( struct subnet_record *subrec, XFILE *fp) { - struct name_record *namerec; - const char *src_type; - struct tm *tm; - int i; - - x_fprintf(fp, "Subnet %s\n----------------------\n", subrec->subnet_name); - for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); - namerec; - namerec = (struct name_record *)ubi_trNext( namerec ) ) - { - x_fprintf(fp,"\tName = %s\t", nmb_namestr(&namerec->name)); - switch(namerec->data.source) - { - case LMHOSTS_NAME: - src_type = "LMHOSTS_NAME"; - break; - case WINS_PROXY_NAME: - src_type = "WINS_PROXY_NAME"; - break; - case REGISTER_NAME: - src_type = "REGISTER_NAME"; - break; - case SELF_NAME: - src_type = "SELF_NAME"; - break; - case DNS_NAME: - src_type = "DNS_NAME"; - break; - case DNSFAIL_NAME: - src_type = "DNSFAIL_NAME"; - break; - case PERMANENT_NAME: - src_type = "PERMANENT_NAME"; - break; - default: - src_type = "unknown!"; - break; - } - x_fprintf(fp,"Source = %s\nb_flags = %x\t", src_type, namerec->data.nb_flags); - - if(namerec->data.death_time != PERMANENT_TTL) - { - tm = LocalTime(&namerec->data.death_time); - x_fprintf(fp, "death_time = %s\t", asctime(tm)); - } - else - x_fprintf(fp, "death_time = PERMANENT\t"); - - if(namerec->data.refresh_time != PERMANENT_TTL) - { - tm = LocalTime(&namerec->data.refresh_time); - x_fprintf(fp, "refresh_time = %s\n", asctime(tm)); - } - else - x_fprintf(fp, "refresh_time = PERMANENT\n"); - - x_fprintf(fp, "\t\tnumber of IPS = %d", namerec->data.num_ips); - for(i = 0; i < namerec->data.num_ips; i++) - x_fprintf(fp, "\t%s", inet_ntoa(namerec->data.ip[i])); - - x_fprintf(fp, "\n\n"); - } + struct name_record *namerec; + const char *src_type; + struct tm *tm; + int i; + + x_fprintf(fp, "Subnet %s\n----------------------\n", subrec->subnet_name); + for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); namerec; + namerec = (struct name_record *)ubi_trNext( namerec ) ) { + + x_fprintf(fp,"\tName = %s\t", nmb_namestr(&namerec->name)); + switch(namerec->data.source) { + case LMHOSTS_NAME: + src_type = "LMHOSTS_NAME"; + break; + case WINS_PROXY_NAME: + src_type = "WINS_PROXY_NAME"; + break; + case REGISTER_NAME: + src_type = "REGISTER_NAME"; + break; + case SELF_NAME: + src_type = "SELF_NAME"; + break; + case DNS_NAME: + src_type = "DNS_NAME"; + break; + case DNSFAIL_NAME: + src_type = "DNSFAIL_NAME"; + break; + case PERMANENT_NAME: + src_type = "PERMANENT_NAME"; + break; + default: + src_type = "unknown!"; + break; + } + + x_fprintf(fp,"Source = %s\nb_flags = %x\t", src_type, namerec->data.nb_flags); + + if(namerec->data.death_time != PERMANENT_TTL) { + tm = LocalTime(&namerec->data.death_time); + x_fprintf(fp, "death_time = %s\t", asctime(tm)); + } else { + x_fprintf(fp, "death_time = PERMANENT\t"); + } + + if(namerec->data.refresh_time != PERMANENT_TTL) { + tm = LocalTime(&namerec->data.refresh_time); + x_fprintf(fp, "refresh_time = %s\n", asctime(tm)); + } else { + x_fprintf(fp, "refresh_time = PERMANENT\n"); + } + + x_fprintf(fp, "\t\tnumber of IPS = %d", namerec->data.num_ips); + for(i = 0; i < namerec->data.num_ips; i++) + x_fprintf(fp, "\t%s", inet_ntoa(namerec->data.ip[i])); + + x_fprintf(fp, "\n\n"); + } } /**************************************************************************** @@ -595,30 +558,27 @@ static void dump_subnet_namelist( struct subnet_record *subrec, XFILE *fp) void dump_all_namelists(void) { - XFILE *fp; - struct subnet_record *subrec; + XFILE *fp; + struct subnet_record *subrec; - fp = x_fopen(lock_path("namelist.debug"),O_WRONLY|O_CREAT|O_TRUNC, 0644); + fp = x_fopen(lock_path("namelist.debug"),O_WRONLY|O_CREAT|O_TRUNC, 0644); - if (!fp) - { - DEBUG(0,("dump_all_namelists: Can't open file %s. Error was %s\n", - "namelist.debug",strerror(errno))); - return; - } + if (!fp) { + DEBUG(0,("dump_all_namelists: Can't open file %s. Error was %s\n", + "namelist.debug",strerror(errno))); + return; + } - for( subrec = FIRST_SUBNET; - subrec; - subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec) ) - dump_subnet_namelist( subrec, fp ); + for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec) ) + dump_subnet_namelist( subrec, fp ); - if( !we_are_a_wins_client() ) - dump_subnet_namelist( unicast_subnet, fp ); + if( !we_are_a_wins_client() ) + dump_subnet_namelist( unicast_subnet, fp ); - if( remote_broadcast_subnet->namelist != NULL ) - dump_subnet_namelist( remote_broadcast_subnet, fp ); + if( remote_broadcast_subnet->namelist != NULL ) + dump_subnet_namelist( remote_broadcast_subnet, fp ); - if( wins_server_subnet != NULL ) - dump_subnet_namelist( wins_server_subnet, fp ); - x_fclose( fp ); + if( wins_server_subnet != NULL ) + dump_subnet_namelist( wins_server_subnet, fp ); + x_fclose( fp ); } diff --git a/source/nmbd/nmbd_namequery.c b/source/nmbd/nmbd_namequery.c index 2a200713b9f..1b07852f111 100644 --- a/source/nmbd/nmbd_namequery.c +++ b/source/nmbd/nmbd_namequery.c @@ -3,7 +3,7 @@ NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 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 @@ -31,106 +31,95 @@ static void query_name_response( struct subnet_record *subrec, struct response_record *rrec, struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - BOOL success = False; - struct nmb_name *question_name = - &rrec->packet->packet.nmb.question.question_name; - struct in_addr answer_ip; - - zero_ip(&answer_ip); - - /* Ensure we don't retry the query but leave the response record cleanup - to the timeout code. We may get more answer responses in which case - we should mark the name in conflict.. */ - rrec->repeat_count = 0; - - if(rrec->num_msgs == 1) - { - /* This is the first response. */ - - if(nmb->header.opcode == NMB_WACK_OPCODE) - { - /* WINS server is telling us to wait. Pretend we didn't get - the response but don't send out any more query requests. */ - - if( DEBUGLVL( 5 ) ) - { - dbgtext( "query_name_response: " ); - dbgtext( "WACK from WINS server %s ", inet_ntoa(p->ip) ); - dbgtext( "in querying name %s ", nmb_namestr(question_name) ); - dbgtext( "on subnet %s.\n", subrec->subnet_name ); - } + struct nmb_packet *nmb = &p->packet.nmb; + BOOL success = False; + struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name; + struct in_addr answer_ip; + + zero_ip(&answer_ip); + + /* Ensure we don't retry the query but leave the response record cleanup + to the timeout code. We may get more answer responses in which case + we should mark the name in conflict.. */ + rrec->repeat_count = 0; + + if(rrec->num_msgs == 1) { + /* This is the first response. */ + + if(nmb->header.opcode == NMB_WACK_OPCODE) { + /* WINS server is telling us to wait. Pretend we didn't get + the response but don't send out any more query requests. */ + + if( DEBUGLVL( 5 ) ) { + dbgtext( "query_name_response: " ); + dbgtext( "WACK from WINS server %s ", inet_ntoa(p->ip) ); + dbgtext( "in querying name %s ", nmb_namestr(question_name) ); + dbgtext( "on subnet %s.\n", subrec->subnet_name ); + } - rrec->repeat_count = 0; - /* How long we should wait for. */ - rrec->repeat_time = p->timestamp + nmb->answers->ttl; - rrec->num_msgs--; - return; - } - else if(nmb->header.rcode != 0) - { - success = False; - - if( DEBUGLVL( 5 ) ) - { - dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name ); - dbgtext( "- negative response from IP %s ", inet_ntoa(p->ip) ); - dbgtext( "for name %s. ", nmb_namestr(question_name) ); - dbgtext( "Error code was %d.\n", nmb->header.rcode ); - } - } - else - { - if (!nmb->answers) - { - dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name ); - dbgtext( "IP %s ", inet_ntoa(p->ip) ); - dbgtext( "returned a success response with no answer\n" ); - return; - } - - success = True; - - putip((char *)&answer_ip,&nmb->answers->rdata[2]); - if( DEBUGLVL( 5 ) ) - { - dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name ); - dbgtext( "- positive response from IP %s ", inet_ntoa(p->ip) ); - dbgtext( "for name %s. ", nmb_namestr(question_name) ); - dbgtext( "IP of that name is %s\n", inet_ntoa(answer_ip) ); - } - - /* Interestingly, we could add these names to our namelists, and - change nmbd to a model that checked its own name cache first, - before sending out a query. This is a task for another day, though. - */ - } - } - else if( rrec->num_msgs > 1) - { - if( DEBUGLVL( 0 ) ) - { - if (nmb->answers) - putip( (char *)&answer_ip, &nmb->answers->rdata[2] ); - dbgtext( "query_name_response: " ); - dbgtext( "Multiple (%d) responses ", rrec->num_msgs ); - dbgtext( "received for a query on subnet %s ", subrec->subnet_name ); - dbgtext( "for name %s.\nThis response ", nmb_namestr(question_name) ); - dbgtext( "was from IP %s, reporting ", inet_ntoa(p->ip) ); - dbgtext( "an IP address of %s.\n", inet_ntoa(answer_ip) ); - } - - /* We have already called the success or fail function, so we - don't call again here. Leave the response record around in - case we get more responses. */ - - return; - } + rrec->repeat_count = 0; + /* How long we should wait for. */ + rrec->repeat_time = p->timestamp + nmb->answers->ttl; + rrec->num_msgs--; + return; + } else if(nmb->header.rcode != 0) { + + success = False; + + if( DEBUGLVL( 5 ) ) { + dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name ); + dbgtext( "- negative response from IP %s ", inet_ntoa(p->ip) ); + dbgtext( "for name %s. ", nmb_namestr(question_name) ); + dbgtext( "Error code was %d.\n", nmb->header.rcode ); + } + } else { + if (!nmb->answers) { + dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name ); + dbgtext( "IP %s ", inet_ntoa(p->ip) ); + dbgtext( "returned a success response with no answer\n" ); + return; + } + + success = True; + + putip((char *)&answer_ip,&nmb->answers->rdata[2]); + + if( DEBUGLVL( 5 ) ) { + dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name ); + dbgtext( "- positive response from IP %s ", inet_ntoa(p->ip) ); + dbgtext( "for name %s. ", nmb_namestr(question_name) ); + dbgtext( "IP of that name is %s\n", inet_ntoa(answer_ip) ); + } + + /* Interestingly, we could add these names to our namelists, and + change nmbd to a model that checked its own name cache first, + before sending out a query. This is a task for another day, though. + */ + } + } else if( rrec->num_msgs > 1) { + + if( DEBUGLVL( 0 ) ) { + if (nmb->answers) + putip( (char *)&answer_ip, &nmb->answers->rdata[2] ); + dbgtext( "query_name_response: " ); + dbgtext( "Multiple (%d) responses ", rrec->num_msgs ); + dbgtext( "received for a query on subnet %s ", subrec->subnet_name ); + dbgtext( "for name %s.\nThis response ", nmb_namestr(question_name) ); + dbgtext( "was from IP %s, reporting ", inet_ntoa(p->ip) ); + dbgtext( "an IP address of %s.\n", inet_ntoa(answer_ip) ); + } + + /* We have already called the success or fail function, so we + don't call again here. Leave the response record around in + case we get more responses. */ + + return; + } - if(success && rrec->success_fn) - (*(query_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, answer_ip, nmb->answers); - else if( rrec->fail_fn) - (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, nmb->header.rcode); + if(success && rrec->success_fn) + (*(query_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, answer_ip, nmb->answers); + else if( rrec->fail_fn) + (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, nmb->header.rcode); } @@ -141,32 +130,30 @@ static void query_name_response( struct subnet_record *subrec, static void query_name_timeout_response(struct subnet_record *subrec, struct response_record *rrec) { - struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; - /* We can only fail here, never succeed. */ - BOOL failed = True; - struct nmb_name *question_name = &sent_nmb->question.question_name; - - if(rrec->num_msgs != 0) - { - /* We got at least one response, and have called the success/fail - function already. */ - - failed = False; - } - - if(failed) - { - if( DEBUGLVL( 5 ) ) - { - dbgtext( "query_name_timeout_response: No response to " ); - dbgtext( "query for name %s ", nmb_namestr(question_name) ); - dbgtext( "on subnet %s.\n", subrec->subnet_name ); - } - if(rrec->fail_fn) - (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, 0); - } - - remove_response_record(subrec, rrec); + struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; + /* We can only fail here, never succeed. */ + BOOL failed = True; + struct nmb_name *question_name = &sent_nmb->question.question_name; + + if(rrec->num_msgs != 0) { + /* We got at least one response, and have called the success/fail + function already. */ + + failed = False; + } + + if(failed) { + if( DEBUGLVL( 5 ) ) { + dbgtext( "query_name_timeout_response: No response to " ); + dbgtext( "query for name %s ", nmb_namestr(question_name) ); + dbgtext( "on subnet %s.\n", subrec->subnet_name ); + } + + if(rrec->fail_fn) + (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, 0); + } + + remove_response_record(subrec, rrec); } /**************************************************************************** @@ -177,24 +164,21 @@ static void query_name_timeout_response(struct subnet_record *subrec, static BOOL query_local_namelists(struct subnet_record *subrec, struct nmb_name *nmbname, struct name_record **namerecp) { - struct name_record *namerec; + struct name_record *namerec; - *namerecp = NULL; + *namerecp = NULL; - if(find_name_in_lmhosts(nmbname, namerecp)) - return True; + if(find_name_in_lmhosts(nmbname, namerecp)) + return True; - if((namerec = find_name_on_subnet(subrec, nmbname, FIND_ANY_NAME))==NULL) - return False; - - if( NAME_IS_ACTIVE(namerec) - && ( (namerec->data.source == SELF_NAME) - || (namerec->data.source == LMHOSTS_NAME) ) ) - { - *namerecp = namerec; - return True; - } - return False; + if((namerec = find_name_on_subnet(subrec, nmbname, FIND_ANY_NAME))==NULL) + return False; + + if( NAME_IS_ACTIVE(namerec) && ( (namerec->data.source == SELF_NAME) || (namerec->data.source == LMHOSTS_NAME) ) ) { + *namerecp = namerec; + return True; + } + return False; } /**************************************************************************** @@ -206,69 +190,57 @@ BOOL query_name(struct subnet_record *subrec, const char *name, int type, query_name_fail_function fail_fn, struct userdata_struct *userdata) { - struct nmb_name nmbname; - struct name_record *namerec; - - make_nmb_name(&nmbname, name, type); - - /* - * We need to check our local namelists first. - * It may be an magic name, lmhosts name or just - * a name we have registered. - */ - - if(query_local_namelists(subrec, &nmbname, &namerec) == True) - { - struct res_rec rrec; - int i; - - memset((char *)&rrec, '\0', sizeof(struct res_rec)); - - /* Fake up the needed res_rec just in case it's used. */ - rrec.rr_name = nmbname; - rrec.rr_type = RR_TYPE_NB; - rrec.rr_class = RR_CLASS_IN; - rrec.ttl = PERMANENT_TTL; - rrec.rdlength = namerec->data.num_ips * 6; - if(rrec.rdlength > MAX_DGRAM_SIZE) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "query_name: nmbd internal error - " ); - dbgtext( "there are %d ip addresses ", namerec->data.num_ips ); - dbgtext( "for name %s.\n", nmb_namestr(&nmbname) ); - } - return False; - } - - for( i = 0; i < namerec->data.num_ips; i++) - { - set_nb_flags( &rrec.rdata[i*6], namerec->data.nb_flags ); - putip( &rrec.rdata[(i*6) + 2], (char *)&namerec->data.ip[i]); - } - - /* Call the success function directly. */ - if(success_fn) - (*(query_name_success_function)success_fn)(subrec, userdata, &nmbname, namerec->data.ip[0], &rrec); - return False; - } - - if(queue_query_name( subrec, - query_name_response, - query_name_timeout_response, - success_fn, - fail_fn, - userdata, - &nmbname) == NULL) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "query_name: Failed to send packet " ); - dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) ); - } - return True; - } - return False; + struct nmb_name nmbname; + struct name_record *namerec; + + make_nmb_name(&nmbname, name, type); + + /* + * We need to check our local namelists first. + * It may be an magic name, lmhosts name or just + * a name we have registered. + */ + + if(query_local_namelists(subrec, &nmbname, &namerec) == True) { + struct res_rec rrec; + int i; + + memset((char *)&rrec, '\0', sizeof(struct res_rec)); + + /* Fake up the needed res_rec just in case it's used. */ + rrec.rr_name = nmbname; + rrec.rr_type = RR_TYPE_NB; + rrec.rr_class = RR_CLASS_IN; + rrec.ttl = PERMANENT_TTL; + rrec.rdlength = namerec->data.num_ips * 6; + if(rrec.rdlength > MAX_DGRAM_SIZE) { + if( DEBUGLVL( 0 ) ) { + dbgtext( "query_name: nmbd internal error - " ); + dbgtext( "there are %d ip addresses ", namerec->data.num_ips ); + dbgtext( "for name %s.\n", nmb_namestr(&nmbname) ); + } + return False; + } + + for( i = 0; i < namerec->data.num_ips; i++) { + set_nb_flags( &rrec.rdata[i*6], namerec->data.nb_flags ); + putip( &rrec.rdata[(i*6) + 2], (char *)&namerec->data.ip[i]); + } + + /* Call the success function directly. */ + if(success_fn) + (*(query_name_success_function)success_fn)(subrec, userdata, &nmbname, namerec->data.ip[0], &rrec); + return False; + } + + if(queue_query_name( subrec, query_name_response, query_name_timeout_response, success_fn, fail_fn, userdata, &nmbname) == NULL) { + if( DEBUGLVL( 0 ) ) { + dbgtext( "query_name: Failed to send packet " ); + dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) ); + } + return True; + } + return False; } /**************************************************************************** @@ -281,24 +253,16 @@ BOOL query_name_from_wins_server(struct in_addr ip_to, query_name_fail_function fail_fn, struct userdata_struct *userdata) { - struct nmb_name nmbname; - - make_nmb_name(&nmbname, name, type); - - if(queue_query_name_from_wins_server( ip_to, - query_name_response, - query_name_timeout_response, - success_fn, - fail_fn, - userdata, - &nmbname) == NULL) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "query_name_from_wins_server: Failed to send packet " ); - dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) ); - } - return True; - } - return False; + struct nmb_name nmbname; + + make_nmb_name(&nmbname, name, type); + + if(queue_query_name_from_wins_server( ip_to, query_name_response, query_name_timeout_response, success_fn, fail_fn, userdata, &nmbname) == NULL) { + if( DEBUGLVL( 0 ) ) { + dbgtext( "query_name_from_wins_server: Failed to send packet " ); + dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) ); + } + return True; + } + return False; } diff --git a/source/nmbd/nmbd_nameregister.c b/source/nmbd/nmbd_nameregister.c index 7bf2584053f..5c9deeb4dbe 100644 --- a/source/nmbd/nmbd_nameregister.c +++ b/source/nmbd/nmbd_nameregister.c @@ -3,7 +3,7 @@ NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 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 @@ -85,7 +85,9 @@ static void register_name_response(struct subnet_record *subrec, */ #if 1 /* OLD_SAMBA_SERVER_HACK */ - if((nmb->header.rcode == ACT_ERR) && strequal(lp_workgroup(), answer_name->name) && + nstring ans_name; + pull_ascii_nstring(ans_name, answer_name->name); + if((nmb->header.rcode == ACT_ERR) && strequal(lp_workgroup(), ans_name) && (answer_name->name_type == 0x1b)) { /* Pretend we did not get this. */ rrec->num_msgs--; @@ -161,10 +163,10 @@ static void register_name_response(struct subnet_record *subrec, remove_response_record(subrec, rrec); } - /**************************************************************************** Deal with a timeout of a WINS registration request ****************************************************************************/ + static void wins_registration_timeout(struct subnet_record *subrec, struct response_record *rrec) { @@ -233,7 +235,6 @@ static void wins_registration_timeout(struct subnet_record *subrec, us trying to register with each of our failover wins servers */ } - /**************************************************************************** Deal with a timeout when registering one of our names. ****************************************************************************/ @@ -290,10 +291,10 @@ static void register_name_timeout_response(struct subnet_record *subrec, remove_response_record(subrec, rrec); } - /**************************************************************************** -initiate one multi-homed name registration packet + Initiate one multi-homed name registration packet. ****************************************************************************/ + static void multihomed_register_one(struct nmb_name *nmbname, uint16 nb_flags, register_name_success_function success_fn, @@ -336,11 +337,11 @@ static void multihomed_register_one(struct nmb_name *nmbname, free(userdata); } - /**************************************************************************** -we have finished the registration of one IP and need to see if we have -any more IPs left to register with this group of wins server for this name + We have finished the registration of one IP and need to see if we have + any more IPs left to register with this group of wins server for this name. ****************************************************************************/ + static void wins_next_registration(struct response_record *rrec) { struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; @@ -388,6 +389,7 @@ static void wins_next_registration(struct response_record *rrec) /**************************************************************************** Try and register one of our names on the unicast subnet - multihomed. ****************************************************************************/ + static void multihomed_register_name(struct nmb_name *nmbname, uint16 nb_flags, register_name_success_function success_fn, register_name_fail_function fail_fn) @@ -416,6 +418,7 @@ static void multihomed_register_name(struct nmb_name *nmbname, uint16 nb_flags, struct subnet_record *subrec; char **wins_tags; struct in_addr *ip_list; + nstring name; for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) ) num_ips++; @@ -431,7 +434,8 @@ static void multihomed_register_name(struct nmb_name *nmbname, uint16 nb_flags, ip_list[i] = subrec->myip; } - add_name_to_subnet(unicast_subnet, nmbname->name, nmbname->name_type, + pull_ascii_nstring(name, nmbname->name); + add_name_to_subnet(unicast_subnet, name, nmbname->name_type, nb_flags, lp_max_ttl(), SELF_NAME, num_ips, ip_list); @@ -456,10 +460,10 @@ static void multihomed_register_name(struct nmb_name *nmbname, uint16 nb_flags, SAFE_FREE(ip_list); } - /**************************************************************************** Try and register one of our names. ****************************************************************************/ + void register_name(struct subnet_record *subrec, const char *name, int type, uint16 nb_flags, register_name_success_function success_fn, @@ -498,10 +502,10 @@ void register_name(struct subnet_record *subrec, } } - /**************************************************************************** Try and refresh one of our names. This is *only* called for WINS refresh ****************************************************************************/ + void wins_refresh_name(struct name_record *namerec) { int t; diff --git a/source/nmbd/nmbd_nodestatus.c b/source/nmbd/nmbd_nodestatus.c index 993e4d9d175..0ea5d6a8182 100644 --- a/source/nmbd/nmbd_nodestatus.c +++ b/source/nmbd/nmbd_nodestatus.c @@ -3,7 +3,7 @@ NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 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 @@ -26,52 +26,52 @@ /**************************************************************************** Deal with a successful node status response. ****************************************************************************/ + static void node_status_response(struct subnet_record *subrec, struct response_record *rrec, struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name; - struct nmb_name *answer_name = &nmb->answers->rr_name; + struct nmb_packet *nmb = &p->packet.nmb; + struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name; + struct nmb_name *answer_name = &nmb->answers->rr_name; - /* Sanity check. Ensure that the answer name in the incoming packet is the - same as the requested name in the outgoing packet. */ + /* Sanity check. Ensure that the answer name in the incoming packet is the + same as the requested name in the outgoing packet. */ - if(!nmb_name_equal(question_name, answer_name)) - { - DEBUG(0,("node_status_response: Answer name %s differs from question \ + if(!nmb_name_equal(question_name, answer_name)) { + DEBUG(0,("node_status_response: Answer name %s differs from question \ name %s.\n", nmb_namestr(answer_name), nmb_namestr(question_name))); - return; - } + return; + } - DEBUG(5,("node_status_response: response from name %s on subnet %s.\n", - nmb_namestr(answer_name), subrec->subnet_name)); + DEBUG(5,("node_status_response: response from name %s on subnet %s.\n", + nmb_namestr(answer_name), subrec->subnet_name)); - /* Just send the whole answer resource record for the success function - to parse. */ - if(rrec->success_fn) - (*(node_status_success_function)rrec->success_fn)(subrec, rrec->userdata, nmb->answers, p->ip); + /* Just send the whole answer resource record for the success function to parse. */ + if(rrec->success_fn) + (*(node_status_success_function)rrec->success_fn)(subrec, rrec->userdata, nmb->answers, p->ip); - /* Ensure we don't retry. */ - remove_response_record(subrec, rrec); + /* Ensure we don't retry. */ + remove_response_record(subrec, rrec); } /**************************************************************************** Deal with a timeout when requesting a node status. ****************************************************************************/ + static void node_status_timeout_response(struct subnet_record *subrec, struct response_record *rrec) { - struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; - struct nmb_name *question_name = &sent_nmb->question.question_name; + struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; + struct nmb_name *question_name = &sent_nmb->question.question_name; - DEBUG(5,("node_status_timeout_response: failed to get node status from name %s on subnet %s\n", - nmb_namestr(question_name), subrec->subnet_name)); + DEBUG(5,("node_status_timeout_response: failed to get node status from name %s on subnet %s\n", + nmb_namestr(question_name), subrec->subnet_name)); - if( rrec->fail_fn) - (*rrec->fail_fn)(subrec, rrec); + if( rrec->fail_fn) + (*rrec->fail_fn)(subrec, rrec); - /* Ensure we don't retry. */ - remove_response_record(subrec, rrec); + /* Ensure we don't retry. */ + remove_response_record(subrec, rrec); } /**************************************************************************** @@ -82,13 +82,11 @@ BOOL node_status(struct subnet_record *subrec, struct nmb_name *nmbname, struct in_addr send_ip, node_status_success_function success_fn, node_status_fail_function fail_fn, struct userdata_struct *userdata) { - if(queue_node_status( subrec, - node_status_response, node_status_timeout_response, - success_fn, fail_fn, userdata, nmbname, send_ip)==NULL) - { - DEBUG(0,("node_status: Failed to send packet trying to get node status for \ + if(queue_node_status( subrec, node_status_response, node_status_timeout_response, + success_fn, fail_fn, userdata, nmbname, send_ip)==NULL) { + DEBUG(0,("node_status: Failed to send packet trying to get node status for \ name %s, IP address %s\n", nmb_namestr(nmbname), inet_ntoa(send_ip))); - return True; - } - return False; + return True; + } + return False; } diff --git a/source/nmbd/nmbd_packets.c b/source/nmbd/nmbd_packets.c index 6c3446d6c84..72eb1b50199 100644 --- a/source/nmbd/nmbd_packets.c +++ b/source/nmbd/nmbd_packets.c @@ -3,7 +3,7 @@ NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 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 @@ -50,13 +50,13 @@ Utility function to find the specific fd to send a packet out on. static int find_subnet_fd_for_address( struct in_addr local_ip ) { - struct subnet_record *subrec; + struct subnet_record *subrec; - for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - if(ip_equal(local_ip, subrec->myip)) - return subrec->nmb_sock; + for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) + if(ip_equal(local_ip, subrec->myip)) + return subrec->nmb_sock; - return ClientNMB; + return ClientNMB; } /*************************************************************************** @@ -65,13 +65,13 @@ Utility function to find the specific fd to send a mailslot packet out on. static int find_subnet_mailslot_fd_for_address( struct in_addr local_ip ) { - struct subnet_record *subrec; + struct subnet_record *subrec; - for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - if(ip_equal(local_ip, subrec->myip)) - return subrec->dgram_sock; + for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) + if(ip_equal(local_ip, subrec->myip)) + return subrec->dgram_sock; - return ClientDGRAM; + return ClientDGRAM; } /*************************************************************************** @@ -80,13 +80,13 @@ Get/Set problematic nb_flags as network byte order 16 bit int. uint16 get_nb_flags(char *buf) { - return ((((uint16)*buf)&0xFFFF) & NB_FLGMSK); + return ((((uint16)*buf)&0xFFFF) & NB_FLGMSK); } void set_nb_flags(char *buf, uint16 nb_flags) { - *buf++ = ((nb_flags & NB_FLGMSK) & 0xFF); - *buf = '\0'; + *buf++ = ((nb_flags & NB_FLGMSK) & 0xFF); + *buf = '\0'; } /*************************************************************************** @@ -95,37 +95,34 @@ Dumps out the browse packet data. static void debug_browse_data(char *outbuf, int len) { - int i,j; - - DEBUG( 4, ( "debug_browse_data():\n" ) ); - for (i = 0; i < len; i+= 16) - { - DEBUGADD( 4, ( "%3x char ", i ) ); - - for (j = 0; j < 16; j++) - { - unsigned char x; - if (i+j >= len) - break; - - x = outbuf[i+j]; - if (x < 32 || x > 127) - x = '.'; + int i,j; + + DEBUG( 4, ( "debug_browse_data():\n" ) ); + for (i = 0; i < len; i+= 16) { + DEBUGADD( 4, ( "%3x char ", i ) ); + + for (j = 0; j < 16; j++) { + unsigned char x; + if (i+j >= len) + break; + + x = outbuf[i+j]; + if (x < 32 || x > 127) + x = '.'; - DEBUGADD( 4, ( "%c", x ) ); - } + DEBUGADD( 4, ( "%c", x ) ); + } - DEBUGADD( 4, ( "%*s hex", 16-j, "" ) ); + DEBUGADD( 4, ( "%*s hex", 16-j, "" ) ); - for (j = 0; j < 16; j++) - { - if (i+j >= len) - break; - DEBUGADD( 4, ( " %02x", (unsigned char)outbuf[i+j] ) ); - } + for (j = 0; j < 16; j++) { + if (i+j >= len) + break; + DEBUGADD( 4, ( " %02x", (unsigned char)outbuf[i+j] ) ); + } - DEBUGADD( 4, ("\n") ); - } + DEBUGADD( 4, ("\n") ); + } } /*************************************************************************** @@ -136,13 +133,11 @@ static uint16 name_trn_id=0; static uint16 generate_name_trn_id(void) { - - if (!name_trn_id) - { - name_trn_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) + ((unsigned)sys_getpid()%(unsigned)100); - } - name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF; - return name_trn_id; + if (!name_trn_id) { + name_trn_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) + ((unsigned)sys_getpid()%(unsigned)100); + } + name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF; + return name_trn_id; } /*************************************************************************** @@ -151,28 +146,25 @@ static uint16 generate_name_trn_id(void) static BOOL send_netbios_packet(struct packet_struct *p) { - BOOL loopback_this_packet = False; - - /* Check if we are sending to or from ourselves as a WINS server. */ - if(ismyip(p->ip) && (p->port == global_nmb_port)) - loopback_this_packet = True; - - if(loopback_this_packet) - { - struct packet_struct *lo_packet = NULL; - DEBUG(5,("send_netbios_packet: sending packet to ourselves.\n")); - if((lo_packet = copy_packet(p)) == NULL) - return False; - queue_packet(lo_packet); - } - else if (!send_packet(p)) - { - DEBUG(0,("send_netbios_packet: send_packet() to IP %s port %d failed\n", - inet_ntoa(p->ip),p->port)); - return False; - } + BOOL loopback_this_packet = False; + + /* Check if we are sending to or from ourselves as a WINS server. */ + if(ismyip(p->ip) && (p->port == global_nmb_port)) + loopback_this_packet = True; + + if(loopback_this_packet) { + struct packet_struct *lo_packet = NULL; + DEBUG(5,("send_netbios_packet: sending packet to ourselves.\n")); + if((lo_packet = copy_packet(p)) == NULL) + return False; + queue_packet(lo_packet); + } else if (!send_packet(p)) { + DEBUG(0,("send_netbios_packet: send_packet() to IP %s port %d failed\n", + inet_ntoa(p->ip),p->port)); + return False; + } - return True; + return True; } /*************************************************************************** @@ -188,45 +180,44 @@ static struct packet_struct *create_and_init_netbios_packet(struct nmb_name *nmb BOOL bcast, BOOL rec_des, struct in_addr to_ip) { - struct packet_struct *packet = NULL; - struct nmb_packet *nmb = NULL; - - /* Allocate the packet_struct we will return. */ - if((packet = (struct packet_struct *)malloc(sizeof(*packet))) == NULL) - { - DEBUG(0,("create_and_init_netbios_packet: malloc fail (1) for packet struct.\n")); - return NULL; - } + struct packet_struct *packet = NULL; + struct nmb_packet *nmb = NULL; + + /* Allocate the packet_struct we will return. */ + if((packet = (struct packet_struct *)malloc(sizeof(*packet))) == NULL) { + DEBUG(0,("create_and_init_netbios_packet: malloc fail (1) for packet struct.\n")); + return NULL; + } - memset((char *)packet,'\0',sizeof(*packet)); + memset((char *)packet,'\0',sizeof(*packet)); - nmb = &packet->packet.nmb; + nmb = &packet->packet.nmb; - nmb->header.name_trn_id = generate_name_trn_id(); - nmb->header.response = False; - nmb->header.nm_flags.recursion_desired = rec_des; - nmb->header.nm_flags.recursion_available = False; - nmb->header.nm_flags.trunc = False; - nmb->header.nm_flags.authoritative = False; - nmb->header.nm_flags.bcast = bcast; + nmb->header.name_trn_id = generate_name_trn_id(); + nmb->header.response = False; + nmb->header.nm_flags.recursion_desired = rec_des; + nmb->header.nm_flags.recursion_available = False; + nmb->header.nm_flags.trunc = False; + nmb->header.nm_flags.authoritative = False; + nmb->header.nm_flags.bcast = bcast; - nmb->header.rcode = 0; - nmb->header.qdcount = 1; - nmb->header.ancount = 0; - nmb->header.nscount = 0; - - nmb->question.question_name = *nmbname; - nmb->question.question_type = QUESTION_TYPE_NB_QUERY; - nmb->question.question_class = QUESTION_CLASS_IN; - - packet->ip = to_ip; - packet->port = NMB_PORT; - packet->fd = ClientNMB; - packet->timestamp = time(NULL); - packet->packet_type = NMB_PACKET; - packet->locked = False; + nmb->header.rcode = 0; + nmb->header.qdcount = 1; + nmb->header.ancount = 0; + nmb->header.nscount = 0; + + nmb->question.question_name = *nmbname; + nmb->question.question_type = QUESTION_TYPE_NB_QUERY; + nmb->question.question_class = QUESTION_CLASS_IN; + + packet->ip = to_ip; + packet->port = NMB_PORT; + packet->fd = ClientNMB; + packet->timestamp = time(NULL); + packet->packet_type = NMB_PACKET; + packet->locked = False; - return packet; /* Caller must free. */ + return packet; /* Caller must free. */ } /*************************************************************************** @@ -283,20 +274,20 @@ static BOOL create_and_init_additional_record(struct packet_struct *packet, static BOOL initiate_name_query_packet( struct packet_struct *packet) { - struct nmb_packet *nmb = NULL; + struct nmb_packet *nmb = NULL; - nmb = &packet->packet.nmb; + nmb = &packet->packet.nmb; - nmb->header.opcode = NMB_NAME_QUERY_OPCODE; - nmb->header.arcount = 0; + nmb->header.opcode = NMB_NAME_QUERY_OPCODE; + nmb->header.arcount = 0; - nmb->header.nm_flags.recursion_desired = True; + nmb->header.nm_flags.recursion_desired = True; - DEBUG(4,("initiate_name_query_packet: sending query for name %s (bcast=%s) to IP %s\n", - nmb_namestr(&nmb->question.question_name), - BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); + DEBUG(4,("initiate_name_query_packet: sending query for name %s (bcast=%s) to IP %s\n", + nmb_namestr(&nmb->question.question_name), + BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); - return send_netbios_packet( packet ); + return send_netbios_packet( packet ); } /*************************************************************************** @@ -305,20 +296,20 @@ static BOOL initiate_name_query_packet( struct packet_struct *packet) static BOOL initiate_name_query_packet_from_wins_server( struct packet_struct *packet) { - struct nmb_packet *nmb = NULL; + struct nmb_packet *nmb = NULL; - nmb = &packet->packet.nmb; + nmb = &packet->packet.nmb; - nmb->header.opcode = NMB_NAME_QUERY_OPCODE; - nmb->header.arcount = 0; + nmb->header.opcode = NMB_NAME_QUERY_OPCODE; + nmb->header.arcount = 0; - nmb->header.nm_flags.recursion_desired = False; + nmb->header.nm_flags.recursion_desired = False; - DEBUG(4,("initiate_name_query_packet_from_wins_server: sending query for name %s (bcast=%s) to IP %s\n", - nmb_namestr(&nmb->question.question_name), - BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); + DEBUG(4,("initiate_name_query_packet_from_wins_server: sending query for name %s (bcast=%s) to IP %s\n", + nmb_namestr(&nmb->question.question_name), + BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); - return send_netbios_packet( packet ); + return send_netbios_packet( packet ); } /*************************************************************************** @@ -328,21 +319,21 @@ static BOOL initiate_name_query_packet_from_wins_server( struct packet_struct *p static BOOL initiate_name_register_packet( struct packet_struct *packet, uint16 nb_flags, struct in_addr *register_ip) { - struct nmb_packet *nmb = &packet->packet.nmb; + struct nmb_packet *nmb = &packet->packet.nmb; - nmb->header.opcode = NMB_NAME_REG_OPCODE; - nmb->header.arcount = 1; + nmb->header.opcode = NMB_NAME_REG_OPCODE; + nmb->header.arcount = 1; - nmb->header.nm_flags.recursion_desired = True; + nmb->header.nm_flags.recursion_desired = True; - if(create_and_init_additional_record(packet, nb_flags, register_ip) == False) - return False; + if(create_and_init_additional_record(packet, nb_flags, register_ip) == False) + return False; - DEBUG(4,("initiate_name_register_packet: sending registration for name %s (bcast=%s) to IP %s\n", - nmb_namestr(&nmb->additional->rr_name), - BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); + DEBUG(4,("initiate_name_register_packet: sending registration for name %s (bcast=%s) to IP %s\n", + nmb_namestr(&nmb->additional->rr_name), + BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); - return send_netbios_packet( packet ); + return send_netbios_packet( packet ); } /*************************************************************************** @@ -380,21 +371,21 @@ for name %s IP %s (bcast=%s) to IP %s\n", static BOOL initiate_name_refresh_packet( struct packet_struct *packet, uint16 nb_flags, struct in_addr *refresh_ip) { - struct nmb_packet *nmb = &packet->packet.nmb; + struct nmb_packet *nmb = &packet->packet.nmb; - nmb->header.opcode = NMB_NAME_REFRESH_OPCODE_8; - nmb->header.arcount = 1; + nmb->header.opcode = NMB_NAME_REFRESH_OPCODE_8; + nmb->header.arcount = 1; - nmb->header.nm_flags.recursion_desired = False; + nmb->header.nm_flags.recursion_desired = False; - if(create_and_init_additional_record(packet, nb_flags, refresh_ip) == False) - return False; + if(create_and_init_additional_record(packet, nb_flags, refresh_ip) == False) + return False; - DEBUG(4,("initiate_name_refresh_packet: sending refresh for name %s (bcast=%s) to IP %s\n", - nmb_namestr(&nmb->additional->rr_name), - BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); + DEBUG(4,("initiate_name_refresh_packet: sending refresh for name %s (bcast=%s) to IP %s\n", + nmb_namestr(&nmb->additional->rr_name), + BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); - return send_netbios_packet( packet ); + return send_netbios_packet( packet ); } /*************************************************************************** @@ -404,21 +395,21 @@ static BOOL initiate_name_refresh_packet( struct packet_struct *packet, static BOOL initiate_name_release_packet( struct packet_struct *packet, uint16 nb_flags, struct in_addr *release_ip) { - struct nmb_packet *nmb = &packet->packet.nmb; + struct nmb_packet *nmb = &packet->packet.nmb; - nmb->header.opcode = NMB_NAME_RELEASE_OPCODE; - nmb->header.arcount = 1; + nmb->header.opcode = NMB_NAME_RELEASE_OPCODE; + nmb->header.arcount = 1; - nmb->header.nm_flags.recursion_desired = False; + nmb->header.nm_flags.recursion_desired = False; - if(create_and_init_additional_record(packet, nb_flags, release_ip) == False) - return False; + if(create_and_init_additional_record(packet, nb_flags, release_ip) == False) + return False; - DEBUG(4,("initiate_name_release_packet: sending release for name %s (bcast=%s) to IP %s\n", - nmb_namestr(&nmb->additional->rr_name), - BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); + DEBUG(4,("initiate_name_release_packet: sending release for name %s (bcast=%s) to IP %s\n", + nmb_namestr(&nmb->additional->rr_name), + BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); - return send_netbios_packet( packet ); + return send_netbios_packet( packet ); } /*************************************************************************** @@ -427,20 +418,20 @@ static BOOL initiate_name_release_packet( struct packet_struct *packet, static BOOL initiate_node_status_packet( struct packet_struct *packet ) { - struct nmb_packet *nmb = &packet->packet.nmb; + struct nmb_packet *nmb = &packet->packet.nmb; - nmb->header.opcode = NMB_NAME_QUERY_OPCODE; - nmb->header.arcount = 0; + nmb->header.opcode = NMB_NAME_QUERY_OPCODE; + nmb->header.arcount = 0; - nmb->header.nm_flags.recursion_desired = False; + nmb->header.nm_flags.recursion_desired = False; - nmb->question.question_type = QUESTION_TYPE_NB_STATUS; + nmb->question.question_type = QUESTION_TYPE_NB_STATUS; - DEBUG(4,("initiate_node_status_packet: sending node status request for name %s to IP %s\n", - nmb_namestr(&nmb->question.question_name), - inet_ntoa(packet->ip))); + DEBUG(4,("initiate_node_status_packet: sending node status request for name %s to IP %s\n", + nmb_namestr(&nmb->question.question_name), + inet_ntoa(packet->ip))); - return send_netbios_packet( packet ); + return send_netbios_packet( packet ); } /**************************************************************************** @@ -456,13 +447,12 @@ static BOOL initiate_node_status_packet( struct packet_struct *packet ) static BOOL assert_check_subnet(struct subnet_record *subrec) { - if( subrec == remote_broadcast_subnet) - { - DEBUG(0,("assert_check_subnet: Attempt to send packet on remote broadcast subnet. \ + if( subrec == remote_broadcast_subnet) { + DEBUG(0,("assert_check_subnet: Attempt to send packet on remote broadcast subnet. \ This is a bug.\n")); - return True; - } - return False; + return True; + } + return False; } /**************************************************************************** @@ -478,46 +468,42 @@ struct response_record *queue_register_name( struct subnet_record *subrec, struct nmb_name *nmbname, uint16 nb_flags) { - struct packet_struct *p; - struct response_record *rrec; - - if(assert_check_subnet(subrec)) - return NULL; - - /* note that all name registration requests have RD set (rfc1002 - - section 4.2.2 */ - if ((p = create_and_init_netbios_packet(nmbname, (subrec != unicast_subnet), True, - subrec->bcast_ip)) == NULL) - return NULL; - - if(initiate_name_register_packet( p, nb_flags, - iface_ip(subrec->bcast_ip)) == False) - { - p->locked = False; - free_packet(p); - return NULL; - } - - if((rrec = make_response_record(subrec, /* subnet record. */ - p, /* packet we sent. */ - resp_fn, /* function to call on response. */ - timeout_fn, /* function to call on timeout. */ - (success_function)success_fn, /* function to call on operation success. */ - (fail_function)fail_fn, /* function to call on operation fail. */ - userdata)) == NULL) - { - p->locked = False; - free_packet(p); - return NULL; - } - - return rrec; -} + struct packet_struct *p; + struct response_record *rrec; + + if(assert_check_subnet(subrec)) + return NULL; + + /* note that all name registration requests have RD set (rfc1002 - section 4.2.2 */ + if ((p = create_and_init_netbios_packet(nmbname, (subrec != unicast_subnet), True, + subrec->bcast_ip)) == NULL) + return NULL; + + if(initiate_name_register_packet( p, nb_flags, iface_ip(subrec->bcast_ip)) == False) { + p->locked = False; + free_packet(p); + return NULL; + } + + if((rrec = make_response_record(subrec, /* subnet record. */ + p, /* packet we sent. */ + resp_fn, /* function to call on response. */ + timeout_fn, /* function to call on timeout. */ + (success_function)success_fn, /* function to call on operation success. */ + (fail_function)fail_fn, /* function to call on operation fail. */ + userdata)) == NULL) { + p->locked = False; + free_packet(p); + return NULL; + } + return rrec; +} /**************************************************************************** Queue a refresh name packet to the broadcast address of a subnet. ****************************************************************************/ + void queue_wins_refresh(struct nmb_name *nmbname, response_function resp_fn, timeout_response_function timeout_fn, @@ -648,47 +634,44 @@ struct response_record *queue_release_name( struct subnet_record *subrec, struct in_addr release_ip, struct in_addr dest_ip) { - struct packet_struct *p; - struct response_record *rrec; - - if(assert_check_subnet(subrec)) - return NULL; - - if ((p = create_and_init_netbios_packet(nmbname, (subrec != unicast_subnet), False, - dest_ip)) == NULL) - return NULL; - - if(initiate_name_release_packet( p, nb_flags, &release_ip) == False) - { - p->locked = False; - free_packet(p); - return NULL; - } - - if((rrec = make_response_record(subrec, /* subnet record. */ - p, /* packet we sent. */ - resp_fn, /* function to call on response. */ - timeout_fn, /* function to call on timeout. */ - (success_function)success_fn, /* function to call on operation success. */ - (fail_function)fail_fn, /* function to call on operation fail. */ - userdata)) == NULL) - { - p->locked = False; - free_packet(p); - return NULL; - } - - /* - * For a broadcast release packet, only send once. - * This will cause us to remove the name asap. JRA. - */ - - if (subrec != unicast_subnet) { - rrec->repeat_count = 0; - rrec->repeat_time = 0; - } - - return rrec; + struct packet_struct *p; + struct response_record *rrec; + + if(assert_check_subnet(subrec)) + return NULL; + + if ((p = create_and_init_netbios_packet(nmbname, (subrec != unicast_subnet), False, dest_ip)) == NULL) + return NULL; + + if(initiate_name_release_packet( p, nb_flags, &release_ip) == False) { + p->locked = False; + free_packet(p); + return NULL; + } + + if((rrec = make_response_record(subrec, /* subnet record. */ + p, /* packet we sent. */ + resp_fn, /* function to call on response. */ + timeout_fn, /* function to call on timeout. */ + (success_function)success_fn, /* function to call on operation success. */ + (fail_function)fail_fn, /* function to call on operation fail. */ + userdata)) == NULL) { + p->locked = False; + free_packet(p); + return NULL; + } + + /* + * For a broadcast release packet, only send once. + * This will cause us to remove the name asap. JRA. + */ + + if (subrec != unicast_subnet) { + rrec->repeat_count = 0; + rrec->repeat_time = 0; + } + + return rrec; } /**************************************************************************** @@ -703,80 +686,80 @@ struct response_record *queue_query_name( struct subnet_record *subrec, struct userdata_struct *userdata, struct nmb_name *nmbname) { - struct packet_struct *p; - struct response_record *rrec; - struct in_addr to_ip; + struct packet_struct *p; + struct response_record *rrec; + struct in_addr to_ip; - if(assert_check_subnet(subrec)) - return NULL; + if(assert_check_subnet(subrec)) + return NULL; - to_ip = subrec->bcast_ip; + to_ip = subrec->bcast_ip; - /* queries to the WINS server turn up here as queries to IP 0.0.0.0 - These need to be handled a bit differently */ - if (subrec->type == UNICAST_SUBNET && is_zero_ip(to_ip)) { - /* what we really need to do is loop over each of our wins - * servers and wins server tags here, but that just doesn't - * fit our architecture at the moment (userdata may already - * be used when we get here). For now we just query the first - * active wins server on the first tag. */ - char **tags = wins_srv_tags(); - if (!tags) { - return NULL; - } - to_ip = wins_srv_ip_tag(tags[0], to_ip); - wins_srv_tags_free(tags); - } - - if(( p = create_and_init_netbios_packet(nmbname, - (subrec != unicast_subnet), - (subrec == unicast_subnet), - to_ip)) == NULL) - return NULL; - - if(lp_bind_interfaces_only()) { - int i; - - DEBUG(10,("queue_query_name: bind_interfaces_only is set, looking for suitable source IP\n")); - for(i = 0; i < iface_count(); i++) { - struct in_addr *ifip = iface_n_ip(i); - - if(ifip == NULL) { - DEBUG(0,("queue_query_name: interface %d has NULL IP address !\n", i)); - continue; - } - - if (ip_equal(*ifip,loopback_ip)) { - DEBUG(5,("queue_query_name: ignoring loopback interface (%d)\n", i)); - continue; - } - - DEBUG(10,("queue_query_name: using source IP %s\n",inet_ntoa(*ifip))); - p->fd = find_subnet_fd_for_address( *ifip ); - break; - } - } - - if(initiate_name_query_packet( p ) == False) { - p->locked = False; - free_packet(p); - return NULL; - } - - if((rrec = make_response_record(subrec, /* subnet record. */ - p, /* packet we sent. */ - resp_fn, /* function to call on response. */ - timeout_fn, /* function to call on timeout. */ - (success_function)success_fn, /* function to call on operation success. */ - (fail_function)fail_fn, /* function to call on operation fail. */ - userdata)) == NULL) - { - p->locked = False; - free_packet(p); - return NULL; - } - - return rrec; + /* queries to the WINS server turn up here as queries to IP 0.0.0.0 + These need to be handled a bit differently */ + if (subrec->type == UNICAST_SUBNET && is_zero_ip(to_ip)) { + /* What we really need to do is loop over each of our wins + * servers and wins server tags here, but that just doesn't + * fit our architecture at the moment (userdata may already + * be used when we get here). For now we just query the first + * active wins server on the first tag. + */ + char **tags = wins_srv_tags(); + if (!tags) { + return NULL; + } + to_ip = wins_srv_ip_tag(tags[0], to_ip); + wins_srv_tags_free(tags); + } + + if(( p = create_and_init_netbios_packet(nmbname, + (subrec != unicast_subnet), + (subrec == unicast_subnet), + to_ip)) == NULL) + return NULL; + + if(lp_bind_interfaces_only()) { + int i; + + DEBUG(10,("queue_query_name: bind_interfaces_only is set, looking for suitable source IP\n")); + for(i = 0; i < iface_count(); i++) { + struct in_addr *ifip = iface_n_ip(i); + + if(ifip == NULL) { + DEBUG(0,("queue_query_name: interface %d has NULL IP address !\n", i)); + continue; + } + + if (ip_equal(*ifip,loopback_ip)) { + DEBUG(5,("queue_query_name: ignoring loopback interface (%d)\n", i)); + continue; + } + + DEBUG(10,("queue_query_name: using source IP %s\n",inet_ntoa(*ifip))); + p->fd = find_subnet_fd_for_address( *ifip ); + break; + } + } + + if(initiate_name_query_packet( p ) == False) { + p->locked = False; + free_packet(p); + return NULL; + } + + if((rrec = make_response_record(subrec, /* subnet record. */ + p, /* packet we sent. */ + resp_fn, /* function to call on response. */ + timeout_fn, /* function to call on timeout. */ + (success_function)success_fn, /* function to call on operation success. */ + (fail_function)fail_fn, /* function to call on operation fail. */ + userdata)) == NULL) { + p->locked = False; + free_packet(p); + return NULL; + } + + return rrec; } /**************************************************************************** @@ -791,33 +774,31 @@ struct response_record *queue_query_name_from_wins_server( struct in_addr to_ip, struct userdata_struct *userdata, struct nmb_name *nmbname) { - struct packet_struct *p; - struct response_record *rrec; - - if ((p = create_and_init_netbios_packet(nmbname, False, False, to_ip)) == NULL) - return NULL; - - if(initiate_name_query_packet_from_wins_server( p ) == False) - { - p->locked = False; - free_packet(p); - return NULL; - } - - if((rrec = make_response_record(wins_server_subnet, /* subnet record. */ - p, /* packet we sent. */ - resp_fn, /* function to call on response. */ - timeout_fn, /* function to call on timeout. */ - (success_function)success_fn, /* function to call on operation success. */ - (fail_function)fail_fn, /* function to call on operation fail. */ - userdata)) == NULL) - { - p->locked = False; - free_packet(p); - return NULL; - } - - return rrec; + struct packet_struct *p; + struct response_record *rrec; + + if ((p = create_and_init_netbios_packet(nmbname, False, False, to_ip)) == NULL) + return NULL; + + if(initiate_name_query_packet_from_wins_server( p ) == False) { + p->locked = False; + free_packet(p); + return NULL; + } + + if((rrec = make_response_record(wins_server_subnet, /* subnet record. */ + p, /* packet we sent. */ + resp_fn, /* function to call on response. */ + timeout_fn, /* function to call on timeout. */ + (success_function)success_fn, /* function to call on operation success. */ + (fail_function)fail_fn, /* function to call on operation fail. */ + userdata)) == NULL) { + p->locked = False; + free_packet(p); + return NULL; + } + + return rrec; } /**************************************************************************** @@ -833,45 +814,41 @@ struct response_record *queue_node_status( struct subnet_record *subrec, struct nmb_name *nmbname, struct in_addr send_ip) { - struct packet_struct *p; - struct response_record *rrec; + struct packet_struct *p; + struct response_record *rrec; - /* Sanity check. */ - if(subrec != unicast_subnet) - { - DEBUG(0,("queue_register_multihomed_name: should only be done on \ + /* Sanity check. */ + if(subrec != unicast_subnet) { + DEBUG(0,("queue_register_multihomed_name: should only be done on \ unicast subnet. subnet is %s\n.", subrec->subnet_name )); - return NULL; - } - - if(assert_check_subnet(subrec)) - return NULL; - - if(( p = create_and_init_netbios_packet(nmbname, False, False, - send_ip)) == NULL) - return NULL; - - if(initiate_node_status_packet(p) == False) - { - p->locked = False; - free_packet(p); - return NULL; - } - - if((rrec = make_response_record(subrec, /* subnet record. */ - p, /* packet we sent. */ - resp_fn, /* function to call on response. */ - timeout_fn, /* function to call on timeout. */ - (success_function)success_fn, /* function to call on operation success. */ - (fail_function)fail_fn, /* function to call on operation fail. */ - userdata)) == NULL) - { - p->locked = False; - free_packet(p); - return NULL; - } - - return rrec; + return NULL; + } + + if(assert_check_subnet(subrec)) + return NULL; + + if(( p = create_and_init_netbios_packet(nmbname, False, False, send_ip)) == NULL) + return NULL; + + if(initiate_node_status_packet(p) == False) { + p->locked = False; + free_packet(p); + return NULL; + } + + if((rrec = make_response_record(subrec, /* subnet record. */ + p, /* packet we sent. */ + resp_fn, /* function to call on response. */ + timeout_fn, /* function to call on timeout. */ + (success_function)success_fn, /* function to call on operation success. */ + (fail_function)fail_fn, /* function to call on operation fail. */ + userdata)) == NULL) { + p->locked = False; + free_packet(p); + return NULL; + } + + return rrec; } /**************************************************************************** @@ -882,169 +859,145 @@ void reply_netbios_packet(struct packet_struct *orig_packet, int rcode, enum netbios_reply_type_code rcv_code, int opcode, int ttl, char *data,int len) { - struct packet_struct packet; - struct nmb_packet *nmb = NULL; - struct res_rec answers; - struct nmb_packet *orig_nmb = &orig_packet->packet.nmb; - BOOL loopback_this_packet = False; - const char *packet_type = "unknown"; + struct packet_struct packet; + struct nmb_packet *nmb = NULL; + struct res_rec answers; + struct nmb_packet *orig_nmb = &orig_packet->packet.nmb; + BOOL loopback_this_packet = False; + const char *packet_type = "unknown"; - /* Check if we are sending to or from ourselves. */ - if(ismyip(orig_packet->ip) && (orig_packet->port == global_nmb_port)) - loopback_this_packet = True; + /* Check if we are sending to or from ourselves. */ + if(ismyip(orig_packet->ip) && (orig_packet->port == global_nmb_port)) + loopback_this_packet = True; - nmb = &packet.packet.nmb; - - /* Do a partial copy of the packet. We clear the locked flag and - the resource record pointers. */ - packet = *orig_packet; /* Full structure copy. */ - packet.locked = False; - nmb->answers = NULL; - nmb->nsrecs = NULL; - nmb->additional = NULL; - - switch (rcv_code) - { - case NMB_STATUS: - { - packet_type = "nmb_status"; - nmb->header.nm_flags.recursion_desired = False; - nmb->header.nm_flags.recursion_available = False; - break; - } - case NMB_QUERY: - { - packet_type = "nmb_query"; - nmb->header.nm_flags.recursion_desired = True; - nmb->header.nm_flags.recursion_available = True; - break; - } - case NMB_REG: - case NMB_REG_REFRESH: - { - packet_type = "nmb_reg"; - nmb->header.nm_flags.recursion_desired = True; - nmb->header.nm_flags.recursion_available = True; - break; - } - case NMB_REL: - { - packet_type = "nmb_rel"; - nmb->header.nm_flags.recursion_desired = False; - nmb->header.nm_flags.recursion_available = False; - break; - } - case NMB_WAIT_ACK: - { - packet_type = "nmb_wack"; - nmb->header.nm_flags.recursion_desired = False; - nmb->header.nm_flags.recursion_available = False; - break; - } - case WINS_REG: - { - packet_type = "wins_reg"; - nmb->header.nm_flags.recursion_desired = True; - nmb->header.nm_flags.recursion_available = True; - break; - } - case WINS_QUERY: - { - packet_type = "wins_query"; - nmb->header.nm_flags.recursion_desired = True; - nmb->header.nm_flags.recursion_available = True; - break; - } - - default: - { - DEBUG(0,("reply_netbios_packet: Unknown packet type: %s %s to ip %s\n", - packet_type, nmb_namestr(&orig_nmb->question.question_name), - inet_ntoa(packet.ip))); - - return; - } - } - - DEBUG(4,("reply_netbios_packet: sending a reply of packet type: %s %s to ip %s \ -for id %hu\n", - packet_type, nmb_namestr(&orig_nmb->question.question_name), - inet_ntoa(packet.ip), orig_nmb->header.name_trn_id)); - - nmb->header.name_trn_id = orig_nmb->header.name_trn_id; - nmb->header.opcode = opcode; - nmb->header.response = True; - nmb->header.nm_flags.bcast = False; - nmb->header.nm_flags.trunc = False; - nmb->header.nm_flags.authoritative = True; + nmb = &packet.packet.nmb; + + /* Do a partial copy of the packet. We clear the locked flag and + the resource record pointers. */ + packet = *orig_packet; /* Full structure copy. */ + packet.locked = False; + nmb->answers = NULL; + nmb->nsrecs = NULL; + nmb->additional = NULL; + + switch (rcv_code) { + case NMB_STATUS: + packet_type = "nmb_status"; + nmb->header.nm_flags.recursion_desired = False; + nmb->header.nm_flags.recursion_available = False; + break; + case NMB_QUERY: + packet_type = "nmb_query"; + nmb->header.nm_flags.recursion_desired = True; + nmb->header.nm_flags.recursion_available = True; + break; + case NMB_REG: + case NMB_REG_REFRESH: + packet_type = "nmb_reg"; + nmb->header.nm_flags.recursion_desired = True; + nmb->header.nm_flags.recursion_available = True; + break; + case NMB_REL: + packet_type = "nmb_rel"; + nmb->header.nm_flags.recursion_desired = False; + nmb->header.nm_flags.recursion_available = False; + break; + case NMB_WAIT_ACK: + packet_type = "nmb_wack"; + nmb->header.nm_flags.recursion_desired = False; + nmb->header.nm_flags.recursion_available = False; + break; + case WINS_REG: + packet_type = "wins_reg"; + nmb->header.nm_flags.recursion_desired = True; + nmb->header.nm_flags.recursion_available = True; + break; + case WINS_QUERY: + packet_type = "wins_query"; + nmb->header.nm_flags.recursion_desired = True; + nmb->header.nm_flags.recursion_available = True; + break; + default: + DEBUG(0,("reply_netbios_packet: Unknown packet type: %s %s to ip %s\n", + packet_type, nmb_namestr(&orig_nmb->question.question_name), + inet_ntoa(packet.ip))); + return; + } + + DEBUG(4,("reply_netbios_packet: sending a reply of packet type: %s %s to ip %s \ +for id %hu\n", packet_type, nmb_namestr(&orig_nmb->question.question_name), + inet_ntoa(packet.ip), orig_nmb->header.name_trn_id)); + + nmb->header.name_trn_id = orig_nmb->header.name_trn_id; + nmb->header.opcode = opcode; + nmb->header.response = True; + nmb->header.nm_flags.bcast = False; + nmb->header.nm_flags.trunc = False; + nmb->header.nm_flags.authoritative = True; - nmb->header.rcode = rcode; - nmb->header.qdcount = 0; - nmb->header.ancount = 1; - nmb->header.nscount = 0; - nmb->header.arcount = 0; + nmb->header.rcode = rcode; + nmb->header.qdcount = 0; + nmb->header.ancount = 1; + nmb->header.nscount = 0; + nmb->header.arcount = 0; - memset((char*)&nmb->question,'\0',sizeof(nmb->question)); + memset((char*)&nmb->question,'\0',sizeof(nmb->question)); - nmb->answers = &answers; - memset((char*)nmb->answers,'\0',sizeof(*nmb->answers)); + nmb->answers = &answers; + memset((char*)nmb->answers,'\0',sizeof(*nmb->answers)); - nmb->answers->rr_name = orig_nmb->question.question_name; - nmb->answers->rr_type = orig_nmb->question.question_type; - nmb->answers->rr_class = orig_nmb->question.question_class; - nmb->answers->ttl = ttl; + nmb->answers->rr_name = orig_nmb->question.question_name; + nmb->answers->rr_type = orig_nmb->question.question_type; + nmb->answers->rr_class = orig_nmb->question.question_class; + nmb->answers->ttl = ttl; - if (data && len) - { - nmb->answers->rdlength = len; - memcpy(nmb->answers->rdata, data, len); - } + if (data && len) { + nmb->answers->rdlength = len; + memcpy(nmb->answers->rdata, data, len); + } - packet.packet_type = NMB_PACKET; - /* Ensure we send out on the same fd that the original - packet came in on to give the correct source IP address. */ - packet.fd = orig_packet->fd; - packet.timestamp = time(NULL); + packet.packet_type = NMB_PACKET; + /* Ensure we send out on the same fd that the original + packet came in on to give the correct source IP address. */ + packet.fd = orig_packet->fd; + packet.timestamp = time(NULL); - debug_nmb_packet(&packet); + debug_nmb_packet(&packet); - if(loopback_this_packet) - { - struct packet_struct *lo_packet; - DEBUG(5,("reply_netbios_packet: sending packet to ourselves.\n")); - if((lo_packet = copy_packet(&packet)) == NULL) - return; - queue_packet(lo_packet); - } - else if (!send_packet(&packet)) - { - DEBUG(0,("reply_netbios_packet: send_packet to IP %s port %d failed\n", - inet_ntoa(packet.ip),packet.port)); - } + if(loopback_this_packet) { + struct packet_struct *lo_packet; + DEBUG(5,("reply_netbios_packet: sending packet to ourselves.\n")); + if((lo_packet = copy_packet(&packet)) == NULL) + return; + queue_packet(lo_packet); + } else if (!send_packet(&packet)) { + DEBUG(0,("reply_netbios_packet: send_packet to IP %s port %d failed\n", + inet_ntoa(packet.ip),packet.port)); + } } /******************************************************************* Queue a packet into a packet queue ******************************************************************/ + static void queue_packet(struct packet_struct *packet) { - struct packet_struct *p; - - if (!packet_queue) - { - packet->prev = NULL; - packet->next = NULL; - packet_queue = packet; - return; - } + struct packet_struct *p; + + if (!packet_queue) { + packet->prev = NULL; + packet->next = NULL; + packet_queue = packet; + return; + } - /* find the bottom */ - for (p=packet_queue;p->next;p=p->next) - ; + /* find the bottom */ + for (p=packet_queue;p->next;p=p->next) + ; - p->next = packet; - packet->next = NULL; - packet->prev = p; + p->next = packet; + packet->next = NULL; + packet->prev = p; } /**************************************************************************** @@ -1053,184 +1006,153 @@ static void queue_packet(struct packet_struct *packet) static struct subnet_record *find_subnet_for_dgram_browse_packet(struct packet_struct *p) { - struct subnet_record *subrec; - - /* Go through all the broadcast subnets and see if the mask matches. */ - for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip)) - return subrec; - } - - /* If the subnet record is the remote announce broadcast subnet, - hack it here to be the first subnet. This is really gross and - is needed due to people turning on port 137/138 broadcast - forwarding on their routers. May fire and brimstone rain - down upon them... - */ - - return FIRST_SUBNET; + struct subnet_record *subrec; + + /* Go through all the broadcast subnets and see if the mask matches. */ + for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip)) + return subrec; + } + + /* If the subnet record is the remote announce broadcast subnet, + hack it here to be the first subnet. This is really gross and + is needed due to people turning on port 137/138 broadcast + forwarding on their routers. May fire and brimstone rain + down upon them... + */ + + return FIRST_SUBNET; } /**************************************************************************** Dispatch a browse frame from port 138 to the correct processing function. ****************************************************************************/ + static void process_browse_packet(struct packet_struct *p, char *buf,int len) { - struct dgram_packet *dgram = &p->packet.dgram; - int command = CVAL(buf,0); - struct subnet_record *subrec = find_subnet_for_dgram_browse_packet(p); - - /* Drop the packet if it's a different NetBIOS scope, or - the source is from one of our names. */ - - if (!strequal(dgram->dest_name.scope, global_scope())) - { - DEBUG(7,("process_browse_packet: Discarding datagram from IP %s. Scope (%s) \ -mismatch with our scope (%s).\n", inet_ntoa(p->ip), dgram->dest_name.scope, global_scope())); - return; - } - - if (is_myname(dgram->source_name.name)) - { - DEBUG(0,("process_browse_packet: Discarding datagram from IP %s. Source name \ + struct dgram_packet *dgram = &p->packet.dgram; + int command = CVAL(buf,0); + struct subnet_record *subrec = find_subnet_for_dgram_browse_packet(p); + char scope[64]; + nstring src_name; + + /* Drop the packet if it's a different NetBIOS scope, or the source is from one of our names. */ + pull_ascii(scope, dgram->dest_name.scope, 64, 64, STR_TERMINATE); + if (!strequal(scope, global_scope())) { + DEBUG(7,("process_browse_packet: Discarding datagram from IP %s. Scope (%s) \ +mismatch with our scope (%s).\n", inet_ntoa(p->ip), scope, global_scope())); + return; + } + + pull_ascii_nstring(src_name, dgram->source_name.name); + if (is_myname(src_name)) { + DEBUG(0,("process_browse_packet: Discarding datagram from IP %s. Source name \ %s is one of our names !\n", inet_ntoa(p->ip), nmb_namestr(&dgram->source_name))); - return; - } - - switch (command) - { - case ANN_HostAnnouncement: - { - debug_browse_data(buf, len); - process_host_announce(subrec, p, buf+1); - break; - } - case ANN_DomainAnnouncement: - { - debug_browse_data(buf, len); - process_workgroup_announce(subrec, p, buf+1); - break; - } - case ANN_LocalMasterAnnouncement: - { - debug_browse_data(buf, len); - process_local_master_announce(subrec, p, buf+1); - break; - } - case ANN_AnnouncementRequest: - { - debug_browse_data(buf, len); - process_announce_request(subrec, p, buf+1); - break; - } - case ANN_Election: - { - debug_browse_data(buf, len); - process_election(subrec, p, buf+1); - break; - } - case ANN_GetBackupListReq: - { - debug_browse_data(buf, len); - process_get_backup_list_request(subrec, p, buf+1); - break; - } - case ANN_GetBackupListResp: - { - debug_browse_data(buf, len); - /* We never send ANN_GetBackupListReq so we - should never get these. */ - DEBUG(0,("process_browse_packet: Discarding GetBackupListResponse \ + return; + } + + switch (command) { + case ANN_HostAnnouncement: + debug_browse_data(buf, len); + process_host_announce(subrec, p, buf+1); + break; + case ANN_DomainAnnouncement: + debug_browse_data(buf, len); + process_workgroup_announce(subrec, p, buf+1); + break; + case ANN_LocalMasterAnnouncement: + debug_browse_data(buf, len); + process_local_master_announce(subrec, p, buf+1); + break; + case ANN_AnnouncementRequest: + debug_browse_data(buf, len); + process_announce_request(subrec, p, buf+1); + break; + case ANN_Election: + debug_browse_data(buf, len); + process_election(subrec, p, buf+1); + break; + case ANN_GetBackupListReq: + debug_browse_data(buf, len); + process_get_backup_list_request(subrec, p, buf+1); + break; + case ANN_GetBackupListResp: + debug_browse_data(buf, len); + /* We never send ANN_GetBackupListReq so we should never get these. */ + DEBUG(0,("process_browse_packet: Discarding GetBackupListResponse \ packet from %s IP %s\n", nmb_namestr(&dgram->source_name), inet_ntoa(p->ip))); - break; - } - case ANN_ResetBrowserState: - { - debug_browse_data(buf, len); - process_reset_browser(subrec, p, buf+1); - break; - } - case ANN_MasterAnnouncement: - { - /* Master browser datagrams must be processed - on the unicast subnet. */ - subrec = unicast_subnet; - - debug_browse_data(buf, len); - process_master_browser_announce(subrec, p, buf+1); - break; - } - case ANN_BecomeBackup: - { - /* - * We don't currently implement this. Log it just in case. - */ - debug_browse_data(buf, len); - DEBUG(10,("process_browse_packet: On subnet %s ignoring browse packet \ -command ANN_BecomeBackup from %s IP %s to %s\n", - subrec->subnet_name, nmb_namestr(&dgram->source_name), - inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name))); - break; - } - default: - { - debug_browse_data(buf, len); - DEBUG(0,("process_browse_packet: On subnet %s ignoring browse packet \ -command code %d from %s IP %s to %s\n", - subrec->subnet_name, command, nmb_namestr(&dgram->source_name), - inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name))); - } - } + break; + case ANN_ResetBrowserState: + debug_browse_data(buf, len); + process_reset_browser(subrec, p, buf+1); + break; + case ANN_MasterAnnouncement: + /* Master browser datagrams must be processed on the unicast subnet. */ + subrec = unicast_subnet; + + debug_browse_data(buf, len); + process_master_browser_announce(subrec, p, buf+1); + break; + case ANN_BecomeBackup: + /* + * We don't currently implement this. Log it just in case. + */ + debug_browse_data(buf, len); + DEBUG(10,("process_browse_packet: On subnet %s ignoring browse packet \ +command ANN_BecomeBackup from %s IP %s to %s\n", subrec->subnet_name, nmb_namestr(&dgram->source_name), + inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name))); + break; + default: + debug_browse_data(buf, len); + DEBUG(0,("process_browse_packet: On subnet %s ignoring browse packet \ +command code %d from %s IP %s to %s\n", subrec->subnet_name, command, nmb_namestr(&dgram->source_name), + inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name))); + break; + } } /**************************************************************************** Dispatch a LanMan browse frame from port 138 to the correct processing function. ****************************************************************************/ + static void process_lanman_packet(struct packet_struct *p, char *buf,int len) { - struct dgram_packet *dgram = &p->packet.dgram; - int command = SVAL(buf,0); - struct subnet_record *subrec = find_subnet_for_dgram_browse_packet(p); - - /* Drop the packet if it's a different NetBIOS scope, or - the source is from one of our names. */ - - if (!strequal(dgram->dest_name.scope, global_scope())) - { - DEBUG(7,("process_lanman_packet: Discarding datagram from IP %s. Scope (%s) \ -mismatch with our scope (%s).\n", inet_ntoa(p->ip), dgram->dest_name.scope, global_scope())); - return; - } - - if (is_myname(dgram->source_name.name)) - { - DEBUG(0,("process_lanman_packet: Discarding datagram from IP %s. Source name \ + struct dgram_packet *dgram = &p->packet.dgram; + int command = SVAL(buf,0); + struct subnet_record *subrec = find_subnet_for_dgram_browse_packet(p); + char scope[64]; + nstring src_name; + + /* Drop the packet if it's a different NetBIOS scope, or the source is from one of our names. */ + + pull_ascii(scope, dgram->dest_name.scope, 64, 64, STR_TERMINATE); + if (!strequal(scope, global_scope())) { + DEBUG(7,("process_lanman_packet: Discarding datagram from IP %s. Scope (%s) \ +mismatch with our scope (%s).\n", inet_ntoa(p->ip), scope, global_scope())); + return; + } + + pull_ascii_nstring(src_name, dgram->source_name.name); + if (is_myname(src_name)) { + DEBUG(0,("process_lanman_packet: Discarding datagram from IP %s. Source name \ %s is one of our names !\n", inet_ntoa(p->ip), nmb_namestr(&dgram->source_name))); - return; - } - - switch (command) - { - case ANN_HostAnnouncement: - { - debug_browse_data(buf, len); - process_lm_host_announce(subrec, p, buf+1); - break; - } - case ANN_AnnouncementRequest: - { - process_lm_announce_request(subrec, p, buf+1); - break; - } - default: - { - DEBUG(0,("process_lanman_packet: On subnet %s ignoring browse packet \ -command code %d from %s IP %s to %s\n", - subrec->subnet_name, command, nmb_namestr(&dgram->source_name), - inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name))); - } - } + return; + } + + switch (command) { + case ANN_HostAnnouncement: + debug_browse_data(buf, len); + process_lm_host_announce(subrec, p, buf+1); + break; + case ANN_AnnouncementRequest: + process_lm_announce_request(subrec, p, buf+1); + break; + default: + DEBUG(0,("process_lanman_packet: On subnet %s ignoring browse packet \ +command code %d from %s IP %s to %s\n", subrec->subnet_name, command, nmb_namestr(&dgram->source_name), + inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name))); + break; + } } /**************************************************************************** @@ -1241,104 +1163,94 @@ command code %d from %s IP %s to %s\n", static BOOL listening(struct packet_struct *p,struct nmb_name *nbname) { - struct subnet_record *subrec = NULL; + struct subnet_record *subrec = NULL; - for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip)) - break; - } + for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip)) + break; + } - if(subrec == NULL) - subrec = unicast_subnet; + if(subrec == NULL) + subrec = unicast_subnet; - return (find_name_on_subnet(subrec, nbname, FIND_SELF_NAME) != NULL); + return (find_name_on_subnet(subrec, nbname, FIND_SELF_NAME) != NULL); } /**************************************************************************** Process udp 138 datagrams ****************************************************************************/ + static void process_dgram(struct packet_struct *p) { - char *buf; - char *buf2; - int len; - struct dgram_packet *dgram = &p->packet.dgram; - - /* If we aren't listening to the destination name then ignore the packet */ - if (!listening(p,&dgram->dest_name)) - { - unexpected_packet(p); - DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from %s\n", - nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip))); - return; - } - - if (dgram->header.msg_type != 0x10 && - dgram->header.msg_type != 0x11 && - dgram->header.msg_type != 0x12) - { - unexpected_packet(p); - /* Don't process error packets etc yet */ - DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from IP %s as it is \ -an error packet of type %x\n", - nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip), dgram->header.msg_type)); - return; - } - - buf = &dgram->data[0]; - buf -= 4; /* XXXX for the pseudo tcp length - - someday I need to get rid of this */ - - if (CVAL(buf,smb_com) != SMBtrans) - return; - - len = SVAL(buf,smb_vwv11); - buf2 = smb_base(buf) + SVAL(buf,smb_vwv12); - - if (len <= 0) - return; - - if (buf2 + len > buf + sizeof(dgram->data)) { - DEBUG(2,("process_dgram: datagram from %s to %s IP %s for %s len=%d too long.\n", + char *buf; + char *buf2; + int len; + struct dgram_packet *dgram = &p->packet.dgram; + + /* If we aren't listening to the destination name then ignore the packet */ + if (!listening(p,&dgram->dest_name)) { + unexpected_packet(p); + DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from %s\n", + nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip))); + return; + } + + if (dgram->header.msg_type != 0x10 && dgram->header.msg_type != 0x11 && dgram->header.msg_type != 0x12) { + unexpected_packet(p); + /* Don't process error packets etc yet */ + DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from IP %s as it is \ +an error packet of type %x\n", nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip), dgram->header.msg_type)); + return; + } + + buf = &dgram->data[0]; + buf -= 4; /* XXXX for the pseudo tcp length - someday I need to get rid of this */ + + if (CVAL(buf,smb_com) != SMBtrans) + return; + + len = SVAL(buf,smb_vwv11); + buf2 = smb_base(buf) + SVAL(buf,smb_vwv12); + + if (len <= 0) + return; + + if (buf2 + len > buf + sizeof(dgram->data)) { + DEBUG(2,("process_dgram: datagram from %s to %s IP %s for %s len=%d too long.\n", + nmb_namestr(&dgram->source_name),nmb_namestr(&dgram->dest_name), + inet_ntoa(p->ip), smb_buf(buf),len)); + len = (buf + sizeof(dgram->data)) - buf; + } + + DEBUG(4,("process_dgram: datagram from %s to %s IP %s for %s of type %d len=%d\n", nmb_namestr(&dgram->source_name),nmb_namestr(&dgram->dest_name), - inet_ntoa(p->ip), smb_buf(buf),len)); - len = (buf + sizeof(dgram->data)) - buf; - } + inet_ntoa(p->ip), smb_buf(buf),CVAL(buf2,0),len)); - DEBUG(4,("process_dgram: datagram from %s to %s IP %s for %s of type %d len=%d\n", - nmb_namestr(&dgram->source_name),nmb_namestr(&dgram->dest_name), - inet_ntoa(p->ip), smb_buf(buf),CVAL(buf2,0),len)); + /* Datagram packet received for the browser mailslot */ + if (strequal(smb_buf(buf),BROWSE_MAILSLOT)) { + process_browse_packet(p,buf2,len); + return; + } - - /* Datagram packet received for the browser mailslot */ - if (strequal(smb_buf(buf),BROWSE_MAILSLOT)) - { - process_browse_packet(p,buf2,len); - return; - } - - /* Datagram packet received for the LAN Manager mailslot */ - if (strequal(smb_buf(buf),LANMAN_MAILSLOT)) { - process_lanman_packet(p,buf2,len); - return; - } - - /* Datagram packet received for the domain logon mailslot */ - if (strequal(smb_buf(buf),NET_LOGON_MAILSLOT)) - { - process_logon_packet(p,buf2,len,NET_LOGON_MAILSLOT); - return; - } - - /* Datagram packet received for the NT domain logon mailslot */ - if (strequal(smb_buf(buf),NT_LOGON_MAILSLOT)) - { - process_logon_packet(p,buf2,len,NT_LOGON_MAILSLOT); - return; - } - - unexpected_packet(p); + /* Datagram packet received for the LAN Manager mailslot */ + if (strequal(smb_buf(buf),LANMAN_MAILSLOT)) { + process_lanman_packet(p,buf2,len); + return; + } + + /* Datagram packet received for the domain logon mailslot */ + if (strequal(smb_buf(buf),NET_LOGON_MAILSLOT)) { + process_logon_packet(p,buf2,len,NET_LOGON_MAILSLOT); + return; + } + + /* Datagram packet received for the NT domain logon mailslot */ + if (strequal(smb_buf(buf),NT_LOGON_MAILSLOT)) { + process_logon_packet(p,buf2,len,NT_LOGON_MAILSLOT); + return; + } + + unexpected_packet(p); } /**************************************************************************** @@ -1347,52 +1259,49 @@ an error packet of type %x\n", static BOOL validate_nmb_response_packet( struct nmb_packet *nmb ) { - BOOL ignore = False; - - switch (nmb->header.opcode) - { - case NMB_NAME_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.ancount == 0) - { - DEBUG(0,("validate_nmb_response_packet: Bad REG/REFRESH Packet. ")); - ignore = True; - } - break; - - case NMB_NAME_QUERY_OPCODE: - if ((nmb->header.ancount != 0) && (nmb->header.ancount != 1)) - { - DEBUG(0,("validate_nmb_response_packet: Bad QUERY Packet. ")); - ignore = True; - } - break; - case NMB_NAME_RELEASE_OPCODE: - if (nmb->header.ancount == 0) - { - DEBUG(0,("validate_nmb_response_packet: Bad RELEASE Packet. ")); - ignore = True; - } - break; - case NMB_WACK_OPCODE: - /* Check WACK response here. */ - if (nmb->header.ancount != 1) - { - DEBUG(0,("validate_nmb_response_packet: Bad WACK Packet. ")); - ignore = True; - } - break; - default: - DEBUG(0,("validate_nmb_response_packet: Ignoring packet with unknown opcode %d.\n", - nmb->header.opcode)); - return True; - } - - if(ignore) - DEBUG(0,("Ignoring response packet with opcode %d.\n", nmb->header.opcode)); - - return ignore; + BOOL ignore = False; + + switch (nmb->header.opcode) { + case NMB_NAME_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.ancount == 0) { + DEBUG(0,("validate_nmb_response_packet: Bad REG/REFRESH Packet. ")); + ignore = True; + } + break; + + case NMB_NAME_QUERY_OPCODE: + if ((nmb->header.ancount != 0) && (nmb->header.ancount != 1)) { + DEBUG(0,("validate_nmb_response_packet: Bad QUERY Packet. ")); + ignore = True; + } + break; + + case NMB_NAME_RELEASE_OPCODE: + if (nmb->header.ancount == 0) { + DEBUG(0,("validate_nmb_response_packet: Bad RELEASE Packet. ")); + ignore = True; + } + break; + + case NMB_WACK_OPCODE: + /* Check WACK response here. */ + if (nmb->header.ancount != 1) { + DEBUG(0,("validate_nmb_response_packet: Bad WACK Packet. ")); + ignore = True; + } + break; + default: + DEBUG(0,("validate_nmb_response_packet: Ignoring packet with unknown opcode %d.\n", + nmb->header.opcode)); + return True; + } + + if(ignore) + DEBUG(0,("Ignoring response packet with opcode %d.\n", nmb->header.opcode)); + + return ignore; } /**************************************************************************** @@ -1401,48 +1310,43 @@ static BOOL validate_nmb_response_packet( struct nmb_packet *nmb ) static BOOL validate_nmb_packet( struct nmb_packet *nmb ) { - BOOL ignore = False; - - switch (nmb->header.opcode) - { - case NMB_NAME_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. */ - case NMB_NAME_MULTIHOMED_REG_OPCODE: - if (nmb->header.qdcount==0 || nmb->header.arcount==0) - { - DEBUG(0,("validate_nmb_packet: Bad REG/REFRESH Packet. ")); - ignore = True; - } - break; - - case NMB_NAME_QUERY_OPCODE: - if ((nmb->header.qdcount == 0) || - ((nmb->question.question_type != QUESTION_TYPE_NB_QUERY) && - (nmb->question.question_type != QUESTION_TYPE_NB_STATUS))) - { - DEBUG(0,("validate_nmb_packet: Bad QUERY Packet. ")); - ignore = True; - } - break; - - case NMB_NAME_RELEASE_OPCODE: - if (nmb->header.qdcount==0 || nmb->header.arcount==0) - { - DEBUG(0,("validate_nmb_packet: Bad RELEASE Packet. ")); - ignore = True; - } - break; - default: - DEBUG(0,("validate_nmb_packet: Ignoring packet with unknown opcode %d.\n", - nmb->header.opcode)); - return True; - } - - if(ignore) - DEBUG(0,("validate_nmb_packet: Ignoring request packet with opcode %d.\n", nmb->header.opcode)); - - return ignore; + BOOL ignore = False; + + switch (nmb->header.opcode) { + case NMB_NAME_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. */ + case NMB_NAME_MULTIHOMED_REG_OPCODE: + if (nmb->header.qdcount==0 || nmb->header.arcount==0) { + DEBUG(0,("validate_nmb_packet: Bad REG/REFRESH Packet. ")); + ignore = True; + } + break; + + case NMB_NAME_QUERY_OPCODE: + if ((nmb->header.qdcount == 0) || ((nmb->question.question_type != QUESTION_TYPE_NB_QUERY) && + (nmb->question.question_type != QUESTION_TYPE_NB_STATUS))) { + DEBUG(0,("validate_nmb_packet: Bad QUERY Packet. ")); + ignore = True; + } + break; + + case NMB_NAME_RELEASE_OPCODE: + if (nmb->header.qdcount==0 || nmb->header.arcount==0) { + DEBUG(0,("validate_nmb_packet: Bad RELEASE Packet. ")); + ignore = True; + } + break; + default: + DEBUG(0,("validate_nmb_packet: Ignoring packet with unknown opcode %d.\n", + nmb->header.opcode)); + return True; + } + + if(ignore) + DEBUG(0,("validate_nmb_packet: Ignoring request packet with opcode %d.\n", nmb->header.opcode)); + + return ignore; } /**************************************************************************** @@ -1452,58 +1356,53 @@ static BOOL validate_nmb_packet( struct nmb_packet *nmb ) static struct subnet_record *find_subnet_for_nmb_packet( struct packet_struct *p, struct response_record **pprrec) { - struct nmb_packet *nmb = &p->packet.nmb; - struct response_record *rrec = NULL; - struct subnet_record *subrec = NULL; - - if(pprrec != NULL) - *pprrec = NULL; - - if(nmb->header.response) - { - /* It's a response packet. Find a record for it or it's an error. */ - - rrec = find_response_record( &subrec, nmb->header.name_trn_id); - if(rrec == NULL) - { - DEBUG(3,("find_subnet_for_nmb_packet: response record not found for response id %hu\n", - nmb->header.name_trn_id)); - unexpected_packet(p); - return NULL; - } - - if(subrec == NULL) - { - DEBUG(0,("find_subnet_for_nmb_packet: subnet record not found for response id %hu\n", - nmb->header.name_trn_id)); - return NULL; - } - - if(pprrec != NULL) - *pprrec = rrec; - return subrec; - } - - /* Try and see what subnet this packet belongs to. */ - - /* WINS server ? */ - if(packet_is_for_wins_server(p)) - return wins_server_subnet; - - /* If it wasn't a broadcast packet then send to the UNICAST subnet. */ - if(nmb->header.nm_flags.bcast == False) - return unicast_subnet; - - /* Go through all the broadcast subnets and see if the mask matches. */ - for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip)) - return subrec; - } - - /* If none match it must have been a directed broadcast - assign - the remote_broadcast_subnet. */ - return remote_broadcast_subnet; + struct nmb_packet *nmb = &p->packet.nmb; + struct response_record *rrec = NULL; + struct subnet_record *subrec = NULL; + + if(pprrec != NULL) + *pprrec = NULL; + + if(nmb->header.response) { + /* It's a response packet. Find a record for it or it's an error. */ + + rrec = find_response_record( &subrec, nmb->header.name_trn_id); + if(rrec == NULL) { + DEBUG(3,("find_subnet_for_nmb_packet: response record not found for response id %hu\n", + nmb->header.name_trn_id)); + unexpected_packet(p); + return NULL; + } + + if(subrec == NULL) { + DEBUG(0,("find_subnet_for_nmb_packet: subnet record not found for response id %hu\n", + nmb->header.name_trn_id)); + return NULL; + } + + if(pprrec != NULL) + *pprrec = rrec; + return subrec; + } + + /* Try and see what subnet this packet belongs to. */ + + /* WINS server ? */ + if(packet_is_for_wins_server(p)) + return wins_server_subnet; + + /* If it wasn't a broadcast packet then send to the UNICAST subnet. */ + if(nmb->header.nm_flags.bcast == False) + return unicast_subnet; + + /* Go through all the broadcast subnets and see if the mask matches. */ + for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip)) + return subrec; + } + + /* If none match it must have been a directed broadcast - assign the remote_broadcast_subnet. */ + return remote_broadcast_subnet; } /**************************************************************************** @@ -1512,79 +1411,71 @@ static struct subnet_record *find_subnet_for_nmb_packet( struct packet_struct *p static void process_nmb_request(struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - struct subnet_record *subrec = NULL; - - debug_nmb_packet(p); - - /* Ensure we have a good packet. */ - if(validate_nmb_packet(nmb)) - return; - - /* Allocate a subnet to this packet - if we cannot - fail. */ - if((subrec = find_subnet_for_nmb_packet(p, NULL))==NULL) - return; - - switch (nmb->header.opcode) - { - case NMB_NAME_REG_OPCODE: - if(subrec == wins_server_subnet) - wins_process_name_registration_request(subrec, p); - else - process_name_registration_request(subrec, p); - break; - - case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */ - case NMB_NAME_REFRESH_OPCODE_9: - if(subrec == wins_server_subnet) - wins_process_name_refresh_request(subrec, p); - else - process_name_refresh_request(subrec, p); - break; - - case NMB_NAME_MULTIHOMED_REG_OPCODE: - if(subrec == wins_server_subnet) - wins_process_multihomed_name_registration_request(subrec, p); - else - { - DEBUG(0,("process_nmb_request: Multihomed registration request must be \ + struct nmb_packet *nmb = &p->packet.nmb; + struct subnet_record *subrec = NULL; + + debug_nmb_packet(p); + + /* Ensure we have a good packet. */ + if(validate_nmb_packet(nmb)) + return; + + /* Allocate a subnet to this packet - if we cannot - fail. */ + if((subrec = find_subnet_for_nmb_packet(p, NULL))==NULL) + return; + + switch (nmb->header.opcode) { + case NMB_NAME_REG_OPCODE: + if(subrec == wins_server_subnet) + wins_process_name_registration_request(subrec, p); + else + process_name_registration_request(subrec, p); + break; + + case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */ + case NMB_NAME_REFRESH_OPCODE_9: + if(subrec == wins_server_subnet) + wins_process_name_refresh_request(subrec, p); + else + process_name_refresh_request(subrec, p); + break; + + case NMB_NAME_MULTIHOMED_REG_OPCODE: + if(subrec == wins_server_subnet) { + wins_process_multihomed_name_registration_request(subrec, p); + } else { + DEBUG(0,("process_nmb_request: Multihomed registration request must be \ directed at a WINS server.\n")); - } - break; - - case NMB_NAME_QUERY_OPCODE: - switch (nmb->question.question_type) - { - case QUESTION_TYPE_NB_QUERY: - { - if(subrec == wins_server_subnet) - wins_process_name_query_request(subrec, p); - else - process_name_query_request(subrec, p); - break; - } - case QUESTION_TYPE_NB_STATUS: - { - if(subrec == wins_server_subnet) - { - DEBUG(0,("process_nmb_request: NB_STATUS request directed at WINS server is \ + } + break; + + case NMB_NAME_QUERY_OPCODE: + switch (nmb->question.question_type) { + case QUESTION_TYPE_NB_QUERY: + if(subrec == wins_server_subnet) + wins_process_name_query_request(subrec, p); + else + process_name_query_request(subrec, p); + break; + case QUESTION_TYPE_NB_STATUS: + if(subrec == wins_server_subnet) { + DEBUG(0,("process_nmb_request: NB_STATUS request directed at WINS server is \ not allowed.\n")); - break; - } - else - process_node_status_request(subrec, p); - break; - } - } - break; + break; + } else { + process_node_status_request(subrec, p); + } + break; + } + break; - case NMB_NAME_RELEASE_OPCODE: - if(subrec == wins_server_subnet) - wins_process_name_release_request(subrec, p); - else - process_name_release_request(subrec, p); - break; - } + case NMB_NAME_RELEASE_OPCODE: + if(subrec == wins_server_subnet) + wins_process_name_release_request(subrec, p); + else + process_name_release_request(subrec, p); + break; + } } /**************************************************************************** @@ -1594,65 +1485,61 @@ not allowed.\n")); static void process_nmb_response(struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - struct subnet_record *subrec = NULL; - struct response_record *rrec = NULL; + struct nmb_packet *nmb = &p->packet.nmb; + struct subnet_record *subrec = NULL; + struct response_record *rrec = NULL; - debug_nmb_packet(p); + debug_nmb_packet(p); - if(validate_nmb_response_packet(nmb)) - return; + if(validate_nmb_response_packet(nmb)) + return; - if((subrec = find_subnet_for_nmb_packet(p, &rrec))==NULL) - return; + if((subrec = find_subnet_for_nmb_packet(p, &rrec))==NULL) + return; - if(rrec == NULL) - { - DEBUG(0,("process_nmb_response: response packet received but no response record \ + if(rrec == NULL) { + DEBUG(0,("process_nmb_response: response packet received but no response record \ found for id = %hu. Ignoring packet.\n", nmb->header.name_trn_id)); - return; - } + return; + } - /* Increment the number of responses received for this record. */ - rrec->num_msgs++; - /* Ensure we don't re-send the request. */ - rrec->repeat_count = 0; + /* Increment the number of responses received for this record. */ + rrec->num_msgs++; + /* Ensure we don't re-send the request. */ + rrec->repeat_count = 0; - /* Call the response received function for this packet. */ - (*rrec->resp_fn)(subrec, rrec, p); + /* Call the response received function for this packet. */ + (*rrec->resp_fn)(subrec, rrec, p); } - /******************************************************************* Run elements off the packet queue till its empty ******************************************************************/ void run_packet_queue(void) { - struct packet_struct *p; - - while ((p = packet_queue)) - { - packet_queue = p->next; - if (packet_queue) - packet_queue->prev = NULL; - p->next = p->prev = NULL; - - switch (p->packet_type) - { - case NMB_PACKET: - if(p->packet.nmb.header.response) - process_nmb_response(p); - else - process_nmb_request(p); - break; - - case DGRAM_PACKET: - process_dgram(p); - break; - } - free_packet(p); - } + struct packet_struct *p; + + while ((p = packet_queue)) { + packet_queue = p->next; + if (packet_queue) + packet_queue->prev = NULL; + p->next = p->prev = NULL; + + switch (p->packet_type) { + case NMB_PACKET: + if(p->packet.nmb.header.response) + process_nmb_response(p); + else + process_nmb_request(p); + break; + + case DGRAM_PACKET: + process_dgram(p); + break; + } + free_packet(p); + } } /******************************************************************* @@ -1665,66 +1552,54 @@ void run_packet_queue(void) void retransmit_or_expire_response_records(time_t t) { - struct subnet_record *subrec; + struct subnet_record *subrec; - for (subrec = FIRST_SUBNET; subrec; - subrec = get_next_subnet_maybe_unicast_or_wins_server(subrec)) - { - struct response_record *rrec, *nextrrec; + for (subrec = FIRST_SUBNET; subrec; subrec = get_next_subnet_maybe_unicast_or_wins_server(subrec)) { + struct response_record *rrec, *nextrrec; - for (rrec = subrec->responselist; rrec; rrec = nextrrec) - { - nextrrec = rrec->next; + for (rrec = subrec->responselist; rrec; rrec = nextrrec) { + nextrrec = rrec->next; - if (rrec->repeat_time <= t) - { - if (rrec->repeat_count > 0) - { - /* Resend while we have a non-zero repeat_count. */ - if(!send_packet(rrec->packet)) - { - DEBUG(0,("retransmit_or_expire_response_records: Failed to resend packet id %hu \ -to IP %s on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip), - subrec->subnet_name)); - } - rrec->repeat_time = t + rrec->repeat_interval; - rrec->repeat_count--; - } - else - { - DEBUG(4,("retransmit_or_expire_response_records: timeout for packet id %hu to IP %s \ -on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip), - subrec->subnet_name)); - - /* - * Check the flag in this record to prevent recursion if we end - * up in this function again via the timeout function call. - */ - - if(!rrec->in_expiration_processing) - { - - /* - * Set the recursion protection flag in this record. - */ - - rrec->in_expiration_processing = True; - - /* Call the timeout function. This will deal with removing the - timed out packet. */ - if(rrec->timeout_fn) - (*rrec->timeout_fn)(subrec, rrec); - else - { - /* We must remove the record ourself if there is - no timeout function. */ - remove_response_record(subrec, rrec); - } - } /* !rrec->in_expitation_processing */ - } /* rrec->repeat_count > 0 */ - } /* rrec->repeat_time <= t */ - } /* end for rrec */ - } /* end for subnet */ + if (rrec->repeat_time <= t) { + if (rrec->repeat_count > 0) { + /* Resend while we have a non-zero repeat_count. */ + if(!send_packet(rrec->packet)) { + DEBUG(0,("retransmit_or_expire_response_records: Failed to resend packet id %hu \ +to IP %s on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip), subrec->subnet_name)); + } + rrec->repeat_time = t + rrec->repeat_interval; + rrec->repeat_count--; + } else { + DEBUG(4,("retransmit_or_expire_response_records: timeout for packet id %hu to IP %s \ +on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip), subrec->subnet_name)); + + /* + * Check the flag in this record to prevent recursion if we end + * up in this function again via the timeout function call. + */ + + if(!rrec->in_expiration_processing) { + + /* + * Set the recursion protection flag in this record. + */ + + rrec->in_expiration_processing = True; + + /* Call the timeout function. This will deal with removing the + timed out packet. */ + if(rrec->timeout_fn) { + (*rrec->timeout_fn)(subrec, rrec); + } else { + /* We must remove the record ourself if there is + no timeout function. */ + remove_response_record(subrec, rrec); + } + } /* !rrec->in_expitation_processing */ + } /* rrec->repeat_count > 0 */ + } /* rrec->repeat_time <= t */ + } /* end for rrec */ + } /* end for subnet */ } /**************************************************************************** @@ -1734,68 +1609,63 @@ on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip), static BOOL create_listen_fdset(fd_set **ppset, int **psock_array, int *listen_number) { - int *sock_array = NULL; - struct subnet_record *subrec = NULL; - int count = 0; - int num = 0; - fd_set *pset = (fd_set *)malloc(sizeof(fd_set)); - - if(pset == NULL) - { - DEBUG(0,("create_listen_fdset: malloc fail !\n")); - return True; - } - - /* Check that we can add all the fd's we need. */ - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - count++; - - if((count*2) + 2 > FD_SETSIZE) - { - DEBUG(0,("create_listen_fdset: Too many file descriptors needed (%d). We can \ + int *sock_array = NULL; + struct subnet_record *subrec = NULL; + int count = 0; + int num = 0; + fd_set *pset = (fd_set *)malloc(sizeof(fd_set)); + + if(pset == NULL) { + DEBUG(0,("create_listen_fdset: malloc fail !\n")); + return True; + } + + /* Check that we can add all the fd's we need. */ + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) + count++; + + if((count*2) + 2 > FD_SETSIZE) { + DEBUG(0,("create_listen_fdset: Too many file descriptors needed (%d). We can \ only use %d.\n", (count*2) + 2, FD_SETSIZE)); - return True; - } - - if((sock_array = (int *)malloc(((count*2) + 2)*sizeof(int))) == NULL) - { - DEBUG(0,("create_listen_fdset: malloc fail for socket array.\n")); - return True; - } - - FD_ZERO(pset); - - /* Add in the broadcast socket on 137. */ - FD_SET(ClientNMB,pset); - sock_array[num++] = ClientNMB; - - /* Add in the 137 sockets on all the interfaces. */ - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - FD_SET(subrec->nmb_sock,pset); - sock_array[num++] = subrec->nmb_sock; - } - - /* Add in the broadcast socket on 138. */ - FD_SET(ClientDGRAM,pset); - sock_array[num++] = ClientDGRAM; - - /* Add in the 138 sockets on all the interfaces. */ - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - FD_SET(subrec->dgram_sock,pset); - sock_array[num++] = subrec->dgram_sock; - } - - *listen_number = (count*2) + 2; - - SAFE_FREE(*ppset); - SAFE_FREE(*psock_array); - - *ppset = pset; - *psock_array = sock_array; + return True; + } + + if((sock_array = (int *)malloc(((count*2) + 2)*sizeof(int))) == NULL) { + DEBUG(0,("create_listen_fdset: malloc fail for socket array.\n")); + return True; + } + + FD_ZERO(pset); + + /* Add in the broadcast socket on 137. */ + FD_SET(ClientNMB,pset); + sock_array[num++] = ClientNMB; + + /* Add in the 137 sockets on all the interfaces. */ + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + FD_SET(subrec->nmb_sock,pset); + sock_array[num++] = subrec->nmb_sock; + } + + /* Add in the broadcast socket on 138. */ + FD_SET(ClientDGRAM,pset); + sock_array[num++] = ClientDGRAM; + + /* Add in the 138 sockets on all the interfaces. */ + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + FD_SET(subrec->dgram_sock,pset); + sock_array[num++] = subrec->dgram_sock; + } + + *listen_number = (count*2) + 2; + + SAFE_FREE(*ppset); + SAFE_FREE(*psock_array); + + *ppset = pset; + *psock_array = sock_array; - return False; + return False; } /**************************************************************************** @@ -1805,214 +1675,211 @@ only use %d.\n", (count*2) + 2, FD_SETSIZE)); BOOL listen_for_packets(BOOL run_election) { - static fd_set *listen_set = NULL; - static int listen_number = 0; - static int *sock_array = NULL; - int i; - - fd_set fds; - int selrtn; - struct timeval timeout; + static fd_set *listen_set = NULL; + static int listen_number = 0; + static int *sock_array = NULL; + int i; + + fd_set fds; + int selrtn; + struct timeval timeout; #ifndef SYNC_DNS - int dns_fd; + int dns_fd; #endif - if(listen_set == NULL || rescan_listen_set) - { - if(create_listen_fdset(&listen_set, &sock_array, &listen_number)) - { - DEBUG(0,("listen_for_packets: Fatal error. unable to create listen set. Exiting.\n")); - return True; - } - rescan_listen_set = False; - } + if(listen_set == NULL || rescan_listen_set) { + if(create_listen_fdset(&listen_set, &sock_array, &listen_number)) { + DEBUG(0,("listen_for_packets: Fatal error. unable to create listen set. Exiting.\n")); + return True; + } + rescan_listen_set = False; + } - memcpy((char *)&fds, (char *)listen_set, sizeof(fd_set)); + memcpy((char *)&fds, (char *)listen_set, sizeof(fd_set)); #ifndef SYNC_DNS - dns_fd = asyncdns_fd(); - if (dns_fd != -1) { - FD_SET(dns_fd, &fds); - } + dns_fd = asyncdns_fd(); + if (dns_fd != -1) { + FD_SET(dns_fd, &fds); + } #endif + /* + * During elections and when expecting a netbios response packet we + * need to send election packets at tighter intervals. + * Ideally it needs to be the interval (in ms) between time now and + * the time we are expecting the next netbios packet. + */ - /* - * During elections and when expecting a netbios response packet we - * need to send election packets at tighter intervals. - * Ideally it needs to be the interval (in ms) between time now and - * the time we are expecting the next netbios packet. - */ - - timeout.tv_sec = (run_election||num_response_packets) ? 1 : NMBD_SELECT_LOOP; - timeout.tv_usec = 0; + timeout.tv_sec = (run_election||num_response_packets) ? 1 : NMBD_SELECT_LOOP; + timeout.tv_usec = 0; - /* Prepare for the select - allow certain signals. */ + /* Prepare for the select - allow certain signals. */ - BlockSignals(False, SIGTERM); + BlockSignals(False, SIGTERM); - selrtn = sys_select(FD_SETSIZE,&fds,NULL,NULL,&timeout); + selrtn = sys_select(FD_SETSIZE,&fds,NULL,NULL,&timeout); - /* We can only take signals when we are in the select - block them again here. */ + /* We can only take signals when we are in the select - block them again here. */ - BlockSignals(True, SIGTERM); + BlockSignals(True, SIGTERM); - if(selrtn == -1) { - return False; - } + if(selrtn == -1) { + return False; + } #ifndef SYNC_DNS - if (dns_fd != -1 && FD_ISSET(dns_fd,&fds)) { - run_dns_queue(); - } + if (dns_fd != -1 && FD_ISSET(dns_fd,&fds)) { + run_dns_queue(); + } #endif - for(i = 0; i < listen_number; i++) { - if (i < (listen_number/2)) { - /* Processing a 137 socket. */ - if (FD_ISSET(sock_array[i],&fds)) { - struct packet_struct *packet = read_packet(sock_array[i], NMB_PACKET); - if (packet) { - /* - * If we got a packet on the broadcast socket and interfaces - * only is set then check it came from one of our local nets. - */ - if(lp_bind_interfaces_only() && (sock_array[i] == ClientNMB) && - (!is_local_net(packet->ip))) { - DEBUG(7,("discarding nmb packet sent to broadcast socket from %s:%d\n", - inet_ntoa(packet->ip),packet->port)); - free_packet(packet); - } else if ((ip_equal(loopback_ip, packet->ip) || - ismyip(packet->ip)) && packet->port == global_nmb_port && - packet->packet.nmb.header.nm_flags.bcast) { - DEBUG(7,("discarding own bcast packet from %s:%d\n", - inet_ntoa(packet->ip),packet->port)); - free_packet(packet); - } else { - /* Save the file descriptor this packet came in on. */ - packet->fd = sock_array[i]; - queue_packet(packet); - } - } - } - } else { - /* Processing a 138 socket. */ - if (FD_ISSET(sock_array[i],&fds)) { - struct packet_struct *packet = read_packet(sock_array[i], DGRAM_PACKET); - if (packet) { - /* - * If we got a packet on the broadcast socket and interfaces - * only is set then check it came from one of our local nets. - */ - if(lp_bind_interfaces_only() && (sock_array[i] == ClientDGRAM) && - (!is_local_net(packet->ip))) { - DEBUG(7,("discarding dgram packet sent to broadcast socket from %s:%d\n", - inet_ntoa(packet->ip),packet->port)); - free_packet(packet); - } else if ((ip_equal(loopback_ip, packet->ip) || - ismyip(packet->ip)) && packet->port == DGRAM_PORT) { - DEBUG(7,("discarding own dgram packet from %s:%d\n", - inet_ntoa(packet->ip),packet->port)); - free_packet(packet); - } else { - /* Save the file descriptor this packet came in on. */ - packet->fd = sock_array[i]; - queue_packet(packet); - } - } - } - } /* end processing 138 socket. */ - } /* end for */ - return False; + for(i = 0; i < listen_number; i++) { + if (i < (listen_number/2)) { + /* Processing a 137 socket. */ + if (FD_ISSET(sock_array[i],&fds)) { + struct packet_struct *packet = read_packet(sock_array[i], NMB_PACKET); + if (packet) { + /* + * If we got a packet on the broadcast socket and interfaces + * only is set then check it came from one of our local nets. + */ + if(lp_bind_interfaces_only() && (sock_array[i] == ClientNMB) && + (!is_local_net(packet->ip))) { + DEBUG(7,("discarding nmb packet sent to broadcast socket from %s:%d\n", + inet_ntoa(packet->ip),packet->port)); + free_packet(packet); + } else if ((ip_equal(loopback_ip, packet->ip) || + ismyip(packet->ip)) && packet->port == global_nmb_port && + packet->packet.nmb.header.nm_flags.bcast) { + DEBUG(7,("discarding own bcast packet from %s:%d\n", + inet_ntoa(packet->ip),packet->port)); + free_packet(packet); + } else { + /* Save the file descriptor this packet came in on. */ + packet->fd = sock_array[i]; + queue_packet(packet); + } + } + } + } else { + /* Processing a 138 socket. */ + if (FD_ISSET(sock_array[i],&fds)) { + struct packet_struct *packet = read_packet(sock_array[i], DGRAM_PACKET); + if (packet) { + /* + * If we got a packet on the broadcast socket and interfaces + * only is set then check it came from one of our local nets. + */ + if(lp_bind_interfaces_only() && (sock_array[i] == ClientDGRAM) && + (!is_local_net(packet->ip))) { + DEBUG(7,("discarding dgram packet sent to broadcast socket from %s:%d\n", + inet_ntoa(packet->ip),packet->port)); + free_packet(packet); + } else if ((ip_equal(loopback_ip, packet->ip) || + ismyip(packet->ip)) && packet->port == DGRAM_PORT) { + DEBUG(7,("discarding own dgram packet from %s:%d\n", + inet_ntoa(packet->ip),packet->port)); + free_packet(packet); + } else { + /* Save the file descriptor this packet came in on. */ + packet->fd = sock_array[i]; + queue_packet(packet); + } + } + } + } /* end processing 138 socket. */ + } /* end for */ + return False; } /**************************************************************************** Construct and send a netbios DGRAM. **************************************************************************/ + BOOL send_mailslot(BOOL unique, const char *mailslot,char *buf, size_t len, const char *srcname, int src_type, const char *dstname, int dest_type, struct in_addr dest_ip,struct in_addr src_ip, int dest_port) { - BOOL loopback_this_packet = False; - struct packet_struct p; - struct dgram_packet *dgram = &p.packet.dgram; - char *ptr,*p2; - char tmp[4]; - - memset((char *)&p,'\0',sizeof(p)); - - if(ismyip(dest_ip) && (dest_port == DGRAM_PORT)) /* Only if to DGRAM_PORT */ - loopback_this_packet = True; - - /* generate_name_trn_id(); */ /* Not used, so gone, RJS */ - - /* DIRECT GROUP or UNIQUE datagram. */ - dgram->header.msg_type = unique ? 0x10 : 0x11; - dgram->header.flags.node_type = M_NODE; - dgram->header.flags.first = True; - dgram->header.flags.more = False; - dgram->header.dgm_id = generate_name_trn_id(); - dgram->header.source_ip = src_ip; - dgram->header.source_port = DGRAM_PORT; - dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */ - dgram->header.packet_offset = 0; + BOOL loopback_this_packet = False; + struct packet_struct p; + struct dgram_packet *dgram = &p.packet.dgram; + char *ptr,*p2; + char tmp[4]; + + memset((char *)&p,'\0',sizeof(p)); + + if(ismyip(dest_ip) && (dest_port == DGRAM_PORT)) /* Only if to DGRAM_PORT */ + loopback_this_packet = True; + + /* generate_name_trn_id(); */ /* Not used, so gone, RJS */ + + /* DIRECT GROUP or UNIQUE datagram. */ + dgram->header.msg_type = unique ? 0x10 : 0x11; + dgram->header.flags.node_type = M_NODE; + dgram->header.flags.first = True; + dgram->header.flags.more = False; + dgram->header.dgm_id = generate_name_trn_id(); + dgram->header.source_ip = src_ip; + dgram->header.source_port = DGRAM_PORT; + dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */ + dgram->header.packet_offset = 0; - make_nmb_name(&dgram->source_name,srcname,src_type); - make_nmb_name(&dgram->dest_name,dstname,dest_type); - - ptr = &dgram->data[0]; - - /* Setup the smb part. */ - ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */ - memcpy(tmp,ptr,4); - set_message(ptr,17,23 + len,True); - memcpy(ptr,tmp,4); - - SCVAL(ptr,smb_com,SMBtrans); - SSVAL(ptr,smb_vwv1,len); - SSVAL(ptr,smb_vwv11,len); - SSVAL(ptr,smb_vwv12,70 + strlen(mailslot)); - SSVAL(ptr,smb_vwv13,3); - SSVAL(ptr,smb_vwv14,1); - SSVAL(ptr,smb_vwv15,1); - SSVAL(ptr,smb_vwv16,2); - p2 = smb_buf(ptr); - safe_strcpy_base(p2, mailslot, dgram->data, sizeof(dgram->data)); - p2 = skip_string(p2,1); + make_nmb_name(&dgram->source_name,srcname,src_type); + make_nmb_name(&dgram->dest_name,dstname,dest_type); + + ptr = &dgram->data[0]; + + /* Setup the smb part. */ + ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */ + memcpy(tmp,ptr,4); + set_message(ptr,17,23 + len,True); + memcpy(ptr,tmp,4); + + SCVAL(ptr,smb_com,SMBtrans); + SSVAL(ptr,smb_vwv1,len); + SSVAL(ptr,smb_vwv11,len); + SSVAL(ptr,smb_vwv12,70 + strlen(mailslot)); + SSVAL(ptr,smb_vwv13,3); + SSVAL(ptr,smb_vwv14,1); + SSVAL(ptr,smb_vwv15,1); + SSVAL(ptr,smb_vwv16,2); + p2 = smb_buf(ptr); + safe_strcpy_base(p2, mailslot, dgram->data, sizeof(dgram->data)); + p2 = skip_string(p2,1); - if (((p2+len) > dgram->data+sizeof(dgram->data)) || ((p2+len) < p2)) { - DEBUG(0, ("send_mailslot: Cannot write beyond end of packet\n")); - return False; - } else { - memcpy(p2,buf,len); - p2 += len; - } - - dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */ - - p.ip = dest_ip; - p.port = dest_port; - p.fd = find_subnet_mailslot_fd_for_address( src_ip ); - p.timestamp = time(NULL); - p.packet_type = DGRAM_PACKET; - - DEBUG(4,("send_mailslot: Sending to mailslot %s from %s IP %s ", mailslot, - nmb_namestr(&dgram->source_name), inet_ntoa(src_ip))); - DEBUG(4,("to %s IP %s\n", nmb_namestr(&dgram->dest_name), inet_ntoa(dest_ip))); - - debug_browse_data(buf, len); - - if(loopback_this_packet) - { - struct packet_struct *lo_packet = NULL; - DEBUG(5,("send_mailslot: sending packet to ourselves.\n")); - if((lo_packet = copy_packet(&p)) == NULL) - return False; - queue_packet(lo_packet); - return True; - } - else - return(send_packet(&p)); + if (((p2+len) > dgram->data+sizeof(dgram->data)) || ((p2+len) < p2)) { + DEBUG(0, ("send_mailslot: Cannot write beyond end of packet\n")); + return False; + } else { + memcpy(p2,buf,len); + p2 += len; + } + + dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */ + + p.ip = dest_ip; + p.port = dest_port; + p.fd = find_subnet_mailslot_fd_for_address( src_ip ); + p.timestamp = time(NULL); + p.packet_type = DGRAM_PACKET; + + DEBUG(4,("send_mailslot: Sending to mailslot %s from %s IP %s ", mailslot, + nmb_namestr(&dgram->source_name), inet_ntoa(src_ip))); + DEBUG(4,("to %s IP %s\n", nmb_namestr(&dgram->dest_name), inet_ntoa(dest_ip))); + + debug_browse_data(buf, len); + + if(loopback_this_packet) { + struct packet_struct *lo_packet = NULL; + DEBUG(5,("send_mailslot: sending packet to ourselves.\n")); + if((lo_packet = copy_packet(&p)) == NULL) + return False; + queue_packet(lo_packet); + return True; + } else { + return(send_packet(&p)); + } } diff --git a/source/nmbd/nmbd_processlogon.c b/source/nmbd/nmbd_processlogon.c index bc3540af70e..2a6a6b66d1f 100644 --- a/source/nmbd/nmbd_processlogon.c +++ b/source/nmbd/nmbd_processlogon.c @@ -3,7 +3,7 @@ NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002 This program is free software; you can redistribute it and/or modify @@ -35,6 +35,7 @@ struct sam_database_info { /**************************************************************************** Send a message to smbd to do a sam delta sync **************************************************************************/ + static void send_repl_message(uint32 low_serial) { TDB_CONTEXT *tdb; @@ -64,432 +65,452 @@ Process a domain logon packet void process_logon_packet(struct packet_struct *p, char *buf,int len, const char *mailslot) { - struct dgram_packet *dgram = &p->packet.dgram; - pstring my_name; - fstring reply_name; - pstring outbuf; - int code; - uint16 token = 0; - uint32 ntversion = 0; - uint16 lmnttoken = 0; - uint16 lm20token = 0; - uint32 domainsidsize; - BOOL short_request = False; - char *getdc; - char *uniuser; /* Unicode user name. */ - pstring ascuser; - char *unicomp; /* Unicode computer name. */ - - memset(outbuf, 0, sizeof(outbuf)); - - if (!lp_domain_logons()) - { - DEBUG(3,("process_logon_packet: Logon packet received from IP %s and domain \ + struct dgram_packet *dgram = &p->packet.dgram; + pstring my_name; + fstring reply_name; + pstring outbuf; + int code; + uint16 token = 0; + uint32 ntversion = 0; + uint16 lmnttoken = 0; + uint16 lm20token = 0; + uint32 domainsidsize; + BOOL short_request = False; + char *getdc; + char *uniuser; /* Unicode user name. */ + pstring ascuser; + char *unicomp; /* Unicode computer name. */ + + memset(outbuf, 0, sizeof(outbuf)); + + if (!lp_domain_logons()) { + DEBUG(3,("process_logon_packet: Logon packet received from IP %s and domain \ logons are not enabled.\n", inet_ntoa(p->ip) )); - return; - } - - pstrcpy(my_name, global_myname()); - - code = SVAL(buf,0); - DEBUG(1,("process_logon_packet: Logon from %s: code = 0x%x\n", inet_ntoa(p->ip), code)); - - switch (code) - { - case 0: - { - char *q = buf + 2; - char *machine = q; - char *user = skip_string(machine,1); - - getdc = skip_string(user,1); - q = skip_string(getdc,1); - token = SVAL(q,3); - - fstrcpy(reply_name,my_name); - - DEBUG(3,("process_logon_packet: Domain login request from %s at IP %s user=%s token=%x\n", - machine,inet_ntoa(p->ip),user,token)); - - q = outbuf; - SSVAL(q, 0, 6); - q += 2; - - fstrcpy(reply_name, "\\\\"); - fstrcat(reply_name, my_name); - fstrcpy(q, reply_name); q = skip_string(q, 1); /* PDC name */ - - SSVAL(q, 0, token); - q += 2; - - dump_data(4, outbuf, PTR_DIFF(q, outbuf)); - - send_mailslot(True, getdc, - outbuf,PTR_DIFF(q,outbuf), - global_myname(), 0x0, - machine, - dgram->source_name.name_type, - p->ip, *iface_ip(p->ip), p->port); - break; - } - - case QUERYFORPDC: - { - char *q = buf + 2; - char *machine = q; - - if (!lp_domain_master()) - { - /* We're not Primary Domain Controller -- ignore this */ - return; - } - - getdc = skip_string(machine,1); - q = skip_string(getdc,1); - q = ALIGN2(q, buf); - - /* at this point we can work out if this is a W9X or NT style - request. Experiments show that the difference is wether the - packet ends here. For a W9X request we now end with a pair of - bytes (usually 0xFE 0xFF) whereas with NT we have two further - strings - the following is a simple way of detecting this */ - if (len - PTR_DIFF(q, buf) <= 3) { - short_request = True; - } else { - unicomp = q; - - /* A full length (NT style) request */ - q = skip_unibuf(unicomp, PTR_DIFF(buf + len, unicomp)); - - if (len - PTR_DIFF(q, buf) > 8) { + return; + } + + pstrcpy(my_name, global_myname()); + + code = SVAL(buf,0); + DEBUG(1,("process_logon_packet: Logon from %s: code = 0x%x\n", inet_ntoa(p->ip), code)); + + switch (code) { + case 0: + { + fstring mach_str, user_str, getdc_str; + char *q = buf + 2; + char *machine = q; + char *user = skip_string(machine,1); + + getdc = skip_string(user,1); + q = skip_string(getdc,1); + token = SVAL(q,3); + + fstrcpy(reply_name,my_name); + + pull_ascii_fstring(mach_str, machine); + pull_ascii_fstring(user_str, user); + pull_ascii_fstring(getdc_str, getdc); + + DEBUG(3,("process_logon_packet: Domain login request from %s at IP %s user=%s token=%x\n", + mach_str,inet_ntoa(p->ip),user_str,token)); + + q = outbuf; + SSVAL(q, 0, 6); + q += 2; + + fstrcpy(reply_name, "\\\\"); + fstrcat(reply_name, my_name); + push_ascii_fstring(q, reply_name); + q = skip_string(q, 1); /* PDC name */ + + SSVAL(q, 0, token); + q += 2; + + dump_data(4, outbuf, PTR_DIFF(q, outbuf)); + + send_mailslot(True, getdc_str, + outbuf,PTR_DIFF(q,outbuf), + global_myname(), 0x0, + mach_str, + dgram->source_name.name_type, + p->ip, *iface_ip(p->ip), p->port); + break; + } + + case QUERYFORPDC: + { + fstring mach_str, getdc_str; + nstring source_name; + char *q = buf + 2; + char *machine = q; + + if (!lp_domain_master()) { + /* We're not Primary Domain Controller -- ignore this */ + return; + } + + getdc = skip_string(machine,1); + q = skip_string(getdc,1); + q = ALIGN2(q, buf); + + /* At this point we can work out if this is a W9X or NT style + request. Experiments show that the difference is wether the + packet ends here. For a W9X request we now end with a pair of + bytes (usually 0xFE 0xFF) whereas with NT we have two further + strings - the following is a simple way of detecting this */ + + if (len - PTR_DIFF(q, buf) <= 3) { + short_request = True; + } else { + unicomp = q; + + /* A full length (NT style) request */ + q = skip_unibuf(unicomp, PTR_DIFF(buf + len, unicomp)); + + if (len - PTR_DIFF(q, buf) > 8) { + /* with NT5 clients we can sometimes + get additional data - a length specificed string + containing the domain name, then 16 bytes of + data (no idea what it is) */ + int dom_len = CVAL(q, 0); + q++; + if (dom_len != 0) { + q += dom_len + 1; + } + q += 16; + } + ntversion = IVAL(q, 0); + lmnttoken = SVAL(q, 4); + lm20token = SVAL(q, 6); + } + + /* Construct reply. */ + q = outbuf; + SSVAL(q, 0, QUERYFORPDC_R); + q += 2; + + fstrcpy(reply_name,my_name); + push_ascii_fstring(q, reply_name); + q = skip_string(q, 1); /* PDC name */ + + /* PDC and domain name */ + if (!short_request) { + /* Make a full reply */ + q = ALIGN2(q, outbuf); + + q += dos_PutUniCode(q, my_name, sizeof(pstring), True); /* PDC name */ + q += dos_PutUniCode(q, lp_workgroup(),sizeof(pstring), True); /* Domain name*/ + SIVAL(q, 0, 1); /* our nt version */ + SSVAL(q, 4, 0xffff); /* our lmnttoken */ + SSVAL(q, 6, 0xffff); /* our lm20token */ + q += 8; + } + + /* RJS, 21-Feb-2000, we send a short reply if the request was short */ + + pull_ascii_fstring(mach_str, machine); + + DEBUG(3,("process_logon_packet: GETDC request from %s at IP %s, \ +reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", + mach_str,inet_ntoa(p->ip), reply_name, lp_workgroup(), + QUERYFORPDC_R, (uint32)ntversion, (uint32)lmnttoken, + (uint32)lm20token )); + + dump_data(4, outbuf, PTR_DIFF(q, outbuf)); + + pull_ascii_fstring(getdc_str, getdc); + pull_ascii_nstring(source_name, dgram->source_name.name); + + send_mailslot(True, getdc_str, + outbuf,PTR_DIFF(q,outbuf), + global_myname(), 0x0, + source_name, + dgram->source_name.name_type, + p->ip, *iface_ip(p->ip), p->port); + return; + } + + case SAMLOGON: + + { + fstring getdc_str; + nstring source_name; + char *q = buf + 2; + fstring asccomp; + + q += 2; + unicomp = q; + uniuser = skip_unibuf(unicomp, PTR_DIFF(buf+len, unicomp)); + getdc = skip_unibuf(uniuser,PTR_DIFF(buf+len, uniuser)); + q = skip_string(getdc,1); + q += 4; /* Account Control Bits - indicating username type */ + domainsidsize = IVAL(q, 0); + q += 4; + + DEBUG(3,("process_logon_packet: SAMLOGON sidsize %d, len = %d\n", domainsidsize, len)); + + if (domainsidsize < (len - PTR_DIFF(q, buf)) && (domainsidsize != 0)) { + q += domainsidsize; + q = ALIGN4(q, buf); + } + + DEBUG(3,("process_logon_packet: len = %d PTR_DIFF(q, buf) = %d\n", len, PTR_DIFF(q, buf) )); + + if (len - PTR_DIFF(q, buf) > 8) { /* with NT5 clients we can sometimes - get additional data - a length specificed string - containing the domain name, then 16 bytes of - data (no idea what it is) */ + get additional data - a length specificed string + containing the domain name, then 16 bytes of + data (no idea what it is) */ int dom_len = CVAL(q, 0); q++; - if (dom_len != 0) { + if (dom_len < (len - PTR_DIFF(q, buf)) && (dom_len != 0)) { q += dom_len + 1; } q += 16; - } - ntversion = IVAL(q, 0); - lmnttoken = SVAL(q, 4); - lm20token = SVAL(q, 6); - } - - /* Construct reply. */ - q = outbuf; - SSVAL(q, 0, QUERYFORPDC_R); - q += 2; - - fstrcpy(reply_name,my_name); - fstrcpy(q, reply_name); - q = skip_string(q, 1); /* PDC name */ - - /* PDC and domain name */ - if (!short_request) /* Make a full reply */ - { - q = ALIGN2(q, outbuf); - - q += dos_PutUniCode(q, my_name, sizeof(pstring), True); /* PDC name */ - q += dos_PutUniCode(q, lp_workgroup(),sizeof(pstring), True); /* Domain name*/ - SIVAL(q, 0, 1); /* our nt version */ - SSVAL(q, 4, 0xffff); /* our lmnttoken */ - SSVAL(q, 6, 0xffff); /* our lm20token */ - q += 8; - } - - /* RJS, 21-Feb-2000, we send a short reply if the request was short */ - - DEBUG(3,("process_logon_packet: GETDC request from %s at IP %s, \ -reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", - machine,inet_ntoa(p->ip), reply_name, lp_workgroup(), - QUERYFORPDC_R, (uint32)ntversion, (uint32)lmnttoken, - (uint32)lm20token )); - - dump_data(4, outbuf, PTR_DIFF(q, outbuf)); - - send_mailslot(True, getdc, - outbuf,PTR_DIFF(q,outbuf), - global_myname(), 0x0, - dgram->source_name.name, - dgram->source_name.name_type, - p->ip, *iface_ip(p->ip), p->port); - return; - } - - case SAMLOGON: - { - char *q = buf + 2; - fstring asccomp; - - q += 2; - unicomp = q; - uniuser = skip_unibuf(unicomp, PTR_DIFF(buf+len, unicomp)); - getdc = skip_unibuf(uniuser,PTR_DIFF(buf+len, uniuser)); - q = skip_string(getdc,1); - q += 4; /* Account Control Bits - indicating username type */ - domainsidsize = IVAL(q, 0); - q += 4; - - DEBUG(3,("process_logon_packet: SAMLOGON sidsize %d, len = %d\n", domainsidsize, len)); - - if (domainsidsize < (len - PTR_DIFF(q, buf)) && (domainsidsize != 0)) { - q += domainsidsize; - q = ALIGN4(q, buf); - } - - DEBUG(3,("process_logon_packet: len = %d PTR_DIFF(q, buf) = %d\n", len, PTR_DIFF(q, buf) )); - - if (len - PTR_DIFF(q, buf) > 8) { - /* with NT5 clients we can sometimes - get additional data - a length specificed string - containing the domain name, then 16 bytes of - data (no idea what it is) */ - int dom_len = CVAL(q, 0); - q++; - if (dom_len < (len - PTR_DIFF(q, buf)) && (dom_len != 0)) { - q += dom_len + 1; - } - q += 16; - } - - ntversion = IVAL(q, 0); - lmnttoken = SVAL(q, 4); - lm20token = SVAL(q, 6); - q += 8; - - DEBUG(3,("process_logon_packet: SAMLOGON sidsize %d ntv %d\n", domainsidsize, ntversion)); - - /* - * we respond regadless of whether the machine is in our password - * database. If it isn't then we let smbd send an appropriate error. - * Let's ignore the SID. - */ - pull_ucs2_pstring(ascuser, uniuser); - pull_ucs2_fstring(asccomp, unicomp); - DEBUG(3,("process_logon_packet: SAMLOGON user %s\n", ascuser)); - - fstrcpy(reply_name, "\\\\"); /* Here it wants \\LOGONSERVER. */ - fstrcat(reply_name, my_name); - - DEBUG(3,("process_logon_packet: SAMLOGON request from %s(%s) for %s, returning logon svr %s domain %s code %x token=%x\n", - asccomp,inet_ntoa(p->ip), ascuser, reply_name, lp_workgroup(), - SAMLOGON_R ,lmnttoken)); - - /* Construct reply. */ - - q = outbuf; - /* we want the simple version unless we are an ADS PDC..which means */ - /* never, at least for now */ - if ((ntversion < 11) || (SEC_ADS != lp_security()) || (ROLE_DOMAIN_PDC != lp_server_role())) { - if (SVAL(uniuser, 0) == 0) { - SSVAL(q, 0, SAMLOGON_UNK_R); /* user unknown */ - } else { - SSVAL(q, 0, SAMLOGON_R); - } + } + + ntversion = IVAL(q, 0); + lmnttoken = SVAL(q, 4); + lm20token = SVAL(q, 6); + q += 8; + + DEBUG(3,("process_logon_packet: SAMLOGON sidsize %d ntv %d\n", domainsidsize, ntversion)); + + /* + * we respond regadless of whether the machine is in our password + * database. If it isn't then we let smbd send an appropriate error. + * Let's ignore the SID. + */ + pull_ucs2_pstring(ascuser, uniuser); + pull_ucs2_fstring(asccomp, unicomp); + DEBUG(3,("process_logon_packet: SAMLOGON user %s\n", ascuser)); + + fstrcpy(reply_name, "\\\\"); /* Here it wants \\LOGONSERVER. */ + fstrcat(reply_name, my_name); + + DEBUG(3,("process_logon_packet: SAMLOGON request from %s(%s) for %s, returning logon svr %s domain %s code %x token=%x\n", + asccomp,inet_ntoa(p->ip), ascuser, reply_name, lp_workgroup(), + SAMLOGON_R ,lmnttoken)); + + /* Construct reply. */ + + q = outbuf; + /* we want the simple version unless we are an ADS PDC..which means */ + /* never, at least for now */ + if ((ntversion < 11) || (SEC_ADS != lp_security()) || (ROLE_DOMAIN_PDC != lp_server_role())) { + if (SVAL(uniuser, 0) == 0) { + SSVAL(q, 0, SAMLOGON_UNK_R); /* user unknown */ + } else { + SSVAL(q, 0, SAMLOGON_R); + } - q += 2; + q += 2; - q += dos_PutUniCode(q, reply_name,sizeof(pstring), True); - q += dos_PutUniCode(q, ascuser, sizeof(pstring), True); - q += dos_PutUniCode(q, lp_workgroup(),sizeof(pstring), True); - } + q += dos_PutUniCode(q, reply_name,sizeof(pstring), True); + q += dos_PutUniCode(q, ascuser, sizeof(pstring), True); + q += dos_PutUniCode(q, lp_workgroup(),sizeof(pstring), True); + } #ifdef HAVE_ADS - else { - GUID domain_guid; - pstring domain; - pstring hostname; - char *component, *dc, *q1; - uint8 size; - char *q_orig = q; - int str_offset; - - get_mydomname(domain); - get_myname(hostname); + else { + GUID domain_guid; + pstring domain; + pstring hostname; + char *component, *dc, *q1; + uint8 size; + char *q_orig = q; + int str_offset; + + get_mydomname(domain); + get_myname(hostname); - if (SVAL(uniuser, 0) == 0) { - SIVAL(q, 0, SAMLOGON_AD_UNK_R); /* user unknown */ - } else { - SIVAL(q, 0, SAMLOGON_AD_R); - } - q += 4; + if (SVAL(uniuser, 0) == 0) { + SIVAL(q, 0, SAMLOGON_AD_UNK_R); /* user unknown */ + } else { + SIVAL(q, 0, SAMLOGON_AD_R); + } + q += 4; - SIVAL(q, 0, ADS_PDC|ADS_GC|ADS_LDAP|ADS_DS| - ADS_KDC|ADS_TIMESERV|ADS_CLOSEST|ADS_WRITABLE); - q += 4; + SIVAL(q, 0, ADS_PDC|ADS_GC|ADS_LDAP|ADS_DS| + ADS_KDC|ADS_TIMESERV|ADS_CLOSEST|ADS_WRITABLE); + q += 4; - /* Push Domain GUID */ - if (False == secrets_fetch_domain_guid(domain, &domain_guid)) { - DEBUG(2, ("Could not fetch DomainGUID for %s\n", domain)); - return; - } - memcpy(q, &domain_guid, sizeof(domain_guid)); - q += sizeof(domain_guid); - - /* Forest */ - str_offset = q - q_orig; - dc = domain; - q1 = q; - while ((component = strtok(dc, "."))) { - dc = NULL; - size = push_ascii(&q[1], component, -1, 0); - SCVAL(q, 0, size); - q += (size + 1); - } + /* Push Domain GUID */ + if (False == secrets_fetch_domain_guid(domain, &domain_guid)) { + DEBUG(2, ("Could not fetch DomainGUID for %s\n", domain)); + return; + } + memcpy(q, &domain_guid, sizeof(domain_guid)); + q += sizeof(domain_guid); + + /* Forest */ + str_offset = q - q_orig; + dc = domain; + q1 = q; + while ((component = strtok(dc, "."))) { + dc = NULL; + size = push_ascii(&q[1], component, -1, 0); + SCVAL(q, 0, size); + q += (size + 1); + } - /* Unk0 */ - SCVAL(q, 0, 0); q++; - - /* Domain */ - SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); - SCVAL(q, 1, str_offset & 0xFF); - q += 2; - - /* Hostname */ - size = push_ascii(&q[1], hostname, -1, 0); - SCVAL(q, 0, size); - q += (size + 1); - SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); - SCVAL(q, 1, str_offset & 0xFF); - q += 2; - - /* NETBIOS of domain */ - size = push_ascii(&q[1], lp_workgroup(), -1, STR_UPPER); - SCVAL(q, 0, size); - q += (size + 1); - - /* Unk1 */ - SCVAL(q, 0, 0); q++; - - /* NETBIOS of hostname */ - size = push_ascii(&q[1], my_name, -1, 0); - SCVAL(q, 0, size); - q += (size + 1); - - /* Unk2 */ - SCVAL(q, 0, 0); q++; - - /* User name */ - if (SVAL(uniuser, 0) != 0) { - size = push_ascii(&q[1], ascuser, -1, 0); - SCVAL(q, 0, size); - q += (size + 1); - } + /* Unk0 */ + SCVAL(q, 0, 0); + q++; - q_orig = q; - /* Site name */ - size = push_ascii(&q[1], "Default-First-Site-Name", -1, 0); - SCVAL(q, 0, size); - q += (size + 1); - - /* Site name (2) */ - str_offset = q - q_orig; - SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); - SCVAL(q, 1, str_offset & 0xFF); - q += 2; - - SCVAL(q, 0, PTR_DIFF(q,q1)); - SCVAL(q, 1, 0x10); /* unknown */ - - SIVAL(q, 0, 0x00000002); q += 4; /* unknown */ - SIVAL(q, 0, (iface_ip(p->ip))->s_addr); q += 4; - SIVAL(q, 0, 0x00000000); q += 4; /* unknown */ - SIVAL(q, 0, 0x00000000); q += 4; /* unknown */ - } + /* Domain */ + SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); + SCVAL(q, 1, str_offset & 0xFF); + q += 2; + + /* Hostname */ + size = push_ascii(&q[1], hostname, -1, 0); + SCVAL(q, 0, size); + q += (size + 1); + SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); + SCVAL(q, 1, str_offset & 0xFF); + q += 2; + + /* NETBIOS of domain */ + size = push_ascii(&q[1], lp_workgroup(), -1, STR_UPPER); + SCVAL(q, 0, size); + q += (size + 1); + + /* Unk1 */ + SCVAL(q, 0, 0); + q++; + + /* NETBIOS of hostname */ + size = push_ascii(&q[1], my_name, -1, 0); + SCVAL(q, 0, size); + q += (size + 1); + + /* Unk2 */ + SCVAL(q, 0, 0); + q++; + + /* User name */ + if (SVAL(uniuser, 0) != 0) { + size = push_ascii(&q[1], ascuser, -1, 0); + SCVAL(q, 0, size); + q += (size + 1); + } + + q_orig = q; + /* Site name */ + size = push_ascii(&q[1], "Default-First-Site-Name", -1, 0); + SCVAL(q, 0, size); + q += (size + 1); + + /* Site name (2) */ + str_offset = q - q_orig; + SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); + SCVAL(q, 1, str_offset & 0xFF); + q += 2; + + SCVAL(q, 0, PTR_DIFF(q,q1)); + SCVAL(q, 1, 0x10); /* unknown */ + + SIVAL(q, 0, 0x00000002); + q += 4; /* unknown */ + SIVAL(q, 0, (iface_ip(p->ip))->s_addr); + q += 4; + SIVAL(q, 0, 0x00000000); + q += 4; /* unknown */ + SIVAL(q, 0, 0x00000000); + q += 4; /* unknown */ + } #endif - /* tell the client what version we are */ - SIVAL(q, 0, ((ntversion < 11) || (SEC_ADS != lp_security())) ? 1 : 13); - /* our ntversion */ - SSVAL(q, 4, 0xffff); /* our lmnttoken */ - SSVAL(q, 6, 0xffff); /* our lm20token */ - q += 8; - - dump_data(4, outbuf, PTR_DIFF(q, outbuf)); - - send_mailslot(True, getdc, - outbuf,PTR_DIFF(q,outbuf), - global_myname(), 0x0, - dgram->source_name.name, - dgram->source_name.name_type, - p->ip, *iface_ip(p->ip), p->port); - break; - } - - /* Announce change to UAS or SAM. Send by the domain controller when a - replication event is required. */ - - case SAM_UAS_CHANGE: { - struct sam_database_info *db_info; - char *q = buf + 2; - int i, db_count; - uint32 low_serial; + /* tell the client what version we are */ + SIVAL(q, 0, ((ntversion < 11) || (SEC_ADS != lp_security())) ? 1 : 13); + /* our ntversion */ + SSVAL(q, 4, 0xffff); /* our lmnttoken */ + SSVAL(q, 6, 0xffff); /* our lm20token */ + q += 8; + + dump_data(4, outbuf, PTR_DIFF(q, outbuf)); + + pull_ascii_fstring(getdc_str, getdc); + pull_ascii_nstring(source_name, dgram->source_name.name); + + send_mailslot(True, getdc, + outbuf,PTR_DIFF(q,outbuf), + global_myname(), 0x0, + dgram->source_name.name, + dgram->source_name.name_type, + p->ip, *iface_ip(p->ip), p->port); + break; + } + + /* Announce change to UAS or SAM. Send by the domain controller when a + replication event is required. */ + + case SAM_UAS_CHANGE: + { + struct sam_database_info *db_info; + char *q = buf + 2; + int i, db_count; + uint32 low_serial; - /* Header */ + /* Header */ - low_serial = IVAL(q, 0); q += 4; /* Low serial number */ + low_serial = IVAL(q, 0); q += 4; /* Low serial number */ - q += 4; /* Date/time */ - q += 4; /* Pulse */ - q += 4; /* Random */ + q += 4; /* Date/time */ + q += 4; /* Pulse */ + q += 4; /* Random */ - /* Domain info */ + /* Domain info */ - q = skip_string(q, 1); /* PDC name */ - q = skip_string(q, 1); /* Domain name */ - q = skip_unibuf(q, PTR_DIFF(buf + len, q)); /* Unicode PDC name */ - q = skip_unibuf(q, PTR_DIFF(buf + len, q)); /* Unicode domain name */ + q = skip_string(q, 1); /* PDC name */ + q = skip_string(q, 1); /* Domain name */ + q = skip_unibuf(q, PTR_DIFF(buf + len, q)); /* Unicode PDC name */ + q = skip_unibuf(q, PTR_DIFF(buf + len, q)); /* Unicode domain name */ - /* Database info */ + /* Database info */ - db_count = SVAL(q, 0); q += 2; + db_count = SVAL(q, 0); q += 2; - db_info = (struct sam_database_info *) - malloc(sizeof(struct sam_database_info) * db_count); - - if (db_info == NULL) { - DEBUG(3, ("out of memory allocating info for %d databases\n", - db_count)); - return; - } + db_info = (struct sam_database_info *) + malloc(sizeof(struct sam_database_info) * db_count); + + if (db_info == NULL) { + DEBUG(3, ("out of memory allocating info for %d databases\n", db_count)); + return; + } - for (i = 0; i < db_count; i++) { - db_info[i].index = IVAL(q, 0); - db_info[i].serial_lo = IVAL(q, 4); - db_info[i].serial_hi = IVAL(q, 8); - db_info[i].date_lo = IVAL(q, 12); - db_info[i].date_hi = IVAL(q, 16); - q += 20; - } - - /* Domain SID */ - - q += IVAL(q, 0) + 4; /* 4 byte length plus data */ + for (i = 0; i < db_count; i++) { + db_info[i].index = IVAL(q, 0); + db_info[i].serial_lo = IVAL(q, 4); + db_info[i].serial_hi = IVAL(q, 8); + db_info[i].date_lo = IVAL(q, 12); + db_info[i].date_hi = IVAL(q, 16); + q += 20; + } + + /* Domain SID */ + + q += IVAL(q, 0) + 4; /* 4 byte length plus data */ - q += 2; /* Alignment? */ - - /* Misc other info */ + q += 2; /* Alignment? */ - q += 4; /* NT version (0x1) */ - q += 2; /* LMNT token (0xff) */ - q += 2; /* LM20 token (0xff) */ + /* Misc other info */ - SAFE_FREE(db_info); /* Not sure whether we need to do anything - useful with these */ + q += 4; /* NT version (0x1) */ + q += 2; /* LMNT token (0xff) */ + q += 2; /* LM20 token (0xff) */ - /* Send message to smbd */ + SAFE_FREE(db_info); /* Not sure whether we need to do anything useful with these */ - send_repl_message(low_serial); + /* Send message to smbd */ - break; - } + send_repl_message(low_serial); + break; + } - default: - { - DEBUG(3,("process_logon_packet: Unknown domain request %d\n",code)); - return; - } - } + default: + DEBUG(3,("process_logon_packet: Unknown domain request %d\n",code)); + return; + } } diff --git a/source/nmbd/nmbd_responserecordsdb.c b/source/nmbd/nmbd_responserecordsdb.c index 7e8c8025aeb..30c0c129508 100644 --- a/source/nmbd/nmbd_responserecordsdb.c +++ b/source/nmbd/nmbd_responserecordsdb.c @@ -34,27 +34,26 @@ int num_response_packets = 0; static void add_response_record(struct subnet_record *subrec, struct response_record *rrec) { - struct response_record *rrec2; + struct response_record *rrec2; - num_response_packets++; /* count of total number of packets still around */ + num_response_packets++; /* count of total number of packets still around */ - DEBUG(4,("add_response_record: adding response record id:%hu to subnet %s. num_records:%d\n", - rrec->response_id, subrec->subnet_name, num_response_packets)); + DEBUG(4,("add_response_record: adding response record id:%hu to subnet %s. num_records:%d\n", + rrec->response_id, subrec->subnet_name, num_response_packets)); - if (!subrec->responselist) - { - subrec->responselist = rrec; - rrec->prev = NULL; - rrec->next = NULL; - return; - } + if (!subrec->responselist) { + subrec->responselist = rrec; + rrec->prev = NULL; + rrec->next = NULL; + return; + } - for (rrec2 = subrec->responselist; rrec2->next; rrec2 = rrec2->next) - ; + for (rrec2 = subrec->responselist; rrec2->next; rrec2 = rrec2->next) + ; - rrec2->next = rrec; - rrec->next = NULL; - rrec->prev = rrec2; + rrec2->next = rrec; + rrec->next = NULL; + rrec->prev = rrec2; } /*************************************************************************** @@ -64,32 +63,31 @@ static void add_response_record(struct subnet_record *subrec, void remove_response_record(struct subnet_record *subrec, struct response_record *rrec) { - if (rrec->prev) - rrec->prev->next = rrec->next; - if (rrec->next) - rrec->next->prev = rrec->prev; - - if (subrec->responselist == rrec) - subrec->responselist = rrec->next; - - if(rrec->userdata) - { - if(rrec->userdata->free_fn) { - (*rrec->userdata->free_fn)(rrec->userdata); - } else { - ZERO_STRUCTP(rrec->userdata); - SAFE_FREE(rrec->userdata); - } - } - - /* Ensure we can delete. */ - rrec->packet->locked = False; - free_packet(rrec->packet); - - ZERO_STRUCTP(rrec); - SAFE_FREE(rrec); - - num_response_packets--; /* count of total number of packets still around */ + if (rrec->prev) + rrec->prev->next = rrec->next; + if (rrec->next) + rrec->next->prev = rrec->prev; + + if (subrec->responselist == rrec) + subrec->responselist = rrec->next; + + if(rrec->userdata) { + if(rrec->userdata->free_fn) { + (*rrec->userdata->free_fn)(rrec->userdata); + } else { + ZERO_STRUCTP(rrec->userdata); + SAFE_FREE(rrec->userdata); + } + } + + /* Ensure we can delete. */ + rrec->packet->locked = False; + free_packet(rrec->packet); + + ZERO_STRUCTP(rrec); + SAFE_FREE(rrec); + + num_response_packets--; /* count of total number of packets still around */ } /**************************************************************************** @@ -104,77 +102,70 @@ struct response_record *make_response_record( struct subnet_record *subrec, fail_function fail_fn, struct userdata_struct *userdata) { - struct response_record *rrec; - struct nmb_packet *nmb = &p->packet.nmb; - - if (!(rrec = (struct response_record *)malloc(sizeof(*rrec)))) - { - DEBUG(0,("make_response_queue_record: malloc fail for response_record.\n")); - return NULL; - } - - memset((char *)rrec, '\0', sizeof(*rrec)); - - rrec->response_id = nmb->header.name_trn_id; - - rrec->resp_fn = resp_fn; - rrec->timeout_fn = timeout_fn; - rrec->success_fn = success_fn; - rrec->fail_fn = fail_fn; - - rrec->packet = p; - - if(userdata) - { - /* Intelligent userdata. */ - if(userdata->copy_fn) - { - if((rrec->userdata = (*userdata->copy_fn)(userdata)) == NULL) - { - DEBUG(0,("make_response_queue_record: copy fail for userdata.\n")); - ZERO_STRUCTP(rrec); - SAFE_FREE(rrec); - return NULL; - } - } - else - { - /* Primitive userdata, do a memcpy. */ - if((rrec->userdata = (struct userdata_struct *) - malloc(sizeof(struct userdata_struct)+userdata->userdata_len)) == NULL) - { - DEBUG(0,("make_response_queue_record: malloc fail for userdata.\n")); - ZERO_STRUCTP(rrec); - SAFE_FREE(rrec); - return NULL; - } - rrec->userdata->copy_fn = userdata->copy_fn; - rrec->userdata->free_fn = userdata->free_fn; - rrec->userdata->userdata_len = userdata->userdata_len; - memcpy(rrec->userdata->data, userdata->data, userdata->userdata_len); - } - } - else - rrec->userdata = NULL; - - rrec->num_msgs = 0; - - if(!nmb->header.nm_flags.bcast) - rrec->repeat_interval = 5; /* 5 seconds for unicast packets. */ - else - rrec->repeat_interval = 1; /* XXXX should be in ms */ - rrec->repeat_count = 3; /* 3 retries */ - rrec->repeat_time = time(NULL) + rrec->repeat_interval; /* initial retry time */ - - /* This packet is not being processed. */ - rrec->in_expiration_processing = False; - - /* Lock the packet so we won't lose it while it's on the list. */ - p->locked = True; - - add_response_record(subrec, rrec); - - return rrec; + struct response_record *rrec; + struct nmb_packet *nmb = &p->packet.nmb; + + if (!(rrec = (struct response_record *)malloc(sizeof(*rrec)))) { + DEBUG(0,("make_response_queue_record: malloc fail for response_record.\n")); + return NULL; + } + + memset((char *)rrec, '\0', sizeof(*rrec)); + + rrec->response_id = nmb->header.name_trn_id; + + rrec->resp_fn = resp_fn; + rrec->timeout_fn = timeout_fn; + rrec->success_fn = success_fn; + rrec->fail_fn = fail_fn; + + rrec->packet = p; + + if(userdata) { + /* Intelligent userdata. */ + if(userdata->copy_fn) { + if((rrec->userdata = (*userdata->copy_fn)(userdata)) == NULL) { + DEBUG(0,("make_response_queue_record: copy fail for userdata.\n")); + ZERO_STRUCTP(rrec); + SAFE_FREE(rrec); + return NULL; + } + } else { + /* Primitive userdata, do a memcpy. */ + if((rrec->userdata = (struct userdata_struct *) + malloc(sizeof(struct userdata_struct)+userdata->userdata_len)) == NULL) { + DEBUG(0,("make_response_queue_record: malloc fail for userdata.\n")); + ZERO_STRUCTP(rrec); + SAFE_FREE(rrec); + return NULL; + } + rrec->userdata->copy_fn = userdata->copy_fn; + rrec->userdata->free_fn = userdata->free_fn; + rrec->userdata->userdata_len = userdata->userdata_len; + memcpy(rrec->userdata->data, userdata->data, userdata->userdata_len); + } + } else { + rrec->userdata = NULL; + } + + rrec->num_msgs = 0; + + if(!nmb->header.nm_flags.bcast) + rrec->repeat_interval = 5; /* 5 seconds for unicast packets. */ + else + rrec->repeat_interval = 1; /* XXXX should be in ms */ + rrec->repeat_count = 3; /* 3 retries */ + rrec->repeat_time = time(NULL) + rrec->repeat_interval; /* initial retry time */ + + /* This packet is not being processed. */ + rrec->in_expiration_processing = False; + + /* Lock the packet so we won't lose it while it's on the list. */ + p->locked = True; + + add_response_record(subrec, rrec); + + return rrec; } /**************************************************************************** @@ -184,18 +175,16 @@ struct response_record *make_response_record( struct subnet_record *subrec, static struct response_record *find_response_record_on_subnet( struct subnet_record *subrec, uint16 id) { - struct response_record *rrec = NULL; - - for (rrec = subrec->responselist; rrec; rrec = rrec->next) - { - if (rrec->response_id == id) - { - DEBUG(4, ("find_response_record: found response record id = %hu on subnet %s\n", - id, subrec->subnet_name)); - break; - } - } - return rrec; + struct response_record *rrec = NULL; + + for (rrec = subrec->responselist; rrec; rrec = rrec->next) { + if (rrec->response_id == id) { + DEBUG(4, ("find_response_record: found response record id = %hu on subnet %s\n", + id, subrec->subnet_name)); + break; + } + } + return rrec; } /**************************************************************************** @@ -205,37 +194,34 @@ static struct response_record *find_response_record_on_subnet( struct response_record *find_response_record(struct subnet_record **ppsubrec, uint16 id) { - struct response_record *rrec = NULL; - - for ((*ppsubrec) = FIRST_SUBNET; (*ppsubrec); - (*ppsubrec) = NEXT_SUBNET_INCLUDING_UNICAST(*ppsubrec)) - { - if((rrec = find_response_record_on_subnet(*ppsubrec, id)) != NULL) - return rrec; - } - - /* There should never be response records on the remote_broadcast subnet. - Sanity check to ensure this is so. */ - if(remote_broadcast_subnet->responselist != NULL) - { - DEBUG(0,("find_response_record: response record found on subnet %s. This should \ + struct response_record *rrec = NULL; + + for ((*ppsubrec) = FIRST_SUBNET; (*ppsubrec); + (*ppsubrec) = NEXT_SUBNET_INCLUDING_UNICAST(*ppsubrec)) { + if((rrec = find_response_record_on_subnet(*ppsubrec, id)) != NULL) + return rrec; + } + + /* There should never be response records on the remote_broadcast subnet. + Sanity check to ensure this is so. */ + if(remote_broadcast_subnet->responselist != NULL) { + DEBUG(0,("find_response_record: response record found on subnet %s. This should \ never happen !\n", remote_broadcast_subnet->subnet_name)); - } + } - /* Now check the WINS server subnet if it exists. */ - if(wins_server_subnet != NULL) - { - *ppsubrec = wins_server_subnet; - if((rrec = find_response_record_on_subnet(*ppsubrec, id))!= NULL) - return rrec; - } + /* Now check the WINS server subnet if it exists. */ + if(wins_server_subnet != NULL) { + *ppsubrec = wins_server_subnet; + if((rrec = find_response_record_on_subnet(*ppsubrec, id))!= NULL) + return rrec; + } - DEBUG(0,("find_response_record: response packet id %hu received with no \ + DEBUG(0,("find_response_record: response packet id %hu received with no \ matching record.\n", id)); - *ppsubrec = NULL; + *ppsubrec = NULL; - return NULL; + return NULL; } /**************************************************************************** @@ -244,21 +230,19 @@ matching record.\n", id)); BOOL is_refresh_already_queued(struct subnet_record *subrec, struct name_record *namerec) { - struct response_record *rrec = NULL; + struct response_record *rrec = NULL; - for (rrec = subrec->responselist; rrec; rrec = rrec->next) - { - struct packet_struct *p = rrec->packet; - struct nmb_packet *nmb = &p->packet.nmb; - - if((nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_8) || - (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_9)) - { - /* Yes it's a queued refresh - check if the name is correct. */ - if(nmb_name_equal(&nmb->question.question_name, &namerec->name)) - return True; - } - } - - return False; -} + for (rrec = subrec->responselist; rrec; rrec = rrec->next) { + struct packet_struct *p = rrec->packet; + struct nmb_packet *nmb = &p->packet.nmb; + + if((nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_8) || + (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_9)) { + /* Yes it's a queued refresh - check if the name is correct. */ + if(nmb_name_equal(&nmb->question.question_name, &namerec->name)) + return True; + } + } + + return False; +} diff --git a/source/nmbd/nmbd_sendannounce.c b/source/nmbd/nmbd_sendannounce.c index 353717ee623..87908e352cf 100644 --- a/source/nmbd/nmbd_sendannounce.c +++ b/source/nmbd/nmbd_sendannounce.c @@ -35,21 +35,21 @@ extern BOOL found_lm_clients; void send_browser_reset(int reset_type, const char *to_name, int to_type, struct in_addr to_ip) { - pstring outbuf; - char *p; + pstring outbuf; + char *p; - DEBUG(3,("send_browser_reset: sending reset request type %d to %s<%02x> IP %s.\n", - reset_type, to_name, to_type, inet_ntoa(to_ip) )); + DEBUG(3,("send_browser_reset: sending reset request type %d to %s<%02x> IP %s.\n", + reset_type, to_name, to_type, inet_ntoa(to_ip) )); - memset(outbuf,'\0',sizeof(outbuf)); - p = outbuf; - SCVAL(p,0,ANN_ResetBrowserState); - p++; - SCVAL(p,0,reset_type); - p++; + memset(outbuf,'\0',sizeof(outbuf)); + p = outbuf; + SCVAL(p,0,ANN_ResetBrowserState); + p++; + SCVAL(p,0,reset_type); + p++; - send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf), - global_myname(), 0x0, to_name, to_type, to_ip, + send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf), + global_myname(), 0x0, to_name, to_type, to_ip, FIRST_SUBNET->myip, DGRAM_PORT); } @@ -60,25 +60,25 @@ void send_browser_reset(int reset_type, const char *to_name, int to_type, struct void broadcast_announce_request(struct subnet_record *subrec, struct work_record *work) { - pstring outbuf; - char *p; + pstring outbuf; + char *p; - work->needannounce = True; + work->needannounce = True; - DEBUG(3,("broadcast_announce_request: sending announce request for workgroup %s \ + DEBUG(3,("broadcast_announce_request: sending announce request for workgroup %s \ to subnet %s\n", work->work_group, subrec->subnet_name)); - memset(outbuf,'\0',sizeof(outbuf)); - p = outbuf; - SCVAL(p,0,ANN_AnnouncementRequest); - p++; + memset(outbuf,'\0',sizeof(outbuf)); + p = outbuf; + SCVAL(p,0,ANN_AnnouncementRequest); + p++; - SCVAL(p,0,work->token); /* (local) Unique workgroup token id. */ - p++; - p += push_string(NULL, p+1, global_myname(), 15, STR_ASCII|STR_UPPER|STR_TERMINATE); + SCVAL(p,0,work->token); /* (local) Unique workgroup token id. */ + p++; + p += push_string(NULL, p+1, global_myname(), 15, STR_ASCII|STR_UPPER|STR_TERMINATE); - send_mailslot(False, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf), - global_myname(), 0x0, work->work_group,0x1e, subrec->bcast_ip, + send_mailslot(False, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf), + global_myname(), 0x0, work->work_group,0x1e, subrec->bcast_ip, subrec->myip, DGRAM_PORT); } @@ -91,33 +91,33 @@ static void send_announcement(struct subnet_record *subrec, int announce_type, time_t announce_interval, const char *server_name, int server_type, const char *server_comment) { - pstring outbuf; - char *p; + pstring outbuf; + char *p; - memset(outbuf,'\0',sizeof(outbuf)); - p = outbuf+1; + memset(outbuf,'\0',sizeof(outbuf)); + p = outbuf+1; - SCVAL(outbuf,0,announce_type); + SCVAL(outbuf,0,announce_type); - /* Announcement parameters. */ - SCVAL(p,0,updatecount); - SIVAL(p,1,announce_interval*1000); /* Milliseconds - despite the spec. */ + /* Announcement parameters. */ + SCVAL(p,0,updatecount); + SIVAL(p,1,announce_interval*1000); /* Milliseconds - despite the spec. */ - push_string(NULL, p+5, server_name, 15, STR_ASCII|STR_UPPER|STR_TERMINATE); + push_string(NULL, p+5, server_name, 15, STR_ASCII|STR_UPPER|STR_TERMINATE); - SCVAL(p,21,lp_major_announce_version()); /* Major version. */ - SCVAL(p,22,lp_minor_announce_version()); /* Minor version. */ + SCVAL(p,21,lp_major_announce_version()); /* Major version. */ + SCVAL(p,22,lp_minor_announce_version()); /* Minor version. */ - SIVAL(p,23,server_type & ~SV_TYPE_LOCAL_LIST_ONLY); - /* Browse version: got from NT/AS 4.00 - Value defined in smb.h (JHT). */ - SSVAL(p,27,BROWSER_ELECTION_VERSION); - SSVAL(p,29,BROWSER_CONSTANT); /* Browse signature. */ + SIVAL(p,23,server_type & ~SV_TYPE_LOCAL_LIST_ONLY); + /* Browse version: got from NT/AS 4.00 - Value defined in smb.h (JHT). */ + SSVAL(p,27,BROWSER_ELECTION_VERSION); + SSVAL(p,29,BROWSER_CONSTANT); /* Browse signature. */ - p += 31 + push_string(NULL, p+31, server_comment, -1, STR_ASCII|STR_TERMINATE); + p += 31 + push_string(NULL, p+31, server_comment, -1, STR_ASCII|STR_TERMINATE); - send_mailslot(False,BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf), - from_name, 0x0, to_name, to_type, to_ip, subrec->myip, - DGRAM_PORT); + send_mailslot(False,BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf), + from_name, 0x0, to_name, to_type, to_ip, subrec->myip, + DGRAM_PORT); } /**************************************************************************** @@ -129,28 +129,23 @@ static void send_lm_announcement(struct subnet_record *subrec, int announce_type time_t announce_interval, char *server_name, int server_type, char *server_comment) { - pstring outbuf; - char *p=outbuf; - - memset(outbuf,'\0',sizeof(outbuf)); - - SSVAL(p,0,announce_type); - SIVAL(p,2,server_type & ~SV_TYPE_LOCAL_LIST_ONLY); - SCVAL(p,6,lp_major_announce_version()); /* Major version. */ - SCVAL(p,7,lp_minor_announce_version()); /* Minor version. */ - SSVAL(p,8,announce_interval); /* In seconds - according to spec. */ - - p += 10; - /*StrnCpy(p,server_name,15); - strupper_m(p); - p = skip_string(p,1); - pstrcpy(p,server_comment); - p = skip_string(p,1);*/ - p += push_string(NULL, p, server_name, 15, STR_ASCII|STR_UPPER|STR_TERMINATE); - p += push_string(NULL, p, server_comment, sizeof(pstring)-15, STR_ASCII|STR_UPPER|STR_TERMINATE); - - send_mailslot(False,LANMAN_MAILSLOT, outbuf, PTR_DIFF(p,outbuf), - from_name, 0x0, to_name, to_type, to_ip, subrec->myip, + pstring outbuf; + char *p=outbuf; + + memset(outbuf,'\0',sizeof(outbuf)); + + SSVAL(p,0,announce_type); + SIVAL(p,2,server_type & ~SV_TYPE_LOCAL_LIST_ONLY); + SCVAL(p,6,lp_major_announce_version()); /* Major version. */ + SCVAL(p,7,lp_minor_announce_version()); /* Minor version. */ + SSVAL(p,8,announce_interval); /* In seconds - according to spec. */ + + p += 10; + p += push_string(NULL, p, server_name, 15, STR_ASCII|STR_UPPER|STR_TERMINATE); + p += push_string(NULL, p, server_comment, sizeof(pstring)-15, STR_ASCII|STR_UPPER|STR_TERMINATE); + + send_mailslot(False,LANMAN_MAILSLOT, outbuf, PTR_DIFF(p,outbuf), + from_name, 0x0, to_name, to_type, to_ip, subrec->myip, DGRAM_PORT); } @@ -161,20 +156,20 @@ static void send_lm_announcement(struct subnet_record *subrec, int announce_type static void send_local_master_announcement(struct subnet_record *subrec, struct work_record *work, struct server_record *servrec) { - /* Ensure we don't have the prohibited bit set. */ - uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY; - - DEBUG(3,("send_local_master_announcement: type %x for name %s on subnet %s for workgroup %s\n", - type, global_myname(), subrec->subnet_name, work->work_group)); - - send_announcement(subrec, ANN_LocalMasterAnnouncement, - global_myname(), /* From nbt name. */ - work->work_group, 0x1e, /* To nbt name. */ - subrec->bcast_ip, /* To ip. */ - work->announce_interval, /* Time until next announce. */ - global_myname(), /* Name to announce. */ - type, /* Type field. */ - servrec->serv.comment); + /* Ensure we don't have the prohibited bit set. */ + uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY; + + DEBUG(3,("send_local_master_announcement: type %x for name %s on subnet %s for workgroup %s\n", + type, global_myname(), subrec->subnet_name, work->work_group)); + + send_announcement(subrec, ANN_LocalMasterAnnouncement, + global_myname(), /* From nbt name. */ + work->work_group, 0x1e, /* To nbt name. */ + subrec->bcast_ip, /* To ip. */ + work->announce_interval, /* Time until next announce. */ + global_myname(), /* Name to announce. */ + type, /* Type field. */ + servrec->serv.comment); } /**************************************************************************** @@ -183,17 +178,17 @@ static void send_local_master_announcement(struct subnet_record *subrec, struct static void send_workgroup_announcement(struct subnet_record *subrec, struct work_record *work) { - DEBUG(3,("send_workgroup_announcement: on subnet %s for workgroup %s\n", - subrec->subnet_name, work->work_group)); - - send_announcement(subrec, ANN_DomainAnnouncement, - global_myname(), /* From nbt name. */ - MSBROWSE, 0x1, /* To nbt name. */ - subrec->bcast_ip, /* To ip. */ - work->announce_interval, /* Time until next announce. */ - work->work_group, /* Name to announce. */ - SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT, /* workgroup announce flags. */ - global_myname()); /* From name as comment. */ + DEBUG(3,("send_workgroup_announcement: on subnet %s for workgroup %s\n", + subrec->subnet_name, work->work_group)); + + send_announcement(subrec, ANN_DomainAnnouncement, + global_myname(), /* From nbt name. */ + MSBROWSE, 0x1, /* To nbt name. */ + subrec->bcast_ip, /* To ip. */ + work->announce_interval, /* Time until next announce. */ + work->work_group, /* Name to announce. */ + SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT, /* workgroup announce flags. */ + global_myname()); /* From name as comment. */ } /**************************************************************************** @@ -203,20 +198,20 @@ static void send_workgroup_announcement(struct subnet_record *subrec, struct wor static void send_host_announcement(struct subnet_record *subrec, struct work_record *work, struct server_record *servrec) { - /* Ensure we don't have the prohibited bits set. */ - uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY; - - DEBUG(3,("send_host_announcement: type %x for host %s on subnet %s for workgroup %s\n", - type, servrec->serv.name, subrec->subnet_name, work->work_group)); - - send_announcement(subrec, ANN_HostAnnouncement, - servrec->serv.name, /* From nbt name. */ - work->work_group, 0x1d, /* To nbt name. */ - subrec->bcast_ip, /* To ip. */ - work->announce_interval, /* Time until next announce. */ - servrec->serv.name, /* Name to announce. */ - type, /* Type field. */ - servrec->serv.comment); + /* Ensure we don't have the prohibited bits set. */ + uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY; + + DEBUG(3,("send_host_announcement: type %x for host %s on subnet %s for workgroup %s\n", + type, servrec->serv.name, subrec->subnet_name, work->work_group)); + + send_announcement(subrec, ANN_HostAnnouncement, + servrec->serv.name, /* From nbt name. */ + work->work_group, 0x1d, /* To nbt name. */ + subrec->bcast_ip, /* To ip. */ + work->announce_interval, /* Time until next announce. */ + servrec->serv.name, /* Name to announce. */ + type, /* Type field. */ + servrec->serv.comment); } /**************************************************************************** @@ -226,20 +221,20 @@ static void send_host_announcement(struct subnet_record *subrec, struct work_rec static void send_lm_host_announcement(struct subnet_record *subrec, struct work_record *work, struct server_record *servrec, int lm_interval) { - /* Ensure we don't have the prohibited bits set. */ - uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY; - - DEBUG(3,("send_lm_host_announcement: type %x for host %s on subnet %s for workgroup %s, ttl: %d\n", - type, servrec->serv.name, subrec->subnet_name, work->work_group, lm_interval)); - - send_lm_announcement(subrec, ANN_HostAnnouncement, - servrec->serv.name, /* From nbt name. */ - work->work_group, 0x00, /* To nbt name. */ - subrec->bcast_ip, /* To ip. */ - lm_interval, /* Time until next announce. */ - servrec->serv.name, /* Name to announce. */ - type, /* Type field. */ - servrec->serv.comment); + /* Ensure we don't have the prohibited bits set. */ + uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY; + + DEBUG(3,("send_lm_host_announcement: type %x for host %s on subnet %s for workgroup %s, ttl: %d\n", + type, servrec->serv.name, subrec->subnet_name, work->work_group, lm_interval)); + + send_lm_announcement(subrec, ANN_HostAnnouncement, + servrec->serv.name, /* From nbt name. */ + work->work_group, 0x00, /* To nbt name. */ + subrec->bcast_ip, /* To ip. */ + lm_interval, /* Time until next announce. */ + servrec->serv.name, /* Name to announce (fstring not netbios name struct). */ + type, /* Type field. */ + servrec->serv.comment); } /**************************************************************************** @@ -249,18 +244,15 @@ static void send_lm_host_announcement(struct subnet_record *subrec, struct work_ static void announce_server(struct subnet_record *subrec, struct work_record *work, struct server_record *servrec) { - /* Only do domain announcements if we are a master and it's - our primary name we're being asked to announce. */ - - if (AM_LOCAL_MASTER_BROWSER(work) && strequal(global_myname(),servrec->serv.name)) - { - send_local_master_announcement(subrec, work, servrec); - send_workgroup_announcement(subrec, work); - } - else - { - send_host_announcement(subrec, work, servrec); - } + /* Only do domain announcements if we are a master and it's + our primary name we're being asked to announce. */ + + if (AM_LOCAL_MASTER_BROWSER(work) && strequal(global_myname(),servrec->serv.name)) { + send_local_master_announcement(subrec, work, servrec); + send_workgroup_announcement(subrec, work); + } else { + send_host_announcement(subrec, work, servrec); + } } /**************************************************************************** @@ -270,43 +262,39 @@ static void announce_server(struct subnet_record *subrec, struct work_record *wo void announce_my_server_names(time_t t) { - struct subnet_record *subrec; - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup()); - - if(work) - { - struct server_record *servrec; - - if (work->needannounce) - { - /* Drop back to a max 3 minute announce. This is to prevent a - single lost packet from breaking things for too long. */ - - work->announce_interval = MIN(work->announce_interval, - CHECK_TIME_MIN_HOST_ANNCE*60); - work->lastannounce_time = t - (work->announce_interval+1); - work->needannounce = False; - } - - /* Announce every minute at first then progress to every 12 mins */ - if ((t - work->lastannounce_time) < work->announce_interval) - continue; - - if (work->announce_interval < (CHECK_TIME_MAX_HOST_ANNCE * 60)) - work->announce_interval += 60; - - work->lastannounce_time = t; - - for (servrec = work->serverlist; servrec; servrec = servrec->next) - { - if (is_myname(servrec->serv.name)) - announce_server(subrec, work, servrec); - } - } /* if work */ - } /* for subrec */ + struct subnet_record *subrec; + + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup()); + + if(work) { + struct server_record *servrec; + + if (work->needannounce) { + /* Drop back to a max 3 minute announce. This is to prevent a + single lost packet from breaking things for too long. */ + + work->announce_interval = MIN(work->announce_interval, + CHECK_TIME_MIN_HOST_ANNCE*60); + work->lastannounce_time = t - (work->announce_interval+1); + work->needannounce = False; + } + + /* Announce every minute at first then progress to every 12 mins */ + if ((t - work->lastannounce_time) < work->announce_interval) + continue; + + if (work->announce_interval < (CHECK_TIME_MAX_HOST_ANNCE * 60)) + work->announce_interval += 60; + + work->lastannounce_time = t; + + for (servrec = work->serverlist; servrec; servrec = servrec->next) { + if (is_myname(servrec->serv.name)) + announce_server(subrec, work, servrec); + } + } /* if work */ + } /* for subrec */ } /**************************************************************************** @@ -316,47 +304,42 @@ void announce_my_server_names(time_t t) void announce_my_lm_server_names(time_t t) { - struct subnet_record *subrec; - static time_t last_lm_announce_time=0; - int announce_interval = lp_lm_interval(); - int lm_announce = lp_lm_announce(); - - if ((announce_interval <= 0) || (lm_announce <= 0)) - { - /* user absolutely does not want LM announcements to be sent. */ - return; - } - - if ((lm_announce >= 2) && (!found_lm_clients)) - { - /* has been set to 2 (Auto) but no LM clients detected (yet). */ - return; - } - - /* Otherwise: must have been set to 1 (Yes), or LM clients *have* - been detected. */ - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup()); - - if(work) - { - struct server_record *servrec; - - if (last_lm_announce_time && ((t - last_lm_announce_time) < announce_interval )) - continue; - - last_lm_announce_time = t; - - for (servrec = work->serverlist; servrec; servrec = servrec->next) - { - if (is_myname(servrec->serv.name)) - /* skipping equivalent of announce_server() */ - send_lm_host_announcement(subrec, work, servrec, announce_interval); - } - } /* if work */ - } /* for subrec */ + struct subnet_record *subrec; + static time_t last_lm_announce_time=0; + int announce_interval = lp_lm_interval(); + int lm_announce = lp_lm_announce(); + + if ((announce_interval <= 0) || (lm_announce <= 0)) { + /* user absolutely does not want LM announcements to be sent. */ + return; + } + + if ((lm_announce >= 2) && (!found_lm_clients)) { + /* has been set to 2 (Auto) but no LM clients detected (yet). */ + return; + } + + /* Otherwise: must have been set to 1 (Yes), or LM clients *have* + been detected. */ + + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup()); + + if(work) { + struct server_record *servrec; + + if (last_lm_announce_time && ((t - last_lm_announce_time) < announce_interval )) + continue; + + last_lm_announce_time = t; + + for (servrec = work->serverlist; servrec; servrec = servrec->next) { + if (is_myname(servrec->serv.name)) + /* skipping equivalent of announce_server() */ + send_lm_host_announcement(subrec, work, servrec, announce_interval); + } + } /* if work */ + } /* for subrec */ } /* Announce timer. Moved into global static so it can be reset @@ -370,7 +353,7 @@ static time_t announce_timer_last=0; void reset_announce_timer(void) { - announce_timer_last = time(NULL) - (CHECK_TIME_MST_ANNOUNCE * 60); + announce_timer_last = time(NULL) - (CHECK_TIME_MST_ANNOUNCE * 60); } /**************************************************************************** @@ -379,45 +362,40 @@ void reset_announce_timer(void) void announce_myself_to_domain_master_browser(time_t t) { - struct subnet_record *subrec; - struct work_record *work; - - if(!we_are_a_wins_client()) - { - DEBUG(10,("announce_myself_to_domain_master_browser: no unicast subnet, ignoring.\n")); - return; - } - - if (!announce_timer_last) - announce_timer_last = t; - - if ((t-announce_timer_last) < (CHECK_TIME_MST_ANNOUNCE * 60)) - { - DEBUG(10,("announce_myself_to_domain_master_browser: t (%d) - last(%d) < %d\n", - (int)t, (int)announce_timer_last, - CHECK_TIME_MST_ANNOUNCE * 60 )); - return; - } - - announce_timer_last = t; - - /* Look over all our broadcast subnets to see if any of them - has the state set as local master browser. */ - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - for (work = subrec->workgrouplist; work; work = work->next) - { - if (AM_LOCAL_MASTER_BROWSER(work)) - { - DEBUG(4,( "announce_myself_to_domain_master_browser: I am a local master browser for \ + struct subnet_record *subrec; + struct work_record *work; + + if(!we_are_a_wins_client()) { + DEBUG(10,("announce_myself_to_domain_master_browser: no unicast subnet, ignoring.\n")); + return; + } + + if (!announce_timer_last) + announce_timer_last = t; + + if ((t-announce_timer_last) < (CHECK_TIME_MST_ANNOUNCE * 60)) { + DEBUG(10,("announce_myself_to_domain_master_browser: t (%d) - last(%d) < %d\n", + (int)t, (int)announce_timer_last, + CHECK_TIME_MST_ANNOUNCE * 60 )); + return; + } + + announce_timer_last = t; + + /* Look over all our broadcast subnets to see if any of them + has the state set as local master browser. */ + + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + for (work = subrec->workgrouplist; work; work = work->next) { + if (AM_LOCAL_MASTER_BROWSER(work)) { + DEBUG(4,( "announce_myself_to_domain_master_browser: I am a local master browser for \ workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name)); - /* Look in nmbd_browsersync.c for the rest of this code. */ - announce_and_sync_with_domain_master_browser(subrec, work); - } - } - } + /* Look in nmbd_browsersync.c for the rest of this code. */ + announce_and_sync_with_domain_master_browser(subrec, work); + } + } + } } /**************************************************************************** @@ -427,49 +405,43 @@ This must *only* be called on shutdown. void announce_my_servers_removed(void) { - int announce_interval = lp_lm_interval(); - int lm_announce = lp_lm_announce(); - struct subnet_record *subrec; - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - struct work_record *work; - for (work = subrec->workgrouplist; work; work = work->next) - { - struct server_record *servrec; - - work->announce_interval = 0; - for (servrec = work->serverlist; servrec; servrec = servrec->next) - { - if (!is_myname(servrec->serv.name)) - continue; - servrec->serv.type = 0; - if(AM_LOCAL_MASTER_BROWSER(work)) - send_local_master_announcement(subrec, work, servrec); - send_host_announcement(subrec, work, servrec); - - - if ((announce_interval <= 0) || (lm_announce <= 0)) - { - /* user absolutely does not want LM announcements to be sent. */ - continue; - } - - if ((lm_announce >= 2) && (!found_lm_clients)) - { - /* has been set to 2 (Auto) but no LM clients detected (yet). */ - continue; - } - - /* - * lm announce was set or we have seen lm announcements, so do - * a lm announcement of host removed. - */ - - send_lm_host_announcement(subrec, work, servrec, 0); - } - } - } + int announce_interval = lp_lm_interval(); + int lm_announce = lp_lm_announce(); + struct subnet_record *subrec; + + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + struct work_record *work; + for (work = subrec->workgrouplist; work; work = work->next) { + struct server_record *servrec; + + work->announce_interval = 0; + for (servrec = work->serverlist; servrec; servrec = servrec->next) { + if (!is_myname(servrec->serv.name)) + continue; + servrec->serv.type = 0; + if(AM_LOCAL_MASTER_BROWSER(work)) + send_local_master_announcement(subrec, work, servrec); + send_host_announcement(subrec, work, servrec); + + if ((announce_interval <= 0) || (lm_announce <= 0)) { + /* user absolutely does not want LM announcements to be sent. */ + continue; + } + + if ((lm_announce >= 2) && (!found_lm_clients)) { + /* has been set to 2 (Auto) but no LM clients detected (yet). */ + continue; + } + + /* + * lm announce was set or we have seen lm announcements, so do + * a lm announcement of host removed. + */ + + send_lm_host_announcement(subrec, work, servrec, 0); + } + } + } } /**************************************************************************** @@ -480,132 +452,127 @@ void announce_my_servers_removed(void) void announce_remote(time_t t) { - char *s; - const char *ptr; - static time_t last_time = 0; - pstring s2; - struct in_addr addr; - char *comment; - int stype = lp_default_server_announce(); - - if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL))) - return; - - last_time = t; - - s = lp_remote_announce(); - if (!*s) - return; - - comment = string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH); - - for (ptr=s; next_token(&ptr,s2,NULL,sizeof(s2)); ) - { - /* The entries are of the form a.b.c.d/WORKGROUP with - WORKGROUP being optional */ - const char *wgroup; - char *pwgroup; - int i; - - pwgroup = strchr_m(s2,'/'); - if (pwgroup) - *pwgroup++ = 0; - if (!pwgroup || !*pwgroup) - wgroup = lp_workgroup(); - else - wgroup = pwgroup; - - addr = *interpret_addr2(s2); + char *s; + const char *ptr; + static time_t last_time = 0; + pstring s2; + struct in_addr addr; + char *comment; + int stype = lp_default_server_announce(); + + if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL))) + return; + + last_time = t; + + s = lp_remote_announce(); + if (!*s) + return; + + comment = string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH); + + for (ptr=s; next_token(&ptr,s2,NULL,sizeof(s2)); ) { + /* The entries are of the form a.b.c.d/WORKGROUP with + WORKGROUP being optional */ + const char *wgroup; + char *pwgroup; + int i; + + pwgroup = strchr_m(s2,'/'); + if (pwgroup) + *pwgroup++ = 0; + if (!pwgroup || !*pwgroup) + wgroup = lp_workgroup(); + else + wgroup = pwgroup; + + addr = *interpret_addr2(s2); - /* Announce all our names including aliases */ - /* Give the ip address as the address of our first - broadcast subnet. */ - - for(i=0; my_netbios_names(i); i++) - { - const char *name = my_netbios_names(i); - - DEBUG(5,("announce_remote: Doing remote announce for server %s to IP %s.\n", - name, inet_ntoa(addr) )); - - send_announcement(FIRST_SUBNET, ANN_HostAnnouncement, - name, /* From nbt name. */ - wgroup, 0x1d, /* To nbt name. */ - addr, /* To ip. */ - REMOTE_ANNOUNCE_INTERVAL, /* Time until next announce. */ - name, /* Name to announce. */ - stype, /* Type field. */ - comment); - } - } + /* Announce all our names including aliases */ + /* Give the ip address as the address of our first + broadcast subnet. */ + + for(i=0; my_netbios_names(i); i++) { + const char *name = my_netbios_names(i); + + DEBUG(5,("announce_remote: Doing remote announce for server %s to IP %s.\n", + name, inet_ntoa(addr) )); + + send_announcement(FIRST_SUBNET, ANN_HostAnnouncement, + name, /* From nbt name. */ + wgroup, 0x1d, /* To nbt name. */ + addr, /* To ip. */ + REMOTE_ANNOUNCE_INTERVAL, /* Time until next announce. */ + name, /* Name to announce. */ + stype, /* Type field. */ + comment); + } + } } /**************************************************************************** Implement the 'remote browse sync' feature Andrew added. These are used to put our browse lists into remote browse lists. - **************************************************************************/ +**************************************************************************/ void browse_sync_remote(time_t t) { - char *s; - const char *ptr; - static time_t last_time = 0; - pstring s2; - struct in_addr addr; - struct work_record *work; - pstring outbuf; - char *p; - fstring myname; + char *s; + const char *ptr; + static time_t last_time = 0; + pstring s2; + struct in_addr addr; + struct work_record *work; + pstring outbuf; + char *p; + fstring myname; - if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL))) - return; + if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL))) + return; - last_time = t; - - s = lp_remote_browse_sync(); - if (!*s) - return; - - /* - * We only do this if we are the local master browser - * for our workgroup on the firsst subnet. - */ - - if((work = find_workgroup_on_subnet(FIRST_SUBNET, lp_workgroup())) == NULL) - { - DEBUG(0,("browse_sync_remote: Cannot find workgroup %s on subnet %s\n", - lp_workgroup(), FIRST_SUBNET->subnet_name )); - return; - } + last_time = t; + + s = lp_remote_browse_sync(); + if (!*s) + return; + + /* + * We only do this if we are the local master browser + * for our workgroup on the firsst subnet. + */ + + if((work = find_workgroup_on_subnet(FIRST_SUBNET, lp_workgroup())) == NULL) { + DEBUG(0,("browse_sync_remote: Cannot find workgroup %s on subnet %s\n", + lp_workgroup(), FIRST_SUBNET->subnet_name )); + return; + } - if(!AM_LOCAL_MASTER_BROWSER(work)) - { - DEBUG(5,("browse_sync_remote: We can only do this if we are a local master browser \ + if(!AM_LOCAL_MASTER_BROWSER(work)) { + DEBUG(5,("browse_sync_remote: We can only do this if we are a local master browser \ for workgroup %s on subnet %s.\n", lp_workgroup(), FIRST_SUBNET->subnet_name )); - return; - } + return; + } - memset(outbuf,'\0',sizeof(outbuf)); - p = outbuf; - SCVAL(p,0,ANN_MasterAnnouncement); - p++; + memset(outbuf,'\0',sizeof(outbuf)); + p = outbuf; + SCVAL(p,0,ANN_MasterAnnouncement); + p++; - fstrcpy(myname, global_myname()); - strupper_m(myname); - myname[15]='\0'; - push_pstring_base(p, myname, outbuf); + fstrcpy(myname, global_myname()); + strupper_m(myname); + myname[15]='\0'; + push_pstring_base(p, myname, outbuf); - p = skip_string(p,1); + p = skip_string(p,1); - for (ptr=s; next_token(&ptr,s2,NULL,sizeof(s2)); ) - { - /* The entries are of the form a.b.c.d */ - addr = *interpret_addr2(s2); + for (ptr=s; next_token(&ptr,s2,NULL,sizeof(s2)); ) { + /* The entries are of the form a.b.c.d */ + addr = *interpret_addr2(s2); - DEBUG(5,("announce_remote: Doing remote browse sync announce for server %s to IP %s.\n", - global_myname(), inet_ntoa(addr) )); + DEBUG(5,("announce_remote: Doing remote browse sync announce for server %s to IP %s.\n", + global_myname(), inet_ntoa(addr) )); - send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf), - global_myname(), 0x0, "*", 0x0, addr, FIRST_SUBNET->myip, DGRAM_PORT); - } + send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf), + global_myname(), 0x0, "*", 0x0, addr, FIRST_SUBNET->myip, DGRAM_PORT); + } } diff --git a/source/nmbd/nmbd_serverlistdb.c b/source/nmbd/nmbd_serverlistdb.c index 2484a7f830b..b4c6e2902de 100644 --- a/source/nmbd/nmbd_serverlistdb.c +++ b/source/nmbd/nmbd_serverlistdb.c @@ -33,28 +33,26 @@ int updatecount = 0; void remove_all_servers(struct work_record *work) { - struct server_record *servrec; - struct server_record *nexts; + struct server_record *servrec; + struct server_record *nexts; - for (servrec = work->serverlist; servrec; servrec = nexts) - { - DEBUG(7,("remove_all_servers: Removing server %s\n",servrec->serv.name)); - nexts = servrec->next; + for (servrec = work->serverlist; servrec; servrec = nexts) { + DEBUG(7,("remove_all_servers: Removing server %s\n",servrec->serv.name)); + nexts = servrec->next; - if (servrec->prev) - servrec->prev->next = servrec->next; - if (servrec->next) - servrec->next->prev = servrec->prev; + if (servrec->prev) + servrec->prev->next = servrec->next; + if (servrec->next) + servrec->next->prev = servrec->prev; - if (work->serverlist == servrec) - work->serverlist = servrec->next; + if (work->serverlist == servrec) + work->serverlist = servrec->next; - ZERO_STRUCTP(servrec); - SAFE_FREE(servrec); + ZERO_STRUCTP(servrec); + SAFE_FREE(servrec); + } - } - - work->subnet->work_changed = True; + work->subnet->work_changed = True; } /*************************************************************************** @@ -64,23 +62,22 @@ void remove_all_servers(struct work_record *work) static void add_server_to_workgroup(struct work_record *work, struct server_record *servrec) { - struct server_record *servrec2; - - if (!work->serverlist) - { - work->serverlist = servrec; - servrec->prev = NULL; - servrec->next = NULL; - return; - } - - for (servrec2 = work->serverlist; servrec2->next; servrec2 = servrec2->next) - ; - - servrec2->next = servrec; - servrec->next = NULL; - servrec->prev = servrec2; - work->subnet->work_changed = True; + struct server_record *servrec2; + + if (!work->serverlist) { + work->serverlist = servrec; + servrec->prev = NULL; + servrec->next = NULL; + return; + } + + for (servrec2 = work->serverlist; servrec2->next; servrec2 = servrec2->next) + ; + + servrec2->next = servrec; + servrec->next = NULL; + servrec->prev = servrec2; + work->subnet->work_changed = True; } /**************************************************************************** @@ -89,14 +86,13 @@ static void add_server_to_workgroup(struct work_record *work, struct server_record *find_server_in_workgroup(struct work_record *work, const char *name) { - struct server_record *ret; + struct server_record *ret; - for (ret = work->serverlist; ret; ret = ret->next) - { - if (strequal(ret->serv.name,name)) - return ret; - } - return NULL; + for (ret = work->serverlist; ret; ret = ret->next) { + if (strequal(ret->serv.name,name)) + return ret; + } + return NULL; } @@ -106,17 +102,17 @@ struct server_record *find_server_in_workgroup(struct work_record *work, const c void remove_server_from_workgroup(struct work_record *work, struct server_record *servrec) { - if (servrec->prev) - servrec->prev->next = servrec->next; - if (servrec->next) - servrec->next->prev = servrec->prev; + if (servrec->prev) + servrec->prev->next = servrec->next; + if (servrec->next) + servrec->next->prev = servrec->prev; - if (work->serverlist == servrec) - work->serverlist = servrec->next; + if (work->serverlist == servrec) + work->serverlist = servrec->next; - ZERO_STRUCTP(servrec); - SAFE_FREE(servrec); - work->subnet->work_changed = True; + ZERO_STRUCTP(servrec); + SAFE_FREE(servrec); + work->subnet->work_changed = True; } /**************************************************************************** @@ -127,47 +123,44 @@ struct server_record *create_server_on_workgroup(struct work_record *work, const char *name,int servertype, int ttl, const char *comment) { - struct server_record *servrec; + struct server_record *servrec; - if (name[0] == '*') - { - DEBUG(7,("create_server_on_workgroup: not adding name starting with '*' (%s)\n", - name)); - return (NULL); - } + if (name[0] == '*') { + DEBUG(7,("create_server_on_workgroup: not adding name starting with '*' (%s)\n", + name)); + return (NULL); + } - if((servrec = find_server_in_workgroup(work, name)) != NULL) - { - DEBUG(0,("create_server_on_workgroup: Server %s already exists on \ + if((servrec = find_server_in_workgroup(work, name)) != NULL) { + DEBUG(0,("create_server_on_workgroup: Server %s already exists on \ workgroup %s. This is a bug.\n", name, work->work_group)); - return NULL; - } + return NULL; + } - if((servrec = (struct server_record *)malloc(sizeof(*servrec))) == NULL) - { - DEBUG(0,("create_server_entry_on_workgroup: malloc fail !\n")); - return NULL; - } + if((servrec = (struct server_record *)malloc(sizeof(*servrec))) == NULL) { + DEBUG(0,("create_server_entry_on_workgroup: malloc fail !\n")); + return NULL; + } - memset((char *)servrec,'\0',sizeof(*servrec)); + memset((char *)servrec,'\0',sizeof(*servrec)); - servrec->subnet = work->subnet; + servrec->subnet = work->subnet; - fstrcpy(servrec->serv.name,name); - fstrcpy(servrec->serv.comment,comment); - strupper_m(servrec->serv.name); - servrec->serv.type = servertype; + fstrcpy(servrec->serv.name,name); + fstrcpy(servrec->serv.comment,comment); + strupper_m(servrec->serv.name); + servrec->serv.type = servertype; - update_server_ttl(servrec, ttl); + update_server_ttl(servrec, ttl); - add_server_to_workgroup(work, servrec); + add_server_to_workgroup(work, servrec); - DEBUG(3,("create_server_on_workgroup: Created server entry %s of type %x (%s) on \ + DEBUG(3,("create_server_on_workgroup: Created server entry %s of type %x (%s) on \ workgroup %s.\n", name,servertype,comment, work->work_group)); - work->subnet->work_changed = True; + work->subnet->work_changed = True; - return(servrec); + return(servrec); } /******************************************************************* @@ -176,15 +169,15 @@ workgroup %s.\n", name,servertype,comment, work->work_group)); void update_server_ttl(struct server_record *servrec, int ttl) { - if(ttl > lp_max_ttl()) - ttl = lp_max_ttl(); + if(ttl > lp_max_ttl()) + ttl = lp_max_ttl(); - if(is_myname(servrec->serv.name)) - servrec->death_time = PERMANENT_TTL; - else - servrec->death_time = (ttl != PERMANENT_TTL) ? time(NULL)+(ttl*3) : PERMANENT_TTL; + if(is_myname(servrec->serv.name)) + servrec->death_time = PERMANENT_TTL; + else + servrec->death_time = (ttl != PERMANENT_TTL) ? time(NULL)+(ttl*3) : PERMANENT_TTL; - servrec->subnet->work_changed = True; + servrec->subnet->work_changed = True; } /******************************************************************* @@ -195,20 +188,18 @@ void update_server_ttl(struct server_record *servrec, int ttl) void expire_servers(struct work_record *work, time_t t) { - struct server_record *servrec; - struct server_record *nexts; + struct server_record *servrec; + struct server_record *nexts; - for (servrec = work->serverlist; servrec; servrec = nexts) - { - nexts = servrec->next; - - if ((servrec->death_time != PERMANENT_TTL) && ((t == -1) || (servrec->death_time < t))) - { - DEBUG(3,("expire_old_servers: Removing timed out server %s\n",servrec->serv.name)); - remove_server_from_workgroup(work, servrec); - work->subnet->work_changed = True; - } - } + for (servrec = work->serverlist; servrec; servrec = nexts) { + nexts = servrec->next; + + if ((servrec->death_time != PERMANENT_TTL) && ((t == -1) || (servrec->death_time < t))) { + DEBUG(3,("expire_old_servers: Removing timed out server %s\n",servrec->serv.name)); + remove_server_from_workgroup(work, servrec); + work->subnet->work_changed = True; + } + } } /******************************************************************* @@ -221,33 +212,30 @@ static uint32 write_this_server_name( struct subnet_record *subrec, struct work_record *work, struct server_record *servrec) { - struct subnet_record *ssub; - struct work_record *iwork; - - /* Go through all the subnets we have already seen. */ - for (ssub = FIRST_SUBNET; ssub != subrec; ssub = NEXT_SUBNET_INCLUDING_UNICAST(ssub)) - { - for(iwork = ssub->workgrouplist; iwork; iwork = iwork->next) - { - if(find_server_in_workgroup( iwork, servrec->serv.name) != NULL) - { - /* - * We have already written out this server record, don't - * do it again. This gives precedence to servers we have seen - * on the broadcast subnets over servers that may have been - * added via a sync on the unicast_subet. - * - * The correct way to do this is to have a serverlist file - * per subnet - this means changes to smbd as well. I may - * add this at a later date (JRA). - */ - - return 0; - } - } - } - - return servrec->serv.type; + struct subnet_record *ssub; + struct work_record *iwork; + + /* Go through all the subnets we have already seen. */ + for (ssub = FIRST_SUBNET; ssub != subrec; ssub = NEXT_SUBNET_INCLUDING_UNICAST(ssub)) { + for(iwork = ssub->workgrouplist; iwork; iwork = iwork->next) { + if(find_server_in_workgroup( iwork, servrec->serv.name) != NULL) { + /* + * We have already written out this server record, don't + * do it again. This gives precedence to servers we have seen + * on the broadcast subnets over servers that may have been + * added via a sync on the unicast_subet. + * + * The correct way to do this is to have a serverlist file + * per subnet - this means changes to smbd as well. I may + * add this at a later date (JRA). + */ + + return 0; + } + } + } + + return servrec->serv.type; } /******************************************************************* @@ -261,30 +249,29 @@ static uint32 write_this_server_name( struct subnet_record *subrec, static uint32 write_this_workgroup_name( struct subnet_record *subrec, struct work_record *work) { - struct subnet_record *ssub; + struct subnet_record *ssub; - if(strequal(lp_workgroup(), work->work_group)) - return 0; + if(strequal(lp_workgroup(), work->work_group)) + return 0; - /* This is a workgroup we have seen on a broadcast subnet. All - these have the same type. */ + /* This is a workgroup we have seen on a broadcast subnet. All + these have the same type. */ - if(subrec != unicast_subnet) - return (SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT|SV_TYPE_LOCAL_LIST_ONLY); + if(subrec != unicast_subnet) + return (SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT|SV_TYPE_LOCAL_LIST_ONLY); - for(ssub = FIRST_SUBNET; ssub; ssub = NEXT_SUBNET_EXCLUDING_UNICAST(ssub)) - { - /* This is the unicast subnet so check if we've already written out - this subnet when we passed over the broadcast subnets. */ + for(ssub = FIRST_SUBNET; ssub; ssub = NEXT_SUBNET_EXCLUDING_UNICAST(ssub)) { + /* This is the unicast subnet so check if we've already written out + this subnet when we passed over the broadcast subnets. */ - if(find_workgroup_on_subnet( ssub, work->work_group) != NULL) - return 0; - } + if(find_workgroup_on_subnet( ssub, work->work_group) != NULL) + return 0; + } - /* All workgroups on the unicast subnet (except our own, which we - have already written out) cannot be local. */ + /* All workgroups on the unicast subnet (except our own, which we + have already written out) cannot be local. */ - return (SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT); + return (SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT); } /******************************************************************* @@ -306,143 +293,130 @@ void write_browse_list_entry(XFILE *fp, const char *name, uint32 rec_type, void write_browse_list(time_t t, BOOL force_write) { - struct subnet_record *subrec; - struct work_record *work; - struct server_record *servrec; - pstring fname,fnamenew; - uint32 stype; - int i; - XFILE *fp; - BOOL list_changed = force_write; - static time_t lasttime = 0; + struct subnet_record *subrec; + struct work_record *work; + struct server_record *servrec; + pstring fname,fnamenew; + uint32 stype; + int i; + XFILE *fp; + BOOL list_changed = force_write; + static time_t lasttime = 0; - /* Always dump if we're being told to by a signal. */ - if(force_write == False) - { - if (!lasttime) - lasttime = t; - if (t - lasttime < 5) - return; - } - - lasttime = t; - - dump_workgroups(force_write); + /* Always dump if we're being told to by a signal. */ + if(force_write == False) { + if (!lasttime) + lasttime = t; + if (t - lasttime < 5) + return; + } + + lasttime = t; + + dump_workgroups(force_write); - for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - if(subrec->work_changed) - { - list_changed = True; - break; - } - } - - if(!list_changed) - return; - - updatecount++; + for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) { + if(subrec->work_changed) { + list_changed = True; + break; + } + } + + if(!list_changed) + return; + + updatecount++; - pstrcpy(fname,lp_lockdir()); - trim_string(fname,NULL,"/"); - pstrcat(fname,"/"); - pstrcat(fname,SERVER_LIST); - pstrcpy(fnamenew,fname); - pstrcat(fnamenew,"."); + pstrcpy(fname,lp_lockdir()); + trim_string(fname,NULL,"/"); + pstrcat(fname,"/"); + pstrcat(fname,SERVER_LIST); + pstrcpy(fnamenew,fname); + pstrcat(fnamenew,"."); - fp = x_fopen(fnamenew,O_WRONLY|O_CREAT|O_TRUNC, 0644); + fp = x_fopen(fnamenew,O_WRONLY|O_CREAT|O_TRUNC, 0644); - if (!fp) - { - DEBUG(0,("write_browse_list: Can't open file %s. Error was %s\n", - fnamenew,strerror(errno))); - return; - } + if (!fp) { + DEBUG(0,("write_browse_list: Can't open file %s. Error was %s\n", + fnamenew,strerror(errno))); + return; + } - /* - * Write out a record for our workgroup. Use the record from the first - * subnet. - */ - - if((work = find_workgroup_on_subnet(FIRST_SUBNET, lp_workgroup())) == NULL) - { - DEBUG(0,("write_browse_list: Fatal error - cannot find my workgroup %s\n", - lp_workgroup())); - x_fclose(fp); - return; - } - - write_browse_list_entry(fp, work->work_group, - SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT|SV_TYPE_LOCAL_LIST_ONLY, - work->local_master_browser_name, work->work_group); - - /* - * We need to do something special for our own names. - * This is due to the fact that we may be a local master browser on - * one of our broadcast subnets, and a domain master on the unicast - * subnet. We iterate over the subnets and only write out the name - * once. - */ - - for (i=0; my_netbios_names(i); i++) - { - stype = 0; - for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - if((work = find_workgroup_on_subnet( subrec, lp_workgroup() )) == NULL) - continue; - if((servrec = find_server_in_workgroup( work, my_netbios_names(i))) == NULL) - continue; - - stype |= servrec->serv.type; - } - - /* Output server details, plus what workgroup they're in. */ - write_browse_list_entry(fp, my_netbios_names(i), stype, - string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH), lp_workgroup()); - } + /* + * Write out a record for our workgroup. Use the record from the first + * subnet. + */ + + if((work = find_workgroup_on_subnet(FIRST_SUBNET, lp_workgroup())) == NULL) { + DEBUG(0,("write_browse_list: Fatal error - cannot find my workgroup %s\n", + lp_workgroup())); + x_fclose(fp); + return; + } + + write_browse_list_entry(fp, work->work_group, + SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT|SV_TYPE_LOCAL_LIST_ONLY, + work->local_master_browser_name, work->work_group); + + /* + * We need to do something special for our own names. + * This is due to the fact that we may be a local master browser on + * one of our broadcast subnets, and a domain master on the unicast + * subnet. We iterate over the subnets and only write out the name + * once. + */ + + for (i=0; my_netbios_names(i); i++) { + stype = 0; + for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) { + if((work = find_workgroup_on_subnet( subrec, lp_workgroup() )) == NULL) + continue; + if((servrec = find_server_in_workgroup( work, my_netbios_names(i))) == NULL) + continue; + + stype |= servrec->serv.type; + } + + /* Output server details, plus what workgroup they're in. */ + write_browse_list_entry(fp, my_netbios_names(i), stype, + string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH), lp_workgroup()); + } - for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - subrec->work_changed = False; - - for (work = subrec->workgrouplist; work ; work = work->next) - { - /* Write out a workgroup record for a workgroup. */ - uint32 wg_type = write_this_workgroup_name( subrec, work); - - if(wg_type) - { - write_browse_list_entry(fp, work->work_group, wg_type, - work->local_master_browser_name, - work->work_group); - } - - /* Now write out any server records a workgroup may have. */ - - for (servrec = work->serverlist; servrec ; servrec = servrec->next) - { - uint32 serv_type; - - /* We have already written our names here. */ - if(is_myname(servrec->serv.name)) - continue; - - serv_type = write_this_server_name(subrec, work, servrec); - - if(serv_type) - { - /* Output server details, plus what workgroup they're in. */ - write_browse_list_entry(fp, servrec->serv.name, serv_type, - servrec->serv.comment, work->work_group); - } - } - } - } + for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) { + subrec->work_changed = False; + + for (work = subrec->workgrouplist; work ; work = work->next) { + /* Write out a workgroup record for a workgroup. */ + uint32 wg_type = write_this_workgroup_name( subrec, work); + + if(wg_type) { + write_browse_list_entry(fp, work->work_group, wg_type, + work->local_master_browser_name, + work->work_group); + } + + /* Now write out any server records a workgroup may have. */ + + for (servrec = work->serverlist; servrec ; servrec = servrec->next) { + uint32 serv_type; + + /* We have already written our names here. */ + if(is_myname(servrec->serv.name)) + continue; + + serv_type = write_this_server_name(subrec, work, servrec); + if(serv_type) { + /* Output server details, plus what workgroup they're in. */ + write_browse_list_entry(fp, servrec->serv.name, serv_type, + servrec->serv.comment, work->work_group); + } + } + } + } - x_fclose(fp); - unlink(fname); - chmod(fnamenew,0644); - rename(fnamenew,fname); - DEBUG(3,("write_browse_list: Wrote browse list into file %s\n",fname)); + x_fclose(fp); + unlink(fname); + chmod(fnamenew,0644); + rename(fnamenew,fname); + DEBUG(3,("write_browse_list: Wrote browse list into file %s\n",fname)); } diff --git a/source/nmbd/nmbd_subnetdb.c b/source/nmbd/nmbd_subnetdb.c index 62968264259..02a91f27606 100644 --- a/source/nmbd/nmbd_subnetdb.c +++ b/source/nmbd/nmbd_subnetdb.c @@ -63,28 +63,27 @@ static void add_subnet(struct subnet_record *subrec) * ************************************************************************** ** */ static int namelist_entry_compare( ubi_trItemPtr Item, ubi_trNodePtr Node ) - { - struct name_record *NR = (struct name_record *)Node; - - if( DEBUGLVL( 10 ) ) - { - struct nmb_name *Iname = (struct nmb_name *)Item; +{ + struct name_record *NR = (struct name_record *)Node; - Debug1( "nmbd_subnetdb:namelist_entry_compare()\n" ); - Debug1( "%d == memcmp( \"%s\", \"%s\", %d )\n", - memcmp( Item, &(NR->name), sizeof(struct nmb_name) ), - nmb_namestr(Iname), nmb_namestr(&NR->name), (int)sizeof(struct nmb_name) ); - } + if( DEBUGLVL( 10 ) ) { + struct nmb_name *Iname = (struct nmb_name *)Item; - return( memcmp( Item, &(NR->name), sizeof(struct nmb_name) ) ); - } /* namelist_entry_compare */ + Debug1( "nmbd_subnetdb:namelist_entry_compare()\n" ); + Debug1( "%d == memcmp( \"%s\", \"%s\", %d )\n", + memcmp( Item, &(NR->name), sizeof(struct nmb_name) ), + nmb_namestr(Iname), nmb_namestr(&NR->name), (int)sizeof(struct nmb_name) ); + } + return( memcmp( Item, &(NR->name), sizeof(struct nmb_name) ) ); +} /**************************************************************************** stop listening on a subnet we don't free the record as we don't have proper reference counting for it yet and it may be in use by a response record ****************************************************************************/ + void close_subnet(struct subnet_record *subrec) { DLIST_REMOVE(subnetlist, subrec); @@ -99,8 +98,6 @@ void close_subnet(struct subnet_record *subrec) } } - - /**************************************************************************** Create a subnet entry. ****************************************************************************/ @@ -109,102 +106,90 @@ static struct subnet_record *make_subnet(const char *name, enum subnet_type type struct in_addr myip, struct in_addr bcast_ip, struct in_addr mask_ip) { - struct subnet_record *subrec = NULL; - int nmb_sock, dgram_sock; - - /* Check if we are creating a non broadcast subnet - if so don't create - sockets. - */ - - if(type != NORMAL_SUBNET) - { - nmb_sock = -1; - dgram_sock = -1; - } - else - { - /* - * Attempt to open the sockets on port 137/138 for this interface - * and bind them. - * Fail the subnet creation if this fails. - */ - - if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, myip.s_addr,True)) == -1) - { - if( DEBUGLVL( 0 ) ) - { - Debug1( "nmbd_subnetdb:make_subnet()\n" ); - Debug1( " Failed to open nmb socket on interface %s ", inet_ntoa(myip) ); - Debug1( "for port %d. ", global_nmb_port ); - Debug1( "Error was %s\n", strerror(errno) ); - } - return NULL; - } - - if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, myip.s_addr,True)) == -1) - { - if( DEBUGLVL( 0 ) ) - { - Debug1( "nmbd_subnetdb:make_subnet()\n" ); - Debug1( " Failed to open dgram socket on interface %s ", inet_ntoa(myip) ); - Debug1( "for port %d. ", DGRAM_PORT ); - Debug1( "Error was %s\n", strerror(errno) ); - } - return NULL; - } - - /* Make sure we can broadcast from these sockets. */ - set_socket_options(nmb_sock,"SO_BROADCAST"); - set_socket_options(dgram_sock,"SO_BROADCAST"); - - } - - subrec = (struct subnet_record *)malloc(sizeof(*subrec)); - - if (!subrec) - { - DEBUG(0,("make_subnet: malloc fail !\n")); - close(nmb_sock); - close(dgram_sock); - return(NULL); - } + struct subnet_record *subrec = NULL; + int nmb_sock, dgram_sock; + + /* Check if we are creating a non broadcast subnet - if so don't create + sockets. */ + + if(type != NORMAL_SUBNET) { + nmb_sock = -1; + dgram_sock = -1; + } else { + /* + * Attempt to open the sockets on port 137/138 for this interface + * and bind them. + * Fail the subnet creation if this fails. + */ + + if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, myip.s_addr,True)) == -1) { + if( DEBUGLVL( 0 ) ) { + Debug1( "nmbd_subnetdb:make_subnet()\n" ); + Debug1( " Failed to open nmb socket on interface %s ", inet_ntoa(myip) ); + Debug1( "for port %d. ", global_nmb_port ); + Debug1( "Error was %s\n", strerror(errno) ); + } + return NULL; + } + + if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, myip.s_addr,True)) == -1) { + if( DEBUGLVL( 0 ) ) { + Debug1( "nmbd_subnetdb:make_subnet()\n" ); + Debug1( " Failed to open dgram socket on interface %s ", inet_ntoa(myip) ); + Debug1( "for port %d. ", DGRAM_PORT ); + Debug1( "Error was %s\n", strerror(errno) ); + } + return NULL; + } + + /* Make sure we can broadcast from these sockets. */ + set_socket_options(nmb_sock,"SO_BROADCAST"); + set_socket_options(dgram_sock,"SO_BROADCAST"); + } + + subrec = (struct subnet_record *)malloc(sizeof(*subrec)); + if (!subrec) { + DEBUG(0,("make_subnet: malloc fail !\n")); + close(nmb_sock); + close(dgram_sock); + return(NULL); + } - memset( (char *)subrec, '\0', sizeof(*subrec) ); - (void)ubi_trInitTree( subrec->namelist, - namelist_entry_compare, - ubi_trOVERWRITE ); - - if((subrec->subnet_name = strdup(name)) == NULL) - { - DEBUG(0,("make_subnet: malloc fail for subnet name !\n")); - close(nmb_sock); - close(dgram_sock); - ZERO_STRUCTP(subrec); - SAFE_FREE(subrec); - return(NULL); - } - - DEBUG(2, ("making subnet name:%s ", name )); - DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip))); - DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip))); + memset( (char *)subrec, '\0', sizeof(*subrec) ); + (void)ubi_trInitTree( subrec->namelist, + namelist_entry_compare, + ubi_trOVERWRITE ); + + if((subrec->subnet_name = strdup(name)) == NULL) { + DEBUG(0,("make_subnet: malloc fail for subnet name !\n")); + close(nmb_sock); + close(dgram_sock); + ZERO_STRUCTP(subrec); + SAFE_FREE(subrec); + return(NULL); + } + + DEBUG(2, ("making subnet name:%s ", name )); + DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip))); + DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip))); - subrec->namelist_changed = False; - subrec->work_changed = False; + subrec->namelist_changed = False; + subrec->work_changed = False; - subrec->bcast_ip = bcast_ip; - subrec->mask_ip = mask_ip; - subrec->myip = myip; - subrec->type = type; - subrec->nmb_sock = nmb_sock; - subrec->dgram_sock = dgram_sock; + subrec->bcast_ip = bcast_ip; + subrec->mask_ip = mask_ip; + subrec->myip = myip; + subrec->type = type; + subrec->nmb_sock = nmb_sock; + subrec->dgram_sock = dgram_sock; - return subrec; + return subrec; } - /**************************************************************************** Create a normal subnet **************************************************************************/ + struct subnet_record *make_normal_subnet(struct interface *iface) { struct subnet_record *subrec; @@ -217,100 +202,99 @@ struct subnet_record *make_normal_subnet(struct interface *iface) return subrec; } - /**************************************************************************** Create subnet entries. **************************************************************************/ BOOL create_subnets(void) { - int num_interfaces = iface_count(); - int i; - struct in_addr unicast_ip, ipzero; - extern struct in_addr loopback_ip; - - if(num_interfaces == 0) { - DEBUG(0,("create_subnets: No local interfaces !\n")); - DEBUG(0,("create_subnets: Waiting for an interface to appear ...\n")); - while (iface_count() == 0) { - sleep(5); - load_interfaces(); - } - } - - num_interfaces = iface_count(); - - /* - * Create subnets from all the local interfaces and thread them onto - * the linked list. - */ - - for (i = 0 ; i < num_interfaces; i++) - { - struct interface *iface = get_interface(i); - - /* - * We don't want to add a loopback interface, in case - * someone has added 127.0.0.1 for smbd, nmbd needs to - * ignore it here. JRA. - */ - - if (ip_equal(iface->ip, loopback_ip)) { - DEBUG(2,("create_subnets: Ignoring loopback interface.\n" )); - continue; - } - - if (!make_normal_subnet(iface)) return False; - } - - if (lp_we_are_a_wins_server()) { - /* Pick the first interface ip address as the WINS server ip. */ - unicast_ip = *iface_n_ip(0); - } else { - /* note that we do not set the wins server IP here. We just - set it at zero and let the wins registration code cope - with getting the IPs right for each packet */ - zero_ip(&unicast_ip); - } - - /* - * Create the unicast and remote broadcast subnets. - * Don't put these onto the linked list. - * The ip address of the unicast subnet is set to be - * the WINS server address, if it exists, or ipzero if not. - */ - - unicast_subnet = make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET, - unicast_ip, unicast_ip, unicast_ip); - - zero_ip(&ipzero); - - remote_broadcast_subnet = make_subnet( "REMOTE_BROADCAST_SUBNET", - REMOTE_BROADCAST_SUBNET, - ipzero, ipzero, ipzero); - - if((unicast_subnet == NULL) || (remote_broadcast_subnet == NULL)) - return False; - - /* - * If we are WINS server, create the WINS_SERVER_SUBNET - don't put on - * the linked list. - */ - - if (lp_we_are_a_wins_server()) - { - if( (wins_server_subnet = make_subnet( "WINS_SERVER_SUBNET", - WINS_SERVER_SUBNET, - ipzero, ipzero, ipzero )) == NULL ) - return False; - } - - return True; + int num_interfaces = iface_count(); + int i; + struct in_addr unicast_ip, ipzero; + extern struct in_addr loopback_ip; + + if(num_interfaces == 0) { + DEBUG(0,("create_subnets: No local interfaces !\n")); + DEBUG(0,("create_subnets: Waiting for an interface to appear ...\n")); + while (iface_count() == 0) { + sleep(5); + load_interfaces(); + } + } + + num_interfaces = iface_count(); + + /* + * Create subnets from all the local interfaces and thread them onto + * the linked list. + */ + + for (i = 0 ; i < num_interfaces; i++) { + struct interface *iface = get_interface(i); + + /* + * We don't want to add a loopback interface, in case + * someone has added 127.0.0.1 for smbd, nmbd needs to + * ignore it here. JRA. + */ + + if (ip_equal(iface->ip, loopback_ip)) { + DEBUG(2,("create_subnets: Ignoring loopback interface.\n" )); + continue; + } + + if (!make_normal_subnet(iface)) + return False; + } + + if (lp_we_are_a_wins_server()) { + /* Pick the first interface ip address as the WINS server ip. */ + unicast_ip = *iface_n_ip(0); + } else { + /* note that we do not set the wins server IP here. We just + set it at zero and let the wins registration code cope + with getting the IPs right for each packet */ + zero_ip(&unicast_ip); + } + + /* + * Create the unicast and remote broadcast subnets. + * Don't put these onto the linked list. + * The ip address of the unicast subnet is set to be + * the WINS server address, if it exists, or ipzero if not. + */ + + unicast_subnet = make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET, + unicast_ip, unicast_ip, unicast_ip); + + zero_ip(&ipzero); + + remote_broadcast_subnet = make_subnet( "REMOTE_BROADCAST_SUBNET", + REMOTE_BROADCAST_SUBNET, + ipzero, ipzero, ipzero); + + if((unicast_subnet == NULL) || (remote_broadcast_subnet == NULL)) + return False; + + /* + * If we are WINS server, create the WINS_SERVER_SUBNET - don't put on + * the linked list. + */ + + if (lp_we_are_a_wins_server()) { + if( (wins_server_subnet = make_subnet( "WINS_SERVER_SUBNET", + WINS_SERVER_SUBNET, + ipzero, ipzero, ipzero )) == NULL ) + return False; + } + + return True; } /******************************************************************* Function to tell us if we can use the unicast subnet. ******************************************************************/ + BOOL we_are_a_wins_client(void) { if (wins_srv_count() > 0) { @@ -326,12 +310,12 @@ Access function used by NEXT_SUBNET_INCLUDING_UNICAST struct subnet_record *get_next_subnet_maybe_unicast(struct subnet_record *subrec) { - if(subrec == unicast_subnet) - return NULL; - else if((subrec->next == NULL) && we_are_a_wins_client()) - return unicast_subnet; - else - return subrec->next; + if(subrec == unicast_subnet) + return NULL; + else if((subrec->next == NULL) && we_are_a_wins_client()) + return unicast_subnet; + else + return subrec->next; } /******************************************************************* @@ -343,19 +327,18 @@ struct subnet_record *get_next_subnet_maybe_unicast(struct subnet_record *subrec struct subnet_record *get_next_subnet_maybe_unicast_or_wins_server(struct subnet_record *subrec) { - if(subrec == unicast_subnet) - { - if(wins_server_subnet) - return wins_server_subnet; - else - return NULL; - } - - if(wins_server_subnet && subrec == wins_server_subnet) - return NULL; - - if((subrec->next == NULL) && we_are_a_wins_client()) - return unicast_subnet; - else - return subrec->next; + if(subrec == unicast_subnet) { + if(wins_server_subnet) + return wins_server_subnet; + else + return NULL; + } + + if(wins_server_subnet && subrec == wins_server_subnet) + return NULL; + + if((subrec->next == NULL) && we_are_a_wins_client()) + return unicast_subnet; + else + return subrec->next; } diff --git a/source/nmbd/nmbd_synclists.c b/source/nmbd/nmbd_synclists.c index b9952fb446c..337c2f94686 100644 --- a/source/nmbd/nmbd_synclists.c +++ b/source/nmbd/nmbd_synclists.c @@ -47,6 +47,7 @@ static XFILE *fp; This is the NetServerEnum callback. Note sname and comment are in UNIX codepage format. ******************************************************************/ + static void callback(const char *sname, uint32 stype, const char *comment, void *state) { @@ -58,6 +59,7 @@ static void callback(const char *sname, uint32 stype, Log in on the remote server's SMB port to their IPC$ service, do a NetServerEnum and record the results in fname ******************************************************************/ + static void sync_child(char *name, int nm_type, char *workgroup, struct in_addr ip, BOOL local, BOOL servers, @@ -78,10 +80,9 @@ static void sync_child(char *name, int nm_type, } make_nmb_name(&calling, local_machine, 0x0); - make_nmb_name(&called , name , nm_type); + make_nmb_name(&called , name, nm_type); - if (!cli_session_request(&cli, &calling, &called)) - { + if (!cli_session_request(&cli, &calling, &called)) { cli_shutdown(&cli); return; } @@ -120,12 +121,12 @@ static void sync_child(char *name, int nm_type, cli_shutdown(&cli); } - /******************************************************************* initialise a browse sync with another browse server. Log in on the remote server's SMB port to their IPC$ service, do a NetServerEnum and record the results ******************************************************************/ + void sync_browse_lists(struct work_record *work, char *name, int nm_type, struct in_addr ip, BOOL local, BOOL servers) @@ -182,8 +183,9 @@ done: } /********************************************************************** -handle one line from a completed sync file + Handle one line from a completed sync file. **********************************************************************/ + static void complete_one(struct sync_record *s, char *sname, uint32 stype, char *comment) { @@ -235,10 +237,10 @@ static void complete_one(struct sync_record *s, create_server_on_workgroup(work, sname,stype, lp_max_ttl(), comment); } - /********************************************************************** -read the completed sync info - **********************************************************************/ + Read the completed sync info. +**********************************************************************/ + static void complete_sync(struct sync_record *s) { XFILE *f; @@ -251,11 +253,13 @@ static void complete_sync(struct sync_record *s) f = x_fopen(s->fname,O_RDONLY, 0); - if (!f) return; + if (!f) + return; while (!x_feof(f)) { - if (!fgets_slash(line,sizeof(pstring),f)) continue; + if (!fgets_slash(line,sizeof(pstring),f)) + continue; ptr = line; @@ -281,8 +285,9 @@ static void complete_sync(struct sync_record *s) } /********************************************************************** -check for completion of any of the child processes - **********************************************************************/ + Check for completion of any of the child processes. +**********************************************************************/ + void sync_check_completion(void) { struct sync_record *s, *next; diff --git a/source/nmbd/nmbd_winsproxy.c b/source/nmbd/nmbd_winsproxy.c index 2e65ebb612d..bace112752f 100644 --- a/source/nmbd/nmbd_winsproxy.c +++ b/source/nmbd/nmbd_winsproxy.c @@ -30,92 +30,85 @@ static void wins_proxy_name_query_request_success( struct subnet_record *subrec, struct userdata_struct *userdata, struct nmb_name *nmbname, struct in_addr ip, struct res_rec *rrec) { - struct packet_struct *original_packet; - struct subnet_record *orig_broadcast_subnet; - struct name_record *namerec; - uint16 nb_flags; - int num_ips; - int i; - int ttl = 3600; /* By default one hour in the cache. */ - struct in_addr *iplist; - - /* Extract the original packet and the original broadcast subnet from - the userdata. */ - - memcpy( (char *)&orig_broadcast_subnet, userdata->data, sizeof(struct subnet_record *) ); - memcpy( (char *)&original_packet, &userdata->data[sizeof(struct subnet_record *)], - sizeof(struct packet_struct *) ); - - nb_flags = get_nb_flags( rrec->rdata ); - - num_ips = rrec->rdlength / 6; - if(num_ips == 0) - { - DEBUG(0,("wins_proxy_name_query_request_success: Invalid number of IP records (0) \ + nstring name; + struct packet_struct *original_packet; + struct subnet_record *orig_broadcast_subnet; + struct name_record *namerec; + uint16 nb_flags; + int num_ips; + int i; + int ttl = 3600; /* By default one hour in the cache. */ + struct in_addr *iplist; + + /* Extract the original packet and the original broadcast subnet from + the userdata. */ + + memcpy( (char *)&orig_broadcast_subnet, userdata->data, sizeof(struct subnet_record *) ); + memcpy( (char *)&original_packet, &userdata->data[sizeof(struct subnet_record *)], + sizeof(struct packet_struct *) ); + + nb_flags = get_nb_flags( rrec->rdata ); + + num_ips = rrec->rdlength / 6; + if(num_ips == 0) { + DEBUG(0,("wins_proxy_name_query_request_success: Invalid number of IP records (0) \ returned for name %s.\n", nmb_namestr(nmbname) )); - return; - } - - if(num_ips == 1) - iplist = &ip; - else - { - if((iplist = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr) )) == NULL) - { - DEBUG(0,("wins_proxy_name_query_request_success: malloc fail !\n")); - return; - } - - for(i = 0; i < num_ips; i++) - putip( (char *)&iplist[i], (char *)&rrec->rdata[ (i*6) + 2]); - } - - /* Add the queried name to the original subnet as a WINS_PROXY_NAME. */ - - if(rrec == PERMANENT_TTL) - ttl = lp_max_ttl(); - - namerec = add_name_to_subnet( orig_broadcast_subnet, nmbname->name, - nmbname->name_type, nb_flags, ttl, - WINS_PROXY_NAME, num_ips, iplist ); - - if(iplist != &ip) - SAFE_FREE(iplist); - - /* - * Check that none of the IP addresses we are returning is on the - * same broadcast subnet as the original requesting packet. If it - * is then don't reply (although we still need to add the name - * to the cache) as the actual machine will be replying also - * and we don't want two replies to a broadcast query. - */ - - if(namerec && original_packet->packet.nmb.header.nm_flags.bcast) - { - for( i = 0; i < namerec->data.num_ips; i++) - { - if( same_net( namerec->data.ip[i], - orig_broadcast_subnet->myip, - orig_broadcast_subnet->mask_ip ) ) - { - DEBUG( 5, ( "wins_proxy_name_query_request_success: name %s is a WINS \ + return; + } + + if(num_ips == 1) { + iplist = &ip; + } else { + if((iplist = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr) )) == NULL) { + DEBUG(0,("wins_proxy_name_query_request_success: malloc fail !\n")); + return; + } + + for(i = 0; i < num_ips; i++) + putip( (char *)&iplist[i], (char *)&rrec->rdata[ (i*6) + 2]); + } + + /* Add the queried name to the original subnet as a WINS_PROXY_NAME. */ + + if(rrec == PERMANENT_TTL) + ttl = lp_max_ttl(); + + pull_ascii_nstring(name, nmbname->name); + namerec = add_name_to_subnet( orig_broadcast_subnet, name, + nmbname->name_type, nb_flags, ttl, + WINS_PROXY_NAME, num_ips, iplist ); + + if(iplist != &ip) + SAFE_FREE(iplist); + + /* + * Check that none of the IP addresses we are returning is on the + * same broadcast subnet as the original requesting packet. If it + * is then don't reply (although we still need to add the name + * to the cache) as the actual machine will be replying also + * and we don't want two replies to a broadcast query. + */ + + if(namerec && original_packet->packet.nmb.header.nm_flags.bcast) { + for( i = 0; i < namerec->data.num_ips; i++) { + if( same_net( namerec->data.ip[i], orig_broadcast_subnet->myip, + orig_broadcast_subnet->mask_ip ) ) { + DEBUG( 5, ( "wins_proxy_name_query_request_success: name %s is a WINS \ proxy name and is also on the same subnet (%s) as the requestor. \ -Not replying.\n", - nmb_namestr(&namerec->name), - orig_broadcast_subnet->subnet_name ) ); - return; - } - } - } - - /* Finally reply to the original name query. */ - reply_netbios_packet(original_packet, /* Packet to reply to. */ - 0, /* Result code. */ - NMB_QUERY, /* nmbd type code. */ - NMB_NAME_QUERY_OPCODE, /* opcode. */ - ttl, /* ttl. */ - rrec->rdata, /* data to send. */ - rrec->rdlength); /* data length. */ +Not replying.\n", nmb_namestr(&namerec->name), orig_broadcast_subnet->subnet_name ) ); + return; + } + } + } + + /* Finally reply to the original name query. */ + reply_netbios_packet(original_packet, /* Packet to reply to. */ + 0, /* Result code. */ + NMB_QUERY, /* nmbd type code. */ + NMB_NAME_QUERY_OPCODE, /* opcode. */ + ttl, /* ttl. */ + rrec->rdata, /* data to send. */ + rrec->rdlength); /* data length. */ } /**************************************************************************** @@ -126,7 +119,7 @@ static void wins_proxy_name_query_request_fail(struct subnet_record *subrec, struct response_record *rrec, struct nmb_name *question_name, int fail_code) { - DEBUG(4,("wins_proxy_name_query_request_fail: WINS server returned error code %d for lookup \ + DEBUG(4,("wins_proxy_name_query_request_fail: WINS server returned error code %d for lookup \ of name %s.\n", fail_code, nmb_namestr(question_name) )); } @@ -137,38 +130,35 @@ proxy query returns. static struct userdata_struct *wins_proxy_userdata_copy_fn(struct userdata_struct *userdata) { - struct packet_struct *p, *copy_of_p; - struct userdata_struct *new_userdata = - (struct userdata_struct *)malloc( userdata->userdata_len ); + struct packet_struct *p, *copy_of_p; + struct userdata_struct *new_userdata = (struct userdata_struct *)malloc( userdata->userdata_len ); - if(new_userdata == NULL) - return NULL; + if(new_userdata == NULL) + return NULL; - new_userdata->copy_fn = userdata->copy_fn; - new_userdata->free_fn = userdata->free_fn; - new_userdata->userdata_len = userdata->userdata_len; + new_userdata->copy_fn = userdata->copy_fn; + new_userdata->free_fn = userdata->free_fn; + new_userdata->userdata_len = userdata->userdata_len; - /* Copy the subnet_record pointer. */ - memcpy( new_userdata->data, userdata->data, sizeof(struct subnet_record *) ); + /* Copy the subnet_record pointer. */ + memcpy( new_userdata->data, userdata->data, sizeof(struct subnet_record *) ); - /* Extract the pointer to the packet struct */ - memcpy((char *)&p, &userdata->data[sizeof(struct subnet_record *)], - sizeof(struct packet_struct *) ); + /* Extract the pointer to the packet struct */ + memcpy((char *)&p, &userdata->data[sizeof(struct subnet_record *)], sizeof(struct packet_struct *) ); - /* Do a deep copy of the packet. */ - if((copy_of_p = copy_packet(p)) == NULL) - { - SAFE_FREE(new_userdata); - return NULL; - } + /* Do a deep copy of the packet. */ + if((copy_of_p = copy_packet(p)) == NULL) { + SAFE_FREE(new_userdata); + return NULL; + } - /* Lock the copy. */ - copy_of_p->locked = True; + /* Lock the copy. */ + copy_of_p->locked = True; - memcpy( &new_userdata->data[sizeof(struct subnet_record *)], (char *)©_of_p, - sizeof(struct packet_struct *) ); + memcpy( &new_userdata->data[sizeof(struct subnet_record *)], (char *)©_of_p, + sizeof(struct packet_struct *) ); - return new_userdata; + return new_userdata; } /**************************************************************************** @@ -178,18 +168,18 @@ proxy query returned. static void wins_proxy_userdata_free_fn(struct userdata_struct *userdata) { - struct packet_struct *p; + struct packet_struct *p; - /* Extract the pointer to the packet struct */ - memcpy((char *)&p, &userdata->data[sizeof(struct subnet_record *)], - sizeof(struct packet_struct *)); + /* Extract the pointer to the packet struct */ + memcpy((char *)&p, &userdata->data[sizeof(struct subnet_record *)], + sizeof(struct packet_struct *)); - /* Unlock the packet. */ - p->locked = False; + /* Unlock the packet. */ + p->locked = False; - free_packet(p); - ZERO_STRUCTP(userdata); - SAFE_FREE(userdata); + free_packet(p); + ZERO_STRUCTP(userdata); + SAFE_FREE(userdata); } /**************************************************************************** @@ -200,22 +190,24 @@ void make_wins_proxy_name_query_request( struct subnet_record *subrec, struct packet_struct *incoming_packet, struct nmb_name *question_name) { - long *ud[(sizeof(struct userdata_struct) + sizeof(struct subrec *) + - sizeof(struct packet_struct *))/sizeof(long *) + 1]; - struct userdata_struct *userdata = (struct userdata_struct *)ud; + long *ud[(sizeof(struct userdata_struct) + sizeof(struct subrec *) + + sizeof(struct packet_struct *))/sizeof(long *) + 1]; + struct userdata_struct *userdata = (struct userdata_struct *)ud; + nstring qname; - memset(ud, '\0', sizeof(ud)); + memset(ud, '\0', sizeof(ud)); - userdata->copy_fn = wins_proxy_userdata_copy_fn; - userdata->free_fn = wins_proxy_userdata_free_fn; - userdata->userdata_len = sizeof(ud); - memcpy( userdata->data, (char *)&subrec, sizeof(struct subnet_record *)); - memcpy( &userdata->data[sizeof(struct subnet_record *)], (char *)&incoming_packet, - sizeof(struct packet_struct *)); - - /* Now use the unicast subnet to query the name with the WINS server. */ - query_name( unicast_subnet, question_name->name, question_name->name_type, - wins_proxy_name_query_request_success, - wins_proxy_name_query_request_fail, - userdata); + userdata->copy_fn = wins_proxy_userdata_copy_fn; + userdata->free_fn = wins_proxy_userdata_free_fn; + userdata->userdata_len = sizeof(ud); + memcpy( userdata->data, (char *)&subrec, sizeof(struct subnet_record *)); + memcpy( &userdata->data[sizeof(struct subnet_record *)], (char *)&incoming_packet, + sizeof(struct packet_struct *)); + + /* Now use the unicast subnet to query the name with the WINS server. */ + pull_ascii_nstring(qname, question_name->name); + query_name( unicast_subnet, qname, question_name->name_type, + wins_proxy_name_query_request_success, + wins_proxy_name_query_request_fail, + userdata); } diff --git a/source/nmbd/nmbd_winsserver.c b/source/nmbd/nmbd_winsserver.c index 784c909c814..1abff5d5e25 100644 --- a/source/nmbd/nmbd_winsserver.c +++ b/source/nmbd/nmbd_winsserver.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. NBT netbios routines and daemon - version 2 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 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 @@ -26,8 +26,9 @@ #define WINS_VERSION 1 /**************************************************************************** -change the wins owner address in the record. + 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) @@ -36,8 +37,9 @@ static void update_wins_owner(struct name_record *namerec, struct in_addr wins_i } /**************************************************************************** -create the wins flags based on the nb flags and the input value. + 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) @@ -74,12 +76,12 @@ static void update_wins_flag(struct name_record *namerec, int 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 + Return the general ID value and increase it if requested. *****************************************************************************/ + static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update) { /* @@ -98,8 +100,9 @@ static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update) } /**************************************************************************** -possibly call the WINS hook external program when a WINS change is made + 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; @@ -139,63 +142,58 @@ 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; + 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; } /**************************************************************************** @@ -204,15 +202,15 @@ 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; + int ttl = nmb->additional->ttl; - if(ttl < lp_min_wins_ttl() ) - ttl = lp_min_wins_ttl(); + if(ttl < lp_min_wins_ttl() ) + ttl = lp_min_wins_ttl(); - if(ttl > lp_max_wins_ttl() ) - ttl = lp_max_wins_ttl(); + if(ttl > lp_max_wins_ttl() ) + ttl = lp_max_wins_ttl(); - return ttl; + return ttl; } /**************************************************************************** @@ -221,177 +219,160 @@ 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 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; + 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 = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == NULL) - { - DEBUG(0,("initialise_wins: Malloc fail !\n")); - return False; - } + 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 = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == 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; - } + /* 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'; + 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); + /* 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); - } + 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; + /* 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)); - } + 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); - } + SAFE_FREE(ip_list); + } - x_fclose(fp); - return True; + x_fclose(fp); + return True; } /**************************************************************************** @@ -400,30 +381,33 @@ 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. */ - - rdata[0] = (nmb->header.opcode & 0xF) << 3; - if (nmb->header.nm_flags.authoritative && - nmb->header.response) rdata[0] |= 0x4; - if (nmb->header.nm_flags.trunc) rdata[0] |= 0x2; - if (nmb->header.nm_flags.recursion_desired) rdata[0] |= 0x1; - if (nmb->header.nm_flags.recursion_available && - nmb->header.response) rdata[1] |= 0x80; - if (nmb->header.nm_flags.bcast) rdata[1] |= 0x10; - - reply_netbios_packet(p, /* Packet to reply to. */ - 0, /* Result code. */ - NMB_WAIT_ACK, /* nmbd type code. */ - NMB_WACK_OPCODE, /* opcode. */ - ttl, /* ttl. */ - (char *)rdata, /* data to send. */ - 2); /* data length. */ + 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. */ + + rdata[0] = (nmb->header.opcode & 0xF) << 3; + if (nmb->header.nm_flags.authoritative && nmb->header.response) + rdata[0] |= 0x4; + if (nmb->header.nm_flags.trunc) + rdata[0] |= 0x2; + if (nmb->header.nm_flags.recursion_desired) + rdata[0] |= 0x1; + if (nmb->header.nm_flags.recursion_available && nmb->header.response) + rdata[1] |= 0x80; + if (nmb->header.nm_flags.bcast) + rdata[1] |= 0x10; + + reply_netbios_packet(p, /* Packet to reply to. */ + 0, /* Result code. */ + NMB_WAIT_ACK, /* nmbd type code. */ + NMB_WACK_OPCODE, /* opcode. */ + ttl, /* ttl. */ + (char *)rdata, /* data to send. */ + 2); /* data length. */ } /**************************************************************************** @@ -432,18 +416,18 @@ Send a WINS name registration response. static void send_wins_name_registration_response(int rcode, int ttl, 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. */ - WINS_REG, /* nmbd type code. */ - NMB_NAME_REG_OPCODE, /* opcode. */ - ttl, /* ttl. */ - rdata, /* data to send. */ - 6); /* data length. */ + 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. */ + WINS_REG, /* nmbd type code. */ + NMB_NAME_REG_OPCODE, /* opcode. */ + ttl, /* ttl. */ + rdata, /* data to send. */ + 6); /* data length. */ } /*********************************************************************** @@ -453,139 +437,128 @@ static void send_wins_name_registration_response(int rcode, int ttl, struct pack void wins_process_name_refresh_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); - BOOL group = (nb_flags & NB_GROUP) ? True : False; - struct name_record *namerec = NULL; - int ttl = get_ttl_from_packet(nmb); - struct in_addr from_ip; - struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); - - putip((char *)&from_ip,&nmb->additional->rdata[2]); - - if(bcast) - { - /* - * We should only get unicast name refresh packets here. - * Anyone trying to refresh broadcast should not be going to a WINS - * server. Log an error here. - */ - - DEBUG(0,("wins_process_name_refresh_request: broadcast name refresh request \ + 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); + BOOL group = (nb_flags & NB_GROUP) ? True : False; + struct name_record *namerec = NULL; + int ttl = get_ttl_from_packet(nmb); + struct in_addr from_ip; + struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); + + putip((char *)&from_ip,&nmb->additional->rdata[2]); + + if(bcast) { + /* + * We should only get unicast name refresh packets here. + * Anyone trying to refresh broadcast should not be going to a WINS + * server. Log an error here. + */ + + DEBUG(0,("wins_process_name_refresh_request: broadcast name refresh 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; - } + nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); + return; + } - DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s \ + DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s \ IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) )); - /* - * See if the name already exists. - */ + /* + * See if the name already exists. + */ - namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); + namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); - /* - * If this is a refresh request and the name doesn't exist then - * treat it like a registration request. This allows us to recover - * from errors (tridge) - */ + /* + * If this is a refresh request and the name doesn't exist then + * treat it like a registration request. This allows us to recover + * from errors (tridge) + */ - if(namerec == NULL) - { - DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s and \ + if(namerec == NULL) { + DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s and \ the name does not exist. Treating as registration.\n", nmb_namestr(question) )); - wins_process_name_registration_request(subrec,p); - return; - } - - /* - * if the name is present but not active, - * simply remove it and treat the request - * as a registration - */ - if (namerec != NULL && !WINS_STATE_ACTIVE(namerec)) - { - DEBUG(5,("wins_process_name_refresh_request: Name (%s) in WINS was \ + wins_process_name_registration_request(subrec,p); + return; + } + + /* + * if the name is present but not active, + * simply remove it and treat the request + * as a registration + */ + if (namerec != NULL && !WINS_STATE_ACTIVE(namerec)) { + DEBUG(5,("wins_process_name_refresh_request: Name (%s) in WINS was \ not active - removing it.\n", nmb_namestr(question) )); - remove_name_from_namelist( subrec, namerec ); - namerec = NULL; - wins_process_name_registration_request(subrec,p); - return; - } - - /* - * Check that the group bits for the refreshing name and the - * name in our database match. - */ - - if((namerec != NULL) && ((group && !NAME_GROUP(namerec)) || (!group && NAME_GROUP(namerec))) ) - { - DEBUG(3,("wins_process_name_refresh_request: Name %s group bit = %s \ + remove_name_from_namelist( subrec, namerec ); + namerec = NULL; + wins_process_name_registration_request(subrec,p); + return; + } + + /* + * Check that the group bits for the refreshing name and the + * name in our database match. + */ + + if((namerec != NULL) && ((group && !NAME_GROUP(namerec)) || (!group && NAME_GROUP(namerec))) ) { + DEBUG(3,("wins_process_name_refresh_request: Name %s group bit = %s \ does not match group bit in WINS for this name.\n", nmb_namestr(question), group ? "True" : "False" )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } - - /* - * For a unique name check that the person refreshing the name is one of the registered IP - * addresses. If not - fail the refresh. Do the same for group names with a type of 0x1c. - * Just return success for unique 0x1d refreshes. For normal group names update the ttl - * and return success. - */ - - if((!group || (group && (question->name_type == 0x1c))) && find_ip_in_name_record(namerec, from_ip )) - { - /* - * Update the ttl. - */ - update_name_ttl(namerec, ttl); - - /* - * if the record is a replica: - * we take ownership and update the version ID. - */ - if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) { - update_wins_owner(namerec, our_fake_ip); - get_global_id_and_update(&namerec->data.id, True); - } - - send_wins_name_registration_response(0, ttl, p); - wins_hook("refresh", namerec, ttl); - return; - } - else if(group) - { - /* - * Normal groups are all registered with an IP address of 255.255.255.255 - * so we can't search for the IP address. - */ - update_name_ttl(namerec, ttl); - send_wins_name_registration_response(0, ttl, p); - return; - } - else if(!group && (question->name_type == 0x1d)) - { - /* - * Special name type - just pretend the refresh succeeded. - */ - send_wins_name_registration_response(0, ttl, p); - return; - } - else - { - /* - * Fail the refresh. - */ - - DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s with IP %s and \ + send_wins_name_registration_response(RFS_ERR, 0, p); + return; + } + + /* + * For a unique name check that the person refreshing the name is one of the registered IP + * addresses. If not - fail the refresh. Do the same for group names with a type of 0x1c. + * Just return success for unique 0x1d refreshes. For normal group names update the ttl + * and return success. + */ + + if((!group || (group && (question->name_type == 0x1c))) && find_ip_in_name_record(namerec, from_ip )) { + /* + * Update the ttl. + */ + update_name_ttl(namerec, ttl); + + /* + * if the record is a replica: + * we take ownership and update the version ID. + */ + if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) { + update_wins_owner(namerec, our_fake_ip); + get_global_id_and_update(&namerec->data.id, True); + } + + send_wins_name_registration_response(0, ttl, p); + wins_hook("refresh", namerec, ttl); + return; + } else if(group) { + /* + * Normal groups are all registered with an IP address of 255.255.255.255 + * so we can't search for the IP address. + */ + update_name_ttl(namerec, ttl); + send_wins_name_registration_response(0, ttl, p); + return; + } else if(!group && (question->name_type == 0x1d)) { + /* + * Special name type - just pretend the refresh succeeded. + */ + send_wins_name_registration_response(0, ttl, p); + return; + } else { + /* + * Fail the refresh. + */ + + DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s with IP %s and \ is IP is not known to the name.\n", nmb_namestr(question), inet_ntoa(from_ip) )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } + send_wins_name_registration_response(RFS_ERR, 0, p); + return; + } } /*********************************************************************** @@ -604,17 +577,17 @@ static void wins_register_query_success(struct subnet_record *subrec, struct in_addr ip, struct res_rec *answers) { - struct packet_struct *orig_reg_packet; + struct packet_struct *orig_reg_packet; - memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); + memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); - DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \ + DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \ name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) )); - send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); + send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); - orig_reg_packet->locked = False; - free_packet(orig_reg_packet); + orig_reg_packet->locked = False; + free_packet(orig_reg_packet); } /*********************************************************************** @@ -632,40 +605,37 @@ static void wins_register_query_fail(struct subnet_record *subrec, struct nmb_name *question_name, int rcode) { - struct userdata_struct *userdata = rrec->userdata; - struct packet_struct *orig_reg_packet; - struct name_record *namerec = NULL; - - memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); - - /* - * We want to just add the name, as we now know the original owner - * didn't want 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 timeout/error response. So we check that - * the name still exists and is in the same state - if so - * we remove it and call wins_process_name_registration_request() - * as we know it will do the right thing now. - */ - - namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME); - - if( (namerec != NULL) - && (namerec->data.source == REGISTER_NAME) - && ip_equal(rrec->packet->ip, *namerec->data.ip) ) - { - remove_name_from_namelist( subrec, namerec); - namerec = NULL; - } - - if(namerec == NULL) - wins_process_name_registration_request(subrec, orig_reg_packet); - else - DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \ + struct userdata_struct *userdata = rrec->userdata; + struct packet_struct *orig_reg_packet; + struct name_record *namerec = NULL; + + memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); + + /* + * We want to just add the name, as we now know the original owner + * didn't want 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 timeout/error response. So we check that + * the name still exists and is in the same state - if so + * we remove it and call wins_process_name_registration_request() + * as we know it will do the right thing now. + */ + + namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME); + + if( (namerec != NULL) && (namerec->data.source == REGISTER_NAME) && ip_equal(rrec->packet->ip, *namerec->data.ip) ) { + remove_name_from_namelist( subrec, namerec); + namerec = NULL; + } + + if(namerec == NULL) + wins_process_name_registration_request(subrec, orig_reg_packet); + else + DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \ querying for name %s in order to replace it and this reply.\n", nmb_namestr(question_name) )); - orig_reg_packet->locked = False; - free_packet(orig_reg_packet); + orig_reg_packet->locked = False; + free_packet(orig_reg_packet); } /*********************************************************************** @@ -728,279 +698,269 @@ querying for name %s in order to replace it and this reply.\n", nmb_namestr(ques void wins_process_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 registering_group_name = (nb_flags & NB_GROUP) ? True : False; - struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); - - 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_registration_request: broadcast name registration request \ + nstring name; + 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 registering_group_name = (nb_flags & NB_GROUP) ? True : False; + struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); + + 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_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; - } + nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); + return; + } - DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \ + DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \ IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) )); - /* - * See if the name already exists. - */ + /* + * See if the name already exists. + */ - namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); + 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_name_registration_request: Name (%s) in WINS was \ + /* + * if the record exists but NOT in active state, + * consider it dead. + */ + if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) { + DEBUG(5,("wins_process_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_name_registration_request: Name (%s) in WINS was \ + 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_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 \ + 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 \ + 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); + send_wins_name_registration_response(0, ttl, p); + return; + } /* - * 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. + * Next two cases are the 'if statement' mentioned above. */ - update_wins_owner(namerec, our_fake_ip); + 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); + send_wins_name_registration_response(0, ttl, p); + return; + } else { - } - update_name_ttl(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 \ + /* + * 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) && (is_myname(namerec->name.name)) ) - { - if(!ismyip(from_ip)) - { - DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \ + 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. + */ + + pull_ascii_nstring(name, namerec->name.name); + if((namerec != NULL) && (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); - send_wins_name_registration_response(0, ttl, p); - wins_hook("refresh", namerec, ttl); - 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 ); - send_wins_name_registration_response( 0, ttl, p ); - wins_hook("refresh", namerec, ttl); - 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. - */ - - query_name_from_wins_server( *namerec->data.ip, - question->name, - question->name_type, - wins_register_query_success, - wins_register_query_fail, - userdata ); - return; - } - - /* - * Name did not exist - add it. - */ - - (void)add_name_to_subnet( subrec, question->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(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); + send_wins_name_registration_response(0, ttl, p); + wins_hook("refresh", namerec, ttl); + return; + } + } - send_wins_name_registration_response(0, ttl, p); + /* + * 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 ); + send_wins_name_registration_response( 0, ttl, p ); + wins_hook("refresh", namerec, ttl); + 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, 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, 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); } /*********************************************************************** @@ -1017,55 +977,54 @@ static void wins_multihomed_register_query_success(struct subnet_record *subrec, 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 \ + 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); + send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); - orig_reg_packet->locked = False; - free_packet(orig_reg_packet); + orig_reg_packet->locked = False; + free_packet(orig_reg_packet); - return; - } + return; + } - if(!find_ip_in_name_record(namerec, from_ip)) - add_ip_to_name_record(namerec, from_ip); + 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); - send_wins_name_registration_response(0, ttl, orig_reg_packet); - wins_hook("add", namerec, ttl); + 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); + send_wins_name_registration_response(0, ttl, orig_reg_packet); + wins_hook("add", namerec, ttl); - orig_reg_packet->locked = False; - free_packet(orig_reg_packet); + orig_reg_packet->locked = False; + free_packet(orig_reg_packet); } /*********************************************************************** @@ -1081,18 +1040,18 @@ static void wins_multihomed_register_query_fail(struct subnet_record *subrec, struct nmb_name *question_name, int rcode) { - struct userdata_struct *userdata = rrec->userdata; - struct packet_struct *orig_reg_packet; + struct userdata_struct *userdata = rrec->userdata; + struct packet_struct *orig_reg_packet; - memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); + 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 \ + 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); + send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); - orig_reg_packet->locked = False; - free_packet(orig_reg_packet); - return; + orig_reg_packet->locked = False; + free_packet(orig_reg_packet); + return; } /*********************************************************************** @@ -1103,250 +1062,241 @@ query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr( 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"); - - 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 \ + 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"); + nstring 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; - } + nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); + return; + } - /* - * Only unique names should be registered multihomed. - */ + /* + * Only unique names should be registered multihomed. + */ - if(group) - { - DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \ + 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; - } + nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); + return; + } - DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \ + 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. - */ + /* + * Deal with policy regarding 0x1d names. + */ - if(question->name_type == 0x1d) - { - DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \ + 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; - } + 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 \ + /* + * 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) ) - { - DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \ + 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_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 \ + 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 \ + 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. - */ - 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("add", namerec, ttl); - } else { - wins_hook("refresh", namerec, ttl); - } - - update_name_ttl(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); - } + 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. + */ + 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("add", namerec, ttl); + } else { + wins_hook("refresh", namerec, ttl); + } + + update_name_ttl(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); + } - send_wins_name_registration_response(0, ttl, p); - wins_hook("refresh", namerec, ttl); - 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 - */ - - query_name_from_wins_server( namerec->data.ip[0], - question->name, - question->name_type, - wins_multihomed_register_query_success, - wins_multihomed_register_query_fail, - userdata ); - - return; - } - - /* - * Name did not exist - add it. - */ - - (void)add_name_to_subnet( subrec, question->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); + send_wins_name_registration_response(0, ttl, p); + wins_hook("refresh", namerec, ttl); + 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, 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, 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); } /*********************************************************************** @@ -1356,76 +1306,68 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio 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 *)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); + 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 *)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); } /**************************************************************************** @@ -1435,55 +1377,48 @@ 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 *)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); + 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 *)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); } /*********************************************************************** @@ -1493,93 +1428,87 @@ void send_wins_name_query_response(int rcode, struct packet_struct *p, 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; - - 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. - */ - - if(strequal( question->name, "*") && (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); + struct nmb_packet *nmb = &p->packet.nmb; + struct nmb_name *question = &nmb->question.question_name; + struct name_record *namerec = NULL; + nstring 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, 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); } /**************************************************************************** @@ -1588,18 +1517,18 @@ 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. */ + 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. */ } /*********************************************************************** @@ -1609,123 +1538,115 @@ static void send_wins_name_release_response(int rcode, struct packet_struct *p) 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 \ + 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)); - return; - } + nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); + return; + } - DEBUG(3,("wins_process_name_release_request: %s name release for name %s \ + DEBUG(3,("wins_process_name_release_request: %s name release for name %s \ IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) )); - /* - * Deal with policy regarding 0x1d names. - */ + /* + * Deal with policy regarding 0x1d names. + */ - if(!releasing_group_name && (question->name_type == 0x1d)) - { - DEBUG(3,("wins_process_name_release_request: Ignoring request \ + if(!releasing_group_name && (question->name_type == 0x1d)) { + DEBUG(3,("wins_process_name_release_request: Ignoring request \ to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) )); - send_wins_name_release_response(0, p); - return; - } + send_wins_name_release_response(0, p); + return; + } - /* - * See if the name already exists. - */ + /* + * See if the name already exists. + */ - namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); - - if( (namerec == NULL) - || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) - { - send_wins_name_release_response(NAM_ERR, p); - return; - } - - /* - * Check that the sending machine has permission to release this name. - * If it's a group name not ending in 0x1c then just say yes and let - * the group time out. - */ - - if(releasing_group_name && (question->name_type != 0x1c)) - { - send_wins_name_release_response(0, p); - return; - } - - /* - * Check that the releasing node is on the list of IP addresses - * for this name. Disallow the release if not. - */ - - if(!find_ip_in_name_record(namerec, from_ip)) - { - DEBUG(3,("wins_process_name_release_request: Refusing request to \ + namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); + + if( (namerec == NULL) || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) { + send_wins_name_release_response(NAM_ERR, p); + return; + } + + /* + * Check that the sending machine has permission to release this name. + * If it's a group name not ending in 0x1c then just say yes and let + * the group time out. + */ + + if(releasing_group_name && (question->name_type != 0x1c)) { + send_wins_name_release_response(0, p); + return; + } + + /* + * Check that the releasing node is on the list of IP addresses + * for this name. Disallow the release if not. + */ + + if(!find_ip_in_name_record(namerec, from_ip)) { + DEBUG(3,("wins_process_name_release_request: Refusing request to \ release name %s as IP %s is not one of the known IP's for this name.\n", - nmb_namestr(question), inet_ntoa(from_ip) )); - send_wins_name_release_response(NAM_ERR, p); - return; - } - - /* - * Check if the record is active. IF it's already released - * or tombstoned, refuse the release. - */ - if (!WINS_STATE_ACTIVE(namerec)) { - DEBUG(3,("wins_process_name_release_request: Refusing request to \ -release name %s as this record is not anymore active.\n", - nmb_namestr(question) )); - send_wins_name_release_response(NAM_ERR, p); - return; - } - - /* - * Check if the record is a 0x1c group - * and has more then one ip - * remove only this address. - */ - - if(releasing_group_name && - (question->name_type == 0x1c) && - (namerec->data.num_ips > 1)) { - remove_ip_from_name_record(namerec, from_ip); - DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n", - inet_ntoa(from_ip),nmb_namestr(question))); - send_wins_name_release_response(0, p); - return; - } + nmb_namestr(question), inet_ntoa(from_ip) )); + send_wins_name_release_response(NAM_ERR, p); + return; + } + + /* + * Check if the record is active. IF it's already released + * or tombstoned, refuse the release. + */ + + if (!WINS_STATE_ACTIVE(namerec)) { + DEBUG(3,("wins_process_name_release_request: Refusing request to \ +release name %s as this record is not active anymore.\n", nmb_namestr(question) )); + send_wins_name_release_response(NAM_ERR, p); + return; + } + + /* + * Check if the record is a 0x1c group + * and has more then one ip + * remove only this address. + */ + + if(releasing_group_name && (question->name_type == 0x1c) && (namerec->data.num_ips > 1)) { + remove_ip_from_name_record(namerec, from_ip); + DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n", + inet_ntoa(from_ip),nmb_namestr(question))); + send_wins_name_release_response(0, p); + return; + } - /* - * Send a release response. - * Flag the name as released and update the ttl - */ + /* + * Send a release response. + * Flag the name as released and update the ttl + */ - send_wins_name_release_response(0, p); + send_wins_name_release_response(0, p); - namerec->data.wins_flags |= WINS_RELEASED; - update_name_ttl(namerec, EXTINCTION_INTERVAL); + namerec->data.wins_flags |= WINS_RELEASED; + update_name_ttl(namerec, EXTINCTION_INTERVAL); - wins_hook("delete", namerec, 0); + wins_hook("delete", namerec, 0); } /******************************************************************* @@ -1817,94 +1738,89 @@ we are not the wins owner !\n", nmb_namestr(&namerec->name))); /******************************************************************* Write out the current WINS database. ******************************************************************/ + void wins_write_database(BOOL background) { - struct name_record *namerec; - pstring fname, fnamenew; + struct name_record *namerec; + pstring fname, fnamenew; - XFILE *fp; + XFILE *fp; - if(!lp_we_are_a_wins_server()) - return; - - /* we will do the writing in a child process to ensure that the parent - doesn't block while this is done */ - if (background) { - CatchChild(); - if (sys_fork()) { - return; - } - } - - slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST); - all_string_sub(fname,"//", "/", 0); - slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid()); - - if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL) - { - DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno))); - if (background) { - _exit(0); - } - return; - } - - DEBUG(4,("wins_write_database: Dump of WINS name list.\n")); - - x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0); + if(!lp_we_are_a_wins_server()) + return; + + /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */ + if (background) { + CatchChild(); + if (sys_fork()) { + return; + } + } + + slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST); + all_string_sub(fname,"//", "/", 0); + slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid()); + + if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL) { + DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno))); + if (background) { + _exit(0); + } + return; + } + + DEBUG(4,("wins_write_database: Dump of WINS name list.\n")); + + x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0); - for( namerec - = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); - namerec; - namerec = (struct name_record *)ubi_trNext( namerec ) ) - { - int i; - struct tm *tm; - - DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) )); - - if( namerec->data.death_time != PERMANENT_TTL ) - { - char *ts, *nl; - - tm = LocalTime(&namerec->data.death_time); - ts = asctime(tm); - nl = strrchr( ts, '\n' ); - if( NULL != nl ) - *nl = '\0'; - DEBUGADD(4,("TTL = %s ", ts )); - } - else - DEBUGADD(4,("TTL = PERMANENT ")); - - for (i = 0; i < namerec->data.num_ips; i++) - DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) )); - DEBUGADD(4,("%2x\n", namerec->data.nb_flags )); - - if( namerec->data.source == REGISTER_NAME ) - { - x_fprintf(fp, "\"%s#%02x\" %d ", - namerec->name.name,namerec->name.name_type, /* Ignore scope. */ - (int)namerec->data.death_time); - - for (i = 0; i < namerec->data.num_ips; i++) - x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) ); - x_fprintf( fp, "%2xR\n", namerec->data.nb_flags ); - } - } + for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) { + int i; + struct tm *tm; + + DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) )); + + if( namerec->data.death_time != PERMANENT_TTL ) { + char *ts, *nl; + + tm = LocalTime(&namerec->data.death_time); + ts = asctime(tm); + nl = strrchr( ts, '\n' ); + if( NULL != nl ) + *nl = '\0'; + DEBUGADD(4,("TTL = %s ", ts )); + } else { + DEBUGADD(4,("TTL = PERMANENT ")); + } + + for (i = 0; i < namerec->data.num_ips; i++) + DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) )); + DEBUGADD(4,("%2x\n", namerec->data.nb_flags )); + + if( namerec->data.source == REGISTER_NAME ) { + nstring name; + pull_ascii_nstring(name, namerec->name.name); + x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */ + (int)namerec->data.death_time); + + for (i = 0; i < namerec->data.num_ips; i++) + x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) ); + x_fprintf( fp, "%2xR\n", namerec->data.nb_flags ); + } + } - x_fclose(fp); - chmod(fnamenew,0644); - unlink(fname); - rename(fnamenew,fname); - if (background) { - _exit(0); - } + x_fclose(fp); + chmod(fnamenew,0644); + unlink(fname); + rename(fnamenew,fname); + if (background) { + _exit(0); + } } /**************************************************************************** -process a internal Samba message receiving a wins record + Process a internal Samba message receiving a wins record. ***************************************************************************/ + void nmbd_wins_new_entry(int msg_type, pid_t src, void *buf, size_t len) { WINS_RECORD *record; @@ -1918,11 +1834,10 @@ void nmbd_wins_new_entry(int msg_type, pid_t src, void *buf, size_t len) if (buf==NULL) return; + /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */ record=(WINS_RECORD *)buf; - ZERO_STRUCT(question); - memcpy(question.name, record->name, 16); - question.name_type=record->type; + make_nmb_name(&question, record->name, record->type); namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME); @@ -1994,9 +1909,9 @@ void nmbd_wins_new_entry(int msg_type, pid_t src, void *buf, size_t len) for (i=0; i<record->num_ips; i++) if(!find_ip_in_name_record(namerec, record->ip[i])) add_ip_to_name_record(namerec, record->ip[i]); - } - else + } else { overwrite=True; + } } /* the replica is a multihomed host */ diff --git a/source/nmbd/nmbd_workgroupdb.c b/source/nmbd/nmbd_workgroupdb.c index 2357fd637b5..08d6fb2c627 100644 --- a/source/nmbd/nmbd_workgroupdb.c +++ b/source/nmbd/nmbd_workgroupdb.c @@ -31,7 +31,7 @@ int workgroup_count = 0; /* unique index key: one for each workgroup */ /**************************************************************************** Add a workgroup into the list. - **************************************************************************/ +**************************************************************************/ static void add_workgroup(struct subnet_record *subrec, struct work_record *work) { @@ -42,164 +42,153 @@ static void add_workgroup(struct subnet_record *subrec, struct work_record *work /**************************************************************************** Create an empty workgroup. - **************************************************************************/ +**************************************************************************/ static struct work_record *create_workgroup(const char *name, int ttl) { - struct work_record *work; - struct subnet_record *subrec; - int t = -1; + struct work_record *work; + struct subnet_record *subrec; + int t = -1; - if((work = (struct work_record *)malloc(sizeof(*work))) == NULL) - { - DEBUG(0,("create_workgroup: malloc fail !\n")); - return NULL; - } - memset((char *)work, '\0', sizeof(*work)); + if((work = (struct work_record *)malloc(sizeof(*work))) == NULL) { + DEBUG(0,("create_workgroup: malloc fail !\n")); + return NULL; + } + memset((char *)work, '\0', sizeof(*work)); - fstrcpy(work->work_group,name); - work->serverlist = NULL; + fstrcpy(work->work_group,name); + work->serverlist = NULL; - work->RunningElection = False; - work->ElectionCount = 0; - work->announce_interval = 0; - work->needelection = False; - work->needannounce = True; - work->lastannounce_time = time(NULL); - work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; - work->dom_state = DOMAIN_NONE; - work->log_state = LOGON_NONE; + work->RunningElection = False; + work->ElectionCount = 0; + work->announce_interval = 0; + work->needelection = False; + work->needannounce = True; + work->lastannounce_time = time(NULL); + work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; + work->dom_state = DOMAIN_NONE; + work->log_state = LOGON_NONE; - work->death_time = (ttl != PERMANENT_TTL) ? time(NULL)+(ttl*3) : PERMANENT_TTL; + work->death_time = (ttl != PERMANENT_TTL) ? time(NULL)+(ttl*3) : PERMANENT_TTL; - /* Make sure all token representations of workgroups are unique. */ + /* Make sure all token representations of workgroups are unique. */ - for (subrec = FIRST_SUBNET; subrec && (t == -1); - subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - struct work_record *w; - for (w = subrec->workgrouplist; w && t == -1; w = w->next) - { - if (strequal(w->work_group, work->work_group)) - t = w->token; - } - } + for (subrec = FIRST_SUBNET; subrec && (t == -1); subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) { + struct work_record *w; + for (w = subrec->workgrouplist; w && t == -1; w = w->next) { + if (strequal(w->work_group, work->work_group)) + t = w->token; + } + } - if (t == -1) - work->token = ++workgroup_count; - else - work->token = t; + if (t == -1) + work->token = ++workgroup_count; + else + work->token = t; - /* No known local master browser as yet. */ - *work->local_master_browser_name = '\0'; - - /* No known domain master browser as yet. */ - *work->dmb_name.name = '\0'; - zero_ip(&work->dmb_addr); - - /* WfWg uses 01040b01 */ - /* Win95 uses 01041501 */ - /* NTAS uses ???????? */ - work->ElectionCriterion = (MAINTAIN_LIST)|(BROWSER_ELECTION_VERSION<<8); - work->ElectionCriterion |= (lp_os_level() << 24); - if (lp_domain_master()) - work->ElectionCriterion |= 0x80; + /* No known local master browser as yet. */ + *work->local_master_browser_name = '\0'; + + /* No known domain master browser as yet. */ + *work->dmb_name.name = '\0'; + zero_ip(&work->dmb_addr); + + /* WfWg uses 01040b01 */ + /* Win95 uses 01041501 */ + /* NTAS uses ???????? */ + work->ElectionCriterion = (MAINTAIN_LIST)|(BROWSER_ELECTION_VERSION<<8); + work->ElectionCriterion |= (lp_os_level() << 24); + if (lp_domain_master()) + work->ElectionCriterion |= 0x80; - return work; + return work; } /******************************************************************* Remove a workgroup. - ******************************************************************/ +******************************************************************/ static struct work_record *remove_workgroup_from_subnet(struct subnet_record *subrec, struct work_record *work) { - struct work_record *ret_work = NULL; + struct work_record *ret_work = NULL; - DEBUG(3,("remove_workgroup: Removing workgroup %s\n", work->work_group)); + DEBUG(3,("remove_workgroup: Removing workgroup %s\n", work->work_group)); - ret_work = work->next; + ret_work = work->next; - remove_all_servers(work); + remove_all_servers(work); - if (!work->serverlist) - { - if (work->prev) - work->prev->next = work->next; - if (work->next) - work->next->prev = work->prev; + if (!work->serverlist) { + if (work->prev) + work->prev->next = work->next; + if (work->next) + work->next->prev = work->prev; - if (subrec->workgrouplist == work) - subrec->workgrouplist = work->next; + if (subrec->workgrouplist == work) + subrec->workgrouplist = work->next; - ZERO_STRUCTP(work); - SAFE_FREE(work); - } + ZERO_STRUCTP(work); + SAFE_FREE(work); + } - subrec->work_changed = True; + subrec->work_changed = True; - return ret_work; + return ret_work; } - /**************************************************************************** Find a workgroup in the workgroup list of a subnet. - **************************************************************************/ +**************************************************************************/ struct work_record *find_workgroup_on_subnet(struct subnet_record *subrec, const char *name) { - struct work_record *ret; + struct work_record *ret; - DEBUG(4, ("find_workgroup_on_subnet: workgroup search for %s on subnet %s: ", - name, subrec->subnet_name)); + DEBUG(4, ("find_workgroup_on_subnet: workgroup search for %s on subnet %s: ", + name, subrec->subnet_name)); - for (ret = subrec->workgrouplist; ret; ret = ret->next) - { - if (!strcmp(ret->work_group,name)) - { - DEBUGADD(4, ("found.\n")); - return(ret); - } - } - DEBUGADD(4, ("not found.\n")); - return NULL; + for (ret = subrec->workgrouplist; ret; ret = ret->next) { + if (strequal(ret->work_group,name)) { + DEBUGADD(4, ("found.\n")); + return(ret); + } + } + DEBUGADD(4, ("not found.\n")); + return NULL; } /**************************************************************************** Create a workgroup in the workgroup list of the subnet. - **************************************************************************/ +**************************************************************************/ struct work_record *create_workgroup_on_subnet(struct subnet_record *subrec, const char *name, int ttl) { - struct work_record *work = NULL; + struct work_record *work = NULL; - DEBUG(4,("create_workgroup_on_subnet: creating group %s on subnet %s\n", - name, subrec->subnet_name)); + DEBUG(4,("create_workgroup_on_subnet: creating group %s on subnet %s\n", + name, subrec->subnet_name)); - if ((work = create_workgroup(name, ttl))) - { - add_workgroup(subrec, work); - - subrec->work_changed = True; + if ((work = create_workgroup(name, ttl))) { + add_workgroup(subrec, work); + subrec->work_changed = True; + return(work); + } - return(work); - } - - return NULL; + return NULL; } /**************************************************************************** Update a workgroup ttl. - **************************************************************************/ +**************************************************************************/ void update_workgroup_ttl(struct work_record *work, int ttl) { - if(work->death_time != PERMANENT_TTL) - work->death_time = time(NULL)+(ttl*3); - work->subnet->work_changed = True; + if(work->death_time != PERMANENT_TTL) + work->death_time = time(NULL)+(ttl*3); + work->subnet->work_changed = True; } /**************************************************************************** @@ -210,8 +199,8 @@ void update_workgroup_ttl(struct work_record *work, int ttl) static void fail_register(struct subnet_record *subrec, struct response_record *rrec, struct nmb_name *nmbname) { - DEBUG(0,("fail_register: Failed to register name %s on subnet %s.\n", - nmb_namestr(nmbname), subrec->subnet_name)); + DEBUG(0,("fail_register: Failed to register name %s on subnet %s.\n", + nmb_namestr(nmbname), subrec->subnet_name)); } /**************************************************************************** @@ -220,50 +209,38 @@ static void fail_register(struct subnet_record *subrec, struct response_record * void initiate_myworkgroup_startup(struct subnet_record *subrec, struct work_record *work) { - int i; + int i; - if(!strequal(lp_workgroup(), work->work_group)) - return; + if(!strequal(lp_workgroup(), work->work_group)) + return; - /* If this is a broadcast subnet then start elections on it - if we are so configured. */ + /* If this is a broadcast subnet then start elections on it if we are so configured. */ - if ((subrec != unicast_subnet) && (subrec != remote_broadcast_subnet) && - (subrec != wins_server_subnet) && lp_preferred_master() && - lp_local_master()) - { - DEBUG(3, ("initiate_myworkgroup_startup: preferred master startup for \ + if ((subrec != unicast_subnet) && (subrec != remote_broadcast_subnet) && + (subrec != wins_server_subnet) && lp_preferred_master() && lp_local_master()) { + DEBUG(3, ("initiate_myworkgroup_startup: preferred master startup for \ workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name)); - work->needelection = True; - work->ElectionCriterion |= (1<<3); - } + work->needelection = True; + work->ElectionCriterion |= (1<<3); + } - /* Register the WORKGROUP<0> and WORKGROUP<1e> names on the network. */ + /* Register the WORKGROUP<0> and WORKGROUP<1e> names on the network. */ - register_name(subrec,lp_workgroup(),0x0,samba_nb_type|NB_GROUP, - NULL, - fail_register,NULL); - - register_name(subrec,lp_workgroup(),0x1e,samba_nb_type|NB_GROUP, - NULL, - fail_register,NULL); - - for( i = 0; my_netbios_names(i); i++) - { - const char *name = my_netbios_names(i); - int stype = lp_default_server_announce() | (lp_local_master() ? - SV_TYPE_POTENTIAL_BROWSER : 0 ); + register_name(subrec,lp_workgroup(),0x0,samba_nb_type|NB_GROUP, NULL, fail_register,NULL); + register_name(subrec,lp_workgroup(),0x1e,samba_nb_type|NB_GROUP, NULL, fail_register,NULL); + + for( i = 0; my_netbios_names(i); i++) { + const char *name = my_netbios_names(i); + int stype = lp_default_server_announce() | (lp_local_master() ? SV_TYPE_POTENTIAL_BROWSER : 0 ); - if(!strequal(global_myname(), name)) - stype &= ~(SV_TYPE_MASTER_BROWSER|SV_TYPE_POTENTIAL_BROWSER| - SV_TYPE_DOMAIN_MASTER|SV_TYPE_DOMAIN_MEMBER); + if(!strequal(global_myname(), name)) + stype &= ~(SV_TYPE_MASTER_BROWSER|SV_TYPE_POTENTIAL_BROWSER|SV_TYPE_DOMAIN_MASTER|SV_TYPE_DOMAIN_MEMBER); - create_server_on_workgroup(work,name,stype|SV_TYPE_LOCAL_LIST_ONLY, - PERMANENT_TTL, - string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH)); - DEBUG(3,("initiate_myworkgroup_startup: Added server name entry %s \ + create_server_on_workgroup(work,name,stype|SV_TYPE_LOCAL_LIST_ONLY, PERMANENT_TTL, + string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH)); + DEBUG(3,("initiate_myworkgroup_startup: Added server name entry %s \ on subnet %s\n", name, subrec->subnet_name)); - } + } } /**************************************************************************** @@ -272,43 +249,34 @@ on subnet %s\n", name, subrec->subnet_name)); void dump_workgroups(BOOL force_write) { - struct subnet_record *subrec; - int debuglevel = force_write ? 0 : 4; + struct subnet_record *subrec; + int debuglevel = force_write ? 0 : 4; - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - if (subrec->workgrouplist) - { - struct work_record *work; - - if( DEBUGLVL( debuglevel ) ) - { - dbgtext( "dump_workgroups()\n " ); - dbgtext( "dump workgroup on subnet %15s: ", subrec->subnet_name ); - dbgtext( "netmask=%15s:\n", inet_ntoa(subrec->mask_ip) ); - } - - for (work = subrec->workgrouplist; work; work = work->next) - { - DEBUGADD( debuglevel, ( "\t%s(%d) current master browser = %s\n", - work->work_group, - work->token, - *work->local_master_browser_name - ? work->local_master_browser_name : "UNKNOWN" ) ); - if (work->serverlist) - { - struct server_record *servrec; - for (servrec = work->serverlist; servrec; servrec = servrec->next) - { - DEBUGADD( debuglevel, ( "\t\t%s %8x (%s)\n", - servrec->serv.name, - servrec->serv.type, - servrec->serv.comment ) ); - } - } - } - } - } + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) { + if (subrec->workgrouplist) { + struct work_record *work; + + if( DEBUGLVL( debuglevel ) ) { + dbgtext( "dump_workgroups()\n " ); + dbgtext( "dump workgroup on subnet %15s: ", subrec->subnet_name ); + dbgtext( "netmask=%15s:\n", inet_ntoa(subrec->mask_ip) ); + } + + for (work = subrec->workgrouplist; work; work = work->next) { + DEBUGADD( debuglevel, ( "\t%s(%d) current master browser = %s\n", work->work_group, + work->token, *work->local_master_browser_name ? work->local_master_browser_name : "UNKNOWN" ) ); + if (work->serverlist) { + struct server_record *servrec; + for (servrec = work->serverlist; servrec; servrec = servrec->next) { + DEBUGADD( debuglevel, ( "\t\t%s %8x (%s)\n", + servrec->serv.name, + servrec->serv.type, + servrec->serv.comment ) ); + } + } + } + } + } } /**************************************************************************** @@ -318,25 +286,22 @@ void dump_workgroups(BOOL force_write) void expire_workgroups_and_servers(time_t t) { - struct subnet_record *subrec; + struct subnet_record *subrec; - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - struct work_record *work; - struct work_record *nextwork; - - for (work = subrec->workgrouplist; work; work = nextwork) - { - nextwork = work->next; - expire_servers(work, t); - - if ((work->serverlist == NULL) && (work->death_time != PERMANENT_TTL) && - ((t == -1) || (work->death_time < t))) - { - DEBUG(3,("expire_workgroups_and_servers: Removing timed out workgroup %s\n", - work->work_group)); - remove_workgroup_from_subnet(subrec, work); - } - } - } + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) { + struct work_record *work; + struct work_record *nextwork; + + for (work = subrec->workgrouplist; work; work = nextwork) { + nextwork = work->next; + expire_servers(work, t); + + if ((work->serverlist == NULL) && (work->death_time != PERMANENT_TTL) && + ((t == -1) || (work->death_time < t))) { + DEBUG(3,("expire_workgroups_and_servers: Removing timed out workgroup %s\n", + work->work_group)); + remove_workgroup_from_subnet(subrec, work); + } + } + } } diff --git a/source/param/loadparm.c b/source/param/loadparm.c index c0d0e501f3d..5d67ae91694 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -563,6 +563,7 @@ static BOOL handle_debug_list( const char *pszParmValue, char **ptr ); static BOOL handle_workgroup( const char *pszParmValue, char **ptr ); static BOOL handle_netbios_aliases( const char *pszParmValue, char **ptr ); static BOOL handle_netbios_scope( const char *pszParmValue, char **ptr ); +static BOOL handle_charset( const char *pszParmValue, char **ptr ); static BOOL handle_ldap_suffix ( const char *pszParmValue, char **ptr ); static BOOL handle_ldap_sub_suffix ( const char *pszParmValue, char **ptr ); @@ -753,9 +754,9 @@ static const struct enum_list enum_map_to_guest[] = { static struct parm_struct parm_table[] = { {"Base Options", P_SEP, P_SEPARATOR}, - {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED}, - {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED}, - {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED}, + {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, handle_charset, NULL, FLAG_ADVANCED}, + {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, handle_charset, NULL, FLAG_ADVANCED}, + {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, handle_charset, NULL, FLAG_ADVANCED}, {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE}, @@ -2701,7 +2702,6 @@ static BOOL handle_netbios_name(const char *pszParmValue, char **ptr) standard_sub_basic(current_user_info.smb_name, netbios_name,sizeof(netbios_name)); - ret = set_global_myname(netbios_name); string_set(&Globals.szNetbiosName,global_myname()); @@ -2711,6 +2711,13 @@ static BOOL handle_netbios_name(const char *pszParmValue, char **ptr) return ret; } +static BOOL handle_charset(const char *pszParmValue, char **ptr) +{ + string_set(ptr, pszParmValue); + init_iconv(); + return True; +} + static BOOL handle_workgroup(const char *pszParmValue, char **ptr) { BOOL ret; |