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.4 (Berkeley) 02/12/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 responses */ 22 23 int s; 24 int timedout, timeout(); 25 char packet[MAXPACKETSIZE]; 26 extern int errno; 27 int nflag; 28 29 main(argc, argv) 30 int argc; 31 char *argv[]; 32 { 33 int cc, count, bits; 34 struct sockaddr from; 35 int fromlen = sizeof(from); 36 struct timeval notime; 37 38 if (argc < 2) { 39 usage: 40 printf("usage: query [ -n ] hosts...\n"); 41 exit(1); 42 } 43 s = socket(AF_INET, SOCK_DGRAM, 0); 44 if (s < 0) { 45 perror("socket"); 46 exit(2); 47 } 48 49 argv++, argc--; 50 if (*argv[0] == '-') { 51 switch (argv[0][1]) { 52 case 'n': 53 nflag++; 54 break; 55 default: 56 goto usage; 57 } 58 argc--, argv++; 59 } 60 count = argc; 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(¬ime, sizeof(notime)); 72 signal(SIGALRM, timeout); 73 alarm(WTIME); 74 while ((count > 0 && !timedout) || 75 select(20, &bits, 0, 0, ¬ime) > 0) { 76 cc = recvfrom(s, packet, sizeof (packet), 0, 77 &from, &fromlen); 78 if (cc <= 0) { 79 if (cc < 0) { 80 if (errno == EINTR) 81 continue; 82 perror("recvfrom"); 83 (void) close(s); 84 exit(1); 85 } 86 continue; 87 } 88 rip_input(&from, cc); 89 count--; 90 } 91 } 92 93 query(host) 94 char *host; 95 { 96 struct sockaddr_in router; 97 register struct rip *msg = (struct rip *)packet; 98 struct hostent *hp; 99 struct servent *sp; 100 101 bzero((char *)&router, sizeof (router)); 102 router.sin_family = AF_INET; 103 router.sin_addr.s_addr = inet_addr(host); 104 if (router.sin_addr.s_addr == -1) { 105 hp = gethostbyname(host); 106 if (hp == 0) { 107 printf("%s: unknown\n", host); 108 exit(1); 109 } 110 bcopy(hp->h_addr, &router.sin_addr, hp->h_length); 111 } 112 sp = getservbyname("router", "udp"); 113 if (sp == 0) { 114 printf("udp/router: service unknown\n"); 115 exit(1); 116 } 117 router.sin_port = sp->s_port; 118 msg->rip_cmd = RIPCMD_REQUEST; 119 msg->rip_vers = RIPVERSION; 120 msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); 121 msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); 122 if (sendto(s, packet, sizeof (struct rip), 0, 123 &router, sizeof(router)) < 0) 124 perror(host); 125 } 126 127 /* 128 * Handle an incoming routing packet. 129 */ 130 rip_input(from, size) 131 struct sockaddr_in *from; 132 int size; 133 { 134 register struct rip *msg = (struct rip *)packet; 135 struct netinfo *n; 136 char *name; 137 int lna, net, subnet; 138 struct hostent *hp; 139 struct netent *np; 140 141 if (msg->rip_cmd != RIPCMD_RESPONSE) 142 return; 143 printf("%d bytes from "); 144 if (nflag) 145 printf("%s:\n", inet_ntoa(from->sin_addr)); 146 else { 147 hp = gethostbyaddr(&from->sin_addr, sizeof (struct in_addr), 148 AF_INET); 149 name = hp == 0 ? "???" : hp->h_name; 150 printf("%s(%s):\n", name, inet_ntoa(from->sin_addr)); 151 } 152 size -= sizeof (int); 153 n = msg->rip_nets; 154 while (size > 0) { 155 register struct sockaddr_in *sin; 156 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 sin = (struct sockaddr_in *)&n->rip_dst; 165 net = inet_netof(sin->sin_addr); 166 subnet = inet_subnetof(sin->sin_addr); 167 lna = inet_lnaof(sin->sin_addr); 168 name = "???"; 169 if (!nflag) { 170 if (lna == INADDR_ANY) { 171 np = getnetbyaddr(net, AF_INET); 172 if (np) 173 name = np->n_name; 174 else if (net == 0) 175 name = "default"; 176 } else if ((subnet != net) && ((lna & 0xff) == 0) && 177 (np = getnetbyaddr(subnet, AF_INET))) { 178 struct in_addr subnaddr, inet_makeaddr(); 179 180 subnaddr = inet_makeaddr(subnet, INADDR_ANY); 181 if (bcmp(&sin->sin_addr, &subnaddr, 182 sizeof(subnaddr)) == 0) 183 name = np->n_name; 184 else 185 goto host; 186 } else { 187 host: 188 hp = gethostbyaddr(&sin->sin_addr, 189 sizeof (struct in_addr), AF_INET); 190 if (hp) 191 name = hp->h_name; 192 } 193 printf("\t%s(%s), metric %d\n", name, 194 inet_ntoa(sin->sin_addr), n->rip_metric); 195 } else 196 printf("\t%s, metric %d\n", 197 inet_ntoa(sin->sin_addr), n->rip_metric); 198 size -= sizeof (struct netinfo), n++; 199 } 200 } 201 202 timeout() 203 { 204 timedout = 1; 205 } 206 207 /* 208 * Return the possible subnetwork number from an internet address. 209 * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING 210 * INSIDE OF THE HOST PART. We can only believe this if we have other 211 * information (e.g., we can find a name for this number). 212 */ 213 inet_subnetof(in) 214 struct in_addr in; 215 { 216 register u_long i = ntohl(in.s_addr); 217 218 if (IN_CLASSA(i)) 219 return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); 220 else if (IN_CLASSB(i)) 221 return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); 222 else 223 return ((i & 0xffffffc0) >> 28); 224 } 225