1 /*- 2 * Copyright (c) 1983, 1986, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code includes software contributed to Berkeley by 6 * Bill Nesheim at Cornell University. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char copyright[] = 13 "@(#) Copyright (c) 1983, 1986, 1993\n\ 14 The Regents of the University of California. All rights reserved.\n"; 15 #endif /* not lint */ 16 17 #ifndef lint 18 static char sccsid[] = "@(#)query.c 8.1 (Berkeley) 06/05/93"; 19 #endif /* not lint */ 20 21 #include <sys/param.h> 22 #include <sys/protosw.h> 23 #include <sys/socket.h> 24 #include <sys/time.h> 25 #include <netinet/in.h> 26 #include <netns/ns.h> 27 #include <netns/idp.h> 28 #include <errno.h> 29 #include <stdio.h> 30 #include <netdb.h> 31 #include "../protocol.h" 32 #define IDPPORT_RIF 1 33 34 #define WTIME 5 /* Time to wait for responses */ 35 36 int s; 37 int timedout, timeout(); 38 char packet[MAXPACKETSIZE]; 39 extern int errno; 40 struct sockaddr_ns myaddr = {sizeof(myaddr), AF_NS}; 41 char *ns_ntoa(); 42 struct ns_addr ns_addr(); 43 main(argc, argv) 44 int argc; 45 char *argv[]; 46 { 47 int cc, count, bits; 48 struct sockaddr from; 49 int fromlen = sizeof(from); 50 struct timeval notime; 51 52 if (argc < 2) { 53 printf("usage: query hosts...\n"); 54 exit(1); 55 } 56 s = getsocket(SOCK_DGRAM, 0); 57 if (s < 0) { 58 perror("socket"); 59 exit(2); 60 } 61 62 argv++, argc--; 63 query(argv,argc); 64 65 /* 66 * Listen for returning packets; 67 * may be more than one packet per host. 68 */ 69 bits = 1 << s; 70 bzero(¬ime, sizeof(notime)); 71 signal(SIGALRM, timeout); 72 alarm(WTIME); 73 while (!timedout || 74 select(20, &bits, 0, 0, ¬ime) > 0) { 75 struct nspacket { 76 struct idp hdr; 77 char data[512]; 78 } response; 79 cc = recvfrom(s, &response, sizeof (response), 0, 80 &from, &fromlen); 81 if (cc <= 0) { 82 if (cc < 0) { 83 if (errno == EINTR) 84 continue; 85 perror("recvfrom"); 86 (void) close(s); 87 exit(1); 88 } 89 continue; 90 } 91 rip_input(&from, response.data, cc); 92 count--; 93 } 94 } 95 static struct sockaddr_ns router = {sizeof(myaddr), AF_NS}; 96 static struct ns_addr zero_addr; 97 static short allones[] = {-1, -1, -1}; 98 99 query(argv,argc) 100 char **argv; 101 { 102 register struct rip *msg = (struct rip *)packet; 103 char *host = *argv; 104 int flags = 0; 105 struct ns_addr specific; 106 107 if (bcmp(*argv, "-r", 3) == 0) { 108 flags = MSG_DONTROUTE; argv++; argc--; 109 } 110 host = *argv; 111 router.sns_addr = ns_addr(host); 112 router.sns_addr.x_port = htons(IDPPORT_RIF); 113 if (ns_hosteq(zero_addr, router.sns_addr)) { 114 router.sns_addr.x_host = *(union ns_host *) allones; 115 } 116 msg->rip_cmd = htons(RIPCMD_REQUEST); 117 msg->rip_nets[0].rip_dst = *(union ns_net *) allones; 118 msg->rip_nets[0].rip_metric = htons(HOPCNT_INFINITY); 119 if (argc > 0) { 120 specific = ns_addr(*argv); 121 msg->rip_nets[0].rip_dst = specific.x_net; 122 specific.x_host = zero_addr.x_host; 123 specific.x_port = zero_addr.x_port; 124 printf("Net asked for was %s\n", ns_ntoa(specific)); 125 } 126 if (sendto(s, packet, sizeof (struct rip), flags, 127 &router, sizeof(router)) < 0) 128 perror(host); 129 } 130 131 /* 132 * Handle an incoming routing packet. 133 */ 134 rip_input(from, msg, size) 135 struct sockaddr_ns *from; 136 register struct rip *msg; 137 int size; 138 { 139 struct netinfo *n; 140 char *name; 141 int lna, net, subnet; 142 struct hostent *hp; 143 struct netent *np; 144 static struct ns_addr work; 145 146 if (htons(msg->rip_cmd) != RIPCMD_RESPONSE) 147 return; 148 printf("from %s\n", ns_ntoa(from->sns_addr)); 149 size -= sizeof (struct idp); 150 size -= sizeof (short); 151 n = msg->rip_nets; 152 while (size > 0) { 153 union ns_net_u net; 154 if (size < sizeof (struct netinfo)) 155 break; 156 net.net_e = n->rip_dst; 157 printf("\t%d, metric %d\n", ntohl(net.long_e), 158 ntohs(n->rip_metric)); 159 size -= sizeof (struct netinfo), n++; 160 } 161 } 162 163 timeout() 164 { 165 timedout = 1; 166 } 167 getsocket(type, proto) 168 int type, proto; 169 { 170 struct sockaddr_ns *sns = &myaddr; 171 int domain = sns->sns_family; 172 int retry, s, on = 1; 173 174 retry = 1; 175 while ((s = socket(domain, type, proto)) < 0 && retry) { 176 perror("socket"); 177 sleep(5 * retry); 178 retry <<= 1; 179 } 180 if (retry == 0) 181 return (-1); 182 while (bind(s, sns, sizeof (*sns), 0) < 0 && retry) { 183 perror("bind"); 184 sleep(5 * retry); 185 retry <<= 1; 186 } 187 if (retry == 0) 188 return (-1); 189 if (domain==AF_NS) { 190 struct idp idp; 191 if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) { 192 perror("setsockopt SEE HEADERS"); 193 exit(1); 194 } 195 idp.idp_pt = NSPROTO_RI; 196 if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &idp, sizeof(idp))) { 197 perror("setsockopt SET HEADERS"); 198 exit(1); 199 } 200 } 201 if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { 202 perror("setsockopt SO_BROADCAST"); 203 exit(1); 204 } 205 return (s); 206 } 207