freebsd-dev/usr.sbin/XNSrouted/tools/query.c
1995-05-30 03:57:47 +00:00

233 lines
6.1 KiB
C

/*-
* Copyright (c) 1983, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* This code includes software contributed to Berkeley by
* Bill Nesheim at Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1983, 1986, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)query.c 8.1 (Berkeley) 6/5/93";
#endif /* not lint */
#include <sys/param.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netns/ns.h>
#include <netns/idp.h>
#include <errno.h>
#include <stdio.h>
#include <netdb.h>
#include "../protocol.h"
#define IDPPORT_RIF 1
#define WTIME 5 /* Time to wait for responses */
int s;
int timedout, timeout();
char packet[MAXPACKETSIZE];
extern int errno;
struct sockaddr_ns myaddr = {sizeof(myaddr), AF_NS};
char *ns_ntoa();
struct ns_addr ns_addr();
main(argc, argv)
int argc;
char *argv[];
{
int cc, count, bits;
struct sockaddr from;
int fromlen = sizeof(from);
struct timeval notime;
if (argc < 2) {
printf("usage: query hosts...\n");
exit(1);
}
s = getsocket(SOCK_DGRAM, 0);
if (s < 0) {
perror("socket");
exit(2);
}
argv++, argc--;
query(argv,argc);
/*
* Listen for returning packets;
* may be more than one packet per host.
*/
bits = 1 << s;
bzero(&notime, sizeof(notime));
signal(SIGALRM, timeout);
alarm(WTIME);
while (!timedout ||
select(20, &bits, 0, 0, &notime) > 0) {
struct nspacket {
struct idp hdr;
char data[512];
} response;
cc = recvfrom(s, &response, sizeof (response), 0,
&from, &fromlen);
if (cc <= 0) {
if (cc < 0) {
if (errno == EINTR)
continue;
perror("recvfrom");
(void) close(s);
exit(1);
}
continue;
}
rip_input(&from, response.data, cc);
count--;
}
}
static struct sockaddr_ns router = {sizeof(myaddr), AF_NS};
static struct ns_addr zero_addr;
static short allones[] = {-1, -1, -1};
query(argv,argc)
char **argv;
{
register struct rip *msg = (struct rip *)packet;
char *host = *argv;
int flags = 0;
struct ns_addr specific;
if (bcmp(*argv, "-r", 3) == 0) {
flags = MSG_DONTROUTE; argv++; argc--;
}
host = *argv;
router.sns_addr = ns_addr(host);
router.sns_addr.x_port = htons(IDPPORT_RIF);
if (ns_hosteq(zero_addr, router.sns_addr)) {
router.sns_addr.x_host = *(union ns_host *) allones;
}
msg->rip_cmd = htons(RIPCMD_REQUEST);
msg->rip_nets[0].rip_dst = *(union ns_net *) allones;
msg->rip_nets[0].rip_metric = htons(HOPCNT_INFINITY);
if (argc > 0) {
specific = ns_addr(*argv);
msg->rip_nets[0].rip_dst = specific.x_net;
specific.x_host = zero_addr.x_host;
specific.x_port = zero_addr.x_port;
printf("Net asked for was %s\n", ns_ntoa(specific));
}
if (sendto(s, packet, sizeof (struct rip), flags,
&router, sizeof(router)) < 0)
perror(host);
}
/*
* Handle an incoming routing packet.
*/
rip_input(from, msg, size)
struct sockaddr_ns *from;
register struct rip *msg;
int size;
{
struct netinfo *n;
char *name;
int lna, net, subnet;
struct hostent *hp;
struct netent *np;
static struct ns_addr work;
if (htons(msg->rip_cmd) != RIPCMD_RESPONSE)
return;
printf("from %s\n", ns_ntoa(from->sns_addr));
size -= sizeof (struct idp);
size -= sizeof (short);
n = msg->rip_nets;
while (size > 0) {
union ns_net_u net;
if (size < sizeof (struct netinfo))
break;
net.net_e = n->rip_dst;
printf("\t%d, metric %d\n", ntohl(net.long_e),
ntohs(n->rip_metric));
size -= sizeof (struct netinfo), n++;
}
}
timeout()
{
timedout = 1;
}
getsocket(type, proto)
int type, proto;
{
struct sockaddr_ns *sns = &myaddr;
int domain = sns->sns_family;
int retry, s, on = 1;
retry = 1;
while ((s = socket(domain, type, proto)) < 0 && retry) {
perror("socket");
sleep(5 * retry);
retry <<= 1;
}
if (retry == 0)
return (-1);
while (bind(s, sns, sizeof (*sns), 0) < 0 && retry) {
perror("bind");
sleep(5 * retry);
retry <<= 1;
}
if (retry == 0)
return (-1);
if (domain==AF_NS) {
struct idp idp;
if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) {
perror("setsockopt SEE HEADERS");
exit(1);
}
idp.idp_pt = NSPROTO_RI;
if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &idp, sizeof(idp))) {
perror("setsockopt SET HEADERS");
exit(1);
}
}
if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
perror("setsockopt SO_BROADCAST");
exit(1);
}
return (s);
}