pax_global_header00006660000000000000000000000064136727032400014516gustar00rootroot0000000000000052 comment=c7d868e8b343ff04b8fa9ab7cb00e80375002d32 .gitignore000066400000000000000000000001241367270324000130470ustar00rootroot00000000000000aklog-kafs kafs-check-config kafs-preload kafs-dns *.o *.os libkafs_client.so* TAGS LICENCE.GPL000066400000000000000000000431151367270324000124740ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. Makefile000066400000000000000000000110631367270324000125230ustar00rootroot00000000000000CFLAGS = -g -O2 -Wall -Wsign-compare MKDIR = mkdir INSTALL = install DESTDIR = ETCDIR = /etc BINDIR = /usr/bin LIBEXECDIR = /usr/libexec MANDIR = /usr/share/man DATADIR = /usr/share/kafs-client UNITDIR = /usr/lib/systemd/system SPECFILE = redhat/kafs-client.spec LNS := ln -sf ############################################################################### # # Determine the current package version from the specfile # ############################################################################### VERSION := $(word 2,$(shell grep "^Version:" $(SPECFILE))) TARBALL := kafs-client-$(VERSION).tar ZTARBALL := $(TARBALL).bz2 ############################################################################### # # Guess at the appropriate word size # ############################################################################### BUILDFOR := $(shell file /usr/bin/make | sed -e 's!.*ELF \(32\|64\)-bit.*!\1!')-bit ifeq ($(BUILDFOR),32-bit) CFLAGS += -m32 else ifeq ($(BUILDFOR),64-bit) CFLAGS += -m64 endif endif ############################################################################### # # Build stuff # ############################################################################### all: $(MAKE) -C src all ############################################################################### # # Install everything # ############################################################################### MAN1 := $(MANDIR)/man1 MAN5 := $(MANDIR)/man5 MAN7 := $(MANDIR)/man7 MAN8 := $(MANDIR)/man8 install: all $(MAKE) -C src install $(MKDIR) -p -m755 $(DESTDIR)$(MAN1)/ $(MKDIR) -p -m755 $(DESTDIR)$(MAN5)/ $(MKDIR) -p -m755 $(DESTDIR)$(MAN7)/ $(MKDIR) -p -m755 $(DESTDIR)$(MAN8)/ $(INSTALL) -D -m 0644 man/*.1 $(DESTDIR)$(MAN1)/ $(INSTALL) -D -m 0644 man/*.5 $(DESTDIR)$(MAN5)/ $(INSTALL) -D -m 0644 man/*.7 $(DESTDIR)$(MAN7)/ $(INSTALL) -D -m 0644 man/*.8 $(DESTDIR)$(MAN8)/ $(INSTALL) -D -m 0644 conf/cellservdb.conf $(DESTDIR)$(DATADIR)/cellservdb.conf $(INSTALL) -D -m 0644 conf/client.conf $(DESTDIR)$(ETCDIR)/kafs/client.conf $(INSTALL) -D -m 0644 conf/kafs_dns.conf $(DESTDIR)$(ETCDIR)/request-key.d/kafs_dns.conf $(INSTALL) -D -m 0644 conf/kafs-config.service $(DESTDIR)$(UNITDIR)/kafs-config.service $(INSTALL) -D -m 0644 conf/afs.mount $(DESTDIR)$(UNITDIR)/afs.mount $(MKDIR) -m755 $(DESTDIR)$(ETCDIR)/kafs/client.d ############################################################################### # # Clean up # ############################################################################### clean: $(MAKE) -C src clean $(RM) debugfiles.list debugsources.list distclean: clean $(MAKE) -C src distclean $(RM) -r rpmbuild $(TARBALL) ############################################################################### # # Generate a tarball # ############################################################################### $(ZTARBALL): git archive --prefix=kafs-client-$(VERSION)/ --format tar HEAD | \ bzip2 -9 >$(ZTARBALL) tarball: $(ZTARBALL) ############################################################################### # # Generate an RPM # ############################################################################### SRCBALL := rpmbuild/SOURCES/$(TARBALL) ZSRCBALL := rpmbuild/SOURCES/$(ZTARBALL) BUILDID := .local rpmver0 := $(shell rpmspec -q ./redhat/kafs-client.spec --define "buildid $(BUILDID)") rpmver1 := $(word 1,$(rpmver0)) rpmver2 := $(subst ., ,$(rpmver1)) rpmver3 := $(lastword $(rpmver2)) rpmver4 := $(patsubst %.$(rpmver3),%,$(rpmver1)) rpmver := $(patsubst kafs-client-%,%,$(rpmver4)) SRPM := rpmbuild/SRPMS/kafs-client-$(rpmver).src.rpm RPMBUILDDIRS := \ --define "_srcrpmdir $(CURDIR)/rpmbuild/SRPMS" \ --define "_rpmdir $(CURDIR)/rpmbuild/RPMS" \ --define "_sourcedir $(CURDIR)/rpmbuild/SOURCES" \ --define "_specdir $(CURDIR)/rpmbuild/SPECS" \ --define "_builddir $(CURDIR)/rpmbuild/BUILD" \ --define "_buildrootdir $(CURDIR)/rpmbuild/BUILDROOT" RPMFLAGS := \ --define "buildid $(BUILDID)" rpm: tarball mkdir -p rpmbuild chmod ug-s rpmbuild mkdir -p rpmbuild/{SPECS,SOURCES,BUILD,BUILDROOT,RPMS,SRPMS} cp $(ZTARBALL) $(ZSRCBALL) rpmbuild -ts $(ZSRCBALL) --define "_srcrpmdir rpmbuild/SRPMS" $(RPMFLAGS) rpmbuild --rebuild $(SRPM) $(RPMBUILDDIRS) $(RPMFLAGS) rpmlint: rpm rpmlint $(SRPM) $(CURDIR)/rpmbuild/RPMS/*/kafs-client-{,debuginfo-}$(rpmver).*.rpm .PHONY: rpmlint rpm tarball $(ZTARBALL) ############################################################################### # # Build debugging # ############################################################################### show_vars: @echo VERSION=$(VERSION) @echo TARBALL=$(TARBALL) @echo BUILDFOR=$(BUILDFOR) README000066400000000000000000000013631367270324000117450ustar00rootroot00000000000000 =========== kAFS CLIENT =========== Contents: (*) Overview. ======== OVERVIEW ======== The kafs-client package provides the basics for using the kAFS filesystem in the Linux kernel. It provides: (*) The aklog-kafs program that can be used to authenticate with Kerberos so that the kAFS filesystem can perform authenticated and encrypted communications with an AFS fileserver. (*) A dynamic mount on /afs so that the roots of arbitrary cells can be mounted automatically, using the DNS to look up their details. This needs to be enabled by: systemctl enable afs.mount and can then be accessed by referring to cell names in the /afs/ directory, for example: ls /afs/grand.central.org/ SUBMITTING_PATCHES000066400000000000000000000035251367270324000136460ustar00rootroot00000000000000 ================== SUBMITTING PATCHES ================== Patches can be sent to the linux-afs@lists.infradead.org mailing list or directly to David Howells , the author, in a private email. When sending patches to be included in kafs-utils, please certify that your patch meets the criteria below by including include a sign-off line in your email which looks like this: Signed-off-by: Random J Developer This confirms that you are permitted to submit the patch for inclusion in kafs-utils under the GPLv2 licence. The full text of the certificate is as follows: Developer's Certificate of Origin v1.1 ====================================== By making a contribution to this project, I certify that: (a) The contribution was created in whole or in part by me and I have the right to submit it under the open source licences indicated in the file; or (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source licence and I have the right under that licence to submit that work with modifications, whether created in whole or in part by me, under the same open source licence (unless I am permitted to submit under a different licence), as indicated in the file; or (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. and also that: (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source licence(s) involved. conf/000077500000000000000000000000001367270324000120075ustar00rootroot00000000000000conf/afs.mount000066400000000000000000000002761367270324000136510ustar00rootroot00000000000000[Unit] Description=kAFS Dynamic Root mount ConditionPathExists=/afs Wants=kafs-config.service [Mount] What=none Where=/afs Type=afs Options=_netdev,dyn [Install] WantedBy=remote-fs.target conf/cellservdb.conf000066400000000000000000001313321367270324000150060ustar00rootroot00000000000000# AuristorFS cellservdb client configuration # 8 October 2017 # # This file should be placed in the yfs-client.conf.d directory # or beincluded within the yfs-client.conf file. [cells] # grand.central.org imported from DNS SRV grand.central.org = { description = "Grand Central Org" use_dns = yes kerberos_realm = GRAND.CENTRAL.ORG servers = { grand.mit.edu = { address = 18.9.48.14 } grand-old-opry.central.org = { address = 128.2.13.219 } } } # wu-wien.ac.at imported from DNS AFSDB wu-wien.ac.at = { description = "University of Economics, Vienna, Austria" use_dns = yes servers = { heimdal.wu-wien.ac.at = { address = 137.208.7.37 } caravaggio.wu-wien.ac.at = { address = 137.208.7.57 } vermeer.wu-wien.ac.at = { address = 137.208.8.14 } goya.wu-wien.ac.at = { address = 137.208.3.33 } } } # hephy.at imported from DNS SRV hephy.at = { description = "hephy-vienna" use_dns = yes servers = { afs01.hephy.oeaw.ac.at = { address = 193.170.243.10 } afs02.hephy.oeaw.ac.at = { address = 193.170.243.12 } afs03.hephy.oeaw.ac.at = { address = 193.170.243.14 } } } # cgv.tugraz.at imported from DNS SRV cgv.tugraz.at = { description = "CGV cell" use_dns = yes servers = { phobos.cgv.tugraz.at = { address = 129.27.218.30 } deimos.cgv.tugraz.at = { address = 129.27.218.31 } trinculo.cgv.tugraz.at = { address = 129.27.218.32 } } } # itp.tugraz.at imported from GCO Public CellServDB 01 Jan 2016 itp.tugraz.at = { description = "Institute of Theoretical and Computational Physics, TU Graz, Aus" use_dns = yes servers = { faepafs1.tu-graz.ac.at = { address = 129.27.161.7 } faepafs2.tu-graz.ac.at = { address = 129.27.161.15 } faepafs3.tu-graz.ac.at = { address = 129.27.161.114 } } } # ualberta.ca imported from GCO Public CellServDB 01 Jan 2016 ualberta.ca = { description = "University of Alberta" use_dns = yes servers = { file13.ucs.ualberta.ca = { address = 129.128.1.131 } mystery.ucs.ualberta.ca = { address = 129.128.98.17 } drake.ucs.ualberta.ca = { address = 129.128.125.40 } } } # cern.ch imported from DNS AFSDB cern.ch = { description = "European Laboratory for Particle Physics, Geneva" use_dns = yes servers = { afsdb1.cern.ch = { address = 137.138.128.148 } afsdb3.cern.ch = { address = 137.138.246.50 } afsdb2.cern.ch = { address = 137.138.246.51 } } } # psi.ch imported from DNS AFSDB psi.ch = { description = "Paul Scherrer Institut - Villigen, Switzerland" use_dns = yes servers = { afs00.psi.ch = { address = 129.129.190.140 } afs01.psi.ch = { address = 129.129.190.141 } afs02.psi.ch = { address = 129.129.190.142 } } } # freedaemon.com imported from GCO Public CellServDB 01 Jan 2016 freedaemon.com = { description = "Free Daemon Consulting, Oklahoma City, OK, USA" use_dns = yes servers = { afs0.freedaemon.com = { address = 66.210.104.254 } afs1.freedaemon.com = { address = 78.46.227.213 } afs2.freedaemon.com = { address = 208.79.89.92 } } } # nilcons.com imported from DNS SRV nilcons.com = { description = "nilcons.com" use_dns = yes servers = { files.nilcons.com = { address = 5.9.14.177 } } } # ics.muni.cz updated 8 Oct 2017 via udebug ics.muni.cz = { description = "Masaryk university, Czech Republic" use_dns = yes servers = { afs-plzen.meta.zcu.cz = { address = 147.228.240.30 } smaug2.ics.muni.cz = { address = 147.251.9.9 } tarkil-xen.cesnet.cz = { address = 195.113.214.4 } } } # zcu.cz imported from AFSDB zcu.cz = { description = "University of West Bohemia, Czech Republic" use_dns = yes servers = { sauron.zcu.cz = { address = 147.228.10.18 } oknos.zcu.cz = { address = 147.228.52.10 } nic.zcu.cz = { address = 147.228.52.17 } } } # desy.de imported from AFSDB desy.de = { description = "Deutsches Elektronen-Synchrotron" use_dns = yes servers = { afsdb2.desy.de = { address = 131.169.2.19 } afsdb3.desy.de = { address = 131.169.2.20 } solar00.desy.de = { address = 131.169.244.60 } afsdb5.desy.de = { address = 131.169.2.42 } } } # naf.desy.de imported from GCO Public CellServDB 01 Jan 2016 naf.desy.de = { description = "National Analysis Facility at DESY" use_dns = yes servers = { tcsh1-vm1.naf.desy.de = { address = 141.34.220.32 } tcsh2-vm1.naf.desy.de = { address = 141.34.230.33 } tcsh3-vm1.naf.desy.de = { address = 141.34.230.34 } } } # gppc.de update 8 Oct 2017 via udebug gppc.de = { description = "GPP Chemnitz mbH" use_dns = yes servers = { gpp1.gppc.de = { address = 213.187.92.33 } tyr.gppc.de = { address = 213.187.92.39 } rhea.gppc.de = { address = 213.187.92.36 } } } # cms.hu-berlin.de imported from GCO Public CellServDB 01 Jan 2016 cms.hu-berlin.de = { description = "Humboldt University Berlin" use_dns = yes servers = { commodus.cms.hu-berlin.de = { address = 141.20.1.65 } faustinus.cms.hu-berlin.de = { address = 141.20.1.66 } marcellus.cms.hu-berlin.de = { address = 141.20.1.67 } } } # ifh.de imported from AFSDB ifh.de = { description = "DESY Zeuthen" use_dns = yes servers = { romulus.ifh.de = { address = 141.34.22.10 } remus.ifh.de = { address = 141.34.22.11 } hekate.ifh.de = { address = 141.34.22.29 } } } # integra-ev.de update 8 Oct 2017 via udebug integra-ev.de = { description = "INTEGRA e.V." use_dns = yes servers = { afsdb2.integra-ev.de = { address = 134.155.48.14 } afsdb1.integra-ev.de = { address = 134.155.48.8 } } } # ipp-garching.mpg.de imported from DNS SRV ipp-garching.mpg.de = { description = "Institut fuer Plasmaphysik" use_dns = yes servers = { afs-db1.rzg.mpg.de = { address = 130.183.9.5 } afs-db3.bc.rzg.mpg.de = { address = 130.183.14.14 } afs-db2.aug.ipp-garching.mpg.de = { address = 130.183.100.10 } } } # mpe.mpg.de imported from GCO Public CellServDB 01 Jan 2016 mpe.mpg.de = { description = "MPE cell" use_dns = yes servers = { irafs1.mpe-garching.mpg.de = { address = 130.183.130.7 } irafs2.mpe-garching.mpg.de = { address = 130.183.134.20 } } } # nicsys.de imported from GCO Public CellServDB 01 Jan 2016 nicsys.de = { description = "NICsys GbR" use_dns = yes servers = { attila.nicsys.de = { address = 213.187.80.3 } } } # tu-berlin.de imported from DNS SRV tu-berlin.de = { description = "TU Berlin" use_dns = yes servers = { afsc-pr-1.tubit.tu-berlin.de = { address = 130.149.204.10 } afsc-pr-2.tubit.tu-berlin.de = { address = 130.149.204.11 } afsc-ba-1.tubit.tu-berlin.de = { address = 130.149.204.70 } } } # tu-chemnitz.de imported from DNS SRV tu-chemnitz.de = { description = "Technische Universitaet Chemnitz, Germany" use_dns = yes servers = { zuse.hrz.tu-chemnitz.de = { address = 134.109.2.1 } andrew.hrz.tu-chemnitz.de = { address = 134.109.2.2 } phoenix.hrz.tu-chemnitz.de = { address = 134.109.2.15 } } } # physik.uni-bonn.de imported from DNS SRV physik.uni-bonn.de = { description = "Institute of Physics, University of Bonn, Germany" use_dns = yes servers = { afsdb1.physik.uni-bonn.de = { address = 131.220.166.33 } afsdb2.physik.uni-bonn.de = { address = 131.220.166.34 } afsdb3.physik.uni-bonn.de = { address = 131.220.166.35 } } } # atlass01.physik.uni-bonn.de imported from GCO Public CellServDB 01 Jan 2016 atlass01.physik.uni-bonn.de = { description = "Bonn ATLAS" use_dns = yes servers = { atlass01.physik.uni-bonn.de = { address = 131.220.165.43 } } } # uni-freiburg.de imported from AFSDB uni-freiburg.de = { description = "Albert-Ludwigs-Universitat Freiburg" use_dns = yes servers = { sv8.ruf.uni-freiburg.de = { address = 132.230.6.237 } sv7.ruf.uni-freiburg.de = { address = 132.230.6.236 } } } # physik.uni-freiburg.de updated 8 Oct 2017 via udebug physik.uni-freiburg.de = { description = "Institute of Physics, University Freiburg, Germany" use_dns = yes servers = { sherlock.physik.uni-freiburg.de = { address = 132.230.77.12 } } } # math.uni-hamburg.de imported from AFSDB math.uni-hamburg.de = { description = "Department of Mathematics Uni Hamburg" use_dns = yes servers = { afs-core.math.uni-hamburg.de = { address = 134.100.223.3 } afs-core2.math.uni-hamburg.de = { address = 134.100.223.6 } afs-core3.math.uni-hamburg.de = { address = 134.100.223.9 } } } # physnet.uni-hamburg.de imported from AFSDB physnet.uni-hamburg.de = { description = "PHYSnet-Rechenzentrum university of hamburg" use_dns = yes servers = { afs-core.physnet.uni-hamburg.de = { address = 134.100.106.44 } afs-core2.physnet.uni-hamburg.de = { address = 134.100.106.45 } afs-core3.physnet.uni-hamburg.de = { address = 134.100.106.47 } } } # iqo.uni-hannover.de imported from AFSDB iqo.uni-hannover.de = { description = "Institut fuer Quantenoptik Hannover" use_dns = yes servers = { afs1.iqo.uni-hannover.de = { address = 130.75.103.221 } afs2.iqo.uni-hannover.de = { address = 130.75.103.223 } } } # mathi.uni-heidelberg.de imported from AFDDB mathi.uni-heidelberg.de = { description = "Uni Heidelberg (Mathematisches Institut)" use_dns = yes servers = { hactar.mathi.uni-heidelberg.de = { address = 129.206.26.241 } } } # urz.uni-heidelberg.de imported from GCO Public CellServDB 01 Jan 2016 urz.uni-heidelberg.de = { description = "Uni Heidelberg (Rechenzentrum)" use_dns = yes servers = { afsdb.urz.uni-heidelberg.de = { address = 129.206.119.10 } afsdb1.urz.uni-heidelberg.de = { address = 129.206.119.16 } afsdb2.urz.uni-heidelberg.de = { address = 129.206.119.17 } } } # uni-hohenheim.de imported from AFSDB uni-hohenheim.de = { description = "University of Hohenheim" use_dns = yes servers = { rs13.serv.uni-hohenheim.de = { address = 144.41.2.2 } rs14.serv.uni-hohenheim.de = { address = 144.41.2.3 } rs15.serv.uni-hohenheim.de = { address = 144.41.2.4 } } } # rz.uni-jena.de imported from SRV rz.uni-jena.de = { description = "Rechenzentrum University of Jena, Germany" use_dns = yes servers = { afs00.rz.uni-jena.de = { address = 141.35.2.180 } afs01.rz.uni-jena.de = { address = 141.35.2.181 } afs02.rz.uni-jena.de = { address = 141.35.2.182 } } } # rrz.uni-koeln.de imported from SRV rrz.uni-koeln.de = { description = "University of Cologne - Reg Comp Center" use_dns = yes servers = { afsdb1.rrz.uni-koeln.de = { address = 134.95.19.3 } afsdb2.rrz.uni-koeln.de = { address = 134.95.19.4 } lyra.rrz.uni-koeln.de = { address = 134.95.19.10 } afs.thp.uni-koeln.de = { address = 134.95.67.97 } ladon.rrz.uni-koeln.de = { address = 134.95.112.8 } } } # mathematik.uni-stuttgart.de updated 8 Oct 2017 via udebug mathematik.uni-stuttgart.de = { description = "University of Stuttgart, Math Dept." use_dns = yes servers = { fbm01.mathematik.uni-stuttgart.de = { address = 129.69.61.1 } fbm02.mathematik.uni-stuttgart.de = { address = 129.69.61.2 } fbm03.mathematik.uni-stuttgart.de = { address = 129.69.61.3 } } } # stud.mathematik.uni-stuttgart.de updated 8 Oct 2017 via udebug stud.mathematik.uni-stuttgart.de = { description = "CIP-Pool of Math. Dept, University of Stuttgart" use_dns = yes servers = { omni.mathematik.uni-stuttgart.de = { address = 129.69.61.28 } stud00.mathematik.uni-stuttgart.de = { address = 129.69.116.200 } stud01.mathematik.uni-stuttgart.de = { address = 129.69.116.201 } stud02.mathematik.uni-stuttgart.de = { address = 129.69.116.202 } stud03.mathematik.uni-stuttgart.de = { address = 129.69.116.203 } stud60.mathematik.uni-stuttgart.de = { address = 129.69.116.210 } } } # s-et.aau.dk imported from GCO Public CellServDB 01 Jan 2016 s-et.aau.dk = { description = "Aalborg Univ., The Student Society, Denmark" use_dns = yes servers = { afs.s-et.aau.dk = { address = 130.225.196.22 } } } # ies.auc.dk imported from SRV ies.auc.dk = { description = "Aalborg Univ., Inst. of Electronic Systems, Denmark" use_dns = yes servers = { afsdb1.kom.auc.dk = { address = 130.225.51.73 } afsdb2.kom.auc.dk = { address = 130.225.51.74 } afsdb3.kom.auc.dk = { address = 130.225.51.85 } } } # asu.edu imported from SRV asu.edu = { description = "Arizona State University" use_dns = yes servers = { authen2.asu.edu = { address = 129.219.10.69 } authen1.asu.edu = { address = 129.219.10.70 } authen3.asu.edu = { address = 129.219.10.72 } authen4.asu.edu = { address = 129.219.110.104 } } } # andrew.cmu.edu imported from SRV andrew.cmu.edu = { description = "Carnegie Mellon University - Computing Services Cell" use_dns = yes servers = { afsdb-02.andrew.cmu.edu = { address = 128.2.10.7 } afsdb-03.andrew.cmu.edu = { address = 128.2.10.11 } } } # club.cc.cmu.edu imported from AFSDB club.cc.cmu.edu = { description = "Carnegie Mellon University Computer Club" use_dns = yes servers = { barium.club.cc.cmu.edu = { address = 128.2.204.149 } sodium.club.cc.cmu.edu = { address = 128.237.157.11 } potassium.club.cc.cmu.edu = { address = 128.237.157.13 } } } # cs.cmu.edu imported from AFSDB cs.cmu.edu = { description = "Carnegie Mellon University - School of Comp. Sci." use_dns = yes servers = { date.srv.cs.cmu.edu = { address = 128.2.172.58 } fig.srv.cs.cmu.edu = { address = 128.2.172.60 } watermelon.srv.cs.cmu.edu = { address = 128.2.200.97 } } } # ece.cmu.edu imported from AFSDB ece.cmu.edu = { description = "Carnegie Mellon University - Elec. Comp. Eng. Dept." use_dns = yes servers = { porok.ece.cmu.edu = { address = 128.2.129.7 } vicio.ece.cmu.edu = { address = 128.2.129.8 } e-xing.ece.cmu.edu = { address = 128.2.129.9 } } } # qatar.cmu.edu imported from AFSDB qatar.cmu.edu = { description = "Carnegie Mellon University - Qatar" use_dns = yes servers = { afs1.qatar.cmu.edu = { address = 86.36.46.6 } afs2.qatar.cmu.edu = { address = 86.36.46.7 } afsdb-03.qatar.cmu.edu = { address = 86.36.46.9 } } } # cnf.cornell.edu imported from AFDSB cnf.cornell.edu = { description = "CNF" use_dns = yes kerberos_realm = CIT.CORNELL.EDU servers = { hole.cnf.cornell.edu = { address = 128.253.198.9 } smoke.cnf.cornell.edu = { address = 128.253.198.27 } mist.cnf.cornell.edu = { address = 128.253.198.231 } } } # math.cornell.edu imported from GCO Public CellServDB 01 Jan 2016 math.cornell.edu = { description = "Cornell Math Dept" use_dns = yes servers = { pooh.math.cornell.edu = { address = 128.84.234.12 } bernoulli.math.cornell.edu = { address = 128.84.234.16 } dyno.math.cornell.edu = { address = 128.84.234.162 } } } # msc.cornell.edu imported from AFSDB msc.cornell.edu = { description = "Cornell University Materials Science Center" use_dns = yes servers = { miranda.ccmr.cornell.edu = { address = 128.84.231.242 } co.ccmr.cornell.edu = { address = 128.84.241.35 } dax.ccmr.cornell.edu = { address = 128.84.249.78 } } } # dbic.dartmouth.edu imported from SRV dbic.dartmouth.edu = { description = "Dartmouth Brain Imaging Center" use_dns = yes servers = { dbicafs1.dartmouth.edu = { address = 129.170.30.143 } dbicafs2.dartmouth.edu = { address = 129.170.30.144 } dbicafs3.dartmouth.edu = { address = 129.170.30.145 } } } # northstar.dartmouth.edu imported SRV northstar.dartmouth.edu = { description = "Dartmouth College Research Computing" use_dns = yes servers = { halley.dartmouth.edu = { address = 129.170.16.22 } andromeda.dartmouth.edu = { address = 129.170.16.26 } cygnusx1.dartmouth.edu = { address = 129.170.16.43 } kuiper.dartmouth.edu = { address = 129.170.199.250 } } } # cs.hm.edu imported from GCO Public CellServDB 01 Jan 2016 cs.hm.edu = { description = "Department Computer Science Munich University Of Applied Science" use_dns = yes servers = { afs1.cs.hm.edu = { address = 129.187.208.31 } } } # iastate.edu imported from GCO Public CellServDB 01 Jan 2016 iastate.edu = { description = "Iowa State University" use_dns = yes servers = { afsdb-1.iastate.edu = { address = 129.186.1.243 } afsdb-2.iastate.edu = { address = 129.186.6.243 } afsdb-3.iastate.edu = { address = 129.186.142.243 } } } # athena.mit.edu imported from AFSDB athena.mit.edu = { description = "MIT/Athena cell" use_dns = yes kerberos_realm = ATHENA.MIT.EDU servers = { leda.mit.edu = { address = 18.7.45.11 } castor.mit.edu = { address = 18.9.48.11 } pollux.mit.edu = { address = 18.9.48.12 } } } # csail.mit.edu imported from AFSDB csail.mit.edu = { description = "MIT Computer Science & Artificial Intelligence Lab" use_dns = yes servers = { titanic.csail.mit.edu = { address = 128.30.2.13 } vasa.csail.mit.edu = { address = 128.30.2.31 } maine.csail.mit.edu = { address = 128.30.2.75 } } } # lns.mit.edu imported from AFSDB lns.mit.edu = { description = "MIT/LNS Cell" use_dns = yes servers = { afs2.lns.mit.edu. = { address = 198.125.160.134 } afsdbserv1.lns.mit.edu. = { address = 198.125.160.217 } afsdbserv2.lns.mit.edu. = { address = 198.125.160.218 } } } # net.mit.edu imported from AFSDB net.mit.edu = { description = "MIT/Network Group cell" use_dns = yes kerberos_realm = ATHENA.MIT.EDU servers = { willy.mit.edu = { address = 18.7.62.60 } moby.mit.edu = { address = 18.9.48.15 } springer.mit.edu = { address = 18.9.48.16 } } } # ops.mit.edu imported from AFSDB ops.mit.edu = { description = "MIT/Operations Group cell" use_dns = yes kerberos_realm = ATHENA.MIT.EDU servers = { despair.mit.edu = { address = 18.9.68.42 } heartbreak.mit.edu = { address = 18.9.68.41 } bitterness.mit.edu = { address = 18.9.68.31 } } } # sipb.mit.edu imported from AFSDB sipb.mit.edu = { description = "MIT/SIPB cell" use_dns = yes kerberos_realm = ATHENA.MIT.EDU servers = { reynelda.mit.edu = { address = 18.181.0.19 } rosebud2.mit.edu = { address = 18.181.0.22 } ronald-ann.mit.edu = { address = 18.181.0.23 } } } # zone.mit.edu imported from AFSDB zone.mit.edu = { description = "MIT/ZONE cell" use_dns = yes kerberos_realm = ATHENA.MIT.EDU servers = { casio.mit.edu = { address = 18.1.41.29 } timex.mit.edu = { address = 18.1.41.30 } seiko.mit.edu = { address = 18.1.41.31 } } } # msu.edu imported from GCO Public CellServDB 01 Jan 2016 msu.edu = { description = "Michigan State University Main Cell" use_dns = yes servers = { afsdb0.cl.msu.edu = { address = 35.9.7.10 } } } # crc.nd.edu imported from GCO Public CellServDB 01 Jan 2016 crc.nd.edu = { description = "University of Notre Dame - Center for Research Computing" use_dns = yes servers = { afsdb1.crc.nd.edu = { address = 129.74.85.34 } afsdb2.crc.nd.edu = { address = 129.74.85.35 } afsdb3.crc.nd.edu = { address = 129.74.85.36 } } } # pitt.edu update 8 Oct 2017 via udebug pitt.edu = { description = "University of Pittsburgh" use_dns = yes servers = { afs-db-01.cssd.pitt.edu = { address = 136.142.8.15 } afs-db-02.cssd.pitt.edu = { address = 136.142.8.20 } afs-db-03.cssd.pitt.edu = { address = 136.142.8.21 } } } # cs.pitt.edu imported from SRV cs.pitt.edu = { description = "University of Pittsburgh - Computer Science" use_dns = yes servers = { afs01.cs.pitt.edu = { address = 136.142.22.5 } afs02.cs.pitt.edu = { address = 136.142.22.6 } afs03.cs.pitt.edu = { address = 136.142.22.7 } } } # psc.edu imported from SRV psc.edu = { description = "PSC (Pittsburgh Supercomputing Center)" use_dns = yes servers = { shaggy.psc.edu = { address = 128.182.59.182 } velma.psc.edu = { address = 128.182.66.184 } daphne.psc.edu = { address = 128.182.66.185 } } } # rose-hulman.edu imported from GCO Public CellServDB 01 Jan 2016 rose-hulman.edu = { description = "Rose-Hulman Institute of Technology" use_dns = yes servers = { afs1.rose-hulman.edu = { address = 137.112.7.11 } afs2.rose-hulman.edu = { address = 137.112.7.12 } afs3.rose-hulman.edu = { address = 137.112.7.13 } } } # rpi.edu imported from AFSDB rpi.edu = { description = "Rensselaer Polytechnic Institute" use_dns = yes servers = { saul.server.rpi.edu = { address = 128.113.22.11 } joab.server.rpi.edu = { address = 128.113.22.12 } korah.server.rpi.edu = { address = 128.113.22.13 } achan.server.rpi.edu = { address = 128.113.22.14 } } } # cs.stanford.edu imported from AFSDB cs.stanford.edu = { description = "Stanford University Computer Science Department" use_dns = yes servers = { cs-afs-1.Stanford.EDU = { address = 171.64.64.10 } cs-afs-2.stanford.edu = { address = 171.64.64.66 } cs-afs-3.stanford.edu = { address = 171.64.64.69 } } } # ir.stanford.edu imported from SRV ir.stanford.edu = { description = "Stanford University" use_dns = yes servers = { afsdb1.stanford.edu = { address = 171.64.7.222 } afsdb2.stanford.edu = { address = 171.64.7.234 } afsdb3.stanford.edu = { address = 171.64.7.246 } } } # slac.stanford.edu imported from AFSDB slac.stanford.edu = { description = "Stanford Linear Accelerator Center" use_dns = yes servers = { afsdb1.slac.stanford.edu = { address = 134.79.18.25 } afsdb2.slac.stanford.edu = { address = 134.79.18.26 } afsdb3.slac.stanford.edu = { address = 134.79.18.27 } } } # cats.ucsc.edu imported from SRV cats.ucsc.edu = { description = "University of California, Santa Cruz" use_dns = yes servers = { afs-prod-front-1.ucsc.edu = { address = 128.114.123.8 } afs-prod-front-2.ucsc.edu = { address = 128.114.123.9 } afs-prod-front-3.ucsc.edu = { address = 128.114.123.10 } } } # ncsa.uiuc.edu imported from SRV ncsa.uiuc.edu = { description = "National Center for Supercomputing Applications at Illinois" use_dns = yes servers = { nile-vm.ncsa.uiuc.edu = { address = 141.142.192.66 } congo-vm.ncsa.uiuc.edu = { address = 141.142.192.143 } kaskaskia-vm.ncsa.uiuc.edu = { address = 141.142.192.144 } } } # umbc.edu imported from AFSDB umbc.edu = { description = "University of Maryland, Baltimore County" use_dns = yes servers = { db2.afs.umbc.edu = { address = 130.85.24.23 } db3.afs.umbc.edu = { address = 130.85.24.87 } db1.afs.umbc.edu = { address = 130.85.24.101 } } } # glue.umd.edu imported from AFSDB glue.umd.edu = { description = "University of Maryland - Project Glue" use_dns = yes servers = { olmec.umd.edu = { address = 128.8.70.11 } egypt.umd.edu = { address = 128.8.236.4 } babylon.umd.edu = { address = 128.8.236.230 } } } # wam.umd.edu imported from AFSDB wam.umd.edu = { description = "University of Maryland Network WAM Project" use_dns = yes servers = { csc-srv.wam.umd.edu = { address = 128.8.70.9 } avw-srv.wam.umd.edu = { address = 128.8.236.5 } ptx-srv.wam.umd.edu = { address = 128.8.236.231 } } } # umich.edu imported from AFSDB umich.edu = { description = "University of Michigan - Campus" use_dns = yes servers = { fear.ifs.umich.edu = { address = 141.211.1.32 } surprise.ifs.umich.edu = { address = 141.211.1.33 } ruthless.ifs.umich.edu = { address = 141.211.1.34 } } } # atlas.umich.edu imported from GCO Public CellServDB 01 Jan 2016 atlas.umich.edu = { description = "ATLAS group cell in physics at University of Michigan" use_dns = yes servers = { linat02.grid.umich.edu = { address = 141.211.43.102 } linat03.grid.umich.edu = { address = 141.211.43.103 } linat04.grid.umich.edu = { address = 141.211.43.104 } } } # citi.umich.edu imported from AFSDB citi.umich.edu = { description = "University of Michigan - Center for Information Technology Integ" use_dns = yes servers = { babylon.citi.umich.edu = { address = 141.212.112.5 } } } # cs.uwm.edu imported from GCO Public CellServDB 01 Jan 2016 cs.uwm.edu = { description = "University of Wisconsin--Milwaukee" use_dns = yes servers = { solomons.cs.uwm.edu = { address = 129.89.38.124 } filip.cs.uwm.edu = { address = 129.89.143.71 } } } # cs.wisc.edu imported from SRV cs.wisc.edu = { description = "Univ. of Wisconsin-Madison, Computer Sciences Dept." use_dns = yes servers = { vldba.cs.wisc.edu = { address = 128.105.9.18 } vldbb.cs.wisc.edu = { address = 128.105.9.19 } vldbc.cs.wisc.edu = { address = 128.105.9.20 } timon.cs.wisc.edu = { address = 128.105.132.14 } pumbaa.cs.wisc.edu = { address = 128.105.132.15 } zazu.cs.wisc.edu = { address = 128.105.132.16 } } } # hep.wisc.edu imported from AFSDB hep.wisc.edu = { description = "University of Wisconsin -- High Energy Physics" use_dns = yes servers = { anise.hep.wisc.edu = { address = 128.104.28.219 } rosemary.hep.wisc.edu = { address = 144.92.180.7 } fennel.hep.wisc.edu = { address = 144.92.180.30 } } } # physics.wisc.edu imported from AFSDB physics.wisc.edu = { description = "Univ. of Wisconsin-Madison, Physics Department" use_dns = yes servers = { kendra.physics.wisc.edu = { address = 128.104.160.13 } fray.physics.wisc.edu = { address = 128.104.160.14 } buffy.physics.wisc.edu = { address = 128.104.160.15 } } } # ciemat.es updated 8 Oct 2017 via udebug ciemat.es = { description = "Ciemat, Madrid, Spain" use_dns = yes servers = { afsdb1.ciemat.es = { address = 192.101.165.10 } afsdb2.ciemat.es = { address = 192.101.165.11 } } } # ific.uv.es imported from GCO Public CellServDB 01 Jan 2016 ific.uv.es = { description = "Instituto de Fisica Corpuscular, Valencia, Spain" use_dns = yes servers = { alpha.ific.uv.es = { address = 147.156.163.11 } } } # alteholz.eu imported from GCO Public CellServDB 01 Jan 2016 alteholz.eu = { description = "alteholz.eu" use_dns = yes servers = { krb1eu.afs.alteholz.net = { address = 78.47.192.125 } } } # in2p3.fr imported from GCO Public CellServDB 01 Jan 2016 in2p3.fr = { description = "IN2P3" use_dns = yes servers = { ccafsdb01.in2p3.fr = { address = 134.158.104.11 } ccafsdb02.in2p3.fr = { address = 134.158.104.12 } ccafsdb03.in2p3.fr = { address = 134.158.104.13 } } } # mcc.ac.gb imported from GCO Public CellServDB 01 Jan 2016 mcc.ac.gb = { description = "University of Manchester" use_dns = yes servers = { nevis.mc.man.ac.uk = { address = 130.88.203.41 } eryri.mc.man.ac.uk = { address = 130.88.203.144 } scafell.mc.man.ac.uk = { address = 130.88.203.145 } } } # rhic.bnl.gov imported from GCO Public CellServDB 01 Jan 2016 rhic.bnl.gov = { description = "Relativistic Heavy Ion Collider" use_dns = yes servers = { rafs03.rcf.bnl.gov = { address = 130.199.6.51 } rafs02.rcf.bnl.gov = { address = 130.199.6.52 } rafs01.rcf.bnl.gov = { address = 130.199.6.69 } } } # usatlas.bnl.gov imported from AFSDB usatlas.bnl.gov = { description = "US Atlas Tier 1 Facility at BNL" use_dns = yes servers = { aafs01.usatlas.bnl.gov = { address = 130.199.48.32 } aafs02.usatlas.bnl.gov = { address = 130.199.48.33 } aafs03.usatlas.bnl.gov = { address = 130.199.48.34 } } } # jpl.nasa.gov imported from AFSDB jpl.nasa.gov = { description = "Jet Propulsion Laboratory" use_dns = yes servers = { afsdb08.jpl.nasa.gov = { address = 137.78.160.21 } afsdb09.jpl.nasa.gov = { address = 137.78.160.22 } afsdb10.jpl.nasa.gov = { address = 137.78.160.23 } } } # bme.hu imported from AFSDB bme.hu = { description = "Budapest University of Technology and Economics" use_dns = yes servers = { zero.eik.bme.hu = { address = 152.66.115.2 } } } # kfki.hu imported from AFSDB kfki.hu = { description = "Wigner Research Centre for Physics - Budapest, Hungary" use_dns = yes servers = { afs0.kfki.hu = { address = 148.6.2.109 } } } # rnd.ru.is imported from AFSDB rnd.ru.is = { description = "Reykjavik University Research and Development Network" use_dns = yes servers = { lithium.rnd.ru.is. = { address = 130.208.242.66 } beryllium.rnd.ru.is. = { address = 130.208.242.67 } boron.rnd.ru.is. = { address = 130.208.242.68 } } } # enea.it updated 8 Oct 2017 via udebug enea.it = { description = "ENEA New Tech. Energy & Environment Agency, Italy" use_dns = yes servers = { aixfs.frascati.enea.it = { address = 192.107.54.5 } rs2ced.frascati.enea.it = { address = 192.107.54.11 } 43p.frascati.enea.it = { address = 192.107.54.12 } afsdb.portici.enea.it = { address = 192.107.70.49 } afsdb1.portici.enea.it = { address = 192.107.70.51 } serverinfo02.bologna.enea.it = { address = 192.107.61.235 } glauco.casaccia.enea.it = { address = 192.107.71.6 } riscdb.trisaia.enea.it = { address = 192.107.96.233 } } } # fusione.it imported from GCO Public CellServDB 01 Jan 2016 fusione.it = { description = "Assoz. FUSIONE/Euratom, ENEA, Frascati-Italy" use_dns = yes servers = { fusafs1.frascati.enea.it = { address = 192.107.90.2 } fusafs2.frascati.enea.it = { address = 192.107.90.3 } fusafs3.frascati.enea.it = { address = 192.107.90.4 } } } # ictp.it updated 8 Oct 2017 via udebug; AFSDB records are wrong ictp.it = { description = "The Abdus Salam International Centre for Theoretical Physics (IC" use_dns = no servers = { afsdb1.ictp.it = { address = 140.105.34.7 } afsdb2.ictp.it = { address = 140.105.34.8 } afsdb3.ictp.it = { address = 140.105.34.205 } } } # infn.it imported from GCO Public CellServDB 01 Jan 2016 infn.it = { description = "Istituto Nazionale di Fisica Nucleare (INFN), Italia" use_dns = yes servers = { afscnaf.infn.it = { address = 131.154.1.7 } afsrm1.roma1.infn.it = { address = 141.108.26.75 } afsna.na.infn.it = { address = 192.84.134.75 } } } # ba.infn.it imported from GCO Public CellServDB 01 Jan 2016 ba.infn.it = { description = "INFN, Sezione di Bari" use_dns = yes servers = { baafsserver.ba.infn.it = { address = 193.206.185.235 } debsrv.ba.infn.it = { address = 193.206.185.236 } } } # kloe.infn.it imported from GCO Public CellServDB 01 Jan 2016 kloe.infn.it = { description = "INFN, KLOE experiment at Laboratori di Frascati" use_dns = yes servers = { kloeafs1.lnf.infn.it = { address = 192.135.25.111 } kloeafs2.lnf.infn.it = { address = 192.135.25.112 } } } # le.infn.it imported from GCO Public CellServDB 01 Jan 2016 le.infn.it = { description = "INFN, Sezione di Lecce" use_dns = yes servers = { afs01.le.infn.it = { address = 192.84.152.40 } afs02.le.infn.it = { address = 192.84.152.148 } } } # lnf.infn.it imported from AFSDB lnf.infn.it = { description = "INFN, Laboratori Nazionali di Frascati" use_dns = yes servers = { afs1.lnf.infn.it = { address = 193.206.84.121 } afs2.lnf.infn.it = { address = 193.206.84.122 } afs3.lnf.infn.it = { address = 193.206.84.123 } } } # lngs.infn.it imported from GCO Public CellServDB 01 Jan 2016 lngs.infn.it = { description = "INFN, Laboratori Nazionali del Gran Sasso" use_dns = yes servers = { afs1.lngs.infn.it = { address = 192.84.135.21 } afs2.lngs.infn.it = { address = 192.84.135.133 } } } # pi.infn.it imported from AFSDB pi.infn.it = { description = "INFN, Sezione di Pisa" use_dns = yes servers = { aix1.pi.infn.it = { address = 192.84.133.50 } afs1.pi.infn.it = { address = 212.189.152.6 } afs2.pi.infn.it = { address = 212.189.152.7 } } } # roma3.infn.it imported from GCO Public CellServDB 01 Jan 2016 roma3.infn.it = { description = "Istituto Nazionale di Fisica Nucleare (INFN), Italia" use_dns = yes servers = { afsrm3.roma3.infn.it = { address = 193.205.159.17 } } } # psm.it imported from GCO Public CellServDB 01 Jan 2016 psm.it = { description = "Progetto San Marco, Universita' di Roma-1" use_dns = yes servers = { atlante.psm.uniroma1.it = { address = 151.100.1.65 } } } # math.unifi.it imported from GCO Public CellServDB 01 Jan 2016 math.unifi.it = { description = "math.unifi.it" use_dns = yes servers = { xeno.math.unifi.it = { address = 150.217.34.182 } } } # dia.uniroma3.it imported from AFSDB dia.uniroma3.it = { description = "University Roma Tre - DIA" use_dns = yes servers = { srv.dia.uniroma3.it = { address = 193.204.161.67 } aux.dia.uniroma3.it = { address = 193.204.161.79 } afs.dia.uniroma3.it = { address = 193.204.161.118 } } } # vn.uniroma3.it imported from GCO Public CellServDB 01 Jan 2016 vn.uniroma3.it = { description = "University Roma Tre, area Vasca Navale" use_dns = yes servers = { alfa2.dia.uniroma3.it = { address = 193.205.219.59 } beta2.dia.uniroma3.it = { address = 193.205.219.60 } gamma2.dia.uniroma3.it = { address = 193.205.219.61 } } } # ictp.trieste.it imported from AFSDB ictp.trieste.it = { description = "Abdus Salam International Centre for Theoretical Physics" use_dns = yes servers = { fs2.ictp.trieste.it = { address = 140.105.16.9 } } } # cmf.nrl.navy.mil imported from AFSDB cmf.nrl.navy.mil = { description = "Naval Research Laboratory - Center for Computational Science" use_dns = yes servers = { picard.cmf.nrl.navy.mil = { address = 134.207.12.68 } riker.cmf.nrl.navy.mil = { address = 134.207.12.69 } kirk.cmf.nrl.navy.mil = { address = 134.207.12.70 } } } # lcp.nrl.navy.mil imported from GCO Public CellServDB 01 Jan 2016 lcp.nrl.navy.mil = { description = "Naval Research Lab - Lab for Computational Physics" use_dns = yes servers = { afs1.lcp.nrl.navy.mil = { address = 132.250.114.2 } afs2.lcp.nrl.navy.mil = { address = 132.250.114.4 } afs3.lcp.nrl.navy.mil = { address = 132.250.114.6 } } } # crossproduct.net imported from SRV crossproduct.net = { description = "crossproduct.net" use_dns = yes servers = { prism.crossproduct.net = { address = 136.248.125.67 } } } # epitech.net imported from GCO Public CellServDB 01 Jan 2016 epitech.net = { description = "EPITECH, France" use_dns = yes servers = { afs-db-1.epitech.net = { address = 163.5.255.41 } afs-db-2.epitech.net = { address = 163.5.255.42 } } } # es.net imported from GCO Public CellServDB 01 Jan 2016 es.net = { description = "Energy Sciences Net" use_dns = yes servers = { fs1.es.net = { address = 198.128.3.21 } fs2.es.net = { address = 198.128.3.22 } fs3.es.net = { address = 198.128.3.23 } } } # sinenomine.net imported from AFSDB sinenomine.net = { description = "Sine Nomine Associates" use_dns = yes servers = { afsdb5.sinenomine.net = { address = 207.89.43.110 } afsdb3.sinenomine.net = { address = 207.89.43.108 } afsdb4.sinenomine.net = { address = 207.89.43.109 } } } # slackers.net imported from AFSDB slackers.net = { description = "The Slackers' Network" use_dns = yes servers = { alexandria.slackers.net = { address = 199.4.150.159 } } } # tproa.net imported from SRV tproa.net = { description = "The People's Republic of Ames" use_dns = yes servers = { service-3.tproa.net = { address = 204.11.35.83 } service-4.tproa.net = { address = 204.11.35.84 } service-5.tproa.net = { address = 204.11.35.85 } } } # nikhef.nl imported from GCO Public CellServDB 01 Jan 2016 nikhef.nl = { description = "The Dutch National Institute for High Energy Physics" use_dns = yes servers = { afs1.nikhef.nl = { address = 192.16.185.26 } afs2.nikhef.nl = { address = 192.16.185.27 } } } # adrake.org imported from SRV adrake.org = { description = "adrake.org" use_dns = yes servers = { afs-vldb.adrake.org = { address = 128.2.98.241 } } } # coed.org imported from SRV coed.org = { description = "Adam Pennington's Cell" use_dns = yes servers = { vice1.coed.org = { address = 108.48.124.91 } } } # dementia.org imported from GCO Public CellServDB 01 Jan 2016 dementia.org = { description = "Dementia Unlimited (old)" use_dns = no kerberos_realm = DEMENTIX.ORG servers = { dedlock.dementix.org = { address = 128.2.13.209 } vorkana.dementix.org = { address = 128.2.234.204 } } } # dementix.org imported from GCO Public CellServDB 01 Jan 2016 dementix.org = { description = "Dementia Unlimited" use_dns = yes servers = { dedlock.dementix.org = { address = 128.2.13.209 } vorkana.dementix.org = { address = 128.2.234.204 } } } # hpc2n.umu.se imported from SRV hpc2n.umu.se = { description = "High Performance Computing Center North - Ume University" use_dns = yes servers = { zenith.hpc2n.umu.se = { address = 130.239.45.214 } blackjack.hpc2n.umu.se = { address = 130.239.45.220 } mamba.hpc2n.umu.se = { address = 130.239.45.228 } } } # ltu.se imported from SRV ltu.se = { description = "Lule tekniska universitet" use_dns = yes servers = { afsdb2.its.ltu.se = { address = 130.240.42.223 } afsdb3.its.ltu.se = { address = 130.240.42.222 } afsdb1.its.ltu.se = { address = 130.240.42.224 } } } # pfriedma.org imported from DNS pfriedma.org = { description = "pfriedma.org" use_dns = yes servers = { vice.pfriedma.org = { address = 50.198.62.99 } } } # kth.se imported from AFSDB kth.se = { description = "Royal Institute of Technology, Stockholm, Sweden" use_dns = yes servers = { sonen.e.kth.se = { address = 130.237.32.145 } anden.e.kth.se = { address = 130.237.48.7 } fadern.e.kth.se = { address = 130.237.48.244 } } } # ict.kth.se imported from SRV ict.kth.se = { description = "Royal Institute of Technology, Information and Communication tec" use_dns = yes servers = { afsdb1.ict.kth.se = { address = 130.237.216.11 } afsdb2.ict.kth.se = { address = 130.237.216.12 } afsdb3.ict.kth.se = { address = 130.237.216.13 } } } # it.kth.se imported from SRV it.kth.se = { description = "Royal Institute of Technology, Teleinformatics, Kista" use_dns = yes servers = { afsdb1.it.kth.se = { address = 130.237.216.14 } afsdb2.it.kth.se = { address = 130.237.216.15 } afsdb3.it.kth.se = { address = 130.237.216.16 } } } # mech.kth.se imported from AFSDB mech.kth.se = { description = "Royal Institute of Technology, MECH" use_dns = yes servers = { matterhorn.mech.kth.se = { address = 130.237.233.142 } castor.mech.kth.se = { address = 130.237.233.143 } pollux.mech.kth.se = { address = 130.237.233.144 } } } # nada.kth.se imported from AFSDB nada.kth.se = { description = "Royal Institute of Technology, NADA" use_dns = yes servers = { afsdb-1.csc.kth.se = { address = 130.237.222.20 } afsdb-2.csc.kth.se = { address = 130.237.223.12 } afsdb-3.csc.kth.se = { address = 130.237.224.78 } afsdb-4.csc.kth.se = { address = 130.237.227.23 } afsdb-5.csc.kth.se = { address = 130.237.228.28 } } } # pdc.kth.se imported from AFSDB pdc.kth.se = { description = "Royal Institute of Technology, PDC" use_dns = yes servers = { crab.pdc.kth.se = { address = 130.237.232.29 } anna.pdc.kth.se = { address = 130.237.232.112 } hokkigai.pdc.kth.se = { address = 130.237.232.114 } } } # stacken.kth.se imported from AFSDB stacken.kth.se = { description = "Stacken Computer Club" use_dns = yes servers = { milko.stacken.kth.se = { address = 130.237.234.3 } hot.stacken.kth.se = { address = 130.237.234.43 } fishburger.stacken.kth.se = { address = 130.237.234.101 } } } # su.se imported from AFSDB su.se = { description = "Stockholm University" use_dns = yes servers = { afsdb1.su.se = { address = 130.237.162.81 } afsdb2.su.se = { address = 130.237.162.82 } afsdb3.su.se = { address = 130.237.162.230 } } } # f9.ijs.si updated 8 Oct 2017 via udebug f9.ijs.si = { description = "F9, Jozef Stefan Institue" use_dns = yes servers = { brenta.ijs.si = { address = 194.249.156.1 } f9pc00.ijs.si = { address = 194.249.156.100 } } } # p-ng.si imported from SRV p-ng.si = { description = "University of Nova Gorica" use_dns = yes servers = { solkan.p-ng.si = { address = 193.2.120.2 } sabotin.p-ng.si = { address = 193.2.120.9 } } } # ihep.su imported from AFSDB ihep.su = { description = "Institute for High-Energy Physics" use_dns = yes servers = { fs0001.ihep.su = { address = 194.190.165.201 } fs0002.ihep.su = { address = 194.190.165.202 } } } # inf.ed.ac.uk imported from AFSDB inf.ed.ac.uk = { description = "School of Informatics, University of Edinburgh" use_dns = yes servers = { afsdb0.inf.ed.ac.uk = { address = 129.215.64.16 } afsdb1.inf.ed.ac.uk = { address = 129.215.64.17 } afsdb2.inf.ed.ac.uk = { address = 129.215.64.18 } } } # phas.gla.ac.uk imported from GCO Public CellServDB 01 Jan 2016 phas.gla.ac.uk = { description = "Univeristy of Glasgow Physics And Astronomy" use_dns = yes servers = { afsdb1.phas.gla.ac.uk = { address = 194.36.1.19 } afsdb3.phas.gla.ac.uk = { address = 194.36.1.27 } afsdb2.phas.gla.ac.uk = { address = 194.36.1.33 } } } # hep.man.ac.uk imported from GCO Public CellServDB 01 Jan 2016 hep.man.ac.uk = { description = "Manchester HEP" use_dns = yes servers = { afs1.hep.man.ac.uk = { address = 194.36.2.3 } afs2.hep.man.ac.uk = { address = 194.36.2.4 } afs3.hep.man.ac.uk = { address = 194.36.2.5 } } } # tlabs.ac.za imported from SRV tlabs.ac.za = { description = "iThemba LABS Cell" use_dns = yes servers = { afs01.tlabs.ac.za = { address = 196.24.232.1 } afs02.tlabs.ac.za = { address = 196.24.232.2 } afs03.tlabs.ac.za = { address = 196.24.232.3 } } } # your-file-system.com imported from SRV your-file-system.com = { description = "AuriStor, Inc. formerly Your File System, Inc." use_dns = yes servers = { bethlehem.auristor.com = { address = [2001:470:30:84:20c:29ff:fe2a:fcc] address = 204.29.154.37 } faultline.auristor.com = { address = [2001:470:30:84:20c:29ff:fe19:de6f] address = 204.29.154.47 } atwater-block.auristor.com = { address = [2001:470:1f07:f77:20c:29ff:fe3b:c525] address = 208.125.0.252 } } } # 1ts.org imported from AFSDB 1ts.org = { description = "1TS.ORG cell" use_dns = yes servers = { vice0.1ts.org = { address = 136.248.125.132 } } } # mrow.org imported from AFSDB mrow.org = { description = "MROW.ORG cell" use_dns = yes servers = { openafs1.tinc.ad.mrow.org = { address = 44.44.69.195 } hyperion.tinc.ad.mrow.org = { address = 44.44.82.1 } washington.tinc.ad.mrow.org = { address = 44.44.69.97 } } } # thok.org imported from AFSDB thok.org = { description = "THOK.ORG cell" use_dns = yes servers = { curl-up-paw-over-nose.thok.org = { address = 172.110.60.210 } } } # openstack.org DNS SRV records available openstack.org = { description = "OpenStack Project" use_dns = yes servers = { afsdb02.openstack.org = { address = 23.253.200.228 } afsdb01.openstack.org = { address = 104.130.136.20 } } } conf/client.conf000066400000000000000000000003451367270324000141360ustar00rootroot00000000000000# # This file stitches together the local kAFS configuration and cell database, # which can be placed in the client.d/ directory, with the generic database. # includedir /etc/kafs/client.d include /usr/share/kafs/cellservdb.conf conf/kafs-config.service000066400000000000000000000002721367270324000155610ustar00rootroot00000000000000[Unit] Description=Preload AFS Cell Database After=local-fs.target DefaultDependencies=no [Service] Type=oneshot ExecStartPre=/sbin/modprobe -q kafs ExecStart=/usr/libexec/kafs-preload conf/kafs_dns.conf000066400000000000000000000001111367270324000144370ustar00rootroot00000000000000create dns_resolver afsdb:* * /usr/libexec/kafs-dns %k man/000077500000000000000000000000001367270324000116355ustar00rootroot00000000000000man/AF_RXRPC.7000066400000000000000000000000141367270324000131640ustar00rootroot00000000000000.so rxrpc.7 man/aklog-kafs.1000066400000000000000000000025241367270324000137410ustar00rootroot00000000000000.\" .\" Copyright (C) 2018 Red Hat, Inc. All Rights Reserved. .\" Written by David Howells (dhowells@redhat.com) .\" .\" This program is free software; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License .\" as published by the Free Software Foundation; either version .\" 2 of the License, or (at your option) any later version. .\" .TH AKLOG-KAFS 1 "16 Apr 2019" Linux "AFS Kerberos authentication" .SH NAME aklog-kafs \- AFS Kerberos authentication tool .SH SYNOPSIS \fBaklog-kafs\fR [ []] .P .B *** NOTE THE ABOVE IS PROVISIONAL AND IS LIKELY TO CHANGE *** .R .SH DESCRIPTION This program is used to get an authentication ticket from Kerberos that can be used by the in-kernel AFS filesystem (kAFS) to perform authenticated and encrypted accesses to the server. Without this only unencrypted anonymous accesses can be made. .P Before calling this, the \fBkinit\fR program or similar should be invoked to authenticate with the appropriate Kerberos server. .SH ARGUMENTS .IP This is the name of the cell with which the ticket is intended to be used. If not given, the name of the default cell will be read from \fB/proc/net/afs/rootcell\fR and used instead. .IP This is the name of the Kerberos realm from which the ticket will be obtained. .SH ERRORS .SH SEE ALSO .ad l .nh .BR kinit (1) man/aklog.1000066400000000000000000000000211367270324000130050ustar00rootroot00000000000000.so aklog-kafs.1 man/kafs-check-config.8000066400000000000000000000047051367270324000151760ustar00rootroot00000000000000.\" .\" Copyright (C) 2019 Red Hat, Inc. All Rights Reserved. .\" Written by David Howells (dhowells@redhat.com) .\" .\" This program is free software; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License .\" as published by the Free Software Foundation; either version .\" 2 of the License, or (at your option) any later version. .\" .TH KAFS-CHECK-CONFIG 1 "16 Apr 2019" Linux "AFS Config Checker" .SH NAME kafs-check-config \- AFS configuration check tool .SH SYNOPSIS \fBkafs-check-config\fR [OPTION]... []* .P Where options are: .P .RS [-46PDvv] [-c ]* [-N ] .RE .SH DESCRIPTION This program is used to check the configuration for the in-kernel AFS filesystem (kAFS). This configuration is used when systemd mounts the filesystem to load up the cell database and create cell automounts in the /afs directory. .P The configuration is also used by the kernel name resolver upcall to provide static configuration for some cells and to specify overrides and limits on DNS lookups. .P If a list of \fB\fR arguments is given, the listed cells will be dumped, including the sources of the Volume Location records and address records. .P The available options are: .SH ARGUMENTS .IP -4 Only show IPv4 addresses in the dump. .IP -6 Only show IPv6 addresses in the dump. .IP -P Dump the parse tree of the configuration file(s). .IP -D Dump the cell database extracted from the configuration. .IP -v Increase the verbosity of the output. This may be specified multiple times. .IP "-c " Specify a configuration file to read instead of the system default. This may be specified multiple times and the configuration files are read and applied in order. .IP "-N " Apply a restriction to the lookup performed for the listed cells (if any are). Restrictions include: .RS .IP "-N vl-srv" Don't use SRV records to find Volume Location servers. .IP "-N vl-afsdb" Don't use AFSDB records to find Volume Location servers. .IP "-N vl-all" Don't use SRV or AFSDB records to find Volume Location servers. .IP "-N vl-host" Don't look cell name up as hostname to find a Volume Location server. .IP "-N vl-dns" Don't do any lookups to find Volume Location servers. Use only the static configuration. .RE .SH EXIT STATUS .IP 0 If check okay and any dumping succeeded. .IP 1 If an error occurs during processing. .IP 2 If a command line error occurs. .SH SEE ALSO .ad l .nh .BR kafs (7), .BR kafs\-client.conf (5) man/kafs-client.conf.5000066400000000000000000000165671367270324000150660ustar00rootroot00000000000000.\" -*- nroff -*- .\" Copyright (C) 2019 Red Hat, Inc. All Rights Reserved. .\" Written by David Howells (dhowells@redhat.com) .\" .\" This program is free software; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License .\" as published by the Free Software Foundation; either version .\" 2 of the License, or (at your option) any later version. .\" .TH KAFS-CLIENT.CONF 5 "17 Apr 2019" Linux "kAFS Configuration" .SH NAME /etc/kafs/client.conf .br /etc/kafs/client.d/ \- kAFS filesystem configuration .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .SH DESCRIPTION Configuration information for the in-kernel kAFS filesystem can be provided in the /etc/kafs/ directory. This may include the following: .IP - A list of cells to be preconfigured .IP - Fallback addresses for each cell. .IP - The name of the default cell (the .B @cell substitution). .IP - A list of strings for the .BR @sys " substitution." .PP When the .B afs.mount service is started by .BR systemd (1), a configuration service .RB ( kafs-config.service ) runs first and loads the configuration into the kernel from the .B client.conf file. This contains directives to include other things, such as the contents of the .B client.d/ directory and the generic public cell database. .PP Once the afs.mount service is started (or if an AFS volume is manually mounted), if a mountpoint is triggered, the kernel will upcall by means of .BR request-key (8) to look up addresses for the Volume Location servers for the named cell. This will also parse the configuration. .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .SH CONFIGURATION FILE FORMAT The file format is based on the MIT Kerberos configuration file format. There are a couple of general directives: .TP .BR include " " /path/to/file This includes the contents of the named file in the parse at this point. .TP .BR includedir " " /path/to/dir/ This includes the files in the named directory in the parse at this point. Files that have names beginning with "." or ending with "~" are ignored. .PP Leading and trailing whitespace on a line is ignored. Any line otherwise beginning with a "#" character is considered a comment and ignored. .PP Any line that contains a label bounded by square brackets, e.g. "[cells]", by itself on that line denotes a switch to the section specified by that label. .PP Configuration data is specified within a named section as a series of .BR key = value pairs, where a value may be one of nothing, an unquoted string, a quoted string or a braced lists containing further key=value pairs. Whitespace either side of the "=" symbol is ignored. .PP For example: .PP .RS .nf [cells] rivendell.example.com = { description = "Last Homely Cell" use_dns = yes servers = { elrond.rivendell.example.com = { address = 192.0.2.23 } } } .fi .RE .PP If two or more consecutive clauses specify values for the same key sequence (so cells:rivendell.example.com:use_dns, for example), then they are merged together to form a single list. If a single value is expected for a configuration item, the last element in the list is taken. .PP To prevent overriding by subsequent conflicting configuration, an asterisk can be placed after the closing brace in a braced list to indicate that that list is closed, for example: .PP .RS .nf [cells] rivendell.example.com = { description = "Foo" use_dns = no }* .fi .RE .PP Strings that are intepreted as boolean values are classed as false if they match one of .BR 0 ", " f ", " false ", " n ", " no " or " off , and classed as true if they match one off .BR 1 ", " t ", " true ", " y ", " yes " or " on . The match is case-independent. .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .SH GENERAL SETTINGS The first section contains general system-level settings shared between all utilities and the kernel. This is denoted by the section label "\fB[defaults]\fP". .PP The system settings that may be changed are configured in this section with the following key-value pairs: .TP .B thiscell = This sets the name of the local cell. This will be used to configure the .B @cell path substitution and will also supply the default cellname for .BR aklog-kafs (1). .TP .B sysname = []* This specifies a (potentially empty) list of strings which the kernel should attempt to substitute in turn for "\fB@sys\fR" at the end of a filename until a match is found. .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .SH CELL DEFINITIONS The second section contains a list of preconfigured cells, to be used in preloading the cell list in /afs and also to provide fallback or override address data for locating Volume Location servers. This is denoted by the section label "\fB[cells]\fP". .PP Within the cell list, each cell is declared with a key=value pair, where the key is the name of the cell and the value is a braced list indicating the details, e.g.: .PP .RS .nf .B [cells] rivendell.example.com = { ... } .fi .RE .PP A cell definition may contain any number of key=value pairs. The keys that are taken note of are: .TP .BR description " = " This is a text description for the cell. .TP .BR show_cell " = " Whether a cell should be shown in /afs. .TP .BR use_dns " = " Whether address look ups for a cell may use the DNS. .TP .BR kerberos_realm " = " The name of the Kerberos realm to use for a cell by default. .TP .BR servers " = " { " ... " } A list of servers for the cell, where each element in the list is a key=value pair, where the key is the name of a server and the value is a braced section of the details for that server. .PP The elements in the list of server details attached to each server can comprise the following keys: .TP .B type = vlserver The server is an AFS Volume Location server. This is the default. .TP .B type = ptserver The server is an AFS Protection server. .TP .BR address " = " [/]
[:] Specify a single address for a server. The .B address is required and can be a single IPv4 or a single IPv6 address, and may be brackets with square brackets (to avoid confusion with the port number, if specified). The .B protocol is optional; currently only .B udp is supported. The .B port is also optional and may be specified to change the UDP port from the default for the server type. .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .SH EXAMPLE .PP .nf .B [defaults] thiscell = rivendell.example.com sysname = fedora28_x86 amd64_linux .B [cells] corp.example.com = { description = "Valinor Corporation cell" use_dns = yes servers = { manwe.corp.example.com = { address = 2001:db8:123::13 address = 203.0.113.19 } ulmo.corp.example.com = { address = [2001:db8:123::750c:1234]:6666 address = 203.0.113.3:6666 } aule.corp.example.com = { address = udp/[2001:db8:123::abcd:9090] address = udp/203.0.113.189 } namo.corp.example.com = { type = ptserver address = 2001:db8:123::8888 address = 203.0.113.88 } } } rivendell.example.com = { description = "Last Homely Cell" servers = { elrond.rivendell.example.com = { address = 192.0.2.23 } arwen.rivendell.example.com = { address = 192.0.2.75 } } } .fi .PP .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .SH SEE ALSO .ad l .nh .BR kafs (7), .BR kafs\-check\-config (8), .BR systemd (1) man/kafs-dns.8000066400000000000000000000073201367270324000134360ustar00rootroot00000000000000.\" .\" Copyright (C) 2020 Red Hat, Inc. All Rights Reserved. .\" Written by David Howells (dhowells@redhat.com) .\" .\" This program is free software; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License .\" as published by the Free Software Foundation; either version .\" 2 of the License, or (at your option) any later version. .\" .TH KAFS-DNS 8 "9 Jun 2020" Linux "AFS kernel address resolver" .SH NAME kafs-dns \- AFS filesystem address resolution helper .SH SYNOPSIS \fB/usr/libexec/kafs-dns\fR [OPTION]... .br \fB/usr/libexec/kafs-dns\fR -D [OPTION]... .br \fB/usr/libexec/kafs-dns\fR -V .PP Where options are: .PP .RS [-v] [-c ]* [-N ] [-o ] .RE .SH DESCRIPTION This program is invoked by the .BR request-key (8) kernel upcall handling program to handle an address resolution request on behalf of the in-kernel AFS filesystem driver to find the Volume Location servers for a cell. It is capable of using static configuration, NSS and DNS SRV and AFSDB record lookups. .PP Note that this program is not meant to be called directly, though it does have a debugging mode that can be used. .PP The first form of the command, without the \fB-D\fR flag cannot be called directly as it requires an under-construction kernel key as its parameter. .PP The debugging form, in which \fB-D\fR is given, doesn't require a key, but must be given a proposed key description and a callout information string. Information about what it is doing is dumped to the output. The result blob may be binary and so is not dumped to stdout, but can be dumped to a file with \fB-o\ \fR. .PP The available options are: .SH ARGUMENTS .IP -D Execute in debug mode. .IP -v Increase the verbosity of the output. This may be specified multiple times. .IP "-c " Specify a configuration file to read instead of the system default. This may be specified multiple times and the configuration files are read and applied in order. .IP "-N " Apply a restriction to the lookup performed for the listed cells (if any are). Restrictions include: .RS .IP "-N vl-srv" Don't use SRV records to find Volume Location servers. .IP "-N vl-afsdb" Don't use AFSDB records to find Volume Location servers. .IP "-N vl-all" Don't use SRV or AFSDB records to find Volume Location servers. .IP "-N vl-host" Don't look cell name up as hostname to find a Volume Location server. .IP "-N vl-dns" Don't do any lookups to find Volume Location servers. Use only the static configuration. .RE .IP "-o " Specify a file in which to dump the proposed payload with which to instantiate a resolver key. .IP "-V" Display version information and exit. .PP The key description, \fB\fR, should be the name of a cell prefixed by "afsdb:". .PP The callout information string, \fB\fR, is a comma separated list of none or more of the following items: .IP "ipv4" Get IPv4 addresses only. .IP "ipv6" Get IPv6 addresses only. .IP "srv=" Allow the extra information that can be gleaned from SRV records to be rendered as output format \fB\fR, where is a number. .SH EXIT STATUS .IP 0 On success. .IP 1 If an error occurs during processing. .IP 2 If a command line error occurs. .IP 3 If bad configuration is detected. .SH EXAMPLE .PP The program can be called with something like: .PP .RS .nf /usr/libexec/kafs-dns -D afsdb:example.com srv=1 .fi .RE .PP The program can also be invoked indirectly with something like: .PP .RS .nf keyctl request2 dns_resolver afsdb:example.com srv=1 @s .fi .RE .PP which will return the serial number of a key that can then be displayed. .SH SEE ALSO .ad l .nh .BR kafs (7), .BR kafs\-client.conf (5), .BR keyctl (1), .BR request-key (8) man/kafs-preload.8000066400000000000000000000024671367270324000143070ustar00rootroot00000000000000.\" .\" Copyright (C) 2020 Red Hat, Inc. All Rights Reserved. .\" Written by David Howells (dhowells@redhat.com) .\" .\" This program is free software; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License .\" as published by the Free Software Foundation; either version .\" 2 of the License, or (at your option) any later version. .\" .TH KAFS-PRELOAD 8 "9 Jun 2020" Linux "AFS configuration preloader" .SH NAME kafs-preload \- AFS filesystem configuration preloader .SH SYNOPSIS \fB/usr/libexec/kafs-preload [-Dv]\fR .SH DESCRIPTION This program loads static configuration into the AFS filesystem, such as preloading some cells and setting the workstation cell (@cell) and the system identifier list (@sys). .PP This is not intended to be called directly, but rather is intended to be called from a systemd service unit file. .PP The available options are: .IP -D Execute in debug mode. Instead of writing to various .BR proc (5) files, it notes what it would do to stdout. .IP -v Increase the verbosity of the output. This may be specified multiple times. .SH EXIT STATUS .IP 0 On success. .IP 1 If an error occurs during processing. .IP 2 If a command line error occurs. .IP 3 If bad configuration is detected. .SH SEE ALSO .ad l .nh .BR kafs (7), .BR kafs\-client.conf (5), .BR proc (5) man/kafs.7000066400000000000000000000077451367270324000126660ustar00rootroot00000000000000.\" .\" Copyright (C) 2019 Red Hat, Inc. All Rights Reserved. .\" Written by David Howells (dhowells@redhat.com) .\" .\" This program is free software; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License .\" as published by the Free Software Foundation; either version .\" 2 of the License, or (at your option) any later version. .\" .TH KAFS 7 "16 Apr 2019" Linux "In-kernel AFS filesystem" .SH NAME kafs \- In-kernel AFS filesystem .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .SH DESCRIPTION .B kafs is a network filesystem driver in the Linux kernel that is able to access AFS cells and the servers contained therein to locate the logical volumes that comprise the cell and the files contained in each volume. .P It supports transport over IPv4 UDP and IPv6 UDP and security based on Kerberos. The authentication token is used to define the user for the purpose of providing access control as well as providing communications security. .P The filesystem is of type "afs" and the mount command can be used to mount afs volumes manually using the "-t" flag on .BR mount (8). .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .SH SETTING UP The \fBkafs-client\fP package should be installed to so that systemd is configured to include a mount of AFS dynamic root on /afs. Note that mounting /afs is not enabled by default, so if it is needed, then \fIsystemd\fP should be told to enable it. This can be done with the following step: .P .RS .nf systemctl enable afs.mount .fi .RE .P This will mount a special directory on \fB/afs\fR which will be populated by an automount directory for each cell listed in the configuration. Doing a pathwalk into one of these directories will result in the \fBafs.cell\fR volume from the cell being mounted onto that directory. .P Local configuration should be placed in a file in the /etc/kafs/client.d/ directory. This will be included from client.conf in the next directory up. .P Typically in the local configuration, the local cell name would be specified and backup details of its Volume Location server addresses would be given. .P Also any overrides for the @sys filename substitution would be specified. See .BR kafs\-client.conf (5). .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .SH OPERATION Once the kafs-client is set up (and if there's no local cell, this is practically zero-conf, provided the cells to be accessed are properly set up with AFSDB or SRV records in the DNS), the /afs directory can be accessed: .P .RS .nf ls /afs//location/within/cell .fi .RE .P For example: .P .RS .nf ls /afs/rivendell.example.com/doc .fi .RE .P The user isn't limited to cells listed in /afs, but any cell can be tried by just substituting the name of the cell into the above formula. It does require the target to have DNS-based configuration provided. .P Note that each logical volume gets a discrete superblock and links between volumes turn into kernel mountpoints that, if stepped on, cause the appropriate volume to be mounted over them. .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .SH SECURITY .P kafs supports Kerberos-based authentication and communication encryption through the use of Kerberos. The \fBkinit\fP program can be use to authenticate with a Kerberos server: .P .RS .nf kinit myname@RIVENDELL.EXAMPLE.COM .fi .RE .P and then the \fBaklog-kafs\fP program to get a ticket for the kernel filesystem to use: .P .RS .nf aklog-kafs rivendell.example.com .fi .RE .P This will be placed on the caller's session keyring and can be viewed there with: .P .RS .nf keyctl show .fi .RE .P Note that the default realm is assumed to be the same as the cell name, but in all upper case. .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .SH SEE ALSO .ad l .nh .BR aklog\-kafs (1), .BR kafs\-client.conf (5), .BR keyctl (1), .BR kinit (1), .BR rxrpc (7), .BR session\-keyring (7), .BR systemctl (1) man/rxrpc.7000066400000000000000000000251541367270324000130720ustar00rootroot00000000000000.\" .\" Copyright (C) 2019 Red Hat, Inc. All Rights Reserved. .\" Written by David Howells (dhowells@redhat.com) .\" .\" This program is free software; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License .\" as published by the Free Software Foundation; either version .\" 2 of the License, or (at your option) any later version. .\" .TH AF_RXRPC 7 "16 Apr 2019" "Linux" "Linux Programmer's Manual" .SH NAME rxrpc \- Linux RxRPC (AFS) protocol implementation .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .SH SYNOPSIS .B #include .br .B #include .PP .IB socket " = socket(AF_RXRPC, SOCK_DGRAM, PF_INET);" .br .IB socket " = socket(AF_RXRPC, SOCK_DGRAM, PF_INET6);" .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .SH DESCRIPTION Linux optionally implements the RxRPC transport protocol, as used by the AFS network filesystem. Both client and server ends are support - even on the same socket - and authentication is supported at both ends. .P This can be used through the BSD socket interface, using the .BR sendmsg "(2) and " recvmsg (2) system calls with control data to multiplex calls over the socket and to provide or retrieve call metadata. .BR request_key (2) is used to find the authentication keys to use in the calling process's keyrings. .P The AF_RXRPC driver uses \fBudp\fR(7) sockets underneath, either IPv4-only or IPv6 (with IPv4), for transport. Under certain circumstances, the underlying transport sockets may be shared between client-only sockets (but are never shared if a socket is implementing a server). .P .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .SS Address format .in +4n .EX struct sockaddr_rxrpc { sa_family_t srx_family; /* AF_RXRPC */ uint16_t srx_service; /* The service identifier */ uint16_t transport_type; /* The type of transport */ uint16_t transport_len; /* Transport address length */ union { sa_family_t family; /* Transport address family */ struct sockaddr_in sin; /* IPv4 transport address */ struct sockaddr_in6 sin6; /* IPv6 transport address */ } transport; }; .EE .in .PP Where .I srx_family is always set to .BR AF_RXRPC ; .I srx_service is set to the service ID of the desired service; .I transport_type is set to the transport type, which is always .B SOCK_DGRAM for now; .I transport_len says how big the address in .I transport is. .P Inside the transport address part, and appropriate address for the underlying socket should be set, including things like family, port and address as appropriate. Note that it may be permissible to use IPv4 addresses on an IPv6 socket. .P .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .SS Socket Options AF_RXRPC provides a number of socket options that can be set with .BR setsockopt (2) and read with .BR getsockopt (2). The socket option level for IPv6 is .BR SOL_RXRPC . .TP .B RXRPC_SECURITY_KEY The option value is a string that specifies the name of a key to pass to .BR request_key (2) to get an appropriate authentication key. Such keys are expected to be of \fIrxrpc\fR type. .IP If this isn't set, AF_RXRPC will perform an unauthenticated, unencrypted call to the server. .TP .B RXRPC_SECURITY_KEYRING The option value is a string that specifies the name of a keyring to pass to .BR request_key (2) to specify the keys used by the server end to authenticate connections. .IP The service keys in the ring should be of type rxrpc_s and their descriptions should be of the form ":" and each should be given an 8-byte secret. .TP .B RXRPC_EXCLUSIVE_CONNECTION The option value should be empty. This causes each call made on this socket to get its own virtual connection and thus its own negotiated security context. .TP .B RXRPC_MIN_SECURITY_LEVEL The option value should be a 4-byte unsigned integer. This can be one of the following constants: .BR RXRPC_SECURITY_PLAIN ", " RXRPC_SECURITY_AUTH " or " RXRPC_SECURITY_ENCRYPT ; the first indicating the packets should be securely checksummed only, the second that packets should be authenticated and the third that full encryption should be employed. .TP .B RXRPC_UPGRADEABLE_SERVICE The option value should be a 2-slot array of 2-byte unsigned integers. To use this, the socket must be a server socket and must have been bound to more than one address with different \fIsrx_service\fP specifiers. .IP Slot[0] in the array specified the service ID to upgrade from; slot[1] specifies the service ID to upgrade to. This allows a client to find out if there's a 'better' version of the service available on the same address, but a different service ID. .IP If the client follows the correct protocol for probing an upgradeable service, the kernel will automatically upgrade the service ID on the connection and this will be reflected in the address returned by .IR recvmsg "(2)." .TP .B RXRPC_SUPPORTED_CMSG The option buffer should have room for a 4-byte integer. The maximum control buffer message type supported by the kernel is written into the buffer. This allows an application to find out what control messages it may use so that it can avoid getting an error if it tries to use something unsupported. .P .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .SS Message flags AF_RXRPC communicates certain information by way of the message flags passed to and received from .BR sendmsg "(2) and " recvmsg (2). .TP .B MSG_MORE This is passed to sendmsg() to indicate that there is more data to be transmitted as part of the request phase of a client call or the reply phase of a service operation. .B MSG_EOR recvmsg() sets this to indicate that the call has been terminated (the control messages must be parsed for information as to why) and that the kernel has discarded the user call ID tag. The tag may now be reused. .B MSG_PEEK This is passed to recvmsg() to look at the front of the message queue without removing any messages or changing the state of any outstanding calls. .B MSG_WAITALL This is passed to sendmsg() to instruct it not to return for a signal if it is still loading up the message queue and progress is being made at the other side in emptying it. This works around the problem of sendmsg() getting interrupted after partially queuing its data, but not then being able to return how much it has consumed. .B MSG_DONTWAIT This is passed to recvmsg() to indicate that it shouldn't wait if the message queue is empty. .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .SS Control messages AF_RXRPC communicates metadata to the caller through the ancillary data buffer (\fImsg_control\fP) in the messages passed to and fro using .BR sendmsg "(2) and " recvmsg (2). When building a control message buffer for sendmsg(), the RXRPC_SUPPORTED_CMSG value should be consulted to make sure that the control message type is supported. .TP .B RXRPC_USER_CALL_ID The data for this is an arbitrary long integer/pointer-sized tag that represents the call to the kernel. It may, for example, hold a pointer to some userspace structure representing the call to the process. .IP [sendmsg] This is passed to sendmsg() when the message proposed will create a client call. It must thereafter be included in all future sendmsg() calls pertaining to that call. .IP [recvmsg] recvmsg() includes the tag in all messages pertaining to a call until the final termination message is reached - which recvmsg() will mark by setting MSG_EOR. .TP .B RXRPC_ABORT The data for this is a 32-bit integer that is the abort code. .IP [sendmsg] When passed to sendmsg(), this causes the operation matching the tag to be aborted; this will be followed up by recvmsg() indicating MSG_EOR and a local error of ECONNABORTED, thereby terminating the tag. .IP [recvmsg] When obtained from recvmsg(), this indicates that a remote abort was received from the peer and the data gives the code for that abort. .TP .B RXRPC_ACK [recvmsg] This conveys no data. It indicates the final acknowledgement to a service call has been received. .TP .B RXRPC_NET_ERROR [recvmsg] This conveys a 32-bit integer into which the network error that terminated a call will have been placed. .TP .B RXRPC_BUSY [recvmsg] This conveys no data. It indicates that the operation has been rejected because the server is busy. .TP .B RXRPC_LOCAL_ERROR [recvmsg] This conveys a 32-bit integer into which the local error that terminated a call will have been placed. .TP .B RXRPC_NEW_CALL [recvmsg] This conveys no data. It indicates that a new service call has arrived at a server socket and is in need of a tag. RXRPC_ACCEPT is must be used for that. .TP .B RXRPC_ACCEPT The data for this is an arbitrary long integer/pointer-sized tag that represents the call to the kernel with the same semantics as for RXRPC_USER_CALL_ID. .IP [sendmsg] Supply a user call ID tag to a new service call. .TP .B RXRPC_EXCLUSIVE_CALL [sendmsg] Indicate that this particular call should be made on its own connection with an unshared negotiated security context. This requires no additional data. .TP .B RXRPC_UPGRADE_SERVICE [sendmsg] Indicate that this call should attempt to probe the service ID on the other side to see if it gets upgraded. The answer can be found in the srx_service value of the peer address recvmsg() returns for this call. This requires no additional data. .TP .B RXRPC_TX_LENGTH The data for this is a signed 64-bit integer. .IP [sendmsg] Specify the exact total transmit size. This allows AF_RXRPC to work out in advance how big encrypted packets are going to be (under some circumstances, there's a data length encrypted inside the packet). .IP If this is set, it may allow AF_RXRPC to be more efficient at filling packets. If the wrong amount of data is given (too little or too much), then the call will be aborted. .TP .B RXRPC_SET_CALL_TIMEOUT The data for this is an array of 1-3 32-bit integers. .IP [sendmsg] Specify various call timeouts. The first timeout is the \fIhard\fP timeout for the call in seconds: the call will be aborted if it takes longer than this amount of time in total. .IP The second timeout is the \fIidle\fP timeout for the call in milliseconds: the call will be aborted if we don't receive the next DATA packet within that amount of time during the reception phase. .IP The third timeout is the \fInormal\fP timeout for the call in milliseconds: the call will be aborted if we go for that amount of time without receiving any type of packet pertaining to the call. .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .SH SEE ALSO .ad l .nh .BR kafs (7), .BR request_key (2) redhat/000077500000000000000000000000001367270324000123315ustar00rootroot00000000000000redhat/kafs-client.spec000066400000000000000000000110121367270324000154000ustar00rootroot00000000000000# % define buildid .local %global libapivermajor 0 %global libapiversion %{libapivermajor}.1 Name: kafs-client Version: 0.5 Release: 1%{?dist}%{?buildid} Summary: The basic tools for kAFS and mounter for the AFS dynamic root License: GPLv2+ URL: https://www.infradead.org/~dhowells/kafs/ Source0: https://www.infradead.org/~dhowells/kafs/kafs-client-%{version}.tar.bz2 Requires: filesystem-afs BuildRequires: krb5-devel BuildRequires: keyutils-libs-devel BuildRequires: openssl-devel BuildRequires: gcc # # Need this for the upcall program to do DNS lookups. # /etc/kafs/client.conf # %global datadir %{_datarootdir}/kafs # keyutils-1.6 request-key allows us to override AFSDB DNS lookups. Requires: keyutils >= 1.6 BuildRequires: systemd-units Requires(post): systemd-units Requires(preun): systemd-units Requires(postun): systemd-units Requires: selinux-policy-base >= 3.7.19-5 %description Provide basic AFS-compatible tools for kAFS and systemd scripts to mount the dynamic root on /afs and preload the cell database. %package libs Summary: Library of routines for dealing with kAFS Requires: %{name}%{?_isa} = %{version}-%{release} %description libs Provide a library of shareable routines for dealing with the kAFS filesystem. These provide things like configuration parsing and DNS lookups. %package libs-devel Summary: Library of routines for dealing with kAFS Requires: %{name}-libs%{?_isa} = %{version}-%{release} %description libs-devel Provide a library of shareable routines for dealing with the kAFS filesystem. These provide things like configuration parsing and DNS lookups. # # We generate a compatibility package that makes kafs look like OpenAFS, but it # needs to be uninstalled be able to install OpenAFS or Auristor. # %package compat Summary: AFS compatibility package Requires: %{name}%{?_isa} = %{version}-%{release} %description compat Compatibility package providing standard AFS names for tools such as aklog. This package must be uninstalled for kAFS to coexist with another AFS implementation (such as OpenAFS). %global _hardened_build 1 %global docdir %{_docdir}/kafs-client %prep %setup -q %build %make_build \ ETCDIR=%{_sysconfdir} \ BINDIR=%{_bindir} \ SBINDIR=%{_sbindir} \ DATADIR=%{datadir} \ INCLUDEDIR=%{_includedir} \ LIBDIR=%{_libdir} \ LIBEXECDIR=%{_libexecdir} \ MANDIR=%{_mandir} \ CFLAGS="-Wall -Werror $RPM_OPT_FLAGS $RPM_LD_FLAGS $ARCH_OPT_FLAGS" %install mkdir -p %{buildroot}%{_bindir} mkdir -p %{buildroot}%{_unitdir} mkdir -p %{buildroot}%{_mandir}/man1 mkdir -p %{buildroot}%{_sysconfdir} mkdir -p %{buildroot}%{_datarootdir} %make_install \ ETCDIR=%{_sysconfdir} \ BINDIR=%{_bindir} \ SBINDIR=%{_sbindir} \ DATADIR=%{datadir} \ INCLUDEDIR=%{_includedir} \ LIBDIR=%{_libdir} \ LIBEXECDIR=%{_libexecdir} \ MANDIR=%{_mandir} \ CFLAGS="-Wall -Werror $RPM_OPT_FLAGS $RPM_LD_FLAGS $ARCH_OPT_FLAGS" # Compat ln -s aklog-kafs %{buildroot}/%{_bindir}/aklog %ldconfig_scriptlets libs %post %systemd_post afs.mount %preun %systemd_preun afs.mount %postun %systemd_postun_with_restart afs.mount %files %doc README %license LICENCE.GPL %{_bindir}/aklog-kafs %{_sbindir}/kafs-check-config %{_unitdir}/* %{_mandir}/man1/aklog-kafs.1* %{_mandir}/man5/*.5* %{_mandir}/man7/*.7* %{_mandir}/man8/*.8* %{_libexecdir}/kafs-preload %{_libexecdir}/kafs-dns %{_sysconfdir}/request-key.d/kafs_dns.conf %files libs %{_libdir}/libkafs_client.so.%{libapiversion} %{_libdir}/libkafs_client.so.%{libapivermajor} %{datadir} %{_sysconfdir}/kafs %config(noreplace) %{_sysconfdir}/kafs/client.conf %config(noreplace) %{_sysconfdir}/kafs/client.d %files libs-devel %{_libdir}/libkafs_client.so %{_includedir}/* %files compat %{_bindir}/aklog %{_mandir}/man1/aklog.1* %changelog * Thu Jun 18 2020 David Howells 0.5-1 - kafs-dns: Fix the -V flag. - kafs-dns: Fix srv[=N] callout option. - Add manpages for kafs-dns and kafs-preload. - kafs-preload: Fix the debugging output. - kafs-dns: Use the right name in the help output and syslog logging. - Rename the etc.conf source to client.conf as that's the installation name * Wed May 20 2020 David Howells 0.4-1 - Use AF_ALG rather than OpenSSL's libcrypto. - Move the aklog.1 manpage to the -compat rpm. * Fri Jul 5 2019 David Howells 0.3-1 - Address Fedora packaging review comments [RH BZ 1724281]. * Tue Apr 16 2019 David Howells 0.2-1 - Improve aklog-kafs and its manpage. - rpm: Depend on filesystem-afs for /afs dir installation. * Fri Feb 9 2018 David Howells 0.1-1 - Initial commit src/000077500000000000000000000000001367270324000116515ustar00rootroot00000000000000src/Makefile000066400000000000000000000062011367270324000133100ustar00rootroot00000000000000CFLAGS ?= -g -Wall -Wsign-compare include Makefile.config all: lib progs CPPFLAGS += -Iinclude -DETCDIR=\"$(ETCDIR)\" ############################################################################### # # Build a library to do config parsing and other stuff. # ############################################################################### lib: $(DEVELLIB) $(DEVELLIB): $(SONAME) $(LNS) $< $@ $(SONAME): $(LIBNAME) $(LNS) $< $@ LIB_HEADERS := $(wildcard include/kafs/*.h) LIB_FILES := \ lib_cell_lookup.c \ lib_cellserv.c \ lib_dns_lookup.c \ lib_object.c \ lib_profile.c LIBVERS := -shared -Wl,-soname,$(SONAME) -Wl,--version-script,version.lds LIB_OBJS := $(patsubst %.c,%.os,$(LIB_FILES)) %.os: %.c $(CC) $(CPPFLAGS) $(CFLAGS) -fPIC -o $@ -c $< $(LIBNAME): $(LIB_OBJS) version.lds Makefile $(CC) $(CFLAGS) -fPIC $(LDFLAGS) $(LIBVERS) -o $@ $(LIB_OBJS) $(LIBLIBS) \ -lresolv $(LIB_OBJS) : $(LIB_HEADERS) Makefile LIB_DEPENDENCY := $(DEVELLIB) LDFLAGS += -L. #%.o: %.c $(LIB_HEADERS) Makefile # $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< ############################################################################### # # Build stuff # ############################################################################### progs: \ aklog-kafs \ kafs-check-config \ kafs-preload \ kafs-dns aklog-kafs: aklog-kafs.o $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -lkrb5 -lkeyutils kafs-check-config: kafs-check-config.o $(DEVELLIB) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ kafs-check-config.o -lkafs_client kafs-preload: preload-cells.o $(DEVELLIB) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ preload-cells.o -lkafs_client KAFS_DNS_OBJS := dns_main.o dns_afsdb_text.o dns_afsdb_v1.o kafs-dns: $(KAFS_DNS_OBJS) $(DEVELLIB) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(KAFS_DNS_OBJS) \ -lkafs_client -lkeyutils kafs-check-config.o: $(LIB_HEADERS) preload-cells.o: $(LIB_HEADERS) $(KAFS_DNS_OBJS): $(LIB_HEADERS) ############################################################################### # # Install everything # ############################################################################### install: all mkdir -p $(DESTDIR)$(INCLUDEDIR)/kafs $(INSTALL) -D -m 0644 $(LIB_HEADERS) $(DESTDIR)$(INCLUDEDIR)/kafs/ $(INSTALL) -D -m 0755 $(LIBNAME) $(DESTDIR)$(LIBDIR)/$(LIBNAME) $(LNS) $(LIBNAME) $(DESTDIR)$(LIBDIR)/$(SONAME) $(LNS) $(LIBDIR)/$(SONAME) $(DESTDIR)$(LIBDIR)/$(DEVELLIB) $(INSTALL) -D -m 0755 aklog-kafs $(DESTDIR)$(BINDIR)/aklog-kafs $(INSTALL) -D -m 0755 kafs-check-config $(DESTDIR)$(SBINDIR)/kafs-check-config $(INSTALL) -D -m 0755 kafs-preload $(DESTDIR)$(LIBEXECDIR)/kafs-preload $(INSTALL) -D -m 0755 kafs-dns $(DESTDIR)$(LIBEXECDIR)/kafs-dns ############################################################################### # # Clean up # ############################################################################### clean: $(RM) aklog-kafs kafs-check-config kafs-preload kafs-dns $(RM) $(DEVELLIB) $(SONAME) $(LIBNAME) $(RM) *.o *~ *.os distclean: clean ############################################################################### # # Build debugging # ############################################################################### show_vars: @echo VERSION=$(VERSION) src/Makefile.config000066400000000000000000000040751367270324000145630ustar00rootroot00000000000000INSTALL = install DESTDIR = ETCDIR = /etc BINDIR = /usr/bin LIBEXECDIR = /usr/libexec INCLUDEDIR = /usr/include DATADIR = /usr/share/kafs-client SPECFILE = ../redhat/kafs-client.spec ifeq ($(origin LIBDIR),undefined) LIBDIR := $(shell ldd /usr/bin/make | grep '\(/libc\)' | sed -e 's!.*\(/.*\)/libc[.].*!\1!') endif LNS := ln -sf ############################################################################### # # Determine the current package version from the specfile # ############################################################################### VERSION := $(word 2,$(shell grep "^Version:" $(SPECFILE))) CPPFLAGS += -DVERSION="\"$(VERSION)\"" ############################################################################### # # Determine the current library version from the version script # ############################################################################### libversion := $(filter KAFS_CLIENT_%,$(shell grep ^KAFS_CLIENT_ version.lds)) libversion := $(lastword $(libversion)) libversion := $(lastword $(libversion)) APIVERSION := $(subst KAFS_CLIENT_,,$(libversion)) vernumbers := $(subst ., ,$(APIVERSION)) APIMAJOR := $(firstword $(vernumbers)) DEVELLIB := libkafs_client.so SONAME := $(DEVELLIB).$(APIMAJOR) LIBNAME := $(DEVELLIB).$(APIVERSION) ############################################################################### # # Guess at the appropriate word size # ############################################################################### BUILDFOR := $(shell file /usr/bin/make | sed -e 's!.*ELF \(32\|64\)-bit.*!\1!')-bit ifeq ($(BUILDFOR),32-bit) CFLAGS += -m32 else ifeq ($(BUILDFOR),64-bit) CFLAGS += -m64 endif endif ############################################################################### # # Guess at the appropriate lib directory and word size # ############################################################################### ifeq ($(origin LIBDIR),undefined) LIBDIR := $(shell ldd /usr/bin/make | grep '\(/libc\)' | sed -e 's!.*\(/.*\)/libc[.].*!\1!') endif BUILDFOR := $(shell file /usr/bin/make | sed -e 's!.*ELF \(32\|64\)-bit.*!\1!')-bit src/aklog-kafs.c000066400000000000000000000264201367270324000140400ustar00rootroot00000000000000/* aklog.c: description * * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * Based on code: * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * Copyright (C) 2008 Chaskiel Grundman. All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * Kerberos-5 strong enctype support for rxkad: * https://tools.ietf.org/html/draft-kaduk-afs3-rxkad-k5-kdf-00 * * Invoke as: aklog-k5 [] */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include struct rxrpc_key_sec2_v1 { uint32_t kver; /* key payload interface version */ uint16_t security_index; /* RxRPC header security index */ uint16_t ticket_length; /* length of ticket[] */ uint32_t expiry; /* time at which expires */ uint32_t kvno; /* key version number */ uint8_t session_key[8]; /* DES session key */ uint8_t ticket[0]; /* the encrypted ticket */ }; #define MD5_DIGEST_SIZE 16 #define RXKAD_TKT_TYPE_KERBEROS_V5 256 #define OSERROR(X, Y) do { if ((long)(X) == -1) { perror(Y); exit(1); } } while(0) #define OSZERROR(X, Y) do { if ((long)(X) == 0) { perror(Y); exit(1); } } while(0) #define KRBERROR(X, Y) do { if ((X) != 0) { const char *msg = krb5_get_error_message(k5_ctx, (X)); fprintf(stderr, "%s: %s\n", (Y), msg); krb5_free_error_message(k5_ctx, msg); exit(1); } } while(0) static const uint64_t des_weak_keys[16] = { 0x0101010101010101ULL, 0xFEFEFEFEFEFEFEFEULL, 0xE0E0E0E0F1F1F1F1ULL, 0x1F1F1F1F0E0E0E0EULL, 0x011F011F010E010EULL, 0x1F011F010E010E01ULL, 0x01E001E001F101F1ULL, 0xE001E001F101F101ULL, 0x01FE01FE01FE01FEULL, 0xFE01FE01FE01FE01ULL, 0x1FE01FE00EF10EF1ULL, 0xE01FE01FF10EF10EULL, 0x1FFE1FFE0EFE0EFEULL, 0xFE1FFE1FFE0EFE0EULL, 0xE0FEE0FEF1FEF1FEULL, 0xFEE0FEE0FEF1FEF1ULL }; #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) static bool des_is_weak_key(uint64_t des) { size_t i; #if __BYTE_ORDER == __LITTLE_ENDIAN des = bswap_64(des); #endif for (i = 0; i < ARRAY_SIZE(des_weak_keys); i++) if (des_weak_keys[i] == des) return true; return false; } static void des_set_odd_parity(uint64_t *p) { uint64_t x = *p, y, z; y = x | 0x0101010101010101ULL; y ^= y >> 4; y ^= y >> 2; y ^= y >> 1; z = x | (y & 0x0101010101010101ULL); *p = z; } /* * Strip Triple-DES parity bits from a block. * * Discard the parity bits and converts an 8-octet block to a 7-octet block. * * See [afs3-rxkad-k5-kdf-00 §4.2] and [RFC3961 §6.3.1]. * * [These docs number the bits weirdly. Bit '8' appears to be the LSB of the * first octet, and 1 the MSB]. */ static void des3_strip_parity_bits(void *random, const void *key) { const unsigned char *k = key; unsigned char *r = random, lsbs; int i; lsbs = k[7] >> 1; for (i = 0; i < 7; i++) { r[i] = (k[i] & 0xfe) | (lsbs & 0x1); lsbs >>= 1; } } /* * Reverse the Triple-DES random-to-key operation, converting three 64-bit DES * keys to 56-bit random strings and concatenate to give a 168-bit random * string that can then be fed to the KDF. */ static unsigned int des3_key_to_random(void *random, const void *key, unsigned int len) { unsigned int new_len = 0; while (len > 8) { des3_strip_parity_bits(random, key); key += 8; random += 7; len -= 8; new_len += 7; } return new_len; } /* * Do HMAC(MD5). */ static size_t HMAC_MD5(const void *key, size_t key_len, const void *data, size_t data_len, unsigned char *md, size_t md_len) { static struct sockaddr_alg sa = { .salg_family = AF_ALG, .salg_type = "hash", .salg_name = "hmac(md5)", }; int alg, sock, ret; alg = socket(AF_ALG, SOCK_SEQPACKET, 0); OSERROR(alg, "AF_ALG"); OSERROR(bind(alg, (struct sockaddr *)&sa, sizeof(sa)), "bind/AF_ALG"); OSERROR(setsockopt(alg, SOL_ALG, ALG_SET_KEY, key, key_len), "setsockopt/AF_ALG"); sock = accept(alg, NULL, 0); OSERROR(sock, "AF_ALG"); OSERROR(write(sock, data, data_len), "write/AF_ALG"); ret = read(sock, md, md_len); OSERROR(ret, "read/AF_ALG"); close(sock); close(alg); return ret; } /* * The data to pass into the key derivation function. */ struct kdf_data { unsigned char i_2; unsigned char Label[6]; unsigned char L_2[4]; } __attribute__((packed)); static const struct kdf_data rxkad_kdf_data = { .Label = "rxkad", /* Including NUL separator */ .L_2 = { 0, 0, 0, 64 }, /* BE integer */ }; /* * Derive a 64-bit key we can pass to rxkad from the ticket data. The ticket * data is used as the key for the HMAC-MD5 algorithm, which is used as the * PRF. We then iterate over a series of constructed source strings, passing * each one through the PRF until we get an MD5 output that we can cut down and * use as a substitute for the DES session key that isn't too weak. * * [afs3-rxkad-k5-kdf-00 §4.3] */ static void key_derivation_function(krb5_creds *creds, uint8_t *session_key) { struct kdf_data kdf_data = rxkad_kdf_data; unsigned int i, len; union { unsigned char md5[MD5_DIGEST_SIZE]; uint64_t n_des; } buf; for (i = 1; i <= 255; i++) { /* K(i) = PRF(Ks, [i]_2 || Label || 0x00 || [L]_2) */ kdf_data.i_2 = i; len = HMAC_MD5(creds->keyblock.contents, creds->keyblock.length, (unsigned char *)&kdf_data, sizeof(kdf_data), buf.md5, sizeof(buf.md5)); if (len < sizeof(buf.n_des)) { fprintf(stderr, "aklog: HMAC returned short result\n"); exit(1); } /* Overlay the DES parity. */ buf.n_des &= 0xfefefefefefefefeULL; des_set_odd_parity(&buf.n_des); if (!des_is_weak_key(buf.n_des)) goto success; } fprintf(stderr, "aklog: Unable to derive strong DES key\n"); exit(1); success: memcpy(session_key, &buf.n_des, sizeof(buf.n_des)); } /* * Extract or derive the session key. */ static void derive_key(krb5_creds *creds, uint8_t *session_key) { unsigned int length = creds->keyblock.length; switch (creds->keyblock.enctype) { case ENCTYPE_NULL: goto not_supported; case ENCTYPE_DES_CBC_CRC: goto just_copy; case ENCTYPE_DES_CBC_MD4: goto just_copy; case ENCTYPE_DES_CBC_MD5: goto just_copy; case ENCTYPE_DES_CBC_RAW: goto deprecated; case ENCTYPE_DES3_CBC_SHA: goto des3_discard_parity; /* des3-cbc-md5 */ case ENCTYPE_DES3_CBC_RAW: goto deprecated; case 7: goto des3_discard_parity; /* des3-cbc-sha1 */ case ENCTYPE_DES_HMAC_SHA1: goto deprecated; case ENCTYPE_DSA_SHA1_CMS: goto not_supported; case ENCTYPE_MD5_RSA_CMS: goto not_supported; case ENCTYPE_SHA1_RSA_CMS: goto not_supported; case ENCTYPE_RC2_CBC_ENV: goto not_supported; case ENCTYPE_RSA_ENV: goto not_supported; case ENCTYPE_RSA_ES_OAEP_ENV: goto not_supported; case ENCTYPE_DES3_CBC_ENV: goto not_supported; case ENCTYPE_DES3_CBC_SHA1: goto des3_discard_parity; /* des3-cbc-sha1-kd */ default: if (length < 7) goto key_too_short; if (creds->keyblock.enctype < 0) goto not_supported; goto derive_key; } /* Strip the parity bits for 3DES then do KDF [afs3-rxkad-k5-kdf-00 §4.2]. */ des3_discard_parity: if (length & 7) { fprintf(stderr, "aklog: 3DES session key not multiple of 8 octets.\n"); exit(1); } creds->keyblock.length = des3_key_to_random(creds->keyblock.contents, creds->keyblock.contents, length); goto derive_key; /* Do KDF [afs3-rxkad-k5-kdf-00 §4.3]. */ derive_key: key_derivation_function(creds, session_key); return; /* Use as-is for single-DES [afs3-rxkad-k5-kdf-00 §4.1]. */ just_copy: if (length != 8) { fprintf(stderr, "aklog: DES session key not 8 octets.\n"); exit(1); } memcpy(session_key, creds->keyblock.contents, length); return; deprecated: fprintf(stderr, "aklog: Ticket contains deprecated enc type (%d)\n", creds->keyblock.enctype); exit(1); not_supported: fprintf(stderr, "aklog: Ticket contains unsupported enc type (%d)\n", creds->keyblock.enctype); exit(1); key_too_short: fprintf(stderr, "aklog: Ticket contains short key block (%u)\n", length); exit(1); } /* * Read the name of default cell. */ static char *get_default_cell(void) { static const char rootcell[] = "/proc/net/afs/rootcell"; ssize_t n; char buf[260], *nl, *cell; int fd; fd = open(rootcell, O_RDONLY); OSERROR(fd, rootcell); n = read(fd, buf, sizeof(buf) - 2); OSERROR(n, rootcell); close(n); if (n == 0) goto unset; buf[n] = 0; nl = memchr(buf, '\n', n); if (nl == buf) goto unset; *nl = 0; cell = strdup(buf); OSZERROR(cell, "strdup"); return cell; unset: fprintf(stderr, "error: The default cell is not set\n"); exit(1); } /* * */ int main(int argc, char **argv) { char *cell, *realm, *princ, *desc, *p; int ret; size_t plen; struct rxrpc_key_sec2_v1 *payload; krb5_error_code kresult; krb5_context k5_ctx; krb5_ccache cc; krb5_creds search_cred, *creds; if (argc < 1 || argc > 3 || (argc == 2 && strcmp(argv[1], "--help") == 0)) { fprintf(stderr, "Usage: aklog-kafs [ []]\n"); exit(1); } if (argc == 1) cell = get_default_cell(); else cell = argv[1]; if (argc == 3) { realm = strdup(argv[2]); OSZERROR(realm, "strdup"); } else { realm = strdup(cell); OSZERROR(realm, "strdup"); for (p = realm; *p; p++) *p = toupper(*p); } for (p = cell; *p; p++) *p = tolower(*p); ret = asprintf(&princ, "afs/%s@%s", cell, realm); OSERROR(ret, "asprintf"); ret = asprintf(&desc, "afs@%s", cell); OSERROR(ret, "asprintf"); printf("CELL %s\n", cell); printf("PRINC %s\n", princ); kresult = krb5_init_context(&k5_ctx); if (kresult) { fprintf(stderr, "krb5_init_context failed\n"); exit(1); } kresult = krb5_cc_default(k5_ctx, &cc); KRBERROR(kresult, "Getting credential cache"); memset(&search_cred, 0, sizeof(krb5_creds)); kresult = krb5_cc_get_principal(k5_ctx, cc, &search_cred.client); KRBERROR(kresult, "Getting client principal"); kresult = krb5_parse_name(k5_ctx, princ, &search_cred.server); KRBERROR(kresult, "Parsing server principal name"); //search_cred.keyblock.enctype = ENCTYPE_DES_CBC_CRC; kresult = krb5_get_credentials(k5_ctx, 0, cc, &search_cred, &creds); KRBERROR(kresult, "Getting tickets"); plen = sizeof(*payload) + creds->ticket.length; payload = calloc(1, plen + 4); if (!payload) { perror("calloc"); exit(1); } printf("plen=%zu tklen=%u rk=%zu\n", plen, creds->ticket.length, sizeof(*payload)); /* use version 1 of the key data interface */ payload->kver = 1; payload->security_index = 2; payload->ticket_length = creds->ticket.length; payload->expiry = creds->times.endtime; payload->kvno = RXKAD_TKT_TYPE_KERBEROS_V5; derive_key(creds, payload->session_key); memcpy(payload->ticket, creds->ticket.data, creds->ticket.length); ret = add_key("rxrpc", desc, payload, plen, KEY_SPEC_SESSION_KEYRING); OSERROR(ret, "add_key"); krb5_free_creds(k5_ctx, creds); krb5_free_cred_contents(k5_ctx, &search_cred); krb5_cc_close(k5_ctx, cc); krb5_free_context(k5_ctx); exit(0); } src/dns_afsdb.h000066400000000000000000000005171367270324000137500ustar00rootroot00000000000000struct kafs_lookup_context; extern void *kafs_generate_text_payload(void *result, const char *cell_name, unsigned int *_ttl, struct kafs_lookup_context *ctx); extern void *kafs_generate_v1_payload(void *result, const char *cell_name, unsigned int *_ttl, struct kafs_lookup_context *ctx); src/dns_afsdb_text.c000066400000000000000000000043041367270324000150050ustar00rootroot00000000000000/* * Generate a set of addresses as a text string. * * Copyright (C) David Howells (dhowells@redhat.com) 2018 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #include #include #include #include #include #include "dns_afsdb.h" static void store_char(char **_b, char n) { *(*_b)++ = n; } static void store_string(char **_b, const char *p) { unsigned int len = strlen(p); memcpy(*_b, p, len); *_b += len; } /* * Generate the payload to pass to the kernel as v1 server bundle. */ static void emit_text_str(char **_b, struct kafs_server_list *vls, unsigned short default_port) { struct kafs_server_addr *addr; struct kafs_server *server; const char *p; unsigned int i, j; char buf[100]; bool need_sep = false; for (i = 0; i < vls->nr_servers; i++) { server = &vls->servers[i]; for (j = 0; j < server->nr_addrs; j++) { addr = &server->addrs[j]; if (need_sep) store_char(_b, ','); need_sep = true; switch (addr->sin.sin_family) { case AF_INET: p = inet_ntop(AF_INET, &addr->sin.sin_addr, buf, sizeof(buf)); if (p) { store_char(_b, '['); store_string(_b, buf); store_char(_b, ']'); } break; case AF_INET6: p = inet_ntop(AF_INET6, &addr->sin6.sin6_addr, buf, sizeof(buf)); if (p) { store_char(_b, '['); store_string(_b, buf); store_char(_b, ']'); } break; default: continue; } if (server->port && server->port != default_port) { sprintf(buf, "%u", server->port); store_char(_b, '+'); store_string(_b, buf); } } } store_char(_b, 0); } void *kafs_generate_text_payload(void *result, const char *cell_name, unsigned int *_ttl, struct kafs_lookup_context *ctx) { struct kafs_cell *cell; char *b = result; ctx->report.what = cell_name; cell = kafs_lookup_cell(cell_name, ctx); if (!cell) return NULL; if (cell->vlservers) emit_text_str(&b, cell->vlservers, 7003); return b; } src/dns_afsdb_v1.c000066400000000000000000000046471367270324000143610ustar00rootroot00000000000000/* * Generate a v1 servers and addresses list. * * Copyright (C) David Howells (dhowells@redhat.com) 2018 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #include #include #include #include #include "dns_afsdb.h" #include "dns_resolver.h" static void store_u8(unsigned char **_b, unsigned char n) { *(*_b)++ = n; } static void store_u16(unsigned char **_b, unsigned short n) { *(*_b)++ = (n >> 0) & 0xff; *(*_b)++ = (n >> 8) & 0xff; } static void store_octets(unsigned char **_b, const void *p, size_t n) { memcpy(*_b, p, n); *_b += n; } /* * Generate the payload to pass to the kernel as v1 server bundle. */ static void emit_v1(unsigned char **_b, struct kafs_server_list *vls) { struct kafs_server_addr *addr; struct kafs_server *server; unsigned int i, j, n; store_u8 (_b, 0); /* It's not a string */ store_u8 (_b, DNS_PAYLOAD_IS_SERVER_LIST); store_u8 (_b, 1); /* Encoding version */ store_u8 (_b, vls->source); store_u8 (_b, vls->status); store_u8 (_b, vls->nr_servers); for (i = 0; i < vls->nr_servers; i++) { server = &vls->servers[i]; n = strlen(server->name); store_u16(_b, n); store_u16(_b, server->pref); store_u16(_b, server->weight); store_u16(_b, server->port); store_u8 (_b, server->source); store_u8 (_b, server->status); store_u8 (_b, server->protocol); store_u8 (_b, server->nr_addrs); store_octets(_b, server->name, n); for (j = 0; j < server->nr_addrs; j++) { addr = &server->addrs[j]; switch (addr->sin.sin_family) { case AF_INET: store_u8(_b, DNS_ADDRESS_IS_IPV4); store_octets(_b, &addr->sin.sin_addr, 4); break; case AF_INET6: store_u8(_b, DNS_ADDRESS_IS_IPV6); store_octets(_b, &addr->sin6.sin6_addr, 16); break; default: store_u8(_b, 0); continue; } } } } void *kafs_generate_v1_payload(void *result, const char *cell_name, unsigned int *_ttl, struct kafs_lookup_context *ctx) { struct kafs_cell *cell; unsigned char *b = result; ctx->report.what = cell_name; cell = kafs_lookup_cell(cell_name, ctx); if (!cell) return NULL; if (_ttl) *_ttl = cell->vlservers->ttl; if (cell->vlservers) emit_v1(&b, cell->vlservers); return b; } src/dns_main.c000066400000000000000000000240111367270324000136030ustar00rootroot00000000000000/* * DNS Resolver Module User-space Helper for AFSDB records * * Copyright (C) Wang Lei (wang840925@gmail.com) 2010 * Authors: Wang Lei (wang840925@gmail.com) * * Copyright (C) David Howells (dhowells@redhat.com) 2018 * * This is a userspace tool for querying AFSDB RR records in the DNS on behalf * of the kernel, and converting the VL server addresses to IPv4 format so that * they can be used by the kAFS filesystem. * * As some function like res_init() should use the static liberary, which is a * bug of libresolv, that is the reason for cifs.upcall to reimplement. * * To use this program, you must tell /sbin/request-key how to invoke it. You * need to have the keyutils package installed and something like the following * lines added to your /etc/request-key.conf file: * * #OP TYPE DESCRIPTION CALLOUT INFO PROGRAM ARG1 ARG2 ARG3 ... * ====== ============ =========== ============ ========================== * create dns_resolver afsdb:* * /sbin/key.dns_resolver %k * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include "dns_afsdb.h" static const char *DNS_PARSE_VERSION = "2.0"; static const char prog[] = "kafs-dns"; static const char key_type[] = "dns_resolver"; static const char afsdb_query_type[] = "afsdb:"; static key_serial_t key; static int debug_mode; static unsigned int output_version = 0; /* * Print an error to stderr or the syslog, negate the key being created and * exit */ void error(const char *fmt, ...) { va_list va; va_start(va, fmt); if (isatty(2)) { fputs("E: ", stderr); vfprintf(stderr, fmt, va); fputc('\n', stderr); } else { vsyslog(LOG_ERR, fmt, va); } va_end(va); /* * on error, negatively instantiate the key ourselves so that we can * make sure the kernel doesn't hang it off of a searchable keyring * and interfere with the next attempt to instantiate the key. */ if (!debug_mode) keyctl_negate(key, 1, KEY_REQKEY_DEFL_DEFAULT); exit(1); } #define error(FMT, ...) error("Error: " FMT, ##__VA_ARGS__) /* * Just print an error to stderr or the syslog */ static void print_error(const char *fmt, ...) { va_list va; va_start(va, fmt); if (isatty(2)) { fputs("E: ", stderr); vfprintf(stderr, fmt, va); fputc('\n', stderr); } else { vsyslog(LOG_ERR, fmt, va); } va_end(va); } /* * Print status information */ static void verbose(const char *fmt, ...) { va_list va; va_start(va, fmt); if (isatty(1)) { fputs("I: ", stdout); vfprintf(stdout, fmt, va); fputc('\n', stdout); } else { vsyslog(LOG_INFO, fmt, va); } va_end(va); } /* * Print usage details, */ static __attribute__((noreturn)) void usage(void) { if (isatty(2)) { fprintf(stderr, "Usage: %s [OPTION]... \n", prog); fprintf(stderr, " %s -D [OPTION]... \n", prog); fprintf(stderr, " %s -V\n", prog); fprintf(stderr, "\n"); fprintf(stderr, "Where [OPTION].. is a combination of one or more of:\n"); fprintf(stderr, "\t-c \n"); fprintf(stderr, "\t-N dns\n"); fprintf(stderr, "\t-N vls-afsdb\n"); fprintf(stderr, "\t-N vls-srv\n"); fprintf(stderr, "\t-N vls-all\n"); fprintf(stderr, "\t-N vl-host\n"); fprintf(stderr, "\t-o \n"); fprintf(stderr, "\t-v\n"); } else { verbose("Usage: %s [-vv] ", prog); } exit(2); } /* * Parse the callout info string. */ static void parse_callout(char *options, struct kafs_lookup_context *ctx) { char *k, *val; ctx->want_ipv4_addrs = true; ctx->want_ipv6_addrs = true; if (!*options) { /* legacy mode */ ctx->want_ipv6_addrs = false; return; } do { k = options; options = strchr(options, ' '); if (!options) options = k + strlen(k); else *options++ = '\0'; if (!*k) continue; if (strchr(k, ',')) error("Option name '%s' contains a comma", k); val = strchr(k, '='); if (val) *val++ = '\0'; if (ctx->report.verbose) ctx->report.verbose("Opt %s", k); if (strcmp(k, "ipv4") == 0) { ctx->want_ipv4_addrs = true; ctx->want_ipv6_addrs = false; } else if (strcmp(k, "ipv6") == 0) { ctx->want_ipv4_addrs = false; ctx->want_ipv6_addrs = true; } else if (strcmp(k, "srv") == 0) { if (!val) error("Option srv missing version"); output_version = atoi(val); } } while (*options); } const struct option long_options[] = { { "conf", 0, NULL, 'c' }, { "debug", 0, NULL, 'D' }, { "no", 0, NULL, 'N' }, { "output", 0, NULL, 'o' }, { "verbose", 0, NULL, 'v' }, { "version", 0, NULL, 'V' }, { NULL, 0, NULL, 0 } }; /* * */ int main(int argc, char *argv[]) { struct kafs_lookup_context ctx = { .report.error = print_error, }; const char *dump_file = NULL; const char *filev[10], **filep = NULL; char *keyend, *p; char *callout_info = NULL; char *buf = NULL, *name, *result, *r_end; unsigned int ttl; size_t ktlen; int ret, filec = 0; if (argc > 1 && strcmp(argv[1], "--help") == 0) usage(); openlog(prog, 0, LOG_DAEMON); while ((ret = getopt_long(argc, argv, "Dvc:N:o:V", long_options, NULL)) != -1) { switch (ret) { case 'c': if (filec >= 9) { fprintf(stderr, "Max 9 files\n"); exit(2); } filev[filec++] = optarg; break; case 'D': debug_mode = 1; break; case 'V': printf("version: %s from %s (%s)\n", DNS_PARSE_VERSION, keyutils_version_string, keyutils_build_string); exit(0); case 'v': if (!ctx.report.verbose) ctx.report.verbose = verbose; else ctx.report.verbose2 = verbose; break; case 'N': if (strcmp(optarg, "vls-srv") == 0) { ctx.no_vls_srv = true; } else if (strcmp(optarg, "vls-afsdb") == 0) { ctx.no_vls_afsdb = true; } else if (strcmp(optarg, "vls-all") == 0) { ctx.no_vls_srv = true; ctx.no_vls_afsdb = true; } else if (strcmp(optarg, "vl-host") == 0) { ctx.no_vl_host = true; } else if (strcmp(optarg, "dns") == 0) { ctx.no_vls_srv = true; ctx.no_vls_afsdb = true; ctx.no_vl_host = true; } else { fprintf(stderr, "Unknown restriction '-N %s'\n", optarg); usage(); } break; case 'o': dump_file = optarg; break; default: if (!isatty(2)) syslog(LOG_ERR, "unknown option: %c", ret); usage(); } } argc -= optind; argv += optind; if (!debug_mode) { if (argc != 1) usage(); /* get the key ID */ if (!**argv) error("Invalid blank key ID"); key = strtol(*argv, &p, 10); if (*p) error("Invalid key ID format"); /* get the key description (of the form "x;x;x;x;:") */ ret = keyctl_describe_alloc(key, &buf); if (ret == -1) error("keyctl_describe_alloc failed: %m"); /* get the callout_info (which can supply options) */ ret = keyctl_read_alloc(KEY_SPEC_REQKEY_AUTH_KEY, (void **)&callout_info); if (ret == -1) error("Invalid key callout_info read: %m"); } else { if (argc != 2) usage(); ret = asprintf(&buf, "%s;-1;-1;0;%s", key_type, argv[0]); if (ret < 0) error("Error %m"); callout_info = argv[1]; } ret = 1; verbose("Key description: '%s'", buf); verbose("Callout info: '%s'", callout_info); p = strchr(buf, ';'); if (!p) error("Badly formatted key description '%s'", buf); ktlen = p - buf; /* make sure it's the type we are expecting */ if (ktlen != sizeof(key_type) - 1 || memcmp(buf, key_type, ktlen) != 0) error("Key type is not supported: '%*.*s'", ktlen, ktlen, buf); keyend = buf + ktlen + 1; /* the actual key description follows the last semicolon */ keyend = rindex(keyend, ';'); if (!keyend) error("Invalid key description: %s", buf); keyend++; if (memcmp(keyend, afsdb_query_type, sizeof(afsdb_query_type) - 1) != 0) error("Only 'afsdb' supported: %s", buf); name = keyend + sizeof(afsdb_query_type) - 1; verbose("Do AFS VL server query for:'%s' mask:'%s'", name, callout_info); parse_callout(callout_info, &ctx); /* Anything we create must fit into 1MiB buffer */ result = mmap(NULL, 1024 * 1024, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); if (result == MAP_FAILED) error("mmap: %m"); if (filec > 0) { filev[filec] = NULL; filep = filev; } if (kafs_init_lookup_context(&ctx) < 0) exit(1); if (kafs_read_config(filep, &ctx.report) < 0) exit(ctx.report.bad_config ? 3 : 1); /* Generate the payload */ switch (output_version) { case 0: r_end = kafs_generate_text_payload(result, name, &ttl, &ctx); break; case 1: default: r_end = kafs_generate_v1_payload(result, name, &ttl, &ctx); break; } if (!r_end) error("failed"); verbose("version %u %zu", output_version, r_end - result); if (dump_file) { int fd = open(dump_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd == -1) { perror(dump_file); exit(1); } if (write(fd, result, r_end - result) != r_end - result) { perror(dump_file); exit(1); } close(fd); } /* Set the key's expiry time from the minimum TTL encountered and then * pass the data to the key. */ if (!debug_mode) { if (ttl != UINT_MAX) { ret = keyctl_set_timeout(key, ttl); if (ret == -1) error("keyctl_set_timeout: %m"); } ret = keyctl_instantiate(key, result, r_end - result, 0); if (ret == -1) error("keyctl_instantiate: %m"); } verbose("Success (%zu bytes)", r_end - result); return 0; } src/dns_resolver.h000066400000000000000000000075741367270324000145440ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ /* DNS resolver interface definitions. * * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public Licence * as published by the Free Software Foundation; either version * 2 of the Licence, or (at your option) any later version. */ #ifndef _UAPI_LINUX_DNS_RESOLVER_H #define _UAPI_LINUX_DNS_RESOLVER_H #include /* * Type of payload. */ enum dns_payload_content_type { DNS_PAYLOAD_IS_SERVER_LIST = 0, /* List of servers, requested by srv=1 */ }; /* * Type of address that might be found in an address record. */ enum dns_payload_address_type { DNS_ADDRESS_IS_IPV4 = 0, /* 4-byte AF_INET address */ DNS_ADDRESS_IS_IPV6 = 1, /* 16-byte AF_INET6 address */ }; /* * Type of protocol used to access a server. */ enum dns_payload_protocol_type { DNS_SERVER_PROTOCOL_UNSPECIFIED = 0, DNS_SERVER_PROTOCOL_UDP = 1, /* Use UDP to talk to the server */ DNS_SERVER_PROTOCOL_TCP = 2, /* Use TCP to talk to the server */ }; /* * Source of record included in DNS resolver payload. */ enum dns_record_source { DNS_RECORD_UNAVAILABLE = 0, /* No source available (empty record) */ DNS_RECORD_FROM_CONFIG = 1, /* From local configuration data */ DNS_RECORD_FROM_DNS_A = 2, /* From DNS A or AAAA record */ DNS_RECORD_FROM_DNS_AFSDB = 3, /* From DNS AFSDB record */ DNS_RECORD_FROM_DNS_SRV = 4, /* From DNS SRV record */ DNS_RECORD_FROM_NSS = 5, /* From NSS */ NR__dns_record_source }; /* * Status of record included in DNS resolver payload. */ enum dns_lookup_status { DNS_LOOKUP_NOT_DONE = 0, /* No lookup has been made */ DNS_LOOKUP_GOOD = 1, /* Good records obtained */ DNS_LOOKUP_GOOD_WITH_BAD = 2, /* Good records, some decoding errors */ DNS_LOOKUP_BAD = 3, /* Couldn't decode results */ DNS_LOOKUP_GOT_NOT_FOUND = 4, /* Got a "Not Found" result */ DNS_LOOKUP_GOT_LOCAL_FAILURE = 5, /* Local failure during lookup */ DNS_LOOKUP_GOT_TEMP_FAILURE = 6, /* Temporary failure during lookup */ DNS_LOOKUP_GOT_NS_FAILURE = 7, /* Name server failure */ NR__dns_lookup_status }; /* * Header at the beginning of binary format payload. */ struct dns_payload_header { __u8 zero; /* Zero byte: marks this as not being text */ __u8 content; /* enum dns_payload_content_type */ __u8 version; /* Encoding version */ } __attribute__((packed)); /* * Header at the beginning of a V1 server list. This is followed directly by * the server records. Each server records begins with a struct of type * dns_server_list_v1_server. */ struct dns_server_list_v1_header { struct dns_payload_header hdr; __u8 source; /* enum dns_record_source */ __u8 status; /* enum dns_lookup_status */ __u8 nr_servers; /* Number of server records following this */ } __attribute__((packed)); /* * Header at the beginning of each V1 server record. This is followed by the * characters of the name with no NUL-terminator, followed by the address * records for that server. Each address record begins with a struct of type * struct dns_server_list_v1_address. */ struct dns_server_list_v1_server { __u16 name_len; /* Length of name (LE) */ __u16 priority; /* Priority (as SRV record) (LE) */ __u16 weight; /* Weight (as SRV record) (LE) */ __u16 port; /* UDP/TCP port number (LE) */ __u8 source; /* enum dns_record_source */ __u8 status; /* enum dns_lookup_status */ __u8 protocol; /* enum dns_payload_protocol_type */ __u8 nr_addrs; } __attribute__((packed)); /* * Header at the beginning of each V1 address record. This is followed by the * bytes of the address, 4 for IPV4 and 16 for IPV6. */ struct dns_server_list_v1_address { __u8 address_type; /* enum dns_payload_address_type */ } __attribute__((packed)); #endif /* _UAPI_LINUX_DNS_RESOLVER_H */ src/include/000077500000000000000000000000001367270324000132745ustar00rootroot00000000000000src/include/kafs/000077500000000000000000000000001367270324000142205ustar00rootroot00000000000000src/include/kafs/cellserv.h000066400000000000000000000077561367270324000162270ustar00rootroot00000000000000/* * kAFS config and cell database parser. * * Copyright (C) David Howells (dhowells@redhat.com) 2018 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #ifndef _KAFS_CELLSERV_H #define _KAFS_CELLSERV_H #include #include #include #include "reporting.h" struct kafs_profile; struct kafs_profile_parse; enum kafs_server_type { kafs_server_is_untyped, kafs_server_is_afs_vlserver, kafs_server_is_afs_ptserver, }; enum kafs_record_source { kafs_record_unavailable, kafs_record_from_config, kafs_record_from_dns_a, kafs_record_from_dns_afsdb, kafs_record_from_dns_srv, kafs_record_from_nss, nr__kafs_record_source }; enum kafs_lookup_status { kafs_lookup_not_done, kafs_lookup_good, kafs_lookup_good_with_bad, kafs_lookup_bad, kafs_lookup_got_not_found, kafs_lookup_got_local_failure, kafs_lookup_got_temp_failure, kafs_lookup_got_ns_failure, nr__kafs_lookup_status }; struct kafs_server_addr { union { struct sockaddr_in sin; struct sockaddr_in6 sin6; }; }; struct kafs_server { char *name; struct kafs_server_addr *addrs; unsigned int max_addrs; unsigned int nr_addrs; unsigned short port; unsigned short pref; unsigned short weight; unsigned char protocol; bool borrowed_name; bool borrowed_addrs; enum kafs_record_source source : 8; enum kafs_lookup_status status : 8; enum kafs_server_type type : 8; }; struct kafs_server_list { unsigned int nr_servers; unsigned int max_servers; unsigned int ttl; enum kafs_record_source source : 8; enum kafs_lookup_status status : 8; struct kafs_server *servers; }; struct kafs_cell { char *name; char *desc; char *realm; bool use_dns; bool show_cell; bool borrowed_name; bool borrowed_desc; bool borrowed_realm; struct kafs_server_list *vlservers; }; struct kafs_cell_db { unsigned int nr_cells; struct kafs_cell *cells[]; }; struct kafs_lookup_context { struct kafs_report report; struct __res_state res; bool want_ipv4_addrs; bool want_ipv6_addrs; bool no_vls_afsdb; bool no_vls_srv; bool no_vl_host; }; /* * object.c */ extern int kafs_init_lookup_context(struct kafs_lookup_context *ctx); extern void kafs_clear_lookup_context(struct kafs_lookup_context *ctx); extern struct kafs_server_list *kafs_alloc_server_list(struct kafs_report *report); extern void kafs_free_server_list(struct kafs_server_list *sl); extern void kafs_free_cell(struct kafs_cell *cell); extern void kafs_transfer_addresses(struct kafs_server *to, const struct kafs_server *from); extern int kafs_transfer_server_list(struct kafs_server_list *to, const struct kafs_server_list *from); extern void kafs_transfer_cell(struct kafs_cell *to, const struct kafs_cell *from); /* * cellserv.c */ extern struct kafs_cell_db *kafs_cellserv_parse_conf(const struct kafs_profile *prof, struct kafs_report *report); extern void kafs_cellserv_dump(const struct kafs_cell_db *db); extern const char *kafs_record_source(enum kafs_record_source source); extern const char *kafs_lookup_status(enum kafs_lookup_status status); extern void kafs_dump_cell(const struct kafs_cell *cell); /* * dns_lookup.c */ extern int kafs_dns_lookup_addresses(struct kafs_server_list *sl, struct kafs_lookup_context *ctx); extern int kafs_dns_lookup_vlservers(struct kafs_server_list *vsl, const char *cell_name, struct kafs_lookup_context *ctx); /* * cell_lookup.c */ extern struct kafs_profile kafs_config_profile; extern struct kafs_cell_db *kafs_cellserv_db; extern const char *kafs_this_cell; extern const char *kafs_sysname; extern int kafs_read_config(const char *const *files, struct kafs_report *report); extern struct kafs_cell *kafs_lookup_cell(const char *cell_name, struct kafs_lookup_context *ctx); #endif /* _KAFS_CELLSERV_H */ src/include/kafs/profile.h000066400000000000000000000101151367270324000160270ustar00rootroot00000000000000/* * Kerberos-style profile file parser. * * Copyright (C) 2018 David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #ifndef _KAFS_PROFILE_H #define _KAFS_PROFILE_H #include #include "reporting.h" enum kafs_profile_value_type { kafs_profile_value_is_list, kafs_profile_value_is_string, }; struct kafs_profile { enum kafs_profile_value_type type : 8; bool final; bool dummy; unsigned int nr_relations; unsigned int line; const char *file; char *name; char *value; struct kafs_profile *parent; struct kafs_profile **relations; }; extern void kafs_profile_dump(const struct kafs_profile *p, unsigned int depth); extern int kafs_profile_parse_file(struct kafs_profile *prof, const char *filename, struct kafs_report *report); extern int kafs_profile_parse_dir(struct kafs_profile *prof, const char *dirname, struct kafs_report *report); extern const struct kafs_profile * kafs_profile_find_first_child(const struct kafs_profile *prof, enum kafs_profile_value_type type, const char *name, struct kafs_report *report); typedef int (*kafs_profile_iterator)(const struct kafs_profile *child, void *data, struct kafs_report *report); extern int kafs_profile_iterate(const struct kafs_profile *prof, enum kafs_profile_value_type type, const char *name, kafs_profile_iterator iterator, void *data, struct kafs_report *report); extern int kafs_profile_count(const struct kafs_profile *prof, enum kafs_profile_value_type type, const char *name, unsigned int *_nr); /* * Constant matching. */ struct kafs_constant_table { const char *name; int value; }; extern int kafs_lookup_constant2(const struct kafs_constant_table tbl[], size_t tbl_size, const char *name, int not_found); #define kafs_lookup_constant(t, n, nf) \ kafs_lookup_constant2(t, sizeof(t)/sizeof(t[0]), (n), (nf)) extern int kafs_lookup_bool(const char *name, int not_found); /* * Convenience relation parsers. */ static inline const char *kafs_profile_get_string(const struct kafs_profile *prof, const char *name, struct kafs_report *report) { const struct kafs_profile *p; p = kafs_profile_find_first_child(prof, kafs_profile_value_is_string, name, report); return p ? p->value : NULL; } static inline bool kafs_profile_get_bool(const struct kafs_profile *prof, const char *name, struct kafs_report *report) { const struct kafs_profile *p; int tmp; p = kafs_profile_find_first_child(prof, kafs_profile_value_is_string, name, report); if (!p || !p->value) return false; tmp = kafs_lookup_bool(p->value, -1); if (tmp == -1) { report->error("%s:%u: Invalid bool value", p->file, p->line); return false; } return tmp; } static inline int kafs_profile_iterate_list(const struct kafs_profile *prof, const char *name, kafs_profile_iterator iterator, void *data, struct kafs_report *report) { return kafs_profile_iterate(prof, kafs_profile_value_is_list, name, iterator, data, report); } static inline int kafs_profile_count_list(const struct kafs_profile *prof, const char *name, unsigned int *_nr) { return kafs_profile_count(prof, kafs_profile_value_is_list, name, _nr); } static inline int kafs_profile_iterate_strings(const struct kafs_profile *prof, const char *name, kafs_profile_iterator iterator, void *data, struct kafs_report *report) { return kafs_profile_iterate(prof, kafs_profile_value_is_string, name, iterator, data, report); } static inline int kafs_profile_count_strings(const struct kafs_profile *prof, const char *name, unsigned int *_nr) { return kafs_profile_count(prof, kafs_profile_value_is_string, name, _nr); } #endif /* _KAFS_PROFILE_H */ src/include/kafs/reporting.h000066400000000000000000000016031367270324000164020ustar00rootroot00000000000000/* * Error reporting context. * * Copyright (C) David Howells (dhowells@redhat.com) 2018 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #ifndef _KAFS_REPORTING_H #define _KAFS_REPORTING_H struct kafs_report { void (*error)(const char *fmt, ...) __attribute__((format(printf, 1, 2))); void (*verbose)(const char *fmt, ...) __attribute__((format(printf, 1, 2))); void (*verbose2)(const char *fmt, ...) __attribute__((format(printf, 1, 2))); const char *what; int line; bool bad_config; /* T if bad config encountered */ bool bad_error; /* T if fatal system error encountered */ bool abandon_alloc; /* T to not clean up on error */ }; #endif /* _KAFS_REPORTING_H */ src/kafs-check-config.c000066400000000000000000000065211367270324000152630ustar00rootroot00000000000000/* * kAFS filesystem configuration checker. * * Copyright (C) David Howells (dhowells@redhat.com) 2018 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #include #include #include #include #include #include #include static void error_report(const char *fmt, ...) { va_list va; va_start(va, fmt); vfprintf(stderr, fmt, va); fputc('\n', stderr); va_end(va); } static void verbose(const char *fmt, ...) { va_list va; va_start(va, fmt); printf("[V] "); vprintf(fmt, va); putchar('\n'); va_end(va); } static __attribute__((noreturn)) void usage(const char *prog) { fprintf(stderr, "Usage: %s [-46PDvv] [-c ]* [-N ] []*\n", prog); fprintf(stderr, "\n"); fprintf(stderr, "Where restrictions are one or more of:\n"); fprintf(stderr, "\t-N dns\n"); fprintf(stderr, "\t-N vls-afsdb\n"); fprintf(stderr, "\t-N vls-srv\n"); fprintf(stderr, "\t-N vls-all\n"); fprintf(stderr, "\t-N vl-host\n"); exit(2); } int main(int argc, char *argv[]) { struct kafs_lookup_context ctx = { .report.error = error_report, .want_ipv4_addrs = true, .want_ipv6_addrs = true, }; const char *filev[10], **filep = NULL; bool dump_profile = false, dump_db = false; int opt, filec = 0; if (argc > 1 && strcmp(argv[1], "--help") == 0) usage(argv[0]); while (opt = getopt(argc, argv, "46PDc:vN:"), opt != -1) { switch (opt) { case 'c': if (filec >= 9) { fprintf(stderr, "Max 9 files\n"); exit(2); } filev[filec++] = optarg; break; case 'v': if (!ctx.report.verbose) ctx.report.verbose = verbose; else ctx.report.verbose2 = verbose; break; case 'P': dump_profile = true; break; case 'D': dump_db = true; break; case '4': ctx.want_ipv4_addrs = true; ctx.want_ipv6_addrs = false; break; case '6': ctx.want_ipv4_addrs = false; ctx.want_ipv6_addrs = true; break; case 'N': if (strcmp(optarg, "vl-srv") == 0) { ctx.no_vls_srv = true; } else if (strcmp(optarg, "vl-afsdb") == 0) { ctx.no_vls_afsdb = true; } else if (strcmp(optarg, "vl-all") == 0) { ctx.no_vls_srv = true; ctx.no_vls_afsdb = true; } else if (strcmp(optarg, "vl-host") == 0) { ctx.no_vl_host = true; } else if (strcmp(optarg, "dns") == 0) { ctx.no_vls_srv = true; ctx.no_vls_afsdb = true; ctx.no_vl_host = true; } else { fprintf(stderr, "Unknown restriction '-N %s'\n", optarg); usage(argv[0]); } break; default: usage(argv[0]); } } argc -= optind; argv += optind; if (filec > 0) { filev[filec] = NULL; filep = filev; } if (kafs_init_lookup_context(&ctx) < 0) exit(1); if (kafs_read_config(filep, &ctx.report) < 0) exit(ctx.report.bad_config ? 3 : 1); if (dump_profile) kafs_profile_dump(&kafs_config_profile, 0); if (dump_db) kafs_cellserv_dump(kafs_cellserv_db); for (; *argv; argv++) { struct kafs_cell *cell; cell = kafs_lookup_cell(*argv, &ctx); if (cell) { printf("\n"); printf("=== Found cell %s ===\n", cell->name); kafs_dump_cell(cell); } } kafs_clear_lookup_context(&ctx); return 0; } src/lib_cell_lookup.c000066400000000000000000000134061367270324000151570ustar00rootroot00000000000000/* * Cell database access. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #include #include #include #include #include #include #include #include static const char *const kafs_std_config[] = { ETCDIR "/kafs/client.conf", NULL }; struct kafs_profile kafs_config_profile = { .name = "" }; struct kafs_cell_db *kafs_cellserv_db; const char *kafs_this_cell; const char *kafs_sysname; #define verbose(r, fmt, ...) \ do { \ if ((r)->verbose) \ (r)->verbose(fmt, ## __VA_ARGS__); \ } while(0) /* * Allocate a cell record. */ struct kafs_cell *kafs_alloc_cell(const char *cell_name, struct kafs_lookup_context *ctx) { struct kafs_cell *cell; cell = calloc(1, sizeof(*cell)); if (!cell) goto error; cell->name = strdup(cell_name); if (!cell->name) goto error; return cell; error: ctx->report.error("%m"); return NULL; } /* * Read the [defaults] section. */ static void kafs_read_defaults(struct kafs_profile *prof, struct kafs_report *report) { const struct kafs_profile *def; const char *p; def = kafs_profile_find_first_child(prof, kafs_profile_value_is_list, "defaults", report); if (!def) { verbose(report, "Cannot find [defaults] section"); return; } /* Find the current cell name (thiscell = ) */ p = kafs_profile_get_string(def, "thiscell", report); if (p) kafs_this_cell = p; /* Find the @sys substitutions (sysname = ...) */ p = kafs_profile_get_string(def, "sysname", report); if (p) kafs_sysname = p; } /* * Read the configuration and initialise the cell database. */ int kafs_read_config(const char *const *files, struct kafs_report *report) { if (!files) files = kafs_std_config; for (; *files; files++) if (kafs_profile_parse_file(&kafs_config_profile, *files, report) == -1) return -1; kafs_cellserv_db = kafs_cellserv_parse_conf(&kafs_config_profile, report); if (!kafs_cellserv_db) return -1; kafs_read_defaults(&kafs_config_profile, report); return 0; } /* * Deal with an unconfigured cell. */ static int kafs_unconfigured_cell(struct kafs_cell *cell, struct kafs_lookup_context *ctx) { struct kafs_server_list *vsl; verbose(&ctx->report, "%s: Cell not found in config", cell->name); vsl = kafs_alloc_server_list(&ctx->report); if (!vsl) return -1; cell->vlservers = vsl; if (kafs_dns_lookup_vlservers(vsl, cell->name, ctx) < 0 || kafs_dns_lookup_addresses(vsl, ctx) < 0) return -1; verbose(&ctx->report, "DNS query AFSDB RR results:%u ttl:%u", vsl->nr_servers, vsl->ttl); return 0; } /* * Look up a cell in configuration and DNS. * * The rules are: * * (*) Look up the cell in the configuration first. * * (*) If there's no cell in the config, we have to try and build it entirely * from the DNS. * * (*) Else: * * (*) We look at the configured no_dns setting: * * (*) If true, we use the list of servers listed in the config * * (*) If false, we try to replace that with one derived from the DNS. * * (*) For each server: * * (*) we try to look up a list of addresses in NSS/DNS. * * (*) If that fails, we use the list of addresses from the config. */ struct kafs_cell *kafs_lookup_cell(const char *cell_name, struct kafs_lookup_context *ctx) { const struct kafs_server_list *cvsl; struct kafs_server_list *vsl; const struct kafs_cell *conf_cell; struct kafs_cell *cell; unsigned int i, j; if (!kafs_cellserv_db && kafs_read_config(NULL, &ctx->report) < 0) return NULL; cell = kafs_alloc_cell(cell_name, ctx); if (!cell) return NULL; for (i = 0; i < kafs_cellserv_db->nr_cells; i++) { conf_cell = kafs_cellserv_db->cells[i]; if (strcmp(cell_name, conf_cell->name) == 0) goto cell_is_configured; } if (kafs_unconfigured_cell(cell, ctx) < 0) goto error; return cell; /* Deal with the case where we have a configuration. */ cell_is_configured: verbose(&ctx->report, "%s: Found cell in config", cell_name); kafs_transfer_cell(cell, conf_cell); vsl = kafs_alloc_server_list(&ctx->report); if (!vsl) goto error; cell->vlservers = vsl; /* The DNS overrides the configuration if indicated. */ if (conf_cell->use_dns) { verbose(&ctx->report, "Query DNS for server list"); if (kafs_dns_lookup_vlservers(vsl, cell_name, ctx) < 0) goto error; verbose(&ctx->report, "Looked up %u VL servers [%s, %s]", vsl->nr_servers, kafs_lookup_status(vsl->status), kafs_record_source(vsl->source)); } /* If we didn't get any servers, copy the server list from the * configuration. */ if (vsl->nr_servers == 0) { verbose(&ctx->report, "Use configured server list"); if (kafs_transfer_server_list(vsl, conf_cell->vlservers) < 0) goto error; } /* Try and look up addresses for all the servers in the list. */ if (kafs_dns_lookup_addresses(vsl, ctx) < 0) goto error; /* Borrow addresses from the config for any server that didn't find any * in the DNS. */ cvsl = conf_cell->vlservers; if (cvsl) { for (i = 0; i < vsl->nr_servers; i++) { struct kafs_server *srv = &vsl->servers[i]; if (srv->nr_addrs) continue; verbose(&ctx->report, "Borrow addresses for '%s'", srv->name); for (j = 0; j < cvsl->nr_servers; j++) { const struct kafs_server *csrv = &cvsl->servers[j]; if (strcmp(srv->name, csrv->name) == 0) { verbose(&ctx->report, "From '%s' %u", csrv->name, csrv->nr_addrs); kafs_transfer_addresses(srv, csrv); break; } } } } return cell; error: if (!ctx->report.abandon_alloc) kafs_free_cell(cell); return NULL; } src/lib_cellserv.c000066400000000000000000000236731367270324000144750ustar00rootroot00000000000000/* * Parse the profile tree into a cell server database * * Copyright (C) David Howells (dhowells@redhat.com) 2018 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #define _GNU_SOURCE #include #include #include #include #include #include #include "dns_resolver.h" #define report_error(r, fmt, ...) \ ({ \ r->error(fmt, ## __VA_ARGS__); \ -1; \ }) #define parse_error(r, fmt, ...) \ ({ \ r->bad_config = true; \ r->error("%s:%u: " fmt, r->what, r->line, ## __VA_ARGS__); \ -1; \ }) #define verbose(r, fmt, ...) \ do { \ if (r->verbose) \ r->verbose(fmt, ## __VA_ARGS__); \ } while(0) #define verbose2(r, fmt, ...) \ do { \ if (r->verbose2) \ r->verbose2(fmt, ## __VA_ARGS__); \ } while(0) /* * Parse an address. */ static int cellserv_parse_address(const struct kafs_profile *child, void *data, struct kafs_report *report) { struct kafs_server *server = data; struct kafs_server_addr *addr = &server->addrs[server->nr_addrs]; const char *v = child->value; if (server->nr_addrs >= server->max_addrs) { report_error(report, "%s: Address list overrun", server->name); return 0; } if (inet_pton(AF_INET, v, &addr->sin.sin_addr) == 1) { addr->sin.sin_family = AF_INET; addr->sin.sin_port = htons(server->port); server->nr_addrs++; return 0; } if (v[0] == '[') { char *p; v++; p = strchr(v, ']'); if (!p || p[1]) goto invalid; p[0] = 0; } if (inet_pton(AF_INET6, v, &addr->sin6.sin6_addr) == 1) { addr->sin6.sin6_family = AF_INET6; addr->sin6.sin6_port = htons(server->port); server->nr_addrs++; return 0; } invalid: parse_error(report, "%s:%u: Invalid address '%s'", child->file, child->line, child->value); return 0; } /* * Parse a server definition. */ static int cellserv_parse_server(const struct kafs_profile *child, void *data, struct kafs_report *report) { struct kafs_server_list *vsl = data; struct kafs_server *server = &vsl->servers[vsl->nr_servers]; unsigned long tmp; unsigned int max_addrs = 0; const char *p; char *q; if (vsl->nr_servers >= vsl->max_servers) { report_error(report, "%s: Server list overrun", server->name); return 0; } memset(server, 0, sizeof(*server)); server->source = kafs_record_from_config; /* Strip off any protocol indicator */ server->name = child->name; if (strncmp(server->name, "udp/", 4) == 0) { server->protocol = DNS_SERVER_PROTOCOL_UDP; server->name += 4; } else if (strncmp(server->name, "tcp/", 4) == 0) { server->protocol = DNS_SERVER_PROTOCOL_TCP; server->name += 4; } if (!server->name[0]) return 0; /* Strip any port number and square brackets */ if (server->name[0] == '[') { server->name++; p = strchr(server->name, ']'); if (!*p) return 0; *(char *)p = 0; p++; if (*p) { if (*p != ':') return 0; p++; goto extract_port; } } /* Look for foo.com:port or 1.2.3.4:port, but dodge 1:2:3:4 */ p = strchr(server->name, ':'); if (!p) goto no_port; *(char *)p = 0; p++; if (strchr(p, ':')) goto no_port; extract_port: tmp = strtoul(p, &q, 0); if (*q) goto unparseable; if (tmp > 65536) goto unparseable; server->port = tmp; no_port: p = kafs_profile_get_string(child, "port", report); if (p) { tmp = strtoul(p, &q, 0); if (*q) goto unparseable; if (tmp > 65536) goto unparseable; server->port = tmp; } /* Generate a list of addresses */ if (kafs_profile_count_strings(child, "address", &max_addrs) < 0) return -1; server->addrs = calloc(max_addrs, sizeof(struct kafs_server)); if (!server->addrs) return -1; server->max_addrs = max_addrs; if (kafs_profile_iterate_strings(child, "address", cellserv_parse_address, server, report) < 0) return -1; p = kafs_profile_get_string(child, "type", report); if (p) { if (strcmp(p, "vlserver") == 0) server->type = kafs_server_is_afs_vlserver; else if (strcmp(p, "ptserver") == 0) server->type = kafs_server_is_afs_ptserver; else fprintf(stderr, "Unknown type '%s'\n", p); } vsl->nr_servers++; return 0; unparseable: parse_error(report, "%s:%u: Invalid address\n", child->file, child->line); return 0; } /* * Find any Volume Location servers listed for a cell. */ static int kafs_cellserv_parse_vl(const struct kafs_profile *child, struct kafs_cell *cell, struct kafs_report *report) { const struct kafs_profile *servers; struct kafs_server_list *vsl; unsigned int max_servers = 0; /* Find any Volume Location servers listed for that cell */ servers = kafs_profile_find_first_child(child, kafs_profile_value_is_list, "servers", report); if (!servers) { verbose(report, "%s: No servers list", child->name); return 0; } if (kafs_profile_count_list(servers, NULL, &max_servers) < 0) return -1; vsl = calloc(1, sizeof(*vsl)); if (!vsl) return -1; vsl->source = kafs_record_from_config; cell->vlservers = vsl; vsl->servers = calloc(max_servers, sizeof(struct kafs_server)); if (!vsl->servers) return -1; vsl->max_servers = max_servers; return kafs_profile_iterate_list(servers, NULL, cellserv_parse_server, vsl, report); } /* * Parse a cell definition. */ static int kafs_cellserv_parse_cell(const struct kafs_profile *child, void *data, struct kafs_report *report) { struct kafs_cell_db *db = data; struct kafs_cell *cell; cell = calloc(1, sizeof(*cell)); if (!cell) return -1; cell->name = child->name; cell->show_cell = kafs_profile_get_bool(child, "show_cell", report); cell->use_dns = kafs_profile_get_bool(child, "use_dns", report); cell->desc = (char *)kafs_profile_get_string(child, "description", report); cell->realm = (char *)kafs_profile_get_string(child, "kerberos_realm", report); cell->borrowed_name = true; cell->borrowed_desc = true; cell->borrowed_realm = true; verbose2(report, "CELL: %s: %s", cell->name, cell->desc); db->cells[db->nr_cells] = cell; db->nr_cells++; return kafs_cellserv_parse_vl(child, cell, report); } /* * Extract cell information from a kafs_profile parse tree. */ struct kafs_cell_db *kafs_cellserv_parse_conf(const struct kafs_profile *prof, struct kafs_report *report) { const struct kafs_profile *cells; struct kafs_cell_db *db; unsigned int nr_cells = 0; cells = kafs_profile_find_first_child(prof, kafs_profile_value_is_list, "cells", report); if (!cells) { report_error(report, "Cannot find [cells] section"); return NULL; } if (kafs_profile_count_list(cells, NULL, &nr_cells) < 0) return NULL; db = calloc(1, sizeof(*db) + nr_cells * sizeof(struct kafs_cell *)); if (!db) return NULL; if (!nr_cells) return db; if (kafs_profile_iterate_list(cells, NULL, kafs_cellserv_parse_cell, db, report) == -1) return NULL; return db; } static const char *const kafs_record_sources[nr__kafs_record_source] = { [kafs_record_unavailable] = "unavailable", [kafs_record_from_config] = "config", [kafs_record_from_dns_a] = "A", [kafs_record_from_dns_afsdb] = "AFSDB", [kafs_record_from_dns_srv] = "SRV", [kafs_record_from_nss] = "nss", }; static const char *const kafs_lookup_statuses[nr__kafs_lookup_status] = { [kafs_lookup_not_done] = "no-lookup", [kafs_lookup_good] = "good", [kafs_lookup_good_with_bad] = "good/bad", [kafs_lookup_bad] = "bad", [kafs_lookup_got_not_found] = "not-found", [kafs_lookup_got_local_failure] = "local-failure", [kafs_lookup_got_temp_failure] = "temp-failure", [kafs_lookup_got_ns_failure] = "ns-failure", }; const char *kafs_record_source(enum kafs_record_source source) { if (source >= nr__kafs_record_source) return "unknown"; return kafs_record_sources[source] ?: "unknown"; } const char *kafs_lookup_status(enum kafs_lookup_status status) { if (status >= nr__kafs_lookup_status) return "unknown"; return kafs_lookup_statuses[status] ?: "unknown"; } /* * Dump a server set. */ void kafs_dump_server_list(const struct kafs_server_list *sl, const char *server_type) { unsigned int j, k; const char *p; char buf[100]; for (j = 0; j < sl->nr_servers; j++) { const struct kafs_server *srv = &sl->servers[j]; printf(" - %s %s [%s; %s]\n", server_type, srv->name, kafs_lookup_status(srv->status), kafs_record_source(srv->source)); if (srv->type) printf(" - %s\n", srv->type == kafs_server_is_afs_vlserver ? "VLServer" : "PTServer"); if (srv->protocol) printf(" - %s\n", srv->protocol == DNS_SERVER_PROTOCOL_UDP ? "udp" : "tcp"); if (srv->port || srv->pref || srv->weight) printf(" - port %u, pref %u, weight %u\n", srv->port, srv->pref, srv->weight); for (k = 0; k < srv->nr_addrs; k++) { const struct kafs_server_addr *addr = &srv->addrs[k]; switch (addr->sin.sin_family) { case AF_INET: p = inet_ntop(AF_INET, &addr->sin.sin_addr, buf, sizeof(buf)); break; case AF_INET6: p = inet_ntop(AF_INET6, &addr->sin6.sin6_addr, buf, sizeof(buf)); break; default: p = NULL; break; } if (p) printf(" - address %s\n", p); } } } /* * Dump a cell. */ void kafs_dump_cell(const struct kafs_cell *cell) { const struct kafs_server_list *vsl = cell->vlservers; if (!cell->use_dns) printf(" - use-dns=no\n"); if (!cell->show_cell) printf(" - show-cell=no\n"); if (vsl) { printf(" - status: %s, from %s\n", kafs_lookup_status(vsl->status), kafs_record_source(vsl->source)); kafs_dump_server_list(vsl, "VLSERVER"); } } /* * Dump the parsed afs database. */ void kafs_cellserv_dump(const struct kafs_cell_db *db) { unsigned int i; for (i = 0; i < db->nr_cells; i++) { const struct kafs_cell *cell = db->cells[i]; printf("CELL %s\n", cell->name); kafs_dump_cell(cell); } } src/lib_dns_lookup.c000066400000000000000000000350641367270324000150300ustar00rootroot00000000000000/* * Build a cell VL address set based on DNS records. * * Copyright (C) Wang Lei (wang840925@gmail.com) 2010 * Authors: Wang Lei (wang840925@gmail.com) * * Copyright (C) David Howells (dhowells@redhat.com) 2018 * * This is a userspace tool for querying AFSDB RR records in the DNS on behalf * of the kernel, and converting the VL server addresses to IPv4 format so that * they can be used by the kAFS filesystem. * * As some function like res_init() should use the static liberary, which is a * bug of libresolv, that is the reason for cifs.upcall to reimplement. * * To use this program, you must tell /sbin/request-key how to invoke it. You * need to have the keyutils package installed and something like the following * lines added to your /etc/request-key.conf file: * * #OP TYPE DESCRIPTION CALLOUT INFO PROGRAM ARG1 ARG2 ARG3 ... * ====== ============ =========== ============ ========================== * create dns_resolver afsdb:* * /sbin/key.dns_resolver %k * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include "dns_resolver.h" #define AFS_VL_PORT 7003 /* volume location service port */ #define verbose(fmt, ...) \ do { \ if (ctx->report.verbose) \ ctx->report.verbose(fmt, ## __VA_ARGS__); \ } while(0) /* * Perform address resolution on a hostname and add the resulting address as a * string to the list of payload segments. */ static int kafs_resolve_addrs(struct kafs_server *server, int socktype, struct kafs_lookup_context *ctx) { struct kafs_server_addr *addr; struct addrinfo hints, *addrs, *ai; int ret, count = 0; verbose("Resolve '%s'", server->name); server->source = kafs_record_from_nss; memset(&hints, 0, sizeof(hints)); hints.ai_socktype = socktype; if (ctx->want_ipv4_addrs && !ctx->want_ipv6_addrs) hints.ai_family = AF_INET; else if (ctx->want_ipv6_addrs && !ctx->want_ipv4_addrs) hints.ai_family = AF_INET6; /* resolve name to ip */ ret = getaddrinfo(server->name, NULL, &hints, &addrs); if (ret) { verbose("%s: getaddrinfo() = %d", server->name, ret); switch (ret) { case EAI_MEMORY: case EAI_SYSTEM: ctx->report.error("%s: getaddrinfo(): %m", server->name); goto system_error; case EAI_FAMILY: case EAI_SOCKTYPE: ctx->report.bad_error = true; server->status = kafs_lookup_got_local_failure; goto fail; default: server->status = kafs_lookup_got_local_failure; /* Fall through. */ fail: ctx->report.error("%s: %s", server->name, gai_strerror(ret)); return 0; case EAI_FAIL: #ifdef EAI_NODATA case EAI_NODATA: #endif case EAI_NONAME: case EAI_SERVICE: server->status = kafs_lookup_got_not_found; goto fail; case EAI_AGAIN: server->status = kafs_lookup_got_temp_failure; goto fail; } } for (ai = addrs; ai; ai = ai->ai_next) count++; server->addrs = calloc(count, sizeof(*addr)); if (!server->addrs) { ctx->report.error("%m"); goto system_error; } server->max_addrs = count; server->source = kafs_record_from_nss; server->status = kafs_lookup_good; for (ai = addrs; ai; ai = ai->ai_next) { addr = &server->addrs[server->nr_addrs]; verbose("RR: %x,%x,%x,%x,%x,%s", ai->ai_flags, ai->ai_family, ai->ai_socktype, ai->ai_protocol, ai->ai_addrlen, ai->ai_canonname); /* convert address to string */ switch (ai->ai_family) { case AF_INET: if (!ctx->want_ipv4_addrs) continue; memcpy(&addr->sin, (struct sockaddr_in *)ai->ai_addr, sizeof(addr->sin)); server->nr_addrs++; break; case AF_INET6: if (!ctx->want_ipv6_addrs) continue; memcpy(&addr->sin6, (struct sockaddr_in *)ai->ai_addr, sizeof(addr->sin6)); server->nr_addrs++; break; default: verbose("Address of unknown family %u", ai->ai_family); continue; } } freeaddrinfo(addrs); return 0; system_error: ctx->report.bad_error = true; return -1; } /* * Go through all the servers records and look up addresses for them. */ int kafs_dns_lookup_addresses(struct kafs_server_list *ss, struct kafs_lookup_context *ctx) { struct kafs_server *server; unsigned int i; int ret; if (ss) { verbose("NR_SERVERS %u", ss->nr_servers); if (ctx->no_vl_host) { verbose("Use of DNS for FS server lookup is disabled."); return 0; } for (i = 0; i < ss->nr_servers; i++) { server = &ss->servers[i]; /* Turn the hostname into IP addresses */ ret = kafs_resolve_addrs(server, SOCK_DGRAM, ctx); if (ret) verbose("AFSDB RR can't resolve. subtype:1, server name:%s", server->name); else verbose("NR_ADDRS %u", server->nr_addrs); } } return 0; } /* * Convert the outcome of an AFSDB record lookup into a set of server records. */ static int kafs_parse_afsdb(struct kafs_server_list *vsl, const char *cell_name, unsigned short subtype, ns_msg handle, ns_sect section, struct kafs_lookup_context *ctx) { struct kafs_server *server; unsigned int rr_ttl, max_servers = 0, i; ns_rr rr; char buf[MAXDNAME]; int rrnum, rr_subtype; verbose("AFSDB RR count is %d", ns_msg_count(handle, section)); /* Count the number of afsdb records */ for (rrnum = 0; rrnum < ns_msg_count(handle, section); rrnum++) { if (ns_parserr(&handle, section, rrnum, &rr)) { ctx->report.error("%s: afsdb parse failed", cell_name); continue; } if (ns_rr_type(rr) != ns_t_afsdb) continue; rr_subtype = ns_get16(ns_rr_rdata(rr)); if (rr_subtype != subtype) continue; max_servers++; } verbose("NR_SERVER %u", max_servers); vsl->max_servers = max_servers; vsl->servers = calloc(max_servers, sizeof(struct kafs_server)); if (!vsl->servers) goto system_error; /* Look at all the resource records in this section. */ for (rrnum = 0; rrnum < ns_msg_count(handle, section); rrnum++) { server = &vsl->servers[vsl->nr_servers]; /* Expand the resource record number rrnum into rr. */ if (ns_parserr(&handle, section, rrnum, &rr)) { ctx->report.error("%s: afsdb parse failed", cell_name); vsl->status = kafs_lookup_bad; continue; } /* We're only interested in AFSDB records */ if (ns_rr_type(rr) != ns_t_afsdb) continue; rr_subtype = ns_get16(ns_rr_rdata(rr)); if (rr_subtype != subtype) continue; /* Expand the name server's domain name */ if (ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), ns_rr_rdata(rr) + 2, buf, MAXDNAME) < 0) { ctx->report.error("%s: afsdb uncompress failed", cell_name); vsl->status = kafs_lookup_bad; continue; } rr_ttl = ns_rr_ttl(rr); if (vsl->ttl > rr_ttl) vsl->ttl = rr_ttl; /* Check the domain name we've just unpacked and add it to * the list of VL servers if it is not a duplicate. * If it is a duplicate, just ignore it. */ for (i = 0; i < vsl->nr_servers; i++) if (strcasecmp(buf, vsl->servers[i].name) == 0) continue; server->name = strdup(buf); if (!server->name) goto system_error; server->port = AFS_VL_PORT; server->protocol = DNS_SERVER_PROTOCOL_UDP; verbose("SERVER[%u] %s", vsl->nr_servers, server->name); vsl->nr_servers++; } if (vsl->nr_servers > 0 && vsl->status == kafs_lookup_bad) vsl->status = kafs_lookup_good_with_bad; if (vsl->nr_servers == 0 && vsl->status == kafs_lookup_good_with_bad) vsl->status = kafs_lookup_got_not_found; return 0; system_error: ctx->report.bad_error = true; ctx->report.error("%m"); return -1; } /* * Look up an AFSDB record to get the VL server addresses. */ static int dns_query_AFSDB(struct kafs_server_list *vsl, const char *cell_name, unsigned short subtype, struct kafs_lookup_context *ctx) { int response_len; /* buffer length */ ns_msg handle; /* handle for response message */ union { HEADER hdr; u_char buf[NS_PACKETSZ]; } response; /* response buffers */ verbose("Get AFSDB RR for cell name:'%s'", cell_name); /* query the dns for an AFSDB resource record */ response_len = res_nquery(&ctx->res, cell_name, ns_c_in, ns_t_afsdb, response.buf, sizeof(response)); if (response_len < 0) { ctx->report.error("%s: %s", cell_name, hstrerror(h_errno)); switch (h_errno) { case HOST_NOT_FOUND: case NO_DATA: default: vsl->status = kafs_lookup_got_not_found; break; case NO_RECOVERY: vsl->status = kafs_lookup_got_ns_failure; break; case TRY_AGAIN: vsl->status = kafs_lookup_got_temp_failure; break; } return 0; } vsl->source = kafs_record_from_dns_afsdb; if (ns_initparse(response.buf, response_len, &handle) < 0) { ctx->report.error("%s: ns_initparse: %s", cell_name, hstrerror(h_errno)); vsl->status = kafs_lookup_bad; return 0; } /* look up the hostnames we've obtained to get the actual addresses */ vsl->status = kafs_lookup_good; return kafs_parse_afsdb(vsl, cell_name, subtype, handle, ns_s_an, ctx); } /* * Convert the outcome of an SRV record lookup into a set of server records. */ static int kafs_parse_srv(struct kafs_server_list *vsl, const char *domain_name, ns_msg handle, ns_sect section, enum dns_payload_protocol_type protocol, struct kafs_lookup_context *ctx) { struct kafs_server *server; unsigned int max_servers = 0, rr_ttl, i; ns_rr rr; char buf[MAXDNAME]; int rrnum; verbose("SRV RR count is %d", ns_msg_count(handle, section)); /* Count the number of srv records */ for (rrnum = 0; rrnum < ns_msg_count(handle, section); rrnum++) { if (ns_parserr(&handle, section, rrnum, &rr)) { ctx->report.error("%s: ns_parserr", domain_name); continue; } if (ns_rr_type(rr) != ns_t_srv) continue; max_servers++; } verbose("NR_SERVER %u", max_servers); vsl->max_servers = max_servers; vsl->servers = calloc(max_servers, sizeof(struct kafs_server)); if (!vsl->servers) goto system_error; for (rrnum = 0; rrnum < ns_msg_count(handle, section); rrnum++) { server = &vsl->servers[vsl->nr_servers]; /* Expand the resource record number rrnum into rr. */ if (ns_parserr(&handle, section, rrnum, &rr)) { ctx->report.error("%s: ns_parserr", domain_name); vsl->status = kafs_lookup_bad; continue; } if (ns_rr_type(rr) != ns_t_srv) continue; ns_get16(ns_rr_rdata(rr)); /* subtype */ /* Expand the name server's domain name */ if (ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), ns_rr_rdata(rr) + 6, buf, MAXDNAME) < 0) { ctx->report.error("%s: ns_name_uncompress", domain_name); vsl->status = kafs_lookup_bad; continue; } rr_ttl = ns_rr_ttl(rr); if (vsl->ttl > rr_ttl) vsl->ttl = rr_ttl; server->pref = ns_get16(ns_rr_rdata(rr)); server->weight = ns_get16(ns_rr_rdata(rr) + 2); server->port = ns_get16(ns_rr_rdata(rr) + 4); verbose("rdata %u %u %u", server->pref, server->weight, server->port); /* Check the domain name we've just unpacked and add it to * the list of VL servers if it is not a duplicate. * If it is a duplicate, just ignore it. */ for (i = 0; i < vsl->nr_servers; i++) if (strcasecmp(buf, vsl->servers[i].name) == 0) continue; server->name = strdup(buf); if (!server->name) goto system_error; server->port = AFS_VL_PORT; server->protocol = protocol; verbose("SERVER[%u] %s", vsl->nr_servers, server->name); vsl->nr_servers++; } if (vsl->nr_servers > 0 && vsl->status == kafs_lookup_bad) vsl->status = kafs_lookup_good_with_bad; if (vsl->nr_servers == 0 && vsl->status == kafs_lookup_good_with_bad) vsl->status = kafs_lookup_got_not_found; return 0; system_error: ctx->report.bad_error = true; ctx->report.error("%m"); return -1; } /* * Look up an SRV record to get the VL server addresses [RFC 5864]. */ static int dns_query_SRV(struct kafs_server_list *vsl, const char *domain_name, const char *service_name, const char *proto_name, struct kafs_lookup_context *ctx) { int response_len; /* buffer length */ ns_msg handle; /* handle for response message */ union { HEADER hdr; u_char buf[NS_PACKETSZ]; } response; enum dns_payload_protocol_type protocol; char name[1024]; snprintf(name, sizeof(name), "_%s._%s.%s", service_name, proto_name, domain_name); verbose("Get SRV RR for name:'%s'", name); response_len = res_nquery(&ctx->res, name, ns_c_in, ns_t_srv, response.buf, sizeof(response)); if (response_len < 0) { ctx->report.error("%s: dns: %s", domain_name, hstrerror(h_errno)); switch (h_errno) { case HOST_NOT_FOUND: case NO_DATA: vsl->status = kafs_lookup_got_not_found; break; case NO_RECOVERY: vsl->status = kafs_lookup_got_ns_failure; break; case TRY_AGAIN: vsl->status = kafs_lookup_got_temp_failure; break; } return 0; } vsl->source = kafs_record_from_dns_srv; if (ns_initparse(response.buf, response_len, &handle) < 0) { ctx->report.error("%s: ns_initparse: %s", domain_name, hstrerror(h_errno)); vsl->status = kafs_lookup_bad; return 0; } if (strcmp(proto_name, "udp") == 0) protocol = DNS_SERVER_PROTOCOL_UDP; else if (strcmp(proto_name, "tcp") == 0) protocol = DNS_SERVER_PROTOCOL_TCP; else protocol = DNS_SERVER_PROTOCOL_UNSPECIFIED; vsl->status = kafs_lookup_good; return kafs_parse_srv(vsl, domain_name, handle, ns_s_an, protocol, ctx); } /* * Look up a cell by name in the DNS. */ int kafs_dns_lookup_vlservers(struct kafs_server_list *vsl, const char *cell_name, struct kafs_lookup_context *ctx) { int ret; vsl->status = kafs_lookup_not_done; if (!ctx->no_vls_srv) { ret = dns_query_SRV(vsl, cell_name, "afs3-vlserver", "udp", ctx); if (ret == 0 && vsl->nr_servers > 0) return 0; } else { verbose("Use of DNS/SRV for VL server lookup is disabled."); } if (!ctx->no_vls_afsdb) { ret = dns_query_AFSDB(vsl, cell_name, 1, ctx); if (ret == 0 && vsl->nr_servers > 0) return 0; } else { verbose("Use of DNS/AFSDB for VL server lookup is disabled."); } return 0; } src/lib_object.c000066400000000000000000000063741367270324000141230ustar00rootroot00000000000000/* * Object creation/destruction. * * Copyright (C) David Howells (dhowells@redhat.com) 2018 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #define _GNU_SOURCE #include #include #include #include #include #include #include /* * Initialise state in a lookup context. */ int kafs_init_lookup_context(struct kafs_lookup_context *ctx) { memset(&ctx->res, 0, sizeof(ctx->res)); if (res_ninit(&ctx->res) < 0) { ctx->report.bad_error = true; ctx->report.error("%m"); return -1; } return 0; } /* * Clear state in a lookup context. */ void kafs_clear_lookup_context(struct kafs_lookup_context *ctx) { res_nclose(&ctx->res); } /* * Allocate a blank server list. */ struct kafs_server_list *kafs_alloc_server_list(struct kafs_report *report) { struct kafs_server_list *sl; sl = calloc(1, sizeof(*sl)); if (!sl) { report->bad_error = true; report->error("%m"); return NULL; } sl->ttl = UINT_MAX; return sl; } /* * Free a server list. */ void kafs_free_server_list(struct kafs_server_list *sl) { unsigned int i; if (sl->servers) { for (i = 0; i < sl->nr_servers; i++) { struct kafs_server *s = &sl->servers[i]; if (!s->borrowed_name) free(s->name); if (!s->borrowed_addrs) free(s->addrs); } free(sl->servers); } free(sl); } /* * Free a cell. */ void kafs_free_cell(struct kafs_cell *cell) { if (!cell->borrowed_name) free(cell->name); if (!cell->borrowed_desc) free(cell->desc); if (!cell->borrowed_realm) free(cell->realm); if (cell->vlservers) kafs_free_server_list(cell->vlservers); free(cell); } /* * Transfer the addresses from one server to another. */ void kafs_transfer_addresses(struct kafs_server *to, const struct kafs_server *from) { to->max_addrs = 0; to->nr_addrs = from->nr_addrs; to->addrs = from->addrs; to->borrowed_addrs = true; } /* * Transfer the list of servers from one server list to another. */ int kafs_transfer_server_list(struct kafs_server_list *to, const struct kafs_server_list *from) { unsigned int i, nr = from->nr_servers; to->source = from->source; to->status = from->status; to->nr_servers = nr; to->max_servers = from->max_servers; to->ttl = from->ttl; if (nr == 0) { to->servers = NULL; return 0; } to->servers = malloc(nr * sizeof(struct kafs_server)); if (!to->servers) return -1; memcpy(to->servers, from->servers, nr * sizeof(struct kafs_server)); for (i = 0; i < nr; i++) { struct kafs_server *s = &to->servers[i]; s->borrowed_name = true; s->max_addrs = 0; s->nr_addrs = 0; s->addrs = NULL; } return 0; } /* * Transfer information from one cell record to another. */ void kafs_transfer_cell(struct kafs_cell *to, const struct kafs_cell *from) { if (!to->name) { to->name = from->name; to->borrowed_name = true; } if (from->desc) { to->desc = from->desc; to->borrowed_desc = true; } if (from->realm) { to->realm = from->realm; to->borrowed_realm = true; } to->use_dns = from->use_dns; to->show_cell = from->show_cell; } src/lib_profile.c000066400000000000000000000255641367270324000143170ustar00rootroot00000000000000/* * Kerberos-style profile file parser. * * Copyright (C) David Howells (dhowells@redhat.com) 2018 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #define report_error(r, fmt, ...) \ ({ \ r->error(fmt, ## __VA_ARGS__); \ -1; \ }) #define parse_error(r, fmt, ...) \ ({ \ r->bad_config = true; \ r->error("%s:%u: " fmt, r->what, r->line, ## __VA_ARGS__); \ -1; \ }) /* * Dump a profile to stdout in tree form. */ void kafs_profile_dump(const struct kafs_profile *p, unsigned int depth) { unsigned int i; if (p->type == kafs_profile_value_is_list) { printf("%*s [*] '%s'%s\n", depth, "", p->name, p->final ? " [final]" : ""); for (i = 0; i < p->nr_relations; i++) kafs_profile_dump(p->relations[i], depth + 2); } else { printf("%*s [=] '%s' = '%s'\n", depth, "", p->name, p->value); } } /* * Find/create relation in the list to which we're contributing. * * If a list relation is already closed then it is replaced unless it is final, * in which case the new stuff is ignored. */ static struct kafs_profile *kafs_profile_get_relation(struct kafs_profile *parent, char *name, enum kafs_profile_value_type type, struct kafs_report *report) { struct kafs_profile *r, **list = parent->relations; bool dummy = false; int i, n = parent->nr_relations; if (parent->type != kafs_profile_value_is_list) { report->error("%s:%u: Can't insert into a non-list", report->what, report->line); return NULL; } if (type == kafs_profile_value_is_list) { for (i = 0; i < n; i++) { r = list[i]; if (r->type != kafs_profile_value_is_list || strcmp(r->name, name) != 0) continue; if (r->final) { dummy = true; goto create; } r->final |= parent->final; return r; } } create: r = malloc(sizeof(*r)); if (!r) return NULL; memset(r, 0, sizeof(*r)); r->type = type; r->name = name; r->parent = parent; r->dummy = dummy | parent->final | parent->dummy; if (!r->dummy) { list = realloc(list, sizeof(*list) * (n + 1)); if (!list) return NULL; list[n] = r; parent->relations = list; parent->nr_relations = n + 1; } return r; } /* * Parse the contents of a kafs_profile file. */ static int kafs_profile_parse_content(struct kafs_profile *prof, const char *file, char *p, char *end, struct kafs_report *report) { struct kafs_profile *section = NULL, *list = NULL, *tmp; unsigned int line = 0; char *eol, *next_line = p, *key, *value; bool at_left; next_line: p = next_line; line++; report->line = line; at_left = p < end && !isblank(*p); while (p < end && isblank(*p)) p++; if (p == end) return 0; eol = strpbrk(p, "\n\r"); if (!eol) { next_line = eol = end; } else { next_line = eol + 1; if (next_line < end && *next_line != *eol && (*next_line == '\n' || *next_line == '\r')) next_line++; /* handle CRLF and LFCR */ while (eol > p && isblank(eol[-1])) eol--; *eol = 0; } if (!*p || p[0] == '#' || p[0] == ';') goto next_line; /* Deal with section markers. */ if (list == section && p[0] == '[') { if (eol - p < 3 || eol[-1] != ']') return parse_error(report, "Bad section label"); p++; eol--; *eol = 0; if (strchr(p, ']')) return parse_error(report, "Bad section label"); section = kafs_profile_get_relation(prof, p, kafs_profile_value_is_list, report); if (!section) return -1; section->file = file; section->line = line; list = section; goto next_line; } /* Things before the first section are either comments or inclusion * directives. */ if (!section) { if (!at_left || strncmp(p, "include", 7) != 0) goto next_line; p += 7; if (isblank(*p)) { /* It's an include directive */ while (*p && isblank(*p)) p++; if (!*p) return parse_error(report, "No include path"); if (kafs_profile_parse_file(prof, p, report) < 0) return -1; } if (strncmp(p, "dir", 3) == 0 && (isblank(p[3]) || !p[3])) { /* It's an includedir directive */ p += 3; while (*p && isblank(*p)) p++; if (!*p) return parse_error(report, "No includedir path"); if (kafs_profile_parse_dir(prof, p, report) < 0) return -1; } goto next_line; } /* Deal with the closure of a list */ if (p[0] == '}') { if (list == section) return parse_error(report, "Unmatched '}'"); p++; if (p[0] == '*') { list->final = true; p++; } if (*p) return parse_error(report, "Unexpected stuff after '}'"); tmp = list; list = list->parent; if (tmp->dummy) free(tmp); goto next_line; } /* Everything else should be a relation specifier of one of the * following forms: * * x = y * x = { .. } */ key = p; p = strchr(p, '='); if (!p) return parse_error(report, "Missing '=' in relation"); if (p == key) return parse_error(report, "Anonymous key in relation"); value = p + 1; while (value < eol && isblank(*value)) value++; p--; while (p > key && isblank(p[-1])) p--; *p = 0; /* Handle the opening of a new list-type relation */ if (value[0] == '{') { if (value[1]) return parse_error(report, "Unexpected stuff after '{'"); list = kafs_profile_get_relation(list, key, kafs_profile_value_is_list, report); if (!list) return -1; list->file = file; list->line = line; goto next_line; } /* Handle a relation with a quoted-string value */ if (value[0] == '"') { char *q; value++; if (eol <= value || eol[-1] != '"') return parse_error(report, "Unterminated string"); eol--; eol[0] = 0; /* Substitute for all the escape chars in place */ for (p = q = value; p < eol;) { char ch = *p++; if (ch == '\\') { if (p >= eol) return parse_error(report, "Uncompleted '\\' escape"); ch = *p++; switch (ch) { case 'n': ch = '\n'; break; case 't': ch = '\t'; break; case 'b': ch = '\b'; break; } } *q++ = ch; } *q = 0; } tmp = kafs_profile_get_relation(list, key, kafs_profile_value_is_string, report); if (!tmp) return -1; tmp->file = file; tmp->line = line; tmp->value = value; goto next_line; } /* * Parse a kafs_profile file. */ int kafs_profile_parse_file(struct kafs_profile *prof, const char *file, struct kafs_report *report) { const char *old_file = report->what; struct stat st; ssize_t n; char *buffer; int fd, ret; report->what = file; fd = open(file, O_RDONLY); if (fd == -1) return -1; if (fstat(fd, &st) == -1) { close(fd); return -1; } buffer = malloc(st.st_size + 1); if (!buffer) { close(fd); return -1; } n = read(fd, buffer, st.st_size); close(fd); if (n == -1) { free(buffer); return -1; } buffer[n] = 0; ret = kafs_profile_parse_content(prof, file, buffer, buffer + n, report); if (ret == 0) report->what = old_file; return ret; } /* * Parse a kafs_profile directory. */ int kafs_profile_parse_dir(struct kafs_profile *prof, const char *dirname, struct kafs_report *report) { const char *old_file = report->what; struct dirent *de; char *filename; DIR *dir; int ret, n; report->what = dirname; report->line = 0; dir = opendir(dirname); if (!dir) return report_error(report, "%s: %m", dirname); while (errno = 0, (de = readdir(dir))) { if (de->d_name[0] == '.') continue; n = strlen(de->d_name); if (n < 1 || de->d_name[n - 1] == '~') continue; if (asprintf(&filename, "%s/%s", dirname, de->d_name) == -1) { closedir(dir); return report_error(report, "%m"); } ret = kafs_profile_parse_file(prof, filename, report); if (ret < 0) { closedir(dir); return -1; } } report->what = dirname; closedir(dir); if (errno != 0) return -1; report->what = old_file; return 0; } /* * Find the first child object of a type and name in the list attached to the * given object. */ const struct kafs_profile *kafs_profile_find_first_child(const struct kafs_profile *prof, enum kafs_profile_value_type type, const char *name, struct kafs_report *report) { unsigned int i; if (prof->type != kafs_profile_value_is_list) { report_error(report, "Trying to find '%s' in relation '%s'", name, prof->name); return NULL; } for (i = 0; i < prof->nr_relations; i++) { const struct kafs_profile *r = prof->relations[i]; if (r->type == type && strcmp(r->name, name) == 0) return r; } return NULL; } /* * Iterate over all the child objects of the given type and name in the list * attached to the given object until the iterator function returns non-zero. */ int kafs_profile_iterate(const struct kafs_profile *prof, enum kafs_profile_value_type type, const char *name, kafs_profile_iterator iterator, void *data, struct kafs_report *report) { unsigned int i; int ret; if (prof->type != kafs_profile_value_is_list) { report_error(report, "Trying to iterate over relation '%s'", prof->name); return -1; } for (i = 0; i < prof->nr_relations; i++) { const struct kafs_profile *r = prof->relations[i]; if (r->type != type) continue; if (name && strcmp(r->name, name) != 0) continue; ret = iterator(r, data, report); if (ret) return ret; } return 0; } static int kafs_count_objects(const struct kafs_profile *child, void *data, struct kafs_report *report) { unsigned int *_nr = data; *_nr += 1; return 0; } /* * Count the number of matching children of an object. */ int kafs_profile_count(const struct kafs_profile *prof, enum kafs_profile_value_type type, const char *name, unsigned int *_nr) { return kafs_profile_iterate(prof, type, NULL, kafs_count_objects, _nr, NULL); } static int cmp_constant(const void *name, const void *entry) { const struct kafs_constant_table *e = entry; return strcasecmp(name, e->name); } /* * Turn a string into a constant. */ int kafs_lookup_constant2(const struct kafs_constant_table *tbl, size_t tbl_size, const char *name, int not_found) { const struct kafs_constant_table *e; e = bsearch(name, tbl, tbl_size, sizeof(tbl[0]), cmp_constant); if (!e) return not_found; return e->value; } static const struct kafs_constant_table bool_names[] = { { "0", false }, { "1", true }, { "f", false }, { "false", false }, { "n", false }, { "no", false }, { "off", false }, { "on", true }, { "t", true }, { "true", true }, { "y", true }, { "yes", true }, }; /* * Parse a string as a bool constant. */ int kafs_lookup_bool(const char *name, int not_found) { return kafs_lookup_constant(bool_names, name, not_found); } src/preload-cells.c000066400000000000000000000100301367270324000145350ustar00rootroot00000000000000/* * Cell preloader for kAFS filesystem. * * Copyright (C) David Howells (dhowells@redhat.com) 2018 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include static void verbose(const char *fmt, ...) { va_list va; va_start(va, fmt); if (isatty(2)) { vprintf(fmt, va); putchar('\n'); } else { vsyslog(LOG_INFO, fmt, va); } va_end(va); } /* * Just print an error to stderr or the syslog */ static void _error(const char *fmt, ...) { va_list va; va_start(va, fmt); if (isatty(2)) { vfprintf(stderr, fmt, va); fputc('\n', stderr); } else { vsyslog(LOG_ERR, fmt, va); } va_end(va); } /* * Write a string to a proc file. */ static void write_to_proc(const char *file, const char *str, bool redirect_to_stdout) { int fd = 1, n; if (!str) return; if (redirect_to_stdout) { printf("WRITE '%s' TO %s\n", str, file); return; } fd = open(file, O_WRONLY); if (fd == -1) { _error("Can't open %s: %m", file); exit(1); } n = strlen(str); if (write(fd, str, n) != n) { _error("Can't write '%s' to %s: %m", str, file); exit(1); } if (close(fd) == -1) { _error("Can't close %s: %m", file); exit(1); } } /* * Parse the cell database file */ int do_preload(const struct kafs_cell_db *db, bool redirect_to_stdout) { unsigned int i; char buf[4096]; int fd, n; if (!redirect_to_stdout) { fd = open("/proc/fs/afs/cells", O_WRONLY); if (fd == -1) { _error("Can't open /proc/fs/afs/cells: %m"); exit(1); } } else { fd = -1; } for (i = 0; i < db->nr_cells; i++) { const struct kafs_cell *cell = db->cells[i]; n = snprintf(buf, sizeof(buf) - 1, "add %s", cell->name); if (redirect_to_stdout) { printf("WRITE '%s' TO /proc/fs/afs/cells\n", buf); continue; } if (write(fd, buf, n) != n) { if (errno != EEXIST) { _error("Can't add cell '%s': %m", cell->name); exit(1); } verbose("%s: Already exists", cell->name); } } if (!redirect_to_stdout) { if (close(fd) == -1) { _error("Can't close /proc/fs/afs/cells: %m"); exit(1); } } write_to_proc("/proc/net/afs/rootcell", kafs_this_cell, redirect_to_stdout); write_to_proc("/proc/net/afs/sysname", kafs_sysname, redirect_to_stdout); exit(0); } static __attribute__((noreturn)) void usage(const char *prog) { fprintf(stderr, "Usage: %s [-Dv] [*]\n", prog); exit(2); } int main(int argc, char *argv[]) { struct kafs_report report = {}; const char *const *files; bool redirect_to_stdout = false; int opt; if (argc > 1 && strcmp(argv[1], "--help") == 0) usage(argv[0]); while (opt = getopt(argc, argv, "Dv"), opt != -1) { switch (opt) { case 'D': redirect_to_stdout = true; break; case 'v': if (!report.verbose) report.verbose = verbose; else report.verbose2 = verbose; break; default: usage(argv[0]); break; } } if (!redirect_to_stdout) { openlog("kafs-preload", 0, LOG_USER); syslog(LOG_NOTICE, "kAFS: Preloading cell database"); } argc -= optind; argv += optind; files = NULL; if (argc > 0) files = (const char **)argv; if (kafs_read_config(files, &report) < 0) exit(3); do_preload(kafs_cellserv_db, redirect_to_stdout); return 0; } src/version.lds000066400000000000000000000011701367270324000140410ustar00rootroot00000000000000KAFS_CLIENT_0.1 { kafs_alloc_cell; kafs_alloc_server_list; kafs_cellserv_dump; kafs_cellserv_parse_conf; kafs_cellserv_profile; kafs_clear_lookup_context; kafs_dns_lookup_addresses; kafs_dns_lookup_vlservers; kafs_dump_cell; kafs_dump_server_list; kafs_free_cell; kafs_free_server_list; kafs_init_celldb; kafs_init_lookup_context; kafs_lookup_bool; kafs_lookup_cell; kafs_lookup_constant2; kafs_profile_count; kafs_profile_dump; kafs_profile_find_first_child; kafs_profile_iterate; kafs_profile_parse_dir; kafs_profile_parse_file; kafs_transfer_addresses; kafs_transfer_cell; kafs_transfer_server_list; };