bootparam_subr.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 407 行
C
407 行
/* SCCSID: @(#)bootparam_subr.c 4.1 7/2/90 *//* Based on: * @(#)bootparam_subr.c 1.10 88/02/29 D/NFS * static char sccsid[] = "@(#)bootparam_subr.c 1.3 87/11/17 SMI"; *//* * Subroutines that implement the bootparam services. */#include <rpcsvc/bootparam.h>#include <netdb.h>#include <nlist.h>#include <stdio.h>#include <ctype.h>#include <sys/file.h>#include <sys/socket.h>#include <sys/mbuf.h>#define KERNEL /* to get RTHASHSIZ */#include <net/route.h>#undef KERNEL#include <net/if.h> /* for structs ifnet and ifaddr */#include <netinet/in.h>#ifdef ifa_broadaddr#include <netinet/in_var.h> /* for struct in_ifaddr (4.3bsd only) */#endif ifa_broadaddr#define LINESIZE 1024 int debug = 0;/* * Whoami turns a client address into a client name * and suggested route machine.*/bp_whoami_res *bootparamproc_whoami_1(argp) bp_whoami_arg *argp;{ static bp_whoami_res res; struct in_addr clnt_addr; struct in_addr route_addr, get_route(); struct hostent *hp; static char clnt_entry[LINESIZE]; static char domain[32]; int reason; if (argp->client_address.address_type != IP_ADDR_TYPE) { if (debug) { fprintf(stderr, "Whoami failed: unknown address type %d\n", argp->client_address.address_type); } return (NULL); } bcopy ((char *) &argp->client_address.bp_address.ip_addr, (char *) &clnt_addr, sizeof (clnt_addr)); hp = gethostbyaddr(&clnt_addr, sizeof clnt_addr, AF_INET); if (hp == NULL) { if (debug) { fprintf(stderr, "Whoami failed: gethostbyaddr for %s.\n", inet_ntoa (clnt_addr)); } return (NULL); } if ((reason = bp_getclntent(hp->h_name, clnt_entry)) != 0) { if (debug) { fprintf(stderr, "bp_getclntent(%s) failed (%s).\n", hp->h_name, reason > 0? (char *)yperr_string(reason) : "entry not found"); } return (NULL); } res.client_name = hp->h_name; getdomainname(domain, sizeof domain); res.domain_name = domain; res.router_address.address_type = IP_ADDR_TYPE; route_addr = get_route(clnt_addr); bcopy ((char *) &route_addr, (char *) &res.router_address.bp_address.ip_addr, sizeof (res.router_address.bp_address.ip_addr)); if (debug) { fprintf(stderr, "Whoami returning name \"%s\" domain \"%s\" router %s\n", res.client_name, res.domain_name, inet_ntoa (res.router_address.bp_address.ip_addr)); } return (&res);}struct nlist nl[] = {#define N_RTHOST 0 { "_rthost" },#define N_RTNET 1 { "_rtnet" }, "",};char *system = "/vmunix";char *kmemf = "/dev/kmem";int kmem;/* * nlist the kernel once at program startup time. */init_nlist(){ if (nl[0].n_type == 0) { nlist(system, nl); if (nl[0].n_type == 0) { fprintf(stderr, "no namelist for %s\n", system); exit(1); } kmem = open(kmemf, 0); if (kmem < 0) { fprintf(stderr, "cannot open %s\n", kmemf); exit(1); } }}/* * get_route paws through the kernel's routing table looking for a route * via a gateway that is on the same network and subnet as the client. * Any gateway will do because the selected gateway will return ICMP redirect * messages to the client if it can not route the traffic itself. */struct in_addrget_route(client_addr) struct in_addr client_addr;{ off_t hostaddr, netaddr; struct mbuf mb; register struct rtentry *rt; register struct mbuf *m; struct netent *np; struct mbuf *routehash[RTHASHSIZ]; struct sockaddr_in *def_sin = NULL; int i, doinghost = 1; u_long net_subnetmask; /* subnet mask in network order */ /* JSD: only attempt route lookup if '-D' (2) specified, since * lookups are currently broken. Just return client addr... */ if (debug != 2) return(client_addr); hostaddr = nl[N_RTHOST].n_value; if (hostaddr == 0) { fprintf(stderr, "rthost: symbol not in namelist\n"); exit(1); } netaddr = nl[N_RTNET].n_value; if (netaddr == 0) { fprintf(stderr, "rtnet: symbol not in namelist\n"); exit(1); } if (lseek(kmem, (off_t) hostaddr, 0) == (off_t) -1) { perror ("lseek rthost"); exit (1); } if (read(kmem, (char *) routehash, sizeof (routehash)) != sizeof (routehash)) { fprintf (stderr, "read rthost in kmem failed.\n"); exit (1); }again: for (i = 0; i < RTHASHSIZ; i++) { if (routehash[i] == 0) continue; for (m = routehash[i]; m; m = mb.m_next) { struct sockaddr_in *sin;#ifdef ifa_broadaddr struct ifnet ifnet; struct ifaddr *ifa; struct ifaddr ifaddr; struct in_ifaddr in_ifaddr; struct in_ifaddr *ia;#endif ifa_broadaddr if (lseek(kmem, (off_t) m, 0) == (off_t) -1) { perror ("lseek routehash"); exit (1); } if (read(kmem, (char *) &mb, sizeof (mb)) != sizeof (mb)) { printf ("read routehash from kmem failed.\n"); exit (1); } rt = mtod(&mb, struct rtentry *); /* * reject routes that are down and routes that are not * on the same net as the client. */ if ((rt->rt_flags & RTF_UP) == 0) { continue; } sin = (struct sockaddr_in *)&rt->rt_gateway; if (netof(client_addr.s_addr) != netof(sin->sin_addr.s_addr)) { continue; }#ifdef ifa_broadaddr /* * reject routes that are not on the same subnet * as the client. */ if (lseek (kmem, (off_t) rt->rt_ifp, 0) == (off_t) -1) { perror ("lseek rt->rt_ifp"); exit (1); } if (read (kmem, (char *) &ifnet, sizeof (struct ifnet)) != sizeof (struct ifnet)) { fprintf (stderr, "read rt->rt_ifp from kmem failed.\n"); exit (1); } ifa = ifnet.if_addrlist; while (ifa != (struct ifaddr *) 0) { if (lseek (kmem, (off_t) ifa, 0) == (off_t) -1) { perror ("lseek ifaddr"); exit (1); } if (read (kmem, (char *) &ifaddr, sizeof (struct ifaddr)) != sizeof (struct ifaddr)) { fprintf (stderr, "read ifaddr from kmem failed.\n"); exit (1); } if (ifaddr.ifa_addr.sa_family == AF_INET) break; ifa = ifaddr.ifa_next; } if (ifa == (struct ifaddr *) 0) { continue; } /* * read same ifaddr struct again, this time as an * in_ifaddr struct. */ if (lseek (kmem, (off_t) ifa, 0) == (off_t) -1) { perror ("lseek in_ifaddr"); exit (1); } if (read (kmem, (char *) &in_ifaddr, sizeof (struct in_ifaddr)) != sizeof (struct in_ifaddr)) { fprintf ("read in_ifaddr from kmem failed.\n"); exit (1); } net_subnetmask = htonl(in_ifaddr.ia_subnetmask); if ((net_subnetmask & sin->sin_addr.s_addr) != (net_subnetmask & client_addr.s_addr)) { if (debug) { /* * must do this in two writes since inet_ntoa * uses static storage for returned result */ fprintf (stderr, "subnet mismatch. gateway = %s, ", inet_ntoa (sin->sin_addr)); fprintf (stderr, "client_addr = %s\n", inet_ntoa (client_addr)); } continue; }#endif ifa_broadaddr /* * route passes all of our tests so far. If it is * marked as a gateway, return it now. Otherwise, * save it as a default to return if there are no * other gateways found. */ if ((rt->rt_flags & RTF_GATEWAY) == 0) { if (def_sin == NULL) def_sin = sin; } else { return (sin->sin_addr); } } } if (doinghost) { if (lseek(kmem, (off_t) netaddr, 0) == (off_t) -1) { perror ("lseek rtnet"); exit (1); } if (read(kmem, (char *) routehash, sizeof (routehash)) != sizeof (routehash)) { fprintf ("read rtnet in kmem failed.\n"); exit (1); } doinghost = 0; goto again; } if (def_sin) { return (def_sin->sin_addr); } if (debug) { fprintf(stderr, "No route found for client %s.\n", inet_ntoa (client_addr)); } bzero ((char *) &client_addr, sizeof (client_addr)); return (client_addr);}/* * argument to netof is in network order. IN_CLASS? macros assume * host order, so we must make the appropriate conversions. */netof(i) register int i;{ i = ntohl(i); if (IN_CLASSA(i)) return (htonl( (i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT)); else if (IN_CLASSB(i)) return (htonl( (i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT)); else return (htonl( (i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT));}/* * Getfile gets the client name and the key and returns its server * and the pathname for that key. */bp_getfile_res *bootparamproc_getfile_1(argp) bp_getfile_arg *argp;{ static bp_getfile_res res; static char clnt_entry[LINESIZE]; struct hostent *hp; char *cp; int reason; if ((reason = bp_getclntkey(argp->client_name, argp->file_id, clnt_entry)) != 0) { if (debug) { fprintf(stderr, "bp_getclntkey(%s, %s) failed (%s).\n", argp->client_name, argp->file_id, reason > 0? (char *)yperr_string(reason) : "entry not found"); } return (NULL); } if ((cp = (char *)index(clnt_entry, ':')) == 0) { return (NULL); } *cp++ = '\0'; res.server_name = clnt_entry; res.server_path = cp; if (*res.server_name == 0) { res.server_address.address_type = IP_ADDR_TYPE; bzero(&res.server_address.bp_address.ip_addr, sizeof(res.server_address.bp_address.ip_addr)); } else { if ((hp = gethostbyname(res.server_name)) == NULL) { if (debug) { fprintf(stderr, "getfile_1: gethostbyname(%s) failed\n", res.server_name); } return (NULL); } res.server_address.address_type = IP_ADDR_TYPE; bcopy ((char *) hp->h_addr, (char *) &res.server_address.bp_address.ip_addr, sizeof (res.server_address.bp_address.ip_addr)); } if (debug) { getf_printres(&res); } return (&res);}getf_printres(res) bp_getfile_res *res;{ fprintf(stderr, "getfile_1: file is \"%s\" %s \"%s\"\n", res->server_name, inet_ntoa (res->server_address.bp_address.ip_addr), res->server_path);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?