16918Ssam #ifndef lint 2*22547Skarels static char sccsid[] = "@(#)query.c 4.7 06/06/85"; 36918Ssam #endif 46918Ssam 56918Ssam #include <sys/param.h> 66918Ssam #include <sys/protosw.h> 76918Ssam #include <sys/socket.h> 815760Skarels #include <sys/time.h> 915760Skarels #include <netinet/in.h> 106918Ssam #include <errno.h> 116918Ssam #include <stdio.h> 128339Ssam #include <netdb.h> 1315760Skarels #include "../protocol.h" 146918Ssam 1515760Skarels #define WTIME 5 /* Time to wait for responses */ 1615760Skarels 176918Ssam int s; 18*22547Skarels int timedout, timeout(); 196918Ssam char packet[MAXPACKETSIZE]; 20*22547Skarels extern int errno; 216918Ssam 226918Ssam main(argc, argv) 236918Ssam int argc; 246918Ssam char *argv[]; 256918Ssam { 2615760Skarels int cc, count, bits; 276918Ssam struct sockaddr from; 2815760Skarels int fromlen = sizeof(from); 2915760Skarels struct timeval notime; 306918Ssam 316918Ssam if (argc < 2) { 326918Ssam printf("usage: query hosts...\n"); 336918Ssam exit(1); 346918Ssam } 3515760Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 366918Ssam if (s < 0) { 376918Ssam perror("socket"); 386918Ssam exit(2); 396918Ssam } 4015760Skarels 416918Ssam argv++, argc--; 426918Ssam count = argc; 436918Ssam while (argc > 0) { 446918Ssam query(*argv); 456918Ssam argv++, argc--; 466918Ssam } 476918Ssam 486918Ssam /* 4915760Skarels * Listen for returning packets; 5015760Skarels * may be more than one packet per host. 516918Ssam */ 5215760Skarels bits = 1 << s; 5315760Skarels bzero(¬ime, sizeof(notime)); 54*22547Skarels signal(SIGALRM, timeout); 55*22547Skarels alarm(WTIME); 56*22547Skarels while ((count > 0 && !timedout) || 57*22547Skarels select(20, &bits, 0, 0, ¬ime) > 0) { 5815760Skarels cc = recvfrom(s, packet, sizeof (packet), 0, 5915760Skarels &from, &fromlen); 606918Ssam if (cc <= 0) { 616918Ssam if (cc < 0) { 62*22547Skarels if (errno == EINTR) 63*22547Skarels continue; 6415760Skarels perror("recvfrom"); 656918Ssam (void) close(s); 666918Ssam exit(1); 676918Ssam } 686918Ssam continue; 696918Ssam } 706918Ssam rip_input(&from, cc); 716918Ssam count--; 726918Ssam } 736918Ssam } 746918Ssam 756918Ssam query(host) 766918Ssam char *host; 776918Ssam { 786918Ssam struct sockaddr_in router; 796918Ssam register struct rip *msg = (struct rip *)packet; 808339Ssam struct hostent *hp; 818339Ssam struct servent *sp; 826918Ssam 836918Ssam bzero((char *)&router, sizeof (router)); 848339Ssam hp = gethostbyname(host); 858339Ssam if (hp == 0) { 866918Ssam printf("%s: unknown\n", host); 876918Ssam exit(1); 886918Ssam } 898339Ssam bcopy(hp->h_addr, &router.sin_addr, hp->h_length); 906918Ssam router.sin_family = AF_INET; 918339Ssam sp = getservbyname("router", "udp"); 928339Ssam if (sp == 0) { 938339Ssam printf("udp/router: service unknown\n"); 948339Ssam exit(1); 958339Ssam } 9615760Skarels router.sin_port = sp->s_port; 976918Ssam msg->rip_cmd = RIPCMD_REQUEST; 9815760Skarels msg->rip_vers = RIPVERSION; 9915760Skarels msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); 10015760Skarels msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); 10115760Skarels if (sendto(s, packet, sizeof (struct rip), 0, 10215760Skarels &router, sizeof(router)) < 0) 1036918Ssam perror(host); 1046918Ssam } 1056918Ssam 1066918Ssam /* 1076918Ssam * Handle an incoming routing packet. 1086918Ssam */ 1096918Ssam rip_input(from, size) 1106918Ssam struct sockaddr_in *from; 1116918Ssam int size; 1126918Ssam { 1136918Ssam register struct rip *msg = (struct rip *)packet; 1146918Ssam struct netinfo *n; 1156918Ssam char *name; 116*22547Skarels int lna, net, subnet; 1178339Ssam struct hostent *hp; 1188339Ssam struct netent *np; 1196918Ssam 1206918Ssam if (msg->rip_cmd != RIPCMD_RESPONSE) 1216918Ssam return; 1228344Ssam hp = gethostbyaddr(&from->sin_addr, sizeof (struct in_addr), AF_INET); 1238339Ssam name = hp == 0 ? "???" : hp->h_name; 12415760Skarels printf("from %s(%s):\n", name, inet_ntoa(from->sin_addr)); 1256918Ssam size -= sizeof (int); 1266918Ssam n = msg->rip_nets; 1276918Ssam while (size > 0) { 1286918Ssam register struct sockaddr_in *sin; 1296918Ssam 1306918Ssam if (size < sizeof (struct netinfo)) 1316918Ssam break; 13215760Skarels if (msg->rip_vers > 0) { 13315760Skarels n->rip_dst.sa_family = 13415760Skarels ntohs(n->rip_dst.sa_family); 13515760Skarels n->rip_metric = ntohl(n->rip_metric); 13615760Skarels } 1376918Ssam sin = (struct sockaddr_in *)&n->rip_dst; 138*22547Skarels net = inet_netof(sin->sin_addr); 139*22547Skarels subnet = inet_subnetof(sin->sin_addr); 140*22547Skarels lna = inet_lnaof(sin->sin_addr); 141*22547Skarels name = "???"; 142*22547Skarels if (lna == INADDR_ANY) { 143*22547Skarels np = getnetbyaddr(net, AF_INET); 144*22547Skarels if (np) 145*22547Skarels name = np->n_name; 146*22547Skarels else if (net == 0) 147*22547Skarels name = "default"; 148*22547Skarels } else if ((subnet != net) && ((lna & 0xff) == 0) && 149*22547Skarels (np = getnetbyaddr(subnet, AF_INET))) { 150*22547Skarels struct in_addr subnaddr, inet_makeaddr(); 151*22547Skarels 152*22547Skarels subnaddr = inet_makeaddr(subnet, INADDR_ANY); 153*22547Skarels if (bcmp(&sin->sin_addr, &subnaddr, sizeof(subnaddr)) == 0) 154*22547Skarels name = np->n_name; 155*22547Skarels else 156*22547Skarels goto host; 1578339Ssam } else { 158*22547Skarels host: 1598339Ssam hp = gethostbyaddr(&sin->sin_addr, 160*22547Skarels sizeof (struct in_addr), AF_INET); 161*22547Skarels if (hp) 162*22547Skarels name = hp->h_name; 1638339Ssam } 16415760Skarels printf("\t%s(%s), metric %d\n", name, 16515760Skarels inet_ntoa(sin->sin_addr), n->rip_metric); 1666918Ssam size -= sizeof (struct netinfo), n++; 1676918Ssam } 1686918Ssam } 16915760Skarels 17015760Skarels timeout() 17115760Skarels { 17215760Skarels timedout = 1; 17315760Skarels } 174*22547Skarels 175*22547Skarels /* 176*22547Skarels * Return the possible subnetwork number from an internet address. 177*22547Skarels * If the address is of the form of a subnet address (most significant 178*22547Skarels * bit of the host part is set), believe the subnet exists. 179*22547Skarels * Otherwise, return the network number. 180*22547Skarels * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING 181*22547Skarels * INSIDE OF THE HOST PART. We can only believe this if we have other 182*22547Skarels * information (e.g., we can find a name for this number). 183*22547Skarels */ 184*22547Skarels inet_subnetof(in) 185*22547Skarels struct in_addr in; 186*22547Skarels { 187*22547Skarels register u_long i = ntohl(in.s_addr); 188*22547Skarels 189*22547Skarels if (IN_CLASSA(i)) { 190*22547Skarels if (IN_SUBNETA(i)) 191*22547Skarels return ((i & IN_CLASSA_SUBNET) >> IN_CLASSA_SUBNSHIFT); 192*22547Skarels else 193*22547Skarels return ((i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT); 194*22547Skarels } else if (IN_CLASSB(i)) { 195*22547Skarels if (IN_SUBNETB(i)) 196*22547Skarels return ((i & IN_CLASSB_SUBNET) >> IN_CLASSB_SUBNSHIFT); 197*22547Skarels else 198*22547Skarels return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); 199*22547Skarels } else 200*22547Skarels return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); 201*22547Skarels } 202