From 5a2f52b79e28530c454cb488a44588147640f061 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 2 Oct 1996 14:09:22 +0000 Subject: - a huge pile of changes from Luke which implement the browse.conf stuff and also fix a pile of nmbd bugs. Unfortunately I found it very hard to disentangle the new features from the bug fixes so I am putting in the new code. I hope this is the last big pile of changes to the 1.9.16 series! (This used to be commit 20b6203dac4bbb43e4e7bea0b214496d76d679d9) --- source3/nameresp.c | 395 +++++++++++++++++++++++++++++------------------------ 1 file changed, 214 insertions(+), 181 deletions(-) (limited to 'source3/nameresp.c') diff --git a/source3/nameresp.c b/source3/nameresp.c index 7fcb41e79f..bd64fba2b6 100644 --- a/source3/nameresp.c +++ b/source3/nameresp.c @@ -35,15 +35,30 @@ extern pstring scope; extern struct in_addr ipzero; extern struct in_addr ipgrp; +uint16 name_trn_id=0; + + +/*************************************************************************** + updates the unique transaction identifier + **************************************************************************/ +void update_name_trn_id(void) +{ + if (!name_trn_id) + { + name_trn_id = (time(NULL)%(unsigned)0x7FFF) + (getpid()%(unsigned)100); + } + name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF; +} + /*************************************************************************** deals with an entry before it dies **************************************************************************/ static void dead_netbios_entry(struct subnet_record *d, - struct response_record *n) + struct response_record *n) { DEBUG(3,("Removing dead netbios entry for %s %s (num_msgs=%d)\n", - inet_ntoa(n->send_ip), namestr(&n->name), n->num_msgs)); + inet_ntoa(n->send_ip), namestr(&n->name), n->num_msgs)); debug_state_type(n->state); @@ -51,118 +66,118 @@ static void dead_netbios_entry(struct subnet_record *d, { case NAME_QUERY_CONFIRM: { - if (!lp_wins_support()) return; /* only if we're a WINS server */ + if (!lp_wins_support()) return; /* only if we're a WINS server */ - if (n->num_msgs == 0) + if (n->num_msgs == 0) { - /* oops. name query had no response. check that the name is - unique and then remove it from our WINS database */ - - /* IMPORTANT: see query_refresh_names() */ - - if ((!NAME_GROUP(n->nb_flags))) - { - struct subnet_record *d1 = find_subnet(ipgrp); - if (d1) - { - /* remove the name that had been registered with us, - and we're now getting no response when challenging. - see rfc1001.txt 15.5.2 - */ - remove_netbios_name(d1, n->name.name, n->name.name_type, - REGISTER, n->send_ip); - } - } - } - break; + /* oops. name query had no response. check that the name is + unique and then remove it from our WINS database */ + + /* IMPORTANT: see query_refresh_names() */ + + if ((!NAME_GROUP(n->reply.nb_flags))) + { + struct subnet_record *d1 = find_subnet(ipgrp); + if (d1) + { + /* remove the name that had been registered with us, + and we're now getting no response when challenging. + see rfc1001.txt 15.5.2 + */ + remove_netbios_name(d1, n->name.name, n->name.name_type, + REGISTER, n->send_ip); + } + } + } + break; } - case NAME_QUERY_MST_CHK: - { - /* if no response received, the master browser must have gone - down on that subnet, without telling anyone. */ - - /* IMPORTANT: see response_netbios_packet() */ - - if (n->num_msgs == 0) - browser_gone(n->name.name, n->send_ip); - break; - } - - case NAME_RELEASE: - { - /* if no response received, it must be OK for us to release the - name. nobody objected (including a potentially dead or deaf - WINS server) */ - - /* IMPORTANT: see response_name_release() */ - - if (ismyip(n->send_ip)) - { - name_unregister_work(d,n->name.name,n->name.name_type); - } - if (!n->bcast) - { - DEBUG(0,("WINS server did not respond to name release!\n")); + case NAME_QUERY_MST_CHK: + { + /* if no response received, the master browser must have gone + down on that subnet, without telling anyone. */ + + /* IMPORTANT: see response_netbios_packet() */ + + if (n->num_msgs == 0) + browser_gone(n->name.name, n->send_ip); + break; + } + + case NAME_RELEASE: + { + /* if no response received, it must be OK for us to release the + name. nobody objected (including a potentially dead or deaf + WINS server) */ + + /* IMPORTANT: see response_name_release() */ + + if (ismyip(n->send_ip)) + { + name_unregister_work(d,n->name.name,n->name.name_type); + } + if (!n->bcast) + { + DEBUG(0,("WINS server did not respond to name release!\n")); /* XXXX whoops. we have problems. must deal with this */ - } - break; - } - - case NAME_REGISTER_CHALLENGE: - { - /* name challenge: no reply. we can reply to the person that - wanted the unique name and tell them that they can have it - */ - - add_name_respond(d,n->fd,d->myip, n->response_id ,&n->name, - n->nb_flags, GET_TTL(0), - n->reply_to_ip, False, n->reply_to_ip); - - if (!n->bcast) - { - DEBUG(1,("WINS server did not respond to name registration!\n")); + } + break; + } + + case NAME_REGISTER_CHALLENGE: + { + /* name challenge: no reply. we can reply to the person that + wanted the unique name and tell them that they can have it + */ + + add_name_respond(d,n->fd,d->myip, n->response_id ,&n->name, + n->reply.nb_flags, GET_TTL(0), + n->reply.ip, False, n->reply.ip); + + if (!n->bcast) + { + DEBUG(1,("WINS server did not respond to name registration!\n")); /* XXXX whoops. we have problems. must deal with this */ - } + } break; - } - - case NAME_REGISTER: - { - /* if no response received, and we are using a broadcast registration - method, it must be OK for us to register the name: nobody objected - on that subnet. if we are using a WINS server, then the WINS - server must be dead or deaf. - */ - if (n->bcast) - { - /* broadcast method: implicit acceptance of the name registration - by not receiving any objections. */ - - /* IMPORTANT: see response_name_reg() */ - - name_register_work(d,n->name.name,n->name.name_type, - n->nb_flags, n->ttl, n->reply_to_ip, n->bcast); - } - else - { - /* received no response. rfc1001.txt states that after retrying, - we should assume the WINS server is dead, and fall back to - broadcasting (see bits about M nodes: can't find any right + } + + case NAME_REGISTER: + { + /* if no response received, and we are using a broadcast registration + method, it must be OK for us to register the name: nobody objected + on that subnet. if we are using a WINS server, then the WINS + server must be dead or deaf. + */ + if (n->bcast) + { + /* broadcast method: implicit acceptance of the name registration + by not receiving any objections. */ + + /* IMPORTANT: see response_name_reg() */ + + name_register_work(d,n->token,n->name.name,n->name.name_type, + n->source, &n->reply, n->ttl, n->reply.ip, n->bcast); + } + else + { + /* received no response. rfc1001.txt states that after retrying, + we should assume the WINS server is dead, and fall back to + broadcasting (see bits about M nodes: can't find any right now) */ - - DEBUG(1,("WINS server did not respond to name registration!\n")); + + DEBUG(1,("WINS server did not respond to name registration!\n")); /* XXXX whoops. we have problems. must deal with this */ - } - break; - } - - default: - { - /* nothing to do but delete the dead expected-response structure */ - /* this is normal. */ - break; - } + } + break; + } + + default: + { + /* nothing to do but delete the dead expected-response structure */ + /* this is normal. */ + break; + } } } @@ -184,81 +199,52 @@ void expire_netbios_response_entries() for (n = d->responselist; n; n = nextn) { - nextn = n->next; + nextn = n->next; if (n->repeat_time <= time(NULL)) - { - if (n->repeat_count > 0) - { - /* resend the entry */ - initiate_netbios_packet(&n->response_id, n->fd, n->quest_type, - n->name.name, n->name.name_type, - n->nb_flags, n->bcast, n->recurse, n->send_ip); + { + if (n->repeat_count > 0) + { + /* resend the entry */ + initiate_netbios_packet(n->response_id, n->fd, n->quest_type, + n->name.name, n->name.name_type, + n->reply.nb_flags, n->bcast, n->recurse, n->send_ip); n->repeat_time += n->repeat_interval; /* XXXX ms needed */ n->repeat_count--; - } - else - { + } + else + { DEBUG(4,("timeout response %d for %s %s\n", - n->response_id, namestr(&n->name), + n->response_id, namestr(&n->name), inet_ntoa(n->send_ip))); - dead_netbios_entry (d,n); /* process the non-response */ + dead_netbios_entry (d,n); /* process the non-response */ remove_response_record(d,n); /* remove the non-response */ - continue; - } - } + continue; + } + } } } } /**************************************************************************** - wrapper function to override a broadcast message and send it to the WINS - name server instead, if it exists. if wins is false, and there has been no - WINS server specified, the packet will NOT be sent. ****************************************************************************/ -struct response_record *queue_netbios_pkt_wins(struct subnet_record *d, - int fd,int quest_type,enum state_type state, - char *name,int name_type,int nb_flags, time_t ttl, - int server_type, char *my_name, char *my_comment, - BOOL bcast,BOOL recurse, - struct in_addr send_ip, struct in_addr reply_to_ip) +void queue_netbios_pkt_wins(struct subnet_record *d, + int fd,int quest_type,enum state_type state, + int token, char *name,int name_type, + enum name_source source, int nb_flags, time_t ttl, + int server_type, char *my_name, char *my_comment, + BOOL bcast,BOOL recurse, + struct in_addr send_ip, struct in_addr reply_to_ip) { - /* XXXX note: please see rfc1001.txt section 10 for details on this - function: it is currently inappropriate to use this - it will do - for now - once there is a clarification of B, M and P nodes and - which one samba is supposed to be - */ - - if ((!lp_wins_support()) && (*lp_wins_server())) - { - /* samba is not a WINS server, and we are using a WINS server */ - struct in_addr wins_ip; - wins_ip = *interpret_addr2(lp_wins_server()); - - if (!zero_ip(wins_ip)) - { - bcast = False; - send_ip = wins_ip; - } - else - { - /* oops. smb.conf's wins server parameter MUST be a host_name - or an ip_address. */ - DEBUG(0,("invalid smb.conf parameter 'wins server'\n")); - } - } - - if (zero_ip(send_ip)) return NULL; - - return queue_netbios_packet(d,fd, quest_type, state, - name, name_type, nb_flags, ttl, + queue_netbios_packet(d,fd, quest_type, state, + token, name, name_type, source, nb_flags, ttl, server_type,my_name,my_comment, - bcast, recurse, send_ip, reply_to_ip); + bcast, recurse, send_ip, reply_to_ip); } @@ -267,36 +253,83 @@ struct response_record *queue_netbios_pkt_wins(struct subnet_record *d, this is intended to be used (not exclusively) for broadcasting to master browsers (WORKGROUP(1d or 1b) or __MSBROWSE__(1)) to get complete lists across a wide area network + + a broadcast message will be over-ridden if the packet it sent to an + ip of zero, and the packet will be sent to the WINS name server instead, + if it exists. if samba is configured to be a WINS server, then the + packet will be dealt with _as if_ it had been sent on the network, + but in fact the function process_nmb() is called. ****************************************************************************/ -struct response_record *queue_netbios_packet(struct subnet_record *d, - int fd,int quest_type,enum state_type state,char *name, - int name_type,int nb_flags, time_t ttl, - int server_type, char *my_name, char *my_comment, - BOOL bcast,BOOL recurse, - struct in_addr send_ip, struct in_addr reply_to_ip) +void queue_netbios_packet(struct subnet_record *d, + int fd,int quest_type,enum state_type state, + int token, char *name, int name_type, + enum name_source source, int nb_flags, time_t ttl, + int server_type, char *my_name, char *my_comment, + BOOL bcast,BOOL recurse, + struct in_addr send_ip, struct in_addr reply_to_ip) { - struct in_addr wins_ip = ipgrp; struct response_record *n; - uint16 id = 0xffff; /* ha ha. no. do NOT broadcast to 255.255.255.255: it's a pseudo address */ - if (ip_equal(wins_ip, send_ip)) return NULL; + if (ip_equal(send_ip, ipgrp)) return; - initiate_netbios_packet(&id, fd, quest_type, name, name_type, - nb_flags, bcast, recurse, send_ip); + /* XXXX note: please see rfc1001.txt section 10 for details on this + function: it is currently inappropriate to use this - it will do + for now - once there is a clarification of B, M and P nodes and + which one samba is supposed to be + */ - if (id == 0xffff) { - DEBUG(4,("did not initiate netbios packet: %s\n", inet_ntoa(send_ip))); - return NULL; + if ((!lp_wins_support()) && (*lp_wins_server())) + { + /* samba is not a WINS server, and we are using a WINS server */ + struct in_addr wins_ip; + wins_ip = *interpret_addr2(lp_wins_server()); + + if (!zero_ip(wins_ip)) + { + bcast = False; + send_ip = wins_ip; + } + else + { + /* oops. smb.conf's wins server parameter MUST be a host_name + or an ip_address. */ + DEBUG(0,("invalid smb.conf parameter 'wins server'\n")); + } } - if ((n = make_response_queue_record(state,id,fd, - quest_type,name,name_type,nb_flags,ttl, - server_type,my_name, my_comment, - bcast,recurse,send_ip,reply_to_ip))) + if (zero_ip(send_ip)) + { + /* doing a netbios query to samba as a WINS server, internally */ + if (lp_wins_support()) /* samba is a WINS server */ + { + DEBUG(4,("queue netbios packet with ourselves...\n")); + bcast = False; + } + else { - add_response_record(d,n); - return n; + return; } - return NULL; + } + + update_name_trn_id(); + + /* queue the response expected because if we do a query with an ip + of zero, we are expecting to hear from ourself immediately */ + if ((n = make_response_queue_record(state, name_trn_id, fd, quest_type, + token, name, name_type, source, nb_flags, ttl, + server_type, my_name, my_comment, + bcast, recurse, send_ip, reply_to_ip))) + { + add_response_record(d,n); + } + + if (!initiate_netbios_packet(name_trn_id, fd, quest_type, name, name_type, + nb_flags, bcast, recurse, send_ip)) + { + /* packet wasn't sent - not expecting a response */ + DEBUG(4,("did not initiate netbios packet: %s\n", inet_ntoa(send_ip))); + remove_response_record(d, n); + return; + } } -- cgit