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) 5/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: }