1*22643Sdist /* 2*22643Sdist * Copyright (c) 1980 Regents of the University of California. 3*22643Sdist * All rights reserved. The Berkeley software License Agreement 4*22643Sdist * specifies the terms and conditions for redistribution. 5*22643Sdist */ 6*22643Sdist 76918Ssam #ifndef lint 8*22643Sdist static char sccsid[] = "@(#)query.c 5.1 (Berkeley) 06/07/85"; 9*22643Sdist #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> 1915760Skarels #include "../protocol.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; 276918Ssam 286918Ssam main(argc, argv) 296918Ssam int argc; 306918Ssam char *argv[]; 316918Ssam { 3215760Skarels int cc, count, bits; 336918Ssam struct sockaddr from; 3415760Skarels int fromlen = sizeof(from); 3515760Skarels struct timeval notime; 366918Ssam 376918Ssam if (argc < 2) { 386918Ssam printf("usage: query hosts...\n"); 396918Ssam exit(1); 406918Ssam } 4115760Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 426918Ssam if (s < 0) { 436918Ssam perror("socket"); 446918Ssam exit(2); 456918Ssam } 4615760Skarels 476918Ssam argv++, argc--; 486918Ssam count = argc; 496918Ssam while (argc > 0) { 506918Ssam query(*argv); 516918Ssam argv++, argc--; 526918Ssam } 536918Ssam 546918Ssam /* 5515760Skarels * Listen for returning packets; 5615760Skarels * may be more than one packet per host. 576918Ssam */ 5815760Skarels bits = 1 << s; 5915760Skarels bzero(¬ime, sizeof(notime)); 6022547Skarels signal(SIGALRM, timeout); 6122547Skarels alarm(WTIME); 6222547Skarels while ((count > 0 && !timedout) || 6322547Skarels select(20, &bits, 0, 0, ¬ime) > 0) { 6415760Skarels cc = recvfrom(s, packet, sizeof (packet), 0, 6515760Skarels &from, &fromlen); 666918Ssam if (cc <= 0) { 676918Ssam if (cc < 0) { 6822547Skarels if (errno == EINTR) 6922547Skarels continue; 7015760Skarels perror("recvfrom"); 716918Ssam (void) close(s); 726918Ssam exit(1); 736918Ssam } 746918Ssam continue; 756918Ssam } 766918Ssam rip_input(&from, cc); 776918Ssam count--; 786918Ssam } 796918Ssam } 806918Ssam 816918Ssam query(host) 826918Ssam char *host; 836918Ssam { 846918Ssam struct sockaddr_in router; 856918Ssam register struct rip *msg = (struct rip *)packet; 868339Ssam struct hostent *hp; 878339Ssam struct servent *sp; 886918Ssam 896918Ssam bzero((char *)&router, sizeof (router)); 908339Ssam hp = gethostbyname(host); 918339Ssam if (hp == 0) { 926918Ssam printf("%s: unknown\n", host); 936918Ssam exit(1); 946918Ssam } 958339Ssam bcopy(hp->h_addr, &router.sin_addr, hp->h_length); 966918Ssam router.sin_family = AF_INET; 978339Ssam sp = getservbyname("router", "udp"); 988339Ssam if (sp == 0) { 998339Ssam printf("udp/router: service unknown\n"); 1008339Ssam exit(1); 1018339Ssam } 10215760Skarels router.sin_port = sp->s_port; 1036918Ssam msg->rip_cmd = RIPCMD_REQUEST; 10415760Skarels msg->rip_vers = RIPVERSION; 10515760Skarels msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); 10615760Skarels msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); 10715760Skarels if (sendto(s, packet, sizeof (struct rip), 0, 10815760Skarels &router, sizeof(router)) < 0) 1096918Ssam perror(host); 1106918Ssam } 1116918Ssam 1126918Ssam /* 1136918Ssam * Handle an incoming routing packet. 1146918Ssam */ 1156918Ssam rip_input(from, size) 1166918Ssam struct sockaddr_in *from; 1176918Ssam int size; 1186918Ssam { 1196918Ssam register struct rip *msg = (struct rip *)packet; 1206918Ssam struct netinfo *n; 1216918Ssam char *name; 12222547Skarels int lna, net, subnet; 1238339Ssam struct hostent *hp; 1248339Ssam struct netent *np; 1256918Ssam 1266918Ssam if (msg->rip_cmd != RIPCMD_RESPONSE) 1276918Ssam return; 1288344Ssam hp = gethostbyaddr(&from->sin_addr, sizeof (struct in_addr), AF_INET); 1298339Ssam name = hp == 0 ? "???" : hp->h_name; 13015760Skarels printf("from %s(%s):\n", name, inet_ntoa(from->sin_addr)); 1316918Ssam size -= sizeof (int); 1326918Ssam n = msg->rip_nets; 1336918Ssam while (size > 0) { 1346918Ssam register struct sockaddr_in *sin; 1356918Ssam 1366918Ssam if (size < sizeof (struct netinfo)) 1376918Ssam break; 13815760Skarels if (msg->rip_vers > 0) { 13915760Skarels n->rip_dst.sa_family = 14015760Skarels ntohs(n->rip_dst.sa_family); 14115760Skarels n->rip_metric = ntohl(n->rip_metric); 14215760Skarels } 1436918Ssam sin = (struct sockaddr_in *)&n->rip_dst; 14422547Skarels net = inet_netof(sin->sin_addr); 14522547Skarels subnet = inet_subnetof(sin->sin_addr); 14622547Skarels lna = inet_lnaof(sin->sin_addr); 14722547Skarels name = "???"; 14822547Skarels if (lna == INADDR_ANY) { 14922547Skarels np = getnetbyaddr(net, AF_INET); 15022547Skarels if (np) 15122547Skarels name = np->n_name; 15222547Skarels else if (net == 0) 15322547Skarels name = "default"; 15422547Skarels } else if ((subnet != net) && ((lna & 0xff) == 0) && 15522547Skarels (np = getnetbyaddr(subnet, AF_INET))) { 15622547Skarels struct in_addr subnaddr, inet_makeaddr(); 15722547Skarels 15822547Skarels subnaddr = inet_makeaddr(subnet, INADDR_ANY); 15922547Skarels if (bcmp(&sin->sin_addr, &subnaddr, sizeof(subnaddr)) == 0) 16022547Skarels name = np->n_name; 16122547Skarels else 16222547Skarels goto host; 1638339Ssam } else { 16422547Skarels host: 1658339Ssam hp = gethostbyaddr(&sin->sin_addr, 16622547Skarels sizeof (struct in_addr), AF_INET); 16722547Skarels if (hp) 16822547Skarels name = hp->h_name; 1698339Ssam } 17015760Skarels printf("\t%s(%s), metric %d\n", name, 17115760Skarels inet_ntoa(sin->sin_addr), n->rip_metric); 1726918Ssam size -= sizeof (struct netinfo), n++; 1736918Ssam } 1746918Ssam } 17515760Skarels 17615760Skarels timeout() 17715760Skarels { 17815760Skarels timedout = 1; 17915760Skarels } 18022547Skarels 18122547Skarels /* 18222547Skarels * Return the possible subnetwork number from an internet address. 18322547Skarels * If the address is of the form of a subnet address (most significant 18422547Skarels * bit of the host part is set), believe the subnet exists. 18522547Skarels * Otherwise, return the network number. 18622547Skarels * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING 18722547Skarels * INSIDE OF THE HOST PART. We can only believe this if we have other 18822547Skarels * information (e.g., we can find a name for this number). 18922547Skarels */ 19022547Skarels inet_subnetof(in) 19122547Skarels struct in_addr in; 19222547Skarels { 19322547Skarels register u_long i = ntohl(in.s_addr); 19422547Skarels 19522547Skarels if (IN_CLASSA(i)) { 19622547Skarels if (IN_SUBNETA(i)) 19722547Skarels return ((i & IN_CLASSA_SUBNET) >> IN_CLASSA_SUBNSHIFT); 19822547Skarels else 19922547Skarels return ((i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT); 20022547Skarels } else if (IN_CLASSB(i)) { 20122547Skarels if (IN_SUBNETB(i)) 20222547Skarels return ((i & IN_CLASSB_SUBNET) >> IN_CLASSB_SUBNSHIFT); 20322547Skarels else 20422547Skarels return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); 20522547Skarels } else 20622547Skarels return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); 20722547Skarels } 208