122643Sdist /* 222643Sdist * Copyright (c) 1980 Regents of the University of California. 333488Sbostic * All rights reserved. 433488Sbostic * 533488Sbostic * Redistribution and use in source and binary forms are permitted 634770Sbostic * provided that the above copyright notice and this paragraph are 734770Sbostic * duplicated in all such forms and that any documentation, 834770Sbostic * advertising materials, and other materials related to such 934770Sbostic * distribution and use acknowledge that the software was developed 1034770Sbostic * by the University of California, Berkeley. The name of the 1134770Sbostic * University may not be used to endorse or promote products derived 1234770Sbostic * from this software without specific prior written permission. 1334770Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434770Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534770Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1622643Sdist */ 1722643Sdist 186918Ssam #ifndef lint 1933488Sbostic char copyright[] = 2033488Sbostic "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 2133488Sbostic All rights reserved.\n"; 2233488Sbostic #endif /* not lint */ 236918Ssam 2433488Sbostic #ifndef lint 25*35780Sbostic static char sccsid[] = "@(#)query.c 5.11 (Berkeley) 10/10/88"; 2633488Sbostic #endif /* not lint */ 2733488Sbostic 286918Ssam #include <sys/param.h> 296918Ssam #include <sys/protosw.h> 306918Ssam #include <sys/socket.h> 3115760Skarels #include <sys/time.h> 3215760Skarels #include <netinet/in.h> 336918Ssam #include <errno.h> 346918Ssam #include <stdio.h> 358339Ssam #include <netdb.h> 3625382Skarels #include <protocols/routed.h> 376918Ssam 3827344Skarels #define WTIME 5 /* Time to wait for all responses */ 3927344Skarels #define STIME 500000 /* usec to wait for another response */ 4015760Skarels 416918Ssam int s; 4222547Skarels int timedout, timeout(); 436918Ssam char packet[MAXPACKETSIZE]; 4422547Skarels extern int errno; 4526146Skarels int nflag; 466918Ssam 476918Ssam main(argc, argv) 486918Ssam int argc; 496918Ssam char *argv[]; 506918Ssam { 51*35780Sbostic extern char *optarg; 52*35780Sbostic extern int optind; 53*35780Sbostic int ch, cc, count, bits; 546918Ssam struct sockaddr from; 5534708Skarels int fromlen = sizeof(from), size = 32*1024; 5627344Skarels struct timeval shorttime; 57*35780Sbostic 58*35780Sbostic while ((ch = getopt(argc, argv, "n")) != EOF) 59*35780Sbostic switch((char)ch) { 60*35780Sbostic case 'n': 61*35780Sbostic nflag++; 62*35780Sbostic break; 63*35780Sbostic case '?': 64*35780Sbostic default: 65*35780Sbostic goto usage; 66*35780Sbostic } 67*35780Sbostic argv += optind; 68*35780Sbostic 69*35780Sbostic if (!*argv) { 70*35780Sbostic usage: printf("usage: query [-n] hosts...\n"); 716918Ssam exit(1); 726918Ssam } 73*35780Sbostic 7415760Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 756918Ssam if (s < 0) { 766918Ssam perror("socket"); 776918Ssam exit(2); 786918Ssam } 7934708Skarels if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0) 8034708Skarels perror("setsockopt SO_RCVBUF"); 8115760Skarels 82*35780Sbostic while (*argv) { 83*35780Sbostic query(*argv++); 8428205Skarels count++; 856918Ssam } 866918Ssam 876918Ssam /* 8815760Skarels * Listen for returning packets; 8915760Skarels * may be more than one packet per host. 906918Ssam */ 9115760Skarels bits = 1 << s; 9227344Skarels bzero(&shorttime, sizeof(shorttime)); 9327344Skarels shorttime.tv_usec = STIME; 9422547Skarels signal(SIGALRM, timeout); 9522547Skarels alarm(WTIME); 9622547Skarels while ((count > 0 && !timedout) || 9727344Skarels select(20, &bits, 0, 0, &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 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 1246918Ssam bzero((char *)&router, 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); 129*35780Sbostic if (hp == NULL) { 130*35780Sbostic fprintf(stderr, "query: %s: ", host); 131*35780Sbostic herror((char *)NULL); 13226146Skarels exit(1); 13326146Skarels } 13426146Skarels bcopy(hp->h_addr, &router.sin_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, 14715760Skarels &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 { 17126146Skarels hp = gethostbyaddr(&from->sin_addr, sizeof (struct in_addr), 17226146Skarels 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); 21026146Skarels if (bcmp(&sin->sin_addr, &subnaddr, 21126146Skarels sizeof(subnaddr)) == 0) 21226146Skarels name = np->n_name; 21326146Skarels else 21426146Skarels goto host; 21526146Skarels } else { 21626146Skarels host: 21726146Skarels hp = gethostbyaddr(&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 24515760Skarels timeout() 24615760Skarels { 24715760Skarels timedout = 1; 24815760Skarels } 24922547Skarels 25022547Skarels /* 25122547Skarels * Return the possible subnetwork number from an internet address. 25222547Skarels * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING 25322547Skarels * INSIDE OF THE HOST PART. We can only believe this if we have other 25422547Skarels * information (e.g., we can find a name for this number). 25522547Skarels */ 25622547Skarels inet_subnetof(in) 25722547Skarels struct in_addr in; 25822547Skarels { 25922547Skarels register u_long i = ntohl(in.s_addr); 26022547Skarels 26125382Skarels if (IN_CLASSA(i)) 26225382Skarels return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); 26325382Skarels else if (IN_CLASSB(i)) 26422547Skarels return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); 26525382Skarels else 26625382Skarels return ((i & 0xffffffc0) >> 28); 26722547Skarels } 268