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.6 (Berkeley) 04/24/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, 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 argv++, argc--; 64 } 65 66 /* 67 * Listen for returning packets; 68 * may be more than one packet per host. 69 */ 70 bits = 1 << s; 71 bzero(&shorttime, sizeof(shorttime)); 72 shorttime.tv_usec = STIME; 73 signal(SIGALRM, timeout); 74 alarm(WTIME); 75 while ((count > 0 && !timedout) || 76 select(20, &bits, 0, 0, &shorttime) > 0) { 77 cc = recvfrom(s, packet, sizeof (packet), 0, 78 &from, &fromlen); 79 if (cc <= 0) { 80 if (cc < 0) { 81 if (errno == EINTR) 82 continue; 83 perror("recvfrom"); 84 (void) close(s); 85 exit(1); 86 } 87 continue; 88 } 89 rip_input(&from, cc); 90 count--; 91 } 92 } 93 94 query(host) 95 char *host; 96 { 97 struct sockaddr_in router; 98 register struct rip *msg = (struct rip *)packet; 99 struct hostent *hp; 100 struct servent *sp; 101 102 bzero((char *)&router, sizeof (router)); 103 router.sin_family = AF_INET; 104 router.sin_addr.s_addr = inet_addr(host); 105 if (router.sin_addr.s_addr == -1) { 106 hp = gethostbyname(host); 107 if (hp == 0) { 108 printf("%s: unknown\n", host); 109 exit(1); 110 } 111 bcopy(hp->h_addr, &router.sin_addr, hp->h_length); 112 } 113 sp = getservbyname("router", "udp"); 114 if (sp == 0) { 115 printf("udp/router: service unknown\n"); 116 exit(1); 117 } 118 router.sin_port = sp->s_port; 119 msg->rip_cmd = RIPCMD_REQUEST; 120 msg->rip_vers = RIPVERSION; 121 msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); 122 msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); 123 if (sendto(s, packet, sizeof (struct rip), 0, 124 &router, sizeof(router)) < 0) 125 perror(host); 126 } 127 128 /* 129 * Handle an incoming routing packet. 130 */ 131 rip_input(from, size) 132 struct sockaddr_in *from; 133 int size; 134 { 135 register struct rip *msg = (struct rip *)packet; 136 struct netinfo *n; 137 char *name; 138 int lna, net, subnet; 139 struct hostent *hp; 140 struct netent *np; 141 142 if (msg->rip_cmd != RIPCMD_RESPONSE) 143 return; 144 printf("%d bytes from ", size); 145 if (nflag) 146 printf("%s:\n", inet_ntoa(from->sin_addr)); 147 else { 148 hp = gethostbyaddr(&from->sin_addr, sizeof (struct in_addr), 149 AF_INET); 150 name = hp == 0 ? "???" : hp->h_name; 151 printf("%s(%s):\n", name, inet_ntoa(from->sin_addr)); 152 } 153 size -= sizeof (int); 154 n = msg->rip_nets; 155 while (size > 0) { 156 register struct sockaddr_in *sin; 157 158 if (size < sizeof (struct netinfo)) 159 break; 160 if (msg->rip_vers > 0) { 161 n->rip_dst.sa_family = 162 ntohs(n->rip_dst.sa_family); 163 n->rip_metric = ntohl(n->rip_metric); 164 } 165 sin = (struct sockaddr_in *)&n->rip_dst; 166 net = inet_netof(sin->sin_addr); 167 subnet = inet_subnetof(sin->sin_addr); 168 lna = inet_lnaof(sin->sin_addr); 169 name = "???"; 170 if (!nflag) { 171 if (lna == INADDR_ANY) { 172 np = getnetbyaddr(net, AF_INET); 173 if (np) 174 name = np->n_name; 175 else if (net == 0) 176 name = "default"; 177 } else if ((lna & 0xff) == 0 && 178 (np = getnetbyaddr(subnet, AF_INET))) { 179 struct in_addr subnaddr, inet_makeaddr(); 180 181 subnaddr = inet_makeaddr(subnet, INADDR_ANY); 182 if (bcmp(&sin->sin_addr, &subnaddr, 183 sizeof(subnaddr)) == 0) 184 name = np->n_name; 185 else 186 goto host; 187 } else { 188 host: 189 hp = gethostbyaddr(&sin->sin_addr, 190 sizeof (struct in_addr), AF_INET); 191 if (hp) 192 name = hp->h_name; 193 } 194 printf("\t%s(%s), metric %d\n", name, 195 inet_ntoa(sin->sin_addr), n->rip_metric); 196 } else 197 printf("\t%s, metric %d\n", 198 inet_ntoa(sin->sin_addr), n->rip_metric); 199 size -= sizeof (struct netinfo), n++; 200 } 201 } 202 203 timeout() 204 { 205 timedout = 1; 206 } 207 208 /* 209 * Return the possible subnetwork number from an internet address. 210 * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING 211 * INSIDE OF THE HOST PART. We can only believe this if we have other 212 * information (e.g., we can find a name for this number). 213 */ 214 inet_subnetof(in) 215 struct in_addr in; 216 { 217 register u_long i = ntohl(in.s_addr); 218 219 if (IN_CLASSA(i)) 220 return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); 221 else if (IN_CLASSB(i)) 222 return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); 223 else 224 return ((i & 0xffffffc0) >> 28); 225 } 226