// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org) package org.xbill.DNS; import java.net.*; import java.io.*; import java.util.*; /** * Well Known Services - Lists services offered by this host. * * @author Brian Wellington */ public class WKSRecord extends Record { private static final long serialVersionUID = -9104259763909119805L; public static class Protocol { /** * IP protocol identifiers. This is basically copied out of RFC 1010. */ private Protocol() {} /** Internet Control Message */ public static final int ICMP = 1; /** Internet Group Management */ public static final int IGMP = 2; /** Gateway-to-Gateway */ public static final int GGP = 3; /** Stream */ public static final int ST = 5; /** Transmission Control */ public static final int TCP = 6; /** UCL */ public static final int UCL = 7; /** Exterior Gateway Protocol */ public static final int EGP = 8; /** any private interior gateway */ public static final int IGP = 9; /** BBN RCC Monitoring */ public static final int BBN_RCC_MON = 10; /** Network Voice Protocol */ public static final int NVP_II = 11; /** PUP */ public static final int PUP = 12; /** ARGUS */ public static final int ARGUS = 13; /** EMCON */ public static final int EMCON = 14; /** Cross Net Debugger */ public static final int XNET = 15; /** Chaos */ public static final int CHAOS = 16; /** User Datagram */ public static final int UDP = 17; /** Multiplexing */ public static final int MUX = 18; /** DCN Measurement Subsystems */ public static final int DCN_MEAS = 19; /** Host Monitoring */ public static final int HMP = 20; /** Packet Radio Measurement */ public static final int PRM = 21; /** XEROX NS IDP */ public static final int XNS_IDP = 22; /** Trunk-1 */ public static final int TRUNK_1 = 23; /** Trunk-2 */ public static final int TRUNK_2 = 24; /** Leaf-1 */ public static final int LEAF_1 = 25; /** Leaf-2 */ public static final int LEAF_2 = 26; /** Reliable Data Protocol */ public static final int RDP = 27; /** Internet Reliable Transaction */ public static final int IRTP = 28; /** ISO Transport Protocol Class 4 */ public static final int ISO_TP4 = 29; /** Bulk Data Transfer Protocol */ public static final int NETBLT = 30; /** MFE Network Services Protocol */ public static final int MFE_NSP = 31; /** MERIT Internodal Protocol */ public static final int MERIT_INP = 32; /** Sequential Exchange Protocol */ public static final int SEP = 33; /** CFTP */ public static final int CFTP = 62; /** SATNET and Backroom EXPAK */ public static final int SAT_EXPAK = 64; /** MIT Subnet Support */ public static final int MIT_SUBNET = 65; /** MIT Remote Virtual Disk Protocol */ public static final int RVD = 66; /** Internet Pluribus Packet Core */ public static final int IPPC = 67; /** SATNET Monitoring */ public static final int SAT_MON = 69; /** Internet Packet Core Utility */ public static final int IPCV = 71; /** Backroom SATNET Monitoring */ public static final int BR_SAT_MON = 76; /** WIDEBAND Monitoring */ public static final int WB_MON = 78; /** WIDEBAND EXPAK */ public static final int WB_EXPAK = 79; private static Mnemonic protocols = new Mnemonic("IP protocol", Mnemonic.CASE_LOWER); static { protocols.setMaximum(0xFF); protocols.setNumericAllowed(true); protocols.add(ICMP, "icmp"); protocols.add(IGMP, "igmp"); protocols.add(GGP, "ggp"); protocols.add(ST, "st"); protocols.add(TCP, "tcp"); protocols.add(UCL, "ucl"); protocols.add(EGP, "egp"); protocols.add(IGP, "igp"); protocols.add(BBN_RCC_MON, "bbn-rcc-mon"); protocols.add(NVP_II, "nvp-ii"); protocols.add(PUP, "pup"); protocols.add(ARGUS, "argus"); protocols.add(EMCON, "emcon"); protocols.add(XNET, "xnet"); protocols.add(CHAOS, "chaos"); protocols.add(UDP, "udp"); protocols.add(MUX, "mux"); protocols.add(DCN_MEAS, "dcn-meas"); protocols.add(HMP, "hmp"); protocols.add(PRM, "prm"); protocols.add(XNS_IDP, "xns-idp"); protocols.add(TRUNK_1, "trunk-1"); protocols.add(TRUNK_2, "trunk-2"); protocols.add(LEAF_1, "leaf-1"); protocols.add(LEAF_2, "leaf-2"); protocols.add(RDP, "rdp"); protocols.add(IRTP, "irtp"); protocols.add(ISO_TP4, "iso-tp4"); protocols.add(NETBLT, "netblt"); protocols.add(MFE_NSP, "mfe-nsp"); protocols.add(MERIT_INP, "merit-inp"); protocols.add(SEP, "sep"); protocols.add(CFTP, "cftp"); protocols.add(SAT_EXPAK, "sat-expak"); protocols.add(MIT_SUBNET, "mit-subnet"); protocols.add(RVD, "rvd"); protocols.add(IPPC, "ippc"); protocols.add(SAT_MON, "sat-mon"); protocols.add(IPCV, "ipcv"); protocols.add(BR_SAT_MON, "br-sat-mon"); protocols.add(WB_MON, "wb-mon"); protocols.add(WB_EXPAK, "wb-expak"); } /** * Converts an IP protocol value into its textual representation */ public static String string(int type) { return protocols.getText(type); } /** * Converts a textual representation of an IP protocol into its * numeric code. Integers in the range 0..255 are also accepted. * @param s The textual representation of the protocol * @return The protocol code, or -1 on error. */ public static int value(String s) { return protocols.getValue(s); } } public static class Service { /** * TCP/UDP services. This is basically copied out of RFC 1010, * with MIT-ML-DEV removed, as it is not unique, and the description * of SWIFT-RVF fixed. */ private Service() {} /** Remote Job Entry */ public static final int RJE = 5; /** Echo */ public static final int ECHO = 7; /** Discard */ public static final int DISCARD = 9; /** Active Users */ public static final int USERS = 11; /** Daytime */ public static final int DAYTIME = 13; /** Quote of the Day */ public static final int QUOTE = 17; /** Character Generator */ public static final int CHARGEN = 19; /** File Transfer [Default Data] */ public static final int FTP_DATA = 20; /** File Transfer [Control] */ public static final int FTP = 21; /** Telnet */ public static final int TELNET = 23; /** Simple Mail Transfer */ public static final int SMTP = 25; /** NSW User System FE */ public static final int NSW_FE = 27; /** MSG ICP */ public static final int MSG_ICP = 29; /** MSG Authentication */ public static final int MSG_AUTH = 31; /** Display Support Protocol */ public static final int DSP = 33; /** Time */ public static final int TIME = 37; /** Resource Location Protocol */ public static final int RLP = 39; /** Graphics */ public static final int GRAPHICS = 41; /** Host Name Server */ public static final int NAMESERVER = 42; /** Who Is */ public static final int NICNAME = 43; /** MPM FLAGS Protocol */ public static final int MPM_FLAGS = 44; /** Message Processing Module [recv] */ public static final int MPM = 45; /** MPM [default send] */ public static final int MPM_SND = 46; /** NI FTP */ public static final int NI_FTP = 47; /** Login Host Protocol */ public static final int LOGIN = 49; /** IMP Logical Address Maintenance */ public static final int LA_MAINT = 51; /** Domain Name Server */ public static final int DOMAIN = 53; /** ISI Graphics Language */ public static final int ISI_GL = 55; /** NI MAIL */ public static final int NI_MAIL = 61; /** VIA Systems - FTP */ public static final int VIA_FTP = 63; /** TACACS-Database Service */ public static final int TACACS_DS = 65; /** Bootstrap Protocol Server */ public static final int BOOTPS = 67; /** Bootstrap Protocol Client */ public static final int BOOTPC = 68; /** Trivial File Transfer */ public static final int TFTP = 69; /** Remote Job Service */ public static final int NETRJS_1 = 71; /** Remote Job Service */ public static final int NETRJS_2 = 72; /** Remote Job Service */ public static final int NETRJS_3 = 73; /** Remote Job Service */ public static final int NETRJS_4 = 74; /** Finger */ public static final int FINGER = 79; /** HOSTS2 Name Server */ public static final int HOSTS2_NS = 81; /** SU/MIT Telnet Gateway */ public static final int SU_MIT_TG = 89; /** MIT Dover Spooler */ public static final int MIT_DOV = 91; /** Device Control Protocol */ public static final int DCP = 93; /** SUPDUP */ public static final int SUPDUP = 95; /** Swift Remote Virtual File Protocol */ public static final int SWIFT_RVF = 97; /** TAC News */ public static final int TACNEWS = 98; /** Metagram Relay */ public static final int METAGRAM = 99; /** NIC Host Name Server */ public static final int HOSTNAME = 101; /** ISO-TSAP */ public static final int ISO_TSAP = 102; /** X400 */ public static final int X400 = 103; /** X400-SND */ public static final int X400_SND = 104; /** Mailbox Name Nameserver */ public static final int CSNET_NS = 105; /** Remote Telnet Service */ public static final int RTELNET = 107; /** Post Office Protocol - Version 2 */ public static final int POP_2 = 109; /** SUN Remote Procedure Call */ public static final int SUNRPC = 111; /** Authentication Service */ public static final int AUTH = 113; /** Simple File Transfer Protocol */ public static final int SFTP = 115; /** UUCP Path Service */ public static final int UUCP_PATH = 117; /** Network News Transfer Protocol */ public static final int NNTP = 119; /** HYDRA Expedited Remote Procedure */ public static final int ERPC = 121; /** Network Time Protocol */ public static final int NTP = 123; /** Locus PC-Interface Net Map Server */ public static final int LOCUS_MAP = 125; /** Locus PC-Interface Conn Server */ public static final int LOCUS_CON = 127; /** Password Generator Protocol */ public static final int PWDGEN = 129; /** CISCO FNATIVE */ public static final int CISCO_FNA = 130; /** CISCO TNATIVE */ public static final int CISCO_TNA = 131; /** CISCO SYSMAINT */ public static final int CISCO_SYS = 132; /** Statistics Service */ public static final int STATSRV = 133; /** INGRES-NET Service */ public static final int INGRES_NET = 134; /** Location Service */ public static final int LOC_SRV = 135; /** PROFILE Naming System */ public static final int PROFILE = 136; /** NETBIOS Name Service */ public static final int NETBIOS_NS = 137; /** NETBIOS Datagram Service */ public static final int NETBIOS_DGM = 138; /** NETBIOS Session Service */ public static final int NETBIOS_SSN = 139; /** EMFIS Data Service */ public static final int EMFIS_DATA = 140; /** EMFIS Control Service */ public static final int EMFIS_CNTL = 141; /** Britton-Lee IDM */ public static final int BL_IDM = 142; /** Survey Measurement */ public static final int SUR_MEAS = 243; /** LINK */ public static final int LINK = 245; private static Mnemonic services = new Mnemonic("TCP/UDP service", Mnemonic.CASE_LOWER); static { services.setMaximum(0xFFFF); services.setNumericAllowed(true); services.add(RJE, "rje"); services.add(ECHO, "echo"); services.add(DISCARD, "discard"); services.add(USERS, "users"); services.add(DAYTIME, "daytime"); services.add(QUOTE, "quote"); services.add(CHARGEN, "chargen"); services.add(FTP_DATA, "ftp-data"); services.add(FTP, "ftp"); services.add(TELNET, "telnet"); services.add(SMTP, "smtp"); services.add(NSW_FE, "nsw-fe"); services.add(MSG_ICP, "msg-icp"); services.add(MSG_AUTH, "msg-auth"); services.add(DSP, "dsp"); services.add(TIME, "time"); services.add(RLP, "rlp"); services.add(GRAPHICS, "graphics"); services.add(NAMESERVER, "nameserver"); services.add(NICNAME, "nicname"); services.add(MPM_FLAGS, "mpm-flags"); services.add(MPM, "mpm"); services.add(MPM_SND, "mpm-snd"); services.add(NI_FTP, "ni-ftp"); services.add(LOGIN, "login"); services.add(LA_MAINT, "la-maint"); services.add(DOMAIN, "domain"); services.add(ISI_GL, "isi-gl"); services.add(NI_MAIL, "ni-mail"); services.add(VIA_FTP, "via-ftp"); services.add(TACACS_DS, "tacacs-ds"); services.add(BOOTPS, "bootps"); services.add(BOOTPC, "bootpc"); services.add(TFTP, "tftp"); services.add(NETRJS_1, "netrjs-1"); services.add(NETRJS_2, "netrjs-2"); services.add(NETRJS_3, "netrjs-3"); services.add(NETRJS_4, "netrjs-4"); services.add(FINGER, "finger"); services.add(HOSTS2_NS, "hosts2-ns"); services.add(SU_MIT_TG, "su-mit-tg"); services.add(MIT_DOV, "mit-dov"); services.add(DCP, "dcp"); services.add(SUPDUP, "supdup"); services.add(SWIFT_RVF, "swift-rvf"); services.add(TACNEWS, "tacnews"); services.add(METAGRAM, "metagram"); services.add(HOSTNAME, "hostname"); services.add(ISO_TSAP, "iso-tsap"); services.add(X400, "x400"); services.add(X400_SND, "x400-snd"); services.add(CSNET_NS, "csnet-ns"); services.add(RTELNET, "rtelnet"); services.add(POP_2, "pop-2"); services.add(SUNRPC, "sunrpc"); services.add(AUTH, "auth"); services.add(SFTP, "sftp"); services.add(UUCP_PATH, "uucp-path"); services.add(NNTP, "nntp"); services.add(ERPC, "erpc"); services.add(NTP, "ntp"); services.add(LOCUS_MAP, "locus-map"); services.add(LOCUS_CON, "locus-con"); services.add(PWDGEN, "pwdgen"); services.add(CISCO_FNA, "cisco-fna"); services.add(CISCO_TNA, "cisco-tna"); services.add(CISCO_SYS, "cisco-sys"); services.add(STATSRV, "statsrv"); services.add(INGRES_NET, "ingres-net"); services.add(LOC_SRV, "loc-srv"); services.add(PROFILE, "profile"); services.add(NETBIOS_NS, "netbios-ns"); services.add(NETBIOS_DGM, "netbios-dgm"); services.add(NETBIOS_SSN, "netbios-ssn"); services.add(EMFIS_DATA, "emfis-data"); services.add(EMFIS_CNTL, "emfis-cntl"); services.add(BL_IDM, "bl-idm"); services.add(SUR_MEAS, "sur-meas"); services.add(LINK, "link"); } /** * Converts a TCP/UDP service port number into its textual * representation. */ public static String string(int type) { return services.getText(type); } /** * Converts a textual representation of a TCP/UDP service into its * port number. Integers in the range 0..65535 are also accepted. * @param s The textual representation of the service. * @return The port number, or -1 on error. */ public static int value(String s) { return services.getValue(s); } } private byte [] address; private int protocol; private int [] services; WKSRecord() {} Record getObject() { return new WKSRecord(); } /** * Creates a WKS Record from the given data * @param address The IP address * @param protocol The IP protocol number * @param services An array of supported services, represented by port number. */ public WKSRecord(Name name, int dclass, long ttl, InetAddress address, int protocol, int [] services) { super(name, Type.WKS, dclass, ttl); if (Address.familyOf(address) != Address.IPv4) throw new IllegalArgumentException("invalid IPv4 address"); this.address = address.getAddress(); this.protocol = checkU8("protocol", protocol); for (int i = 0; i < services.length; i++) { checkU16("service", services[i]); } this.services = new int[services.length]; System.arraycopy(services, 0, this.services, 0, services.length); Arrays.sort(this.services); } void rrFromWire(DNSInput in) throws IOException { address = in.readByteArray(4); protocol = in.readU8(); byte [] array = in.readByteArray(); List list = new ArrayList(); for (int i = 0; i < array.length; i++) { for (int j = 0; j < 8; j++) { int octet = array[i] & 0xFF; if ((octet & (1 << (7 - j))) != 0) { list.add(new Integer(i * 8 + j)); } } } services = new int[list.size()]; for (int i = 0; i < list.size(); i++) { services[i] = ((Integer) list.get(i)).intValue(); } } void rdataFromString(Tokenizer st, Name origin) throws IOException { String s = st.getString(); address = Address.toByteArray(s, Address.IPv4); if (address == null) throw st.exception("invalid address"); s = st.getString(); protocol = Protocol.value(s); if (protocol < 0) { throw st.exception("Invalid IP protocol: " + s); } List list = new ArrayList(); while (true) { Tokenizer.Token t = st.get(); if (!t.isString()) break; int service = Service.value(t.value); if (service < 0) { throw st.exception("Invalid TCP/UDP service: " + t.value); } list.add(new Integer(service)); } st.unget(); services = new int[list.size()]; for (int i = 0; i < list.size(); i++) { services[i] = ((Integer) list.get(i)).intValue(); } } /** * Converts rdata to a String */ String rrToString() { StringBuffer sb = new StringBuffer(); sb.append(Address.toDottedQuad(address)); sb.append(" "); sb.append(protocol); for (int i = 0; i < services.length; i++) { sb.append(" " + services[i]); } return sb.toString(); } /** * Returns the IP address. */ public InetAddress getAddress() { try { return InetAddress.getByAddress(address); } catch (UnknownHostException e) { return null; } } /** * Returns the IP protocol. */ public int getProtocol() { return protocol; } /** * Returns the services provided by the host on the specified address. */ public int [] getServices() { return services; } void rrToWire(DNSOutput out, Compression c, boolean canonical) { out.writeByteArray(address); out.writeU8(protocol); int highestPort = services[services.length - 1]; byte [] array = new byte[highestPort / 8 + 1]; for (int i = 0; i < services.length; i++) { int port = services[i]; array[port / 8] |= (1 << (7 - port % 8)); } out.writeByteArray(array); } }