summaryrefslogtreecommitdiff
path: root/source3/nmbd/nmbd_packets.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2002-06-27 14:37:17 +0000
committerAndrew Tridgell <tridge@samba.org>2002-06-27 14:37:17 +0000
commit223ddc3f2daf25b16ce60230336747d5fab61e39 (patch)
tree66fc3123346244d5cc7b0dd47274b214fa1d104d /source3/nmbd/nmbd_packets.c
parent675a108c65834f9402d967926b30e50e811843c1 (diff)
downloadsamba-223ddc3f2daf25b16ce60230336747d5fab61e39.tar.gz
samba-223ddc3f2daf25b16ce60230336747d5fab61e39.tar.bz2
samba-223ddc3f2daf25b16ce60230336747d5fab61e39.zip
The next phase in the WINS rewrite!
We now cope wiith multiple WINS groups and multiple failover servers for release and refresh as well as registration. We also do the regitrations in the same fashion as W2K does, where we don't try to register the next IP in the list for a name until the WINS server has acked the previos IP. This prevents us flooding the WINS server and also seems to make for much more reliable multi-homed registration. I also changed the dead WINS server code to mark pairs of IPs dead, not individual IPs. The idea is that a WINS server might be dead from the point of view of one of our interfaces, but not another, so we need to keep talking to it on one while moving onto a failover WINS server on the other interface. This copes much better with partial LAN outages and weird routing tables. (This used to be commit 313f2c9ff7a513802e4f893324865e70912d419e)
Diffstat (limited to 'source3/nmbd/nmbd_packets.c')
-rw-r--r--source3/nmbd/nmbd_packets.c232
1 files changed, 122 insertions, 110 deletions
diff --git a/source3/nmbd/nmbd_packets.c b/source3/nmbd/nmbd_packets.c
index f0c8b755c9..64b63627d7 100644
--- a/source3/nmbd/nmbd_packets.c
+++ b/source3/nmbd/nmbd_packets.c
@@ -237,48 +237,44 @@ static BOOL create_and_init_additional_record(struct packet_struct *packet,
uint16 nb_flags,
struct in_addr *register_ip)
{
- struct nmb_packet *nmb = &packet->packet.nmb;
-
- if((nmb->additional = (struct res_rec *)malloc(sizeof(struct res_rec))) == NULL)
- {
- DEBUG(0,("initiate_name_register_packet: malloc fail for additional record.\n"));
- return False;
- }
-
- memset((char *)nmb->additional,'\0',sizeof(struct res_rec));
-
- nmb->additional->rr_name = nmb->question.question_name;
- nmb->additional->rr_type = RR_TYPE_NB;
- nmb->additional->rr_class = RR_CLASS_IN;
-
- /* See RFC 1002, sections 5.1.1.1, 5.1.1.2 and 5.1.1.3 */
- if (nmb->header.nm_flags.bcast)
- nmb->additional->ttl = PERMANENT_TTL;
- else
- nmb->additional->ttl = lp_max_ttl();
-
- nmb->additional->rdlength = 6;
-
- set_nb_flags(nmb->additional->rdata,nb_flags);
-
- /* Set the address for the name we are registering. */
- putip(&nmb->additional->rdata[2], register_ip);
+ struct nmb_packet *nmb = &packet->packet.nmb;
-#if 0
- /* I removed this forced source IP as it breaks wins failover. The
- problem is that our 2nd interface IP may not be routable to the
- wins server, in which case all these nice packets we are senidng
- out will never get a response and we end up marking a perfectly good wins server dead.
+ if((nmb->additional = (struct res_rec *)malloc(sizeof(struct res_rec))) == NULL) {
+ DEBUG(0,("initiate_name_register_packet: malloc fail for additional record.\n"));
+ return False;
+ }
- In general I can't see any reason why we should force the source
- ip on a packet anyway. We should just let the kernels routin
- table take care of it, as that is the only place which really
- knows what is routable and what isn't. (tridge)
- */
- packet->fd = find_subnet_fd_for_address( *register_ip );
-#endif
+ memset((char *)nmb->additional,'\0',sizeof(struct res_rec));
- return True;
+ nmb->additional->rr_name = nmb->question.question_name;
+ nmb->additional->rr_type = RR_TYPE_NB;
+ nmb->additional->rr_class = RR_CLASS_IN;
+
+ /* See RFC 1002, sections 5.1.1.1, 5.1.1.2 and 5.1.1.3 */
+ if (nmb->header.nm_flags.bcast)
+ nmb->additional->ttl = PERMANENT_TTL;
+ else
+ nmb->additional->ttl = lp_max_ttl();
+
+ nmb->additional->rdlength = 6;
+
+ set_nb_flags(nmb->additional->rdata,nb_flags);
+
+ /* Set the address for the name we are registering. */
+ putip(&nmb->additional->rdata[2], register_ip);
+
+ /*
+ it turns out that Jeremys code was correct, we are supposed
+ to send registrations from the IP we are registering. The
+ trick is what to do on timeouts! When we send on a
+ non-routable IP then the reply will timeout, and we should
+ treat this as success, not failure. That means we go into
+ our standard refresh cycle for that name which copes nicely
+ with disconnected networks.
+ */
+ packet->fd = find_subnet_fd_for_address(*register_ip);
+
+ return True;
}
/***************************************************************************
@@ -353,28 +349,28 @@ static BOOL initiate_name_register_packet( struct packet_struct *packet,
Sends out a multihomed name register.
**************************************************************************/
-static BOOL initiate_multihomed_name_register_packet( struct packet_struct *packet,
- uint16 nb_flags, struct in_addr *register_ip)
+static BOOL initiate_multihomed_name_register_packet(struct packet_struct *packet,
+ uint16 nb_flags, struct in_addr *register_ip)
{
- struct nmb_packet *nmb = &packet->packet.nmb;
- fstring second_ip_buf;
+ struct nmb_packet *nmb = &packet->packet.nmb;
+ fstring second_ip_buf;
- fstrcpy(second_ip_buf, inet_ntoa(packet->ip));
+ fstrcpy(second_ip_buf, inet_ntoa(packet->ip));
- nmb->header.opcode = NMB_NAME_MULTIHOMED_REG_OPCODE;
- nmb->header.arcount = 1;
+ nmb->header.opcode = NMB_NAME_MULTIHOMED_REG_OPCODE;
+ nmb->header.arcount = 1;
- nmb->header.nm_flags.recursion_desired = True;
-
- if(create_and_init_additional_record(packet, nb_flags, register_ip) == False)
- return False;
-
- DEBUG(4,("initiate_multihomed_name_register_packet: sending registration \
+ nmb->header.nm_flags.recursion_desired = True;
+
+ if(create_and_init_additional_record(packet, nb_flags, register_ip) == False)
+ return False;
+
+ DEBUG(4,("initiate_multihomed_name_register_packet: sending registration \
for name %s IP %s (bcast=%s) to IP %s\n",
- nmb_namestr(&nmb->additional->rr_name), inet_ntoa(*register_ip),
- BOOLSTR(nmb->header.nm_flags.bcast), second_ip_buf ));
+ nmb_namestr(&nmb->additional->rr_name), inet_ntoa(*register_ip),
+ BOOLSTR(nmb->header.nm_flags.bcast), second_ip_buf ));
- return send_netbios_packet( packet );
+ return send_netbios_packet( packet );
}
/***************************************************************************
@@ -518,6 +514,67 @@ struct response_record *queue_register_name( struct subnet_record *subrec,
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,
+ uint16 nb_flags,
+ struct in_addr refresh_ip,
+ const char *tag)
+{
+ struct packet_struct *p;
+ struct response_record *rrec;
+ struct in_addr wins_ip;
+ struct userdata_struct *userdata;
+ fstring ip_str;
+
+ wins_ip = wins_srv_ip_tag(tag, refresh_ip);
+
+ if ((p = create_and_init_netbios_packet(nmbname, False, False, wins_ip)) == NULL) {
+ return;
+ }
+
+ if (!initiate_name_refresh_packet(p, nb_flags, &refresh_ip)) {
+ p->locked = False;
+ free_packet(p);
+ return;
+ }
+
+ fstrcpy(ip_str, inet_ntoa(refresh_ip));
+
+ DEBUG(6,("Refreshing name %s IP %s with WINS server %s using tag '%s'\n",
+ nmb_namestr(nmbname), ip_str, inet_ntoa(wins_ip), tag));
+
+ 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);
+
+ if ((rrec = make_response_record(unicast_subnet,
+ p,
+ resp_fn, timeout_fn,
+ NULL,
+ NULL,
+ userdata)) == NULL) {
+ p->locked = False;
+ free_packet(p);
+ return;
+ }
+
+ free(userdata);
+
+ /* we don't want to repeat refresh packets */
+ rrec->repeat_count = 0;
+}
+
+
/****************************************************************************
Queue a multihomed register name packet to a given WINS server IP
****************************************************************************/
@@ -581,14 +638,15 @@ unicast subnet. subnet is %s\n.", subrec->subnet_name ));
****************************************************************************/
struct response_record *queue_release_name( struct subnet_record *subrec,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- release_name_success_function success_fn,
- release_name_fail_function fail_fn,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname,
- uint16 nb_flags,
- struct in_addr release_ip)
+ response_function resp_fn,
+ timeout_response_function timeout_fn,
+ release_name_success_function success_fn,
+ release_name_fail_function fail_fn,
+ struct userdata_struct *userdata,
+ struct nmb_name *nmbname,
+ uint16 nb_flags,
+ struct in_addr release_ip,
+ struct in_addr dest_ip)
{
struct packet_struct *p;
struct response_record *rrec;
@@ -597,7 +655,7 @@ struct response_record *queue_release_name( struct subnet_record *subrec,
return NULL;
if ((p = create_and_init_netbios_packet(nmbname, (subrec != unicast_subnet), False,
- subrec->bcast_ip)) == NULL)
+ dest_ip)) == NULL)
return NULL;
if(initiate_name_release_packet( p, nb_flags, &release_ip) == False)
@@ -634,52 +692,6 @@ struct response_record *queue_release_name( struct subnet_record *subrec,
}
/****************************************************************************
- Queue a refresh name packet to the broadcast address of a subnet.
-****************************************************************************/
-
-struct response_record *queue_refresh_name( struct subnet_record *subrec,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- refresh_name_success_function success_fn,
- refresh_name_fail_function fail_fn,
- struct userdata_struct *userdata,
- struct name_record *namerec,
- struct in_addr refresh_ip)
-{
- struct packet_struct *p;
- struct response_record *rrec;
-
- if(assert_check_subnet(subrec))
- return NULL;
-
- if(( p = create_and_init_netbios_packet(&namerec->name, (subrec != unicast_subnet), False,
- subrec->bcast_ip)) == NULL)
- return NULL;
-
- if( !initiate_name_refresh_packet( p, namerec->data.nb_flags, &refresh_ip ) )
- {
- 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 query name packet to the broadcast address of a subnet.
****************************************************************************/