124265Ssklower /* 226177Ssklower * Copyright (c) 1983, 1986 Regents of the University of California. 324265Ssklower * All rights reserved. The Berkeley software License Agreement 424265Ssklower * specifies the terms and conditions for redistribution. 526177Ssklower * 626177Ssklower * This file include significant work done at Cornell University 726177Ssklower * by Bill Nesheim. That work included by permission. 824265Ssklower */ 924265Ssklower 1024265Ssklower #ifndef lint 1124326Ssklower char copyright[] = 1226177Ssklower "@(#) Copyright (c) 1983, 1986 Regents of the University of California.\n\ 1324326Ssklower All rights reserved.\n"; 1424265Ssklower #endif not lint 1524265Ssklower 1624326Ssklower #ifndef lint 17*30814Sbostic static char sccsid[] = "@(#)query.c 5.5 (Berkeley) 04/06/87"; 1824326Ssklower #endif not lint 1924326Ssklower 2024265Ssklower #include <sys/param.h> 2124265Ssklower #include <sys/protosw.h> 2224265Ssklower #include <sys/socket.h> 2324265Ssklower #include <sys/time.h> 2424265Ssklower #include <netinet/in.h> 2524265Ssklower #include <netns/ns.h> 2624265Ssklower #include <netns/idp.h> 2724265Ssklower #include <errno.h> 2824265Ssklower #include <stdio.h> 2924265Ssklower #include <netdb.h> 3024265Ssklower #include "../protocol.h" 3124265Ssklower #define IDPPORT_RIF 1 3224265Ssklower 3324265Ssklower #define WTIME 5 /* Time to wait for responses */ 3424265Ssklower 3524265Ssklower int s; 3624265Ssklower int timedout, timeout(); 3724265Ssklower char packet[MAXPACKETSIZE]; 3824265Ssklower extern int errno; 3924265Ssklower struct sockaddr_ns myaddr = {AF_NS}; 40*30814Sbostic char *ns_ntoa(); 4126176Ssklower struct ns_addr ns_addr(); 4224265Ssklower main(argc, argv) 4324265Ssklower int argc; 4424265Ssklower char *argv[]; 4524265Ssklower { 4624265Ssklower int cc, count, bits; 4724265Ssklower struct sockaddr from; 4824265Ssklower int fromlen = sizeof(from); 4924265Ssklower struct timeval notime; 5024265Ssklower 5124265Ssklower if (argc < 2) { 5224265Ssklower printf("usage: query hosts...\n"); 5324265Ssklower exit(1); 5424265Ssklower } 5524265Ssklower s = getsocket(SOCK_DGRAM, 0); 5624265Ssklower if (s < 0) { 5724265Ssklower perror("socket"); 5824265Ssklower exit(2); 5924265Ssklower } 6024265Ssklower 6124265Ssklower argv++, argc--; 6224326Ssklower query(argv,argc); 6324265Ssklower 6424265Ssklower /* 6524265Ssklower * Listen for returning packets; 6624265Ssklower * may be more than one packet per host. 6724265Ssklower */ 6824265Ssklower bits = 1 << s; 6924265Ssklower bzero(¬ime, sizeof(notime)); 7024265Ssklower signal(SIGALRM, timeout); 7124265Ssklower alarm(WTIME); 7224326Ssklower while (!timedout || 7324265Ssklower select(20, &bits, 0, 0, ¬ime) > 0) { 7424265Ssklower struct nspacket { 7524265Ssklower struct idp hdr; 7624265Ssklower char data[512]; 7724265Ssklower } response; 7824265Ssklower cc = recvfrom(s, &response, sizeof (response), 0, 7924265Ssklower &from, &fromlen); 8024265Ssklower if (cc <= 0) { 8124265Ssklower if (cc < 0) { 8224265Ssklower if (errno == EINTR) 8324265Ssklower continue; 8424265Ssklower perror("recvfrom"); 8524265Ssklower (void) close(s); 8624265Ssklower exit(1); 8724265Ssklower } 8824265Ssklower continue; 8924265Ssklower } 9024265Ssklower rip_input(&from, response.data, cc); 9124265Ssklower count--; 9224265Ssklower } 9324265Ssklower } 9426176Ssklower static struct sockaddr_ns router = {AF_NS}; 9526176Ssklower static struct ns_addr zero_addr; 9626176Ssklower static short allones[] = {-1, -1, -1}; 9724265Ssklower 9824326Ssklower query(argv,argc) 9924326Ssklower char **argv; 10024265Ssklower { 10124265Ssklower register struct rip *msg = (struct rip *)packet; 10224326Ssklower char *host = *argv; 10326176Ssklower struct ns_addr specific; 10424265Ssklower 10524326Ssklower argv++; argc--; 10626176Ssklower router.sns_addr = ns_addr(host); 10724265Ssklower router.sns_addr.x_port = htons(IDPPORT_RIF); 10826176Ssklower if (ns_hosteq(zero_addr, router.sns_addr)) { 10926176Ssklower router.sns_addr.x_host = *(union ns_host *) allones; 11026176Ssklower } 11124265Ssklower msg->rip_cmd = htons(RIPCMD_REQUEST); 11226176Ssklower msg->rip_nets[0].rip_dst = *(union ns_net *) allones; 11324265Ssklower msg->rip_nets[0].rip_metric = htons(HOPCNT_INFINITY); 11424326Ssklower if (argc > 0) { 11526176Ssklower specific = ns_addr(*argv); 11626176Ssklower msg->rip_nets[0].rip_dst = specific.x_net; 11726176Ssklower specific.x_host = zero_addr.x_host; 11826176Ssklower specific.x_port = zero_addr.x_port; 11926176Ssklower printf("Net asked for was %s\n", ns_ntoa(specific)); 12024326Ssklower } 12124265Ssklower if (sendto(s, packet, sizeof (struct rip), 0, 12224265Ssklower &router, sizeof(router)) < 0) 12324265Ssklower perror(host); 12424265Ssklower } 12524265Ssklower 12624265Ssklower /* 12724265Ssklower * Handle an incoming routing packet. 12824265Ssklower */ 12924265Ssklower rip_input(from, msg, size) 13024265Ssklower struct sockaddr_ns *from; 13124265Ssklower register struct rip *msg; 13224265Ssklower int size; 13324265Ssklower { 13424265Ssklower struct netinfo *n; 13524265Ssklower char *name; 13624265Ssklower int lna, net, subnet; 13724265Ssklower struct hostent *hp; 13824265Ssklower struct netent *np; 13926176Ssklower static struct ns_addr work; 14024265Ssklower 14124265Ssklower if (htons(msg->rip_cmd) != RIPCMD_RESPONSE) 14224265Ssklower return; 14326176Ssklower printf("from %s\n", ns_ntoa(from->sns_addr)); 14424265Ssklower size -= sizeof (struct idp); 14524265Ssklower size -= sizeof (short); 14624265Ssklower n = msg->rip_nets; 14724265Ssklower while (size > 0) { 14826176Ssklower union ns_net_u net; 14924265Ssklower if (size < sizeof (struct netinfo)) 15024265Ssklower break; 15126176Ssklower net.net_e = n->rip_dst; 15226176Ssklower printf("\t%d, metric %d\n", ntohl(net.long_e), 15324265Ssklower ntohs(n->rip_metric)); 15424265Ssklower size -= sizeof (struct netinfo), n++; 15524265Ssklower } 15624265Ssklower } 15724265Ssklower 15824265Ssklower timeout() 15924265Ssklower { 16024265Ssklower timedout = 1; 16124265Ssklower } 16224265Ssklower getsocket(type, proto) 16324265Ssklower int type, proto; 16424265Ssklower { 16524265Ssklower struct sockaddr_ns *sns = &myaddr; 16624265Ssklower int domain = sns->sns_family; 16724265Ssklower int retry, s, on = 1; 16824265Ssklower 16924265Ssklower retry = 1; 17024265Ssklower while ((s = socket(domain, type, proto)) < 0 && retry) { 17124265Ssklower perror("socket"); 17224265Ssklower sleep(5 * retry); 17324265Ssklower retry <<= 1; 17424265Ssklower } 17524265Ssklower if (retry == 0) 17624265Ssklower return (-1); 17724265Ssklower while (bind(s, sns, sizeof (*sns), 0) < 0 && retry) { 17824265Ssklower perror("bind"); 17924265Ssklower sleep(5 * retry); 18024265Ssklower retry <<= 1; 18124265Ssklower } 18224265Ssklower if (retry == 0) 18324265Ssklower return (-1); 18424265Ssklower if (domain==AF_NS) { 18524265Ssklower struct idp idp; 18624265Ssklower if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) { 18724265Ssklower perror("setsockopt SEE HEADERS"); 18824265Ssklower exit(1); 18924265Ssklower } 19024265Ssklower idp.idp_pt = NSPROTO_RI; 19124265Ssklower if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &idp, sizeof(idp))) { 19224265Ssklower perror("setsockopt SET HEADERS"); 19324265Ssklower exit(1); 19424265Ssklower } 19524265Ssklower } 19624265Ssklower if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { 19724265Ssklower perror("setsockopt SO_BROADCAST"); 19824265Ssklower exit(1); 19924265Ssklower } 20024265Ssklower return (s); 20124265Ssklower } 202