/* $Header: xnsbfs.c,v 1.4 87/01/16 15:46:52 ed Exp $ */ /* * $Log: xnsbfs.c,v $ * Revision 1.4 87/01/16 15:46:52 ed * Webster changes * * Revision 1.4 87/01/16 15:46:52 ed * Added exit(0) for normal exit * * Revision 1.3 86/12/16 15:29:56 ed * Add -a option to perform broadcast for Authentication servers * * Revision 1.2 86/07/29 06:39:27 jqj * added some comments and code cleanup in main routine. * * Revision 1.1 86/06/27 13:14:38 jqj * Initial revision * */ /* * XNS broadcast for servers: * syntax: xnsbfs -a [xnshostaddress] * * With -a option, broadcast for Authentication servers, * else Clearinghouse servers * With no arguments, sends a broadcast query to all directly connected XNS * networks looking for Clearinghouse servers * With an argument, sends a query to the particular address specified. * * Cornell University * Dept. of Computer Science * */ #include <sys/types.h> #include <sys/time.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <net/if.h> #include <netns/ns.h> #include <netns/idp.h> #include <signal.h> #include <syslog.h> #include <stdio.h> #include <errno.h> #include "pex.h" #define DEFAULTNET 2269 #define BUFLEN 1024 #define BFSPEXClientType 2 #define BFSClearinghouseSocket 20 #define BFSClearinghouseProgram 2 #define BFSClearinghouseVersion 2 #define BFSAuthenticationSocket 21 #define BFSAuthenticationProgram 14 #define BFSAuthenticationVersion 2 extern char *ns_ntoa(); int authlookup= 0; static int s; static int rnum = 1; /* PEX transaction ID */ static union { u_long c_long; u_short c_short[2]; } converter; struct xnsifdata { struct sockaddr_ns myaddr; struct sockaddr_ns bcstaddr; }; sendrequest(s,who,prognum,vernum) int s; struct sockaddr_ns *who; u_long prognum; u_short vernum; { struct pex *pex; struct CourierData { u_short courierlow; u_short courierhigh; u_short couriermsgtype; u_short tid; u_short program[2]; u_short version; u_short procval; } *cd; char buf[576]; int len; pex = (struct pex *)&buf[0]; cd = (struct CourierData *)&buf[/* sizeof struct pex */ 6 ]; pex->ph_idh = 0; pex->ph_idl = htons(rnum++); pex->ph_client = htons(BFSPEXClientType); cd->courierlow = cd->courierhigh = htons(3); cd->couriermsgtype = cd->tid = 0; converter.c_long = htonl(prognum); cd->program[0] = converter.c_short[0]; cd->program[1] = converter.c_short[1]; cd->version = htons(vernum); cd->procval = 0; len = sizeof (*cd) + /* sizeof(*pex) */ 6; if ( sendto(s, (char*)buf, len, 0, who, sizeof (*who)) < 0) { perror("sendto"); } } #define NUMIFS 20 main(argc, argv) int argc; char *argv[]; { struct ns_addr * daddr; struct xnsifdata baddrlist[NUMIFS]; extern struct ns_addr *getXNSaddr(); extern FILE *outfile; int i, numif; outfile = stdout; numif = localbcst(baddrlist); if (argc <= 1) for (i = 0; i < numif; i++) bfs(baddrlist[i]); else for (i=1; i < argc; i++) if ( strcmp(argv[i], "-a") == 0 ) { authlookup++; if (argc == 2) { for (i = 0; i < numif; i++) bfs(baddrlist[i]); } } else if ((daddr = getXNSaddr(argv[i])) != (struct ns_addr *) NULL) { baddrlist[i].bcstaddr.sns_family = AF_NS; if (daddr->x_host.s_host[0] == 0 && daddr->x_host.s_host[1] == 0 && daddr->x_host.s_host[2] == 0) { daddr->x_host.s_host[0] = 0xFFFF; daddr->x_host.s_host[1] = 0xFFFF; daddr->x_host.s_host[2] = 0xFFFF; } baddrlist[i-1].bcstaddr.sns_addr = *daddr; baddrlist[i-1].myaddr.sns_family = AF_NS; bfs(baddrlist[i-1]); } exit(0); } bfs(ifdata) struct xnsifdata ifdata; { struct sockaddr_ns me, you, who; struct idp *idp; struct pex *pex; u_short *data; struct ns_addr *srvr; char buf[576]; int yoursize; int m,n,clienttype; int bytesReceived; static int on = 1; int mask; struct timeval tval; u_long prognum; u_short vernum; if ((s = socket(AF_NS, SOCK_DGRAM, 0)) < 0) { perror("socket"); exit(1); } idp = (struct idp *)&buf[0]; pex = (struct pex *) &buf[ sizeof (struct idp)]; data = (u_short *) &buf[sizeof (struct idp) + /*sizeof (struct pex)*/ 6]; me = ifdata.myaddr; me.sns_port = htons(getpid()%1000+3000); /* so we don't have to be root */ if (bind(s, &me, sizeof (me)) < 0 ) { perror("bind:"); exit(1); } if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) { perror("setsockopt SEE HEADERS:"); exit(1); } idp->idp_pt = NSPROTO_PE; if (setsockopt(s, 0, SO_DEFAULT_HEADERS, idp, sizeof(struct idp))) { perror("setsockopt SET HEADER:"); exit(1); } if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { perror("setsockopt SO_BROADCAST:"); exit(1); } who = ifdata.bcstaddr; if (authlookup) { who.sns_port = htons(BFSAuthenticationSocket); prognum= BFSAuthenticationProgram; vernum= BFSAuthenticationVersion; } else { who.sns_port = htons(BFSClearinghouseSocket); prognum= BFSClearinghouseProgram; vernum= BFSClearinghouseVersion; } sendrequest(s,&who, prognum, vernum); tval.tv_sec = 3; tval.tv_usec = 0; mask = 1<<s; while ((select(20, &mask, 0, 0, &tval) > 0) && (mask & 1<<s) ) { fflush(stdout); yoursize = sizeof (you); if ((n = recvfrom(s, (char *) buf, sizeof(buf), 0, &you, &yoursize)) < 0) { extern int errno; if (errno != EINTR) perror("rcvfrom:"); continue; } tval.tv_sec = 3; tval.tv_usec = 0; mask = 1<<s; if ( idp->idp_pt != NSPROTO_PE ) { fprintf(stderr,"idp_pt = %d ?\n", idp->idp_pt); continue; } converter.c_short[0] = pex->ph_idh; converter.c_short[1] = pex->ph_idl; m = htonl(converter.c_long); clienttype = ntohs(pex->ph_client); bytesReceived = n - sizeof (struct idp) - /*sizeof (struct pex)*/ 6; if ( clienttype != BFSPEXClientType) continue; /* got a BFS reply packet, figure out what it is */ /* figure out size of packet */ if (ntohs(data[2]) == 2 /* result */ ) { srvr = (struct ns_addr *)&data[6]; } printdomains(you.sns_addr); } /* listen for more */ close(s); } /* * return the broadcast address (including network number) of the local network. * We consider only broadcast nets, though a reasonable extension would be to * send a point-to-point BFS to the host at the other end of a p-to-p link. */ localbcst(results) struct xnsifdata results[]; { int s, n, numinterfaces, numxnsifs; struct ifconf ifc; char buf[sizeof(struct ifreq) * (NUMIFS-1)]; /* array of structures */ struct ifreq *ifr; extern char *malloc(); if ((s = socket(AF_NS, SOCK_DGRAM, 0)) < 0) { perror("socket:"); exit(1); } ifc.ifc_len = sizeof (buf); ifc.ifc_buf = buf; if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { perror("ioctl SIOCGIFCONF:"); numinterfaces = 0; } else numinterfaces = ifc.ifc_len / sizeof (struct ifreq); for (n = 0, ifr = ifc.ifc_req, numxnsifs = 0; n < numinterfaces && numxnsifs < NUMIFS-1; n++, ifr++) { /* no one cares about software loopback interfaces */ /* we don't care about non-XNS addressess either */ if (strncmp(ifr->ifr_name,"lo", 2)==0 || ifr->ifr_addr.sa_family != AF_NS) continue; results[numxnsifs].myaddr = *(struct sockaddr_ns *) &ifr->ifr_addr; /* get IF flags */ if (ioctl(s, SIOCGIFFLAGS, (char *)ifr) < 0) { perror("ioctl SIOCGIFFLAGS:"); continue; } if ((ifr->ifr_flags & IFF_UP) == 0 || (ifr->ifr_flags & IFF_BROADCAST) == 0) continue; /* get the broadcast address */ if (ioctl(s, SIOCGIFBRDADDR, (char *)ifr) < 0) { perror("ioctl SIOCGIFBRDADDR:"); continue; } bcopy( &ifr->ifr_broadaddr, &results[numxnsifs++].bcstaddr, sizeof(struct sockaddr_ns) ); } close(s); return numxnsifs; }