1
0
mirror of https://github.com/samba-team/samba.git synced 2025-06-03 17:05:54 +03:00
samba-mirror/source/utils/nmb-agent.c

296 lines
5.7 KiB
C

/*
Unix SMB/Netbios implementation.
Version 2
SMB agent/socket plugin
Copyright (C) Andrew Tridgell 1999
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
#include "smb.h"
#define SECURITY_MASK 0
#define SECURITY_SET 0
/* this forces non-unicode */
#define CAPABILITY_MASK CAP_UNICODE
#define CAPABILITY_SET 0
/* and non-unicode for the client too */
#define CLI_CAPABILITY_MASK CAP_UNICODE
#define CLI_CAPABILITY_SET 0
extern int DEBUGLEVEL;
static int ClientNMB = -1;
/****************************************************************************
terminate sockent connection
****************************************************************************/
static void free_sock(void *sock)
{
if (sock != NULL)
{
free(sock);
}
}
static void filter_reply(struct packet_struct *p, int tr_id)
{
p->packet.nmb.header.name_trn_id = tr_id;
}
static BOOL process_cli_sock(struct sock_redir **socks,
uint32 num_socks,
struct sock_redir *sock)
{
struct packet_struct *p;
struct nmb_state *nmb;
static uint16 trn_id = 0x0;
p = receive_packet(sock->c, NMB_SOCK_PACKET, 0);
if (p == NULL)
{
DEBUG(0,("client closed connection\n"));
return False;
}
nmb = (struct nmb_state*)malloc(sizeof(struct nmb_state));
if (nmb == NULL)
{
free_packet(p);
return False;
}
sock->s = ClientNMB;
sock->n = nmb;
sock->c_id = p->packet.nmb.header.name_trn_id;
sock->s_id = trn_id;
trn_id++;
if (trn_id > 0xffff)
{
trn_id = 0x0;
}
DEBUG(10,("new trn_id: %d\n", trn_id));
filter_reply(p, sock->s_id);
nmb->ip = p->ip;
nmb->port = p->port;
p->fd = ClientNMB;
p->packet_type = NMB_PACKET;
if (!send_packet(p))
{
DEBUG(0,("server is dead\n"));
free_packet(p);
return False;
}
free_packet(p);
return True;
}
static BOOL process_srv_sock(struct sock_redir **socks,
uint32 num_socks,
int fd)
{
int nmb_id;
int tr_id;
int i;
struct packet_struct *p;
p = receive_packet(fd, NMB_PACKET, 0);
if (p == NULL)
{
return True;
}
#if 0
if (!p->packet.nmb.header.response)
{
DEBUG(10,("skipping response packet\n"));
free_packet(p);
return True;
}
#endif
nmb_id = p->packet.nmb.header.name_trn_id;
DEBUG(10,("process_srv_sock:\tnmb_id:\t%d\n", nmb_id));
for (i = 0; i < num_socks; i++)
{
if (socks[i] == NULL)
{
continue;
}
tr_id = socks[i]->s_id;
DEBUG(10,("list:\tfd:\t%d\tc_id:\t%d\ttr_id:\t%d\n",
socks[i]->c,
socks[i]->c_id,
tr_id));
if (nmb_id != tr_id)
{
continue;
}
filter_reply(p, socks[i]->c_id);
p->fd = socks[i]->c;
p->packet_type = NMB_SOCK_PACKET;
if (!send_packet(p))
{
DEBUG(0,("client is dead\n"));
return False;
}
return True;
}
return True;
}
static int get_agent_sock(char *id)
{
fstring dir;
fstring path;
slprintf(dir, sizeof(dir)-1, "/tmp/.nmb");
slprintf(path, sizeof(path)-1, "%s/agent", dir);
return create_pipe_socket(dir, 0777, path, 0777);
}
static void start_nmb_agent(void)
{
struct vagent_ops va =
{
free_sock,
get_agent_sock,
process_cli_sock,
process_srv_sock,
NULL,
NULL,
0
};
CatchChild();
start_agent(&va);
}
/******************************************************************************
open the socket communication
*****************************************************************************/
static BOOL open_sockets(BOOL isdaemon, int port)
{
/* The sockets opened here will be used to receive broadcast
packets *only*. Interface specific sockets are opened in
make_subnet() in namedbsubnet.c. Thus we bind to the
address "0.0.0.0". The parameter 'socket address' is
now deprecated.
*/
if ( isdaemon )
ClientNMB = open_socket_in(SOCK_DGRAM, port,0,0);
else
ClientNMB = 0;
if ( ClientNMB == -1 )
return( False );
/* we are never interested in SIGPIPE */
BlockSignals(True,SIGPIPE);
set_socket_options( ClientNMB, "SO_BROADCAST" );
DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) );
return( True );
} /* open_sockets */
/****************************************************************************
usage on the program
****************************************************************************/
static void usage(char *pname)
{
printf("Usage: %s [-D]", pname);
printf("\nVersion %s\n",VERSION);
printf("\t-D run as a daemon\n");
printf("\t-h usage\n");
printf("\n");
}
int main(int argc, char *argv[])
{
pstring configfile;
BOOL is_daemon = False;
int opt;
extern pstring debugf;
int global_nmb_port = NMB_PORT;
TimeInit();
pstrcpy(configfile,CONFIGFILE);
while ((opt = getopt(argc, argv, "Dh")) != EOF)
{
switch (opt)
{
case 'D':
{
is_daemon = True;
break;
}
case 'h':
default:
{
usage(argv[0]);
break;
}
}
}
slprintf(debugf, sizeof(debugf)-1, "log.%s", argv[0]);
setup_logging(argv[0], !is_daemon);
charset_initialise();
if (!lp_load(configfile,True,False,False))
{
DEBUG(0,("Unable to load config file\n"));
}
if (is_daemon)
{
DEBUG(0,("%s: becoming daemon\n", argv[0]));
become_daemon();
}
if (!open_sockets(True, global_nmb_port))
{
return 1;
}
start_nmb_agent();
return 0;
}