/* locbrok - location broker
* vix 13sep91 [written]
*/
#ifndef LINT
static char RCSid[] = "$Id: locbrok.c,v 1.9 2001/03/24 21:14:26 vixie Exp $";
#endif
/* Copyright (c) 1996 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#ifdef DEBUG
int Debug = 0;
#endif
#ifdef WANT_TCPIP
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "rtty.h"
#include "misc.h"
#include "locbrok.h"
#define USAGE_STR "[-s service] [-x debuglev]"
/* misc.c */
#ifndef isnumber
extern int isnumber(char *);
#endif
typedef struct reg_db {
char *name;
u_short port;
u_short client;
struct reg_db *next;
} reg_db;
static reg_db *find_byname(char *name),
*find_byport(u_int port);
static int add(char *name, u_int port, u_int client);
static void server(void),
client_input(int fd),
rm_byclient(u_int client),
print(void);
static char *ProgName = "amnesia",
*Service = LB_SERVNAME;
static int Port,
MaxFD;
static fd_set Clients;
static reg_db *RegDB = NULL;
main(int argc, char *argv[]) {
struct servent *serv;
char ch;
ProgName = argv[0];
while ((ch = getopt(argc, argv, "s:x:")) != EOF) {
switch (ch) {
case 's':
Service = optarg;
break;
case 'x':
Debug = atoi(optarg);
break;
default:
USAGE((stderr, "%s: getopt=%c ?\n", ProgName, ch));
}
}
if (isnumber(Service) && (Port = atoi(Service))) {
/* numeric service; we're ok */
;
} else if (NULL != (serv = getservbyname(Service, "tcp"))) {
/* found the service name; we're ok */
Port = ntohs(serv->s_port);
} else {
/* nothing worked; use default */
Port = LB_SERVPORT;
fprintf(stderr, "%s: service `%s' not found, using port %d\n",
ProgName, Service, Port);
}
server();
}
static void
server(void) {
int serv, on = 1;
struct sockaddr_in name;
serv = socket(PF_INET, SOCK_STREAM, 0);
ASSERT(serv>=0, "socket")
setsockopt(serv, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on);
name.sin_family = AF_INET;
#ifndef NO_SOCKADDR_LEN
name.sin_len = sizeof(struct sockaddr_in);
#endif
name.sin_addr.s_addr = INADDR_ANY;
name.sin_port = htons(Port);
ASSERT(bind(serv, (struct sockaddr *)&name, sizeof name)>=0, "bind")
FD_ZERO(&Clients);
MaxFD = serv;
listen(serv, 5);
for (;;) {
fd_set readfds;
int nset, fd;
readfds = Clients;
FD_SET(serv, &readfds);
nset = select(MaxFD+1, &readfds, NULL, NULL, NULL);
if (nset < 0 && errno == EINTR)
continue;
ASSERT(nset>=0, "assert")
for (fd = 0; fd <= MaxFD; fd++) {
if (!FD_ISSET(fd, &readfds))
continue;
if (fd == serv) {
int namesize = sizeof name;
int addr, local, cl;
ASSERT((cl=accept(serv,
(struct sockaddr *)&name,
&namesize))>=0,
"accept")
addr = ntohl(name.sin_addr.s_addr);
local = (addr == INADDR_ANY) ||
((IN_CLASSA(addr) &&
(addr & IN_CLASSA_NET) >>
IN_CLASSA_NSHIFT)
== IN_LOOPBACKNET);
fprintf(stderr,
"accept from %08x (%slocal)\n",
addr, local?"":"not ");
FD_SET(cl, &Clients);
if (cl > MaxFD)
MaxFD = cl;
continue;
}
if (FD_ISSET(fd, &Clients)) {
client_input(fd);
}
}
}
}
static void
client_input(int fd) {
locbrok lb;
reg_db *db;
int keepalive = 0;
if (0 >= read(fd, &lb, sizeof lb)) {
fputs("locbrok.client_input: ", stderr);
perror("read");
goto death;
}
lb.lb_port = ntohs(lb.lb_port);
lb.lb_nlen = ntohs(lb.lb_nlen);
if (lb.lb_nlen >= LB_MAXNAMELEN) {
fprintf(stderr, "client_input: fd%d sent oversize req\n", fd);
goto death;
}
lb.lb_name[lb.lb_nlen] = '\0';
fprintf(stderr, "client_input(fd %d, port %d, %d:`%s')\n",
fd, lb.lb_port, lb.lb_nlen, lb.lb_name);
if (lb.lb_port && !lb.lb_nlen) {
if (NULL != (db = find_byport(lb.lb_port))) {
lb.lb_nlen = min(strlen(db->name), LB_MAXNAMELEN);
strncpy(lb.lb_name, db->name, lb.lb_nlen);
}
} else if (!lb.lb_port && lb.lb_nlen) {
if (NULL != (db = find_byname(lb.lb_name))) {
lb.lb_port = db->port;
}
} else if (lb.lb_port && lb.lb_nlen) {
if (add(lb.lb_name, lb.lb_port, fd) == -1) {
lb.lb_nlen = 0;
} else {
keepalive++;
print();
}
} else {
fprintf(stderr, "bogus client_input (port,nlen both 0)\n");
goto death;
}
lb.lb_port = htons(lb.lb_port);
lb.lb_nlen = htons(lb.lb_nlen);
write(fd, &lb, sizeof lb);
if (keepalive)
return;
death:
close(fd);
FD_CLR(fd, &Clients);
rm_byclient(fd);
print();
}
static reg_db *
find_byname(const char *name) {
reg_db *db;
for (db = RegDB; db; db = db->next)
if (!strcmp(name, db->name))
return (db);
return (NULL);
}
static reg_db *
find_byport(u_int port) {
reg_db *db;
for (db = RegDB; db; db = db->next)
if (port == db->port)
return (db);
return (NULL);
}
static int
add(const char *name, u_int port, u_int client) {
reg_db *db;
if (find_byname(name) || find_byport(port))
return (-1);
db = (reg_db *) safe_malloc(sizeof(reg_db));
db->name = safe_malloc(strlen(name)+1);
strcpy(db->name, name);
db->port = port;
db->client = client;
db->next = RegDB;
RegDB = db;
return (0);
}
static void
rm_byclient(u_int client) {
reg_db *cur = RegDB, *prev = NULL;
while (cur) {
if (cur->client == client) {
reg_db *tmp = cur;
if (prev)
prev->next = cur->next;
else
RegDB = cur->next;
cur = cur->next;
free(tmp->name);
free(tmp);
} else {
prev = cur;
cur = cur->next;
}
}
}
static void
print(void) {
reg_db *db;
fprintf(stderr, "db:\n");
for (db = RegDB; db; db = db->next)
fprintf(stderr, "(%s %d %d)\n",
db->name, db->port, db->client);
fprintf(stderr, "---\n");
}
#else /*WANT_TCPIP*/
#include <stdio.h>
int
main(int argc, char *argv[]) {
fprintf(stderr, "There is no location broker for this system.\n");
exit(1);
}
#endif /*WANT_TCPIP*/
syntax highlighted by Code2HTML, v. 0.9.1