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.1 (Berkeley) 06/07/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 "../protocol.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("from %s(%s):\n", name, inet_ntoa(from->sin_addr)); 131 size -= sizeof (int); 132 n = msg->rip_nets; 133 while (size > 0) { 134 register struct sockaddr_in *sin; 135 136 if (size < sizeof (struct netinfo)) 137 break; 138 if (msg->rip_vers > 0) { 139 n->rip_dst.sa_family = 140 ntohs(n->rip_dst.sa_family); 141 n->rip_metric = ntohl(n->rip_metric); 142 } 143 sin = (struct sockaddr_in *)&n->rip_dst; 144 net = inet_netof(sin->sin_addr); 145 subnet = inet_subnetof(sin->sin_addr); 146 lna = inet_lnaof(sin->sin_addr); 147 name = "???"; 148 if (lna == INADDR_ANY) { 149 np = getnetbyaddr(net, AF_INET); 150 if (np) 151 name = np->n_name; 152 else if (net == 0) 153 name = "default"; 154 } else if ((subnet != net) && ((lna & 0xff) == 0) && 155 (np = getnetbyaddr(subnet, AF_INET))) { 156 struct in_addr subnaddr, inet_makeaddr(); 157 158 subnaddr = inet_makeaddr(subnet, INADDR_ANY); 159 if (bcmp(&sin->sin_addr, &subnaddr, sizeof(subnaddr)) == 0) 160 name = np->n_name; 161 else 162 goto host; 163 } else { 164 host: 165 hp = gethostbyaddr(&sin->sin_addr, 166 sizeof (struct in_addr), AF_INET); 167 if (hp) 168 name = hp->h_name; 169 } 170 printf("\t%s(%s), metric %d\n", name, 171 inet_ntoa(sin->sin_addr), n->rip_metric); 172 size -= sizeof (struct netinfo), n++; 173 } 174 } 175 176 timeout() 177 { 178 timedout = 1; 179 } 180 181 /* 182 * Return the possible subnetwork number from an internet address. 183 * If the address is of the form of a subnet address (most significant 184 * bit of the host part is set), believe the subnet exists. 185 * Otherwise, return the network number. 186 * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING 187 * INSIDE OF THE HOST PART. We can only believe this if we have other 188 * information (e.g., we can find a name for this number). 189 */ 190 inet_subnetof(in) 191 struct in_addr in; 192 { 193 register u_long i = ntohl(in.s_addr); 194 195 if (IN_CLASSA(i)) { 196 if (IN_SUBNETA(i)) 197 return ((i & IN_CLASSA_SUBNET) >> IN_CLASSA_SUBNSHIFT); 198 else 199 return ((i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT); 200 } else if (IN_CLASSB(i)) { 201 if (IN_SUBNETB(i)) 202 return ((i & IN_CLASSB_SUBNET) >> IN_CLASSB_SUBNSHIFT); 203 else 204 return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); 205 } else 206 return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); 207 } 208