[Samba] Netbios name service forwarding.
James
james at madingley.org
Thu Feb 20 22:26:08 GMT 2003
I wrote this little program to deal with the situation
where there are a number of workgroups on a number of
subnets with no WINS server [actually I couldn't get this
configuration to run with a WINS server - but that's
another story]
You run this program on machines bridging your subnets and
it listens for netbios nameserver packets and forwards
them. [Broadcast packets are sent on to other nets as
broadcast packets, the unicast replies are returned as
unicast replies] It also sends a copy of any netbios
traffic it sees to the local nmbd which will be running
on a different port.
So I have a machine running samba bridging
eth0 192.168.42.0/24
eth1 192.168.48.0/24
I start nmbd with nmbd -D -p 138
and this program
nbnsfw 138 eth0 eth1
then my windows machines on each side can resolve names
without a WINS server and across multiple workgroups.
take care,
J.
-------------- next part --------------
/*
* nbnsfw.c:
*
* Copyright (c) 2003 James McKenzie <james at fishsoup.dhs.org>,
* 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.
*
*/
static char rcsid[] =
"$Id: nbnsfw.c,v 1.2 2003/02/20 22:00:46 root Exp root $";
/*
* $Log: nbnsfw.c,v $
* Revision 1.2 2003/02/20 22:00:46 root
* #
*
* Revision 1.1 2003/02/20 21:54:22 root
* Initial revision
*
*/
#include <syslog.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <malloc.h>
#include <net/if.h>
#include <arpa/inet.h>
#define NETBIOSPORT 137
typedef struct iface_struct
{
struct iface_struct *next;
char *name;
int fd;
struct sockaddr_in me;
struct sockaddr_in nmbd;
struct sockaddr_in bcast;
struct sockaddr_in addr_cache[0x10000];
}
*iface;
iface ifs;
void
open_if (char *name, int nb_port, int dm_port)
{
struct sockaddr_in me = { 0 };
iface i = (iface) malloc (sizeof (struct iface_struct));
int fd;
int one = 1;
int j;
struct ifreq ifr = { 0 };
bzero (i, sizeof (struct iface_struct));
i->name = strdup (name);
i->fd = socket (AF_INET, SOCK_DGRAM, 0);
if (i->fd < 0)
{
syslog (LOG_ERR, "Can't open socket: %m");
exit (1);
}
strcpy (&ifr.ifr_name[0], name);
if (setsockopt (i->fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof (ifr)))
{
syslog (LOG_ERR, "Can't bind to interface %s: %m", name);
exit (1);
}
bzero (&ifr, sizeof (ifr));
strcpy (&ifr.ifr_name[0], name);
if (ioctl (i->fd, SIOCGIFADDR, &ifr))
{
syslog (LOG_ERR, "Can't get ip address for interface %s: %m", name);
exit (1);
}
bcopy (&ifr.ifr_addr, &i->me, sizeof (struct sockaddr_in));
i->me.sin_port = htons (nb_port);
bzero (&ifr, sizeof (ifr));
strcpy (&ifr.ifr_name[0], name);
if (ioctl (i->fd, SIOCGIFBRDADDR, &ifr))
{
syslog (LOG_ERR, "Can't get broadcast address for interface %s: %m",
name);
exit (1);
}
bcopy (&ifr.ifr_addr, &i->bcast, sizeof (struct sockaddr_in));
i->bcast.sin_port = htons (nb_port);
me.sin_addr.s_addr = INADDR_ANY;
me.sin_port = htons (nb_port);
if (bind (i->fd, (struct sockaddr *) &me, sizeof (struct sockaddr_in)) < 00)
{
syslog (LOG_ERR, "Can't bind to port %d on interface %s: %m",
nb_port, name);
exit (1);
}
if (setsockopt (i->fd, SOL_SOCKET, SO_BROADCAST, &one, sizeof (one)))
{
syslog (LOG_ERR, "Can't enable broadcasts on interface %s: %m", name);
exit (1);
}
i->nmbd = i->me;
i->nmbd.sin_port = htons (dm_port);
for (j = 0; j < 0x10000; ++j)
{
i->addr_cache[j].sin_addr.s_addr = INADDR_BROADCAST;
i->addr_cache[j].sin_port = htons (nb_port);
}
{
char buf[1024], *ptr = buf;
ptr +=
sprintf (ptr, "Initialized %s ip %s", name, inet_ntoa (i->me.sin_addr));
ptr += sprintf (ptr, " bcast %s", inet_ntoa (i->bcast.sin_addr));
syslog (LOG_ERR, ptr);
}
i->next = ifs;
ifs = i;
}
int
main (int argc, char **argv)
{
unsigned char buf[8192];
int w = getdtablesize ();
int len;
int fromlen;
iface i, j;
struct sockaddr_in from;
fd_set rfds;
int tid;
int bcast;
int dmport;
if (argc < 3)
{
fprintf (stderr, "Usage:\n");
fprintf (stderr, "%s nmbdport interface [interface] [interface] ...\n");
exit (1);
}
openlog ("nbnsfw", LOG_CONS, LOG_DAEMON);
daemon (0, 0);
setsid ();
argc--;
argv++;
dmport = atoi (*(argv++));
argc--;
while (argc--)
{
open_if (*(argv++), NETBIOSPORT, dmport);
}
syslog (LOG_ERR, "Local nmbd port is %d", dmport);
for (;;)
{
FD_ZERO (&rfds);
for (i = ifs; i; i = i->next)
FD_SET (i->fd, &rfds);
select (w, &rfds, 0, 0, NULL);
for (i = ifs; i; i = i->next)
{
if (FD_ISSET (i->fd, &rfds))
{
int me = 0;
bzero (&from, fromlen = sizeof (from));
len =
recvfrom (i->fd, buf, sizeof (buf), 0,
(struct sockaddr *) &from, &fromlen);
if (!len)
continue;
if (fromlen != sizeof (struct sockaddr_in))
continue;
for (j = ifs; j; j = j->next)
if (from.sin_addr.s_addr == j->me.sin_addr.s_addr)
me++;
if (me)
continue;
tid = (buf[0] << 8) + buf[1];
bcast = buf[3] & 0x10;
i->addr_cache[tid] = from;
#if 0
printf ("%s %s.%d T%04x %s ->\n",
i->name, inet_ntoa (from.sin_addr),
ntohs (from.sin_port), tid,
bcast ? "(BROAD)" : " ");
#endif
for (j = ifs; j; j = j->next)
{
struct sockaddr_in to;
if (j == i)
continue;
if (bcast)
{
/*It's a broadcast packet send it out */
/*on the bcast address */
to = j->bcast;
}
else
{
/*It's unicast, look up the tid and send */
/*it to a responsible citizen */
to = j->addr_cache[tid];
}
#if 0
printf ("\t\t\t\t\t\t%s %s.%d\n", j->name,
inet_ntoa (to.sin_addr), ntohs (to.sin_port));
#endif
sendto (j->fd, buf, len, 0, (struct sockaddr *) &to,
sizeof (struct sockaddr_in));
}
/*Copy any packets we se to our poor belegured NMB */
/*Deamon running on port whatever on the interface */
/*the packet entered on */
sendto (i->fd, buf, len, 0, (struct sockaddr *) &i->nmbd,
sizeof (struct sockaddr_in));
}
}
}
}
More information about the samba
mailing list