summaryrefslogtreecommitdiffstats
path: root/source/nmbd/nmbd_nameregister.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/nmbd/nmbd_nameregister.c')
-rw-r--r--source/nmbd/nmbd_nameregister.c792
1 files changed, 334 insertions, 458 deletions
diff --git a/source/nmbd/nmbd_nameregister.c b/source/nmbd/nmbd_nameregister.c
index b6d3c20d995..c3361cec60b 100644
--- a/source/nmbd/nmbd_nameregister.c
+++ b/source/nmbd/nmbd_nameregister.c
@@ -1,5 +1,6 @@
/*
- Unix SMB/CIFS implementation.
+ Unix SMB/Netbios implementation.
+ Version 1.9.
NBT netbios routines and daemon - version 2
Copyright (C) Andrew Tridgell 1994-1998
Copyright (C) Luke Kenneth Casson Leighton 1994-1998
@@ -25,10 +26,6 @@
extern fstring global_myworkgroup;
-/* forward declarations */
-static void wins_next_registration(struct response_record *rrec);
-
-
/****************************************************************************
Deal with a response packet when registering one of our names.
****************************************************************************/
@@ -36,489 +33,368 @@ static void wins_next_registration(struct response_record *rrec);
static void register_name_response(struct subnet_record *subrec,
struct response_record *rrec, struct packet_struct *p)
{
- /*
- * If we are registering broadcast, then getting a response is an
- * error - we do not have the name. If we are registering unicast,
- * then we expect to get a response.
- */
-
- struct nmb_packet *nmb = &p->packet.nmb;
- BOOL bcast = nmb->header.nm_flags.bcast;
- BOOL success = True;
- struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
- struct nmb_name *answer_name = &nmb->answers->rr_name;
- struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
- int ttl = 0;
- uint16 nb_flags = 0;
- struct in_addr register_ip;
- fstring reg_name;
-
- putip(&register_ip,&sent_nmb->additional->rdata[2]);
- fstrcpy(reg_name, inet_ntoa(register_ip));
-
- if (subrec == unicast_subnet) {
- /* we know that this wins server is definately alive - for the moment! */
- wins_srv_alive(rrec->packet->ip, register_ip);
- }
-
- /* Sanity check. Ensure that the answer name in the incoming packet is the
- same as the requested name in the outgoing packet. */
-
- if(!question_name || !answer_name) {
- DEBUG(0,("register_name_response: malformed response (%s is NULL).\n",
- question_name ? "question_name" : "answer_name" ));
- return;
- }
-
- if(!nmb_name_equal(question_name, answer_name)) {
- DEBUG(0,("register_name_response: Answer name %s differs from question name %s.\n",
- nmb_namestr(answer_name), nmb_namestr(question_name)));
- return;
- }
-
- if(bcast) {
- /*
- * Special hack to cope with old Samba nmbd's.
- * Earlier versions of Samba (up to 1.9.16p11) respond
- * to a broadcast name registration of WORKGROUP<1b> when
- * they should not. Hence, until these versions are gone,
- * we should treat such errors as success for this particular
- * case only. jallison@whistle.com.
- */
-
+ /*
+ * If we are registering broadcast, then getting a response is an
+ * error - we do not have the name. If we are registering unicast,
+ * then we expect to get a response.
+ */
+
+ struct nmb_packet *nmb = &p->packet.nmb;
+ BOOL bcast = nmb->header.nm_flags.bcast;
+ BOOL success = True;
+ struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
+ struct nmb_name *answer_name = &nmb->answers->rr_name;
+ int ttl = 0;
+ uint16 nb_flags = 0;
+ struct in_addr registered_ip;
+
+ /* Sanity check. Ensure that the answer name in the incoming packet is the
+ same as the requested name in the outgoing packet. */
+
+ if(!question_name || !answer_name)
+ {
+ DEBUG(0,("register_name_response: malformed response (%s is NULL).\n",
+ question_name ? "question_name" : "answer_name" ));
+ return;
+ }
+
+ if(!nmb_name_equal(question_name, answer_name))
+ {
+ DEBUG(0,("register_name_response: Answer name %s differs from question \
+name %s.\n", nmb_namestr(answer_name), nmb_namestr(question_name)));
+ return;
+ }
+
+ if(bcast)
+ {
+ /*
+ * Special hack to cope with old Samba nmbd's.
+ * Earlier versions of Samba (up to 1.9.16p11) respond
+ * to a broadcast name registration of WORKGROUP<1b> when
+ * they should not. Hence, until these versions are gone,
+ * we should treat such errors as success for this particular
+ * case only. jallison@whistle.com.
+ */
+
#if 1 /* OLD_SAMBA_SERVER_HACK */
- if((nmb->header.rcode == ACT_ERR) && strequal(global_myworkgroup, answer_name->name) &&
- (answer_name->name_type == 0x1b)) {
- /* Pretend we did not get this. */
- rrec->num_msgs--;
-
- DEBUG(5,("register_name_response: Ignoring broadcast response to registration of name %s due to old Samba server bug.\n",
- nmb_namestr(answer_name)));
- return;
- }
+ if((nmb->header.rcode == ACT_ERR) && strequal(global_myworkgroup, answer_name->name) &&
+ (answer_name->name_type == 0x1b))
+ {
+ /* Pretend we did not get this. */
+ rrec->num_msgs--;
+
+ DEBUG(5,("register_name_response: Ignoring broadcast response to \
+registration of name %s due to old Samba server bug.\n", nmb_namestr(answer_name)));
+ return;
+ }
#endif /* OLD_SAMBA_SERVER_HACK */
- /* Someone else has the name. Log the problem. */
- DEBUG(1,("register_name_response: Failed to register name %s IP %s on subnet %s via broadcast. Error code was %d. Reject came from IP %s\n",
- nmb_namestr(answer_name),
- reg_name,
- subrec->subnet_name, nmb->header.rcode, inet_ntoa(p->ip)));
- success = False;
- } else {
- /* Unicast - check to see if the response allows us to have the name. */
- 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 register requests. */
-
- DEBUG(5,("register_name_response: WACK from WINS server %s in registering name %s IP %s\n",
- inet_ntoa(p->ip), nmb_namestr(answer_name), reg_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) {
- /* Error code - we didn't get the name. */
- success = False;
-
- DEBUG(0,("register_name_response: %sserver at IP %s rejected our name registration of %s IP %s with error code %d.\n",
- subrec==unicast_subnet?"WINS ":"",
- inet_ntoa(p->ip),
- nmb_namestr(answer_name),
- reg_name,
- nmb->header.rcode));
- } else {
- success = True;
- /* Get the data we need to pass to the success function. */
- nb_flags = get_nb_flags(nmb->answers->rdata);
- ttl = nmb->answers->ttl;
-
- /* send off a registration for the next IP, if any */
- wins_next_registration(rrec);
- }
- }
-
- DEBUG(5,("register_name_response: %s in registering %sname %s IP %s with %s.\n",
- success ? "success" : "failure",
- subrec==unicast_subnet?"WINS ":"",
- nmb_namestr(answer_name),
- reg_name,
- inet_ntoa(rrec->packet->ip)));
-
- if(success) {
- /* Enter the registered name into the subnet name database before calling
- the success function. */
- standard_success_register(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip);
- if( rrec->success_fn)
- (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip);
- } else {
- if( rrec->fail_fn)
- (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
- /* Remove the name. */
- standard_fail_register( subrec, rrec, question_name);
- }
-
- /* Ensure we don't retry. */
- remove_response_record(subrec, rrec);
+ /* Someone else has the name. Log the problem. */
+ DEBUG(1,("register_name_response: Failed to register \
+name %s on subnet %s via broadcast. Error code was %d. Reject came from IP %s\n",
+ nmb_namestr(answer_name),
+ subrec->subnet_name, nmb->header.rcode, inet_ntoa(p->ip)));
+ success = False;
+ }
+ else
+ {
+ /* Unicast - check to see if the response allows us to have the name. */
+ if(nmb->header.rcode != 0)
+ {
+ /* Error code - we didn't get the name. */
+ success = False;
+
+ DEBUG(0,("register_name_response: server at IP %s rejected our \
+name registration of %s with error code %d.\n", inet_ntoa(p->ip),
+ nmb_namestr(answer_name), nmb->header.rcode));
+
+ }
+ else 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 register requests. */
+
+ DEBUG(5,("register_name_response: WACK from WINS server %s in registering \
+name %s on subnet %s.\n", inet_ntoa(p->ip), nmb_namestr(answer_name), 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
+ {
+ success = True;
+ /* Get the data we need to pass to the success function. */
+ nb_flags = get_nb_flags(nmb->answers->rdata);
+ putip((char*)&registered_ip,&nmb->answers->rdata[2]);
+ ttl = nmb->answers->ttl;
+ }
+ }
+
+ DEBUG(5,("register_name_response: %s in registering name %s on subnet %s.\n",
+ success ? "success" : "failure", nmb_namestr(answer_name), subrec->subnet_name));
+
+ if(success)
+ {
+ /* Enter the registered name into the subnet name database before calling
+ the success function. */
+ standard_success_register(subrec, rrec->userdata, answer_name, nb_flags, ttl, registered_ip);
+ if( rrec->success_fn)
+ (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, answer_name, nb_flags, ttl, registered_ip);
+ }
+ else
+ {
+ if( rrec->fail_fn)
+ (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
+ /* Remove the name. */
+ standard_fail_register( subrec, rrec, question_name);
+ }
+
+ /* Ensure we don't retry. */
+ 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)
-{
- struct userdata_struct *userdata = rrec->userdata;
- struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
- struct nmb_name *nmbname = &sent_nmb->question.question_name;
- struct in_addr register_ip;
- fstring src_addr;
-
- putip(&register_ip,&sent_nmb->additional->rdata[2]);
-
- fstrcpy(src_addr, inet_ntoa(register_ip));
-
- DEBUG(2,("wins_registration_timeout: WINS server %s timed out registering IP %s\n",
- inet_ntoa(rrec->packet->ip), src_addr));
-
- /* mark it temporarily dead for this source address */
- wins_srv_died(rrec->packet->ip, register_ip);
-
- /* if we have some userdata then use that to work out what
- wins server to try next */
- if (userdata) {
- const char *tag = (const char *)userdata->data;
-
- /* try the next wins server in our failover list for
- this tag */
- rrec->packet->ip = wins_srv_ip_tag(tag, register_ip);
- }
-
- /* if we have run out of wins servers for this tag then they
- must all have timed out. We treat this as *success*, not
- failure, and go into our standard name refresh mode. This
- copes with all the wins servers being down */
- if (wins_srv_is_dead(rrec->packet->ip, register_ip)) {
- uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata);
- int ttl = sent_nmb->additional->ttl;
-
- standard_success_register(subrec, userdata, nmbname, nb_flags, ttl, register_ip);
- if(rrec->success_fn) {
- (*(register_name_success_function)rrec->success_fn)(subrec,
- rrec->userdata,
- nmbname,
- nb_flags,
- ttl,
- register_ip);
- }
-
- /* send off a registration for the next IP, if any */
- wins_next_registration(rrec);
-
- /* don't need to send this packet any more */
- remove_response_record(subrec, rrec);
- return;
- }
-
- /* we will be moving to the next WINS server for this group,
- send it immediately */
- rrec->repeat_count = 2;
- rrec->repeat_time = time(NULL) + 1;
- rrec->in_expiration_processing = False;
-
- DEBUG(6,("Retrying register of name %s IP %s with WINS server %s\n",
- nmb_namestr(nmbname), src_addr, inet_ntoa(rrec->packet->ip)));
-
- /* notice that we don't remove the response record. This keeps
- us trying to register with each of our failover wins servers */
-}
-
-
/****************************************************************************
Deal with a timeout when registering one of our names.
****************************************************************************/
static void register_name_timeout_response(struct subnet_record *subrec,
- struct response_record *rrec)
-{
- /*
- * If we are registering unicast, then NOT getting a response is an
- * error - we do not have the name. If we are registering broadcast,
- * then we don't expect to get a response.
- */
-
- struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
- BOOL bcast = sent_nmb->header.nm_flags.bcast;
- BOOL success = False;
- struct nmb_name *question_name = &sent_nmb->question.question_name;
- uint16 nb_flags = 0;
- int ttl = 0;
- struct in_addr registered_ip;
-
- if (bcast) {
- if(rrec->num_msgs == 0) {
- /* Not receiving a message is success for broadcast registration. */
- success = True;
-
- /* Pull the success values from the original request packet. */
- nb_flags = get_nb_flags(sent_nmb->additional->rdata);
- ttl = sent_nmb->additional->ttl;
- putip(&registered_ip,&sent_nmb->additional->rdata[2]);
- }
- } else {
- /* wins timeouts are special */
- wins_registration_timeout(subrec, rrec);
- return;
- }
-
- DEBUG(5,("register_name_timeout_response: %s in registering name %s on subnet %s.\n",
- success ? "success" : "failure", nmb_namestr(question_name), subrec->subnet_name));
- if(success) {
- /* Enter the registered name into the subnet name database before calling
- the success function. */
- standard_success_register(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
- if( rrec->success_fn)
- (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
- } else {
- if( rrec->fail_fn)
- (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
- /* Remove the name. */
- standard_fail_register( subrec, rrec, question_name);
- }
-
- /* Ensure we don't retry. */
- remove_response_record(subrec, rrec);
-}
-
-
-/****************************************************************************
-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,
- register_name_fail_function fail_fn,
- struct in_addr ip,
- const char *tag)
-{
- struct userdata_struct *userdata;
- struct in_addr wins_ip = wins_srv_ip_tag(tag, ip);
- fstring ip_str;
-
- userdata = (struct userdata_struct *)malloc(sizeof(*userdata) + strlen(tag) + 1);
- if (!userdata) {
- DEBUG(0,("Failed to allocate userdata structure!\n"));
- return;
- }
- ZERO_STRUCTP(userdata);
- userdata->userdata_len = strlen(tag) + 1;
- strlcpy(userdata->data, tag, userdata->userdata_len);
-
- fstrcpy(ip_str, inet_ntoa(ip));
-
- DEBUG(6,("Registering name %s IP %s with WINS server %s using tag '%s'\n",
- nmb_namestr(nmbname), ip_str, inet_ntoa(wins_ip), tag));
-
- if (queue_register_multihomed_name(unicast_subnet,
- register_name_response,
- register_name_timeout_response,
- success_fn,
- fail_fn,
- userdata,
- nmbname,
- nb_flags,
- ip,
- wins_ip) == NULL) {
- DEBUG(0,("multihomed_register_one: Failed to send packet trying to register name %s IP %s\n",
- nmb_namestr(nmbname), inet_ntoa(ip)));
- }
-
- 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
-****************************************************************************/
-static void wins_next_registration(struct response_record *rrec)
+ struct response_record *rrec)
{
- struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
- struct nmb_name *nmbname = &sent_nmb->question.question_name;
- uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata);
- struct userdata_struct *userdata = rrec->userdata;
- const char *tag;
- struct in_addr last_ip;
- struct subnet_record *subrec;
-
- putip(&last_ip,&sent_nmb->additional->rdata[2]);
-
- if (!userdata) {
- /* it wasn't multi-homed */
- return;
- }
-
- tag = (const char *)userdata->data;
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
- if (ip_equal(last_ip, subrec->myip)) {
- subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec);
- break;
- }
- }
-
- if (!subrec) {
- /* no more to do! */
- return;
- }
-
- switch (sent_nmb->header.opcode) {
- case NMB_NAME_MULTIHOMED_REG_OPCODE:
- multihomed_register_one(nmbname, nb_flags, NULL, NULL, subrec->myip, tag);
- break;
- case NMB_NAME_REFRESH_OPCODE_8:
- queue_wins_refresh(nmbname,
- register_name_response,
- register_name_timeout_response,
- nb_flags, subrec->myip, tag);
- break;
- }
+ /*
+ * If we are registering unicast, then NOT getting a response is an
+ * error - we do not have the name. If we are registering broadcast,
+ * then we don't expect to get a response.
+ */
+
+ struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
+ BOOL bcast = sent_nmb->header.nm_flags.bcast;
+ BOOL success = False;
+ struct nmb_name *question_name = &sent_nmb->question.question_name;
+ uint16 nb_flags = 0;
+ int ttl = 0;
+ struct in_addr registered_ip;
+
+ if(bcast)
+ {
+ if(rrec->num_msgs == 0)
+ {
+ /* Not receiving a message is success for broadcast registration. */
+ success = True;
+
+ /* Pull the success values from the original request packet. */
+ nb_flags = get_nb_flags(sent_nmb->additional->rdata);
+ ttl = sent_nmb->additional->ttl;
+ putip(&registered_ip,&sent_nmb->additional->rdata[2]);
+ }
+ }
+ else
+ {
+ /* Unicast - if no responses then it's an error. */
+ if(rrec->num_msgs == 0)
+ {
+ DEBUG(2,("register_name_timeout_response: WINS server at address %s is not \
+responding.\n", inet_ntoa(rrec->packet->ip)));
+
+ /* Keep trying to contact the WINS server periodically. This allows
+ us to work correctly if the WINS server is down temporarily when
+ we come up. */
+
+ /* Reset the number of attempts to zero and double the interval between
+ retries. Max out at 5 minutes. */
+ rrec->repeat_count = 3;
+ rrec->repeat_interval *= 2;
+ if(rrec->repeat_interval > (5 * 60))
+ rrec->repeat_interval = (5 * 60);
+ rrec->repeat_time = time(NULL) + rrec->repeat_interval;
+ rrec->in_expiration_processing = False;
+
+ DEBUG(5,("register_name_timeout_response: increasing WINS timeout to %d seconds.\n",
+ (int)rrec->repeat_interval));
+ return; /* Don't remove the response record. */
+ }
+ }
+
+ DEBUG(5,("register_name_timeout_response: %s in registering name %s on subnet %s.\n",
+ success ? "success" : "failure", nmb_namestr(question_name), subrec->subnet_name));
+ if(success)
+ {
+ /* Enter the registered name into the subnet name database before calling
+ the success function. */
+ standard_success_register(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
+ if( rrec->success_fn)
+ (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
+ }
+ else
+ {
+ if( rrec->fail_fn)
+ (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
+ /* Remove the name. */
+ standard_fail_register( subrec, rrec, question_name);
+ }
+
+ /* Ensure we don't retry. */
+ remove_response_record(subrec, 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)
+
+static BOOL multihomed_register_name( struct nmb_name *nmbname, uint16 nb_flags,
+ register_name_success_function success_fn,
+ register_name_fail_function fail_fn,
+ struct userdata_struct *userdata)
{
- /*
- If we are adding a group name, we just send multiple
- register name packets to the WINS server (this is an
- internet group name.
-
- If we are adding a unique name, We need first to add
- our names to the unicast subnet namelist. This is
- because when a WINS server receives a multihomed
- registration request, the first thing it does is to
- send a name query to the registering machine, to see
- if it has put the name in it's local namelist.
- We need the name there so the query response code in
- nmbd_incomingrequests.c will find it.
-
- We are adding this name prematurely (we don't really
- have it yet), but as this is on the unicast subnet
- only we will get away with this (only the WINS server
- will ever query names from us on this subnet).
- */
- int num_ips=0;
- int i, t;
- struct subnet_record *subrec;
- char **wins_tags;
- struct in_addr *ip_list;
-
- for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) )
- num_ips++;
-
- if((ip_list = (struct in_addr *)malloc(num_ips * sizeof(struct in_addr)))==NULL) {
- DEBUG(0,("multihomed_register_name: malloc fail !\n"));
- return;
- }
-
- for (subrec = FIRST_SUBNET, i = 0;
- subrec;
- subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec), i++ ) {
- ip_list[i] = subrec->myip;
- }
-
- add_name_to_subnet(unicast_subnet, nmbname->name, nmbname->name_type,
- nb_flags, lp_max_ttl(), SELF_NAME,
- num_ips, ip_list);
-
- /* get the list of wins tags - we try to register for each of them */
- wins_tags = wins_srv_tags();
-
- /* Now try and register the name for each wins tag. Note that
- at this point we only register our first IP with each wins
- group. We will register the rest from
- wins_next_registration() when we get the reply for this
- one. That follows the way W2K does things (tridge)
- */
- for (t=0; wins_tags && wins_tags[t]; t++) {
- multihomed_register_one(nmbname, nb_flags,
- success_fn, fail_fn,
- ip_list[0],
- wins_tags[t]);
- }
-
- wins_srv_tags_free(wins_tags);
-
- SAFE_FREE(ip_list);
+ /*
+ If we are adding a group name, we just send multiple
+ register name packets to the WINS server (this is an
+ internet group name.
+
+ If we are adding a unique name, We need first to add
+ our names to the unicast subnet namelist. This is
+ because when a WINS server receives a multihomed
+ registration request, the first thing it does is to
+ send a name query to the registering machine, to see
+ if it has put the name in it's local namelist.
+ We need the name there so the query response code in
+ nmbd_incomingrequests.c will find it.
+
+ We are adding this name prematurely (we don't really
+ have it yet), but as this is on the unicast subnet
+ only we will get away with this (only the WINS server
+ will ever query names from us on this subnet).
+ */
+
+ int num_ips=0;
+ int i;
+ struct in_addr *ip_list = NULL;
+ struct subnet_record *subrec;
+
+ for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) )
+ num_ips++;
+
+ if((ip_list = (struct in_addr *)malloc(num_ips * sizeof(struct in_addr)))==NULL)
+ {
+ DEBUG(0,("multihomed_register_name: malloc fail !\n"));
+ return True;
+ }
+
+ for( subrec = FIRST_SUBNET, i = 0;
+ subrec;
+ subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec), i++ )
+ ip_list[i] = subrec->myip;
+
+ (void)add_name_to_subnet( unicast_subnet, nmbname->name, nmbname->name_type,
+ nb_flags, lp_max_ttl(), SELF_NAME,
+ num_ips, ip_list);
+
+ /* Now try and register the name, num_ips times. On the last time use
+ the given success and fail functions. */
+
+ for( i = 0; i < num_ips; i++)
+ {
+ if(queue_register_multihomed_name( unicast_subnet,
+ register_name_response,
+ register_name_timeout_response,
+ (i == num_ips - 1) ? success_fn : NULL,
+ (i == num_ips - 1) ? fail_fn : NULL,
+ (i == num_ips - 1) ? userdata : NULL,
+ nmbname,
+ nb_flags,
+ ip_list[i]) == NULL)
+ {
+ DEBUG(0,("multihomed_register_name: Failed to send packet trying to \
+register name %s IP %s\n", nmb_namestr(nmbname), inet_ntoa(ip_list[i]) ));
+
+ SAFE_FREE(ip_list);
+ return True;
+ }
+ }
+
+ SAFE_FREE(ip_list);
+
+ return False;
}
-
/****************************************************************************
Try and register one of our names.
****************************************************************************/
-void register_name(struct subnet_record *subrec,
+
+BOOL register_name(struct subnet_record *subrec,
char *name, int type, uint16 nb_flags,
register_name_success_function success_fn,
register_name_fail_function fail_fn,
struct userdata_struct *userdata)
{
- struct nmb_name nmbname;
-
- make_nmb_name(&nmbname, name, type);
-
- /* Always set the NB_ACTIVE flag on the name we are
- registering. Doesn't make sense without it.
- */
-
- nb_flags |= NB_ACTIVE;
-
- if (subrec == unicast_subnet) {
- /* we now always do multi-homed registration if we are
- registering to a WINS server. This copes much
- better with complex WINS setups */
- multihomed_register_name(&nmbname, nb_flags,
- success_fn, fail_fn);
- return;
- }
-
- if (queue_register_name(subrec,
- register_name_response,
- register_name_timeout_response,
- success_fn,
- fail_fn,
- userdata,
- &nmbname,
- nb_flags) == NULL) {
- DEBUG(0,("register_name: Failed to send packet trying to register name %s\n",
- nmb_namestr(&nmbname)));
- }
+ struct nmb_name nmbname;
+
+ make_nmb_name(&nmbname, name, type);
+
+ /* Always set the NB_ACTIVE flag on the name we are
+ registering. Doesn't make sense without it.
+ */
+
+ nb_flags |= NB_ACTIVE;
+
+ /* If this is the unicast subnet, and we are a multi-homed
+ host, then register a multi-homed name. */
+
+ if( (subrec == unicast_subnet) && we_are_multihomed())
+ return multihomed_register_name(&nmbname, nb_flags,
+ success_fn, fail_fn,
+ userdata);
+
+ if(queue_register_name( subrec,
+ register_name_response,
+ register_name_timeout_response,
+ success_fn,
+ fail_fn,
+ userdata,
+ &nmbname,
+ nb_flags) == NULL)
+ {
+ DEBUG(0,("register_name: Failed to send packet trying to register name %s\n",
+ nmb_namestr(&nmbname)));
+ return True;
+ }
+ return False;
}
-
/****************************************************************************
- Try and refresh one of our names. This is *only* called for WINS refresh
+ Try and refresh one of our names.
****************************************************************************/
-void wins_refresh_name(struct name_record *namerec)
-{
- int t;
- char **wins_tags;
- /* get the list of wins tags - we try to refresh for each of them */
- wins_tags = wins_srv_tags();
-
- for (t=0; wins_tags && wins_tags[t]; t++) {
- queue_wins_refresh(&namerec->name,
- register_name_response,
- register_name_timeout_response,
- namerec->data.nb_flags,
- namerec->data.ip[0], wins_tags[t]);
- }
-
- wins_srv_tags_free(wins_tags);
+BOOL refresh_name(struct subnet_record *subrec, struct name_record *namerec,
+ refresh_name_success_function success_fn,
+ refresh_name_fail_function fail_fn,
+ struct userdata_struct *userdata)
+{
+ int i;
+
+ /*
+ * Go through and refresh the name for all known ip addresses.
+ * Only call the success/fail function on the last one (it should
+ * only be done once).
+ */
+
+ for( i = 0; i < namerec->data.num_ips; i++)
+ {
+ if(queue_refresh_name( subrec,
+ register_name_response,
+ register_name_timeout_response,
+ (i == (namerec->data.num_ips - 1)) ? success_fn : NULL,
+ (i == (namerec->data.num_ips - 1)) ? fail_fn : NULL,
+ (i == (namerec->data.num_ips - 1)) ? userdata : NULL,
+ namerec,
+ namerec->data.ip[i]) == NULL)
+ {
+ DEBUG(0,("refresh_name: Failed to send packet trying to refresh name %s\n",
+ nmb_namestr(&namerec->name)));
+ return True;
+ }
+ }
+ return False;
}