122643Sdist /* 222643Sdist * Copyright (c) 1980 Regents of the University of California. 3*33488Sbostic * All rights reserved. 4*33488Sbostic * 5*33488Sbostic * Redistribution and use in source and binary forms are permitted 6*33488Sbostic * provided that this notice is preserved and that due credit is given 7*33488Sbostic * to the University of California at Berkeley. The name of the University 8*33488Sbostic * may not be used to endorse or promote products derived from this 9*33488Sbostic * software without specific prior written permission. This software 10*33488Sbostic * is provided ``as is'' without express or implied warranty. 1122643Sdist */ 1222643Sdist 136918Ssam #ifndef lint 14*33488Sbostic char copyright[] = 15*33488Sbostic "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 16*33488Sbostic All rights reserved.\n"; 17*33488Sbostic #endif /* not lint */ 186918Ssam 19*33488Sbostic #ifndef lint 20*33488Sbostic static char sccsid[] = "@(#)query.c 5.8 (Berkeley) 02/16/88"; 21*33488Sbostic #endif /* not lint */ 22*33488Sbostic 236918Ssam #include <sys/param.h> 246918Ssam #include <sys/protosw.h> 256918Ssam #include <sys/socket.h> 2615760Skarels #include <sys/time.h> 2715760Skarels #include <netinet/in.h> 286918Ssam #include <errno.h> 296918Ssam #include <stdio.h> 308339Ssam #include <netdb.h> 3125382Skarels #include <protocols/routed.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; 3722547Skarels int timedout, timeout(); 386918Ssam char packet[MAXPACKETSIZE]; 3922547Skarels extern int errno; 4026146Skarels int nflag; 416918Ssam 426918Ssam main(argc, argv) 436918Ssam int argc; 446918Ssam char *argv[]; 456918Ssam { 4628205Skarels int cc, count, bits; 476918Ssam struct sockaddr from; 4815760Skarels int fromlen = sizeof(from); 4927344Skarels struct timeval shorttime; 506918Ssam 516918Ssam if (argc < 2) { 5226146Skarels usage: 5326146Skarels printf("usage: query [ -n ] hosts...\n"); 546918Ssam exit(1); 556918Ssam } 5615760Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 576918Ssam if (s < 0) { 586918Ssam perror("socket"); 596918Ssam exit(2); 606918Ssam } 6115760Skarels 626918Ssam argv++, argc--; 6326146Skarels if (*argv[0] == '-') { 6426159Skarels switch (argv[0][1]) { 6526146Skarels case 'n': 6626146Skarels nflag++; 6726146Skarels break; 6826146Skarels default: 6926146Skarels goto usage; 7026146Skarels } 7126146Skarels argc--, argv++; 7226146Skarels } 736918Ssam while (argc > 0) { 746918Ssam query(*argv); 7528205Skarels count++; 766918Ssam argv++, argc--; 776918Ssam } 786918Ssam 796918Ssam /* 8015760Skarels * Listen for returning packets; 8115760Skarels * may be more than one packet per host. 826918Ssam */ 8315760Skarels bits = 1 << s; 8427344Skarels bzero(&shorttime, sizeof(shorttime)); 8527344Skarels shorttime.tv_usec = STIME; 8622547Skarels signal(SIGALRM, timeout); 8722547Skarels alarm(WTIME); 8822547Skarels while ((count > 0 && !timedout) || 8927344Skarels select(20, &bits, 0, 0, &shorttime) > 0) { 9015760Skarels cc = recvfrom(s, packet, sizeof (packet), 0, 9115760Skarels &from, &fromlen); 926918Ssam if (cc <= 0) { 936918Ssam if (cc < 0) { 9422547Skarels if (errno == EINTR) 9522547Skarels continue; 9615760Skarels perror("recvfrom"); 976918Ssam (void) close(s); 986918Ssam exit(1); 996918Ssam } 1006918Ssam continue; 1016918Ssam } 1026918Ssam rip_input(&from, cc); 1036918Ssam count--; 1046918Ssam } 1056918Ssam } 1066918Ssam 1076918Ssam query(host) 1086918Ssam char *host; 1096918Ssam { 1106918Ssam struct sockaddr_in router; 1116918Ssam register struct rip *msg = (struct rip *)packet; 1128339Ssam struct hostent *hp; 1138339Ssam struct servent *sp; 1146918Ssam 1156918Ssam bzero((char *)&router, sizeof (router)); 11626146Skarels router.sin_family = AF_INET; 11726146Skarels router.sin_addr.s_addr = inet_addr(host); 11826146Skarels if (router.sin_addr.s_addr == -1) { 11926146Skarels hp = gethostbyname(host); 12026146Skarels if (hp == 0) { 12126146Skarels printf("%s: unknown\n", host); 12226146Skarels exit(1); 12326146Skarels } 12426146Skarels bcopy(hp->h_addr, &router.sin_addr, hp->h_length); 1256918Ssam } 1268339Ssam sp = getservbyname("router", "udp"); 1278339Ssam if (sp == 0) { 1288339Ssam printf("udp/router: service unknown\n"); 1298339Ssam exit(1); 1308339Ssam } 13115760Skarels router.sin_port = sp->s_port; 1326918Ssam msg->rip_cmd = RIPCMD_REQUEST; 13315760Skarels msg->rip_vers = RIPVERSION; 13415760Skarels msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); 13515760Skarels msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); 13615760Skarels if (sendto(s, packet, sizeof (struct rip), 0, 13715760Skarels &router, sizeof(router)) < 0) 1386918Ssam perror(host); 1396918Ssam } 1406918Ssam 1416918Ssam /* 1426918Ssam * Handle an incoming routing packet. 1436918Ssam */ 1446918Ssam rip_input(from, size) 1456918Ssam struct sockaddr_in *from; 1466918Ssam int size; 1476918Ssam { 1486918Ssam register struct rip *msg = (struct rip *)packet; 14928205Skarels register struct netinfo *n; 1506918Ssam char *name; 15122547Skarels int lna, net, subnet; 1528339Ssam struct hostent *hp; 1538339Ssam struct netent *np; 1546918Ssam 1556918Ssam if (msg->rip_cmd != RIPCMD_RESPONSE) 1566918Ssam return; 15726959Skarels printf("%d bytes from ", size); 15826146Skarels if (nflag) 15926146Skarels printf("%s:\n", inet_ntoa(from->sin_addr)); 16026146Skarels else { 16126146Skarels hp = gethostbyaddr(&from->sin_addr, sizeof (struct in_addr), 16226146Skarels AF_INET); 16326146Skarels name = hp == 0 ? "???" : hp->h_name; 16426146Skarels printf("%s(%s):\n", name, inet_ntoa(from->sin_addr)); 16526146Skarels } 1666918Ssam size -= sizeof (int); 1676918Ssam n = msg->rip_nets; 1686918Ssam while (size > 0) { 16928205Skarels if (size < sizeof (struct netinfo)) 17028205Skarels break; 17128205Skarels if (msg->rip_vers > 0) { 17228205Skarels n->rip_dst.sa_family = 17328205Skarels ntohs(n->rip_dst.sa_family); 17428205Skarels n->rip_metric = ntohl(n->rip_metric); 17528205Skarels } 17628205Skarels switch (n->rip_dst.sa_family) { 1776918Ssam 17828205Skarels case AF_INET: 17928205Skarels { register struct sockaddr_in *sin; 18028205Skarels 1816918Ssam sin = (struct sockaddr_in *)&n->rip_dst; 18222547Skarels net = inet_netof(sin->sin_addr); 18322547Skarels subnet = inet_subnetof(sin->sin_addr); 18422547Skarels lna = inet_lnaof(sin->sin_addr); 18522547Skarels name = "???"; 18626146Skarels if (!nflag) { 18728205Skarels if (sin->sin_addr.s_addr == 0) 18828205Skarels name = "default"; 18928205Skarels else if (lna == INADDR_ANY) { 19026146Skarels np = getnetbyaddr(net, AF_INET); 19126146Skarels if (np) 19226146Skarels name = np->n_name; 19326146Skarels else if (net == 0) 19426146Skarels name = "default"; 19526959Skarels } else if ((lna & 0xff) == 0 && 19626146Skarels (np = getnetbyaddr(subnet, AF_INET))) { 19726146Skarels struct in_addr subnaddr, inet_makeaddr(); 19822547Skarels 19926146Skarels subnaddr = inet_makeaddr(subnet, INADDR_ANY); 20026146Skarels if (bcmp(&sin->sin_addr, &subnaddr, 20126146Skarels sizeof(subnaddr)) == 0) 20226146Skarels name = np->n_name; 20326146Skarels else 20426146Skarels goto host; 20526146Skarels } else { 20626146Skarels host: 20726146Skarels hp = gethostbyaddr(&sin->sin_addr, 20826146Skarels sizeof (struct in_addr), AF_INET); 20926146Skarels if (hp) 21026146Skarels name = hp->h_name; 21126146Skarels } 21226146Skarels printf("\t%s(%s), metric %d\n", name, 21326146Skarels inet_ntoa(sin->sin_addr), n->rip_metric); 21426146Skarels } else 21526146Skarels printf("\t%s, metric %d\n", 21626146Skarels inet_ntoa(sin->sin_addr), n->rip_metric); 21728205Skarels break; 21828205Skarels } 21928205Skarels 22028205Skarels default: 22128205Skarels { u_short *p = (u_short *)n->rip_dst.sa_data; 22228205Skarels 22328205Skarels printf("\t(af %d) %x %x %x %x %x %x %x, metric %d\n", 22428205Skarels p[0], p[1], p[2], p[3], p[4], p[5], p[6], 22528205Skarels n->rip_dst.sa_family, 22628205Skarels n->rip_metric); 22728205Skarels break; 22828205Skarels } 22928205Skarels 23028205Skarels } 23128205Skarels size -= sizeof (struct netinfo), n++; 2326918Ssam } 2336918Ssam } 23415760Skarels 23515760Skarels timeout() 23615760Skarels { 23715760Skarels timedout = 1; 23815760Skarels } 23922547Skarels 24022547Skarels /* 24122547Skarels * Return the possible subnetwork number from an internet address. 24222547Skarels * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING 24322547Skarels * INSIDE OF THE HOST PART. We can only believe this if we have other 24422547Skarels * information (e.g., we can find a name for this number). 24522547Skarels */ 24622547Skarels inet_subnetof(in) 24722547Skarels struct in_addr in; 24822547Skarels { 24922547Skarels register u_long i = ntohl(in.s_addr); 25022547Skarels 25125382Skarels if (IN_CLASSA(i)) 25225382Skarels return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); 25325382Skarels else if (IN_CLASSB(i)) 25422547Skarels return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); 25525382Skarels else 25625382Skarels return ((i & 0xffffffc0) >> 28); 25722547Skarels } 258