1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 static char sccsid[] = "@(#)query.c 5.7 (Berkeley) 05/15/86"; 9 #endif not lint 10 11 #include <sys/param.h> 12 #include <sys/protosw.h> 13 #include <sys/socket.h> 14 #include <sys/time.h> 15 #include <netinet/in.h> 16 #include <errno.h> 17 #include <stdio.h> 18 #include <netdb.h> 19 #include <protocols/routed.h> 20 21 #define WTIME 5 /* Time to wait for all responses */ 22 #define STIME 500000 /* usec to wait for another response */ 23 24 int s; 25 int timedout, timeout(); 26 char packet[MAXPACKETSIZE]; 27 extern int errno; 28 int nflag; 29 30 main(argc, argv) 31 int argc; 32 char *argv[]; 33 { 34 int cc, count, bits; 35 struct sockaddr from; 36 int fromlen = sizeof(from); 37 struct timeval shorttime; 38 39 if (argc < 2) { 40 usage: 41 printf("usage: query [ -n ] hosts...\n"); 42 exit(1); 43 } 44 s = socket(AF_INET, SOCK_DGRAM, 0); 45 if (s < 0) { 46 perror("socket"); 47 exit(2); 48 } 49 50 argv++, argc--; 51 if (*argv[0] == '-') { 52 switch (argv[0][1]) { 53 case 'n': 54 nflag++; 55 break; 56 default: 57 goto usage; 58 } 59 argc--, argv++; 60 } 61 while (argc > 0) { 62 query(*argv); 63 count++; 64 argv++, argc--; 65 } 66 67 /* 68 * Listen for returning packets; 69 * may be more than one packet per host. 70 */ 71 bits = 1 << s; 72 bzero(&shorttime, sizeof(shorttime)); 73 shorttime.tv_usec = STIME; 74 signal(SIGALRM, timeout); 75 alarm(WTIME); 76 while ((count > 0 && !timedout) || 77 select(20, &bits, 0, 0, &shorttime) > 0) { 78 cc = recvfrom(s, packet, sizeof (packet), 0, 79 &from, &fromlen); 80 if (cc <= 0) { 81 if (cc < 0) { 82 if (errno == EINTR) 83 continue; 84 perror("recvfrom"); 85 (void) close(s); 86 exit(1); 87 } 88 continue; 89 } 90 rip_input(&from, cc); 91 count--; 92 } 93 } 94 95 query(host) 96 char *host; 97 { 98 struct sockaddr_in router; 99 register struct rip *msg = (struct rip *)packet; 100 struct hostent *hp; 101 struct servent *sp; 102 103 bzero((char *)&router, sizeof (router)); 104 router.sin_family = AF_INET; 105 router.sin_addr.s_addr = inet_addr(host); 106 if (router.sin_addr.s_addr == -1) { 107 hp = gethostbyname(host); 108 if (hp == 0) { 109 printf("%s: unknown\n", host); 110 exit(1); 111 } 112 bcopy(hp->h_addr, &router.sin_addr, hp->h_length); 113 } 114 sp = getservbyname("router", "udp"); 115 if (sp == 0) { 116 printf("udp/router: service unknown\n"); 117 exit(1); 118 } 119 router.sin_port = sp->s_port; 120 msg->rip_cmd = RIPCMD_REQUEST; 121 msg->rip_vers = RIPVERSION; 122 msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); 123 msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); 124 if (sendto(s, packet, sizeof (struct rip), 0, 125 &router, sizeof(router)) < 0) 126 perror(host); 127 } 128 129 /* 130 * Handle an incoming routing packet. 131 */ 132 rip_input(from, size) 133 struct sockaddr_in *from; 134 int size; 135 { 136 register struct rip *msg = (struct rip *)packet; 137 register struct netinfo *n; 138 char *name; 139 int lna, net, subnet; 140 struct hostent *hp; 141 struct netent *np; 142 143 if (msg->rip_cmd != RIPCMD_RESPONSE) 144 return; 145 printf("%d bytes from ", size); 146 if (nflag) 147 printf("%s:\n", inet_ntoa(from->sin_addr)); 148 else { 149 hp = gethostbyaddr(&from->sin_addr, sizeof (struct in_addr), 150 AF_INET); 151 name = hp == 0 ? "???" : hp->h_name; 152 printf("%s(%s):\n", name, inet_ntoa(from->sin_addr)); 153 } 154 size -= sizeof (int); 155 n = msg->rip_nets; 156 while (size > 0) { 157 if (size < sizeof (struct netinfo)) 158 break; 159 if (msg->rip_vers > 0) { 160 n->rip_dst.sa_family = 161 ntohs(n->rip_dst.sa_family); 162 n->rip_metric = ntohl(n->rip_metric); 163 } 164 switch (n->rip_dst.sa_family) { 165 166 case AF_INET: 167 { register struct sockaddr_in *sin; 168 169 sin = (struct sockaddr_in *)&n->rip_dst; 170 net = inet_netof(sin->sin_addr); 171 subnet = inet_subnetof(sin->sin_addr); 172 lna = inet_lnaof(sin->sin_addr); 173 name = "???"; 174 if (!nflag) { 175 if (sin->sin_addr.s_addr == 0) 176 name = "default"; 177 else if (lna == INADDR_ANY) { 178 np = getnetbyaddr(net, AF_INET); 179 if (np) 180 name = np->n_name; 181 else if (net == 0) 182 name = "default"; 183 } else if ((lna & 0xff) == 0 && 184 (np = getnetbyaddr(subnet, AF_INET))) { 185 struct in_addr subnaddr, inet_makeaddr(); 186 187 subnaddr = inet_makeaddr(subnet, INADDR_ANY); 188 if (bcmp(&sin->sin_addr, &subnaddr, 189 sizeof(subnaddr)) == 0) 190 name = np->n_name; 191 else 192 goto host; 193 } else { 194 host: 195 hp = gethostbyaddr(&sin->sin_addr, 196 sizeof (struct in_addr), AF_INET); 197 if (hp) 198 name = hp->h_name; 199 } 200 printf("\t%s(%s), metric %d\n", name, 201 inet_ntoa(sin->sin_addr), n->rip_metric); 202 } else 203 printf("\t%s, metric %d\n", 204 inet_ntoa(sin->sin_addr), n->rip_metric); 205 break; 206 } 207 208 default: 209 { u_short *p = (u_short *)n->rip_dst.sa_data; 210 211 printf("\t(af %d) %x %x %x %x %x %x %x, metric %d\n", 212 p[0], p[1], p[2], p[3], p[4], p[5], p[6], 213 n->rip_dst.sa_family, 214 n->rip_metric); 215 break; 216 } 217 218 } 219 size -= sizeof (struct netinfo), n++; 220 } 221 } 222 223 timeout() 224 { 225 timedout = 1; 226 } 227 228 /* 229 * Return the possible subnetwork number from an internet address. 230 * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING 231 * INSIDE OF THE HOST PART. We can only believe this if we have other 232 * information (e.g., we can find a name for this number). 233 */ 234 inet_subnetof(in) 235 struct in_addr in; 236 { 237 register u_long i = ntohl(in.s_addr); 238 239 if (IN_CLASSA(i)) 240 return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); 241 else if (IN_CLASSB(i)) 242 return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); 243 else 244 return ((i & 0xffffffc0) >> 28); 245 } 246