diff options
-rw-r--r-- | source/client/client.c | 25 | ||||
-rw-r--r-- | source/include/nameserv.h | 12 | ||||
-rw-r--r-- | source/include/proto.h | 12 | ||||
-rw-r--r-- | source/include/version.h | 2 | ||||
-rw-r--r-- | source/libsmb/namequery.c | 4 | ||||
-rw-r--r-- | source/nameannounce.c | 46 | ||||
-rw-r--r-- | source/namedbname.c | 17 | ||||
-rw-r--r-- | source/namedbserver.c | 51 | ||||
-rw-r--r-- | source/nameelect.c | 125 | ||||
-rw-r--r-- | source/namepacket.c | 42 | ||||
-rw-r--r-- | source/nameresp.c | 6 | ||||
-rw-r--r-- | source/nameresp.doc | 12 | ||||
-rw-r--r-- | source/nameserv.c | 23 | ||||
-rw-r--r-- | source/nameservreply.c | 55 | ||||
-rw-r--r-- | source/nameservresp.c | 4 | ||||
-rw-r--r-- | source/namework.c | 156 | ||||
-rw-r--r-- | source/nmbd/nmbd.c | 2 | ||||
-rw-r--r-- | source/smbd/ipc.c | 2 | ||||
-rw-r--r-- | source/utils/nmblookup.c | 4 |
19 files changed, 394 insertions, 206 deletions
diff --git a/source/client/client.c b/source/client/client.c index 2eb4be7d132..14a6e20ab58 100644 --- a/source/client/client.c +++ b/source/client/client.c @@ -3585,7 +3585,7 @@ static void server_info() /**************************************************************************** try and browse available connections on a host ****************************************************************************/ -static BOOL list_servers() +static BOOL list_servers(char *wk_grp) { char *rparam = NULL; char *rdata = NULL; @@ -3600,7 +3600,7 @@ static BOOL list_servers() p = param; SSVAL(p,0,0x68); /* api number */ p += 2; - strcpy(p,"WrLehDO"); + strcpy(p,"WrLehDz"); p = skip_string(p,1); strcpy(p,"B16BBDz"); @@ -3615,6 +3615,11 @@ static BOOL list_servers() SIVAL(p,0,SV_TYPE_ALL); + p += 4; + + strcpy(p, wk_grp); + p = skip_string(p,1); + if (call_api(PTR_DIFF(p+4,param),0, 8,10000, &rprcnt,&rdrcnt, @@ -3638,9 +3643,10 @@ static BOOL list_servers() for (i=0;i<count;i++) { char *sname = p2; int comment_offset = IVAL(p2,22) & 0xFFFF; - printf("\t%-16.16s %s\n", + uint32 stype = IVAL(p2,18); + printf("\t%-16.16s %s %8x\n", sname, - comment_offset?rdata+comment_offset-converter:""); + comment_offset?rdata+comment_offset-converter:"", stype); ok=True; p2 += 26; @@ -3651,7 +3657,7 @@ static BOOL list_servers() if (rparam) {free(rparam); rparam = NULL;} if (rdata) {free(rdata); rdata = NULL;} - SIVAL(p,0,SV_TYPE_DOMAIN_ENUM); + SIVAL(p,0,0x7fffffff); if (call_api(PTR_DIFF(p+4,param),0, 8,10000, @@ -3676,9 +3682,10 @@ static BOOL list_servers() for (i=0;i<count;i++) { char *sname = p2; int comment_offset = IVAL(p2,22) & 0xFFFF; - printf("\t%-16.16s %s\n", + uint32 stype =IVAL(p2,18); + printf("\t%-16.16s %s %8x\n", sname, - comment_offset?rdata+comment_offset-converter:""); + comment_offset?rdata+comment_offset-converter:"",stype); ok=True; p2 += 26; @@ -4391,9 +4398,9 @@ static void usage(char *pname) sleep(1); browse_host(True); } - if (!list_servers()) { + if (!list_servers(workgroup)) { sleep(1); - list_servers(); + list_servers(workgroup); } send_logout(); diff --git a/source/include/nameserv.h b/source/include/nameserv.h index de5e492644a..b634250c811 100644 --- a/source/include/nameserv.h +++ b/source/include/nameserv.h @@ -85,7 +85,17 @@ enum name_source {STATUS_QUERY, LMHOSTS, REGISTER, SELF, DNS, DNSFAIL}; enum node_type {B_NODE=0, P_NODE=1, M_NODE=2, NBDD_NODE=3}; enum packet_type {NMB_PACKET, DGRAM_PACKET}; -enum master_state { MST_NONE, MST_WON, MST_MSB, MST_BROWSER, MST_DOMAIN }; +enum master_state +{ + MST_NONE, + MST_WON, + MST_MSB, + MST_BROWSER, + MST_DOMAIN_NONE, + MST_DOMAIN_MEM, + MST_DOMAIN_TST, + MST_DOMAIN +}; enum state_type { diff --git a/source/include/proto.h b/source/include/proto.h index 2286b93a6d5..e7225a72719 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -256,7 +256,7 @@ BOOL ms_browser_name(char *name, int type); void remove_name(struct subnet_record *d, struct name_record *n); struct name_record *find_name(struct name_record *n, struct nmb_name *name, - int search, struct in_addr ip); + int search); struct name_record *find_name_search(struct subnet_record **d, struct nmb_name *name, int search, struct in_addr ip); @@ -286,6 +286,7 @@ struct response_record *find_response_record(struct subnet_record **d, uint16 id); void remove_old_servers(struct work_record *work, time_t t, BOOL remove_all); +struct server_record *find_server(struct work_record *work, char *name); struct server_record *add_server_entry(struct subnet_record *d, struct work_record *work, char *name,int servertype, @@ -320,12 +321,13 @@ void run_elections(void); void process_election(struct packet_struct *p,char *buf); BOOL check_elections(void); void process_logon_packet(struct packet_struct *p,char *buf,int len); +void debug_browse_data(char *outbuf, int len); void initiate_netbios_packet(uint16 *id, int fd,int quest_type,char *name,int name_type, int nb_flags,BOOL bcast,BOOL recurse, struct in_addr to_ip); void reply_netbios_packet(struct packet_struct *p1,int trn_id, - int rcode,int opcode, BOOL recurse, + int rcode, int rcv_code, int opcode, BOOL recurse, struct nmb_name *rr_name,int rr_type,int rr_class,int ttl, char *data,int len); void queue_packet(struct packet_struct *packet); @@ -357,11 +359,12 @@ void add_my_names(void); void remove_my_names(); void refresh_my_names(time_t t); void query_refresh_names(void); -void add_name_respond(struct subnet_record *d, int fd, uint16 response_id, +void add_name_respond(struct subnet_record *d, int fd, struct in_addr from_ip, + uint16 response_id, struct nmb_name *name, int nb_flags, int ttl, struct in_addr register_ip, BOOL new_owner, struct in_addr reply_to_ip); -void send_name_response(int fd, +void send_name_response(int fd, struct in_addr from_ip, int name_trn_id, int opcode, BOOL success, BOOL recurse, struct nmb_name *reply_name, int nb_flags, int ttl, struct in_addr ip); @@ -369,6 +372,7 @@ void reply_name_release(struct packet_struct *p); void reply_name_reg(struct packet_struct *p); void reply_name_status(struct packet_struct *p); void reply_name_query(struct packet_struct *p); +void debug_state_type(int state); void response_netbios_packet(struct packet_struct *p); void reset_server(char *name, int state, struct in_addr ip); void tell_become_backup(void); diff --git a/source/include/version.h b/source/include/version.h index 964411164dd..7bde637b184 100644 --- a/source/include/version.h +++ b/source/include/version.h @@ -1 +1 @@ -#define VERSION "1.9.16alpha10" +#define VERSION "1.9.16a10" diff --git a/source/libsmb/namequery.c b/source/libsmb/namequery.c index d1b1ae7d3e5..54809130017 100644 --- a/source/libsmb/namequery.c +++ b/source/libsmb/namequery.c @@ -173,6 +173,8 @@ BOOL name_status(int fd,char *name,int name_type,BOOL recurse, continue; } + debug_nmb_packet(p2); + _interpret_node_status(&nmb2->answers->rdata[0], master,rname); free_packet(p2); return(True); @@ -266,6 +268,8 @@ BOOL name_query(int fd,char *name,int name_type, continue; } + debug_nmb_packet(p2); + if (nmb2->header.opcode != 0 || nmb2->header.nm_flags.bcast || nmb2->header.rcode || diff --git a/source/nameannounce.c b/source/nameannounce.c index 63dfc1555b0..3107d02c149 100644 --- a/source/nameannounce.c +++ b/source/nameannounce.c @@ -48,7 +48,7 @@ extern pstring ServerComment; extern int updatecount; extern int workgroup_count; -/* what server type are we currently */ +extern struct in_addr ipgrp; /**************************************************************************** send a announce request to the local net @@ -146,12 +146,19 @@ void announce_backup(void) char *p; struct subnet_record *d1; int tok; + static uint32 id_count = 0; if (!lastrun) lastrun = t; +#if 1 + if (t < lastrun + 1 * 60) +#else if (t < lastrun + CHECK_TIME_ANNOUNCE_BACKUP * 60) +#endif return; lastrun = t; + DEBUG(4,("checking backups...\n")); + for (tok = 0; tok <= workgroup_count; tok++) { for (d1 = subnetlist; d1; d1 = d1->next) @@ -178,14 +185,15 @@ void announce_backup(void) bzero(outbuf,sizeof(outbuf)); p = outbuf; + CVAL(p,0) = ANN_GetBackupListReq; - p++; - - CVAL(p,0) = 1; /* count? */ - SIVAL(p,1,work->token); /* workgroup unique key index */ - p += 5; - p++; + CVAL(p,1) = work->token; /* workgroup unique key index */ + SIVAL(p,2,++id_count); /* unique count. not that we use it! */ + + p += 6; + debug_browse_data(outbuf, PTR_DIFF(p,outbuf)); + if (!AM_DOMCTL(work)) { /* only ask for a list of backup domain controllers @@ -199,6 +207,8 @@ void announce_backup(void) *iface_ip(d->bcast_ip)); } + debug_browse_data(outbuf, PTR_DIFF(p,outbuf)); + if (!AM_MASTER(work)) { /* only ask for a list of master browsers if we @@ -208,7 +218,7 @@ void announce_backup(void) ClientDGRAM,outbuf, PTR_DIFF(p,outbuf), myname, work->work_group, - 0x0,0x1b,d->bcast_ip, + 0x0,0x1d,d->bcast_ip, *iface_ip(d->bcast_ip)); } } @@ -246,13 +256,15 @@ static void do_announce_host(int command, CVAL(p,22) = 0x02; /* minor version */ SIVAL(p,23,server_type); - SSVAL(p,27,0xaa55); /* browse signature */ - SSVAL(p,29,0x001f); /* browse version: CIFS draft 1.0 indicates 0x001f */ + SSVAL(p,27,0x010f); /* browse version: got from NT/AS 4.00 */ + SSVAL(p,29,0xaa55); /* browse signature */ strcpy(p+31,server_comment); p += 31; p = skip_string(p,1); + debug_browse_data(outbuf, PTR_DIFF(p,outbuf)); + /* send the announcement */ send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf, PTR_DIFF(p,outbuf), @@ -290,6 +302,8 @@ void remove_my_servers(void) void announce_server(struct subnet_record *d, struct work_record *work, char *name, char *comment, time_t ttl, int server_type) { + uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_SERVER_UNIX; + if (AM_MASTER(work)) { DEBUG(3,("sending local master announce to %s for %s(1e)\n", @@ -307,11 +321,15 @@ void announce_server(struct subnet_record *d, struct work_record *work, /* XXXX should we do a domain-announce-kill? */ if (server_type != 0) { + if (AM_DOMCTL(work)) { + domain_type |= SV_TYPE_DOMAIN_CTRL; + } do_announce_host(ANN_DomainAnnouncement, - work->work_group, 0x00, d->myip, - MSBROWSE , 0x01, d->bcast_ip, + name , 0x00, d->myip, + MSBROWSE, 0x01, d->bcast_ip, ttl*1000, - name, server_type ? SV_TYPE_DOMAIN_ENUM : 0, comment); + work->work_group, server_type ? domain_type : 0, + comment); } } else @@ -345,6 +363,8 @@ void announce_host(void) { struct work_record *work; + if (ip_equal(d->bcast_ip, ipgrp)) continue; + for (work = d->workgrouplist; work; work = work->next) { uint32 stype = work->ServerType; diff --git a/source/namedbname.c b/source/namedbname.c index 82b19077f9d..c06d10f60c4 100644 --- a/source/namedbname.c +++ b/source/namedbname.c @@ -120,7 +120,7 @@ void remove_name(struct subnet_record *d, struct name_record *n) **************************************************************************/ struct name_record *find_name(struct name_record *n, struct nmb_name *name, - int search, struct in_addr ip) + int search) { struct name_record *ret; @@ -132,12 +132,7 @@ struct name_record *find_name(struct name_record *n, if ((search&FIND_SELF) == FIND_SELF && ret->source != SELF) continue; - /* zero ip is either samba's ip or a way of finding a - name without needing to know the ip address */ - if (zero_ip(ip) || ip_equal(ip, ret->ip)) - { - return ret; - } + return ret; } } return NULL; @@ -161,7 +156,9 @@ struct name_record *find_name_search(struct subnet_record **d, { if (*d != NULL) { - return find_name((*d)->namelist, name, search, ip); + DEBUG(4,("find_name on local: %s %s search %x\n", + namestr(name),inet_ntoa(ip), search)); + return find_name((*d)->namelist, name, search); } else { @@ -180,7 +177,9 @@ struct name_record *find_name_search(struct subnet_record **d, if (*d == NULL) return NULL; - return find_name((*d)->namelist, name, search, ip); + DEBUG(4,("find_name on WINS: %s %s search %x\n", + namestr(name),inet_ntoa(ip), search)); + return find_name((*d)->namelist, name, search); } diff --git a/source/namedbserver.c b/source/namedbserver.c index de0cda79cce..f6956441292 100644 --- a/source/namedbserver.c +++ b/source/namedbserver.c @@ -103,6 +103,26 @@ static void add_server(struct work_record *work,struct server_record *s) /**************************************************************************** + find a server in a server list. + **************************************************************************/ +struct server_record *find_server(struct work_record *work, char *name) +{ + struct server_record *ret; + + if (!work) return NULL; + + for (ret = work->serverlist; ret; ret = ret->next) + { + if (strequal(ret->serv.name,name)) + { + return ret; + } + } + return NULL; +} + + +/**************************************************************************** add a server entry ****************************************************************************/ struct server_record *add_server_entry(struct subnet_record *d, @@ -115,33 +135,30 @@ struct server_record *add_server_entry(struct subnet_record *d, struct server_record *s; if (name[0] == '*') - { + { return (NULL); - } - - for (s = work->serverlist; s; s = s->next) - { - if (strequal(name,s->serv.name)) break; - } + } + s = find_server(work, name); + if (s && !replace) - { - DEBUG(4,("Not replacing %s\n",name)); - return(s); - } + { + DEBUG(4,("Not replacing %s\n",name)); + return(s); + } if (!s || s->serv.type != servertype || !strequal(s->serv.comment, comment)) updatedlists=True; if (!s) - { - newentry = True; - s = (struct server_record *)malloc(sizeof(*s)); + { + newentry = True; + s = (struct server_record *)malloc(sizeof(*s)); - if (!s) return(NULL); + if (!s) return(NULL); - bzero((char *)s,sizeof(*s)); - } + bzero((char *)s,sizeof(*s)); + } if (d->my_interface && strequal(lp_workgroup(),work->work_group)) diff --git a/source/nameelect.c b/source/nameelect.c index ba66f41a916..2b0fa5c0dd0 100644 --- a/source/nameelect.c +++ b/source/nameelect.c @@ -41,6 +41,7 @@ extern pstring scope; extern pstring myname; extern struct in_addr ipzero; +extern struct in_addr ipgrp; /* machine comment for host announcements */ extern pstring ServerComment; @@ -201,21 +202,27 @@ void name_unregister_work(struct subnet_record *d, char *name, int name_type) void name_register_work(struct subnet_record *d, char *name, int name_type, int nb_flags, time_t ttl, struct in_addr ip, BOOL bcast) { - enum name_source source = ismyip(ip) ? SELF : REGISTER; + enum name_source source = (ismyip(ip) || ip_equal(ip, ipzero)) ? + SELF : REGISTER; if (source == SELF) { struct work_record *work = find_workgroupstruct(d, lp_workgroup(), False); - if (work && work->state != MST_NONE) + add_netbios_entry(d,name,name_type,nb_flags,ttl,source,ip,True,!bcast); + + if (work) { - /* samba is in the process of working towards master browser-ness. - initiate the next stage. - */ - become_master(d, work); + if (work->state != MST_NONE) + { + /* samba is in the process of working towards master browser-ness. + initiate the next stage. + */ + become_master(d, work); + return; + } } } - add_netbios_entry(d,name,name_type,nb_flags,ttl,source,ip,True,!bcast); } @@ -248,8 +255,8 @@ void become_master(struct subnet_record *d, struct work_record *work) if (!work) return; - DEBUG(2,("Becoming master for %s (currently at stage %d)\n", - work->work_group,work->state)); + DEBUG(2,("Becoming master for %s %s (currently at stage %d)\n", + work->work_group,inet_ntoa(d->bcast_ip),work->state)); switch (work->state) { @@ -298,10 +305,50 @@ void become_master(struct subnet_record *d, struct work_record *work) /* ask all servers on our local net to announce to us */ announce_request(work, d->bcast_ip); } + break; + } + + case MST_BROWSER: + { + /* don't have to do anything: just report success */ + DEBUG(3,("3rd stage: become master browser!\n")); + + break; + } + + case MST_DOMAIN_NONE: + { + if (lp_domain_master()) + { + work->state = MST_DOMAIN_MEM; /* ... become domain member */ + DEBUG(3,("domain first stage: register as domain member\n")); + + /* add domain member name */ + add_my_name_entry(d,work->work_group,0x1e,NB_ACTIVE ); + + /* DON'T do anything else after calling add_my_name_entry() */ + return; + } + else + { + DEBUG(4,("samba not configured as a domain master.\n")); + } + + break; + } + case MST_DOMAIN_MEM: + { if (lp_domain_master()) { - DEBUG(3,("third stage: register as domain master\n")); + work->state = MST_DOMAIN_TST; /* ... possibly become domain master */ + DEBUG(3,("domain second stage: register as domain master\n")); + + if (lp_domain_logons()) + { + work->ServerType |= SV_TYPE_DOMAIN_MEMBER; + add_server_entry(d,work,myname,work->ServerType,0,ServerComment,True); + } /* add domain master name */ add_my_name_entry(d,work->work_group,0x1b,NB_ACTIVE ); @@ -311,34 +358,62 @@ void become_master(struct subnet_record *d, struct work_record *work) } else { - DEBUG(3,("samba not configured as a domain master: no third stage.\n")); + DEBUG(4,("samba not configured as a domain master.\n")); } break; } - case MST_BROWSER: /* while we were still a master browser... */ + + case MST_DOMAIN_TST: /* while we were still a master browser... */ { /* update our server status */ if (lp_domain_master()) { - DEBUG(3,("fourth stage: samba is now a domain master.\n")); + struct subnet_record *d1; + uint32 update_type = 0; + + DEBUG(3,("domain third stage: samba is now a domain master.\n")); work->state = MST_DOMAIN; /* ... registering WORKGROUP(1b) succeeded */ - work->ServerType |= SV_TYPE_DOMAIN_MASTER; + update_type |= SV_TYPE_DOMAIN_MASTER; if (lp_domain_logons()) { - work->ServerType |= SV_TYPE_DOMAIN_CTRL; - work->ServerType |= SV_TYPE_DOMAIN_MEMBER; + update_type |= SV_TYPE_DOMAIN_CTRL; } + + work->ServerType |= update_type; add_server_entry(d,work,myname,work->ServerType,0,ServerComment,True); + + for (d1 = subnetlist; d1; d1 = d1->next) + { + struct work_record *w; + if (ip_equal(d1->bcast_ip, d->bcast_ip)) continue; + + for (w = d1->workgrouplist; w; w = w->next) + { + struct server_record *s = find_server(w, myname); + if (strequal(w->work_group, work->work_group)) + { + w->ServerType |= update_type; + } + if (s) + { + s->serv.type |= update_type; + DEBUG(4,("found server %s on %s: update to %8x\n", + s->serv.name, inet_ntoa(d1->bcast_ip), + s->serv.type)); + } + } + } } break; } + case MST_DOMAIN: { - /* nothing else to become, at the moment: we are top-dog. */ + /* don't have to do anything: just report success */ DEBUG(3,("fifth stage: there isn't one yet!\n")); break; } @@ -414,16 +489,16 @@ void run_elections(void) lastime = t; for (d = subnetlist; d; d = d->next) - { - struct work_record *work; - for (work = d->workgrouplist; work; work = work->next) + { + struct work_record *work; + for (work = d->workgrouplist; work; work = work->next) { if (work->RunningElection) - { - send_election(d,work->work_group, work->ElectionCriterion, + { + send_election(d,work->work_group, work->ElectionCriterion, t-StartupTime,myname); - if (work->ElectionCount++ >= 4) + if (work->ElectionCount++ >= 4) { /* I won! now what :-) */ DEBUG(2,(">>> Won election on %s %s <<<\n", @@ -434,9 +509,9 @@ void run_elections(void) become_master(d, work); } - } + } } - } + } } diff --git a/source/namepacket.c b/source/namepacket.c index 5afdb8af0ed..acedbc01511 100644 --- a/source/namepacket.c +++ b/source/namepacket.c @@ -40,6 +40,40 @@ extern struct in_addr ipgrp; static uint16 name_trn_id=0; + +/*************************************************************************** + updates the unique transaction identifier + **************************************************************************/ +void debug_browse_data(char *outbuf, int len) +{ + int i,j; + for (i = 0; i < len; i+= 16) + { + DEBUG(4, ("%3x char ", i)); + + for (j = 0; j < 16; j++) + { + unsigned char x = outbuf[i+j]; + if (x < 32 || x > 127) x = '.'; + + if (i+j >= len) break; + DEBUG(4, ("%c", x)); + } + + DEBUG(4, (" hex ", i)); + + for (j = 0; j < 16; j++) + { + if (i+j >= len) break; + DEBUG(4, (" %02x", outbuf[i+j])); + } + + DEBUG(4, ("\n")); + } + +} + + /*************************************************************************** updates the unique transaction identifier **************************************************************************/ @@ -138,7 +172,7 @@ void initiate_netbios_packet(uint16 *id, reply to a netbios name packet ****************************************************************************/ void reply_netbios_packet(struct packet_struct *p1,int trn_id, - int rcode,int opcode, BOOL recurse, + int rcode, int rcv_code, int opcode, BOOL recurse, struct nmb_name *rr_name,int rr_type,int rr_class,int ttl, char *data,int len) { @@ -150,7 +184,7 @@ void reply_netbios_packet(struct packet_struct *p1,int trn_id, p = *p1; - switch (rr_type) + switch (rcv_code) { case NMB_STATUS: { @@ -539,5 +573,9 @@ BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname, p.timestamp = time(NULL); p.packet_type = DGRAM_PACKET; + DEBUG(4,("send mailslot %s from %s %s", mailslot, + inet_ntoa(src_ip),namestr(&dgram->source_name))); + DEBUG(4,("to %s %s\n", inet_ntoa(dest_ip),namestr(&dgram->dest_name))); + return(send_packet(&p)); } diff --git a/source/nameresp.c b/source/nameresp.c index f87088dffa5..0f76323df0b 100644 --- a/source/nameresp.c +++ b/source/nameresp.c @@ -45,6 +45,8 @@ static void dead_netbios_entry(struct subnet_record *d, DEBUG(3,("Removing dead netbios entry for %s %s (num_msgs=%d)\n", inet_ntoa(n->send_ip), namestr(&n->name), n->num_msgs)); + debug_state_type(n->state); + switch (n->state) { case NAME_QUERY_CONFIRM: @@ -113,7 +115,7 @@ static void dead_netbios_entry(struct subnet_record *d, wanted the unique name and tell them that they can have it */ - add_name_respond(d,n->fd, n->response_id ,&n->name, + 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); @@ -140,7 +142,7 @@ static void dead_netbios_entry(struct subnet_record *d, /* IMPORTANT: see response_name_reg() */ name_register_work(d,n->name.name,n->name.name_type, - n->nb_flags, n->ttl, n->send_ip, n->bcast); + n->nb_flags, n->ttl, n->reply_to_ip, n->bcast); } else { diff --git a/source/nameresp.doc b/source/nameresp.doc index 0349bd47c2e..23340a8c28e 100644 --- a/source/nameresp.doc +++ b/source/nameresp.doc @@ -131,18 +131,6 @@ samba should take this into account (see rfc1001.txt 10.3). remove_name_entry() issues this samba 'state' response_name_rel() deals with responses to NAME_RELEASE. -- NAME_REGISTER_CHALLENGE - -when a samba 'state' of type NAME_REGISTER_CHALLENGE is sent, and a -response is not received, it is assumed that the server being queried -is either dead, deaf or unreachable. the host that wanted this -unique name is then informed that it can have it (the name query -challenge went unanswered) and that its registration of this name -did in fact succeed. - -reply_name_reg() issues this samba 'state' -response_name_query_register() deals with responses. - - NAME_REGISTER when a samba 'state' of type NAME_REGISTER is sent, and a response is diff --git a/source/nameserv.c b/source/nameserv.c index 371f12e0110..ee75a9825a3 100644 --- a/source/nameserv.c +++ b/source/nameserv.c @@ -37,6 +37,7 @@ extern int DEBUGLEVEL; extern pstring scope; extern pstring myname; +extern pstring ServerComment; extern struct in_addr ipzero; extern struct in_addr ipgrp; @@ -124,7 +125,7 @@ void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags) it must be re-registered, rather than just registered */ make_nmb_name(&n, name, type, scope); - if (find_name(d->namelist, &n, SELF, ipzero)) + if (find_name(d->namelist, &n, SELF)) re_reg = True; /* XXXX BUG: if samba is offering WINS support, it should still add the @@ -141,6 +142,7 @@ void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags) actually be true */ + DEBUG(4,("samba as WINS server adding: ")); /* this will call add_netbios_entry() */ name_register_work(d, name, type, nb_flags,0, ipzero, False); } @@ -155,10 +157,11 @@ void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags) } else { + /* broadcast the packet, but it comes from ipzero */ queue_netbios_packet(d,ClientNMB, re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER, name, type, nb_flags, GET_TTL(0), - True, True, d->bcast_ip, d->bcast_ip); + True, True, d->bcast_ip, ipzero); } } @@ -181,9 +184,10 @@ void add_my_names(void) for (d = subnetlist; d; d = d->next) { - if (!d->my_interface) continue; + BOOL wins_iface = ip_equal(d->bcast_ip, ipgrp); + + if (!d->my_interface && !wins_iface) continue; - /* these names need to be refreshed with the WINS server */ add_my_name_entry(d, myname,0x20,NB_ACTIVE); add_my_name_entry(d, myname,0x03,NB_ACTIVE); add_my_name_entry(d, myname,0x00,NB_ACTIVE); @@ -195,11 +199,20 @@ void add_my_names(void) add_netbios_entry(d,"__SAMBA__",0x20,NB_ACTIVE,0,SELF,ip,False,wins); add_netbios_entry(d,"__SAMBA__",0x00,NB_ACTIVE,0,SELF,ip,False,wins); - if (lp_domain_logons() && lp_domain_master()) { + if (!wins_iface && lp_domain_logons() && lp_domain_master()) { /* XXXX the 0x1c is apparently something to do with domain logons */ add_my_name_entry(d, my_workgroup(),0x1c,NB_ACTIVE|NB_GROUP); } } + if (lp_domain_master() && (d = find_subnet(ipgrp))) + { + struct work_record *work = find_workgroupstruct(d, lp_workgroup(), True); + if (work && work->state == MST_NONE) + { + work->state = MST_DOMAIN_NONE; + become_master(d, work); + } + } } diff --git a/source/nameservreply.c b/source/nameservreply.c index 6501bded685..84b9277d603 100644 --- a/source/nameservreply.c +++ b/source/nameservreply.c @@ -42,7 +42,8 @@ extern struct in_addr ipgrp; /**************************************************************************** add a netbios entry. respond to the (possibly new) owner. **************************************************************************/ -void add_name_respond(struct subnet_record *d, int fd, uint16 response_id, +void add_name_respond(struct subnet_record *d, int fd, struct in_addr from_ip, + uint16 response_id, struct nmb_name *name, int nb_flags, int ttl, struct in_addr register_ip, BOOL new_owner, struct in_addr reply_to_ip) @@ -52,7 +53,7 @@ void add_name_respond(struct subnet_record *d, int fd, uint16 response_id, nb_flags,ttl,REGISTER,register_ip,False,True); /* reply yes or no to the host that requested the name */ - send_name_response(fd, response_id, NMB_REG, + send_name_response(fd,from_ip, response_id, NMB_REG, new_owner, True, name, nb_flags, ttl, reply_to_ip); } @@ -60,7 +61,7 @@ void add_name_respond(struct subnet_record *d, int fd, uint16 response_id, /**************************************************************************** send a registration / release response: pos/neg **************************************************************************/ -void send_name_response(int fd, +void send_name_response(int fd, struct in_addr from_ip, int name_trn_id, int opcode, BOOL success, BOOL recurse, struct nmb_name *reply_name, int nb_flags, int ttl, struct in_addr ip) @@ -85,14 +86,14 @@ void send_name_response(int fd, rdata[1] = 0; putip(&rdata[2],(char *)&ip); - p.ip = ip; + p.ip = from_ip; p.port = NMB_PORT; p.fd = fd; p.timestamp = time(NULL); p.packet_type = NMB_PACKET; reply_netbios_packet(&p,name_trn_id, - rcode,opcode,recurse, + rcode,opcode,opcode,recurse, reply_name, 0x20, 0x1, ttl, rdata, 6); @@ -145,7 +146,7 @@ void reply_name_release(struct packet_struct *p) if (bcast) return; /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */ - send_name_response(p->fd, nmb->header.name_trn_id, NMB_REL, + send_name_response(p->fd,p->ip, nmb->header.name_trn_id, NMB_REL, success, False, &nmb->question.question_name, nb_flags, 0, ip); } @@ -285,7 +286,7 @@ void reply_name_reg(struct packet_struct *p) /* send WAIT ACKNOWLEDGEMENT see rfc1002.txt 4.2.16 */ reply_netbios_packet(p,nmb->header.name_trn_id, - 0,NMB_WAIT_ACK,False, + 0,NMB_WAIT_ACK,NMB_WAIT_ACK,False, reply_name, 0x0a, 0x01, 15*1000, /* 15 seconds long enough to wait? */ rdata, 2); @@ -302,7 +303,7 @@ void reply_name_reg(struct packet_struct *p) or an END-NODE CHALLENGE REGISTRATION RESPONSE see rfc1002.txt 4.2.7 */ - send_name_response(p->fd, nmb->header.name_trn_id, NMB_REG, + send_name_response(p->fd,p->ip, nmb->header.name_trn_id, NMB_REG, success, True, reply_name, nb_flags, ttl, ip); } @@ -322,6 +323,7 @@ void reply_name_status(struct packet_struct *p) int names_added; struct name_record *n; struct subnet_record *d = NULL; + int search = FIND_SELF; BOOL bcast = nmb->header.nm_flags.bcast; @@ -335,9 +337,13 @@ void reply_name_status(struct packet_struct *p) DEBUG(3,("Name status for name %s %s\n", namestr(&nmb->question.question_name), inet_ntoa(p->ip))); + if (bcast) + search |= FIND_WINS; + else + search |= FIND_LOCAL; + n = find_name_search(&d, &nmb->question.question_name, - FIND_SELF|FIND_LOCAL, - p->ip); + search, p->ip); if (!n) return; @@ -396,7 +402,7 @@ void reply_name_status(struct packet_struct *p) /* Send a POSITIVE NAME STATUS RESPONSE */ reply_netbios_packet(p,nmb->header.name_trn_id, - 0,0,True, + 0,NMB_STATUS,0,True, &nmb->question.question_name, nmb->question.question_type, nmb->question.question_class, @@ -452,15 +458,26 @@ void reply_name_query(struct packet_struct *p) if (name_type == 0x1b) { /* even if it's a broadcast, we don't ignore queries for PDC names */ - search |= FIND_WINS; - search &= ~FIND_SELF; + search = FIND_WINS; } - if (!(d = find_req_subnet(p->ip, bcast))) + if (search | FIND_LOCAL) { - DEBUG(3,("name query: bcast %s not known\n", - inet_ntoa(p->ip))); - success = False; + if (!(d = find_req_subnet(p->ip, bcast))) + { + DEBUG(3,("name query: bcast %s not known\n", + inet_ntoa(p->ip))); + success = False; + } + } + else + { + if (!(d = find_subnet(ipgrp))) + { + DEBUG(3,("name query: wins search %s not known\n", + inet_ntoa(p->ip))); + success = False; + } } DEBUG(3,("Name query ")); @@ -492,7 +509,7 @@ void reply_name_query(struct packet_struct *p) another WINS server if the name is not in our database, or we are not a WINS server ourselves */ - ttl = n->death_time - p->timestamp; + ttl = n->death_time ? n->death_time - p->timestamp : GET_TTL(0); retip = n->ip; nb_flags = n->nb_flags; } @@ -524,7 +541,7 @@ void reply_name_query(struct packet_struct *p) } reply_netbios_packet(p,nmb->header.name_trn_id, - rcode,0,True, + rcode,NMB_QUERY,0,True, &nmb->question.question_name, nmb->question.question_type, nmb->question.question_class, diff --git a/source/nameservresp.c b/source/nameservresp.c index e47afc55b34..46acc2b9927 100644 --- a/source/nameservresp.c +++ b/source/nameservresp.c @@ -339,7 +339,7 @@ static void response_name_query_register(struct nmb_packet *nmb, } /* register the old or the new owners' ip */ - add_name_respond(d, n->fd, n->response_id,&n->name,n->nb_flags, + add_name_respond(d, n->fd, d->myip, n->response_id,&n->name,n->nb_flags, GET_TTL(0), register_ip, new_owner, n->reply_to_ip); } @@ -434,7 +434,7 @@ static void debug_rr_type(int rr_type) /**************************************************************************** report the response record nmbd state ****************************************************************************/ -static void debug_state_type(int state) +void debug_state_type(int state) { /* report the state type to help debugging */ switch (state) diff --git a/source/namework.c b/source/namework.c index 85a07a7dc94..4329e6f197a 100644 --- a/source/namework.c +++ b/source/namework.c @@ -64,6 +64,7 @@ extern int updatecount; extern time_t StartupTime; +extern BOOL updatedlists; /**************************************************************************** tell a server to become a backup browser @@ -195,18 +196,22 @@ BOOL listening_name(struct work_record *work, struct nmb_name *n) resources. We just have to pass it to smbd (via browser.dat) and let the client choose using bit masks. ******************************************************************/ -static void process_announce(struct packet_struct *p,int command,char *buf) +static void process_announce(struct packet_struct *p,uint16 command,char *buf) { struct dgram_packet *dgram = &p->packet.dgram; struct in_addr ip = dgram->header.source_ip; struct subnet_record *d = find_subnet(ip); int update_count = CVAL(buf,0); + int ttl = IVAL(buf,1)/1000; char *name = buf+5; int osmajor=CVAL(buf,21); int osminor=CVAL(buf,22); uint32 servertype = IVAL(buf,23); + uint32 browse_type= CVAL(buf,27); + uint32 browse_sig = CVAL(buf,29); char *comment = buf+31; + struct work_record *work; char *work_name; char *serv_name = dgram->source_name.name; @@ -215,9 +220,9 @@ static void process_announce(struct packet_struct *p,int command,char *buf) comment[43] = 0; DEBUG(4,("Announce(%d) %s(%x)",command,name,name[15])); - DEBUG(4,("%s count=%d ttl=%d OS=(%d,%d) type=%08x comment=%s\n", + DEBUG(4,("%s count=%d ttl=%d OS=(%d,%d) type=%08x sig=%4x %4x comment=%s\n", namestr(&dgram->dest_name),update_count,ttl,osmajor,osminor, - servertype,comment)); + servertype,browse_type,browse_sig,comment)); name[15] = 0; @@ -236,7 +241,7 @@ static void process_announce(struct packet_struct *p,int command,char *buf) return; } - if (same_context(dgram)) return; + if (!strequal(dgram->dest_name.scope,scope )) return; if (command == ANN_DomainAnnouncement) { /* XXXX if we are a master browser for the workgroup work_name, @@ -249,6 +254,7 @@ static void process_announce(struct packet_struct *p,int command,char *buf) */ work_name = name; + add = True; } else { work_name = dgram->dest_name.name; } @@ -268,9 +274,10 @@ static void process_announce(struct packet_struct *p,int command,char *buf) ttl = GET_TTL(ttl); - /* add them to our browse list */ + /* add them to our browse list, and update the browse.dat file */ add_server_entry(d,work,name,servertype,ttl,comment,True); - + updatedlists = True; + #if 0 /* the tell become backup code is broken, no great harm is done by disabling it */ @@ -339,12 +346,12 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf) struct dgram_packet *dgram = &p->packet.dgram; struct in_addr ip = dgram->header.source_ip; int count = CVAL(buf,0); - int Index = IVAL(buf,1); /* caller's index representing workgroup */ + uint32 info = IVAL(buf,1); /* XXXX caller's incremental info */ char *buf1; - DEBUG(3,("Receive Backup ack for %s from %s total=%d index=%d\n", + DEBUG(3,("Receive Backup ack for %s from %s total=%d info=%d\n", namestr(&dgram->dest_name), inet_ntoa(ip), - count, Index)); + count, info)); if (same_context(dgram)) return; @@ -352,44 +359,49 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf) /* go through the list of servers attempting to sync browse lists */ for (buf1 = buf+5; *buf1 && count; buf1 = skip_string(buf1, 1), --count) - { - struct in_addr back_ip; - struct subnet_record *d; + { + struct in_addr back_ip; + struct subnet_record *d; - DEBUG(4,("Searching for backup browser %s at %s...\n", + DEBUG(4,("Searching for backup browser %s at %s...\n", buf1, inet_ntoa(ip))); - /* XXXX assume name is a DNS name NOT a netbios name. a more complete - approach is to use reply_name_query functionality to find the name */ - back_ip = *interpret_addr2(buf1); + /* XXXX assume name is a DNS name NOT a netbios name. a more complete + approach is to use reply_name_query functionality to find the name */ + + back_ip = *interpret_addr2(buf1); - if (zero_ip(back_ip)) + if (zero_ip(back_ip)) { DEBUG(4,("Failed to find backup browser server using DNS\n")); continue; } DEBUG(4,("Found browser server at %s\n", inet_ntoa(back_ip))); + DEBUG(4,("END THIS LOOP: CODE NEEDS UPDATING\n")); - if ((d = find_subnet(back_ip))) + /* XXXX function needs work */ + continue; + + if ((d = find_subnet(back_ip))) { struct subnet_record *d1; for (d1 = subnetlist; d1; d1 = d1->next) - { + { struct work_record *work; for (work = d1->workgrouplist; work; work = work->next) { - if (work->token == Index) - { + if (work->token == 0 /* token */) + { queue_netbios_packet(d1,ClientNMB,NMB_QUERY,NAME_QUERY_SRV_CHK, work->work_group,0x1d,0,0, False,False,back_ip,back_ip); return; - } + } } - } + } } - } + } } @@ -397,19 +409,18 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf) send a backup list response. **************************************************************************/ static void send_backup_list(char *work_name, struct nmb_name *src_name, - int info_count, int token, int info, + int token, uint32 info, int name_type, struct in_addr ip) { struct subnet_record *d; char outbuf[1024]; char *p, *countptr, *nameptr; int count = 0; - int i, j; char *theirname = src_name->name; DEBUG(3,("sending backup list of %s to %s: %s(%x) %s(%x)\n", work_name, inet_ntoa(ip), - myname,0x20,theirname,0x0)); + myname,0x0,theirname,0x0)); if (name_type == 0x1d) { @@ -429,18 +440,20 @@ static void send_backup_list(char *work_name, struct nmb_name *src_name, p = outbuf; CVAL(p,0) = ANN_GetBackupListResp; /* backup list response */ - p++; - countptr = p; /* count pointer */ - - SSVAL(p,1,token); /* sender's workgroup index representation */ - SSVAL(p,3,info); /* XXXX clueless: info, usually zero */ + p++; + countptr = p; + + SIVAL(p,1,info); /* the sender's unique info */ + p += 5; nameptr = p; - + +#if 0 + for (d = subnetlist; d; d = d->next) - { + { struct work_record *work; for (work = d->workgrouplist; work; work = work->next) @@ -465,9 +478,9 @@ static void send_backup_list(char *work_name, struct nmb_name *src_name, /* workgroup request: include all backup browsers in the list */ /* domain request: include all domain members in the list */ - + if ((name_type == 0x1d && (s->serv.type & MASTER_TYPE)) || - (name_type == 0x1b && (s->serv.type & DOMCTL_TYPE))) + (name_type == 0x1b && (s->serv.type & DOMCTL_TYPE))) { DEBUG(4, ("%s ", s->serv.name)); @@ -476,52 +489,34 @@ static void send_backup_list(char *work_name, struct nmb_name *src_name, strupper(p); p = skip_string(p,1); } - } + } } - } - + } + +#endif + + count++; + strcpy(p,myname); + strupper(p); + p = skip_string(p,1); + if (count == 0) { DEBUG(4, ("none\n")); - return; } else { DEBUG(4, (" - count %d\n", count)); } - CVAL(countptr,0) = count; /* total number of backup browsers found */ - + CVAL(countptr, 0) = count; + { int len = PTR_DIFF(p, outbuf); - - for (i = 0; i < len; i+= 16) - { - DEBUG(4, ("%3x char ", i)); - - for (j = 0; j < 16; j++) - { - unsigned char x = outbuf[i+j]; - if (x < 32 || x > 127) x = '.'; - - if (i+j >= len) break; - DEBUG(4, ("%c", x)); - } - - DEBUG(4, (" hex ", i)); - - for (j = 0; j < 16; j++) - { - if (i+j >= len) break; - DEBUG(4, (" %02x", outbuf[i+j])); - } - - DEBUG(4, ("\n")); - } - + debug_browse_data(outbuf, len); } send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf), - myname,theirname,0x20,0x0,ip,*iface_ip(ip)); + myname,theirname,0x0,0x0,ip,*iface_ip(ip)); } @@ -544,15 +539,12 @@ static void process_send_backup_list(struct packet_struct *p,char *buf) struct subnet_record *d; struct work_record *work; - int count = CVAL(buf,0); - int token = SVAL(buf,1); /* sender's key index for the workgroup? */ - int info = SVAL(buf,3); /* XXXX don't know: some sort of info */ + int token = CVAL(buf,0); /* sender's key index for the workgroup */ + uint32 info = IVAL(buf,1); /* XXXX don't know: some sort of info */ int name_type = dgram->dest_name.name_type; if (same_context(dgram)) return; - if (count <= 0) return; - if (name_type != 0x1b && name_type != 0x1d) { DEBUG(0,("backup request to wrong type %d from %s\n", name_type,inet_ntoa(ip))); @@ -565,11 +557,11 @@ static void process_send_backup_list(struct packet_struct *p,char *buf) { if (strequal(work->work_group, dgram->dest_name.name)) { - DEBUG(2,("sending backup list to %s %s count=%d\n", - namestr(&dgram->dest_name),inet_ntoa(ip),count)); + DEBUG(2,("sending backup list to %s %s id=%x\n", + namestr(&dgram->dest_name),inet_ntoa(ip),info)); send_backup_list(work->work_group,&dgram->source_name, - count,token,info,name_type,ip); + token,info,name_type,ip); return; } } @@ -634,7 +626,6 @@ static void process_reset_browser(struct packet_struct *p,char *buf) } } - /******************************************************************* process a announcement request @@ -759,6 +750,7 @@ void process_browse_packet(struct packet_struct *p,char *buf,int len) case ANN_DomainAnnouncement: case ANN_LocalMasterAnnouncement: { + debug_browse_data(buf, len); process_announce(p,command,buf+1); break; } @@ -777,15 +769,17 @@ void process_browse_packet(struct packet_struct *p,char *buf,int len) case ANN_GetBackupListReq: { + debug_browse_data(buf, len); process_send_backup_list(p,buf+1); break; } case ANN_GetBackupListResp: - { - process_rcv_backup_list(p, buf+1); - break; - } + { + debug_browse_data(buf, len); + process_rcv_backup_list(p, buf+1); + break; + } case ANN_ResetBrowserState: { diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c index 40cb06aad4b..10b356d9b50 100644 --- a/source/nmbd/nmbd.c +++ b/source/nmbd/nmbd.c @@ -323,7 +323,7 @@ static void process(void) announce_host(); -#if 0 +#if 1 /* XXXX what was this stuff supposed to do? It sent ANN_GetBackupListReq packets which I think should only be sent when trying to find out who to browse with */ diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c index 0f00e3ec21d..415c939bf38 100644 --- a/source/smbd/ipc.c +++ b/source/smbd/ipc.c @@ -1013,7 +1013,7 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, int counted=0,total=0; int i; fstring domain; - BOOL domains = False; + BOOL domains; BOOL domain_request; BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY; diff --git a/source/utils/nmblookup.c b/source/utils/nmblookup.c index 4fbd8390368..a543b90762f 100644 --- a/source/utils/nmblookup.c +++ b/source/utils/nmblookup.c @@ -49,7 +49,7 @@ static BOOL open_sockets(void) return False; } - ServerFD = open_socket_in(SOCK_DGRAM, 0,3); + ServerFD = open_socket_in(SOCK_DGRAM, NMB_PORT,3); if (ServerFD == -1) return(False); @@ -164,7 +164,7 @@ int main(int argc,char *argv[]) strcpy(lookup,"\01\02__MSBROWSE__\02"); lookup_type = 1; } else { - lookup_type = 0x1d; + lookup_type = 0x1b; } } |