mirror of
https://github.com/samba-team/samba.git
synced 2025-08-02 00:22:11 +03:00
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 commit is contained in:
@ -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) {
|
||||
|
||||
/* Now, figure out what socket name we were bound to. We want the port */
|
||||
/* Try again on any port ... */
|
||||
|
||||
name_size = sizeof(sock_out);
|
||||
sock_out.sin_port = INADDR_ANY;
|
||||
|
||||
getsockname(dgram_sock, (struct sockaddr_in *)&sock_out, &name_size);
|
||||
if (bind(dgram_sock, (struct sockaddr_in *)&sock_out, sizeof(sock_out)) < 0) {
|
||||
|
||||
fprintf(stderr, "Socket bound to IP:%s, port: %d\n", inet_ntoa(sock_out.sin_addr), ntohs(sock_out.sin_port));
|
||||
DEBUG(4, ("failed to bind socket to address ...\n"));
|
||||
return False;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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], ®ister_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.
|
||||
*********************************************************/
|
||||
|
Reference in New Issue
Block a user