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 6*34770Sbostic * provided that the above copyright notice and this paragraph are 7*34770Sbostic * duplicated in all such forms and that any documentation, 8*34770Sbostic * advertising materials, and other materials related to such 9*34770Sbostic * distribution and use acknowledge that the software was developed 10*34770Sbostic * by the University of California, Berkeley. The name of the 11*34770Sbostic * University may not be used to endorse or promote products derived 12*34770Sbostic * from this software without specific prior written permission. 13*34770Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*34770Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*34770Sbostic * 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*34770Sbostic static char sccsid[] = "@(#)query.c 5.10 (Berkeley) 06/18/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 { 5128205Skarels int cc, count, bits; 526918Ssam struct sockaddr from; 5334708Skarels int fromlen = sizeof(from), size = 32*1024; 5427344Skarels struct timeval shorttime; 556918Ssam 566918Ssam if (argc < 2) { 5726146Skarels usage: 5826146Skarels printf("usage: query [ -n ] hosts...\n"); 596918Ssam exit(1); 606918Ssam } 6115760Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 626918Ssam if (s < 0) { 636918Ssam perror("socket"); 646918Ssam exit(2); 656918Ssam } 6634708Skarels if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0) 6734708Skarels perror("setsockopt SO_RCVBUF"); 6815760Skarels 696918Ssam argv++, argc--; 7026146Skarels if (*argv[0] == '-') { 7126159Skarels switch (argv[0][1]) { 7226146Skarels case 'n': 7326146Skarels nflag++; 7426146Skarels break; 7526146Skarels default: 7626146Skarels goto usage; 7726146Skarels } 7826146Skarels argc--, argv++; 7926146Skarels } 806918Ssam while (argc > 0) { 816918Ssam query(*argv); 8228205Skarels count++; 836918Ssam argv++, argc--; 846918Ssam } 856918Ssam 866918Ssam /* 8715760Skarels * Listen for returning packets; 8815760Skarels * may be more than one packet per host. 896918Ssam */ 9015760Skarels bits = 1 << s; 9127344Skarels bzero(&shorttime, sizeof(shorttime)); 9227344Skarels shorttime.tv_usec = STIME; 9322547Skarels signal(SIGALRM, timeout); 9422547Skarels alarm(WTIME); 9522547Skarels while ((count > 0 && !timedout) || 9627344Skarels select(20, &bits, 0, 0, &shorttime) > 0) { 9715760Skarels cc = recvfrom(s, packet, sizeof (packet), 0, 9815760Skarels &from, &fromlen); 996918Ssam if (cc <= 0) { 1006918Ssam if (cc < 0) { 10122547Skarels if (errno == EINTR) 10222547Skarels continue; 10315760Skarels perror("recvfrom"); 1046918Ssam (void) close(s); 1056918Ssam exit(1); 1066918Ssam } 1076918Ssam continue; 1086918Ssam } 1096918Ssam rip_input(&from, cc); 1106918Ssam count--; 1116918Ssam } 11234708Skarels exit (count > 0 ? count : 0); 1136918Ssam } 1146918Ssam 1156918Ssam query(host) 1166918Ssam char *host; 1176918Ssam { 1186918Ssam struct sockaddr_in router; 1196918Ssam register struct rip *msg = (struct rip *)packet; 1208339Ssam struct hostent *hp; 1218339Ssam struct servent *sp; 1226918Ssam 1236918Ssam bzero((char *)&router, sizeof (router)); 12426146Skarels router.sin_family = AF_INET; 12526146Skarels router.sin_addr.s_addr = inet_addr(host); 12626146Skarels if (router.sin_addr.s_addr == -1) { 12726146Skarels hp = gethostbyname(host); 12826146Skarels if (hp == 0) { 12926146Skarels printf("%s: unknown\n", host); 13026146Skarels exit(1); 13126146Skarels } 13226146Skarels bcopy(hp->h_addr, &router.sin_addr, hp->h_length); 1336918Ssam } 1348339Ssam sp = getservbyname("router", "udp"); 1358339Ssam if (sp == 0) { 1368339Ssam printf("udp/router: service unknown\n"); 1378339Ssam exit(1); 1388339Ssam } 13915760Skarels router.sin_port = sp->s_port; 1406918Ssam msg->rip_cmd = RIPCMD_REQUEST; 14115760Skarels msg->rip_vers = RIPVERSION; 14215760Skarels msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); 14315760Skarels msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); 14415760Skarels if (sendto(s, packet, sizeof (struct rip), 0, 14515760Skarels &router, sizeof(router)) < 0) 1466918Ssam perror(host); 1476918Ssam } 1486918Ssam 1496918Ssam /* 1506918Ssam * Handle an incoming routing packet. 1516918Ssam */ 1526918Ssam rip_input(from, size) 1536918Ssam struct sockaddr_in *from; 1546918Ssam int size; 1556918Ssam { 1566918Ssam register struct rip *msg = (struct rip *)packet; 15728205Skarels register struct netinfo *n; 1586918Ssam char *name; 15922547Skarels int lna, net, subnet; 1608339Ssam struct hostent *hp; 1618339Ssam struct netent *np; 1626918Ssam 1636918Ssam if (msg->rip_cmd != RIPCMD_RESPONSE) 1646918Ssam return; 16526959Skarels printf("%d bytes from ", size); 16626146Skarels if (nflag) 16726146Skarels printf("%s:\n", inet_ntoa(from->sin_addr)); 16826146Skarels else { 16926146Skarels hp = gethostbyaddr(&from->sin_addr, sizeof (struct in_addr), 17026146Skarels AF_INET); 17126146Skarels name = hp == 0 ? "???" : hp->h_name; 17226146Skarels printf("%s(%s):\n", name, inet_ntoa(from->sin_addr)); 17326146Skarels } 1746918Ssam size -= sizeof (int); 1756918Ssam n = msg->rip_nets; 1766918Ssam while (size > 0) { 17728205Skarels if (size < sizeof (struct netinfo)) 17828205Skarels break; 17928205Skarels if (msg->rip_vers > 0) { 18028205Skarels n->rip_dst.sa_family = 18128205Skarels ntohs(n->rip_dst.sa_family); 18228205Skarels n->rip_metric = ntohl(n->rip_metric); 18328205Skarels } 18428205Skarels switch (n->rip_dst.sa_family) { 1856918Ssam 18628205Skarels case AF_INET: 18728205Skarels { register struct sockaddr_in *sin; 18828205Skarels 1896918Ssam sin = (struct sockaddr_in *)&n->rip_dst; 19022547Skarels net = inet_netof(sin->sin_addr); 19122547Skarels subnet = inet_subnetof(sin->sin_addr); 19222547Skarels lna = inet_lnaof(sin->sin_addr); 19322547Skarels name = "???"; 19426146Skarels if (!nflag) { 19528205Skarels if (sin->sin_addr.s_addr == 0) 19628205Skarels name = "default"; 19728205Skarels else if (lna == INADDR_ANY) { 19826146Skarels np = getnetbyaddr(net, AF_INET); 19926146Skarels if (np) 20026146Skarels name = np->n_name; 20126146Skarels else if (net == 0) 20226146Skarels name = "default"; 20326959Skarels } else if ((lna & 0xff) == 0 && 20426146Skarels (np = getnetbyaddr(subnet, AF_INET))) { 20526146Skarels struct in_addr subnaddr, inet_makeaddr(); 20622547Skarels 20726146Skarels subnaddr = inet_makeaddr(subnet, INADDR_ANY); 20826146Skarels if (bcmp(&sin->sin_addr, &subnaddr, 20926146Skarels sizeof(subnaddr)) == 0) 21026146Skarels name = np->n_name; 21126146Skarels else 21226146Skarels goto host; 21326146Skarels } else { 21426146Skarels host: 21526146Skarels hp = gethostbyaddr(&sin->sin_addr, 21626146Skarels sizeof (struct in_addr), AF_INET); 21726146Skarels if (hp) 21826146Skarels name = hp->h_name; 21926146Skarels } 22034708Skarels printf("\t%-17s metric %2d name %s\n", 22134708Skarels inet_ntoa(sin->sin_addr), n->rip_metric, name); 22226146Skarels } else 22334708Skarels printf("\t%-17s metric %2d\n", 22426146Skarels inet_ntoa(sin->sin_addr), n->rip_metric); 22528205Skarels break; 22628205Skarels } 22728205Skarels 22828205Skarels default: 22928205Skarels { u_short *p = (u_short *)n->rip_dst.sa_data; 23028205Skarels 23128205Skarels printf("\t(af %d) %x %x %x %x %x %x %x, metric %d\n", 23228205Skarels p[0], p[1], p[2], p[3], p[4], p[5], p[6], 23328205Skarels n->rip_dst.sa_family, 23428205Skarels n->rip_metric); 23528205Skarels break; 23628205Skarels } 23728205Skarels 23828205Skarels } 23928205Skarels size -= sizeof (struct netinfo), n++; 2406918Ssam } 2416918Ssam } 24215760Skarels 24315760Skarels timeout() 24415760Skarels { 24515760Skarels timedout = 1; 24615760Skarels } 24722547Skarels 24822547Skarels /* 24922547Skarels * Return the possible subnetwork number from an internet address. 25022547Skarels * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING 25122547Skarels * INSIDE OF THE HOST PART. We can only believe this if we have other 25222547Skarels * information (e.g., we can find a name for this number). 25322547Skarels */ 25422547Skarels inet_subnetof(in) 25522547Skarels struct in_addr in; 25622547Skarels { 25722547Skarels register u_long i = ntohl(in.s_addr); 25822547Skarels 25925382Skarels if (IN_CLASSA(i)) 26025382Skarels return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); 26125382Skarels else if (IN_CLASSB(i)) 26222547Skarels return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); 26325382Skarels else 26425382Skarels return ((i & 0xffffffc0) >> 28); 26522547Skarels } 266