This is ripquery.c in view mode; [Download] [Up]
/*
* $Header: /disk/d/src/devel/gated/dist/src/RCS/ripquery.c,v 2.1 92/02/24 14:12:53 jch Exp $
*/
/*%Copyright%*/
/************************************************************************
* *
* GateD, Release 2 *
* *
* Copyright (c) 1990,1991,1992 by Cornell University *
* All rights reserved. *
* *
* THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY *
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT *
* LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY *
* AND FITNESS FOR A PARTICULAR PURPOSE. *
* *
* Royalty-free licenses to redistribute GateD Release *
* 2 in whole or in part may be obtained by writing to: *
* *
* GateDaemon Project *
* Information Technologies/Network Resources *
* 143 Caldwell Hall *
* Cornell University *
* Ithaca, NY 14853-2602 *
* *
* GateD is based on Kirton's EGP, UC Berkeley's routing *
* daemon (routed), and DCN's HELLO routing Protocol. *
* Development of Release 2 has been supported by the *
* National Science Foundation. *
* *
* Please forward bug fixes, enhancements and questions to the *
* gated mailing list: gated-people@gated.cornell.edu. *
* *
* Authors: *
* *
* Jeffrey C Honig <jch@gated.cornell.edu> *
* Scott W Brim <swb@gated.cornell.edu> *
* *
*************************************************************************
* *
* Portions of this software may fall under the following *
* copyrights: *
* *
* Copyright (c) 1988 Regents of the University of California. *
* All rights reserved. *
* *
* Redistribution and use in source and binary forms are *
* permitted provided that the above copyright notice and *
* this paragraph are duplicated in all such forms and that *
* any documentation, advertising materials, and other *
* materials related to such distribution and use *
* acknowledge that the software was developed by the *
* University of California, Berkeley. The name of the *
* University may not be used to endorse or promote *
* products derived from this software without specific *
* prior written permission. THIS SOFTWARE IS PROVIDED *
* ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, *
* INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
* *
************************************************************************/
#ifndef __STDC__
#define const
#endif /* __STDC__ */
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/param.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#ifndef HPUX7_X
#include <arpa/inet.h>
#endif /* HPUX7_X */
#include <errno.h>
#include <stdio.h>
#include <netdb.h>
#define RIPCMDS
#include "routed.h"
/* macros to select internet address given pointer to a struct sockaddr */
/* result is u_long */
#define sock_inaddr(x) (((struct sockaddr_in *)(x))->sin_addr)
/* result is struct in_addr */
#define in_addr_ofs(x) (((struct sockaddr_in *)(x))->sin_addr)
/* Calculate the natural netmask for a given network */
#define inet_netmask(net) (IN_CLASSA(net) ? IN_CLASSA_NET :\
(IN_CLASSB(net) ? IN_CLASSB_NET :\
(IN_CLASSC(net) ? IN_CLASSC_NET : 0)))
#ifdef vax11c
#define perror(s) vmsperror(s)
#endif /* vax11c */
#define WTIME 5 /* Time to wait for responses */
#define STIME 1 /* Time to wait between packets */
int s;
char packet[MAXPACKETSIZE];
int cmds_request[] =
{RIPCMD_REQUEST, RIPCMD_POLL, 0};
int cmds_poll[] =
{RIPCMD_POLL, RIPCMD_REQUEST, 0};
int *cmds = cmds_poll;
int nflag;
int dflag;
const char *version = "$Revision: 2.1 $";
extern int errno;
extern char *optarg;
extern int optind, opterr;
extern char *inet_ntoa();
/*
* Return the possible subnetwork number from an internet address.
* SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING
* INSIDE OF THE HOST PART. We can only believe this if we have other
* information (e.g., we can find a name for this number).
*/
long
inet_subnetof(in)
struct in_addr in;
{
register long i = ntohl(in.s_addr);
if (IN_CLASSA(i))
return (i & IN_CLASSB_NET);
else if (IN_CLASSB(i))
return (i & IN_CLASSC_NET);
else
return (i & 0xffffffc0);
}
/*
* Trace RIP packets
*/
void
rip_trace(dir, who, cp, size)
struct sockaddr_in *who; /* should be sockaddr */
char *dir;
caddr_t cp;
register int size;
{
register struct rip *rpmsg = (struct rip *) cp;
register struct netinfo *n;
register const char *cmd = "Invalid";
if (rpmsg->rip_cmd && rpmsg->rip_cmd < RIPCMD_MAX) {
cmd = ripcmds[rpmsg->rip_cmd];
}
(void) fprintf(stderr, "RIP %s %s.%d vers %d, cmd %s, length %d",
dir,
inet_ntoa(who->sin_addr),
ntohs(who->sin_port),
rpmsg->rip_vers,
cmd, size);
switch (rpmsg->rip_cmd) {
#ifdef RIPCMD_POLL
case RIPCMD_POLL:
#endif /* RIPCMD_POLL */
case RIPCMD_REQUEST:
case RIPCMD_RESPONSE:
(void) fprintf(stderr, "\n");
size -= 4 * sizeof(char);
n = rpmsg->rip_nets;
for (; size > 0; n++, size -= sizeof(struct netinfo)) {
if (size < sizeof(struct netinfo)) {
break;
}
(void) fprintf(stderr, "\tnet %-15s metric %2d size %d\n", inet_ntoa(sock_inaddr(&n->rip_dst)),
ntohl((u_long) n->rip_metric), size);
}
(void) fprintf(stderr, "RIP %s end of packet", dir);
break;
case RIPCMD_TRACEON:
(void) fprintf(stderr, ", file %*s", size, rpmsg->rip_tracefile);
break;
#ifdef RIPCMD_POLLENTRY
case RIPCMD_POLLENTRY:
n = rpmsg->rip_nets;
(void) fprintf(stderr, ", net %s", inet_ntoa(sock_inaddr(&n->rip_dst)));
break;
#endif /* RIPCMD_POLLENTRY */
default:
(void) fprintf(stderr, "\n");
break;
}
(void) fprintf(stderr, "\n");
}
void
query(host, cmd)
char *host;
int cmd;
{
struct sockaddr_in router;
register struct rip *msg = (struct rip *) packet;
struct hostent *hp;
struct servent *sp;
bzero((char *) &router, sizeof(router));
hp = gethostbyname(host);
if (hp == 0) {
router.sin_addr.s_addr = inet_addr(host);
if (router.sin_addr.s_addr == (u_long) - 1) {
(void) printf("%s: unknown\n", host);
exit(1);
}
} else {
(void) memcpy((char *) &router.sin_addr, hp->h_addr, hp->h_length);
}
sp = getservbyname("router", "udp");
if (sp == NULL) {
(void) fprintf(stderr, "No service for router available\n");
exit(1);
}
router.sin_family = AF_INET;
router.sin_port = sp->s_port;
msg->rip_cmd = cmd;
msg->rip_vers = RIPVERSION;
msg->rip_nets[0].rip_dst.rip_family = htons(AF_UNSPEC);
msg->rip_nets[0].rip_metric = htonl((u_long) HOPCNT_INFINITY);
if (dflag) {
rip_trace("SEND", &router, (caddr_t) msg, sizeof(struct rip));
}
if (sendto(s, packet, sizeof(struct rip), 0, (struct sockaddr *) & router, sizeof(router)) < 0)
perror(host);
}
/*
* Handle an incoming routing packet.
*/
void
rip_input(from, size)
struct sockaddr_in *from;
int size;
{
register struct rip *msg = (struct rip *) packet;
struct netinfo *n;
const char *name;
u_long lna, net, subnet;
struct hostent *hp;
struct netent *np;
if (dflag) {
rip_trace("RECV", from, (caddr_t) msg, size);
}
if (msg->rip_cmd != RIPCMD_RESPONSE)
return;
hp = gethostbyaddr((char *) &from->sin_addr, sizeof(struct in_addr), AF_INET);
name = hp == 0 ? "???" : hp->h_name;
(void) printf("%d bytes from %s(%s):\n", size, name, inet_ntoa(from->sin_addr));
size -= sizeof(int);
n = msg->rip_nets;
while (size > 0) {
register struct sockaddr_in *sin;
int i;
if (size < sizeof(struct netinfo))
break;
if (msg->rip_vers) {
n->rip_dst.rip_family = ntohs(n->rip_dst.rip_family);
n->rip_metric = ntohl((u_long) n->rip_metric);
}
sin = (struct sockaddr_in *) & n->rip_dst;
if (sin->sin_port) {
(void) printf("**Non-zero port (%d) **",
sin->sin_port & 0xFFFF);
}
for (i = 0; i < 8; i++)
if (n->rip_dst.rip_zero2[i]) {
(void) printf("sockaddr = ");
for (i = 0; i < 8; i++)
(void) printf("%d ", n->rip_dst.rip_zero2[i] & 0xFF);
break;
}
net = inet_netmask(ntohl(sin->sin_addr.s_addr)) & ntohl(sin->sin_addr.s_addr);
subnet = inet_subnetof(sin->sin_addr);
lna = inet_lnaof(sin->sin_addr);
name = "???";
if (!nflag) {
if (net == 0) {
name = "default";
} else if (lna == INADDR_ANY) {
net = IN_CLASSA(net) ? net >> IN_CLASSA_NSHIFT :
IN_CLASSB(net) ? net >> IN_CLASSB_NSHIFT :
net >> IN_CLASSC_NSHIFT;
np = getnetbyaddr(net, AF_INET);
if (np)
name = np->n_name;
} else if (sin->sin_addr.s_addr == htonl(subnet)) {
subnet = IN_CLASSA(subnet) ? subnet >> IN_CLASSB_NSHIFT :
IN_CLASSB(subnet) ? subnet >> IN_CLASSC_NSHIFT :
subnet >> 4;
np = getnetbyaddr(subnet, AF_INET);
if (np)
name = np->n_name;
} else {
hp = gethostbyaddr((char *) &sin->sin_addr, sizeof(struct in_addr), AF_INET);
if (hp)
name = hp->h_name;
}
(void) printf("\t%s(%s), metric %d\n", name,
inet_ntoa(sin->sin_addr), n->rip_metric);
} else {
(void) printf("\t%s, metric %d\n",
inet_ntoa(sin->sin_addr), n->rip_metric);
}
size -= sizeof(struct netinfo), n++;
}
}
int
main(argc, argv)
int argc;
char *argv[];
{
int c, cc, bits, errflg = 0, *cmd = cmds;
struct sockaddr from;
int fromlen = sizeof(from);
static struct timeval *wait_time, long_time =
{WTIME, 0}, short_time =
{STIME, 0};
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
perror("socket");
#ifdef vax11c
exit(0x10000002);
#else /* vax11c */
exit(2);
#endif /* vax11c */
}
while ((c = getopt(argc, argv, "dnprvw:")) != EOF) {
switch (c) {
case 'd':
dflag++;
break;
case 'n':
nflag++;
break;
case 'p':
cmd = cmds_poll;
break;
case 'r':
cmd = cmds_request;
break;
case 'v':
(void) fprintf(stderr, "RIPQuery %s\n", version);
break;
case 'w':
long_time.tv_sec = atoi(optarg);
(void) fprintf(stderr, "Wait time set to %d\n", long_time.tv_sec);
break;
case '?':
errflg++;
break;
}
}
if (errflg || (optind >= argc)) {
(void) printf("usage: ripquery [ -d ] [ -n ] [ -p ] [ -r ] [ -v ] [ -w time] hosts...\n");
exit(1);
}
setnetent(1);
for (; optind < argc; optind++) {
retry:
query(argv[optind], *cmd);
bits = 1 << s;
wait_time = &long_time;
for (;;) {
#ifndef vax11c
cc = select(s + 1, (struct fd_set *) & bits, (struct fd_set *) 0, (struct fd_set *) 0, wait_time);
#else /* vax11c */
cc = Socket_Ready(s, wait_time->tv_sec);
#endif /* vax11c */
if (cc == 0) {
if (wait_time == &short_time) {
break;
}
if (*(++cmd)) {
goto retry;
} else {
break;
}
} else if (cc < 0) {
perror("select");
(void) close(s);
exit(1);
} else {
wait_time = &short_time;
cc = recvfrom(s, packet, sizeof(packet), 0, &from, &fromlen);
if (cc <= 0) {
if (cc < 0) {
if (errno == EINTR) {
continue;
}
perror("recvfrom");
(void) close(s);
exit(1);
}
continue;
}
rip_input((struct sockaddr_in *) & from, cc);
}
}
}
endnetent();
exit(0);
return (0);
}
#ifdef vax11c
/*
* See if a socket is ready for reading (waiting "n" seconds)
*/
static int
Socket_Ready(Socket, Wait_Time)
{
#include <vms/iodef.h>
#define EFN_1 20
#define EFN_2 21
int Status;
int Timeout_Delta[2];
int Dummy;
unsigned short int IOSB[4];
/*
* Check for data (using MSG_PEEK)
*/
Status = SYS$QIO(EFN_1,
Socket,
IO$_READVBLK,
IOSB,
0,
0,
&Dummy,
sizeof(Dummy),
MSG_PEEK,
0,
0,
0);
/*
* Check for completion
*/
if (IOSB[0] != 0) {
return (1);
}
/*
* Setup timer
*/
if (Wait_Time) {
Timeout_Delta[0] = -(Wait_Time * 10000000);
Timeout_Delta[1] = -1;
SYS$SETIMR(EFN_2, Timeout_Delta, 0, Socket_Ready);
SYS$WFLOR(EFN_1, (1 << EFN_1) | (1 << EFN_2));
if (IOSB[0] != 0) {
SYS$CANTIM(Socket_Ready, 0);
return (1);
}
}
/*
* Last chance
*/
if (IOSB[0] == 0) {
/*
* Lose:
*/
SYS$CANCEL(Socket);
return (0);
}
return (1);
}
#endif /* vax11c */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.