/****************************************************************************
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;
p = param;
SSVAL(p,0,0x68); /* api number */
p += 2;
- strcpy(p,"WrLehDO");
+ strcpy(p,"WrLehDz");
p = skip_string(p,1);
strcpy(p,"B16BBDz");
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,
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;
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,
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;
sleep(1);
browse_host(True);
}
- if (!list_servers()) {
+ if (!list_servers(workgroup)) {
sleep(1);
- list_servers();
+ list_servers(workgroup);
}
send_logout();
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
{
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);
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,
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);
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);
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);
-#define VERSION "1.9.16alpha10"
+#define VERSION "1.9.16a10"
continue;
}
+ debug_nmb_packet(p2);
+
_interpret_node_status(&nmb2->answers->rdata[0], master,rname);
free_packet(p2);
return(True);
continue;
}
+ debug_nmb_packet(p2);
+
if (nmb2->header.opcode != 0 ||
nmb2->header.nm_flags.bcast ||
nmb2->header.rcode ||
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
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)
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
*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
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));
}
}
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),
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",
/* 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
{
struct work_record *work;
+ if (ip_equal(d->bcast_ip, ipgrp)) continue;
+
for (work = d->workgrouplist; work; work = work->next)
{
uint32 stype = work->ServerType;
**************************************************************************/
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;
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;
{
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
{
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);
}
}
+/****************************************************************************
+ 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 *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))
extern pstring myname;
extern struct in_addr ipzero;
+extern struct in_addr ipgrp;
/* machine comment for host announcements */
extern pstring ServerComment;
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);
}
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)
{
/* 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 );
}
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;
}
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",
become_master(d, work);
}
- }
+ }
}
- }
+ }
}
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
**************************************************************************/
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)
{
p = *p1;
- switch (rr_type)
+ switch (rcv_code)
{
case NMB_STATUS:
{
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));
}
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:
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);
/* 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
{
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
extern pstring scope;
extern pstring myname;
+extern pstring ServerComment;
extern struct in_addr ipzero;
extern struct in_addr ipgrp;
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
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);
}
}
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);
}
}
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);
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);
+ }
+ }
}
/****************************************************************************
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)
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);
}
/****************************************************************************
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)
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);
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);
}
/* 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);
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);
}
int names_added;
struct name_record *n;
struct subnet_record *d = NULL;
+ int search = FIND_SELF;
BOOL bcast = nmb->header.nm_flags.bcast;
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;
/* 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,
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 "));
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;
}
}
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,
}
/* 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);
}
/****************************************************************************
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)
extern time_t StartupTime;
+extern BOOL updatedlists;
/****************************************************************************
tell a server to become a backup browser
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;
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;
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,
*/
work_name = name;
+ add = True;
} else {
work_name = dgram->dest_name.name;
}
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 */
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;
/* 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;
- }
+ }
}
- }
+ }
}
- }
+ }
}
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)
{
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)
/* 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));
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));
}
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)));
{
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;
}
}
}
}
-
/*******************************************************************
process a announcement request
case ANN_DomainAnnouncement:
case ANN_LocalMasterAnnouncement:
{
+ debug_browse_data(buf, len);
process_announce(p,command,buf+1);
break;
}
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:
{
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 */
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;
return False;
}
- ServerFD = open_socket_in(SOCK_DGRAM, 0,3);
+ ServerFD = open_socket_in(SOCK_DGRAM, NMB_PORT,3);
if (ServerFD == -1)
return(False);
strcpy(lookup,"\01\02__MSBROWSE__\02");
lookup_type = 1;
} else {
- lookup_type = 0x1d;
+ lookup_type = 0x1b;
}
}