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 633488Sbostic * provided that this notice is preserved and that due credit is given 733488Sbostic * to the University of California at Berkeley. The name of the University 833488Sbostic * may not be used to endorse or promote products derived from this 933488Sbostic * software without specific prior written permission. This software 1033488Sbostic * is provided ``as is'' without express or implied warranty. 1122643Sdist */ 1222643Sdist 136918Ssam #ifndef lint 1433488Sbostic char copyright[] = 1533488Sbostic "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 1633488Sbostic All rights reserved.\n"; 1733488Sbostic #endif /* not lint */ 186918Ssam 1933488Sbostic #ifndef lint 20*34708Skarels static char sccsid[] = "@(#)query.c 5.9 (Berkeley) 06/11/88"; 2133488Sbostic #endif /* not lint */ 2233488Sbostic 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; 48*34708Skarels int fromlen = sizeof(from), size = 32*1024; 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 } 61*34708Skarels if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0) 62*34708Skarels perror("setsockopt SO_RCVBUF"); 6315760Skarels 646918Ssam argv++, argc--; 6526146Skarels if (*argv[0] == '-') { 6626159Skarels switch (argv[0][1]) { 6726146Skarels case 'n': 6826146Skarels nflag++; 6926146Skarels break; 7026146Skarels default: 7126146Skarels goto usage; 7226146Skarels } 7326146Skarels argc--, argv++; 7426146Skarels } 756918Ssam while (argc > 0) { 766918Ssam query(*argv); 7728205Skarels count++; 786918Ssam argv++, argc--; 796918Ssam } 806918Ssam 816918Ssam /* 8215760Skarels * Listen for returning packets; 8315760Skarels * may be more than one packet per host. 846918Ssam */ 8515760Skarels bits = 1 << s; 8627344Skarels bzero(&shorttime, sizeof(shorttime)); 8727344Skarels shorttime.tv_usec = STIME; 8822547Skarels signal(SIGALRM, timeout); 8922547Skarels alarm(WTIME); 9022547Skarels while ((count > 0 && !timedout) || 9127344Skarels select(20, &bits, 0, 0, &shorttime) > 0) { 9215760Skarels cc = recvfrom(s, packet, sizeof (packet), 0, 9315760Skarels &from, &fromlen); 946918Ssam if (cc <= 0) { 956918Ssam if (cc < 0) { 9622547Skarels if (errno == EINTR) 9722547Skarels continue; 9815760Skarels perror("recvfrom"); 996918Ssam (void) close(s); 1006918Ssam exit(1); 1016918Ssam } 1026918Ssam continue; 1036918Ssam } 1046918Ssam rip_input(&from, cc); 1056918Ssam count--; 1066918Ssam } 107*34708Skarels exit (count > 0 ? count : 0); 1086918Ssam } 1096918Ssam 1106918Ssam query(host) 1116918Ssam char *host; 1126918Ssam { 1136918Ssam struct sockaddr_in router; 1146918Ssam register struct rip *msg = (struct rip *)packet; 1158339Ssam struct hostent *hp; 1168339Ssam struct servent *sp; 1176918Ssam 1186918Ssam bzero((char *)&router, sizeof (router)); 11926146Skarels router.sin_family = AF_INET; 12026146Skarels router.sin_addr.s_addr = inet_addr(host); 12126146Skarels if (router.sin_addr.s_addr == -1) { 12226146Skarels hp = gethostbyname(host); 12326146Skarels if (hp == 0) { 12426146Skarels printf("%s: unknown\n", host); 12526146Skarels exit(1); 12626146Skarels } 12726146Skarels bcopy(hp->h_addr, &router.sin_addr, hp->h_length); 1286918Ssam } 1298339Ssam sp = getservbyname("router", "udp"); 1308339Ssam if (sp == 0) { 1318339Ssam printf("udp/router: service unknown\n"); 1328339Ssam exit(1); 1338339Ssam } 13415760Skarels router.sin_port = sp->s_port; 1356918Ssam msg->rip_cmd = RIPCMD_REQUEST; 13615760Skarels msg->rip_vers = RIPVERSION; 13715760Skarels msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); 13815760Skarels msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); 13915760Skarels if (sendto(s, packet, sizeof (struct rip), 0, 14015760Skarels &router, sizeof(router)) < 0) 1416918Ssam perror(host); 1426918Ssam } 1436918Ssam 1446918Ssam /* 1456918Ssam * Handle an incoming routing packet. 1466918Ssam */ 1476918Ssam rip_input(from, size) 1486918Ssam struct sockaddr_in *from; 1496918Ssam int size; 1506918Ssam { 1516918Ssam register struct rip *msg = (struct rip *)packet; 15228205Skarels register struct netinfo *n; 1536918Ssam char *name; 15422547Skarels int lna, net, subnet; 1558339Ssam struct hostent *hp; 1568339Ssam struct netent *np; 1576918Ssam 1586918Ssam if (msg->rip_cmd != RIPCMD_RESPONSE) 1596918Ssam return; 16026959Skarels printf("%d bytes from ", size); 16126146Skarels if (nflag) 16226146Skarels printf("%s:\n", inet_ntoa(from->sin_addr)); 16326146Skarels else { 16426146Skarels hp = gethostbyaddr(&from->sin_addr, sizeof (struct in_addr), 16526146Skarels AF_INET); 16626146Skarels name = hp == 0 ? "???" : hp->h_name; 16726146Skarels printf("%s(%s):\n", name, inet_ntoa(from->sin_addr)); 16826146Skarels } 1696918Ssam size -= sizeof (int); 1706918Ssam n = msg->rip_nets; 1716918Ssam while (size > 0) { 17228205Skarels if (size < sizeof (struct netinfo)) 17328205Skarels break; 17428205Skarels if (msg->rip_vers > 0) { 17528205Skarels n->rip_dst.sa_family = 17628205Skarels ntohs(n->rip_dst.sa_family); 17728205Skarels n->rip_metric = ntohl(n->rip_metric); 17828205Skarels } 17928205Skarels switch (n->rip_dst.sa_family) { 1806918Ssam 18128205Skarels case AF_INET: 18228205Skarels { register struct sockaddr_in *sin; 18328205Skarels 1846918Ssam sin = (struct sockaddr_in *)&n->rip_dst; 18522547Skarels net = inet_netof(sin->sin_addr); 18622547Skarels subnet = inet_subnetof(sin->sin_addr); 18722547Skarels lna = inet_lnaof(sin->sin_addr); 18822547Skarels name = "???"; 18926146Skarels if (!nflag) { 19028205Skarels if (sin->sin_addr.s_addr == 0) 19128205Skarels name = "default"; 19228205Skarels else if (lna == INADDR_ANY) { 19326146Skarels np = getnetbyaddr(net, AF_INET); 19426146Skarels if (np) 19526146Skarels name = np->n_name; 19626146Skarels else if (net == 0) 19726146Skarels name = "default"; 19826959Skarels } else if ((lna & 0xff) == 0 && 19926146Skarels (np = getnetbyaddr(subnet, AF_INET))) { 20026146Skarels struct in_addr subnaddr, inet_makeaddr(); 20122547Skarels 20226146Skarels subnaddr = inet_makeaddr(subnet, INADDR_ANY); 20326146Skarels if (bcmp(&sin->sin_addr, &subnaddr, 20426146Skarels sizeof(subnaddr)) == 0) 20526146Skarels name = np->n_name; 20626146Skarels else 20726146Skarels goto host; 20826146Skarels } else { 20926146Skarels host: 21026146Skarels hp = gethostbyaddr(&sin->sin_addr, 21126146Skarels sizeof (struct in_addr), AF_INET); 21226146Skarels if (hp) 21326146Skarels name = hp->h_name; 21426146Skarels } 215*34708Skarels printf("\t%-17s metric %2d name %s\n", 216*34708Skarels inet_ntoa(sin->sin_addr), n->rip_metric, name); 21726146Skarels } else 218*34708Skarels printf("\t%-17s metric %2d\n", 21926146Skarels inet_ntoa(sin->sin_addr), n->rip_metric); 22028205Skarels break; 22128205Skarels } 22228205Skarels 22328205Skarels default: 22428205Skarels { u_short *p = (u_short *)n->rip_dst.sa_data; 22528205Skarels 22628205Skarels printf("\t(af %d) %x %x %x %x %x %x %x, metric %d\n", 22728205Skarels p[0], p[1], p[2], p[3], p[4], p[5], p[6], 22828205Skarels n->rip_dst.sa_family, 22928205Skarels n->rip_metric); 23028205Skarels break; 23128205Skarels } 23228205Skarels 23328205Skarels } 23428205Skarels size -= sizeof (struct netinfo), n++; 2356918Ssam } 2366918Ssam } 23715760Skarels 23815760Skarels timeout() 23915760Skarels { 24015760Skarels timedout = 1; 24115760Skarels } 24222547Skarels 24322547Skarels /* 24422547Skarels * Return the possible subnetwork number from an internet address. 24522547Skarels * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING 24622547Skarels * INSIDE OF THE HOST PART. We can only believe this if we have other 24722547Skarels * information (e.g., we can find a name for this number). 24822547Skarels */ 24922547Skarels inet_subnetof(in) 25022547Skarels struct in_addr in; 25122547Skarels { 25222547Skarels register u_long i = ntohl(in.s_addr); 25322547Skarels 25425382Skarels if (IN_CLASSA(i)) 25525382Skarels return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); 25625382Skarels else if (IN_CLASSB(i)) 25722547Skarels return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); 25825382Skarels else 25925382Skarels return ((i & 0xffffffc0) >> 28); 26022547Skarels } 261