summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sharpe <sharpe@samba.org>2001-02-18 10:36:03 +0000
committerRichard Sharpe <sharpe@samba.org>2001-02-18 10:36:03 +0000
commit0293869b1f6012d1f106e4ab1bd392cea1c66ff0 (patch)
tree62aee01474ad53662e67737ef0c59ef5efc0ad84
parentfd46817f0b20c633c80dee70a29cf7478e2dfd68 (diff)
downloadsamba-0293869b1f6012d1f106e4ab1bd392cea1c66ff0.tar.gz
samba-0293869b1f6012d1f106e4ab1bd392cea1c66ff0.tar.bz2
samba-0293869b1f6012d1f106e4ab1bd392cea1c66ff0.zip
Fixes to libsmbclient so it will work when browsing real Windows systems which
only respond to port 138 when dealing with NetBIOS datagrams. We use the unexpected packed database. (This used to be commit 620cc34015ab16d25f7ef7e13cbc3d0f669da11e)
-rw-r--r--source3/libsmb/clidgram.c43
-rw-r--r--source3/libsmb/libsmbclient.c4
-rw-r--r--source3/libsmb/namequery.c153
3 files changed, 181 insertions, 19 deletions
diff --git a/source3/libsmb/clidgram.c b/source3/libsmb/clidgram.c
index c58e3fc796..68ac3b5c45 100644
--- a/source3/libsmb/clidgram.c
+++ b/source3/libsmb/clidgram.c
@@ -42,6 +42,7 @@ int cli_send_mailslot(BOOL unique, char *mailslot, char *buf, int len,
struct sockaddr_in sock_out;
char *ptr, *p2;
char tmp[4];
+ int name_size;
bzero((char *)&p, sizeof(p));
@@ -51,8 +52,6 @@ int cli_send_mailslot(BOOL unique, char *mailslot, char *buf, int len,
if (dgram_sock < 1) {
- int name_size;
-
if ((dgram_sock = open_socket_out(SOCK_DGRAM, &dest_ip, 138, LONG_CONNECT_TIMEOUT)) < 0) {
DEBUG(4, ("open_sock_out failed ..."));
@@ -67,22 +66,35 @@ int cli_send_mailslot(BOOL unique, char *mailslot, char *buf, int len,
/* Now, bind my addr to it ... */
bzero((char *)&sock_out, sizeof(sock_out));
- putip((char *)&sock_out.sin_addr, (char *)&src_ip);
- sock_out.sin_port = INADDR_ANY;
+ sock_out.sin_addr.s_addr = INADDR_ANY;
+ sock_out.sin_port = htons(138);
sock_out.sin_family = AF_INET;
- bind(dgram_sock, (struct sockaddr_in *)&sock_out, sizeof(sock_out));
+ if (bind(dgram_sock, (struct sockaddr_in *)&sock_out, sizeof(sock_out)) < 0) {
+
+ /* Try again on any port ... */
- /* Now, figure out what socket name we were bound to. We want the port */
+ sock_out.sin_port = INADDR_ANY;
- name_size = sizeof(sock_out);
+ if (bind(dgram_sock, (struct sockaddr_in *)&sock_out, sizeof(sock_out)) < 0) {
- getsockname(dgram_sock, (struct sockaddr_in *)&sock_out, &name_size);
+ DEBUG(4, ("failed to bind socket to address ...\n"));
+ return False;
- fprintf(stderr, "Socket bound to IP:%s, port: %d\n", inet_ntoa(sock_out.sin_addr), ntohs(sock_out.sin_port));
+ }
+
+ }
}
+ /* Now, figure out what socket name we were bound to. We want the port */
+
+ name_size = sizeof(sock_out);
+
+ getsockname(dgram_sock, (struct sockaddr_in *)&sock_out, &name_size);
+
+ fprintf(stderr, "Socket bound to IP:%s, port: %d\n", inet_ntoa(sock_out.sin_addr), ntohs(sock_out.sin_port));
+
/*
* Next, build the DGRAM ...
*/
@@ -93,8 +105,10 @@ int cli_send_mailslot(BOOL unique, char *mailslot, char *buf, int len,
dgram->header.flags.first = True;
dgram->header.flags.more = False;
dgram->header.dgm_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) + ((unsigned)sys_getpid()%(unsigned)100);
- dgram->header.source_ip = src_ip;
+ dgram->header.source_ip.s_addr = sock_out.sin_addr.s_addr;
+ fprintf(stderr, "Source IP = %0X\n", dgram->header.source_ip);
dgram->header.source_port = ntohs(sock_out.sin_port);
+ fprintf(stderr, "Source Port = %0X\n", dgram->header.source_port);
dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
dgram->header.packet_offset = 0;
@@ -147,7 +161,7 @@ int cli_get_response(BOOL unique, char *mailslot, char *buf, int bufsiz)
{
struct packet_struct *packet;
- packet = read_packet(dgram_sock, DGRAM_PACKET);
+ packet = receive_dgram_packet(dgram_sock, 2, mailslot);
if (packet) { /* We got one, pull what we want out of the SMB data ... */
@@ -166,7 +180,6 @@ int cli_get_response(BOOL unique, char *mailslot, char *buf, int bufsiz)
else
return -1;
- return 0;
}
/*
@@ -187,7 +200,7 @@ int cli_get_backup_list(const char *myname, const char *send_to_name)
}
- bzero(&my_ip, 4); /* Cheap way to get 0.0.0.0 in there */
+ my_ip.s_addr = inet_addr("0.0.0.0");
if (!resolve_name(myname, &my_ip, 0x00)) { /* FIXME: Call others here */
@@ -220,7 +233,6 @@ int cli_get_backup_list(const char *myname, const char *send_to_name)
/* Should check the response here ... FIXME */
- return 0;
}
/*
@@ -236,7 +248,4 @@ int cli_get_backup_server(char *my_name, char *target, char *servername, int nam
strncpy(servername, cli_backup_list, MIN(16, namesize));
- /* Should check the response here ... FIXME */
-
- return 0;
}
diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c
index 3541028fb8..67d5b92100 100644
--- a/source3/libsmb/libsmbclient.c
+++ b/source3/libsmb/libsmbclient.c
@@ -544,8 +544,6 @@ int smbc_init(smbc_get_auth_data_fn fn, int debug)
in_client = True; /* FIXME, make a param */
-
-
if (!lp_load(conf, True, False, False)) {
/*
@@ -563,6 +561,8 @@ int smbc_init(smbc_get_auth_data_fn fn, int debug)
reopen_logs(); /* Get logging working ... */
+ name_register_wins(my_netbios_name, 0);
+
/*
* Now initialize the file descriptor array and figure out what the
* max open files is, so we can return FD's that are above the max
diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
index 3e4855b037..f6ada87840 100644
--- a/source3/libsmb/namequery.c
+++ b/source3/libsmb/namequery.c
@@ -190,6 +190,100 @@ BOOL name_status_find(int type, struct in_addr to_ip, char *name)
return True;
}
+/****************************************************************************
+ Do a NetBIOS name registation to try to claim a name ...
+***************************************************************************/
+BOOL name_register(int fd, const char *name, int name_type,
+ struct in_addr name_ip, int opcode,
+ BOOL bcast,
+ struct in_addr to_ip, int *count)
+{
+ int i, retries = 3, retry = bcast?250:2000;
+ struct timeval tval;
+ struct packet_struct p;
+ struct packet_struct *p2;
+ struct nmb_packet *nmb = &p.packet.nmb;
+ struct in_addr register_ip;
+
+ DEBUG(4, ("name_register: %s as %s on %s\n", name, inet_ntoa(name_ip), inet_ntoa(to_ip)));
+
+ register_ip.s_addr = name_ip.s_addr; /* Fix this ... */
+
+ bzero((char *)&p, sizeof(p));
+
+ *count = 0;
+
+ nmb->header.name_trn_id = generate_trn_id();
+ nmb->header.opcode = opcode;
+ nmb->header.response = False;
+ nmb->header.nm_flags.bcast = False;
+ nmb->header.nm_flags.recursion_available = False;
+ nmb->header.nm_flags.recursion_desired = True; /* ? */
+ nmb->header.nm_flags.trunc = False;
+ nmb->header.nm_flags.authoritative = True;
+
+ nmb->header.qdcount = 1;
+ nmb->header.ancount = 0;
+ nmb->header.nscount = 0;
+ nmb->header.arcount = 1;
+
+ make_nmb_name(&nmb->question.question_name, name, name_type);
+
+ nmb->question.question_type = 0x20;
+ nmb->question.question_class = 0x1;
+
+ /* Now, create the additional stuff for a registration request */
+
+ if ((nmb->additional = (struct res_rec *)malloc(sizeof(struct res_rec))) == NULL) {
+
+ DEBUG(0, ("name_register: malloc fail for additional record.\n"));
+ return False;
+
+ }
+
+ bzero((char *)nmb->additional, 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;
+
+ nmb->additional->rdata[0] = NB_MFLAG & 0xFF;
+
+ /* Set the address for the name we are registering. */
+ putip(&nmb->additional->rdata[2], &register_ip);
+
+ p.ip = to_ip;
+ p.port = NMB_PORT;
+ p.fd = fd;
+ p.timestamp = time(NULL);
+ p.packet_type = NMB_PACKET;
+
+ GetTimeOfDay(&tval);
+
+ if (!send_packet(&p))
+ return False;
+
+ retries--;
+
+ if ((p2 = receive_nmb_packet(fd, 10, nmb->header.name_trn_id))) {
+ struct nmb_packet *nmb2 = &p2->packet.nmb;
+ debug_nmb_packet(p2);
+
+
+ free(p2); /* No memory leaks ... */
+
+ }
+
+ return True;
+}
/****************************************************************************
Do a netbios name query to find someones IP.
@@ -456,6 +550,65 @@ void endlmhosts(FILE *fp)
fclose(fp);
}
+BOOL name_register_wins(const char *name, int name_type)
+{
+ int sock, i, return_count;
+ int num_interfaces = iface_count();
+ struct in_addr sendto_ip;
+
+ /*
+ * Do a broadcast register ...
+ */
+
+ if (!lp_wins_server())
+ return False;
+
+ DEBUG(4, ("name_register_wins:Registering my name %s on %s\n", name, lp_wins_server()));
+
+ sock = open_socket_in(SOCK_DGRAM, 0, 3,
+ interpret_addr("0.0.0.0"), True);
+
+ if (sock == -1) return False;
+
+ set_socket_options(sock, "SO_BROADCAST");
+
+ sendto_ip.s_addr = inet_addr(lp_wins_server());
+
+ if (num_interfaces > 1) {
+
+ for (i = 0; i < num_interfaces; i++) {
+
+ if (!name_register(sock, name, name_type, *iface_n_ip(i),
+ NMB_NAME_MULTIHOMED_REG_OPCODE,
+ True, sendto_ip, &return_count)) {
+
+ close(sock);
+ return False;
+
+ }
+
+ }
+
+ }
+ else {
+
+ if (!name_register(sock, name, name_type, *iface_n_ip(0),
+ NMB_NAME_REG_OPCODE,
+ True, sendto_ip, &return_count)) {
+
+ close(sock);
+ return False;
+
+ }
+
+ }
+
+ close(sock);
+
+ return True;
+
+}
+
/********************************************************
Resolve via "bcast" method.
*********************************************************/