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