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