1 #ifndef lint 2 static char sccsid[] = "@(#)query.c 4.7 06/06/85"; 3 #endif 4 5 #include <sys/param.h> 6 #include <sys/protosw.h> 7 #include <sys/socket.h> 8 #include <sys/time.h> 9 #include <netinet/in.h> 10 #include <errno.h> 11 #include <stdio.h> 12 #include <netdb.h> 13 #include "../protocol.h" 14 15 #define WTIME 5 /* Time to wait for responses */ 16 17 int s; 18 int timedout, timeout(); 19 char packet[MAXPACKETSIZE]; 20 extern int errno; 21 22 main(argc, argv) 23 int argc; 24 char *argv[]; 25 { 26 int cc, count, bits; 27 struct sockaddr from; 28 int fromlen = sizeof(from); 29 struct timeval notime; 30 31 if (argc < 2) { 32 printf("usage: query hosts...\n"); 33 exit(1); 34 } 35 s = socket(AF_INET, SOCK_DGRAM, 0); 36 if (s < 0) { 37 perror("socket"); 38 exit(2); 39 } 40 41 argv++, argc--; 42 count = argc; 43 while (argc > 0) { 44 query(*argv); 45 argv++, argc--; 46 } 47 48 /* 49 * Listen for returning packets; 50 * may be more than one packet per host. 51 */ 52 bits = 1 << s; 53 bzero(¬ime, sizeof(notime)); 54 signal(SIGALRM, timeout); 55 alarm(WTIME); 56 while ((count > 0 && !timedout) || 57 select(20, &bits, 0, 0, ¬ime) > 0) { 58 cc = recvfrom(s, packet, sizeof (packet), 0, 59 &from, &fromlen); 60 if (cc <= 0) { 61 if (cc < 0) { 62 if (errno == EINTR) 63 continue; 64 perror("recvfrom"); 65 (void) close(s); 66 exit(1); 67 } 68 continue; 69 } 70 rip_input(&from, cc); 71 count--; 72 } 73 } 74 75 query(host) 76 char *host; 77 { 78 struct sockaddr_in router; 79 register struct rip *msg = (struct rip *)packet; 80 struct hostent *hp; 81 struct servent *sp; 82 83 bzero((char *)&router, sizeof (router)); 84 hp = gethostbyname(host); 85 if (hp == 0) { 86 printf("%s: unknown\n", host); 87 exit(1); 88 } 89 bcopy(hp->h_addr, &router.sin_addr, hp->h_length); 90 router.sin_family = AF_INET; 91 sp = getservbyname("router", "udp"); 92 if (sp == 0) { 93 printf("udp/router: service unknown\n"); 94 exit(1); 95 } 96 router.sin_port = sp->s_port; 97 msg->rip_cmd = RIPCMD_REQUEST; 98 msg->rip_vers = RIPVERSION; 99 msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); 100 msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); 101 if (sendto(s, packet, sizeof (struct rip), 0, 102 &router, sizeof(router)) < 0) 103 perror(host); 104 } 105 106 /* 107 * Handle an incoming routing packet. 108 */ 109 rip_input(from, size) 110 struct sockaddr_in *from; 111 int size; 112 { 113 register struct rip *msg = (struct rip *)packet; 114 struct netinfo *n; 115 char *name; 116 int lna, net, subnet; 117 struct hostent *hp; 118 struct netent *np; 119 120 if (msg->rip_cmd != RIPCMD_RESPONSE) 121 return; 122 hp = gethostbyaddr(&from->sin_addr, sizeof (struct in_addr), AF_INET); 123 name = hp == 0 ? "???" : hp->h_name; 124 printf("from %s(%s):\n", name, inet_ntoa(from->sin_addr)); 125 size -= sizeof (int); 126 n = msg->rip_nets; 127 while (size > 0) { 128 register struct sockaddr_in *sin; 129 130 if (size < sizeof (struct netinfo)) 131 break; 132 if (msg->rip_vers > 0) { 133 n->rip_dst.sa_family = 134 ntohs(n->rip_dst.sa_family); 135 n->rip_metric = ntohl(n->rip_metric); 136 } 137 sin = (struct sockaddr_in *)&n->rip_dst; 138 net = inet_netof(sin->sin_addr); 139 subnet = inet_subnetof(sin->sin_addr); 140 lna = inet_lnaof(sin->sin_addr); 141 name = "???"; 142 if (lna == INADDR_ANY) { 143 np = getnetbyaddr(net, AF_INET); 144 if (np) 145 name = np->n_name; 146 else if (net == 0) 147 name = "default"; 148 } else if ((subnet != net) && ((lna & 0xff) == 0) && 149 (np = getnetbyaddr(subnet, AF_INET))) { 150 struct in_addr subnaddr, inet_makeaddr(); 151 152 subnaddr = inet_makeaddr(subnet, INADDR_ANY); 153 if (bcmp(&sin->sin_addr, &subnaddr, sizeof(subnaddr)) == 0) 154 name = np->n_name; 155 else 156 goto host; 157 } else { 158 host: 159 hp = gethostbyaddr(&sin->sin_addr, 160 sizeof (struct in_addr), AF_INET); 161 if (hp) 162 name = hp->h_name; 163 } 164 printf("\t%s(%s), metric %d\n", name, 165 inet_ntoa(sin->sin_addr), n->rip_metric); 166 size -= sizeof (struct netinfo), n++; 167 } 168 } 169 170 timeout() 171 { 172 timedout = 1; 173 } 174 175 /* 176 * Return the possible subnetwork number from an internet address. 177 * If the address is of the form of a subnet address (most significant 178 * bit of the host part is set), believe the subnet exists. 179 * Otherwise, return the network number. 180 * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING 181 * INSIDE OF THE HOST PART. We can only believe this if we have other 182 * information (e.g., we can find a name for this number). 183 */ 184 inet_subnetof(in) 185 struct in_addr in; 186 { 187 register u_long i = ntohl(in.s_addr); 188 189 if (IN_CLASSA(i)) { 190 if (IN_SUBNETA(i)) 191 return ((i & IN_CLASSA_SUBNET) >> IN_CLASSA_SUBNSHIFT); 192 else 193 return ((i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT); 194 } else if (IN_CLASSB(i)) { 195 if (IN_SUBNETB(i)) 196 return ((i & IN_CLASSB_SUBNET) >> IN_CLASSB_SUBNSHIFT); 197 else 198 return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); 199 } else 200 return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); 201 } 202