122643Sdist /* 222643Sdist * Copyright (c) 1980 Regents of the University of California. 322643Sdist * All rights reserved. The Berkeley software License Agreement 422643Sdist * specifies the terms and conditions for redistribution. 522643Sdist */ 622643Sdist 76918Ssam #ifndef lint 8*26146Skarels static char sccsid[] = "@(#)query.c 5.3 (Berkeley) 02/12/86"; 922643Sdist #endif not lint 106918Ssam 116918Ssam #include <sys/param.h> 126918Ssam #include <sys/protosw.h> 136918Ssam #include <sys/socket.h> 1415760Skarels #include <sys/time.h> 1515760Skarels #include <netinet/in.h> 166918Ssam #include <errno.h> 176918Ssam #include <stdio.h> 188339Ssam #include <netdb.h> 1925382Skarels #include <protocols/routed.h> 206918Ssam 2115760Skarels #define WTIME 5 /* Time to wait for responses */ 2215760Skarels 236918Ssam int s; 2422547Skarels int timedout, timeout(); 256918Ssam char packet[MAXPACKETSIZE]; 2622547Skarels extern int errno; 27*26146Skarels int nflag; 286918Ssam 296918Ssam main(argc, argv) 306918Ssam int argc; 316918Ssam char *argv[]; 326918Ssam { 3315760Skarels int cc, count, bits; 346918Ssam struct sockaddr from; 3515760Skarels int fromlen = sizeof(from); 3615760Skarels struct timeval notime; 376918Ssam 386918Ssam if (argc < 2) { 39*26146Skarels usage: 40*26146Skarels printf("usage: query [ -n ] hosts...\n"); 416918Ssam exit(1); 426918Ssam } 4315760Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 446918Ssam if (s < 0) { 456918Ssam perror("socket"); 466918Ssam exit(2); 476918Ssam } 4815760Skarels 496918Ssam argv++, argc--; 50*26146Skarels if (*argv[0] == '-') { 51*26146Skarels switch (*argv[1]) { 52*26146Skarels case 'n': 53*26146Skarels nflag++; 54*26146Skarels break; 55*26146Skarels default: 56*26146Skarels goto usage; 57*26146Skarels } 58*26146Skarels argc--, argv++; 59*26146Skarels } 606918Ssam count = argc; 616918Ssam while (argc > 0) { 626918Ssam query(*argv); 636918Ssam argv++, argc--; 646918Ssam } 656918Ssam 666918Ssam /* 6715760Skarels * Listen for returning packets; 6815760Skarels * may be more than one packet per host. 696918Ssam */ 7015760Skarels bits = 1 << s; 7115760Skarels bzero(¬ime, sizeof(notime)); 7222547Skarels signal(SIGALRM, timeout); 7322547Skarels alarm(WTIME); 7422547Skarels while ((count > 0 && !timedout) || 7522547Skarels select(20, &bits, 0, 0, ¬ime) > 0) { 7615760Skarels cc = recvfrom(s, packet, sizeof (packet), 0, 7715760Skarels &from, &fromlen); 786918Ssam if (cc <= 0) { 796918Ssam if (cc < 0) { 8022547Skarels if (errno == EINTR) 8122547Skarels continue; 8215760Skarels perror("recvfrom"); 836918Ssam (void) close(s); 846918Ssam exit(1); 856918Ssam } 866918Ssam continue; 876918Ssam } 886918Ssam rip_input(&from, cc); 896918Ssam count--; 906918Ssam } 916918Ssam } 926918Ssam 936918Ssam query(host) 946918Ssam char *host; 956918Ssam { 966918Ssam struct sockaddr_in router; 976918Ssam register struct rip *msg = (struct rip *)packet; 988339Ssam struct hostent *hp; 998339Ssam struct servent *sp; 1006918Ssam 1016918Ssam bzero((char *)&router, sizeof (router)); 102*26146Skarels router.sin_family = AF_INET; 103*26146Skarels router.sin_addr.s_addr = inet_addr(host); 104*26146Skarels if (router.sin_addr.s_addr == -1) { 105*26146Skarels hp = gethostbyname(host); 106*26146Skarels if (hp == 0) { 107*26146Skarels printf("%s: unknown\n", host); 108*26146Skarels exit(1); 109*26146Skarels } 110*26146Skarels bcopy(hp->h_addr, &router.sin_addr, hp->h_length); 1116918Ssam } 1128339Ssam sp = getservbyname("router", "udp"); 1138339Ssam if (sp == 0) { 1148339Ssam printf("udp/router: service unknown\n"); 1158339Ssam exit(1); 1168339Ssam } 11715760Skarels router.sin_port = sp->s_port; 1186918Ssam msg->rip_cmd = RIPCMD_REQUEST; 11915760Skarels msg->rip_vers = RIPVERSION; 12015760Skarels msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); 12115760Skarels msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); 12215760Skarels if (sendto(s, packet, sizeof (struct rip), 0, 12315760Skarels &router, sizeof(router)) < 0) 1246918Ssam perror(host); 1256918Ssam } 1266918Ssam 1276918Ssam /* 1286918Ssam * Handle an incoming routing packet. 1296918Ssam */ 1306918Ssam rip_input(from, size) 1316918Ssam struct sockaddr_in *from; 1326918Ssam int size; 1336918Ssam { 1346918Ssam register struct rip *msg = (struct rip *)packet; 1356918Ssam struct netinfo *n; 1366918Ssam char *name; 13722547Skarels int lna, net, subnet; 1388339Ssam struct hostent *hp; 1398339Ssam struct netent *np; 1406918Ssam 1416918Ssam if (msg->rip_cmd != RIPCMD_RESPONSE) 1426918Ssam return; 143*26146Skarels printf("%d bytes from "); 144*26146Skarels if (nflag) 145*26146Skarels printf("%s:\n", inet_ntoa(from->sin_addr)); 146*26146Skarels else { 147*26146Skarels hp = gethostbyaddr(&from->sin_addr, sizeof (struct in_addr), 148*26146Skarels AF_INET); 149*26146Skarels name = hp == 0 ? "???" : hp->h_name; 150*26146Skarels printf("%s(%s):\n", name, inet_ntoa(from->sin_addr)); 151*26146Skarels } 1526918Ssam size -= sizeof (int); 1536918Ssam n = msg->rip_nets; 1546918Ssam while (size > 0) { 1556918Ssam register struct sockaddr_in *sin; 1566918Ssam 1576918Ssam if (size < sizeof (struct netinfo)) 1586918Ssam break; 15915760Skarels if (msg->rip_vers > 0) { 16015760Skarels n->rip_dst.sa_family = 16115760Skarels ntohs(n->rip_dst.sa_family); 16215760Skarels n->rip_metric = ntohl(n->rip_metric); 16315760Skarels } 1646918Ssam sin = (struct sockaddr_in *)&n->rip_dst; 16522547Skarels net = inet_netof(sin->sin_addr); 16622547Skarels subnet = inet_subnetof(sin->sin_addr); 16722547Skarels lna = inet_lnaof(sin->sin_addr); 16822547Skarels name = "???"; 169*26146Skarels if (!nflag) { 170*26146Skarels if (lna == INADDR_ANY) { 171*26146Skarels np = getnetbyaddr(net, AF_INET); 172*26146Skarels if (np) 173*26146Skarels name = np->n_name; 174*26146Skarels else if (net == 0) 175*26146Skarels name = "default"; 176*26146Skarels } else if ((subnet != net) && ((lna & 0xff) == 0) && 177*26146Skarels (np = getnetbyaddr(subnet, AF_INET))) { 178*26146Skarels struct in_addr subnaddr, inet_makeaddr(); 17922547Skarels 180*26146Skarels subnaddr = inet_makeaddr(subnet, INADDR_ANY); 181*26146Skarels if (bcmp(&sin->sin_addr, &subnaddr, 182*26146Skarels sizeof(subnaddr)) == 0) 183*26146Skarels name = np->n_name; 184*26146Skarels else 185*26146Skarels goto host; 186*26146Skarels } else { 187*26146Skarels host: 188*26146Skarels hp = gethostbyaddr(&sin->sin_addr, 189*26146Skarels sizeof (struct in_addr), AF_INET); 190*26146Skarels if (hp) 191*26146Skarels name = hp->h_name; 192*26146Skarels } 193*26146Skarels printf("\t%s(%s), metric %d\n", name, 194*26146Skarels inet_ntoa(sin->sin_addr), n->rip_metric); 195*26146Skarels } else 196*26146Skarels printf("\t%s, metric %d\n", 197*26146Skarels inet_ntoa(sin->sin_addr), n->rip_metric); 1986918Ssam size -= sizeof (struct netinfo), n++; 1996918Ssam } 2006918Ssam } 20115760Skarels 20215760Skarels timeout() 20315760Skarels { 20415760Skarels timedout = 1; 20515760Skarels } 20622547Skarels 20722547Skarels /* 20822547Skarels * Return the possible subnetwork number from an internet address. 20922547Skarels * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING 21022547Skarels * INSIDE OF THE HOST PART. We can only believe this if we have other 21122547Skarels * information (e.g., we can find a name for this number). 21222547Skarels */ 21322547Skarels inet_subnetof(in) 21422547Skarels struct in_addr in; 21522547Skarels { 21622547Skarels register u_long i = ntohl(in.s_addr); 21722547Skarels 21825382Skarels if (IN_CLASSA(i)) 21925382Skarels return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); 22025382Skarels else if (IN_CLASSB(i)) 22122547Skarels return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); 22225382Skarels else 22325382Skarels return ((i & 0xffffffc0) >> 28); 22422547Skarels } 225