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