148130Sbostic /*-
261541Sbostic * Copyright (c) 1982, 1986, 1993
361541Sbostic * The Regents of the University of California. All rights reserved.
433488Sbostic *
548130Sbostic * %sccs.include.redist.c%
622643Sdist */
722643Sdist
86918Ssam #ifndef lint
961541Sbostic static char copyright[] =
1061541Sbostic "@(#) Copyright (c) 1982, 1986, 1993\n\
1161541Sbostic The Regents of the University of California. All rights reserved.\n";
1233488Sbostic #endif /* not lint */
136918Ssam
1433488Sbostic #ifndef lint
15*69038Sbostic static char sccsid[] = "@(#)query.c 8.3 (Berkeley) 04/28/95";
1633488Sbostic #endif /* not lint */
1733488Sbostic
186918Ssam #include <sys/param.h>
196918Ssam #include <sys/protosw.h>
206918Ssam #include <sys/socket.h>
2115760Skarels #include <sys/time.h>
2246785Sbostic #include <signal.h>
2315760Skarels #include <netinet/in.h>
2446785Sbostic #include <protocols/routed.h>
2546785Sbostic #include <arpa/inet.h>
2646785Sbostic #include <netdb.h>
276918Ssam #include <errno.h>
2846785Sbostic #include <unistd.h>
296918Ssam #include <stdio.h>
3046785Sbostic #include <stdlib.h>
3146785Sbostic #include <string.h>
326918Ssam
3327344Skarels #define WTIME 5 /* Time to wait for all responses */
3427344Skarels #define STIME 500000 /* usec to wait for another response */
3515760Skarels
366918Ssam int s;
3746785Sbostic int timedout;
3846785Sbostic void timeout();
396918Ssam char packet[MAXPACKETSIZE];
4026146Skarels int nflag;
416918Ssam
main(argc,argv)426918Ssam main(argc, argv)
436918Ssam int argc;
446918Ssam char *argv[];
456918Ssam {
4635780Sbostic extern char *optarg;
4735780Sbostic extern int optind;
4835780Sbostic int ch, cc, count, bits;
496918Ssam struct sockaddr from;
5050635Skarels struct sigaction sigact;
5134708Skarels int fromlen = sizeof(from), size = 32*1024;
5227344Skarels struct timeval shorttime;
5335780Sbostic
5435780Sbostic while ((ch = getopt(argc, argv, "n")) != EOF)
5550635Skarels switch (ch) {
5635780Sbostic case 'n':
5735780Sbostic nflag++;
5835780Sbostic break;
5935780Sbostic case '?':
6035780Sbostic default:
6135780Sbostic goto usage;
6235780Sbostic }
6335780Sbostic argv += optind;
6435780Sbostic
6535780Sbostic if (!*argv) {
6635780Sbostic usage: printf("usage: query [-n] hosts...\n");
676918Ssam exit(1);
686918Ssam }
6935780Sbostic
7015760Skarels s = socket(AF_INET, SOCK_DGRAM, 0);
716918Ssam if (s < 0) {
726918Ssam perror("socket");
736918Ssam exit(2);
746918Ssam }
7534708Skarels if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0)
7634708Skarels perror("setsockopt SO_RCVBUF");
7715760Skarels
7835780Sbostic while (*argv) {
7935780Sbostic query(*argv++);
8028205Skarels count++;
816918Ssam }
826918Ssam
836918Ssam /*
8415760Skarels * Listen for returning packets;
8515760Skarels * may be more than one packet per host.
866918Ssam */
8715760Skarels bits = 1 << s;
8869005Sbostic memset(&shorttime, 0, sizeof(shorttime));
8927344Skarels shorttime.tv_usec = STIME;
9069005Sbostic memset(&sigact, 0, sizeof(sigact));
9150635Skarels sigact.sa_handler = timeout;
9250635Skarels /*sigact.sa_flags = 0; /* no restart */
9350635Skarels if (sigaction(SIGALRM, &sigact, (struct sigaction *)NULL) == -1)
9450635Skarels perror("sigaction");
9522547Skarels alarm(WTIME);
9622547Skarels while ((count > 0 && !timedout) ||
9746785Sbostic select(20, (fd_set *)&bits, NULL, NULL, &shorttime) > 0) {
9815760Skarels cc = recvfrom(s, packet, sizeof (packet), 0,
9915760Skarels &from, &fromlen);
1006918Ssam if (cc <= 0) {
1016918Ssam if (cc < 0) {
10222547Skarels if (errno == EINTR)
10322547Skarels continue;
10415760Skarels perror("recvfrom");
1056918Ssam (void) close(s);
1066918Ssam exit(1);
1076918Ssam }
1086918Ssam continue;
1096918Ssam }
1106918Ssam rip_input(&from, cc);
1116918Ssam count--;
1126918Ssam }
11334708Skarels exit (count > 0 ? count : 0);
1146918Ssam }
1156918Ssam
query(host)1166918Ssam query(host)
1176918Ssam char *host;
1186918Ssam {
1196918Ssam struct sockaddr_in router;
1206918Ssam register struct rip *msg = (struct rip *)packet;
1218339Ssam struct hostent *hp;
1228339Ssam struct servent *sp;
1236918Ssam
12469005Sbostic memset(&router, 0, sizeof (router));
12526146Skarels router.sin_family = AF_INET;
12626146Skarels router.sin_addr.s_addr = inet_addr(host);
12726146Skarels if (router.sin_addr.s_addr == -1) {
12826146Skarels hp = gethostbyname(host);
12935780Sbostic if (hp == NULL) {
13035780Sbostic fprintf(stderr, "query: %s: ", host);
13135780Sbostic herror((char *)NULL);
13226146Skarels exit(1);
13326146Skarels }
13469005Sbostic memmove(&router.sin_addr, hp->h_addr, hp->h_length);
1356918Ssam }
1368339Ssam sp = getservbyname("router", "udp");
1378339Ssam if (sp == 0) {
1388339Ssam printf("udp/router: service unknown\n");
1398339Ssam exit(1);
1408339Ssam }
14115760Skarels router.sin_port = sp->s_port;
1426918Ssam msg->rip_cmd = RIPCMD_REQUEST;
14315760Skarels msg->rip_vers = RIPVERSION;
14415760Skarels msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
14515760Skarels msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
14615760Skarels if (sendto(s, packet, sizeof (struct rip), 0,
14746785Sbostic (struct sockaddr *)&router, sizeof(router)) < 0)
1486918Ssam perror(host);
1496918Ssam }
1506918Ssam
1516918Ssam /*
1526918Ssam * Handle an incoming routing packet.
1536918Ssam */
1546918Ssam rip_input(from, size)
1556918Ssam struct sockaddr_in *from;
1566918Ssam int size;
1576918Ssam {
1586918Ssam register struct rip *msg = (struct rip *)packet;
15928205Skarels register struct netinfo *n;
1606918Ssam char *name;
16122547Skarels int lna, net, subnet;
1628339Ssam struct hostent *hp;
1638339Ssam struct netent *np;
1646918Ssam
1656918Ssam if (msg->rip_cmd != RIPCMD_RESPONSE)
1666918Ssam return;
16726959Skarels printf("%d bytes from ", size);
16826146Skarels if (nflag)
16926146Skarels printf("%s:\n", inet_ntoa(from->sin_addr));
17026146Skarels else {
17146785Sbostic hp = gethostbyaddr((char *)&from->sin_addr,
17246785Sbostic sizeof (struct in_addr), AF_INET);
17326146Skarels name = hp == 0 ? "???" : hp->h_name;
17426146Skarels printf("%s(%s):\n", name, inet_ntoa(from->sin_addr));
17526146Skarels }
1766918Ssam size -= sizeof (int);
1776918Ssam n = msg->rip_nets;
1786918Ssam while (size > 0) {
17928205Skarels if (size < sizeof (struct netinfo))
18028205Skarels break;
18128205Skarels if (msg->rip_vers > 0) {
18228205Skarels n->rip_dst.sa_family =
18328205Skarels ntohs(n->rip_dst.sa_family);
18428205Skarels n->rip_metric = ntohl(n->rip_metric);
18528205Skarels }
18628205Skarels switch (n->rip_dst.sa_family) {
1876918Ssam
18828205Skarels case AF_INET:
18928205Skarels { register struct sockaddr_in *sin;
19028205Skarels
1916918Ssam sin = (struct sockaddr_in *)&n->rip_dst;
19222547Skarels net = inet_netof(sin->sin_addr);
19322547Skarels subnet = inet_subnetof(sin->sin_addr);
19422547Skarels lna = inet_lnaof(sin->sin_addr);
19522547Skarels name = "???";
19626146Skarels if (!nflag) {
19728205Skarels if (sin->sin_addr.s_addr == 0)
19828205Skarels name = "default";
19928205Skarels else if (lna == INADDR_ANY) {
20026146Skarels np = getnetbyaddr(net, AF_INET);
20126146Skarels if (np)
20226146Skarels name = np->n_name;
20326146Skarels else if (net == 0)
20426146Skarels name = "default";
20526959Skarels } else if ((lna & 0xff) == 0 &&
20626146Skarels (np = getnetbyaddr(subnet, AF_INET))) {
20726146Skarels struct in_addr subnaddr, inet_makeaddr();
20822547Skarels
20926146Skarels subnaddr = inet_makeaddr(subnet, INADDR_ANY);
210*69038Sbostic if (memcmp(&sin->sin_addr, &subnaddr,
21126146Skarels sizeof(subnaddr)) == 0)
21226146Skarels name = np->n_name;
21326146Skarels else
21426146Skarels goto host;
21526146Skarels } else {
21626146Skarels host:
21746785Sbostic hp = gethostbyaddr((char *)&sin->sin_addr,
21826146Skarels sizeof (struct in_addr), AF_INET);
21926146Skarels if (hp)
22026146Skarels name = hp->h_name;
22126146Skarels }
22234708Skarels printf("\t%-17s metric %2d name %s\n",
22334708Skarels inet_ntoa(sin->sin_addr), n->rip_metric, name);
22426146Skarels } else
22534708Skarels printf("\t%-17s metric %2d\n",
22626146Skarels inet_ntoa(sin->sin_addr), n->rip_metric);
22728205Skarels break;
22828205Skarels }
22928205Skarels
23028205Skarels default:
23128205Skarels { u_short *p = (u_short *)n->rip_dst.sa_data;
23228205Skarels
23328205Skarels printf("\t(af %d) %x %x %x %x %x %x %x, metric %d\n",
23428205Skarels p[0], p[1], p[2], p[3], p[4], p[5], p[6],
23528205Skarels n->rip_dst.sa_family,
23628205Skarels n->rip_metric);
23728205Skarels break;
23828205Skarels }
23928205Skarels
24028205Skarels }
24128205Skarels size -= sizeof (struct netinfo), n++;
2426918Ssam }
2436918Ssam }
24415760Skarels
24546785Sbostic void
timeout()24615760Skarels timeout()
24715760Skarels {
24815760Skarels timedout = 1;
24915760Skarels }
25022547Skarels
25122547Skarels /*
25222547Skarels * Return the possible subnetwork number from an internet address.
25322547Skarels * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING
25422547Skarels * INSIDE OF THE HOST PART. We can only believe this if we have other
25522547Skarels * information (e.g., we can find a name for this number).
25622547Skarels */
25722547Skarels inet_subnetof(in)
25822547Skarels struct in_addr in;
25922547Skarels {
26022547Skarels register u_long i = ntohl(in.s_addr);
26122547Skarels
26225382Skarels if (IN_CLASSA(i))
26325382Skarels return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
26425382Skarels else if (IN_CLASSB(i))
26522547Skarels return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
26625382Skarels else
26725382Skarels return ((i & 0xffffffc0) >> 28);
26822547Skarels }
269