OSF DCE Application Development Guide Core Components Revision 1.
The information contained within this document is subject to change without notice. OSF MAKES NO WARRANTY OF ANY KIND WITH REGARD TO THIS MATERIAL, INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. OSF shall not be liable for errors contained herein, or for any direct or indirect, incidental, special or consequential damages in connection with the furnishing, performance, or use of this material.
RESTRICTED RIGHTS NOTICE: Use, duplication, or disclosure by the Government is subject to the restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in Technical Data and Computer Software clause at DFARS 52.2277013. RESTRICTED RIGHTS LEGEND: Use, duplication or disclosure by the Government is subject to restrictions as set forth in paragraph (b)(3)(B) of the rights in Technical Data and Computer Software clause in DAR 7-104.9(a). This computer software is submitted with "restricted rights.
Part 1.
Preface The provides information about how to use the the application programming interfaces (APIs) provided for each OSF Distributed Computing Environment (DCE) component. Audience This guide is written for application programmers with UNIX operating system and C language experience who want to develop and write applications to run on DCE. Applicability This is Revision 1.1 of this document. It applies to the OSF DCE Version 1.1 offering and related updates. See your software license for details.
OSF DCE Application Development Guide—Core Components • • (This volume) • The is divided into parts as follows: 1. DCE Facilities 2. DCE Threads 3. DCE Remote Procedure Call 4. DCE Distributed Time Service 5.
Preface [] Brackets enclose optional items in format and syntax descriptions. {} Braces enclose a list from which you must choose an item in format and syntax descriptions. | A vertical bar separates items in a list of choices. <> Angle brackets enclose the name of a key on the keyboard. ... Horizontal ellipsis points indicate that you can repeat the preceding item one or more times.
0− 0 Tandem Computers Incorporated 124245
Contents _____________________________ Preface . . . . . . . . . . . . . . . . . . . . . . . . . . xxiii Audience . . . . . . . . . . . . . . . . . . . . xxiii Applicability . . . . . . . . . . . . . . . . . . . xxiii Purpose . . . . . . . . . . . . . . . . . . xxiii . . . . . . . . . . . . . . . . . xxiii Related Documents . . . . . . . . . . . . . . . . . xxiv . . . . . . .
OSF DCE Application Development Guide—Core Components 2.8 Managing Server Key Tables Chapter 3. DCE Application Messaging . . . . . . . . . . . . . 2-25 . . . . . . . . . . . . . . . . 3-1 . . . . . . . . . . . . 3.1 DCE and Messages . . . . 3-1 3.2 DCE Messaging Interface Usage . . . . . . . . . . 3.2.1 A Simple DCE Messaging Example . . . . . . 3.2.2 The DCE Message Interface and sams Input and Output Files . . . . . . . . . . . . . . . . . . . . .
Contents 5.6.3 5.6.4 5.6.5 5.6.6 5.6.7 5.6.8 5.7 Storing or Retrieving Data . . . . Freeing Data . . . . . . . . Making or Retrieving Headers . . . Performing Iteration . . . . . . Deleting Items from a Backing Store . Locking and Unlocking a Backing Store Example of Backing Store Use . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-6 5-7 5-8 5-8 5-8 5-9 . . . . . . . . . . . 5-9 . . . . . . . . . . . 6-1 . . . . . .
OSF DCE Application Development Guide—Core Components 8.2.1 8.2.2 8.2.3 Types of Signals . . . . . . . . DCE Threads Signal Handling . . . . Alternatives to Using Signals . . . . . . . . . . . . . 8-5 8-7 8-8 8.3 Nonthreaded Libraries . . . . . . . . . . . . . . 8.3.1 Working with Nonthreaded Software . . . . . . . 8.3.2 Making Nonthreaded Code Thread-Reentrant . . . . . . . . . . 8-9 8-9 8-10 8.4 Avoiding Nonreentrant Software . . . . 8.4.1 Global Lock . . . . . . . 8.4.
Contents 11.2.4 11.2.5 11.2.6 11.2.7 11.2.8 Specifying Interface Attributes . . . . Import Declarations . . . . . . . Constant Declarations . . . . . . Type Declarations . . . . . . . . Operation Declarations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-13 11-13 11-14 11-14 11-15 11.3 Running the IDL Compiler . . . . . . . . . . . . . . . 11-16 11.4 Writing the Client Code . . . . . . . . . . . . . . 11-16 11.
OSF DCE Application Development Guide—Core Components 14.1 Threads of Execution in RPC Applications . . . . . . . 14.1.1 Remote Procedure Call Threads . . . . . . . 14.1.2 Cancels . . . . . . . . . . . . . . . 14.1.3 Multithreaded RPC Applications . . . . . . . . . . . . . . . . . . . 14-2 14-3 14-5 14-6 14.2 Security and RPC: Using Authenticated Remote Procedure Calls . . . . . . . . . . . . . . . 14.2.1 Authentication . . . . . . . . . 14.2.2 Authorization . . . . . . . . . . 14.2.
Contents 16.5 Nested Calls and Callbacks . . . . . . . . . . . . . . 16-31 16.6 Routing Remote Procedure Calls 16.6.1 Obtaining an Endpoint 16.6.2 Buffering Call Requests 16.6.3 Queuing Incoming Calls 16.6.4 Selecting a Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16-33 16-36 16-40 16-42 16-44 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
OSF DCE Application Development Guide—Core Components 17.9.4 17.9.5 String Constants NULL Constants . . . . . . . . . . . . . . . . 17-15 17-15 17.10 Type Declarations . . . . . . . . . . . 17.10.1 Type Attributes . . . . . . . . . 17.10.2 Base Type Specifiers . . . . . . . . 17.10.3 Constructed Type Specifiers . . . . . . 17.10.4 Predefined Type Specifiers . . . . . . 17.10.5 Type Declarator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Contents 18.3.8 18.3.9 18.3.10 18.3.11 18.3.12 18.3.13 18.3.14 18.3.15 18.3.16 18.3.17 The code and nocode Attributes . . . The represent_as Attribute . . . . . The enable_allocate Attribute . . . . The heap Attribute . . . . . . . The extern_exceptions Attribute . . . The encode and decode Attributes . . . The cs_char Attribute . . . . . . . The cs_stag, cs_drtag, and cs_rtag Attributes The cs_tag_rtn Attribute . . . . . . The binding_callout Attribute . . . . 18.4 Summary of Attributes . . . . 18.
OSF DCE Application Development Guide—Core Components 22.3 About the GSSAPI . . . . . . . 22.4 UNIX System Security and DCE Security 22.5 . . . . . . . . . 22-2 . . . . . . . . . . 22-2 What Authentication and Authorization Mean . . . . . . . . . 22-3 . . . 22-4 22.6 Authentication, Authorization, and Data Protection in Brief 22.7 . Summary of DCE Security Services and Facilities . . 22.7.1 Interfaces to the Security Server . . . . 22.7.
Contents Chapter 25. GSSAPI Credentials . . . . . . . . . . 25-1 25.1 Using Default Credentials . . . . . . . . . . . . 25.1.1 Initiating a Security Context . . . . . . . . . 25.1.2 Accepting a Security Context . . . . . . . . . . . . . . . . . 25-2 25-2 25-2 25.2 Creating New Credential Handles . . . . . . . . 25.2.1 Initiating a Security Context with New Credential Handles . . . . . . . . . . . . . . 25.2.2 Accepting a Security Context Using New Credential Handles . . . . . . . . . . . . .
OSF DCE Application Development Guide—Core Components 28.3.2 28.3.3 Creating and Managing Attribute Instances . . . . Reading Attribute Instances . . . . . . . . . . . . . . . 28-15 28-17 28.4 The Attribute Trigger Facility . . . . . . . . . . . . 28.4.1 Defining an Attribute Trigger/Attribute Association . . . . . . . . . . . . . . . 28.4.2 Trigger Binding . . . . . . . . . . . . . 28.4.3 Access Control on Attributes with Triggers . . . . . . . 28-19 . . . . . . 28-20 28-21 28-23 28.
Contents Chapter 30. The Key Management API . 30.1 R e t r i e v i n g . . a 30.2 Changing a Key . . . . . . Key . . . 30.3 Automatic Key Management . . . . . . . . . . . . 30-1 . . . . . . . . . . . . . . . . . . 30-1 . . . . . . . . . . . 30-2 . . . . . . . . . . . . . . 30-3 . . . . . . . . . . . . . . 30-3 30.5 Deleting a Compromised Key . . . . . . . . . . . . . . 30-3 . . . . . . . . . . . . .
OSF DCE Application Development Guide—Core Components 35.1 The Client-Side API . . . . . . . . . 35.2 The Password Management Network Interface . Index xvi . . . . . . . . . . . . . . . . . . . . . . . . . . . Tandem Computers Incorporated . . . . . . . . . . . 35-2 . . . . .
Contents LIST OF FIGURES Figure 2-1. The dced Entry Lists . . . . . . . . . . . . . . . . . . 2-7 Figure 2-2. Structure of an Entry . . . . . . . . . . . . . . . . . . 2-7 Figure 2-3. Accessing Hostdata . . . . . . . . . . . . . . . . . . . 2-10 . . . . . . . . . . . . . . . . . 3-7 . . . . . . . . . 4-12 Figure 3-1. sams and DCE Messages Figure 4-1. Serviceability and DCE Applications . . . . . Figure 6-1.
OSF DCE Application Development Guide—Core Components Figure 14-7. NSI Attributes .................... 1 4 - 1 5 Figure 14-8. Parts of a Global Name . . . . . . . . . . . . . . . . . . 14-17 Figure 14-9. Possible Information in a Server Entry 14-19 . . . . . . . . . . . . . Figure 14-10. Possible Mappings of a Group . . . . . . . . . . . . . . . . 14-19 Figure 14-11. Possible Mappings of a Profile . . . . . . . . . . . . . . . . 14-21 Figure 14-12.
Contents Figure 28-1. The sec_attr_schema_entry_t Figure 28-2. The sec_attr_t Data Type Data Type ............. 28-10 . . . . . . . . . . . . . . . . . 28-15 Figure 28-3. The sec_attr_bind_info_t Data Type .............. Figure 31-1. ACL Program Interfaces . . . . . . . . . . . . . . . 31-2 Figure 31-2. Protection with Extended Naming . . . . . . . . . . . . . . . 31-5 . . . . . . . . . . . 33-4 Figure 33-1. Event Number Formats . . . . . .
OSF DCE Application Development Guide—Core Components LIST OF TABLES TABLE 2-1. API Routines for Remote Server Management TABLE 4-1. Serviceability Message Severities . . . . . . . . . . . . . . . . 2-19 . . . . . . . . . . 4-21 TABLE 4-2. Serviceability Message Processing Specifiers . . . . . . . . . . . TABLE 4-3. Remote Operations by Application Servers . . . . . . . . . . . . 4-39 . . . . . . . . . 7-15 . . . . . . . .
Chapter 1.
OSF DCE Application Development Guide—Core Components data for all servers on the host, and a database of endpoints (server addresses) through which running servers can be contacted. Some of the functions that you can remotely perform include starting and stopping servers. • Application Message Service This service provides a convenient way to manage readable character strings of information that are usually displayed to application users.
Chapter 2. DCE Host Services Every DCE host must maintain certain kinds of data about itself and the servers it provides. For example, each host stores configuration data about its DCE environment, and it also stores data about servers registered and running on the host. In addition, each host needs some services to not only manage this data but also to administer the host and DCE servers. For example, a service that can start and stop specific servers has obvious value.
OSF DCE Application Development Guide—Core Components Of course, in a distributed environment, these data and services must be easily yet securely accessible from other hosts. The DCE host daemon (dced) is a continuously running program on each host that provides access to the host services either locally on that host or remotely from another host. 2.
DCE Host Services manage them. This also allows for scalability because it is impractical to manage a large system by logging into all its hosts. The features of dced are greatly enhanced when used remotely. Of course, an administrator can use dced to locally manage a host’s services, but dced’s real power is in remotely managing system and application server configurations, key tables, server startup, login configurations, and cell information.
OSF DCE Application Development Guide—Core Components • Elements matching both an interface identifier and object UUID Administrators can manage the endpoint map by using dcecp with the endpoint object. You can use the dced_server_disable_if() routine to mark as disabled all the endpoints for a specific interface.
DCE Host Services 3. Access (read or write) the actual data for the entries obtained or peform other functions appropriate for the service. For example, if your application reads the hostdata management service’s cell name entry, the API accesses dced which may actually read the data from a file. For another example, if your application established a binding to the security validation service, it could validate the security daemon. 4. Release the resources obtained in step 2. 5.
OSF DCE Application Development Guide—Core Components Since the dced_binding_from_rpc_binding( ) routine already knows which host to bind to from an RPC binding input parameter, it uses one of the global variables defined for each service (instead of a string) to specify which dced service to use. 2.4.2 The dced Programs Maintains Entry Lists One dced service’s data is very different from another’s (for example, server configuration data versus key table data), but you manipulate the data in a similar way.
DCE Host Services Figure 2-1. The dced Entry Lists dced hostdata entry list .. . Host Data Entry .. . Server Management Entry Lists srvrconf entry list srvrexec entry list .. . .. . Server Configuration Entry Server Execution Entry .. . .. . keytab entry list .. . Key Table Entry .. . Although an entry can be associated with many different kinds of data items, all entries have the same structure, shown in Figure 2-2. Figure 2-2.
OSF DCE Application Development Guide—Core Components storage_tag The storage tag locates the actual data. Each service knows how to interpret this tag to find the data. For example, some data is stored in a file, the name of which is contained in the storage tag. Other data is stored in memory and the storage tag contains a pointer to the memory location. The data type is dced_string_t. 2.4.
DCE Host Services the objects in an entry list. The output includes the address of an allocated buffer of data and a count of the number of objects the buffer contains. The data type in the buffer depends on the service used. display() This is an application-specific routine that displays the data. Before the data is displayed, it must be interpreted depending on the service.
OSF DCE Application Development Guide—Core Components 2.4.4 Managing Individual dced Entries Figure 2-3 shows examples of individual dced entries and the locations of associated data. The data item name or its UUID is used to find an entry, and then the storage tag is used to find the data. Figure 2-3. Accessing Hostdata DCE Host dced hostdata entry UUID . . . file location srvrexec entry UUID . . . object location srvrconf entry data UUID . . . object location data keytab entry UUID . . .
DCE Host Services structure. The server management data is stored in memory. The dced program uses UUIDs (maintained in the entry lists by dced) to find an entry. The location of the data in memory is indicated by the storage tag. The data returned for one entry is a structure of server data (server_t). All data for the srvrconf and srvrexec entries are accessed from memory for fast retrieval, but the srvrconf data is also stored on disk for use when a host needs to reboot.
OSF DCE Application Development Guide—Core Components Each routine is described as follows: dced_binding_from_rpc_binding() The dced_binding_from_rpc_binding( ) routine returns a dced binding handle whose data type is dced_binding_handle_t. This binding handle is used in all subsequent dced API routines to access the service.
DCE Host Services 2.5 Managing Hostdata on a Remote Host Administrators typically use the dcecp hostdata object to remotely manage the data of the hostdata service. However, application developers can use the dced API for their own management applications or if dcecp does not handle a task in the desired way, such as for a browser of hostdata that uses a graphical user interface. 2.5.1 Kinds of Hostdata Stored Each hostdata item is stored in a file, and dced has a UUID associated with each.
OSF DCE Application Development Guide—Core Components int num_attr, str_size; sec_attr_enc_str_array_t *attr_array; . . . dced_binding_create(dced_c_service_hostdata, dced_c_binding_syntax_default, &dced_bh, &status); /*Create Entry Data */ uuid_create(&(entry.id), &status); entry.name = (dced_string_t)("NEWERprinter"); entry.description = (dced_string_t)("Configuration for a new printer."); entry.storage_tag = (dced_string_t)("/etc/NEWprinter"); /* Create the Attributes, one for this example */ data.
DCE Host Services instead of dced_hostdata_create(). dced_binding_free( ) Each call to the dced_binding_create( ) routine requires a corresponding call to dced_binding_free() to release the binding resources allocated. Use the dced_hostdata_delete( ) routine to delete application-specific hostdata items and their entries. For example, the printer installed in the example is easily removed with this routine.
OSF DCE Application Development Guide—Core Components sec_attr_enc_str_array_t *attr_array; unsigned_char_t *string_uuid, temp_string[200]; dced_attr_list_t attr_list; dced_binding_create(dced_c_service_hostdata, dced_c_binding_syntax_default, &dced_bh, &status); dced_hostdata_read(dced_bh, &dced_g_uuid_hostdata_post_proc, &dced_g_uuid_fileattr, &data_ptr, &status); /* Create New Array and Copy Old Data into it */ num_strings = data_ptr->attr_value.tagged_union.
DCE Host Services how the data is to be interpreted. In this example, we know the data to be read is plain text, so we use the global variable dced_g_uuid_fileattr to specify plain text rather than binary data (dced_g_uuid_binfileattr). Create a New Array The next few lines copy the existing array of print strings into a new array that has additional space allocated for the new data. dced_inq_id() This routine acquires the UUID dced that maintains for a known entry name.
OSF DCE Application Development Guide—Core Components Servers are typically configured by an administrator using the dcecp server object in a script after the server is installed on the host.
DCE Host Services TABLE 2-1.
OSF DCE Application Development Guide—Core Components dced_binding_create("srvrconf@hosts/somehost", dced_c_binding_syntax_default, &dced_bh, &status); dced_inq_id(dced_bh, server_name, &srvrconf_id, &status); if(status == error_status_ok) { puts("Configuration already exists for this server."); dced_binding_free(dced_bh, &status); return; } /* ___________setup a server_t structure ________________*/ uuid_create(&(conf.id), &status); conf.name = server_name; conf.entryname = (dced_string_t)"/.
DCE Host Services Set Up service_t Structures for Each Interface Each service that the server supports is represented by a service_t data structure that contains the interface specification, among other things. In this example the client stub for the interface was compiled with the program so that the interface specification (greetif_v1_0_c_ifspec) could be obtained without building the structure from scratch.
OSF DCE Application Development Guide—Core Components 2.6.3 Starting and Stopping Servers A server typically runs as persistent process or is started on demand when a client makes a remote procedure call to it. Management applications can start remote servers by using the dced_server_start( ) routine. This is a srvrconf routine that takes as input server configuration data in the form of an attribute list.
DCE Host Services name input. Each name used to identify an object of each service has a UUID. If dced maintains a UUID for a srvrexec object, the server is running. However, it is possible that the server is in an in-between state as it is starting up or shutting down. For a more robust check as to whether the server is running, use the dced_object_read( ) routine to read the server_t structure for the srvrexec object. If the exec_data.tagged_union.running_data.
OSF DCE Application Development Guide—Core Components To control the services of remote servers, management applications use the dced_server_disable_if() and dced_server_enable_if( ) routines. These routines work on the srvrexec object. When a service (interface) is disabled, a client that already knows about the service (through a binding handle to this interface and server) will no longer work because the interface is unregistered with the RPC runtime.
DCE Host Services 2.8 Managing Server Key Tables Keys for servers are analogous to passwords for human users. Keys also play a major role in authenticated remote procedure calls. Keys have some similarities with passwords. For example, server keys and user passwords have to follow the same change policy (or a more stringent one) for a given host or cell. This means that, just as a user has to periodically come up with a new password, a server has to periodically generate a new key.
OSF DCE Application Development Guide—Core Components dced_binding_set_auth_info(dced_bh, rpc_c_protect_level_default, rpc_c_authn_default, NULL, rpc_c_authz_dce, &status); dced_list_get(dced_bh, &entries, &status); for(i=0; i
DCE Host Services greater security risk because data is sent over the network. For remote access, these routines actually get all the keys during one remote procedure call to be more efficient and to minimize the time keys are being sent over the network. Earlier in this section we described how to change the key of a key table with the dced_keytab_change_key( ) routine.
Chapter 3.
OSF DCE Application Development Guide—Core Components Both of the DCE message facilities use XPG4 message catalog files (see the X/Open Portability Guide) to hold message text. The message catalogs are generated by a DCE utility (called sams) during the application development process, and must be installed in the correct platform-dependent location in order for the DCE messaging library routines to be able to find them (and, consequently, the messages) at runtime.
DCE Application Messaging Each line in a sams file consists of a simple header and value combination. The header indicates the meaning of the value being specified, and value is the value itself. A sams file for messaging use is normally made up of three parts (although only two parts are needed for the short example in this chapter).
OSF DCE Application Development Guide—Core Components 3.2.1.2 Processing the .sams File The entire sams file for the hello program is as follows: # Part I component hel # Part II start code text action explanation end hello_msg "Hello World" "None required" "Greeting message for sample messaging program" We create the file with these contents and name it hel.sams.
DCE Application Messaging All that remains now is to create a simple C program that calls a DCE messaging routine to output the ‘‘Hello World’’ message. 3.2.1.3 Program Source The complete source code for hello.c is as follows: #include #include "dcehelmsg.h" int main( int char { argc, *argv[]) dce_printf(hello_msg); } To build the application, you simply • Process the hel.sams file with the sams command. • Build and link hello from the following modules: — dcehelmsg.c — hello.
OSF DCE Application Development Guide—Core Components file messages as arrays in program memory is contained in the dcecmpmsg.c file generated with the sams -o t option. To initialize the table before using it the application must also call the dce_msg_define_msg_table( ) routine, described in Section 3.3.3. The message routines will, when called, attempt to use the application’s message catalog; but if it cannot be found, the in-memory table will be used instead. 3.2.
DCE Application Messaging Figure 3-1. sams and DCE Messages hel.sams dcehelmsg.man (doc) dcehelmsg.h sams dcehelmsg.c hello.c dce_printf(hello_msg); .. . . . . . . . . . . . . . . . . . . . . . . . .. .. ... .. .. dcehel.msg .. .. .. .. .. .. .. ... .. .. .. gencat .. .. .. .. (executed by .. .. sams ) ... ... .. .. .. .. .. .. dcehel.cat .. .. (message catalog) ... .. . . . . . . . . . . . . . . . . . . . . . . . .... dcehelmsg.sml (doc) dcehelmsg.
OSF DCE Application Development Guide—Core Components The sams output filenames are made up of the following pieces: tech_name + comp_name + part_name + extension where: tech_name Is the technology name (optionally specified at the top of the hel.sams file); by default dce. comp_name Is the component name (specified at the top of the hel.sams file); in this case, hel. part_name Is a substring identifying the particular file; for example, svc or msg, and so on.
DCE Application Messaging — dce_sprintf() — dce_pgm_printf() — dce_pgm_sprintf( ) — dce_pgm_fprintf() • Message retrieval routines These routines retrieve a specified message. If necessary, the message catalog is opened. — dce_msg_get_msg() — dce_msg_get() — dce_msg_get_default_msg( ) — dce_error_inq_text() • Message table routines Miscellaneous routines for manipulating in-memory message tables.
OSF DCE Application Development Guide—Core Components 3.3.1 Message Output Routines The six message output routines in this group essentially reproduce the functionality of printf(), fprintf( ), and sprintf(), with the difference being that they operate on a specified message rather than on a string variable. The routines can be called without any special preparation (but see the descriptions of the three dce_pgm_ routines).
DCE Application Messaging The following code fragment shows how dce_sprintf() might be called to write the message (with some argument values) into a string: unsigned char *my_msg; my_msg = dce_sprintf(arg_msg, 2, 8); /* Process my_msg as appropriate...
OSF DCE Application Development Guide—Core Components where nnnn is the process ID of the application making the call. dce_error_inq_text() Opens a message catalog, extracts a message identified by a message ID, and places the message in the space pointed to by the text parameter. If the message catalog is inaccessible, and there is a default message in memory, the default message is copied into the space passed.
DCE Application Messaging it. If the message catalog is inaccessible, and the message exists in an in-memory table, then this message (the default message) is returned in the allocated space. If neither the catalog nor the default message is available, an error status code is placed in the status output parameter. The following code fragment shows how dce_msg_get_msg( ) might be called to retrieve the ‘‘Hello World’’ message defined in the example program earlier in this chapter: #include
OSF DCE Application Development Guide—Core Components #include #include #include "dcehelmsg.h" unsigned char unsigned32 *my_msg; status; <. . .> my_msg = dce_msg_get_default_msg(hello_msg, &status); printf("Message is: %s\n", my_msg); Note that, in order for this call to be successful, dce_msg_define_msg_table( ) must first have been called to set the table up in memory. For an example of how this is done, see the following section. 3.3.
DCE Application Messaging <. . .> dce_msg_define_msg_table(hel_msg_table, sizeof(hel_msg_table) / sizeof(hel_msg_table[0]), &status); dce_msg_translate_table( ) Makes a new copy of the specified in-memory message table (that is, updates the table with the contents of a message table, which has changed because of a change in locale).
OSF DCE Application Development Guide—Core Components The following code fragment shows how dce_msg_cat_open( ) might be called to open the message catalog containing the ‘‘Hello World’’ message defined for the example application earlier in this chapter: #include #include #include "dcehelmsg.h" dce_msg_cat_handle_t unsigned32 hel_msg_handle; status; <. . .
DCE Application Messaging The routine will fail if the message catalog is not installed or if LANG is not properly set. The following code fragment shows how dce_msg_get_cat_msg( ) might be called to retrieve the ‘‘Hello World’’ message: #include #include #include "dcehelmsg.h" unsigned32 unsigned_char_t status; *msg; <. . .
Chapter 4. Using the DCE Serviceability Application Interface DCE serviceability was originally developed simply as a way of standardizing server messages.
OSF DCE Application Development Guide—Core Components specify message routing, and those that specify some action (usually some form of program exit) that should be taken immediately after the message is written. The effect of the presence of a severity attribute is to cause the message text to contain a severityidentifying string when displayed or written.
Using the DCE Serviceability Application Interface the index of the message text within the subtable. By convention, cmp is a three-character code identifying the application as a whole; serviceability uses it to group all of an application’s message and table data together. Specifying svc_c_sev_error gives the message the severity of ‘‘error;’’ the significance of severity in serviceability will be explained in the following sections.
OSF DCE Application Development Guide—Core Components The component name that you specify at the top of a sams file must consist of a threecharacter (no more, no less) string. For the ‘‘Hello World’’ program, we will use the component name hel: # Part I of simple sams file ... component hel The hel string will be used to identify all the files and data structures that sams will generate from the file.
Using the DCE Serviceability Application Interface main is the name of the subcomponent, specified in quotes. hel_i_svc_main is a name that will be used (later on in the file) to identify a message that describes the subcomponent. (Note that sams assigns values to all of these indexes automatically.) The third (and final) part of the sams file consists of a series of records that specify the messages themselves. Each record is delimited by the start and end keywords.
OSF DCE Application Development Guide—Core Components To change the default collection size, specify collection size dddd (where dddd is the collection size you desire) in a separate line in Part 1 of the sams file. code Identifies the message. sub-component Identifies the subcomponent that will use the message. (This must also have been defined in Part II of the sams file.) attributes Specifies various things about the message: what kind of message it is, how it is to be routed, and so on.
Using the DCE Serviceability Application Interface 4.1.2.
OSF DCE Application Development Guide—Core Components dcehelmsg.sml Code for a subsection documenting the messages. dcehelmsg.man Code for a reference page subsection documenting the messages. dcehelmsg.idx Code for building an index for the subsection. dcehelsvc.c Code defining the serviceability table. (This is a separate table containing the serviceability subcomponent identifying messages specified at the end of the sams file.) dcehelsvc.h Header file containing definitions for dcehelsvc.c.
Using the DCE Serviceability Application Interface hel_svc_handle = dce_svc_register(hel_svc_table, \ (idl_char*)"hel", &status); if (status != svc_s_ok) { printf("dce_svc_register failed\n"); exit(1); } This call is the only initialization we need if we have installed our message catalog and are willing to depend on the message(s) being extracted from there.
OSF DCE Application Development Guide—Core Components contained in dcehelmac.h. A convenience macro is generated for every message in a sams file that has both subcomponent and attributes specified. The macro’s name is formed from the uppercase version of its code value (as specified in the sams file), with the string _MSG appended. The complete source code for hello_svc.c is as follows: #include #include #include #include #include #include #include
Using the DCE Serviceability Application Interface 4.1.2.4 Building and Running the Program To build the application, you simply perform these steps: 1. Process the hel.sams file with the sams command 2. Build and link hello_svc from the the following modules: • dcehelmsg.c • dcehelsvc.c • hello_svc.c 4.1.2.5 Fields of a Serviceability Message When executed, the program will print a message similar to the following: 1994-04-05-20:13:34.500+00:00I----- PID#9467 NOTICE hel main hello_svc.
OSF DCE Application Development Guide—Core Components establish the application’s program name, that name would appear in this field instead of the process ID. See Section 4.3.1 for further information. severity The severity level of the message (NOTICE in the example). component The component name of the program that wrote the message (hel in the example). subcomponent The subcomponent that wrote the message (main in the example; note that this program has only one subcomponent).
Using the DCE Serviceability Application Interface hel.sams dcehelmac.h dcehelmsg.man (doc) dcehelsvc.h sams dcehelsvc.c dcehelmsg.c dcehelmsg.h hello_svc.c dce_svc_printf(HEL_S_HELLO_MSG); .. . . . . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. dcehel.msg .. .. .. ... .. .. .. .. .. .. .. .. gencat .. (executed by ... .. sams) .. .. .. .. .. .. .. .. ... ... dcehel.cat .. .. .. (message catalog) .. .. . . . . . . . . . . . . . . . . . . . . . . .... dcehelmsg.sml (doc) dcehelmsg.
OSF DCE Application Development Guide—Core Components Because we executed the simplest form of the sams command (that is, without specifying any output flags), the full repertory of sams output files was created, even though the following files were not needed for our application: • dcehel.msg and dcehel.cat The file dcehel.msg is input to gencat when it is invoked by sams to create dcehel.cat, the message catalog.
Using the DCE Serviceability Application Interface 4.2.2 Components and Subcomponents The very first step in incorporating serviceability into a server is to analyze it into functionally discrete modules (called subcomponents), each of which will usually be associated with a separate set of messages. The program itself is regarded as the component.
OSF DCE Application Development Guide—Core Components deletion of tickets, threads, files, sockets, RPC endpoints, or other objects; message transfer, including name lookup, binding, and forwarding; directory maintenance (including caching, advertising, skulking, and replication); and database maintenance (including replication or synchronization).
Using the DCE Serviceability Application Interface • dce_svc_register() This is the function call for registering a serviceability message table. Either it or DCE_SVC_DEFINE_HANDLE( ) must be called before any routines can be called to display or log messages. An example of its use can be seen in the illustrated hello_svc.c code. • dce_svc_unregister() This is the function call for destroying a serviceability handle.
OSF DCE Application Development Guide—Core Components • dce_svc_printf( ) This is the normal call for writing or displaying serviceability messages. It cannot be called with a literal text argument; instead, the message text and other necessary information must be pre-specified in a file that is processed by the sams utility, which in turn outputs sets of tables from which the messages are extracted for output. The tutorial in Section 4.1.2 provides a brief example of how this is done.
Using the DCE Serviceability Application Interface — svc_c_route_nolog However, most routing is done either by passing specially formatted strings to dce_svc_routing() or by environment variable values. See Section 4.3.4 for more detailed information. severity The available severity attribute constants are — svc_c_sev_fatal — svc_c_sev_error — svc_c_sev_warning — svc_c_sev_notice — svc_c_sev_notice_verbose For more detailed information, see Section 4.3.3.
OSF DCE Application Development Guide—Core Components 1994-04-06-20:06:33.113+00:00I----- hello NOTICE hel main hello_svc.c This message has exactly 2 not 7 argument(s) line_nr 0xa444e208 4.3.2 Extended Format Notation for Message Text A slightly extended notation allows you to define message texts in the sams file that will (if desired) have format specifiers in their application code forms (that is, in the .c and .
Using the DCE Serviceability Application Interface TABLE 4-1. Serviceability Message Severities ______________________________________________________________________ Name Specifier Meaning ______________________________________________________________________ ______________________________________________________________________ FATAL svc_c_sev_fatal A fatal error has occurred; the program is about to exit.
OSF DCE Application Development Guide—Core Components 4.3.4 Howto Route Messages Serviceability messages can be written to any of the normal output destinations. Routing for serviceability messages can be specified in any of three different ways (in ascending order of precedence): 1. By the contents of a routing file 2. By the contents of a routing environment variable 3.
Using the DCE Serviceability Application Interface sev:out_form:dest[;out_form:dest . . . ][GOESTO: {sev | comp}] where: sev Specifies the severity level of the message, and must be one of the following: • FATAL • ERROR • WARNING • NOTICE • NOTICE_VERBOSE The meanings of these severity levels are explained in detail in Section 4.3.3.
OSF DCE Application Development Guide—Core Components The multiple files are named by appending a dot to the simple specified name, followed by the current generation number. When the number of entries in a file reaches the maximum specified by count, the file is closed, the generation number is incremented, and the next file is opened.
Using the DCE Serviceability Application Interface means that WARNING messages should show up in three places: twice to stderr, and then once to the file /tmp/foo. Note that a GOESTO specification should be the last element in a multidestination route specification. 4.3.4.2 Routing by Environment Variable Serviceability message routing can also be specified by the contents of certain environment variables.
OSF DCE Application Development Guide—Core Components unsigned_char_t *my_route = "NOTICE:STDOUT:-;TEXTFILE:/tmp/my_log"; unsigned_char_t *error_route = "ERROR:TEXTFILE:/tmp/errors_%ld"; dce_svc_routing(my_route, &status); if (status != svc_s_ok) { printf("dce_svc_routing failed\n"); exit(1); } dce_svc_routing(error_route, &status); if (status != svc_s_ok) { printf("dce_svc_routing failed\n"); exit(1); } 4.3.4.
Using the DCE Serviceability Application Interface _______________________________________________________________________ Name Attribute Meaning ________________________________________________________ __________________________________________________________ BINFILE Write binary log entry. _________________________________________________________ TEXTFILE Write human-readable text. _________________________________________________________ FILE Equivalent to TEXTFILE.
OSF DCE Application Development Guide—Core Components char *argtypes The format-specifier string for the message. int argtypes_size The number of format specifiers for the message. char *fac_name The component or subcomponent (‘‘facility’’) name string. char *message_text Message text string. char *progname Program name string, set by the application’s call to dce_svc_set_progname(). char *file Filename string identifying file from which entry was read.
Using the DCE Serviceability Application Interface 1994-04-05-20:13:34.500+00:00I----- PID#9467 NOTICE hel main hello_svc.c line_nr 0xa444e208 Hello World In this example, the first line is the message prolog, and the second line is the message text.
OSF DCE Application Development Guide—Core Components However, the serviceability routines will still, by default, attempt first to retrieve a specified message from the message catalog, even if an in-memory table has been initialized; only if the message catalog cannot be found will the in-memory table be used. You can change the default behavior of the serviceability routines by setting the SVC_NOXPGCAT environment variable to 1 (or any nonzero value).
Using the DCE Serviceability Application Interface structure by calling one of the DCE DTS utc_...( ) routines. const char *argtypes The format-specifier string for the message. unsigned32 table_index sams file in Section 4.1.2.1. unsigned32 attributes Message attributes, ORed together. unsigned32 message_index Index number of the message in the message table (for example, hel_s_hello in the example at the beginning of this chapter). char *format Format argument values for the message.
OSF DCE Application Development Guide—Core Components and which could be altered by calling the filter control routine below.
Using the DCE Serviceability Application Interface /***** * install_filters-- calls dce_svc_define_filter() to install * the above 2 routines. Note that this must * be done after dce_svc_register() is * called, not before. *****/ void install_filters() { unsigned32 status; dce_svc_define_filter(hel_svc_handle, hel_filter, \ hel_filter_control, &status); } 4.3.
OSF DCE Application Development Guide—Core Components The following call in hello_svc.c would have written this message to standard error (because that is the routing specified in the sams file), provided that debug level 3 had been activated: DCE_SVC_LOG((HEL_S_DEBUG_MESSAGE_1_MSG)); Note the use of the double parentheses. This is made necessary by the fact that it is a macro that takes a variable number of arguments. Note alse the use of the convenience macro form of the message.
Using the DCE Serviceability Application Interface This macro can be used to test the active debug level and avoid calling a debug output routine if the level of its message is disabled at the time of the call (disabling the level does not stop any routines from being executed; it only suppresses the output messages at that level). See Section 4.3.13 for more information. • DCE_SVC_DEBUG_IS( ) Tests the active debug level for a subcomponent.
OSF DCE Application Development Guide—Core Components • If DCE_SVC_DEBUG() or DCE_SVC_LOG() is used to print the message, the debug level is specified in the call. The debug level can be set by calling dce_svc_debug_set_levels( ) and passing to it a specially formatted string (the debug level is also set when debug routing is specified; see the next section for further information). Levels can be separately specified for subcomponents.
Using the DCE Serviceability Application Interface • svc_c_debug4 • svc_c_debug5 • svc_c_debug6 • svc_c_debug7 • svc_c_debug8 • svc_c_debug9 4.3.12.
OSF DCE Application Development Guide—Core Components unsigned_char_t *debug_routes = \ "hel:*.4:TEXTFILE:/tmp/hel_debug_log_%ld;STDERR:-"; A debug level of svc_c_debug4 is specified, and all debug messages of that level or lower will be written both to standard error and in text form to the following file: /tmp/hel_debug_log_process_ID where process_ID is the process ID of the program writing the messages.
Using the DCE Serviceability Application Interface For example, developers should understand the implications of supplying function calls as arguments to serviceability debug output routines (such as DCE_SVC_DEBUG). If the debug code is compiled in (that is, if DCE_DEBUG is defined), then the parameterized function calls will always be executed because the output routine itself will still be called—even though it will produce no output.
OSF DCE Application Development Guide—Core Components _______________________________________________________________________________ Server ‘‘Implementation’’ Library Routine Purpose _______________________________________________________________________________ com _svc_set_route( ) dce_svc_routing() Remotely sets serviceability message routing.
Using the DCE Serviceability Application Interface 3. Runtime steps • At server startup: The binding handles that the server receives from the RPC runtime, and which it then registers both with the Name Server Interface (NSI) and the endpoint mapper under its ‘‘own’’ interface, must also be registered to the endpoint mapper with the serviceability interface. Note that servers do not explicitly register the serviceability interface with the NSI.
OSF DCE Application Development Guide—Core Components { if (!your_test_write_access(h)) *st = no_authorization_error; else dce_svc_routing(where, st); } /***** * * hel_svc_set_dbg_route -- remote call-in to set debug routing. * *****/ static void hel_svc_set_dbg_route( handle_t h, idl_byte where[], error_status_t *st ) { if (!your_test_write_access(h)) *st = no_authorization_error; else dce_svc_debug_routing(where, st); } <. . .> /***** * * hel_svc_inq_stats -- remote request for operating statistics.
Using the DCE Serviceability Application Interface { if (!your_test_access(h)) *st = no_authorization_error; else /* operation is currently not implemented in library ... *st = svc_s_no_stats; */ } /* /* /* /* /* /* /* /* /* /* /* */ The table of slots is created by IDL from the service.idl */ file, src/dce/utils/svc/service.idl, the output of which */ is service.h.
OSF DCE Application Development Guide—Core Components 4. Register both sets of binding handles with the endpoint map 5. Export both sets of binding handles to the namespace Note that (for brevity’s sake) status return checks have been omitted from this code. <. . .> /* Register server interface/type_uuid/epv associations /* with rpc runtime.
Using the DCE Serviceability Application Interface 4.3.14.4 Importing and Accessing the Remote Interface The following code fragments are intended to give an idea how a client might import both the hello_svc server’s interface and its exported serviceability interface. Note that (for brevity’s sake) status return checks have been omitted from this code. /* Import binding info from namespace. */ for (server_num = 0; server_num < nservers; server_num++) { /* Begin the binding import loop.
OSF DCE Application Development Guide—Core Components if ((svc_ret == 0) || (ret == 0)) { break; } } /* End the binding import loop. */ rpc_ns_binding_import_done(&import_context, &status); rpc_ns_binding_import_done(&svc_import_context, &status); } /* Annotate binding handles for security.
Chapter 5. The DCE Backing Store This chapter describes the backing store library that DCE provides for the convenience of programmers who are writing DCE servers. A backing store is a persistent database or persistent object store from which typed data can be stored and retrieved by a key. Note: Sometimes the backing store is called a database. For instance, the associated IDL file is dce/database.idl, and the name of the backing store routines begin with dce_db_.
OSF DCE Application Development Guide—Core Components A program can have more than one backing store open at the same time. 5.2 Using a Backing Store Although the backing store library is a generalized service, you are encouraged to use it in a particular, standardized way. You should use the header and the recommended IDL interface format that are described in the following sections. Standardized use will ease the transition to later developments in DCE. 5.
The DCE Backing Store /* The standard header for each "object" in the database.
OSF DCE Application Development Guide—Core Components dce_db_header_t header; /* Header must be first! */ /* (server-specific data goes here) */ } XXX_data_t; void XXX_data_convert( [in] handle_t [in, out] XXX_data_t [out] error_status_t ); h, *data *st } It should be compiled with the following Attribute Configuration File (ACF), which instructs the idl compiler to write the data conversion routine into the XXX_cstub.c file: interface XXX { [encode, decode] XXX_data_convert([comm_status] st); } 5.
The DCE Backing Store 5.5.2 Conformant Arrays Not Allowed You cannot use conformant arrays in objects stored to a backing store. This is because the IDL-generated code that encodes (pickles) the structure has no way to predict or detect the size of the array. When the object is fetched, there will likely be insufficient space provided for the structure, and the array’s data will destroy whatever is in memory after the structure. To illustrate the problem more clearly, here is an example.
OSF DCE Application Development Guide—Core Components 5.6 The Backing Store Routines Many of the backing store routines appear in three versions: plain, by name, and by UUID. The plain version will work with backing stores that were created to be indexed either by name, or by UUID, while the restricted versions accept only the matching type. It is advantageous to use the restricted versions when they are appropriate because they provide type checking by the compiler, as well as visual clarity of purpose.
The DCE Backing Store The following routines store data into a backing store: dce_db_store( ) This routine can store into a backing store that is indexed by name or by UUID. The key’s type must match the flag that was used in dce_db_open( ). dce_db_store_by_name() This routine can store only into a backing store that is indexed by name. dce_db_store_by_uuid() This routine can store only into a backing store that is indexed by UUID.
OSF DCE Application Development Guide—Core Components 5.6.5 Making or Retrieving Headers The dce_db_std_header_init( ) routine initializes a standard backing store header from the values the caller provides in its arguments. It places the values into the header only and does not write into the backing store file. The dce_db_header_fetch() routine retrieves the header of an object in the backing store. 5.6.
The DCE Backing Store dce_db_open( ). dce_db_delete_by_name() This routine deletes an item only from a backing store that is indexed by name. dce_db_delete_by_uuid( ) This routine deletes an item only from a backing store that is indexed by UUID. To delete an entire backing store, ensure that the data file is not open, and remove it. There is only one file. 5.6.8 Locking and Unlocking a Backing Store The dce_db_lock( ) and dce_db_unlock( ) routines lock and unlock a backing store.
OSF DCE Application Development Guide—Core Components phone_record_t } phone_data_t; ph; /* * The following routine returns the entire contents of the * directory from the backing store by using the iteration * routines.
The DCE Backing Store return; } if (e_array->count == 0) { /* No items, nothing to do */ dce_db_unlock(db_h, st); return; } /* Allocate the space for the output. */ e_array->entry = rpc_sm_allocate( e_array->count*sizeof(e_array->entry[0]),st); if (*st != rpc_s_ok) { dce_fprintf(stderr, *st); /* or some other treatment */ return } dce_db_iter_start(db_h, st); i = 0; while (TRUE) { /* Get the next key.
Part 2.
Chapter 6. Introduction to Multithreaded Programming DCE Threads is a user-level (nonkernel) threads package based on the pthreads interface specified by POSIX in 1003.4a, Draft 4. This chapter introduces multithreaded programming, which is the division of a program into multiple threads (parts) that execute concurrently. In addition, this chapter describes four software models that improve multithreaded programming performance. A thread is a single sequential flow of control within a program.
OSF DCE Application Development Guide—Core Components You can think of threads as executing simultaneously, regardless of the number of processors present. You cannot make any assumptions about the start or finish times of threads or the sequence in which they execute, unless explicitly synchronized. • Shared Resources An advantage of using multiple threads over using separate processes is that the former share a single address space, all open files, and other resources.
Introduction to Multithreaded Programming certain rooms or performs certain types of work (washing floors, polishing furniture, and so forth), and each works independently. Figure 6-1 shows a task performed by three threads in a work crew model. Figure 6-1. Work Crew Model TASK Thread A Setup Thread B Cleanup Thread C (Time) 6.2.3 Pipelining Model In the pipelining model, a task is divided into steps.
OSF DCE Application Development Guide—Core Components 6.2.4 Combinations of Models You may find it appropriate to combine the software models in a single program if your task is complex. For example, a program could be designed using the pipelining model, but one or more steps could be handled by a work crew. In addition, tasks could be assigned to a work crew by taking a task from a work queue and deciding (based on the task characteristics) which threads are needed for the work crew. 6.
Introduction to Multithreaded Programming • Blocking Calls Certain system or library calls may cause an entire process to block while waiting for the call to complete, thus causing all other threads to stop executing. Chapter 8 discusses blocking in more detail.
Chapter 7. Thread Concepts and Operations This chapter discusses concepts and techniques related to DCE Threads.
OSF DCE Application Development Guide—Core Components • Terminated The thread has completed all of its work. Figure 7-1 shows the transitions between states for a typical thread implementation. Figure 7-1. Thread State Transitions Waiting Ready Running Terminated The operations that you can perform include starting, waiting for, terminating, and deleting threads. 7.1.1 Starting a Thread To start a thread, create it using the pthread_create() routine.
Thread Concepts and Operations • An error occurs in the thread. Examples of errors that cause thread termination are programming errors, segmentation faults, or unhandled exceptions. 7.1.3 Waiting for a Thread to Terminate A thread waits for the termination of another thread by calling the pthread_join( ) routine. Execution in the current thread is suspended until the specified thread terminates.
OSF DCE Application Development Guide—Core Components 7.3 Attributes Objects An attributes object is used to describe the behavior of threads, mutexes, and condition variables. This description consists of the individual attribute values that are used to create an attributes object. Whether an attribute is valid depends on whether it describes threads, mutexes, or condition variables.
Thread Concepts and Operations 7.3.3 Thread Attributes A thread attributes object allows you to specify values for thread attributes other than the defaults when you create a thread with the pthread_create( ) routine. To use a thread attributes object, perform the following steps: 1. Create a thread attributes object by calling the routine pthread_attr_create(). 2. Call the routines discussed in the following subsections to set the individual attributes of the thread attributes object. 3.
OSF DCE Application Development Guide—Core Components • SCHED_BG_NP (Background) Like SCHED_OTHER and SCHED_FG_NP, SCHED_BG_NP ensures that all threads, regardless of priority, receive some scheduling. However, SCHED_BG_NP can be denied execution by the SCHED_FIFO or SCHED_RR policies. The BG stands for background.
Thread Concepts and Operations 7.3.3.4 Stacksize Attribute The stacksize attribute is the minimum size (in bytes) of the memory required for a thread’s stack. The default value is machine dependent. Set this attribute by calling the pthread_attr_setstacksize( ) routine. 7.3.4 Mutex Attributes A mutex attributes object allows you to specify values for mutex attributes other than the defaults when you create a mutex with the routine pthread_mutex_init( ).
OSF DCE Application Development Guide—Core Components by another thread, the thread requesting the lock is blocked when it tries to lock the mutex if you call pthread_mutex_lock( ) (see Figure 7-2). The blocked thread continues and is not blocked if you call pthread_mutex_trylock( ). Figure 7-2. Only One Thread Can Lock a Mutex var access lock mutex_var Thread A block Thread B Each mutex must be initialized. (To initialize mutexes as part of the program’s one-time initialization code, see Section 7.
Thread Concepts and Operations • A nonrecursive mutex is locked only once by a thread, like a fast mutex. If the thread tries to lock the mutex again without first unlocking it, the thread receives an error. Thus, nonrecursive mutexes are more informative than fast mutexes because fast mutexes block in such a case, leaving it up to you to determine why the thread no longer executes. Also, if someone other than the owner tries to unlock a nonrecursive mutex, an error is returned.
OSF DCE Application Development Guide—Core Components proceed m utex_ready and unlock System activity (transparent to thread) (unlock) wait (lock) YES wait NO ready read predicate lock mutex_ready Thread A First, thread A locks the mutex named mutex_ready that is associated with the condition variable. Then it reads the predicate associated with the condition variable named ready.
Thread Concepts and Operations Thread B updates the predicate named ready associated with the condition variable to the state thread A is waiting for. It also executes a signal on the condition variable while holding the mutex mutex_ready. Figure 7-5. Thread A Wakes Up and Proceeds var access lock mutex_var Thread A block Thread B Thread A wakes up, verifies that the condition variable is in the correct state, and proceeds to execute task Y (see Figure 7-3).
OSF DCE Application Development Guide—Core Components 7.4.3 Other Synchronization Methods There is another synchronization method that is not anonymous: the join primitive. This allows a thread to wait for another specific thread to complete its execution. When the second thread is finished, the first thread unblocks and continues its execution. Unlike mutexes and condition variables, the join primitive is not associated with any particular shared data. 7.
Thread Concepts and Operations The pthread_keycreate() routine generates a unique key value that is shared by all threads in the process. This key is the identifier of a piece of thread-specific data. Each thread uses the same key value to assign or retrieve a thread-specific value. This keeps your data separate from other thread-specific data. One call to the pthread_keycreate() routine creates a cell in all threads.
OSF DCE Application Development Guide—Core Components processes that do not have specific places for cancel requests. Asynchronous cancelability is disabled by default. Disable asynchronous cancelability when calling threads routines or any other runtime library routines that are not explicitly documented as cancel-safe. Note: If general cancelability is disabled, the thread cannot be canceled, regardless of whether asynchronous cancelability is enabled or disabled.
Thread Concepts and Operations TABLE 7-1. Sample Thread Proprities ____________________ Thread Priority ____________________ ____________________ A Minimum B Middle C Middle D aximum M ____________________ Figures 7-6 through 7-8 show execution flows, depending on whether the threads use the SCHED_FIFO, S C H E D _ R R ,ro SCHED_OTHER (default) scheduling policy.
Chapter 8. Programming with Threads This chapter discusses issues you face when writing a multithreaded program and how to deal with those issues. The topics discussed in this chapter are as follows: • Calling UNIX services • Using signals • Nonthreaded libraries • Avoiding nonreentrant software • Avoiding priority inversion • Using synchronization objects • Signaling a condition variable 8.
OSF DCE Application Development Guide—Core Components calls any particular service at a time to avoid problems with system calls that are not thread-reentrant. Jacket routines are provided for UNIX input and output system calls (documented in any UNIX programmer’s manual) and the fork( ) and sigaction( ) system calls. Jackets are not provided for any other UNIX system calls or for any of the C runtime library services. See /usr/include/dce/cma_ux.h for the full list of jacket routines. 8.1.1.
Programming with Threads unpredictable behavior. For example, one thread has a mutex locked, and the state covered by that mutex is inconsistent while another thread calls the fork( ) routine. In the child process, the mutex will be in the locked state, and it cannot be unlocked because only the forking thread exists in the child process. Having the child reinitialize the mutex is unsatisfactory because this approach does not resolve the question of how to correct the inconsistent state in the child.
OSF DCE Application Development Guide—Core Components #undef fork 8.1.2 Blocking System Calls DCE Threads provides jacket routines that make certain system calls threadsynchronous. If calling one of these jacketed system calls would normally block the process, the jacket routine ensures that only the calling thread is blocked and that the process remains available to execute other threads. Examples of jacketed system calls include read(), write( ), open( ), socket(), send( ), and recv().
Programming with Threads process, but the lock owner will not exist to unlock it. Therefore, the resource protected by the lock will be permanently unavailable. The fact that there may be mutexes outstanding only becomes a problem if your code attempts to lock a mutex that could be locked by another thread at the time of the fork(). This means that you cannot call outside of your own code between the call to fork( ) and the call to exec().
OSF DCE Application Development Guide—Core Components 8.2.1.1 Terminating Signals Terminating signals result in the termination of the process by default. Whether a particular signal is terminating or not is independent of whether it is synchronously or asynchronously delivered. 8.2.1.2 Nonterminating Signals Nonterminating signals do not result in the termination of the process by default. Nonterminating signals represent events that can be either internal or external to the process.
Programming with Threads Asynchronous, terminating signals represent an occurrence of an event that is external to the process and, if unhandled, results in the termination of the process. When an asynchronous terminating signal is delivered, DCE Threads catches it and checks to see if any threads are waiting for it. If threads are waiting, they are awakened, and the signal is considered handled and is dismissed.
OSF DCE Application Development Guide—Core Components 8.2.2.2 The POSIX sigaction( ) Service The DCE Threads implementation of the POSIX sigaction( ) service allows for perthread handlers to be installed for catching synchronous signals. The sigaction( ) routine modifies behavior only for individual threads and works only for synchronous signals. Setting the signal action to SIG_DFL for a specific signal will restore the thread’s default behavior for that signal.
Programming with Threads In a multithreaded program, signals cannot be used in a modular way because, on most current UNIX implementations, signals are inherently a process construct. There is only one instantiation of each signal and of each signal handler routine for all of the threads in an application. If one thread handles a particular signal in one way, and a different thread handles the same signal in a different way, then the thread that installs its signal handler last handles the signal.
OSF DCE Application Development Guide—Core Components By using the global lock, you ensure that only one thread executes in outside libraries, which may call each other, and in unknown code. Using a single global lock is safer than using multiple local locks because it is difficult to be aware of everything a library may be doing or of the interactions that library can have with other libraries. 8.3.
Programming with Threads without interference. However, this is difficult to do successfully because the function may be called by many libraries. A global lock solves this problem by providing a universal lock. Any code that calls any nonreentrant function uses the same lock. To lock a global lock, call the pthread_lock_global_np( ) routine. To unlock a global lock, call the pthread_unlock_global_np( ) routine. Note: Many COBOL and FORTRAN compilers generate inherently nonreentrant code.
OSF DCE Application Development Guide—Core Components The following subsections discuss the use of mutexes to prevent two potential problems: race conditions and deadlocks. Also discussed is why you should signal a condition variable with the associated mutex locked. 8.6.
Programming with Threads 8.7 Signaling a Condition Variable When you are signaling a condition variable and that signal may cause the condition variable to be deleted, it is recommended that you signal or broadcast with the mutex locked. The recommended coding for signaling a condition variable appears at the end of this chapter. The following two C code fragments show coding that is not recommended.
Chapter 9. Using the DCE Threads ExceptionReturning Interface DCE Threads provides the following two ways to obtain information about the status of a threads routine: • The routine returns a status value to the thread. • The routine raises an exception. Before you write a multithreaded program, you must choose only one of the preceding two methods of receiving status. These two methods cannot be used together in the same code module. The POSIX P1003.
OSF DCE Application Development Guide—Core Components ENDTRY A try_block or a handler_block is a sequence of statements, the first of which may be declarations, as in a normal block. If an exception is raised in the try_block, the catch clauses are evaluated in order to see if any one matches the current exception. The CATCH or CATCH_ALL clauses absorb an exception; that is, they catch an exception propagating out of the try_block, and direct execution into the associated handler_block.
Using the DCE Threads Exception-Returning Interface Note that a CATCH_ALL handler and RERAISE could be used to do this, but the epilogue code would then have to be duplicated in two places, as follows: TRY try_block CATCH_ALL final_block RERAISE; ENDTRY { final_block } A FINALLY statement has exactly this meaning, but avoids code duplication. Note: The behavior of FINALLY along with the CATCH or CATCH_ALL clauses is undefined. Do not combine them for the same try_block.
OSF DCE Application Development Guide—Core Components 9.3 Operations on Exceptions An exception is an object that describes an error condition. Operations on exception objects allow errors to be reported and handled. If an exception is handled properly, the program can recover from errors. For example, if an exception is raised from a parity error while reading a tape, the recovery action may be to retry 100 times before giving up.
Using the DCE Threads Exception-Returning Interface If an exception is unhandled, the entire application process is terminated. Aborting the process, rather than just the faulting thread, provides clean termination at the point of error. This prevents the disappearance of the faulting thread from causing problems at some later point. An example of raising an exception is as follows: RAISE (parity_error); 9.3.
OSF DCE Application Development Guide—Core Components 9.3.5 Defining Epilogue Actions for a Block A FINALLY mechanism is provided so that multithreaded programs can restore invariants as certain scopes are unwound; for example, restoring shared data to a correct state and releasing locks. This is often the ideal way to define, in one place, the cleanup activities for normal or abnormal exit from a block that has changed some invariant.
Using the DCE Threads Exception-Returning Interface 9.4 Rules and Conventions for Modular Use of Exceptions The following rules ensure that exceptions are used in a modular way so that independent software components can be written without requiring knowledge of each other: • Use unique names for exceptions. A naming convention makes sure that the names for exceptions that are declared EXTERN from different modules do not clash.
OSF DCE Application Development Guide—Core Components Write functions that propagate exceptions to their callers so that the function does not modify any persistent process state before raising the exception. A call to the matching close call is required only if the open_file operation is successful in the current scope.
Using the DCE Threads Exception-Returning Interface TABLE 9-1. DCE Threads Exceptions _____________________________________________________________________ Exception Definition _____________________________________________________________________ _____________________________________________________________________ pthread_badparam_e An improper parameter was used. _____________________________________________________________________ pthread_cancel_e A thread cancellation is in progress.
OSF DCE Application Development Guide—Core Components _____________________________________________________________________ Exception Definition _____________________________________________________________________ exc_resoper_e An unhandled reserved operand fault exception occurred. _____________________________________________________________________ exc_SIGBUS_e An unhandled bus error signal occurred.
Part 3.
Chapter 10. DCE Threads Example The example in this chapter shows the use of DCE Threads in a C program that performs a prime number search. The program finds a specified number of prime numbers, then sorts and displays these numbers. Several threads participate in the search: each thread takes a number (the next one to be checked), sees if it is a prime, records it if it is prime, and then takes another number, and so on. This program shows the work crew model of programming (see Chapter 6).
OSF DCE Application Development Guide—Core Components protocol needs to be performed on all global data to ensure its visibility and protect its integrity. Each worker thread then determines if its current work item (a number) is prime by trying to divide numbers into it. If the number proves to be nondivisible, it is put on the list of primes. Cancels are explicitly turned off while working with the list of primes in order to better control any cancels that do occur.
DCE Threads Example 10.2 DCE Threads Example Body The following is the DCE Threads example: #include #include #include /* * Constants used by the example.
OSF DCE Application Development Guide—Core Components * for which the predicate (thread_hold) will be set by the parent. */ status = pthread_mutex_lock (&cond_mutex); check(status,"1:Mutex_lock bad status\n"); while (thread_hold) { status = pthread_cond_wait (&cond_var, &cond_mutex); check(status,"3:Cond_wait bad status\n"); } status = pthread_mutex_unlock (&cond_mutex); check(status,"4:Mutex_unlock bad status\n"); /* * Perform checks on ever larger integers until the requested * number of primes is found.
DCE Threads Example } else if (count == request) { not_done = 0; count++; for (notifiee = 0; notifiee < workers; notifiee++) { if (notifiee != my_number) { status = pthread_cancel ( threads[notifiee] ); check(status,"12:Cancel bad status\n"); } } } status = pthread_mutex_unlock (&prime_list); check(status,"13:Mutex_unlock bad status\n"); /* Reenable cancels */ pthread_setcancel(CANCEL_ON); } pthread_testcancel (); } pthread_exit (my_number); } main() { int worker_num; /* Counter used when indexing workers i
OSF DCE Application Development Guide—Core Components prime_search, (pthread_addr_t)worker_num); check(status,"19:Pthread_create bad status\n"); } /* * Set the predicate thread_hold to zero, and broadcast on the * condition variable that the worker threads may proceed. */ status = pthread_mutex_lock (&cond_mutex); check(status,"20:Mutex_lock bad status\n"); thread_hold = 0; status = pthread_cond_broadcast (&cond_var); check(status,"20.
DCE Threads Example /* * Take the list of prime numbers found by the worker threads and * sort them from lowest value to highest. The worker threads work * concurrently; there is no guarantee that the prime numbers * will be found in order. Therefore, a sort is performed.
Chapter 11. Developing a Simple RPC Application This chapter first explains how to write an interface definition in the DCE RPC Interface Definition Language (IDL) and illustrates the basic features of IDL. As an example, we present an interface definition for greet, a very simple application that prints greetings from a client and a remote server. The remainder of the chapter describes how to develop, build, and run the greet client and server programs.
OSF DCE Application Development Guide—Core Components A distributes application uses dispersed computing resources such as CPUs, databases, devices, and services. The following are examples: • A calendar-management application that allows authorized users to access the personal calendars of other users. • A graphics application that processes data on central CPUs and displays the results on workstations.
Developing a Simple RPC Application TABLE 11-1. Basic Tasks of an RPC Application __________________________________________________________________ Client Tasks Server Tasks _________________________________________________________________ ___________________________________________________________________ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. Select network protocols. Register RPC interfaces. Register endpoints in endpoint map. Advertise RPC interfaces and objects in the namespace. Listen for calls.
OSF DCE Application Development Guide—Core Components 11.1.1 RPC Application Code An RPC server or client contains application code, one or more RPC stubs, and the RPC runtime. RPC application code is the code written for a specific RPC application by the application developer. Application code implements and calls remote procedures, and also calls any RPC runtime routines the application needs. An RPC stub is an interfacespecific code module that uses an RPC interface to pass and receive arguments.
Developing a Simple RPC Application 11.1.2 Stubs The stub performs basic support functions for remote procedure calls. For instance, stubs prepare input and output arguments for transmission between systems with different forms of data representation. The stubs use the RPC runtime to handle the transmission between the client and server. The client stub can also use the runtime to find servers for the client.
OSF DCE Application Development Guide—Core Components 11.1.3 The RPC Runtime In addition to one or more RPC stubs, every RPC server and RPC client is linked with a copy of the RPC runtime. Runtime operations perform tasks such as controlling communications between clients and servers and finding servers for clients on request. An interface’s client and server stubs exchange arguments through their local RPC runtimes. The client runtime transmits remote procedure calls to the server.
Developing a Simple RPC Application RPC Client RPC Server Calling Code Remote Procedures 1 5 8 Server Stub Client Stub 2 6 RPC Runtime 3 4 RPC Runtime 7 Output arguments/return value Input arguments The following steps describe the interrelationships of the components of RPC applications, as shown in the previous figure: 124245 1. The client’s application code invokes a remote procedure call, passing the input arguments to the stub for the particular RPC interface. 2.
OSF DCE Application Development Guide—Core Components 11.1.5 Overview of DCE RPC Development Tasks The tasks involved in developing an RPC application resemble those involved in developing a local application. As an RPC developer, you perform the following basic tasks: 1. Design your application, deciding what procedures you need, which will be remote procedures, and how the remote procedures will be grouped into RPC interfaces. 2.
Developing a Simple RPC Application 6. Generate object code from application code. 7. Create an executable client and server from the object files. Figure 11-5 illustrates this task. For the client, link object code of the client stub(s) and the client application with the RPC runtime and any other needed runtime libraries. For the server, link object code for the server stub(s), the initialization routines, and the set(s) of remote procedures with the RPC runtime and any other needed runtime libraries.
OSF DCE Application Development Guide—Core Components IDL, see Chapter 17. For information on the IDL compiler, see the idl(1rpc) reference page. An IDL interface definition consists of a header and a body. The following example shows the interface definition for the greet application: /* * greet.idl * * The "greet" interface. */ [uuid(3d6ead56-06e3-11ca-8dd1-826901beabcd), version(1.
Developing a Simple RPC Application A comment can be inserted at any place in an interface definition where whitespace is permitted. IDL comments, like C comments, begin with /* (a slash and an asterisk) and end with */ (an asterisk and a slash). 11.2.1 RPC Interfaces That Represent Services The simplest RPC application uses only one RPC interface. However, an application can use multiple RPC interfaces, and, frequently, an integral set of RPC interfaces work together as an RPC service.
OSF DCE Application Development Guide—Core Components Clients can use any practical combination of RPC interfaces, whether offered by the same or different servers. For this example, using a database access interface, a client on a graphics workstation can call a remote procedure on a database server to fetch data from a central database.
Developing a Simple RPC Application 11.2.3 Naming the Interface After you have used uuidgen to generate a skeletal interface definition, replace the dummy string INTERFACENAME with the name of your interface. By convention, the name of an interface definition file is the same as the name of the interface it defines, with the suffix .idl appended. For example, the definition for a bank interface would reside in a bank.
OSF DCE Application Development Guide—Core Components By default, the IDL compiler resolves relative pathnames of imported files by looking first in the current working directory and then in the system IDL directory. The -I option of the IDL compiler allows you to specify additional directories to search. You can thereby avoid putting absolute pathnames in your interface definitions. For example, if an imported file has the absolute pathname /dbproject/src/dbconstants.
Developing a Simple RPC Application The type_specifier constructs for structures and unions permit the application of attributes to members. In the following example, one member of a structure is a conformant array (an array without a fixed upper bound), and the size_is attribute names another member of the structure that at runtime provides information about the size of the array: typedef struct { long dsize; [size_is(dsize)] float darray[]; } dataset; 11.2.
OSF DCE Application Development Guide—Core Components If you want an interface to always use explicit binding handles, the first parameter of each operation declaration must be a binding handle, as in the following example: void greet( [in] [in, string] [out, string] ); handle_t h, char client_greeting[], char server_reply[REPLY_SIZE] However, if you want applications to use the ACF feature of an implicit binding handle (or even an automatic binding handle) for some or all procedures, operation declaratio
Developing a Simple RPC Application 1. It checks the command-line arguments for an entry name to use for its search in the namespace. 2. It calls rpc_ns_binding_import_begin( ) to start the search in the namespace. 3. It calls rpc_ns_binding_import_next() to obtain a binding to a server. 4. It calls the greet remote procedure with a string greeting. 5. It prints the reply from the server. The greet_client.
OSF DCE Application Development Guide—Core Components /* * greet_client.c * * Client of "greet" interface. */ #include #include #include "greet.h" #include "util.h" int main( int argc, char *argv[] ) { rpc_ns_handle_t import_context; handle_t binding_h; error_status_t status; idl_char reply[REPLY_SIZE]; if (argc < 2) { fprintf(stderr, "usage: greet_client \n"); exit(1); } /* * Start importing servers using the name specified * on the command line.
Developing a Simple RPC Application In this example, after each call to an RPC runtime routine, the client program calls the application-specific ERROR_CHECK macro. If the status from the RPC runtime routine is not error_status_ok, dce_error_inq_text( ) is called and the error message is printed. As specified in the greet.idl interface definition, the greet application uses explicit handles. The client therefore passes a binding handle of type handle_t as the first parameter of the greet procedure.
OSF DCE Application Development Guide—Core Components 11.5.1.1 Including idl-Generated Headers Like greet_client.c, the greet_server.c module includes greet.h so that constants, data types, and procedure prototypes are available in the application. For example: /* * greet_server.c * * Main program (initialization) for "greet" server. */ #include #include #include #include "greet.h" #include "util.
Developing a Simple RPC Application 11.5.1.3 Selecting Protocol Sequences The server calls rpc_server_use_all_protseqs() to obtain endpoints on which to listen for remote procedure calls: /* * Use all protocol sequences that are available. */ rpc_server_use_all_protseqs(rpc_c_protseq_max_reqs_default, &status); ERROR_CHECK(status, "Can’t use protocol sequences"); 11.5.1.
OSF DCE Application Development Guide—Core Components /* * Export ourselves into the CDS namespace. */ rpc_ns_binding_export( rpc_c_ns_syntax_default, (unsigned_char_p_t) argv[1], greetif_v1_0_s_ifspec, binding_vector, NULL, &status); ERROR_CHECK(status, "Can’t export into CDS namespace"); 11.5.1.7 Listening for Calls To begin listening rpc_server_listen(). for remote procedure call requests, the server calls /* * Start listening for calls. */ printf("Listening...
Developing a Simple RPC Application /* * greet_manager.c * * Implementation of "greet" interface. */ #include #include "greet.h" void greet( handle_t h, idl_char *client_greeting, idl_char *server_reply ) { printf("The client says: %s\n", client_greeting); strcpy(server_reply, "Hi, client!"); } 11.6 Building the greet Programs The client side of the greet application is the greet_client program, which is built from the following: • The user-written greet_client.
OSF DCE Application Development Guide—Core Components LIBDIRS LIBS LIBALL INCDIRS CFLAGS IDLFLAGS all: = = = = = = -L${DCEROOT}/usr/lib -ldce ${LIBDIRS} ${LIBS} -I. -I${DCEROOT}/share/include -g ${INCDIRS} -v ${INCDIRS} -cc_cmd "${CC} ${CFLAGS} -c" greet_client greet_server greet.h greet_cstub.o greet_sstub.o: greet.idl ${IDL} ${IDLFLAGS} greet.idl greet_client: greet.h greet_client.o util.o greet_cstub.o ${CC} -o greet_client greet_client.o greet_cstub.o util.o \ ${LIBALL} greet_server: greet.
Developing a Simple RPC Application The server program can be terminated at any time by a signal, which on many systems can be generated by . When applications such as greet execute, many errors can occur that have nothing to do with your own code. In general, errors that occur when a remote procedure call executes are reported as exceptions.
Chapter 12. RPC Fundamentals DCE RPC provides a call environment that behaves essentially like a local call environment. However, some special requirements are imposed on remote procedure calls by the remoteness of calling code to the called procedure. Therefore, a remote procedure call may not always behave exactly like a local procedure call.
OSF DCE Application Development Guide—Core Components by-reference passing mechanism for input/output parameters, remote procedure calls with input/output parameters have copy-in/copy-out semantics due to the differing address spaces of the calling and called code. These two passing mechanisms are only slightly different, and most procedure calls are not sensitive to the differences between call-by-reference and copy-in/copy-out semantics.
RPC Fundamentals 12.2 Communications Protocols A communications link depends on a set of communications protocols. A communications protocol is a clearly defined set of operational rules and procedures for communications.
OSF DCE Application Development Guide—Core Components Figure 12-1. A Binding Client’s system Server’s system Network RPC & comm. protocols Client Client Network address Endpoint Server Binding information includes the following components: • Protocol sequence A valid combination of communications protocols presented by the runtime as a character string. Each protocol sequence includes a network protocol, a transport protocol, and an RPC protocol that works with them.
RPC Fundamentals 12.3.1 Server Binding Information Binding information for a server is known as server binding information. A binding handle that refers to server binding information is known as a server binding handle. The use of server binding handles differs on servers and clients. 12.3.1.1 Server Binding On a Server Servers use a list of server binding handles. Each represents one way to establish a binding with the server.
OSF DCE Application Development Guide—Core Components The additional information required that a client imposes on the RPC runtime includes an RPC interface identifier and an object UUID, as follows: • Interface identifier The interface UUID and version numbers of an RPC interface: — Interface UUID: The interface UUID, unlike the interface name, clearly identifies the RPC interface across time and space.
RPC Fundamentals Figure 12-2. Information Used to Identify a Compatible Server System Network Protocol sequence Comm. protocols Network address Server Endpoint Interface Interface UUID & version numbers Object Object UUID 12.3.3 HowClients Obtain Server Binding Information When a client initiates a series of related remote procedure calls, the RPC runtime tries to establish a binding, which requires the address of a compatible server.
OSF DCE Application Development Guide—Core Components • It is effective in dynamic end-user environments. • Binding information is stored in a named server entry. Data can be dynamic. Servers can automatically place their binding information in the namespace. Changes in binding information are made once by a server or administrator and then propagated automatically by the directory service to the replicas of the data. • There is centralized administration of data in a namespace.
RPC Fundamentals providing binding information to clients. Applications should use the directory service to advertise binding information. 12.3.4 Client Binding Information for Servers When making a remote procedure call, the client runtime provides information about the client to the server runtime.
OSF DCE Application Development Guide—Core Components 3. The address from which the client is making the remote procedure call, which the communications protocols supply to the server A server application can use the client binding handle to ask the RPC runtime about the object UUID requested by a client or about the client’s authentication information. 12.4 Endpoints An endpoint is the address of a specific server instance on a host system.
RPC Fundamentals 12.4.2 Dynamic Endpoints A dynamic endpoint is requested and assigned at runtime. For some transport protocols, the number of endpoints is limited; for example, TCP/IP and UDP/IP use a 16-bit number for endpoints, which allows 65,535 endpoints. When the supply of endpoints for a transport protocol is limited, the protocol ensures an adequate supply of endpoints by limiting the portion that can be reserved as well-known endpoints.
OSF DCE Application Development Guide—Core Components 12.5 Execution Semantics Execution semantics identify the ability of a procedure to execute more than once during a given remote procedure call. The communications environment that underlies remote procedure calls affects their reliability.
RPC Fundamentals The broadcast capabilities of RPC runtime have a number of distinct limitations: • Not all systems and networks support broadcasting. In particular, broadcasting is not supported by the RPC connection-oriented protocol. • Broadcasts are limited to hosts on the local network. • Broadcasts make inefficient use of network bandwidth and processor cycles.
OSF DCE Application Development Guide—Core Components • The resources of the server and the network • The requirements of each call • The number of calls that can be concurrently offered at some level of service • The performance requirements An accurate analysis of the requirements of a given server involves detailed work load and resource characterization and modeling techniques. Although measurement of live configurations under load will offer the best information, general guidelines apply.
RPC Fundamentals type of object on which the manager operates. For example, one manager of a queue-management interface may operate on print queues, while another manager may operate on batch queues.
Chapter 13. Basic RPC Routine Usage This chapter introduces a number of basic DCE RPC routines for directory service, communications, and authentication operations and discusses major usage issues important for developing DCE RPC applications. This chapter discusses the following topics: • Overview of basic runtime routines • Server initialization tasks • How clients find servers 13.
OSF DCE Application Development Guide—Core Components applications to manipulate string representations of binding information (string bindings). 13.1.2 Basic Operations of the NSI The NSI routines perform operations on a namespace for RPC applications.
Basic RPC Routine Usage TABLE 13-1.
OSF DCE Application Development Guide—Core Components 13.2 Server Initialization Using the RPC Routines Before a server can receive any remote procedure calls, it should usually initialize itself by calling the dce_server_register( ) routine so that the server is properly recognized by DCE. However, servers can instead use a series of the lower-level RPC runtime routines. The server initialization code, written by the application developer, varies among servers.
Basic RPC Routine Usage To simultaneously offer alternative implementations of an RPC interface for different types of objects, a server uses alternative managers. Servers that implement each of their interfaces with only one manager can usually avoid the tasks associated with assigning object types. However, when a server offers multiple managers, each manager must be dedicated to operating on a separate type of object.
OSF DCE Application Development Guide—Core Components 13.2.2 Registering Interfaces A server calls the rpc_server_register_if( ) routine to tell the RPC runtime about a specific RPC interface. Registering an interface informs the runtime that the server is offering that interface and makes it available to clients. A server can register any number of interfaces with the RPC runtime by calling the rpc_server_register_if() routine once for each set of procedures, or manager, that implements an interface.
Basic RPC Routine Usage 13.2.3 Selecting RPC Protocol Sequences A server can inquire about whether the local RPC runtime supports a specific protocol sequence by using the rpc_network_is_protseq_valid() routine. The server can also use the rpc_network_inq_protseqs() routine to ask the RPC runtime for a list of all protocol sequences supported by both the RPC runtime and the operating system.
OSF DCE Application Development Guide—Core Components interface identifier, object UUID, and binding information that the server offers, the endpoint mapper service creates an element in the local endpoint map. A server does not necessarily need to register well-known endpoints; however, by registering well-known endpoints, the server ensures that clients can always obtain them.
Basic RPC Routine Usage To refer to binding information, the application code obtains a list of server binding handles from the RPC runtime and passes the list to the export operation. The list contains binding handles for all the protocol sequence and endpoint combinations that the server has requested; it does this by calling the use-protocol-sequence operations. However, the server can remove any of those binding handles from the list before exporting it.
OSF DCE Application Development Guide—Core Components CDS object entry, or both. If you need ACL permissions, see your CDS administrator. The ACL permissions are as follows: • To create an entry, you need insert permission to the parent directory. • To read an entry, you need read permission to the CDS object entry. • To write to an entry, you need write permission to the CDS object entry. • To delete an entry, you need delete permission either to the CDS object entry or to the parent directory.
Basic RPC Routine Usage server binding handles that refer to server binding information obtained from either source. 13.3.1 Searching a Namespace To obtain binding information from a namespace, a client can do one of the following: • The client must call the import routines rpc_ns_binding_import_begin(), rpc_ns_binding_import_next( ), and rpc_ns_binding_import_done( ) to obtain a binding handle for a compatible server.
OSF DCE Application Development Guide—Core Components Client Application Server binding handle 3 Runtime Server binding information 2 Importing 1 Server binding information Server entry = Reference to binding information The callouts in the figure refer to the following operations: 1. The import operation looks up binding information of a server that is compatible with the client.
Basic RPC Routine Usage Also, if binding information changes, the users are responsible for updating any string bindings used by their clients. Reducing manual intervention in the use of string bindings requires that an application provide its own mechanisms for storing, maintaining, and accessing binding information. In contrast, a directory service such as CDS provides these mechanisms automatically to applications that store binding information in a namespace.
Chapter 14. RPC and Other DCE Components This chapter discusses aspects of the internal behavior of remote procedure calls that are significant for advanced RPC programmers, including the following topics: • Threads of execution in RPC applications • Authenticated remote procedure calls • Using the Name Service Interface DCE RPC is a fully integrated part of the distributed computing environment. The communications capabilities of DCE RPC are used by clients and servers of other DCE components.
OSF DCE Application Development Guide—Core Components client uses this information to establish a relationship, known as a binding, with the server. 14.1 Threads of Execution in RPC Applications Each remote procedure call occurs in an execution context called a thread. A thread is a single sequential flow of control with one point of execution on a single processor at any instant. A thread created and managed by application code is an application thread.
RPC and Other DCE Components Figure 14-2. Server Application Thread and Multiple Call Threads Server remote procedures The server application thread (listening for calls) Single address space Available call threads Remote procedure executing in call thread Maximum concurrent calls = 4 14.1.1 Remote Procedure Call Threads In distributed processing, a call extends to and from client and server address spaces.
OSF DCE Application Development Guide—Core Components 1. The RPC thread begins in the client process, as a client application thread makes a remote procedure call to its stub; at this point, the client thread becomes part of the RPC thread. 2. The RPC thread extends across the network to the server address space. 3. The RPC thread extends into a call thread, where the remote procedure executes. While a called remote procedure is executing, the call thread becomes part of the RPC thread.
RPC and Other DCE Components incoming calls avoids remote procedure calls failing during short-term congestion. The queue capacity for incoming calls is implementation dependent; most implementations offer a small queue capacity. The queuing of incoming calls is discussed in Chapter 16, under the topic of the routing of incoming calls. 14.1.2 Cancels DCE RPC uses and supports the synchronous cancel capability provided by POSIX threads (pthreads).
OSF DCE Application Development Guide—Core Components 3. The RPC thread returns to the canceled client application thread with one of the following outcomes: • If a cancel exception has not been taken, the RPC thread returns normal call results (output arguments, return value, or both) with a pending cancel. • If the remote procedure is using an exception handler, a cancel exception can be handled. The procedure resumes, and the RPC thread returns normal call results without pending any cancel.
RPC and Other DCE Components Figure 14-6.
OSF DCE Application Development Guide—Core Components On the application level, a server makes itself available for authenticated communications by registering its principal name and the authentication service that it supports with the RPC runtime. The server principal name is the name used to identify the server as a principal to the registry service provided by the security service.
RPC and Other DCE Components 14.2.1.1 Cross-Cell Authentication A client can engage in authenticated RPC with a target server that is in the client’s cell or in a foreign cell. In the case of cross-cell authentication, DCE security performs the necessary additional steps on behalf of the client. To establish authenticated RPC with a foreign server, a client must supply the fully qualified principal name of the server.
OSF DCE Application Development Guide—Core Components sequence, the routine uses the rpc_c_protect_level_pkt level instead. rpc_c_protect_level_pkt Ensures that all data received is from the expected client. This level attaches a verifier to each message. rpc_c_protect_level_pkt_integrity Ensures and verifies that none of the data transferred between client and server has been modified.
RPC and Other DCE Components When a client establishes authenticated RPC, it must indicate which authorization option it wants to use. It is the server’s responsibility to implement the type of authorization appropriate for the objects that it controls. When the server calls rpc_binding_inq_auth_caller() to return information about an authenticated client, it gets back either the client’s principal name or a pointer to the data structure that contains the client’s credentials.
OSF DCE Application Development Guide—Core Components 14.2.3 Authenticated RPC Routines Authenticated RPC is implemented as a set of related RPC routines. Some of the routines are for use by clients, some are for use by servers and their managers, and some are for use by both clients and servers.
RPC and Other DCE Components function to validate remote client calls to the server’s management routines. For example, the user function can call rpc_binding_inq_auth_caller( ) to return authentication and authorization information about the calling client.
OSF DCE Application Development Guide—Core Components Outlines strategies for using each kind of entry. • The service model Describes the service model for defining RPC servers and introduces NSI usage models intended to guide application developers in assessing how to best use NSI for a given application. • The resource model Describes the resource model for defining RPC servers. 14.3.
RPC and Other DCE Components • NSI object attribute The object attribute stores a list of one or more object UUIDs. Whenever a server exports any object UUIDs to a server entry, the server entry contains an object attribute as well as a binding attribute. When a client imports from that entry, the import operation returns an object UUID from the list stored in the object attribute. • NSI group attribute The group attribute stores the entry names of the members of a single group.
OSF DCE Application Development Guide—Core Components When implementing the resource model or when used to distinguish server instances, a server entry contains an object attribute as well as a binding attribute. On finding a server entry whose binding attribute contains compatible binding information, an NSI search operation also looks in the entry for an object attribute.
RPC and Other DCE Components For NSI operations on entries in the local cell, you can omit the cell name. • Cell-relative name (using DCE name syntax): Each directory service entry requires a cell-relative name, which contains a directory pathname and a leaf name. — A directory pathname follows the cell name and indicates the hierarchical relationship of the entry to the cell root.
OSF DCE Application Development Guide—Core Components Only interchangeable server instances can share a server entry. Each server entry must contain binding information. Every combination of protocol sequence and network addressing information represents a potential binding. The network addressing information can contain a network address, but lacks an endpoint, making the address partially bound. A server entry can also contain a list of object UUIDs exported by the server.
RPC and Other DCE Components Figure 14-9. Possible Information in a Server Entry One Server Entry Bindings Interface UUID/version pair 1 with binding information 1 Interface UUID/version pair 2 with binding information 1 Interface UUID/version pair 1 with binding information 2 Interface UUID/version pair 2 with binding information 3 Interface UUID/version pair 1 with binding information 3 Object UUID 1 Object UUID 2 Objects Object UUID 3 Object UUID 4 14.3.1.
OSF DCE Application Development Guide—Core Components Server entry 1: Binding information Interface identifiers Object UUIDs Group A: Member name Server entry 2: Member name Binding information Interface identifiers Object UUIDs Member name Group B: Member name Member name Server entry 5: Binding information Interface identifiers Object UUIDs Server entry 3: Binding information Interface identifiers Object UUIDs Server entry 4: Binding information Interface identifiers Object UUIDs Key: = Member o
RPC and Other DCE Components — A group corresponding to the requested RPC interface — A profile • Priority value The priority value (0 is the highest priority; 7 is the lowest priority) is designated by the creator of a profile element to help determine the order for using the element NSI search operations to select among like-priority elements at random. • Annotation string The annotation string enables you to identify the purpose of the profile element.
OSF DCE Application Development Guide—Core Components Profile A: Group: Profile element: Member name Member name Interface UUID Interface version member name priority annotation Server entry: Binding information Interface identifiers Object UUIDs Profile element: Interface UUID Interface version member name priority annotation Server entry: Binding information Interface identifiers Object UUIDs Server entry: Binding information Interface identifiers Object UUIDs Server entry: Binding information In
RPC and Other DCE Components profile administrator can set up profile elements that refer (directly or indirectly) to only a subset of the server entries that offer a given RPC interface. Also, the administrator can assign different search priorities to the elements for an interface. 14.3.1.6 Guidelines for Constructing Names of Directory Service Entries A global name includes both a cell name and a cell-relative name composed of a directory pathname and a leaf name.
OSF DCE Application Development Guide—Core Components an integer. For example, the following leaf names distinguish two instances of a calendar service on the JULES system: calendar_JULES_01 calendar_JULES_02 Avoid automatically generating entry names for the server entries of server instances; for example, by using unique data such as a timestamp (calendar_verne_15OCT91_21:25:32) or a process identifier (calendar_jules_208004D6).
RPC and Other DCE Components • Naming a profile The leaf name of a profile should indicate the profile users; for example, for a profile that serves the members of an accounting department, the following is an effective leaf name: accounting_profile The following text describes the NSI begin, next, and done operations. NSI accesses a variety of search and inquire operations that read NSI attributes in directory service entries.
OSF DCE Application Development Guide—Core Components TABLE 14-1. NSI next Operations _______________________________________________________________________ Search Operation Attributes Traversed ______________________________________________________________________ ________________________________________________________________________ rpc_ns_binding_import_next() Searches for binding and object attributes of a compatible server; reads any NSI attribute in a search path.
RPC and Other DCE Components 14.3.1.8 Environment Variables DCE RPC provides predefined environment variables that a client can use for NSI operations. An environment variable is a variable that stores information, such as a name, about a particular environment. The NSI interface provides two environment variables, RPC_DEFAULT_ENTRY and RPC_DEFAULT_ENTRY_SYNTAX, which are described in the OSF DCE Application Development Reference.
OSF DCE Application Development Guide—Core Components path can encompass every entry named as the member of a profile element that contains the target interface identifier. A search finishes only when it finds a server entry containing compatible binding information and the nonnil object UUID, if requested.
RPC and Other DCE Components Step 3: Profile attribute If the binding and group attributes do not lead to compatible binding information, the search continues by reading the profile attribute, if present; if the directory service entry lacks a profile attribute, the search fails. The search operation identifies all the profile elements containing the requested interface identifier and searches them in the order of their priority, beginning with the 0 (zero) priority elements.
OSF DCE Application Development Guide—Core Components Figure 14-12. The import_next, lookup_next Search Algorithm in a Single Entry Search RETURNS compatible binding information Search STARTS Yes Step 1. Binding attribute Yes Contains Compatible binding info. ? For each potential binding, DO ? No No Yes Compatible object UUID ? No Step 2. Group attribute Yes For each group member, DO Yes For each profile element of a compatible interface id, DO ? No Step 3.
RPC and Other DCE Components 14.3.2.2 Examples of Searching for Server Entries This subsection provides several examples of how the NSI import_next and lookup_next operations search for binding information associated with a given RPC interface and object in a namespace. The examples in this guide use the following conventions: • To simplify the following examples, each member name is represented by a leaf name preceded by the symbol that represents the local cell (/.:).
OSF DCE Application Development Guide—Core Components The fields are the interface identifier (interface UUID and version numbers), member name, priority, and annotation. /.:/LandS/anthro/esther_r_profile contents: ec1eeb60-5943-11c9-a309-08002b102989,1.0 /.../C=US/O=uw/OU=MadCity/LandS/Cal_host_7 0 Calendar_interface_V1.0 ec1eeb60-5943-11c9-a309-08002b102989,2.0 /.../C=US/O=uw/OU=MadCity/LandS/Cal_host_4 1 Calendar_interface_V2.0 62251ddd-51ed-11ca-852c-08002b1bb4f6,2.0 /...
RPC and Other DCE Components a. The operation rejects the first profile element for the interface because it refers to the wrong version numbers. b. In the next profile element, the operation finds the correct version numbers (2.0). The search proceeds to the associated server entry, /.:/LandS/Cal_host_4. 2. The search ends with the indicated server entry, where the binding information requested by the client resides: /.:/LandS/Cal_host_4 contents: calendar-if-uuid,2.0 binding-information 14.3.2.2.
OSF DCE Application Development Guide—Core Components 3. The search ends at the indicated server entry, /.:/LandS/Stats_host_6, where a server address for the requested interface resides: /.:/LandS/Stats_host_6 contents: Statistics-if-uuid,1.0 binding-information 14.3.2.2.3 Example 3: Importing an Interface and an Object Target Interface: Print Server V2.1 Target Object: Laser Printer Print Queue 1. The search starts with the entry /.
RPC and Other DCE Components /.:/Bldg/Print_server_host_7 /.:/Bldg/Print_server_host_9 4. The search selects the /.:/Bldg/Print_server_host_9 entry. This entry contains both a server address for the requested Version 2.1 of the interface and the requested object UUID of the Laser_printer queue: /.:/Bldg/Print_server_host_9 contents: print_server-if-uuid, 2.1 binding-information laser_printer_queue-object-uuid The search returns binding information from this entry to the client. 14.3.2.
OSF DCE Application Development Guide—Core Components 14.3.3 Strategies for Using Directory Service Entries When developing an RPC application, decide how an application will use the namespace and design your application accordingly. The following subsections discuss issues associated with how servers use different types of directory service entries. 14.3.3.1 Using Server Entries An application requires separate server entries for servers on different hosts.
RPC and Other DCE Components Before exporting, each server instance must acquire the entry name of its server entry from an external source. When a unique server instance stops running, its server entry becomes available. An available server entry should be reused for a new instance of that server by providing the existing entry’s name for a new server instance to use with the export operation. If any existing server entries are unavailable, a new server instance requires a new server entry name.
OSF DCE Application Development Guide—Core Components For servers that advertise resources in server entries, groups often use subsets for server entries according to the resources they advertise. For example, print servers can be grouped according to supported file formats. In this case, an administrator creates a group entry for each file format; for example, post_printers, sixel_printers, and ascii_printers. Each print server entry is a member of one or more groups.
RPC and Other DCE Components Priority 7 Priority 5 Priority 3 Priority 0 Regional Headquarters Local City Rest of region Other regions An individual user can have a personalized user profile that contains elements for interfaces the user uses regularly and a default element that specifies a public profile, such as the cell profile, as the default profile. NSI searches use the default profile when a client needs an RPC interface that lacks an element in the user profile. 14.3.
OSF DCE Application Development Guide—Core Components 14.3.4.1 Interchangeable Server Instances With the service model, servers offer an identical service that operates the same way on all host systems. For example, an application that uses the service model is a collection of equivalent print servers that support an identical set of file formats, and that are installed on printers in a single location.
RPC and Other DCE Components Note: The number of entries traversed by a search operation is unrelated to the number of binding handles it returns. Figure 14-15 shows interchangeable service instances offering an identical statistics service on a single host. To access this service, clients request the Statistics V1.0 interface and specify the nil object UUID. The starting entry for the NSI search is a group corresponding to local servers that offer the service (or a profile that refers to that group).
OSF DCE Application Development Guide—Core Components 14.3.4.2 Distinct Service Instances on a Single Host With the service model, when multiple server instances on a given host are somehow unique, each instance must export to a separate server entry. The exported binding information must contain one or more instance-specific, well-known endpoints or an instance UUID.
RPC and Other DCE Components After finding a server entry with compatible binding information for the statistics interface, the import operation returns an instance UUID along with binding information. Every remote procedure call made with that binding information goes to the server instance that exported the instance UUID. Figure 14-16. Service Model: Distinct Instances on One Host MAYA system Statistics −service server instance 1 MAYA system Statistics −service server instance 2 Statistics V1.
OSF DCE Application Development Guide—Core Components Applications use object UUIDs to refer to resources as follows: 1. Servers offer resources by assigning an object UUID to each specific resource. 2. Clients obtain those object UUIDs and use them to learn about a server that offers a given resource. 3. When making a remote procedure call, a client requests a resource by passing its UUID as part of the server binding information. Each RPC resource or type of resource requires its own object UUID.
RPC and Other DCE Components If yes, then a client must specify an object UUID to the import operation. • Does the type of resource you are using last for a long time (months or years), so you can advertise object UUIDs efficiently in the namespace? The information kept in a namespace should be static or rarely change. For example, print queues are appropriate RPC resources.
OSF DCE Application Development Guide—Core Components the search. 3. The import operation returns a binding handle that refers to the requested object UUID and binding information for a server that offers the corresponding object. 4. The client issues the remote procedure call by using that binding handle. 5. The server looks up the type of the requested object. 6. The server assigns the remote procedure call to the manager that implements the called remote procedure for that type of object. 14.3.5.
RPC and Other DCE Components AZTEC system Process−control server MAYA system Process−control server Process_control V1.2 interface Process_control V1.2 interface AZTEC’s process stats file MAYA’s process stats file Exporting Exporting Name service database /.:/hosts/AZTEC/Process_control /.:/hosts/MAYA/Process_control Interface ID for Process_control V1.2 Interface ID for Process_control V1.
OSF DCE Application Development Guide—Core Components subsetting resources, try to assign each resource to a single set so that its object UUID is exported to only one server entry. Figure 14-18 illustrates a single server entry implementation for each server for the resource model. Figure 14-18. Resource Model: A Single Server Entry for Each Server AZTEC system Calendar server MAYA system Calendar server Calendar V1.1 interface Calendar V1.
RPC and Other DCE Components with many RPC resources should usually have each server create a single server entry for itself and export the object UUIDs of the resources it offers to that server entry. For example, an application that accesses a different personal calendar for every member of an organization needs to avoid using a separate server entry for each calendar.
OSF DCE Application Development Guide—Core Components Figure 14-19. Resource Model: A Separate Server Entry for Each Object Print server 1 Print server 2 Print V1.0 interface ASCII format Print V1.0 interface PostScript format ASCII format Exporting PostScript format Sixel format Exporting Name service database /.:/Bldg/PrintServer_1_FF/ASCII /.:/Bldg/PrintServer_2_FF/ASCII Interface ID for Print V1.0 Interface ID for Print V1.0 Object UUID for ASCII format Object UUID for ASCII format /.
RPC and Other DCE Components Applications that use a separate entry for each object UUID need to use groups cautiously. Keeping groups small when clients are requesting a specific object is essential because an NSI search looks up the group members in random order. Therefore, the members of a group form a localized flat NSI search path rather than the hierarchical path. Flat search paths are inefficient because the average search will look at half the members. Small groups are not a problem.
Chapter 15. Writing Internationalized RPC Applications An internationalized DCE RPC application is one that • Uses the operating system platform’s locale definition functions to establish language-specific and culture-specific conventions for the user and programming environment. • Isolates all user-visible messages into message catalogs by using the sams (symbols and message strings) utility.
OSF DCE Application Development Guide—Core Components The remainder of this chapter describes the DCE RPC features for character and code set interoperability in remote procedure calls that are available to programmers who are developing internationalized DCE RPC applications. The first section describes the concepts of character sets, code sets and code set conversion and explains the default character and code set conversion mechanism that the RPC runtime protocol supports for remote procedure calls.
Writing Internationalized RPC Applications 15.2 Remote Procedure Call with Character/Code Set Interoperability Table 11-1 in Chapter 11 illustrates the basic tasks of an RPC application. Table 15-1 shows these basic tasks integrated with the additional tasks required to implement an RPC that provides character and code set interoperability. TABLE 15-1.
OSF DCE Application Development Guide—Core Components __________________________________________________________________ Client Tasks Server Tasks __________________________________________________________________ __________________________________________________________________ 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. Get code set tags sent from the client. Calculate the buffer size for possible conversion of input arguments from network to local code set. Unmarshall input arguments.
Writing Internationalized RPC Applications processes on the client host and processes on the server host. 2. The server, as part of its initialization phase, calls a DCE RPC routine that retrieves information about code sets support on the server’s host.
OSF DCE Application Development Guide—Core Components If the client and server are character set compatible, and they support a common code set into which one or the other (or both) can convert, the evaluation routine deems the server to be compatible with the client. The NSI import routines return this server’s binding information to the client. 15−6 7. The client makes the remote procedure call. 8.
Writing Internationalized RPC Applications 19. The server stub next calls a new stub support routine that converts, based on the code set identifying information from the client, the character data from the server’s local code set to the network code set. 20. The server stub marshalls the converted output arguments and transmits them to the client runtime along with code set identifying information. 21.
OSF DCE Application Development Guide—Core Components 4. Writes the server code and includes the steps to get the server’s supported code sets and export them to the name service database, and to remove them from the name service database upon termination or exit. 5. Writes the client code and includes the steps to set up the character and code set evaluation mechanism. 6. Writes the character and code set compatibility evaluation routine.
Writing Internationalized RPC Applications output parameters. If the operation does not specify any international character output data, then it is not necessary to create this parameter. You must define these code set tag parameters as unsigned long integers or unsigned long integers passed by reference. The receiving tag parameter must be declared as a pointer to the receiving tag unsigned long integer.
OSF DCE Application Development Guide—Core Components • The cs_char attribute, which associates the local data type that the application code uses to represent international characters in the local code set with the special typedef defined in the .idl file. This is a required ACF attribute for an RPC application that passes international character data. Chapter 18 provides complete details on how to specify the cs_char ACF attribute and the programming restrictions associated with its use.
Writing Internationalized RPC Applications between the local and network code sets. And, if you use the cs_tag_rtn attribute, you must provide the routine that sets the code set tag parameters for the operations in the application that transfer international characters. DCE RPC provides several buffer-sizing routines and one tag-setting routine.
OSF DCE Application Development Guide—Core Components • wchar_t_local_size()—Calculates the necessary buffer size for code set conversion from a network code set to a local code set when the wchar_t data type has been specified as the local data type in the .acf file. If your internationalized RPC application uses either of these data types as the local type in the ACF, it can use these DCE RPC buffer-sizing routines; in order to do so, simply link with the DCE library when compiling your application.
Writing Internationalized RPC Applications • cs_byte_to_netcs( )—Converts international character data from a local code set to a network code set when the cs_byte type has been specified as the local data type in the .acf file. • cs_byte_from_netcs( )—Converts international character data from a network code set to a local code set when the cs_byte type has been specified as the local data type in the .acf file.
OSF DCE Application Development Guide—Core Components convert between code set names and identifiers. 15.3.3.3 Tag-Setting Routine Recall from Section 15.3.1 that operations that specify international characters as input and output parameters declare special code set tag parameters. The purpose of these parameters is to hold the unique identifier for the code set into which the input or output data is to be encoded when it is transferred over the network.
Writing Internationalized RPC Applications routine. Note that the rpc_cs_get_tags() routine always sets the receiving tag value on the server side to the value that the client specified in the desired receiving tag. See the rpc_cs_get_tags(3rpc) reference page for an explanation of this routine’s signature and function.
OSF DCE Application Development Guide—Core Components the interface and export the binding information. The locale-setting function also establishes the value for two platform-specific macros that indicate • The maximum number of bytes the local code set uses to encode one character. • The maximum number of bytes that any of the supported code sets on the host will use to encode one character. On POSIX, XPG3, and XPG4 platforms, these macros are MB_CUR_MAX and MB_LEN_MAX and are defined in stdlib.
Writing Internationalized RPC Applications 15.3.4.3 Registering the Server’s Supported Code Sets in the Namespace The next step in writing an internationalized RPC server is to make a call in the server’s initialization code to the DCE RPC routine rpc_ns_mgmt_set_attribute( ), which takes the code sets array returned by rpc_rgy_get_codesets() and exports it to the server’s entry in the name service database.
OSF DCE Application Development Guide—Core Components {\ if (returned_st == expected_st) { \ } \ else { \ dce_error_inq_text(returned_st, \ (unsigned char *)unexpected, &dce_status); \ dce_error_inq_text(expected_st,\ (unsigned char *)expected, &dce_status); \ printf("FAILED %s()\nresult: %s\nexpected: func, unexpected, expected); \ } \ } \ static unsigned char static unsigned char static int %s\n\n", \ unexpected[dce_c_error_string_len]; expected[dce_c_error_string_len]; dce_status; int main(int argc, c
Writing Internationalized RPC Applications CHECK_STATUS(TRUE, "rpc_rgy_get_codesets", status, expected); rpc_server_register_if ( cs_test_v1_0_s_ifspec, NULL, NULL, &status ); CHECK_STATUS(TRUE, "rpc_server_register_if", status, expected); rpc_server_use_all_protseqs ( rpc_c_protseq_max_reqs_default, &status ); CHECK_STATUS(TRUE, "rpc_server_use_all_protseqs", status, expected); rpc_server_inq_bindings ( &binding_vector, &status ); CHECK_STATUS(TRUE, "rpc_server_inq_bindings", status, expected); rpc_ns_bind
OSF DCE Application Development Guide—Core Components */ rpc_ns_mgmt_free_codesets (&arr, &status); CHECK_STATUS(TRUE, "rpc_ns_mgmt_free_codeset", status, expected); sigemptyset(&sigset); sigaddset(&sigset, SIGINT); if (pthread_signal_to_cancel_np(&sigset, &this_thread) != 0) { printf("pthread_signal_to_cancel_np failed\n"); exit(1); } TRY { server_pid = getpid(); printf("Listening for remote procedure calls...
Writing Internationalized RPC Applications &binding_vector, &status ); CHECK_STATUS(TRUE, "rpc_binding_vector_free", status, expected); rpc_server_unregister_if ( cs_test_v1_0_s_ifspec, NULL, &status ); CHECK_STATUS(TRUE, "rpc_server_unregister_if", status, expected); (void)pthread_mutex_destroy(&mutex); } CATCH_ALL { /* * Remove code set attribute from namespace on a signal.
OSF DCE Application Development Guide—Core Components CHECK_STATUS(TRUE, "rpc_server_unregister_if", status, expected); (void)pthread_mutex_destroy(&mutex); } ENDTRY; } 15.3.5 Writing the Client Code A programmer who is developing an RPC client that supports character and code set interoperability needs to add the following steps to the client code in addition to the basic functions for RPC: 1. Setting the client’s locale 2.
Writing Internationalized RPC Applications ‘‘universal’’ code set. The DCE RPC functions for character and code set interoperability use the universal code set as the default ‘‘intermediate’’ code set into which a client or server can convert if there are no other compatible code sets between them. Section 15.3.6 discusses intermediate code sets in more detail. 15.3.5.
OSF DCE Application Development Guide—Core Components */ #define CHECK_STATUS(t, func, returned_st, expected_st) \ { \ if (returned_st == expected_st) { \ /* * Do nothing.
Writing Internationalized RPC Applications /* * Add code set compatibility checking logic to the context.
OSF DCE Application Development Guide—Core Components /* * This program reads the data from a file. */ fp_in = fopen("./i18n_input_data", "r"); if (fp_in == NULL) { printf("i18n_input_data open failed\n"); return; } fp_out = fopen(".
Writing Internationalized RPC Applications 15.3.6 Writing the Evaluation Routine Recall from Chapter 1 of the and Chapter 11 of this guide that when a prospective client attempts to import binding information from a namespace entry that it looks up by name, the NSI import routine checks the binding for compatibility with the client by comparing interface UUIDs and protocol sequences.
OSF DCE Application Development Guide—Core Components 15.3.6.1 DCE RPC Evaluation Routines DCE RPC provides two character and code set compatibility evaluation routines: rpc_cs_eval_with_universal( ) and rpc_cs_eval_without_universal(). To use either one of these routines, specify their names in the evaluation function argument to the rpc_ns_import_ctx_add_eval() routine. (The sample client code shown in Section 15.3.5.3 specifies a DCE RPC character and code set evaluation routine.
Writing Internationalized RPC Applications server’s local code set. 2. If both client and server support converters for each other’s local code sets (that is, they can convert to and from each other’s local code set), the routine sets the conversion method to RMIR. 3. If the server can convert to and from the client’s local code set, but the client cannot convert from the server’s local code set, the routine sets the conversion method to SMIR. 4.
OSF DCE Application Development Guide—Core Components • The rpc_rgy_get_codesets() routine • The rpc_cs_char_set_compat_check() routine • The rpc_cs_binding_set_tags( ) routine • The dce_cs_loc_to_rgy( ) routine • The rpc_ns_mgmt_read_codesets() routine • The rpc_ns_mgmt_free_codesets() routine Refer to the OSF DCE Application Development Reference for complete details about these routines.
Writing Internationalized RPC Applications 15.3.6.4 Example Character and Code Set Evaluation Logic Here is an example client program of the cs_test interface that provides its own character and code set evaluation logic. This example client uses the rpc_cs_binding_set_tags( ) routine to set the code set tags within the client code rather than using a tag-setting routine to set them within the stub code. #include #include #include #include #include
OSF DCE Application Development Guide—Core Components unsigned32 unsigned16 error_status_t error_status_t unsigned char char char FILE drtag; stag_max_bytes; status; temp_status; err_buf[256]; *nsi_entry_name; *client_locale_name; *fp_in, *fp_out; nsi_entry_name = getenv("I18N_SERVER_ENTRY"); setlocale(LC_ALL, ""); rpc_ns_binding_lookup_begin ( rpc_c_ns_syntax_default, (unsigned_char_p_t)nsi_entry_name, cs_test_v1_0_c_ifspec, NULL, rpc_c_binding_max_count_default, &lookup_context, &status ); CHECK_STATUS(
Writing Internationalized RPC Applications &status ); CHECK_STATUS(FALSE, "rpc_ns_binding_select", status, rpc_s_ok); if (status != rpc_s_ok) { rpc_ns_mgmt_free_codesets(&client, &status); CHECK_STATUS(TRUE, "rpc_ns_mgmt_free_codesets", status, rpc_s_ok); } rpc_ns_binding_inq_entry_name ( bind_handle, rpc_c_ns_syntax_default, &entry_name, &status ); CHECK_STATUS(TRUE, "rpc_ns_binding_inq_entry_name", status, \ rpc_s_ok); if (status != rpc_s_ok) { rpc_ns_mgmt_free_codesets(&client, &status); CHECK_STATUS(TRU
OSF DCE Application Development Guide—Core Components /* * Start evaluation */ if (client->codesets[0].c_set == server->codesets[0].c_set) { /* * client and server are using the same code set */ stag = client->codesets[0].c_set; drtag = server->codesets[0].c_set; break; } /* * check character set compatibility first */ rpc_cs_char_set_compat_check ( client->codesets[0].c_set, server->codesets[0].
Writing Internationalized RPC Applications if (smir_true && cmir_true) { /* RMIR model works */ stag = client->codesets[0].c_set; drtag = server->codesets[0].c_set; stag_max_bytes = client->codesets[0].c_max_bytes; } else if (smir_true) { /* SMIR model */ stag = client->codesets[0].c_set; drtag = client->codesets[0].c_set; stag_max_bytes = client->codesets[0].c_max_bytes; } else { /* CMIR model */ stag = server->codesets[0].c_set; drtag = server->codesets[0].c_set; stag_max_bytes = server->codesets[0].
OSF DCE Application Development Guide—Core Components /* * try another binding */ rpc_binding_free ( &bind_handle, &status ); CHECK_STATUS(FALSE, "rpc_binding_free", status, rpc_s_ok); if (status != rpc_s_ok) { rpc_ns_mgmt_free_codesets(&server, &status); CHECK_STATUS(FALSE, "rpc_ns_mgmt_free_codesets", \ status, rpc_s_ok); rpc_ns_mgmt_free_codesets(&client, &status); CHECK_STATUS(TRUE, "rpc_ns_mgmt_free_codesets", \ status, rpc_s_ok); } } } rpc_ns_mgmt_free_codesets(&server, &status); CHECK_STATUS(FALSE, "
Writing Internationalized RPC Applications tet_result(TET_DCE_FAIL); } fp_out = fopen(".
Chapter 16. Topics in RPC Application Development This chapter describes special features of DCE RPC for application development. The topics include • Memory management • Error handling • Context handles • Pipes • Nested calls and callbacks • Routing RPCs • Portable data and the IDL encoding services 16.1 Memory Management When called to handle a remote operation, RPC client stubs allocate and free memory by using whatever memory management scheme is currently in effect.
OSF DCE Application Development Guide—Core Components RPC server stubs do not allocate memory. Instead, they rely on the manager code—the code that the server stubs call—to allocate it for them. The following sections gives guidelines for how client code and manager code should use the the various allocation and free routines provided with DCE. Note: DCE provides two versions of DCE RPC stub support routines.
Topics in RPC Application Development declare the reflect_deletions operation attribute. Manager code uses the operating system allocation routine to create storage for its internal data. The server stub does not automatically free memory that operating system allocation routines have allocated. Instead, manager code must use the operating system free routine to deallocate the memory explicitly before it exits.
OSF DCE Application Development Guide—Core Components /* Get RPC memory allocation thread handle */ rpc_ss_thread_handle_t thread_handle; idl_void_p_t (*p_saved_alloc)(unsigned long); void (*p_saved_free)(idl_void_p_t); TRY thread_handle = rpc_ss_get_thread_handle(); CATCH(pthread_badparam_e) thread_handle = NULL; ENDTRY if (thread_handle == NULL) { /* Set up rpc_ss_allocate environment */ rpc_ss_enable_allocate(); } rpc_ss_swap_client_alloc_free( appl_client_alloc,appl_client_free, &p_saved_alloc,&p_save
Topics in RPC Application Development rpc_ss_swap_client_alloc_free(), client code must ensure that it has not been called from a manager routine. Deallocation of allocated storage returned from the client stubs is not automatic. Therefore, client code must ensure that it uses the free routine that it specified in the call to rpc_ss_swap_client_alloc_free() to deallocate each piece of allocated storage.
OSF DCE Application Development Guide—Core Components handles with the manager thread. 16.1.4.2 Transitioning from Client to Server to Client Immediately before the program changes from a client to a server, it must obtain a handle on its environment as a client by calling rpc_ss_get_thread_handle(). When it reverts from a server to a client, it must reestablish the client environment by calling the rpc_ss_set_thread_handle( ) routine, supplying the previously obtained handle as a parameter. 16.
Topics in RPC Application Development • You can use a simpler coding style. • Exceptions work well for coarse-grained exception handling. • If your application does not contain any exception handlers and the application thread gets an error, the application thread is terminated and a system-dependent error message from the threads package is printed. Note: RPC exceptions are equivalent to RPC status codes.
OSF DCE Application Development Guide—Core Components The fault_status attribute has the following characteristics: • Occurs where you do not want transparent local/remote behavior • Occurs where you expect that you may be passing incorrect data to the server or the server is not coded robustly, or both • Works well for fine-grained error handling • Requires that you adjust procedure declarations between local and distributed code • Controls the reporting only of errors that come from the server an
Topics in RPC Application Development The comm_status attribute is useful only if the call to the operation has a specific recovery action to perform for one or more communications failures; for example, rpc_s_comm_failure or rpc_s_no_more_bindings. The comm_status attribute is recommended only when the application knows that it is calling a remote operation.
OSF DCE Application Development Guide—Core Components environment, finding a server may not be difficult (if the network is relatively stable and has enough resources), and adding comm_status serves only to introduce differences between the local and distributed applications. If a decision as to what action to take is based upon a communications failure, then you may try to add the conditional code comm_status requires. Otherwise, using auto_handle allows an attempt on each available server.
Topics in RPC Application Development CATCH_ALL display_message("Stock quote not currently available"); ENDTRY This example assumes that update_a_quote( ) eventually calls the remote operation query_stock_quote() and that this call may raise an exception that is detected and reported here. The advantage of using exceptions in this case is that all of the work done in update_a_quote( ) has the same error recovery and it does not need to be repeated at every call to a remote operation.
OSF DCE Application Development Guide—Core Components A manager routine that returns a context handle as an out parameter declares it as my_handle_t *h; The routine then sets the value of the handle as follows: *h = &context_data; A routine that refers to a context handle as an in parameter declares it as my_handle_t h; and dereferences the handle as follows: context_data = (my_handle_t*)h; For the in,out case, the routine uses the same declaration as in the out case, and dereferences the handle as foll
Topics in RPC Application Development /* A storage object name string: /* typedef [string] char* store_name_t; */ */ /* A buffer type for data: typedef byte store_buf_t[*]; */ /* Note that the context handle is an [out] parameter of the open /* routine, an [in, out] parameter of the close routine, and an /* [in] parameter of the other routines.
OSF DCE Application Development Guide—Core Components 16.3.2 Context Handles in a Server Manager Server manager code to provide a rudimentary implementation of the store interface is as follows: /* context_manager.c -- implementation of "store" interface. */ /* */ /* The server maintains a certain number of storage areas, only one of */ /* which can be (or should be) opened by a single client at a time.
Topics in RPC Application Development /* The server entry name: extern unsigned_char_p_t entry; */ /* Initialization control block: pthread_once_t init_once_blk = pthread_once_init; */ /****** * * store_mgmt_init -- Zeroes out all the storelet structures; executed * only once per server instance, as soon as a client * has called the store_open() routine.
OSF DCE Application Development Guide—Core Components pthread_once(&init_once_blk, store_mgmt_init); /* The following loop goes through all the storelets, looking for /* one whose reference count is zero. As soon as one such is /* found, a handle is allocated for it, storage is allocated for /* its store structure, and the loop (and the call) terminates. If /* no unreferenced storelet is found, a status of -1 is returned /* and no handle is allocated...
Topics in RPC Application Development /* If the reference count turned out to have */ /* been accessed between our first check and our */ /* locking the mutex, we must now unlock the mutex */ /* preparatory to looping around to check the next */ /* storelet... */ *status = pthread_mutex_unlock((pthread_mutex_t *)hdr); if (*status != 0) { return; } } } /* The following is reached only if we never found a free /* storelet...
OSF DCE Application Development Guide—Core Components spec = (store_spec_t *)*store_h; /* Get the store spec. hdr = headers + spec->number; /* Point to the correct storelet. */ */ /* If the thing is actually opened, close it... if (hdr->refcount > 0) { /* Lock the header first...
Topics in RPC Application Development * store_read -- Read a certain number of bytes from the opened store. * ******/ /************************************************************************/ void store_read( store_handle_t store_h, /* Store handle. */ unsigned32 buf_size, /* Number of bytes to read. */ store_buf_t buffer, /* Space to return data read in. */ unsigned32 *data_size, /* To return number of bytes read in. */ error_status_t *status ) { store_spec_t *spec; /* Our handle pointer.
OSF DCE Application Development Guide—Core Components store_handle_t store_h, unsigned32 buf_size, store_buf_t buffer, unsigned32 *data_size, error_status_t *status /* /* /* /* Store handle. Number of bytes to write. Data to be written. To return number of bytes written. */ */ */ */ ) { store_spec_t *spec; store_hdr_t *hdr; /* Our pointer to store handle. /* Pointer to a storelet. */ */ /* Do an access check on IDL_handle here... /* [--ORIGINAL NOTE] -- I don’t know what the above means.
Topics in RPC Application Development error_status_t status) /* status we want to print the message for. { dce_error_string_t error_string; int print_status; */ dce_error_inq_text(status, error_string, &print_status); fprintf(stderr," Manager: %s: %s0, caller, error_string); } The sample implementation of the store interface is obviously too limited for any practical use, but it does demonstrate the application of context handles in a straightforward way.
OSF DCE Application Development Guide—Core Components The stub detects outstanding context when it marshals context handle parameters. Outstanding context is considered to exist from the point at which a non-NULL pointer value is returned, until a NULL pointer value is returned. When outstanding context exists, the server stub code will call a context rundown routine in response to certain exceptions that indicate a loss of contact with the client.
Topics in RPC Application Development 16.3.4 Binding and Security Information One element that is clearly missing from the context handle sample code is any access checking. To do this, it is necessary to get the client binding, although it may not be immediately obvious how to do this with a context handle. The answer is actually quite simple but, to understand it, it helps to have a clear idea of how binding parameters operate in RPC.
OSF DCE Application Development Guide—Core Components This technique can be used in a number of ways; for example, to permit the client to use implicit binding while the server manager operations extract authorization information from a client binding handle. In the case of a context handle, the principle is the same. You use the server .acf declarations to add a binding parameter to the call on the server side.
Topics in RPC Application Development One of the pipe support routines that the client must provide is an alloc routine, which allocates a buffer for each chunk of pipe data. Given that pipes are intended to process data asynchronously, consuming it as it arrives, the alloc routine should not just blindly allocate a new buffer each time it is called, since the net effect would be to allocate space for the whole stream.
OSF DCE Application Development Guide—Core Components handle_t binding_h, test_pipe_t test_pipe, error_status_t *status ) { char buffer[SBUFFSIZE]; int count; char *cptr; do { (*(test_pipe.pull))(test_pipe.state, buffer, \ SBUFFSIZE, &count); for (cptr = buffer; cptr < buffer + count; cptr++) putchar(*cptr); } while (count > 0); } Using the buffer supplied by the manager, the test_pipe.pull routine unmarshals an amount of data that is nonzero, but not more than the buffer can hold.
Topics in RPC Application Development client_pipe_state_t * state; byte *buf; unsigned int esize; unsigned int *ecount; { if ( ! state->file_open ) { state->file_handle = open(state->filename,O_RDONLY); if (state->file_handle == -1) { printf("Client couldn’t open %s0, state->filename); exit(0); } state->file_open = true; } *ecount = read( state->file_handle, buf, esize ); if (*ecount == 0) { close(state->file_handle); state->file_open = false; } } Finally, the client must do the following: 1.
OSF DCE Application Development Guide—Core Components 16.4.2 Output Pipes An [out] pipe is implemented in a similar way to an input pipe, except that the client and server make use of the push routine instead of the pull routine. The following samples show an [out] pipe used to read the output from a shell command executed by the server.
Topics in RPC Application Development { if ((str_ptr = popen(cmd, "r")) == NULL) return; while ((n = fread(buffer, sizeof(char), \ SBUFFSIZE, str_ptr)) > 0) { (*(test_pipe->push))(test_pipe->state, buffer, n); } (*(test_pipe->push))(test_pipe->state, buffer, 0); fclose(str_ptr); } /* Here’s another method: list an arbitrary directory * This time, we buffer the directory names as null* terminated strings of various lengths.
OSF DCE Application Development Guide—Core Components */ void test_push( rpc_ss_pipe_state_t *state, idl_char *buf, unsigned32 count ) { unsigned_char_t *cptr; for (cptr = buf; cptr < buf + count; cptr++) { /* For the second, directory reading example, uncomment the following: if (*cptr == 0) *cptr = ’0; */ putchar(*cptr); } } For an out pipe, the client code must do the following: 1. Allocate the test_pipe_t structure. 2. Initialize the test_pipe_t.push and test_pipe_t.state fields. 3.
Topics in RPC Application Development or test_pipe.pull), and the server manager makes a cycle of calls to either test_pipe.push or test_pipe.pull of the stub. The application code gives the illusion that the server manager is calling the client-supplied callbacks. In fact, the manager is actually calling stub-supplied callbacks, and the client callbacks are asynchronous: a server manager call to one of the callback routines does not necessarily result in a call to the corresponding client callback.
OSF DCE Application Development Guide—Core Components 4. The first remote procedure then resumes executing the initial call. Figure 16-1.
Topics in RPC Application Development Multithreaded RPC application The server application thread (listening) Remote server A client application thread 1 Calling code RPC thread Call thread acting as a client 4 First remote procedure Call thread Second remote procedure 3 Nested RPC thread 2 Single address space The application threads in the preceding figure are performing the following activities: 1.
OSF DCE Application Development Guide—Core Components 2. When the request arrives at the endpoint, the server’s system places it in a request buffer belonging to the corresponding server. 3. As one of its scheduled tasks, the server gets the incoming calls from the request buffer. The server either accepts or rejects an incoming call, depending on available resources. If no call thread is available, an accepted call is queued to wait its turn for an available call thread. 4.
Topics in RPC Application Development DCE daemon Step 1. Endpoint map Interface ID Object UUID Prot. seq. ... ... ncacn_ip_tcp 1025 ... ... ... ncadg_ip_udp 2001 ... Ept. . . . Server process Returned call Step 6. Endpoint Step 5. Select manager for call Call thread Request buffer Step 4. 1025 Step 2. Call queue Endpoint Request buffer 2001 Incoming call Step 3. Key: = remote procedure call The concepts in the following subsections are for the advanced RPC developer.
OSF DCE Application Development Guide—Core Components 16.6.1 Obtaining an Endpoint The endpoint mapper service of dced maintains the local endpoint map. The endpoint map is composed of elements which contain fully bound server binding information for a potential binding and an associated interface identifier and object UUID (which may be nil). Optionally, a map element can also contain an annotation such as the interface name.
Topics in RPC Application Development Server’s Inputs to Endpoint−Register Operation interface −handle > Interface ID: 2FAC8900 −31F8−11CA−B331 −08002B13D56D,1.0 binding −handle −list* > Server addresses: ncacn_ip_tcp:16.20.15.25[1025] ncadg_ip_udp:16.20.15.
OSF DCE Application Development Guide—Core Components • A server binding handle that refers to compatible binding information that contains the following: — A protocol sequence from the client’s server binding information — The same RPC protocol major version number that the client runtime supports — At least one transfer syntax that matches one used by the client’s system To identify the endpoint of a compatible server, the endpoint service uses the following rules: 1. 2.
Topics in RPC Application Development Call asking for non−nil Object UUID ? No No Interface UUID registered (with nil object UUID) ? No No Yes Non−nil object UUID and interface UUID registered together ? Yes Yes Other mapping information compatible ? Yes Insert endpoint into server binding information. Endpoint lookup fails. You can design a server to allow the coexistence on a host system of multiple interchangeable instances of a server.
OSF DCE Application Development Guide—Core Components For interchangeable server instances to register their endpoints in the local endpoint map, they must instruct the endpoint map service not to replace any existing elements for the same interface identifier and object UUID. Each server instance can create new map elements for itself by calling the rpc_ep_register_no_replace( ) routine.
Topics in RPC Application Development How the runtime handles a given request depends partly on the communications protocol over which it arrives, as follows: • A call over a connectionless transport is routed by the server’s system to the call request buffer for the endpoint specified in the call. • A call over a connection-oriented transport may be routed by the server’s system to a request buffer or the call may go directly to the server process.
OSF DCE Application Development Guide—Core Components Figure 16-6. A Request Buffer at Full Capacity System Rejected request Request buffer −− call request maximum = 5 6 5 4 3 2 1 (connection refused; datagram timed out) 16.6.3 Queuing Incoming Calls Each server process uses a first-in, first-out call queue. When the server is already executing its maximum number of concurrent calls, it uses the queue to hold incoming calls.
Topics in RPC Application Development Figure 16-7. Stages of Call Routing by a Server Process A. B. Server process Server process Call thread −− concurrent calls maximum = 1 Call thread Call queue Available call thread No available call thread 1 queue empty Incoming call Call queue 2 3 queue Incoming call 1 NOT full 4 5 C. Server process D.
OSF DCE Application Development Guide—Core Components 4. In stage D, the called procedure has completed call 1, making the call thread available. The server has removed call 2 from the queue and is passing it to the call thread for execution. Thus, the queue is partially empty as call 12 arrives, so the server accepts the call and adds it to the queue. 16.6.
Topics in RPC Application Development Figure 16-8. Decisions for Selecting a Manager Call asking for non −nil Object UUID ? Yes Non −nil type UUID set for object ? No No Yes Manager registered with same non−nil type UUID ? Manager registered for nil type UUID ? No No Yes Yes Reject call Dispatch call to nil type manager Dispatch call to appropriate non−nil type manager Key: = The default decision path 16.
OSF DCE Application Development Guide—Core Components and decoding functions are just like marshalling and unmarshalling, except that the data is stored locally and is not transmitted over the network; the IDL encoding services separate the data marshalling and unmarshalling functions from interaction with the RPC runtime.
Topics in RPC Application Development to as different buffering styles. The different buffering styles are: • Incremental encoding The incremental encoding style requires that you provide an allocate routine which creates an empty buffer into which IDL encoding services can place encoded data, and a write routine which IDL encoding services will call when the buffer is full or all the parameters of the operation have been encoded.
OSF DCE Application Development Guide—Core Components 16.7.3 IDL Encoding Services Handles When an application’s encoding or decoding operation is invoked, the handle passed to it must be an IDL encoding services handle (the idl_es_handle_t type). The IDL encoding services handle indicates whether encoding or decoding is required, and what style of buffering is to be used.
Topics in RPC Application Development 16.7.4 Programming Example The following example uses the IDL encoding service features described in the preceding sections. The example verifies that the results of a number of decoding operations are the same as the parameters used to create the corresponding encodings.
OSF DCE Application Development Guide—Core Components The test code for the example is as follows: #include #include #include #include #include #include #include "rpcexc.h" "es_array.
Topics in RPC Application Development /* * User write routine for incremental encode */ void es_write(state, buf, size) idl_void_p_t state; idl_byte *buf; idl_ulong_int size; { es_state_t *p_es_state = (es_state_t *)state; write(p_es_state->file_handle, buf, size); free(p_es_state->malloced_addr); } /* * User read routine for incremental decode */ void es_read(state, buf, size) idl_void_p_t state; idl_byte **buf; idl_ulong_int *size; { es_state_t *p_es_state = (es_state_t *)state; read(p_es_state->file_hand
OSF DCE Application Development Guide—Core Components { arr[i] = random()%10000; sarr[i].b = i & 0 x 7 f ; sarr[i].l = random()%10000; ref_sarr[i] = sarr[i]; tarr[i].b = i & 0 x 7 f ; fo r j ( = 0; j < ; 7 j++) tarr[i].a[j] = random()%10000; ref_tarr[i] = tarr[i]; } /* *Incremental encode/decode */ /* Encode data using one operation */ es_state.file_handle = open("es_array_1.dat", \ O_CREAT|O_TRUNC|O_WRONLY, 0777); if (es_state.file_handle < 0) { printf("Can’t open es_array_1.
Topics in RPC Application Development /* Decode the data using another operation with the same signature */ out_data_addr = (idl_byte *)(((out_buff - (idl_byte *)0) + 7) & (˜7)); out_data_size = (OUT_BUFF_SIZE - (out_data_addr - out_buff)) & (˜7); es_state.file_handle = open("es_array_1.dat", O_RDONLY, 0); if (es_state.file_handle < 0) { printf("Can’t open es_array_1.
OSF DCE Application Development Guide—Core Components array_op2(es_h, sarr); idl_es_handle_free(&es_h, &status); if (status != error_status_ok) { printf("Error %08x from idl_es_handle_free\n", status); exit(0); } idl_es_decode_buffer(fixed_buff_start, encoding_size, &es_h, &status); if (status != error_status_ok) { printf("Error %08x from idl_es_decode_buffer\n", status); exit(0); } array_op2(es_h, out_sarr); idl_es_handle_free(&es_h, &status); if (status != error_status_ok) { printf("Error %08x from idl_es
Topics in RPC Application Development idl_es_decode_buffer(dyn_buff_start, encoding_size, &es_h, &status); if (status != error_status_ok) { printf("Error %08x from idl_es_decode_buffer\n", status); exit(0); } array_op3(es_h, out_tarr); rpc_ss_free (dyn_buff_start); idl_es_handle_free(&es_h, &status); if (status != error_status_ok) { printf("Error %08x from idl_es_handle_free\n", status); exit(0); } fori ( = 0; i < ; N i++) { if (out_tarr[i].b != ref_tarr[i].b) { printf("array_op3 - out_tarr[%d].
OSF DCE Application Development Guide—Core Components 16.7.5 Performing Multiple Operations on a Single Handle Multiple operations can be performed using one encoding handle before the handle is released. In this case, all the encoded data is part of the same buffer system. A single decoding handle is used to obtain the contents of the encoded data. Decoding operations must be called in the same order the encoding operations were called to create the encoded data.
Chapter 17. Interface Definition Language This chapter describes how to construct an Interface Definition Language (IDL) file. First, it describes the IDL syntax notation conventions and lexical elements. It then describes the interface definition structure and the individual language elements supported by the IDL compiler. 17.1 The Interface Definition Language File The IDL file defines all aspects of an interface that affect data passed over the network between a caller (client) and a callee (server).
OSF DCE Application Development Guide—Core Components Constant Constant width typeface is used for source code examples (in IDL or in C) that are displayed separately from regular text. 17.2.2 Special Symbols IDL documentation uses the following symbolic notations: [item] Italic brackets surrounding an item, which may include brackets in regular typeface, indicate that the item contained within them is optional.
Interface Definition Language alphabetic character. No IDL identifier can exceed 31 characters. In some cases, an identifier has a shorter maximum length because the IDL compiler uses the identifier as a base from which to construct other identifiers; we identify such cases as they occur. 17.3.2 Keywords IDL reserves some identifiers as keywords. In the text of this chapter, keywords are represented in bold typeface, and identifiers chosen by application developers are represented in italic typeface. 17.
OSF DCE Application Development Guide—Core Components A keyword, identifier, or number not preceded by a punctuation character must be preceded by whitespace. A keyword, identifier, or number not followed by a punctuation character must be followed by whitespace. Unless we note otherwise, any punctuation character may be preceded and/or followed by whitespace. When enclosed in "" (double quotes) or ’’ (single quotes), whitespace constructs are treated literally.
Interface Definition Language Some C data types are supported by IDL only with modifications or restrictions. For example, unions must be discriminated, and all arrays must be accompanied by bounds information. 17.4.3 Attributes The stub modules that are generated from an interface definition require more information about the interface than can be expressed in C. For example, stubs must know whether an operation parameter is an input or an output.
OSF DCE Application Development Guide—Core Components [interface_attribute, ...] interface interface_name Interface names, together with major and minor version numbers, are used by the IDL compiler to construct identifiers for interface specifiers, entry point vectors, and entry point vector types. If the major and minor version numbers are single digits, the interface name can be up to 17 characters long. 17.5.
Interface Definition Language TABLE 17-1.
OSF DCE Application Development Guide—Core Components • local 17.7.1 The uuid Attribute The uuid attribute specifies the Universal Unique Identifier (UUID) that is assigned to an interface. The uuid attribute takes the following form: uuid (uuid_string) A uuid_string is the string representation of a UUID. This string is typically generated as part of a skeletal interface definition by the utility u u i d g e n .
Interface Definition Language version (1.1) /* major and minor version numbers */ version (3) /* major version number only */ The version attribute can be omitted altogether, in which case the interface is assigned 0.0 as the default version number. A client and a server can communicate only if the following requirements are met: • The interface imported by the client and the interface exported by the server have the same major version number.
OSF DCE Application Development Guide—Core Components Each endpoint_spec is a string in the following form: " family : [endpoint] " The family identifies a protocol family. The following are accepted values for family: • ncacn_ip_tcp: NCA Connection over Internet Protocol: Transmission Control Protocol (TCP/IP) • ncadg_ip_udp: NCA Datagram over Internet Protocol: User Datagram Protocol (UDP/IP) The endpoint identifies a well-known endpoint for the specified family.
Interface Definition Language The following is a sample declaration of an exceptions attribute: [uuid(06255501-08AF-11CB-8C4F-08002B13D56D), version (1.1), exceptions ( exc_e_exquota, binop_e_aborted, binop_e_too_busy, binop_e_shutdown) ] interface binop { long binop_add( [in] long a, [in] long b ); } See Chapter 16 for more information on using exceptions. 17.7.5 The pointer_default Attribute IDL supports two kinds of pointer semantics.
OSF DCE Application Development Guide—Core Components 17.7.6 The local Attribute The local attribute indicates that an interface definition does not declare any remote operations and that the IDL compiler should therefore generate only header files, not stub files. The local attribute takes the following form: local An interface containing operation definitions must have either the local attribute or the uuid attribute. No interface can have both.
Interface Definition Language 17.8 Import Declarations The IDL import_declaration specifies interface definition files that declare types and constants used by the importing interface. It takes the following form: import file,... ; The file argument is the pathname, enclosed in double quotes, of the interface definition you are importing. This pathname can be relative; the -I option of the IDL compiler allows you to specify a directory from which to resolve import pathnames.
OSF DCE Application Development Guide—Core Components IDL provides only integer, Boolean, character, string, and null pointer constants. Following are examples of constant declarations: const short TEN = 10; const boolean FAUX = FALSE; const char* DSCH = "Dmitri Shostakovich"; 17.9.1 Integer Constants An integer_type_spec is a type_specifier for an integer, except that the int_size for an integer constant cannot be hyper. An integer is the decimal representation of an integer.
Interface Definition Language 17.9.4 String Constants A string is a sequence of ASCII characters enclosed in double quotes. Whitespace characters are interpreted literally. The \ (backslash) character introduces an escape sequence, as defined in the ANSI C standard. The " (double quote) character can be coded in a string only if it is escaped by a backslash. You can specify any previously defined string constant as the value of a string constant. 17.9.
OSF DCE Application Development Guide—Core Components • ptr: The type being declared is a full pointer. • unique: The type being declared is a unique pointer. • string: The array type being declared is a string type. 17.10.2 BaseType Specifiers IDL base types include integers, floating-point numbers, characters, a boolean type, a byte type, a void type, and a primitive handle type. Table 17-2 lists the IDL base data type specifiers.
Interface Definition Language The idl_ macros are defined in dce/idlbase.h, which is included by header files that the IDL compiler generates. 17.10.3 Constructed Type Specifiers IDL constructed types include structures, unions, enumerations, pipes, arrays, and pointers. (In IDL, as in C, arrays and pointers are specified via declarator constructs rather than type specifiers.
OSF DCE Application Development Guide—Core Components 17.11 Operation Declarations The IDL operation_declaration can take the following forms: [[operation_attribute, ...]] type_specifier operation_identifier (parameter_declaration, ...); [[operation_attribute, ...]] type_specifier operation_identifier ([void]); Use the first form for an operation that has one or more parameters; use the second form for an operation that has no parameters.
Interface Definition Language 17.11.1 Operation Attributes Operation attributes determine the semantics to be applied by the RPC client and server protocol when an operation is called. 17.11.2 Operation Attributes: Execution Semantics The idempotent attribute specifies that an operation is idempotent; that is, it can safely be executed more than once. The broadcast attribute specifies that an operation is to be broadcast to all hosts on the local network each time the operation is called.
OSF DCE Application Development Guide—Core Components 17.12 Parameter Declarations A parameter_declaration is used in an operation declaration to declare a parameter of the operation. A parameter_declaration takes the following form: [parameter_attribute, ...] type_specifier parameter_declarator If an interface does not use implicit handles or use interface-based binding, the first parameter must be an explicit handle that gives the object UUID and location.
Interface Definition Language For information on the semantics of pointers as operation parameters, refer to the discussion of pointers in Section 17.14.7. 17.13 Basic Data Types The following subsections describe the basic data types provided by IDL and the treatment of international characters within IDL.
OSF DCE Application Development Guide—Core Components 17.13.2 Floating-Point Types IDL provides two sizes of floating-point data types, specified as follows: float double A float is represented in 32 bits. A double is represented in 64 bits. 17.13.3 The char Type The IDL character type is specified as follows: [unsigned] char A char is unsigned and is represented in 8 bits. The keyword unsigned is optional and has no effect. IDL does not support a signed character type.
Interface Definition Language format conversion by transmitting that type as an array of byte. 17.13.6 The void Type The IDL void type is specified as follows: void The void type may be used to do the following: • Specify the type of an operation that does not return a value • Specify the type of a context handle parameter, which must be void* • Specify the type of a NULL pointer constant, which must be void* 17.13.
OSF DCE Application Development Guide—Core Components The error_status_t data type contains an additional semantic to indicate that this particular unsigned long contains a DCE format error status value. This additional semantic enables the IDL compiler to perform any necessary translation when moving the status value between systems with differing hardware architectures and software operating systems.
Interface Definition Language • Structures • Unions • Enumerations • Pipes • Arrays • Strings In IDL, as in C, arrays and pointers are specified via declarator constructs. The other constructed types are specified via type specifiers. 17.14.1 Structures The type_specifier for a structure type can take the following forms: struct [tag] { struct_member; ...
OSF DCE Application Development Guide—Core Components A structure can contain a conformant array (conformant structure) only as its last member. And such a structure can be contained by another structure only as its last member, and so on. A conformant structure cannot be returned by an operation as its value and cannot be simply an out parameter. Note that a structure can contain any number of pointer to conformant arrays.
Interface Definition Language The union_name specifies a name to be used in C code generated by the IDL compiler. When the IDL compiler generates C code to represent an IDL union, it embeds the union and its discriminator in a C structure. The name of the IDL union becomes the name of the C structure. If you supply a union_name in your type declaration, the compiler assigns this name to the embedded C union; otherwise, the compiler assigns the generic name tagged_union.
OSF DCE Application Development Guide—Core Components pointer or any structure that contains a ref or unique pointer. The following is an example of an encapsulated union. /* IDL construct /* typedef union fred switch (long a) ralph { case 1: float b; case 2: long c; } bill; /* becomes in the generated header file /* typedef struct fred { long a; union { float b; long c; } ralph; } bill; 17.14.2.
Interface Definition Language The following example shows uses of a nonencapsulated union. typedef [switch_type(long)] union { [case (1,3)] float a_float; [case (2)] short b_short; [default] ; /* An empty arm. } n_e_union_t; Nothing is shipped. */ typedef struct { long a; /* The discriminant for the */ /* union later in this struct. */ [switch_is (a)] n_e_union_t b; } a_struct; /* Note switch can follow union in operation */ void op1 ( [in] handle_t h, [in,switch_is (s)] n_e_union_t u, [in] long s ); 17.
OSF DCE Application Development Guide—Core Components The type_specifier specifies the type for the elements of the pipe. This type cannot be a pointer type, a type that contains a pointer, a conformant type, a context handle, a handle_t element type, or a data type that is declared as transmit_as. A pipe type can be used to declare only the type of an operation parameter.
Interface Definition Language typedef struct pipe_t { void (* pull)( rpc_ss_pipe_state_t state, element_t *buf, idl_ulong_int esize, idl_ulong_int *ecount ); void (* push)( rpc_ss_pipe_state_t state, element_t *buf, idl_ulong_int ecount ); void (* alloc)( rpc_ss_pipe_state_t state, idl_ulong_int bsize, element_t **buf, idl_ulong_int *bcount ); rpc_ss_pipe_state_t state; } pipe_t; The pipe data structure specifies pointers to three separate routines and a pipe state.
OSF DCE Application Development Guide—Core Components 17.14.4.2 Rules for Using Pipes Observe the following rules when defining pipes in IDL: • Pipe types must only be parameters. In other words, pipes of pipes, arrays of pipes, and structures or unions containing pipes as members are illegal. • A pipe cannot be a function result. • The element type of a pipe cannot be a pointer or contain a pointer. • The element type of a pipe cannot be a context_handle or handle_t type.
Interface Definition Language After this sequence, neither the server stub nor the client stub can continue to execute properly. To avoid this situation, you must reraise the exception. • A pipe cannot be used in an operation that has the broadcast or idempotent attribute. • The element type of a pipe cannot be a conformant structure. • The maximum length of pipe type IDs is 29 characters. 17.14.
OSF DCE Application Development Guide—Core Components [ ] The lower bound is 0 (zero). The upper bound is determined by a max_is or size_is attribute. [lower .. ] The lower bound is lower. The upper bound is determined by a max_is or size_is attribute. [* .. upper] The lower bound is determined by a min_is attribute. The upper bound is upper. [* .. *] The lower bound is determined by a min_is attribute. The upper bound is determined by a size_is or max_is attribute. 17.14.5.
Interface Definition Language IDL Type Definition: typedef struct { long s; [size_is(s)] long fa3[3..*][-4..1][-1..2]; } t1; C Translation: typedef struct { idl_long_int s; idl_long_int fa3[1][6][4]; } t1; IDL Parameter Declaration: [in,out,size_is(s)] long fa3[3..*][-4..1][-1..2] C Translation: /* [in, out] */ idl_long_int fa3[][6][4] 17.14.5.3 Array Attributes Array attributes specify the size of an array or the part of an array that is to be transferred during a call.
OSF DCE Application Development Guide—Core Components Note that an array with an array attribute (that is, a conformant or varying array) is not allowed to have the transmit_as attribute. 17.14.5.3.1 The min_is Attribute The min_is attribute is used to specify the variable(s) from which the values of one or more lower bounds of the array will be obtained at runtime. If any dimension of an array has an unspecified lower bound, the array must have a min_is attribute.
Interface Definition Language /* [in, out] */ idl_long_int fa3[][6][4] 17.14.5.3.2 The max_is Attribute The max_is attribute is used to specify the variables from which the values of one or more upper bounds of the array are obtained at runtime. If any dimension of an array has an unspecified upper bound, the array must have a max_is or size_is attribute. A variable must be identified for each dimension in which the upper bound is unspecified.
OSF DCE Application Development Guide—Core Components /* Assume the following values for the referenced variables: n3 = 5 ; x2 = 12; x3 = 14; z2 = 9 ; z3 = 10; */ /* The following declaration */ int [min_is(,,n3),max_is(,x2,x3)] hh[3..13,4..*,*..*]; /* specifies the same data to be */ /* transmitted as the declaration */ int [min_is(,,n3),size_is(,z2,z3)] hh[3..13,4..*,*..*]; 17.14.5.3.
Interface Definition Language 17.14.5.3.5 The first_is Attribute The first_is attribute is one of the attributes that can be used to allow the amount of data in an array that will be transmitted to be determined at runtime. Each first_is attribute specifies a lower data limit, which is the lowest index value in that dimension for the array elements to be transmitted. If the entry in a first_is attribute for a dimension is empty, the effect is as if the lower bound in that dimension had been specified.
OSF DCE Application Development Guide—Core Components When an array with the length_is attribute is used in a remote procedure call, the elements actually passed in the call can be a subset of the maximum possible. The length_is attribute is for use with varying arrays.
Interface Definition Language 17.14.6 Strings IDL implements strings as one-dimensional arrays to which the string attribute is assigned.
OSF DCE Application Development Guide—Core Components one more than the maximum number of characters the string is to hold. For instance, if a string is to store 80 characters, the string must be declared with a size of 81: /* A string type that holds 80 characters */ typedef [string] char string_t [81]; If an array has the string attribute or if the type of an array has the string attribute, the array cannot have the first_is, the last_is, or the length_is attribute. 17.14.
Interface Definition Language Examples of pointers are shown at the end of this section. 17.14.7.1.1 Reference Pointers A reference pointer is the least complex form of pointer. The most common use for this class of pointer is as a passing mechanism; for example, passing an integer by reference.
OSF DCE Application Development Guide—Core Components 17.14.7.1.2 Full Pointers A full pointer is the most complex form of pointer. It supports all capabilities associated with pointers. For example, by using a full pointer you can build complex data structures such as linked lists, trees, queues, or arbitrary graphs.
Interface Definition Language A unique pointer has the following characteristics: • It can have a NULL value. • It can change from NULL to non-NULL during a call. This change results in memory being allocated on return from the call, whereby the result is stored in the allocated memory. • It can change from non-NULL to NULL during a call. This change can result in the orphaning of the memory pointed to on return from the call.
OSF DCE Application Development Guide—Core Components The following example shows how a unique pointer can be used: [ uuid(D37A0E80-5D23-11C9-B199-08002B13D56D) ] interface Unique_ptrs { typedef [ref] long *r_ptr; typedef [unique] long *u_ptr; typedef [ptr] long *f_ptr; void op1 ( [ref,in,out,string] char *my_rname, [unique,in,out,string] char *my_uname, [ptr,in,out,string] char *my_pname ); } 17.14.7.
Interface Definition Language void op ([in] long *int_value); To pass a NULL value, use a full pointer. The following two methods make int_value into a full pointer: • Applying the ptr attribute to the declaration of the parameter, int_value: void op ([in, ptr] long *int_value); • Using the pointer_default (ptr) attribute in an interface header : [uuid(135e7f00-1682-11ca-bf61-08002b111685, pointer_default(ptr), version(1.
OSF DCE Application Development Guide—Core Components 17.14.7.6 Resolving a Possible Pointer Ambiguity A declaration of the following form raises a possible ambiguity about the type of myarray: void op ([in, out] long s, [in, out, size_is(s)] long **myarray); IDL defines myarray in this case to be an array of pointers to longs, not a pointer to an array of longs. The max_is and size_is attributes always apply to the top-level, or rightmost, * (asterisk) in the IDL signature of a parameter. 17.14.7.
Interface Definition Language 17.14.7.8.1 Allocating and Freeing Memory Manager code within RPC servers usually uses the rpc_ss_allocate( ) routine to allocate storage. Storage that is allocated by rpc_ss_allocate( ) is released by the server stub after any output parameters have been marshalled by the stubs. Storage allocated by other allocators is not released automatically but must be freed by the manager code.
OSF DCE Application Development Guide—Core Components The syntax of the rpc_ss_disable_allocate() routine is as follows: void rpc_ss_disable_allocate (void); 17.14.7.9 Advanced Memory Management Support Memory management may also involve setting and swapping the mechanisms used for allocating and freeing memory.
Interface Definition Language The syntax of the routine is as follows: void rpc_ss_swap_client_alloc_free ( idl_void_p_t (*p_allocate) ( idl_size_t size), void (*p_free) ( idl_void_p_t ptr), idl_void_p_t (**p_p_old_allocate) ( idl_size_t size), void (**p_p_old_free) ( idl_void_p_t ptr) ); The p_allocate parameter points to a routine that has the same procedure declaration as the malloc() routine, and is used by the client stub when performing memory allocation.
OSF DCE Application Development Guide—Core Components The main manager thread must not return control to the server stub before all the threads it spawned complete execution; otherwise, unpredictable results may occur. The listener thread can cancel the main manager thread if the remote procedure call is orphaned or if a cancellation occurs on the client side of the application. You should code the main manager thread to terminate any spawned threads before it exits.
Interface Definition Language 17.14.7.
OSF DCE Application Development Guide—Core Components The STRING_TREE.IDL Example [uuid(0144d600-2d28-11c9-a812-08002b0ecef1), version(0)] interface string_tree { /* * Maximum length of a string in the tree */ const long int st_c_name_len = 32; /* * Definition of a node in the tree. */ typedef struct node { [string] char name[0..st_c_name_len]; [ptr] struct node *left; [ptr] struct node *right; } st_node_t; /* * Operation that prunes the left subtree of the specified * tree and returns it as the value.
Interface Definition Language /* ** Create a tree with a few nodes */ st_node_t *st_make_tree() { st_node_t *root = (st_node_t *)malloc(sizeof(st_node_t)); strcpy(root->name,"Root Node"); /* left subtree node */ root->left = (st_node_t *)malloc(sizeof(st_node_t)); strcpy(root->left->name,"Left subtree"); /* left subtree children */ root->left->right = NULL; root->left->left = (st_node_t *)malloc(sizeof(st_node_t)); strcpy(root->left->left->name,"Child of left subtree"); root->left->left->left = NULL; root->
OSF DCE Application Development Guide—Core Components The MANAGER.C Example #include #include "string_tree.h" /* ** Prune the left subtree of the specified tree and return ** it as the function value. */ st_node_t *st_prune_left (tree) /* [in,out] */ st_node_t *tree; { st_node_t *left_sub_tree = tree->left; tree->left = (st_node_t *)NULL; return left_sub_tree; } The SERVER.C Example #include #include "string_tree.
Interface Definition Language rpc_ep_register( /* register addresses in endpoint map database */ string_tree_v0_0_s_ifspec, /* interface specification */ binding_vector, /* (string_tree.h) the set of binding handles */ NULL, "", &status ); check_error(status, "Can’t add address to the endpoint database\n"); rpc_ns_binding_export( /* establish namespace entry rpc_c_ns_syntax_dce, /* syntax of the entry name (rpc.
OSF DCE Application Development Guide—Core Components 17.14.8 Customized Handles The handle attribute specifies that the type being declared is a user-defined, nonprimitive handle type, and is to be used in place of the predefined primitive handle type handle_t. The term customized handle is used to denote a nonprimitive handle.
Interface Definition Language A customized handle can be coded either in a parameter list as an explicit handle or in an interface header as an implicit handle. 17.14.9 Context Handles Manager code often maintains state information for a client. A handle to this state information is passed to the client in an output parameter or as an operation result.
OSF DCE Application Development Guide—Core Components You can also define a context handle within a type declaration as a forward reference to a structure type by tag, as follows: typedef [context_handle] struct opaque_struct * opaque_ch_t; Note that you do not need to define the structure type in the IDL file; it is a forward reference to a structure whose definition can be included into the server code, either from a private .h file or from a server IDL file.
Interface Definition Language This practice is not recommended, however, since it violates the opaqueness of the context handle type. The type name in a context handle declaration must be no longer than 23 characters. The first operation on a context creates a context handle that the server procedure passes to the client. The client then passes the unmodified handle back to the server in a subsequent remote call. The called procedure interprets the context handle.
OSF DCE Application Development Guide—Core Components typedef [context_handle] void * my_context; then the rundown procedure is as follows: void my_context_rundown (my_context this_object); Server application code that uses a certain context handle may be executing in one or more server threads at the time that RPC detects that communications between the server and the client that is using that context have broken.
Interface Definition Language context handle parameters cannot be NULL. However, if the only context handle parameters in an operation are output, they carry no binding information. In this case, you must use another method to bind the client to a server. If you specify multiple context handles in an operation, all active context handles must map to the same remote address space on the same server or the call fails.
OSF DCE Application Development Guide—Core Components * bound to that server be passed as the binding parameter h. * * Operation to OPEN a file; returns context handle for that * file. */ file_handle_t file_open ( /* RPC handle bound to file server */ [in] handle_t h, /* File specification of file to open */ [in] filespec_t fs ); /* * The file_read call is able to use the context handle * obtained from the file_open as the binding parameter, * thus an RPC handle is not necessary.
Interface Definition Language Example of a Context Rundown Procedure /* * fh_rundown.c: */ A context rundown procedure. #include #include "context_handle.h" void file_handle_t_rundown ( file_handle_t file_handle /* IDL-generated header file */ /* Active context handle */ * (open file handle) */ ) { /* * This procedure is called by the RPC runtime on the * SERVER side when communication is broken between the * client and server.
OSF DCE Application Development Guide—Core Components To build an application that uses presented and transmitted types, you must write routines to perform conversions between the types and to manage storage for the types, and you must link those routines with your application code. At runtime, the client and server stubs call these routines before sending and after receiving data of these types.
Interface Definition Language • A type that includes the handle attribute in its definition cannot be used, directly or indirectly, in the definition of a type with the transmit_as attribute. Nor can a type that includes the transmit_as attribute in its definition be used, directly or indirectly, in the definition of a type with the handle attribute. • A conformant array type. • A varying array type. • A structure type containing a conformant array. • An array type of which any instance is varying.
OSF DCE Application Development Guide—Core Components 17.16 IDL Grammar Synopsis This section summarizes IDL syntax, in extended Backus-Naur Format (BNF) notation. ::= "{" "}" ::= "[" "]" "interface" ::= [ "," ] ... ::= "uuid" "(" ")" | "version" "(" [ ".
Interface Definition Language | | "TRUE" | "FALSE" | "NULL" ::= ::= | "?" ":" ::= | "||" ::= | "&&" ::= | "|" ::= |
OSF DCE Application Development Guide—Core Components ::= """ [ ] ... """ ::= "typedef" [ ] ::= | ::= | | ::= [ "," ] ...
Interface Definition Language ::= | | | | ::= "struct" | ::= "struct" "{" "}" ::= "struct" "{" "}" ::= ::= [ ] ...
OSF DCE Application Development Guide—Core Components ::= ::= [ ::= ] ... [ ] ... ::= [ ] ... | ::= | ::= "case" ":" ::= "[" "case" "(" \ [ , ] ...
Interface Definition Language ::= ::= "first_is" "(" ")" | "last_is" "(" ")" | "length_is" "(" ")" | "max_is" "(" ")" | "min_is" "(" ")" | "size_is" "(" ")" | | | "ignore" | ::= [ "," ] ...
OSF DCE Application Development Guide—Core Components ::= ISO_LATIN_1 | ISO_MULTI_LINGUAL | ISO_UCS ::= [ "," ] ...
Chapter 18. Attribute Configuration Language The Attribute Configuration Language is used for writing an Attribute Configuration File (ACF). Use the attributes in the ACF to modify the interaction between the application code and stubs without affecting the client/server network interaction. 18.1 Syntax Notation Conventions The syntax of the Attribute Configuration Language is similar to the syntax of IDL. For syntax information, see the syntax notation conventions for the IDL.
OSF DCE Application Development Guide—Core Components 18.2.1 Naming the ACF To name the ACF, replace the extension of the IDL file (.idl) with the extension of the ACF (.acf). For example, the ACF associated with my_idl_filename.idl is my_idl_filename.acf. 18.2.2 Compiling the ACF When you issue the idl command, naming the IDL file to compile, it searches for a corresponding ACF and compiles it along with the IDL file.
Attribute Configuration Language 18.3 Structure The structure of the ACF is as follows: interface_header { interface_body } Follow these structural rules when creating an ACF: • The basename of the ACF must be the same as the basename of the IDL file although the extensions are different. • The interface name in the ACF must be the same as the interface name in the corresponding IDL file.
OSF DCE Application Development Guide—Core Components • extern_exceptions(exception_name[,exception_name]...) • cs_tag_rtn(tag_set_routine) The following example shows how to use more than one attribute in the ACF interface header: [auto_handle, binding_callout(rpc_ss_bind_authn_client)] \ interface phone_direct { } 18.3.2 ACF Interface Body The ACF interface body can contain the elements in the following list.
Attribute Configuration Language 18.3.3 The include Statement This statement specifies any additional header files you want included in the generated stub code. You can specify more than one header file. Do not specify the directory name or file extension when you use the include statement. The compiler appends the correct extension for the language you are using. For C, the compiler appends the .h extension.
OSF DCE Application Development Guide—Core Components operation in the interface starts from the top of the list when looking for a server to bind to. The auto_handle attribute can occur at most once in the ACF. If an interface uses the auto_handle attribute, the presence of a binding handle or context handle parameter in an operation overrides auto_handle for that operation. The auto_handle attribute declaration has the following syntax. (See the example at the end of this section.
Attribute Configuration Language operation parameter. The explicit_handle attribute has the following syntax. (See the example at the end of this section.) For an interface— [explicit_handle] interface interface_name For an operation— [explicit_handle] operation_name ([parameter_list] ); When used as an ACF interface attribute, the explicit_handle attribute applies to all operations in the IDL file. When used as an ACF operation attribute, this attribute applies to only the operation you specify.
OSF DCE Application Development Guide—Core Components 18.3.6 The implicit_handle Attribute This attribute allows the application program to manage the binding to the server. You specify the data type and name of the handle variable as part of the implicit_handle attribute. The implicit_handle attribute informs the compiler of the name and type of the global variable through which the binding handle is implicitly passed to the client stub.
Attribute Configuration Language 18.3.7 The comm_status and fault_status Attributes The comm_status and fault_status attributes cause the status code of any communications failure or server runtime failure that occurs in a remote procedure call to be stored in a parameter or returned as an operation result, instead of being raised to the client application code as an exception. The comm_status attribute causes communications failures to be reported through a specified parameter.
OSF DCE Application Development Guide—Core Components • If the parameter name is different from any name defined within the operation definition in the IDL file, the IDL compiler creates an extra output parameter of type error_status_t in the application code after the last parameter defined in the IDL file. In a successfully completed remote call, this extra parameter has the value error_status_ok.
Attribute Configuration Language /* * The three server procedures below illustrate the different * models of comm_status and fault_status appearing in the * idl and acf declarations above. * * RPC automatically passes back DCE error codes through * comm_status and fault_status. These examples differ in * their handling of the nonerror case. */ error_status_t add (double a, double b, double * c) { ... *c = answer; /* * comm_status and fault_status are operation attributes.
OSF DCE Application Development Guide—Core Components double multiply (double a, double b, error_status_t * c_sts, error_status_t * f_sts) { /* * c_sts and f_sts appear in the acf, but do not appear * in the idl definition. In this case, c_sts and f_sts * are placed at the end of the parameter list generated * by the idl compiler. To conform to the prototype * generated by idl, your server code must also declare * these parameters.
Attribute Configuration Language Do not use nocode on any of the operations if the compiler is generating only server stub code because it has no effect. Server stubs must always contain generated code for all operations. In the following example, the IDL compiler generates client stub code for the operations open, read, and close, but not for the operation write. An alternative method for specifying the same behavior is to use [nocode] write( ) in the ACF.
OSF DCE Application Development Guide—Core Components If you use the represent_as attribute, you must write routines that perform the conversions between the local and network types, and routines that release the memory storage used to hold the converted data. The conversion routines are part of your application code.
Attribute Configuration Language Example Using the represent_as Attribute ACF [auto_handle] interface phonedir { /* * You must specify an included file that contains the * definition of my_dir_t. */ include "user_types"; /* * The application code wants to pass data type my_dir_t * rather than dir_t. The [represent_as] clause allows * this, and you must supply routines to convert dir_t * to/from my_dir_t.
OSF DCE Application Development Guide—Core Components represent_as attribute. If the operation does not meet either of these conditions, but the manager application code needs to make use of the rpc_ss_allocate( ) and rpc_ss_free() routines, then use the enable_allocate attribute to force the stub code to enable. The enable_allocate attribute has the following syntax.
Attribute Configuration Language For a type— typedef [heap] type_name; For a parameter— operation_name ([heap] parameter_name); Any identifier occurring as a parameter name within an operation declaration in the ACF must also be a parameter name within the corresponding operation declaration in IDL. The heap attribute is ignored for pipes, context handles, and scalars.
OSF DCE Application Development Guide—Core Components The extern_exceptions attribute indicates that the specified exceptions are defined and initialized in some other external manner before calling the extern_exceptions attribute. They may be predefined exceptions (such as exc_e_exquota) that were provided by another interface, or exceptions that are defined and initialized explicitly by the application itself.
Attribute Configuration Language compiler to generate encoding or decoding stubs for operations defined in a corresponding IDL interface rather than generating RPC stubs for those operations. The encode and decode attributes have the following syntax. (See the example at the end of this section.
OSF DCE Application Development Guide—Core Components ACF interface es_array { [encode] in_array_op1(); [decode] out_array_op1(); [encode, decode] array_op2(); } IDL File [uuid(20aac780-5398-11c9-b996-08002b13d56d), version(0)] interface es_array { void in_array_op1([in] handle_t h, [in] long arr[100]); void out_array_op1([in] handle_t h, [out] long arr[100]); void array_op2([in] handle_t h, [in,out] long big[100]); void array_op3([in] handle_t h, [in,out] long big[100]); } 18.3.
Attribute Configuration Language The cs_char attribute differs from the [transmit_as] attribute in that it does not affect the network contract between the client and server.
OSF DCE Application Development Guide—Core Components needs of your application, you can use these RPC routines ( cs_byte_* and wchar_t_*) instead of providing your own routines. If you do provide your own routines for buffer sizing and code set conversion, they must follow a specific signature. See the reference pages for the cs_byte_*(3rpc) and wchar_t_*(3rpc) routines for a complete description of the required signatures for these routines.
Attribute Configuration Language typedef [cs_char(ltype)] my_byte; For a fixed array, if the IDL file contains typedef struct { my_byte fixed_array[80]; } fixed_struct; the declaration generated in the header file is typedef struct { ltype fixed_array[80]; } fixed_struct; The number of array elements in the local and network representations of the data must be the same as the array size stated in the IDL.
OSF DCE Application Development Guide—Core Components For a conformant varying array, if the IDL file contains typedef struct { long s; long l; [size_is(s), length_is(l)] my_byte open_array[]; } open_struct; the declaration generated in the header file is typedef struct { idl_long_int s; idl_long_int l; ltype open_array[1]; } open_struct; The maximum number of array elements in the local representation and the maximum number of array elements in the network representation need not be the same.
Attribute Configuration Language characters in in parameters must use the cs_stag attribute in the associated ACF. The cs_drtag attribute has the following syntax: operation_name ([cs_drtag] parameter_name); The cs_drtag attribute identifies the code set the client would like the server to use when returning international characters.
OSF DCE Application Development Guide—Core Components [cs_tag_rtn(tag_set_routine)] operation_name ([parameter_list] ); When used as an ACF interface attribute, the cs_tag_rtn attribute applies to all operations defined in the corresponding IDL file. When used as an ACF operation attribute, the cs_tag_rtn attribute applies only to the operation you specify. The tag_set_routine is the name of the stub support routine that the client and server stubs will call to set the operation’s code set tag parameters.
Attribute Configuration Language ACF typedef [cs_char(ltype)] my_byte; [cs_tag_rtn(set_tags)] a_op( [cs_stag] stag, [cs_drtag] drtag, [cs_rtag] p_rtag ); b_op( [cs_stag] stag, [cs_drtag] drtag, [cs_rtag] p_rtag ); Generated Header File typedef byte my_byte; void a_op( /* [in] */ idl_long_int s, /* [in, out] */ idl_long_int *p_l, /* [in, out, size_is(s), length_is(*p_l)] */ ltype a[] ); void b_op( /* [in] */ idl_ulong_int stag, /* [in] */ idl_ulong_ing drtag, /* [out] */ idl_ulong_int *p_rtag, /* [in] */ id
OSF DCE Application Development Guide—Core Components The binding_callout attribute has the following syntax. (See the example at the end of this section.) [binding_callout(routine_name)] interface interface_name The routine_name specifies the name of a binding callout routine that the client stub will call to modify the server binding handle before initiating the remote procedure call to the server. The IDL compiler will generate a function prototype for routine_name in the generated header file.
Attribute Configuration Language bindcall { } Generated Header File (bindcall.h) void my_bh_callout( rpc_binding_handle_t *p_binding, rpc_if_handle_t interface_handle, error_status_t *p_st ); 18.4 Summary of Attributes Table 18-1 lists the attributes available for use in the ACF and where in the file the attribute can be used. TABLE 18-1.
OSF DCE Application Development Guide—Core Components 18.5 Attribute Configuration Language This section summarizes the ACF syntax, in extended BNF notation. ::= "{" "}" ::= [ ] "interface" ::= "[" "]" ::= [ "," ] ...
Attribute Configuration Language ::= ";" | ";" | ";" ::= "include" ::= \ [ "," ] ...
OSF DCE Application Development Guide—Core Components "cs_tag_rtn" "(" ")" ::= ::= [ "," ] ... ::= [ ] ::= "[" "]" ::= [ "," ] ...
Part 4.
Chapter 19. Introduction to the Distributed Time Service API This chapter describes the DCE Distributed Time Service (DTS) programming routines. You can use these routines to obtain timestamps that are based on Coordinated Universal Time (UTC). You can also use the DTS routines to translate among different timestamp formats and perform calculations on timestamps. Applications can use the timestamps that DTS supplies to determine event sequencing, duration, and scheduling.
OSF DCE Application Development Guide—Core Components 19.1 DTS Time Representation UTC is the international time standard that has largely replaced Greenwich Mean Time (GMT). The standard is administered by the International Time Bureau (BIH) and is widely used. DTS uses opaque binary timestamps that represent UTC for all of its internal processes. You cannot read or disassemble a DTS binary timestamp; the DTS API allows applications to convert or manipulate timestamps, but they cannot be displayed.
Introduction to the Distributed Time Service API associated with the time. Although DTS displays all times in the previous format, variations to the ISO format shown in Figure 19-2 are also accepted as input for the ASCII conversion routines. Figure 19-2.
OSF DCE Application Development Guide—Core Components A relative time is normally used as input for commands or system routines. Figure 19-3 shows the full syntax for a relative time. Figure 19-3. Full Syntax for a Relative Time Relative date and time component Inaccuracy component DD−hh:mm:ss.fffIss.fff Days fractions hours seconds minutes Inaccuracy designator seconds fractions The following example shows a relative time of 21 days, 8 hours, and 30 minutes, 25 seconds with an inaccuracy of 0.
Introduction to the Distributed Time Service API Figure 19-4. Syntax for Representing a Duration P Yn Mn Wn DnT Hn Mn SnIn Period Designator Inaccuracy Designator/Inaccuracy Years/Year Designator Seconds/Second Designator Months/Month Designator Minutes/Minute Designator Weeks/Week Designator Hours/Hour Designator Days/Day Designator Time Designator 19.1.2.
OSF DCE Application Development Guide—Core Components and can convert other types of time structures to its own presentation of UTC-based time. The DTS API routines are used to perform these conversions for applications on your system. Table 19-1 lists the absolute time structures that the DTS API uses to modify binary times for applications. TABLE 19-1.
Introduction to the Distributed Time Service API The API provides the necessary routines for converting between opaque binary timestamps and character strings that can be displayed and read by users. 19.2.2 The tm Structure The tm structure is based on the time in years, months, days, hours, minutes, and seconds since 00:00:00 GMT (Greenwich Mean Time), 1 January 1900. The tm structure is defined in the time.h header file.
OSF DCE Application Development Guide—Core Components 19.2.4 The reltimespec Structure The reltimespec structure represents relative time. This structure is similar to the timespec structure, except that the first field is signed in the reltimespec structure. (The field is unsigned in the timespec structure.) You can find the reltimespec structure in the dce/utc.h header file.
Introduction to the Distributed Time Service API Retrieving Time ... utc_gettime utc_getusertime Converting Times ... tm To/From Structures: utc_anytime utc_gmtime utc_localtime utc_mkanytime utc_mkgmtime utc_mklocaltime utc_mkreltime utc_reltime To/From timespec Structures: utc_binreltime utc_bintime utc_mkbinreltime utc_mkbintime To/From ASCII text: utc_ascanytime utc_ascgmtime utc_asclocaltime utc_ascreltime utc_mkasctime utc_mkascreltime Manipulating Times ...
OSF DCE Application Development Guide—Core Components • utc_ascanytime Converts a binary timestamp into an ASCII string that represents an arbitrary time zone • utc_ascgmtime Converts a binary timestamp into an ASCII string that expresses a GMT time • utc_asclocaltime Converts a binary timestamp to an ASCII string that represents a local time • utc_ascreltime Converts a binary timestamp that expresses a relative time to its ASCII representation • utc_binreltime Converts a relative binary timestamp
Introduction to the Distributed Time Service API Gets the time zone label and offset from GMT, given utc • utc_mkanytime Converts a tm structure and TDF (expressing the time in an arbitrary time zone) into a binary timestamp • utc_mkascreltime Converts a null-terminated character string, which represents a relative timestamp, to a binary timestamp • utc_mkasctime Converts a null-terminated character string, which represents an absolute timestamp, to a binary timestamp • utc_mkbinreltime Converts a ti
Chapter 20. Time-Provider Interface This chapter describes the Time-Provider Interface (TPI) for DCE Distributed Time Service software. The chapter provides a brief overview of the TPI, explains how to use external time-providers with DTS, and describes the data structures and message protocols that make up the TPI. Coordinated Universal Time (UTC) is widely used and is disseminated throughout the world by various standards organizations.
OSF DCE Application Development Guide—Core Components • The DTS daemon is the client. • The Time-Provider process (TP process) is the server. Both the RPC-client (DTS daemon) and the server (TP process) must be running on the same system. Applications running on RPC communicate through an interface that is well known to both the client and the server. The RPC interface consists of a set of procedures, data types, and constants that describe how a client can invoke a routine running on the server.
Time-Provider Interface 3. The procedure terminates and returns the results through the TP server stub, the RPC runtime library, and the TP client stub. 4. The procedure terminates in the DTS call, where the returned parameters are examined. 5. DTS then calls the ServerRequestProviderTime remote procedure. Input parameters are passed to the TP client stub, dispatched to the RPC runtime library, and then passed to the TP server stub. Figure 20-1.
OSF DCE Application Development Guide—Core Components ContactProvider is the first routine called by DTS. The routine is called to verify that the TP process is running and to obtain a control message that DTS uses for subsequent communications with the TP process and for synchronization after it receives the timestamps.
Time-Provider Interface • Time Response Message An output parameter that contains a TP process status value (K_TPI_SUCCESS or K_TPI_FAILURE), a count of the timestamps that are returned, and the timestamps obtained from the external time-provider. The timestamp count is an integer in the range K_MIN_TIMESTAMPS to K_MAX_TIMESTAMPS. Each timestamp consists of three utc time values: — The system clock time immediately before the TP process polls the external time source.
OSF DCE Application Development Guide—Core Components interface time_provider { import "dce/nbase.idl"; import "dce/utctypes.idl"; /* Minimum and Maximum number of times to read time source at * each synchronization */ const long K_MIN_TIMESTAMPS = 1; const long K_MAX_TIMESTAMPS = 6; /* Message status field return values */ const long K_TPI_FAILURE = 0; const long K_TPI_SUCCESS = 1; /* This structure contains one reading of the TP wrapped in * the timestamps of the local clock.
Time-Provider Interface /* TP timestamp message. The actual time-provider * synchronization data. The status is the result of the * operation (success or failure). The timeStampCount * parameter returns the number of timestamps being returned * in this message. The timeStampList is the set of * timestamps being returned from the TP.
OSF DCE Application Development Guide—Core Components * | | *| | * | | * +--------------------------------------------+ * | . | * | . | * | . | * | . | * | . | * +--------------------------------------------+ * | | *| | * | | * +--------------------------------------------+ */ /* The RPC-based Time-Provider Program (TPP) interfaces are * defined here.
Time-Provider Interface 20.3 Initializing the Time-Provider Process Initializing the RPC-based TP process prepares it to receive remote procedure calls from a DTS daemon requesting the timestamps. The following steps are involved: 1. Include the header file (dtsprovider.h) that is created by compiling /usr/include/dce/dtsprovider.idl, which contains the interface definition. 2. Register the interface with the DCE RPC runtime. 3.
OSF DCE Application Development Guide—Core Components rpc_server_use_all_protseqs (max_calls, &RPCstatus); /* This routine is called to obtain a vector of binding * handles that were established with registration of * protocol sequences. */ rpc_server_inq_bindings (&bind_vector, &RPCstatus); /* This routine adds the address information of the binding * handle for the TP server to the endpoint mapper database.
Time-Provider Interface 1. Initialize the TP process, as described previously. Listen for RPC calls. 2. If the ContactProvider procedure is invoked, perform the following steps: 3. 4. a. Initialize the control message to the appropriate values (status value to K_TPI_SUCCESS; nextPoll, timeout, and noClockSet to valid integer values). b. Set the communication status output parameter to rpc_s_ok. c. Return from the procedure call. (The DCE RPC runtime returns the values to DTS.
OSF DCE Application Development Guide—Core Components 5. Make the remote procedure call ServerRequestProviderTime to obtain the timestamps from the external time-provider. If the procedure does not return within the elapsed time specified by the control message (timeout), then synchronize with peer servers. Schedule the next synchronization based upon the applicable DTS management parameters, ignoring nextPoll. 6. If the procedure returns successfully, verify that the TP process status is K_TPI_SUCCESS.
Chapter 21. DTS API Routines Programming Example This chapter contains a C programming example showing a practical application of the DTS API programming routines. The program performs the following actions: • Prompts the user to enter two sets of time coordinates corresponding to the timestamps of two ‘‘events.’’ • Stores those coordinates in a tm structure. • Converts the tm structure to a utc structure. • Prints out the utc structure in ISO text format. • Determines which event occurred first.
OSF DCE Application Development Guide—Core Components PrintTime(&event1); printf("\nThe second event is : "); PrintTime(&event2); printf("\n"); /* Determine which event occurred first.
DTS API Routines Programming Example /* Print out a utc structure in ISO text format. */ void PrintTime(utcTime) struct utc *utcTime; { char string[50]; /* Break up the time string. */ if (utc_ascgmtime(string, 50, utcTime)) exit(1); printf("%s\n",string); /* Out: Converted time */ /* In: String length */ /* In: Time to convert */ } /* Prompt the user to enter time coordinates. Store the * coordinates in a tm structure and then convert the tm * structure to a utc structure.
Part 5.
Chapter 22. Overview of Security This chapter provides a brief overview of the two security services available in DCE: • DCE Security Service • Generic Security Services (GSS) Refer to the OSF DCE Application Development Reference for detailed information on the Application Program Interfaces (APIs) discussed in the security chapters of this guide. 22.
OSF DCE Application Development Guide—Core Components The use of authenticated RPC is explained in Chapters 13 and 14. Chapter 14 contains information about a number of RPC routines that relate directly to security issues, such as rpc_binding_set_auth_info().
Overview of Security any compromise to the local security of a computer in the distributed environment may introduce opportunities for compromising network security, DCE security does not diminish the importance of local security. In fact, the relative importance of local system security is greater in the distributed environment because the consequences of a local security breach may not be local.
OSF DCE Application Development Guide—Core Components 22.6 Authentication, Authorization, and Data Protection in Brief When one principal talks to another in a distributed computing environment, there is a risk that communications between the two will provide a means for compromising the security of one or the other. For example, a client may attack a server, or a server may set a trap for clients.
Overview of Security 2. Principal A now makes a request to Principal B to perform some operation that requires the c permission to object d, and presents its certified privilege attributes. Principal B may grant or deny c access to d after examining the ACL that protects object d. (An ACL associates the privilege attributes of principals with permissions to an object.
OSF DCE Application Development Guide—Core Components 22.7 Summary of DCE Security Services and Facilities The DCE Security Service consists of services and facilities. The security services are • The registry service, which maintains a database of principals, groups, organizations, accounts, and administrative policies. • The authentication service, which verifies the identity of a principal and issues tickets that the principal uses to access remote services.
Overview of Security The security daemon (a replicated server) • sec_create_db Creates the security databases • sec_admin Administers instances of the security daemon • sec_salvage_db Converts the security database from one version of DCE to another Salvages a corrupted security database • The security validation service of dced Enables clients of the security server to communicate with it All other interfaces to the security server are more precisely characterized as interfaces to its three service
OSF DCE Application Development Guide—Core Components Obtains a login session’s ticket(s) to remote services (the login and su tools also perform this service) • klist Lists a login session’s tickets to remote services • kdestroy Destroys a login session’s tickets to remote services There are two security APIs that distributed applications are most likely to call to use the authentication service: • Authenticated RPC facility • GSSAPI Although an application that uses GSSAPI may not make explicit ca
Overview of Security 22.7.3 Interfaces to the Extended Registry Attribute Facility The user interface to the ERA facility consists of DCE control program (dcecp) commands that allow users to modify the registry schema to create and maintain attribute types and to create and maintain instances of those types. The API to the ERA facility consists of calls that are prefixed with sec_rgy_attr_. 22.7.4 Interfaces to the Extended Privilege Attribute Facility There are no user interfaces to the EPA facility.
OSF DCE Application Development Guide—Core Components 22.7.7 Interfaces to the Access Control List Facility The only user interface to the ACL facility is the dcecp ACL object acl_edit. This tool edits an object’s ACL, the entries of which specify the permissions to the object that may be granted to principals possessing specified privilege attributes. The ACL API consists of routines that are prefixed with sec_acl_.
Overview of Security Default DCE Security tools Applications Local OS security APIs Security API GSSAPI RPC API RPC or Peer to Peer Remote client or server Security and RPC runtime libraries Local operating system 22.9 DTS, the Cell Namespace, and Security The following subsections discuss the dependencies of DCE security on the Distributed Time Service (DTS), and the relationship between the security namespace and the Cell Directory Service (CDS) namespace.
OSF DCE Application Development Guide—Core Components Since the security namespace is rooted in the CDS namespace, security names have equivalent CDS names. Thus, for example, an entry for a principal in the registry database has the first of the following forms in the security namespace and the second of the following forms in the CDS namespace: /.../cell_name/principal_name /...
Chapter 23. Authentication This chapter explains concepts related to authentication. Both the authenticated RPC facility and the GSSAPI let you use Shared-Secret Authentication. When using the Authenticated RPC facility, you can choose the authentication protocol that your application uses to perform authentication. DCE Shared-Secret Authentication, which is used by the Authenticated RPC facility and the GSSAPI, is the default authentication protocol (and the chief topic of this chapter).
DCE Security Service 23.1.1 Principals Previously in this guide, we defined the term ‘‘principal’’ rather loosely. ‘‘Principal’’ is more precisely defined as follows: an entity that is capable of believing that it can communicate securely with another entity. In DCE Security, principals are represented as entries in the Registry database.
Authentication replicas) defines a separate cell. From the perspective of security only, a cell is also known as a ‘‘realm.’’ We mention this because the term ‘‘realm’’ is more familiar to some readers than is the term ‘‘cell.’’ A security cell is always configured to coincide with a corresponding CDS cell, and perhaps Distributed File System (DFS) cell as well. DCE documentation refers to such a collective configuration of services as a ‘‘cell.’’ 23.1.
DCE Security Service Refer to the discussion of Authenticated RPC in Part 3 of this guide for complete information about protection levels. 23.1.4.2 GSSAPI and Protection Levels Unlike secure RPC, where the client chooses a protection level that is then applied automatically to all data transferred in either direction, applications that use GSSAPI must protect data on a message-by-message basis.
Authentication 23.2 A Walkthrough of the Shared-Secret Authentication Protocol This section presents a 2-part walkthrough of the Shared-Secret Authentication protocol: • Section 23.2.1, ‘‘A Walkthrough of User Authentication,’’ explains what happens when a user logs in using the default DCE login tool. • Section 23.2.2, ‘‘A Walkthrough of DCE Application Authentication Using Authenticated RPC,’’ explains what happens when the logged-in user runs an application that uses authenticated RPC.
DCE Security Service the next chapter. 23.2.1 A Walkthrough of User Authentication This section explains how DCE Security authenticates a user. DCE User authentication can be thought of as consisting of two successive procedures: 1. Acquisition by the Security Client of a Ticket-Granting Ticket (TGT) for the user 2. Acquisition by the Security Client of a Privilege-Ticket-Granting Ticket (PTGT) for the user These procedures are described in the following two subsections.
Authentication Core Services for more detailed information on how security clients and the Authentication Service determine which protocol to use.) For a general discussion of the security aspects of these protocols, and of security administration and security ERAs, see the chapter entitled "Creating and Maintaining Principals, Groups, and Organizations" in the OSF DCE Administration Guide — Core Services. This section explains how the three protocols operate. 23.2.1.1.
DCE Security Service Figure 23-2. Client Acquires Ticket-Granting Ticket Using Third-Party Protocol secval Process User Interface ÅÅÅ ÍÍÍ ÅÅÅ ÍÍÍ ÍÍÍ ÍÍÍÍ ÅÅÅ ÍÍÍÍ ÅÅÅ ÍÍÍÍ ËËË ËËË ÁÁÁ ËËË ÂÂÂÂÂÂÂÂÂ ÁÁÁ ÂÂÂÂÂÂÂÂÂ ÁÁÁ ÅÅÅ ÂÂÂÂÂÂÂÂÂ ÅÅÅ ÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅÅÅ ÁÁÁÁÁÁÁ ÂÂÂÂÂÂ ËËË ÅÅÅÅÅÅÅÅ ÁÁÁÁÁÁÁ ÂÂÂÂÂÂ ËËË ÅÅÅÅÅÅÅÅ ÁÁÁÁÁÁÁ ÂÂÂÂÂÂ ËËË ÅÅÅÅÅÅÅÅ ÍÍÍÍÍ ÅÅÅ ÍÍÍÍÍ ÅÅÅ ÍÍÍÍÍ Login: principalname password sec_login_setup_ identity(principalname.. mtgt sec_login_valid_and cert_ident(password..
Authentication 1. The user logs in, entering the correct username. The login program invokes sec_login_setup_identity( ), which takes the user’s principal name as one of its arguments, and sec_login_valid_and_cert_ident(), which has as one of its arguments the user’s password. sec_login_valid_and_cert_ident() causes the Security runtime to request a Ticket-Granting Ticket (TGT) from the Authentication Service.
DCE Security Service proceeds with preparation of the user’s Ticket-Granting Ticket. 4. The Authentication Service then prepares the user’s Ticket-Granting Ticket, encrypts it using conversation key 2 (which it received from the client Security Runtime) and returns the encrypted TGT to the client. 5. The client Security Runtime decrypts the reply from the Authentication Service using conversation key 2, obtains the user’s Ticket-Granting Ticket, and it becomes part of the login context.
Authentication • In Step 1, the client Security runtime sends to the Authentication Service, in addition to the user’s name (UUID), a timestamp encrypted in the user’s secret key. • In Step 2, the Authentication Service, before preparing the user’s TGT, verifies the user as follows: 1. It decrypts the timestamp using the copy of the user’s key it obtained from the Registry. 2.
DCE Security Service Figure 23-3. Client Acquires Ticket-Granting Ticket Using the DCE1.0 Protocol User interface Registry Service login: principalname password get TGT for client ID corresponding to principalname ÀÀÀÀÀÀ ÄÄÄ ÀÀÀÀÀÀ ÄÄÄ ÁÁÁÁÁ ÀÀÀÀÀÀ ÄÄÄ ÁÁÁÁÁ ÀÀÀÀÀÀ ÄÄÄ ÁÁÁÁÁ ÀÀÀÀÀÀ ÀÀÀÀÀÀ ÀÀÀ ÀÀÀ ÄÄÄ ÁÁÁÁÁ ÂÂÂ ÄÄÄ ÄÄÄ ÁÁÁÁÁ ÂÂÂ ÂÂ ÄÄÄ ÁÁÁÁÁ ÁÁÁÁÁ sec_login_setup_ identity(principalname. . .) If status = OK, then get password prepare TGT RPC TGT ID sec_login_valid_and_ cert_ident(passwd. . .
Authentication service of interest; in this case, it is the Privilege Service. 2. Upon receiving the request for a TGT, the Authentication Service obtains the user’s secret key from the Registry database (where the secret keys of all principals in the cell are stored). Using its own secret key, the Authentication Service encrypts the user’s identity, along with a conversation key, in a TGT. The Authentication Service seals the TGT in an ‘‘envelope’’ that is encrypted using the user’s secret key.
DCE Security Service 2. Since the request for a ticket to the Privilege Service is encrypted under the conversation key associated with the TGT, the Authentication Service believes that the identity of the user is authentic; that is, no other principal could have sent a message so encrypted because no other principal knows the secret key under which the Authentication Service encrypted that conversation key.
Authentication Figure 23-4.
DCE Security Service 4. The Privilege Service decrypts the ticket sent to it, learning both the identity of the user and the conversation key it will use to encrypt its response. The Privilege Service believes the identity is authentic because the ID information was encrypted under its own secret key, and no principal other than the Authentication Service could have encrypted the information using this secret key.
Authentication addition of its identity to the delegation chain. The Privilege Service uses the delegation token, which is a seal over the EPAC encrypted in the Privilege Service’s key, to determine whether or not to certify the initiator’s credentials. If the initiator’s credentials are valid, the Privilege Service generates a new seal and delegation token to seal the initiator’s and the intermediary’s EPACs. Again, the delegation token is encrypted in the Privilege Service’s key.
DCE Security Service Figure 23-5. Client Sets Authentication and Authorization Information User interface start application API layer rpc_ns_binding_import_begin() rpc_ns_binding_import_next() . . .
Authentication 7. The Security runtime receives the client’s request, and learns from the header that the request is authenticated. Figure 23-6. Client Principal Makes Application Request Client Principal user action Application user interface Security runtime API app_request(binding ...
DCE Security Service 9. The Security runtime encrypts the random number using the fourth conversation key, which the Authentication Service gave it for the purpose of talking to the application server. The RPC runtime sends the encrypted random number and the server ticket to the application server. 10. The Security runtime decrypts the ticket using its secret key, in the process learning the conversation key and the client’s authorization.
Authentication Figure 23-7.
DCE Security Service 12. The client runtime receives and decrypts the response, and returns data to the application interface through the API. Figure 23-8.
Authentication application request and the ticket to the server at connection setup, rather than separately, as illustrated in Figures 23-6 and 23-7. 23.2.3 A Walkthrough of DCE Application Authentication Using GSSAPI This section describes the process by which applications that manage network communications without RPC can use GSSAPI and DCE Security to authenticate the applications with which they communicate. It continues from the end of "A Walkthrough of User Authentication", see Section 23.2.1.
DCE Security Service Figure 23-9. Peer Applications Establish a Security Context i.pI ../security/figures/2_authn_80.ps 0 0 1 1. The context initiator uses the gss_init_sec_context routine to request a ticket from the DCE Security Server that will allow the initiator to talk to the context acceptor.
Authentication • Ticket • EPAC(s) • Encrypted time stamp It sends the GSSAPI token to the initiator, which forwards it to the acceptor. 4. The acceptor calls the gss_accept_sec_context() routine which separates the ticket, the EPAC(s), and the encrypted time stamp, and send them to the acceptor’s Security Runtime. 5.
DCE Security Service 23.3.1 Authentication Service Surrogates A principal trusts another principal in its cell because it trusts the Authentication Service to authenticate all principals that are members of the cell, except for the Authentication Service itself, which its member principals trust a priori. The Authentication Service can authenticate all principals in its cell because it shares a secret key with each of them.
Authentication 23.3.2 Intercell Authentication by Trust Peers This section explains how a client principal in one cell is authenticated by an Authentication Service in a peer cell so that the client principal may communicate with another principal that is a member of the foreign cell. 1. A client principal, having already been authenticated by its Authentication Service and having acquired its PAC, requests a service from a foreign cell.
Chapter 24. Authorization This chapter explains concepts related to authorization. The authenticated RPC facility enables you to select the authorization protocol that your application uses. Among the authorization protocols supported by the DCE Security Service for use by authenticated RPC is DCE authorization (the default), and name-based authorization. This chapter first discusses DCE authorization, and more particularly, DCE access control lists (ACLs).
OSF DCE Application Development Guide—Core Components Note: The implementation of DCE ACLs is aligned with POSIX P1003.6 Draft 12. In the discussions in this chapter, we use the general term name to refer to a principal, group, or cell identifier; but readers should always bear in mind that these names have two representations: as UUIDs in ACL program interfaces and as print strings in user interfaces. 24.1.
Authorization Aside from the distinctions previously described, there are no differences between Object ACLs and Creation ACLs; therefore, the information about ACLs in the rest of this chapter does not differentiate between them. 24.1.2 ACL Manager Types A separate ACL manager type manages the ACLs for each class of objects for which permissions are uniquely defined.
OSF DCE Application Development Guide—Core Components 24.1.4 ACL Entries DCE authorization defines two basic kinds of ACL entries: • Those that associate a specified privilege attribute with a permission set; these are privilege attribute entries. • Those that specify a permission set that masks a permission set specified in a privilege attribute entry; these are mask entries. The following subsections describe the two kinds of ACL entries in detail. 24.1.4.
Authorization • group The group entry establishes the permissions for the local group named in this entry. An ACL may contain a number of entries of this type, but each entry must be unique with respect to the group it specifies. • foreign_group The foreign_group entry establishes the permissions for the foreign group named in this entry. An ACL may contain a number of entries of this type, but each entry must be unique with respect to the foreign group it specifies.
OSF DCE Application Development Guide—Core Components Following are descriptions of the fields: • The ACL entry_type specifies an ACL entry type as described in the previous list. • The key field specifies the privilege attribute to which the permissions listed in the entry apply. The key field for the ACL entry types user, group, foreign_user, foreign_group, and foreign_other explicitly names a principal, group, or cell.
Authorization from having no mask_obj entry in the ACL. In the first case, the effective permission set is empty; in the second case, the effective permission set is identical to the permission set in the privilege attribute entry. ACL entries for masks consist of two fields in the following form: entry_type:permissions Following are descriptions of the fields: • The entry_type field specifies one of the two masks entry types: mask_obj or unauthenticated.
OSF DCE Application Development Guide—Core Components 24.1.6 Examples of ACL Checking The following subsections provide some examples that illustrate ACLs and the accesscheck algorithms. The examples use the arbitrary convention of ordering entries as follows: masks, principals, groups, and ‘‘other’’ entries. However, the access check algorithm disregards the order in which entries appear in an ACL.
Authorization 2. The foreign_user entry for /.../cella/fritzb specifies the permissions abc. The application of the mask_obj, which specifies the permissions ab to this permission set, yields the permissions ab. Since the unauthenticated mask entry is missing from the ACL, all permissions for unauthenticated identities are masked, yielding an empty effective permission set. The result of these checks is that /...
OSF DCE Application Development Guide—Core Components 2. The matching entry among the user entries specifies the permissions abcdefg. Applying mask_obj (bcde) yields the permission set bcde. Applying the unauthenticated mask (ab) to the permission set bcde yields the effective permission set b. Since the principal ugob requests a permission (b) that is a member of the effective permissions set, this principal’s request is granted.
Authorization 3. There is no entry for the group projecty, so this check yields no permissions. 4. There is no other_obj entry, so this check can yield no permissions. 5. The principal is local, so no foreign_other entry can be a match; this check yields no permissions. 6. Having failed to match any entry examined in the preceding checks, the principal matches the any_other entry, which yields the permission set ab.
Chapter 25. GSSAPI Credentials A GSSAPI credential is a data structure that provides proof of an application’s claim to a principal name. An application uses a credential to establish its global identity. The global identity can be, but is not necessarily, related to the local user name under which the application (either the initiator or the acceptor) is running.
OSF DCE Application Development Guide—Core Components • Delegate credentials For detailed information on the GSSAPI routines referred to in this chapter, see the OSF DCE Application Development Reference. 25.
GSSAPI Credentials registered for the context acceptor to generate the default credential handle. The credential is an ACCEPT credential type. 25.2 Creating New Credential Handles An application can create a new credential handle to pass to the gss_init_sec_context() routine or the gss_accept_sec_context() routine.
OSF DCE Application Development Guide—Core Components 25.3 Delegating Credentials In delegation, an initiator forwards its identity to an acceptor so that the acceptor can use the identity to act as an agent for the initiator. There are two forms of delegation: — Impersonation delegation — Traced delegation 25.3.
Chapter 26. The Extended Privilege Attribute API This chapter describes the extended privilege attribute (EPA) API. The EPA facility addresses the requirements of complex distributed systems by allowing clients and servers to invoke secure operations via one or more intermediate servers. In a simple client/server distributed environment, most operations involve two principals: the initiator of the operation and the target of the operation.
OSF DCE Application Development Guide—Core Components • sec_login_disable_delegation() • sec_login_set_extended_attrs( ) 26.1 Identities of Principals in Delegation The identity of principals in a delegation chain is maintained in extended privilege attribute certificates (EPACs), as are the identities for all DCE principals. Each EPAC contains the name and group memberships of a principal in the delegation chain and any extended attributes that apply to the principal.
The Extended Privilege Attribute API permissions can be granted by delegate ACL entries. Delegate ACL entries grant permissions to principals only if they are acting as delegates.
OSF DCE Application Development Guide—Core Components If the requested permission is granted, the ACL manager then checks the permissions granted to the delegates in the chain. This checking is similar to the standard accesscheck algorithm, but it takes into account any additional delegate permissions granted to the delegates. If the requested permission is not granted to all delegates, access is denied. If the requested permission is granted to all delegates, access is granted. 26.
The Extended Privilege Attribute API Note that ACLs on objects that are targets of impersonation need list only the delegation initiator, not each delegate in the chain. Generally, traced delegation is the preferred method. The high degree of location transparency inherent in simple delegation greatly increases the risk of a client being compromised by a Trojan horse application.
OSF DCE Application Development Guide—Core Components • Anonymous principal UUID: fad18d52-ac83-11cc-b72d-0800092784e9 • Anonymous group UUID: fc6ed07a-ac83-11cc-97af-0800092784e9 The other_obj, any_other,other_obj_deleg, and any_other_deleg ACL entries define the anonymous principal’s access to objects. The entries must be set up just as for any other principal. The appropriate direct or delegate permissions must be granted to the anonymous principal or the delegated operation will fail. 26.2.2.
The Extended Privilege Attribute API 26.2.3 Optional and Required Restrictions When a principal calls sec_login_become_initiator( ) to enable delegation, or sec_login_become_delegate() or sec_login_become_impersonator( ) to become an intermediary, the principal can specify optional and required restrictions. Optional and required restrictions are provided for use by applications that have specific authorization requirements.
OSF DCE Application Development Guide—Core Components • sec_id_compat_mode_initiator Compatibility mode is on. The pre-Version 1.1 PAC data is extracted from the EPAC of the delegation initiator. • sec_id_compat_mode_caller Compatibility mode is on. The pre-Version 1.1 PAC data extracted from the EPAC of the last intermediary in the delegation chain. 26.
The Extended Privilege Attribute API • sec_cred_get_req_restrictions() Returns required restrictions • sec_cred_get_tgt_restrictions( ) Returns target restrictions • sec_cred_get_v1_pac( ) Returns pre-Version 1.1 privilege attributes • sec_cred_is_authenticated() Returns TRUE if the caller’s privilege attributes are authenticated or FALSE otherwise The sec_login_cred_*()calls are used by clients that are part of a delegation chain.
OSF DCE Application Development Guide—Core Components 26.5 Setting Extended Attributes The login API sec_login_set_extended_attrs( ) call adds extended registry attributes to a login context. The extended registry attributes must have been established and attached to the object by using the ERA API. (For more information on ERAs, see Chapter 28.
Chapter 27. The Registry API This chapter describes the registry API. Like the other security APIs, this one provides a simpler binding mechanism than the standard RPC handle structure. It includes facilities for creating and maintaining the registry database. Applications that run in the default DCE registry environment (that is, those that assume the presence of the default registry tools and servers) have no reason to call this API. 27.
OSF DCE Application Development Guide—Core Components The following calls bind a client to a registry server in preparation for registry operations.
The Registry API • principal Contains principal names; each name is associated with account information that is also specified here (for example, the name of the primary group) • group Contains groups and the names of their member principals • organization Contains organizations and the names of their member principals These three objects are referred to as name domains, and each member of a domain is referred to as a PGO item.
OSF DCE Application Development Guide—Core Components Changes the name of a PGO item • sec_rgy_pgo_replace() Replaces information corresponding to the specified PGO item The sec_rgy_pgo_*() interface contains the following calls for maintaining PGO membership lists: • sec_rgy_pgo_add_member() Adds a member to a group or organization membership list • sec_rgy_pgo_delete_member( ) Deletes a member from a group or organization membership list • sec_rgy_pgo_get_members() Returns a list of members of a gr
The Registry API 27.2.2 Creating and Maintaining Accounts The login-name field of an account contains a principal name, a primary group name, and an organization name. The account may also contain a project list (also known as a concurrent group set) that specifies all the groups to which the principal corresponding to the account belongs, but the login-name field itself specifies only one group name.
OSF DCE Application Development Guide—Core Components Replaces only the account data that is accessible to the user of the account 27.2.3 Registry Properties and Policies The following subsections outline some registry API parameters that affect the cell as a whole, and the routines that enable an application to retrieve and set values for them. 27.2.3.1 Registry Properties Several registry parameters and flags affect all accounts in the registry.
The Registry API 27.2.3.3 Organization Policies Another parameter set controls the set of accounts of principals that are members of an organization. These parameters control the lifetime and length of passwords, as well as the set of characters from which passwords may be composed. This parameter set also specifies the default lifespan of accounts associated with the organization.
OSF DCE Application Development Guide—Core Components • sec_rgy_wait_until_consistent( ) Blocks until all previous database updates have been propagated to all sites. This is useful for applications that first bind and write to an update site, and then bind to an arbitrary query site and depend upon up-to-date information. Note: The sec_rgy_wait_until_consistent() routine is not available in DCE Release 1.0 Version 1.0.2.
Chapter 28. The Extended Attribute API This chapter describes the extended attribute APIs. There are two extended attribute APIs: the extended registry attribute (ERA) interface to create attributes in the registry database and the DCE attribute interface to create attributes in a database of your choice.
OSF DCE Application Development Guide—Core Components The ERA API provides the ability to define attribute types and to attach attribute instances to registry objects. registry objects are nodes in the registry database, to which access is controlled by an ACL manager type. The registry objects are • principal • group • organization • policy • directory • replist • attr_schema All registry objects and their accompanying ACL manager type are described in the .
The Extended Attribute API 28.1.3 Attribute Type Components The sec_attr_schema_entry_t data type defines an attribute type. This data type contains attribute type identifiers and characteristics. The identifiers of attribute types are a name and a UUID. Generally, the name is used for interactive access and the UUID for programmatic access. Attribute type characteristics describe the format and function of the attribute type and thus control the format and function of instances of that type.
OSF DCE Application Development Guide—Core Components The attribute value is a string of encrypted bytes. This encrypted data can be passed over the network and is available to user-developed applications. • i18n_data An internationalized string of bytes with a tag identifying the OSF registered codeset used to encode the data. • uuid A DCE UUID. • attr_set The value is an attribute set, a vector of attribute type UUIDs used to associate multiple related attribute instances (members of the set).
The Extended Attribute API 28.1.3.2 ACL Manager Set An attribute type’s ACL manager set specifies the ACL manager type or types (by UUID) that control access to the object types to which attribute instances of this type can be attached. Attribute instances can be attached only to objects protected by the ACL manager types in the schema entry. For example, suppose an ACL manager set for an attribute type named MVSname lists only the ACL manager type for principals.
OSF DCE Application Development Guide—Core Components 28.1.3.3.2 The Multivalued Flag The multivalued flag specifies whether or not instances of the attribute can be multivalued. If an attribute is multivalued, multiple instances of the same attribute type can be attached to a single registry object. For example, if the multivalued flag is set on, a single principal can have multiple instances of attribute type A. If the flag is set off, a single principal can have only one instance of attribute type A.
The Extended Attribute API 28.1.3.4 The Intercell Action Field The intercell action field of the schema entry specifies the action that should be taken by the privilege server when reading attributes from a foreign cell.
OSF DCE Application Development Guide—Core Components attributes for which no schema entry exists 2. If the privilege server finds a matching attribute type in the local attribute schema, it retrieves the attribute.
The Extended Attribute API 28.1.3.7 Trigger Binding The schema entry trigger binding field contains a binding handle to a remote trigger that will perform processing for the attribute instances. See Section 28.4 for more information on attribute triggers. 28.2 Calls to Manipulate Schema Entries This section first introduces the sec_attr_schema_entry_t data type used by the calls that create and update schema entries that define attribute types.
OSF DCE Application Development Guide—Core Components • sec_attr_bind_info_t Specifies binding information for the trigger server associated with the attribute type (if an attribute trigger is associated with the attribute type). The sec_attr_bind_info_t data type uses two other data types: sec_attr_bind_auth_info_t and sec_attr_binding_t. The sec_attr_bind_info_t structure for trigger binding is described fully in Section 28.4. Figure 28-1 illustrates the structure of a sec_attr_schema_entry_t data type.
The Extended Attribute API 28.2.2.1 The sec_rgy_attr_sch_create_entry( ) Call The sec_rgy_attr_sch_create_entry( ) call creates a schema entry that defines an attribute type in the attribute schema. This call uses the sec_attr_schema_entry_t data type that completely defines the schema entry, including the following: • The attribute type name (generally used for interactive access) and UUID (generally used for programmatic access).
OSF DCE Application Development Guide—Core Components • Attribute name • Reserved flag • Apply defaults flag • Intercell action flag • Trigger binding • Comment Note that ACL managers can be added to a schema entry’s ACL manager set, but they cannot be modified or deleted. To modify any other schema entry fields implies a drastic change to the attribute type. If this change must be made, the schema entry must be deleted (which deletes all attribute instances of that type) and then recreated.
The Extended Attribute API released. The following calls allocate, initialize, and release a sec_attr_cursor_t for use with the sec_rgy_attr_sch_scan( ) call: • sec_rgy_attr_sch_cursor_init() The sec_rgy_attr_sch_cursor_init( ) call allocates resources to the cursor and initializes the cursor to the first attribute type entry in the attribute schema. This call also supplies the total number of entries in the attribute schema as part of its output. The cursor allocation is a local operation.
OSF DCE Application Development Guide—Core Components 28.2.3.3 The sec_rgy_attr_sch_lookup_by_id( ) and sec_rgy_attr_sch_lookup_by_name( ) Calls The sec_rgy_attr_sch_lookup_by_id() call reads the attribute schema entry identified by UUID. The output of the call is a sec_attr_schema_entry_t type that contains the specified attribute type’s name, UUID, and characteristics. Generally, this call is used for programmatic access. For interactive access, use the sec_rgy_attr_sch_lookup_by_name() call.
The Extended Attribute API is a tagged union of the actual value assigned (or to be assigned to the attribute instance) and a data type of sec_attr_encoding_t that specifies the encoding tags that define the attribute type characteristics. Figure 28-2 illustrates the structure of a sec_attr_t data type. Figure 28-2.
OSF DCE Application Development Guide—Core Components For multivalued attributes, because every instance of the multivalued attribute is identified by the same UUID, every instance is overwritten with the supplied value. For example, suppose object delores has three attributes of the multivalued type security_role. If you pass in one value for security_role, the values of all three are changed to the one you enter.
The Extended Attribute API Note that, if the deletion of any attribute instance in the array fails, all fail. However, to help pinpoint the cause of the failure, the call identifies the first attribute whose deletion failed in a failure index by array element number. 28.3.3 Reading Attribute Instances This section describes the calls that read attribute instances, and it describes the cursor used by the sec_rgy_attr_lookup_by_id( ) call. 28.3.3.
OSF DCE Application Development Guide—Core Components 28.3.3.2 The sec_rgy_attr_lookup_by_id( ) Call The sec_rgy_attr_lookup_by_id( ) call reads attributes specified by UUID for an object specified by name and domain. Specifically the call returns the following: • An array of sec_attr_t values. • A count of the total number of attribute instances returned. • A count of the total number of attribute instances that could not be returned because of size constraints of the sec_attr_t array.
The Extended Attribute API Note: Since attribute triggers cannot be associated with an attribute set instance, this call provides no way to supply input data to a query attribute trigger. 28.3.3.4 The sec_rgy_attr_lookup_by_name() Call The sec_rgy_attr_lookup_by_name() call reads a single attribute instance specified by name for an object specified by name and domain. The call returns a sec_attr_t for the specified attribute instance.
OSF DCE Application Development Guide—Core Components 28.4.1 Defining an Attribute Trigger/Attribute Association When an attribute is created with the sec_rgy_attr_update( ) call, you define the association between the attribute type and an attribute trigger by specifying the following: • Trigger Type Defines the trigger as a query server (invoked for query operations) or an update server (invoked for updates operations).
The Extended Attribute API • Binds to the attribute trigger (using a binding from the attribute type’s schema entry) • Makes the remote sec_attr_trig_update() call to the attribute trigger server, passing in the attributes provided by the caller • If the sec_attr_trig_update( ) call is successful, stores the output attribute(s) in the registry database and returns the output attribute(s) to the caller 28.4.2 Trigger Binding Two data types are used to defined an attribute trigger.
OSF DCE Application Development Guide—Core Components 28.4.2.1 The sec_attr_binding_t Data Type To describe the binding handle, the sec_attr_binding_t type uses a sec_attr_bind_type_t data type that specifies the format to the data used to generate the binding handle and a tagged union that contains the binding handle.
The Extended Attribute API 28.4.3 Access Control on Attributes with Triggers When a query or update call accesses an attribute associated with an attribute trigger, the call checks the ACL of the object with which the attribute is associated to see if the client has the permissions required for the operation. If access is granted, the operation returns a binding handle authenticated with the client’s login context.
OSF DCE Application Development Guide—Core Components 28.5.2 The sec_rgy_attr_trig_query() and sec_rgy_attr_trig_update( ) Calls The sec_attr_trig_query() call reads instances of attributes coded with a trigger type of query for a specified object. It passes an array of sec_attr_t values to a query attribute trigger and receives the output parameters back from the server.
The Extended Attribute API Note also that the DCE attribute calls are suffixed with 3dce, not 3sec (for example, dce_attr_sch_bind.3dce). The DCE attribute API consists of the following calls: • dce_attr_sch_bind() Returns an opaque handle of type dce_attr_sch_handle_t to a schema object specified by name and sets authentication and authorization parameters for the handle. This is the call used to bind to the schema of your choice.
OSF DCE Application Development Guide—Core Components • dce_attr_sch_lookup_by_id( ) Reads a schema entry identified by UUID. This call sec_rgy_attr_lookup_by_id( ) and is used in the same way. • • is based on Reads a schema entry identified by name. This call is sec_rgy_attr_sch_lookup_by_name( ) and is used in the same way. based on dce_attr_sch_lookup_by_name( ) dce_attr_sch_get_acl_mgrs() Retrieves the UUIDs of ACL manager types protecting objects dominated by a named schema.
The Extended Attribute API #define SA_BND_AUTH_INFO(B) #define SA_BND_AUTH_INFO_TYPE(B) (B)->auth_info (SA_BND_AUTH_INFO(B)).info_type #define SA_BND_AUTH_SVR_PNAME_P(B) \ (SA_BND_AUTH_DCE_INFO(B)).svr_princ_name #define SA_BND_AUTH_PROT_LEVEL(B) \ (SA_BND_AUTH_DCE_INFO(B)).protect_level #define SA_BND_AUTH_AUTHN_SVC(B) \ (SA_BND_AUTH_DCE_INFO(B)).authn_svc #define SA_BND_AUTH_AUTHZ_SVC(B) \ (SA_BND_AUTH_DCE_INFO(B)).
OSF DCE Application Development Guide—Core Components 28.7.2 Macros to Access Schema Entry Fields In the following macro definitions, S is a pointer to sec_attr_schema_entry_t (and its equivalent dce_attr_sch data type) and I and J are nonnegative integers for array element selection.
The Extended Attribute API (SA_BND_TYPE((SA_TRG_BND_INFO_P(S)),I)) #define SA_TRG_BND_STRING_P(S,I) \ (SA_BND_STRING_P((SA_TRG_BND_INFO_P(S)),I)) #define SA_TRG_BND_SVRNAME_P(S,I) \ (SA_BND_SVRNAME_P((SA_TRG_BND_INFO_P(S)),I)) #define SA_TRG_BND_SVRNAME_SYNTAX(S,I) \ (SA_BND_SVRNAME_SYNTAX((SA_TRG_BND_INFO_P(S)),I)) #define SA_TRG_BND_SVRNAME_NAME_P(S,I) \ (SA_BND_SVRNAME_NAME_P((SA_TRG_BND_INFO_P(S)),I)) #define SA_TRG_BND_TWRSET_P(S,I) \ (SA_BND_TWRSET_P((SA_TRG_BND_INFO_P(S)),I)) #define SA_TRG_BND_TWRS
OSF DCE Application Development Guide—Core Components #define SA_ATTR_PRINTSTRING_P(S) \ (SA_ATTR_VALUE(S)).tagged_union.printstring #define SA_ATTR_STR_ARRAY_P(S) \ (SA_ATTR_VALUE(S)).tagged_union.string_array #define SA_ATTR_STR_ARRAY_NUM(S) #define SA_ATTR_STR_ARRAY_ELT_P(S,I) (SA_ATTR_STR_ARRAY_P(S))->num_strings (SA_ATTR_STR_ARRAY_P(S))->strings[I] #define SA_ATTR_BYTES_P(S) \ (SA_ATTR_VALUE(S)).tagged_union.
The Extended Attribute API (SA_BND_AUTH_SVR_PNAME_P(SA_ATTR_BND_INFO_P(S))) #define SA_ATTR_BND_AUTH_PROT_LEVEL(S) \ (SA_BND_AUTH_PROT_LEVEL(SA_ATTR_BND_INFO_P(S))) #define SA_ATTR_BND_AUTH_AUTHN_SVC(S) \ (SA_BND_AUTH_AUTHN_SVC(SA_ATTR_BND_INFO_P(S))) #define SA_ATTR_BND_AUTH_AUTHZ_SVC(S) \ (SA_BND_AUTH_AUTHZ_SVC(SA_ATTR_BND_INFO_P(S))) #define SA_ATTR_BND_NUM(S) \ (SA_BND_NUM(SA_ATTR_BND_INFO_P(S))) #define SA_ATTR_BND_ARRAY(S,I) \ (SA_BND_ARRAY((SA_ATTR_BND_INFO_P(S)),I)) #define SA_ATTR_BND_TYPE(S,I) \ (
OSF DCE Application Development Guide—Core Components (SA_BND_TWR_LEN((SA_ATTR_BND_INFO_P(S)),I,J)) #define SA_ATTR_BND_TWR_OCTETS(S,I,J) \ (SA_BND_TWR_OCTETS((SA_ATTR_BND_INFO_P(S)),I,J)) 28.7.4 Binding Data Structure Size Calculation Macros The following macros are supplied to calculate the size of data types that hold binding information. The macros work with the ERA API data types and their equivalent dce_attr_sch data types.
The Extended Attribute API (((N) - 1) * sizeof(sec_attr_acl_mgr_info_p_t)) ) 28.7.6 Attribute Instance Data Structure Size Calculation Macros The following macros are supplied to calculate the size of data types that hold attribute information. /* * SA_ATTR_STR_ARRAY_SIZE(N) - calculate the size required * for a sec_attr_enc_str_array_t with N sec_attr_enc_printstring_p_t-s.
OSF DCE Application Development Guide—Core Components #define SA_BND_AUTH_INFO_TYPE_VALID(B) ( \ (SA_BND_AUTH_INFO_TYPE(B)) == sec_attr_bind_auth_none || \ (SA_BND_AUTH_INFO_TYPE(B)) == sec_attr_bind_auth_dce ? true : false ) /* * SA_BND_AUTH_PROT_LEV_VALID(B) - evaluates to TRUE (1) * if the binding auth_info protect_level is valid; FALSE (0) otherwise. * B is a pointer to a sec_attr_bind_info_t.
The Extended Attribute API */ #define SA_BND_AUTH_AUTHZ_SVC_VALID(B) ( \ (SA_BND_AUTH_AUTHZ_SVC(B)) == rpc_c_authz_none || \ (SA_BND_AUTH_AUTHZ_SVC(B)) == rpc_c_authz_name || \ (SA_BND_AUTH_AUTHZ_SVC(B)) == rpc_c_authz_dce ? \ true : false ) 28.7.8 Schema Entry Semantic Check Macros The following macros are supplied to check the semantics of schema entry fields. In the macros, S is a pointer to sec_attr_schema_entry_t and its equivalent dce_attr_sch data type.
OSF DCE Application Development Guide—Core Components #define SA_ATTR_BND_AUTH_INFO_TYPE_VALID(S) \ (SA_BND_AUTH_INFO_TYPE_VALID(SA_ATTR_BND_INFO_P(S))) #define SA_ATTR_BND_AUTH_PROT_LEV_VALID(S) \ (SA_BND_AUTH_PROT_LEV_VALID(SA_ATTR_BND_INFO_P(S))) #define SA_ATTR_BND_AUTH_AUTHN_SVC_VALID(S) \ (SA_BND_AUTH_AUTHN_SVC_VALID(SA_ATTR_BND_INFO_P(S))) #define SA_ATTR_BND_AUTH_AUTHZ_SVC_VALID(S) \ (SA_BND_AUTH_AUTHZ_SVC_VALID(SA_ATTR_BND_INFO_P(S)) #define SA_SCH_FLAG_IS_SET(S,F) \ (((S)->schema_entry_flags & (F)
The Extended Attribute API /* * Macros to set the flags.
OSF DCE Application Development Guide—Core Components #define SA_SCH_TRIG_FLAG_IS_SET(S,F) \ (((S)->trig_types & (F)) == (F)) #define SA_SCH_TRIG_FLAG_IS_NONE(S) \ (SA_SCH_TRIG_FLAG_IS_SET((S),sec_attr_trig_type_none)) #define SA_SCH_TRIG_FLAG_IS_QUERY(S) \ (SA_SCH_TRIG_FLAG_IS_SET((S),sec_attr_trig_type_query)) #define SA_SCH_TRIG_FLAG_IS_UPDATE(S) \ (SA_SCH_FLAG_IS_SET((S),sec_attr_trig_type_update)) 28.
Chapter 29. The Login API The login API communicates with the security server to establish, and possibly change, a principal’s login context. A login context contains the information necessary for a principal to qualify for (although not necessarily be granted) access to network services and possibly local resources as well.
OSF DCE Application Development Guide—Core Components c. 3. The runtime decrypts the message containing the PTGT and returns information about the source of the authentication information to the API. (If the authentication information comes from the network security server, then the login context is validated.) Finally, the client invokes sec_login_set_context(), which enables child processes spawned from the calling process to inherit the validated context.
The Login API uncertified context issue a warning. 29.1.2 Validating the Login Context Without Certifying the Security Server An application that does not use login contexts to set local identity information does not need to certify its login contexts. Since an illegitimate security server is unlikely to know the key of a remote server principal with which the application may communicate, the application will simply be refused the service requested from the remote server principal.
OSF DCE Application Development Guide—Core Components { sec_login_purge_context(login_context) ...application login-failure actions... } ...application-specific login-valid actions... } } 29.2 Context Inheritance A process inherits the login context of its parent process unless the child process is associated with a principal that has logged in and so established a separate login context.
The Login API 29.3 Handling Expired Certificates of Identity For a dishonest principal to make use of an intercepted certificate of identity, it must succeed in decrypting it. In order to make the task of decryption more difficult, a certificate of identity has a limited lifespan; and, once it expires, the associated login context is no longer valid. Because this security feature may inconvenience users, an application may wish to warn a user when the certificate of identity is about to expire.
OSF DCE Application Development Guide—Core Components 29.4 Importing and Exporting Contexts Under some circumstances, an application may need two processes to run using the same login context. A process may acquire its login context in a form suitable for imparting to another process by calling sec_login_export_context(). This call collects the login context from the local context cache and loads it into a buffer.
The Login API sec_login_get_current_context(&login_context,&st); sec_login_inquire_net_info(login_context,&net_info,&st); for (i=0; i < num_groups; i++) { ... query whether user wants to discard any current group memberships. Copy new group set to new_groups array ... } if (!sec_login_newgroups(login_context,sec_login_no_flags, num_new_groups, new_groups, &restricted_context,&st)) { if (st == sec_login_s_groupset_invalid) printf("Newgroupsetinvalid\n"); ...application-specific error handling...
OSF DCE Application Development Guide—Core Components structure. 29.6.3 Getting Password and Group Information for Local Process Identities Two calls, sec_login_get_pwent() and sec_login_get_groups(), are useful for setting the local identity of a process. These routines return password or group information from the network registry, if that service is available, or from the local files of password and group information, if the network service is unavailable. 29.6.
Chapter 30. The Key Management API Every principal has an entry in the registry database that specifies a secret key. In the case of an interactive principal (that is, a user), the secret key is derived from the principal’s password. Just as users need to keep their passwords secure by memorizing them (rather than writing them down, for example), a noninteractive principal also needs to be able to store and retrieve its secret key in a secure manner.
OSF DCE Application Development Guide—Core Components When there are valid tickets that are encoded with different key versions, an application may need to retrieve more than one key version. In that case, the application may call sec_key_mgmt_initialize_cursor( ) to set a cursor in the local storage to the first suitable entry corresponding to the named principal and key type, and then call sec_key_mgmt_get_next_key() to get all versions of that key in storage.
The Key Management API principal. (The key version specified in this routine must not be 0 [zero].) The replicas should notify the master when they have completed setting their local stores to the new key. 4. Cause the master to call sec_key_mgmt_change_key( ) (here again, the key version must not be 0) after all replicas have set the new key locally, thereby updating both the master’s local storage and the registry database entry.
OSF DCE Application Development Guide—Core Components principal. Two routines delete a principal’s key: • The sec_key_mgmt_delete_key( ) routine removes all key types having the specified key version identifier from the local key storage, thus invalidating all extant tickets encoded with that key. • The sec_key_mgmt_delete_key_type( ) routine removes only a specified version of a specified key type.
Chapter 31. The Access Control List APIs As a rule, DCE Security Service interfaces are local client-side APIs only. The access control list (ACL) facility includes this kind of interface, and some others as well, as follows: • The DCE client ACL interface, sec_acl_*(), is a local interface that calls a clientside implementation of the ACL network interface. It enables clients to browse or edit DCE ACLs.
OSF DCE Application Development Guide—Core Components Figure 31-1. ACL Program Interfaces Client Server Resolver Code Application Code DCE Library IDL generated code IDL generated code sec_acl_xxx() ACL Library Application Code DCE Library Backing Store Library Cell Directory Service ACL Store 31.1 The Client-Side API The client-side API is a local interface consisting of a set of routines that are prefixed sec_acl.
The Access Control List APIs identified by the ACL handle in combination with the manager type that manages it. ACL editing calls must also specify the ACL type to be read or otherwise manipulated (the object, default container, or default Object ACL types). An application calls sec_acl_bind( ) to get an ACL handle. The handle itself is opaque to the calling program, which needs none of the information encoded in it to use the ACL interface.
OSF DCE Application Development Guide—Core Components An ACL can occupy a substantial amount of memory. The memory management routine, sec_acl_release(), frees the memory occupied by an ACL, and returns it to the pool. This is implemented strictly as a local operation. 31.1.3 Errors Although the ACL API saves errors received from the DCE RPC runtime (or other APIs) in ACL handle data, it returns an error describing the ACL operation that failed as a result of the RPC error.
The Access Control List APIs 31.3 Extended Naming of Protected Objects The DCE ACL model supports extended naming so that ACL managers can separately protect objects that are not registered in the cell namespace. This provides an alternative to registering all the server’s objects with CDS. The server alone is registered, and it contains code to identify its own objects by name.
OSF DCE Application Development Guide—Core Components 31.3.1 The ACL Network Interface The ACL network interface, rdacl_*(), provides a DCE-common interface to ACL managers. It is the interface exported by the default DCE ACL managers to the default DCE ACL client (that is, the dcecp tool), and any other client based on the client API. The client API, sec_acl_*( ), is a local interface that calls a client-side implementation of the ACL network interface.
The Access Control List APIs 31.3.2 The ACL Library The ACL library provides an implementation of the ACL manager interface and the ACL network interface for the convenience of programmers who are writing ACL managers for DCE servers. The ACL library meets the following needs: • It provides stable storage for ACLs. • It implements the rdacl_*() interface, including support for multiple object types, initial default Object ACLs, and initial default Container ACLs.
OSF DCE Application Development Guide—Core Components with this part: — dce_acl_resolve_by_name( ) Finds an ACL’s UUID, given an object’s name. — dce_acl_resolve_by_uuid() Finds an ACL’s UUID, given an object’s UUID. 31.3.2.2.1 Initialization Routines An ACL manager must first define the types of the objects it manages. For example, a simple directory service would have directories and entries, and each type of object would have a different ACL manager.
The Access Control List APIs • dce_acl_inq_acl_from_header( ) Retrieves the UUID of an ACL from the header of an object in the backing store. • dce_acl_inq_prin_and_group( ) Inquires the principal and the group of an RPC caller. 31.3.2.2.3 Creating ACL Objects The following convenience functions may be used by an application programmer to create ACL objects in other servers or clients. • dce_acl_copy_acl( ) Copies an ACL. • dce_acl_obj_init( ) Initializes an ACL for an object.
OSF DCE Application Development Guide—Core Components The operations in the rdacl_*() interface share an initial set of parameters that specify the ACL object being operated upon: handle_t sec_acl_component_name_t uuid_t sec_acl_type_t h component_name *manager_type sec_acl_type The sec_acl_type parameter indicates whether a protection ACL, an initial default Object ACL, or an initial default Container ACL is desired.
The Access Control List APIs The following two examples illustrate the general structure of the dce_acl_resolve_by_uuid( ) API and dce_acl_resolve_by_name( ) API that are supplied in the ACL library. They may be used as paradigms for creating additional resolver routines. The first example shows dce_acl_resolve_by_name( ). A server has several objects and stores each in a backing store database. Part of the standard header for each object is a structure that contains the UUID of the ACL for that object.
OSF DCE Application Development Guide—Core Components #define STAT_CHECK_RET(st) { if (st != error_status_ok) return; } dce_acl_resolve_func_t dce_acl_resolve_by_uuid( /* in */ handle_t h, sec_acl_component_name_t component_name, sec_acl_type_t sec_acl_type, uuid_t *manager_type, boolean32 writing, void *resolver_arg, /* out */ uuid_t *acl_uuid, error_status_t *st ) { dce_db_handle_t db_h; dce_db_header_t dbh; uuid_t obj; /* Get the object.
The Access Control List APIs The next example shows dce_acl_resolve_by_name(). A server uses the residual name to resolve an ACL object by using dce_acl_resolve_by_name( ). This routine requires a DCE database that maps names into ACL UUIDs. This backing store database must be maintained by the server application so that created objects always get a name, and that name must be a key into a database that stores the UUID identifying the object.
Chapter 32. The ID Map API In the multicell environment, the global print string representation of a principal identity can be ambiguous, even though every principal and its native cell have unique names in the form of UUIDs to which the print string representations normally resolve. For example, all ACLs maintain UUIDs as the definitive representations of principal and cell names. The acl_edit tool, on the other hand, takes as input (and also outputs) this same information as print strings.
Chapter 33. DCE Audit Service Audit plays a critical role in distributed systems. Adequate audit facilities are necessary for detecting and recording critical events in distributed applications. Audit, a key component of DCE, is provided by the DCE Audit Service. This chapter provides an introduction to the DCE Audit Service. 33.1 Features of the DCE Audit Service The DCE Audit Service has the following features: • An audit daemon performs the logging of audit records based on specified criteria.
OSF DCE Application Development Guide—Core Components Other APIs are also provided which can be used to create tools that examine and analyze the audit event records. • audit daemon Maintains the filters and the audit logs. • audit management interface Management interface to the audit daemon. Used by the administrator to specify how the audit daemon will filter the recording of audit events. This interface is available from the DCE control program. 33.
DCE Audit Service 33.3.3 Events An audit event is any event that an audit client wishes to record. Generally, audit events involve the integrity of the system. For example, when a client withdraws cash from his bank account, this can be an audit event. An audit event is associated with a code point in the application server code. The terms audit event, event, and auditable event are used interchangeably in this book. 33.3.3.
OSF DCE Application Development Guide—Core Components Format D is not administered by OSF and can be used freely within the cell. These event numbers may not be unique across cells and should not be used by application servers that are installed in more than one cell. Format E is reserved for future use. The event number formats are illustrated in Figure 33-1. Figure 33-1.
DCE Audit Service #define #define #define #define #define evt_vn_bank_server_acct_open evt_vn_bank_server_acct_close evt_vn_bank_server_acct_withdraw evt_vn_bank_server_acct_deposit evt_vn_bank_server_acct_transfer 0x01000000 0x01000001 0x01000002 0x01000003 0x01000004 33.3.3.5 Administration of Event Numbers Organizations and vendors must administer the event numbers assigned to them (through the set-id) to maintain the unique assignment of event numbers. 33.3.
OSF DCE Application Development Guide—Core Components • What events will be audited? • What should be the outcome of these events before an audit record is written? • Will the audit record be logged in the audit trail file or displayed on the system console, or both? For example, for the bank server program, you can impose the following conditions before an audit record is written: ‘‘Audit all withdrawal transactions (the audit events) that fail because of access denial (outcome of the event) that are
DCE Audit Service 33.3.8 Audit Trail File The audit trail file contains all the audit records that are written by the audit daemon or the audit APIs. You can specify either a central audit trail file or a local audit trail file. The central audit trail file is maintained by the audit daemon. The local audit trail file is maintained by the audit library. The terms audit trail file and audit trail are used interchangeably in this book. 33.
OSF DCE Application Development Guide—Core Components #define evt_vn_bank_server_acct_close 0xC1000001 /* event number for the 3rd code point, acct_withdraw() */ #define evt_vn_bank_server_acct_withdraw 0xC1000002 /* event number for the 4th code point, acct_deposit() */ #define evt_vn_bank_server_acct_deposit 0xC1000003 /* event number for the 5th code point, acct_transfer() */ #define evt_vn_bank_server_acct_transfer 0xC1000004 3.
DCE Audit Service dce_aud_commit(at,ard,options,format,&outcome,&status); acct_close() /* second code point */ /* Uses the event number for acct_close(), * evt_vn_bank_server_acct_close */ dce_aud_start(evt_vn_bank_server_acct_close, binding,options,outcome,&ard, &status); if (ard) /* If events need to be logged */ dce_aud_put_ev_info(ard,info,&status); if (ard) /* If events need to be logged */ dce_aud_commit(at,ard,options,format,&outcome,&status); 5.
OSF DCE Application Development Guide—Core Components b. Write an audit record only if an operation in that event class failed because of access denial. c. If the first condition is fulfilled, write the audit record in an audit trail file only. The filter for all other users has the following filter guides: a. Audit the events in both event classes, subject to the next condition. b. Write an audit record if an operation in that event class succeeded or failed. c.
DCE Audit Service The audit clients are the users of the filter information. Using the audit APIs, the audit client reads the information on filters and event class configuration. The audit client reads these files only once, unless an update notification is received from the audit daemon (which is triggered by an update initiated by an administrator using the DCE control program).
Chapter 34. Using the Audit API Functions This chapter describes the use of the audit API functions to add audit capability to distributed applications and to write audit trail analysis and examination tools. 34.1 Adding Audit Capability to Distributed Applications To record audit events in an audit trail file, the DCE audit API functions must be called in the distributed application to perform the following: 1. Open the audit trail file during the startup of the application. 2.
OSF DCE Application Development Guide—Core Components 34.1.1 Opening the Audit Trail To open the audit trail file, the main routine of the application server uses the dce_aud_open() function. With this function call, the audit trail file can be • opened for reading or for writing. • directed to the default audit trail file or to a specific file.
Using the Audit API Functions • dce_aud_start_with_uuid( ) For use by RPC-based applications that know their client’s identity in UUID form. The dce_aud_start_*() functions determine if a specified event must be audited based on the subject identity and event outcome that were defined for that event by the filters. If the event specifics match the event filters (that is, the event has to be audited), these functions return a pointer to an audit record buffer.
OSF DCE Application Development Guide—Core Components You can opt not to use the dce_aud_put_ev_info( ) function if the information provided by the audit record header is already sufficient for your auditing purposes. If you elect to use this function, it can be called one or more times, the order of which is preserved in the audit record.
Using the Audit API Functions The audit_trail parameter is the trail descriptor returned in the dce_aud_open() call made earlier. The ard parameter is the audit record descriptor returned in the dce_aud_start( ) call (and used in the dce_aud_put_ev_info() function call). The format parameter specifies a format version number of the event-specific information. The initial version number should be zero, and be incremented when the format changes.
OSF DCE Application Development Guide—Core Components These functions and the APIs that are used for each are discussed in the following sections. 34.2.1 Opening an Audit Trail File for Reading To open the audit trail file for reading, use the dce_aud_open( ) function and specify aud_c_trl_open_read as the value for the flags parameter. In this case, the values for the first_evt_number and num_of_evts does not affect the call.
Using the Audit API Functions FORMAT The format version number of the audit event record Details of these attributes, their values, and the allowable operators are discussed in the OSF DCE Application Development Reference. For example, to have the function retrieve audit records that pertain to the event number 0xC01000001 only, you can set the predicate to the following: EVENT=0xC01000001 If the predicate parameter is set to NULL (that is, no criteria), the next audit record is read.
OSF DCE Application Development Guide—Core Components 34.2.4 Discarding the Audit Record The dce_aud_discard( ) function frees the memory allocated to the binary version of the audit record, that is, the structure returned by the dce_aud_next() function. The dce_aud_discard( ) function does not free the structures allocated by dce_aud_print(), dce_aud_get_header( ),or dce_aud_get_ev_info(). 34.2.
Chapter 35. The Password Management API User passwords are the weakest link in the chain of DCE security. Users, unless their choices are restricted, typically choose passwords that are easy for them to remember; unfortunately, these memorable passwords are also easy for attackers to ‘‘crack.’’ The password management facility is intended to reduce this risk by providing the tools necessary to develop customized password management servers, and to call them from client password change programs.
OSF DCE Application Development Guide—Core Components Security Client . . . RPC (Enforcepassword validation policy in password change/add program...) sec_pwd_mgmt...() showgrestorepsbpse242 155 :M(rs_pwd_mgmt_setup )S244 155 :Mpsbpsegsave360 rotate() sec_rgy_acct_passwd . rs_acct_passwd . RPC RPC Security Server rsec_pwd_mgmt_ rsec_pwd_mgmt_ gen_pwd( ) str_chk( ) Password Management Server For information on how to administer password generation and strength-checking, see the . 35.
The Password Management API 2. The client calls sec_pwd_mgmt_get_val_type( ), specifying the handle returned by sec_pwd_mgmt_setup( ) in step 1. The value of the principal’s pwd_val_type ERA is extracted from the handle and returned to the client. 3. The client analyzes the principal’s pwd_val_type ERA to determine whether a generated password is required. If so, it calls sec_pwd_mgmt_gen_pwd(), specifying the number of passwords needed, and the handle returned by sec_pwd_mgmt_setup.
OSF DCE Application Development Guide—Core Components sec_pwd_mgmt_free_handle(&pwd_mgmt_h, &st); 35.2 The Password Management Network Interface The password management interface, rsec_pwd_mgmt_*( ), provides a DCE-common interface to password management servers. It is the interface exported by the sample password management server provided with DCE Version 1.1 (pwd_strengthd), and it is the interface that application developers should use to write their own password management servers.
Index _____________________________ A ACCEPT credential type creating, 25-3 defined, 25-1 accounts, registry database, 27-5 ACF, 16-6, 18-1 See also Attribute Configuration Language attribute list, 18-2 body, 18-4 compiling, 18-2 features, 18-2 file extension, 18-2 grammar synopsis, 18-30 header, 18-3 naming, 18-2 structure, 18-3 table of attributes, 18-29 ACL, 14-11, 24-2, 24-3 access checking, 24-7 to 24-11 contents, 24-3 definition, 24-1 editor, 31-2 entries, 24-4 to 24-7 errors, 31-4 extended naming, 3
OSF DCE Application Development Guide—Core Components min_is, 17-36 size_is, 17-37 bounds, 17-33 conformant, 17-33 conformant and varying, 17-33 fixed, 17-33 open, 17-33 rules for, 17-40 varying, 17-33 array_attribute attribute, 17-25 array_declarator, 17-33 ASCII text strings, binary timestamps translated to, 19-2 asynchronous cancelability, 7-13 asynchronous signals, 8-6 at-most-once semantics, 12-12 attribute code sets, 15-17 instance access control, 28-5 defined, 28-2 schema, defined, 28-1 type access c
Index opening audit trail file for reading, 34-6 reading audit records into a buffer, 34-6 specifying amount of header information, 34-3 transforming audit records into text, 34-7 clients, 33-2 code point, 33-2 data type, 34-4 event, 33-3 event class, 33-5 event class number, 33-5 event name, 33-3 event number, 33-3 event-id, 33-3 format, 33-3 set-id, 33-3 record criteria for selection, 34-6 predicates, 34-6 structure, 33-6 service, 33-1 components, 33-1 concepts, 33-2 features, 33-1 trail file, 33-7 life c
OSF DCE Application Development Guide—Core Components B backing store closing, 5-6 creating a new, 5-6 deleting items from, 5-8 iterating through, 5-8 library, 5-1 locking, 5-9 opening an existing, 5-6 retrieving data from, 5-7 storing data into, 5-7 traversing the keys of, 5-8 backing store API dce_db_close(),5-6 dce_db_delete( ),5-8 dce_db_delete_by_name(), 5-9 dce_db_delete_by_uuid( ), 5-9 dce_db_fetch(),5-7 dce_db_fetch_by_name( ), 5-7 dce_db_fetch_by_uuid( ), 5-7 dce_db_inq_count( ), 5-8 dce_db_iter_d
Index CATCH_ALL statement, 9-1, 9-7, 9-8 CDS, and security namespace, 22-11 cell and security, 23-3 name, RPC, 14-16 profile, RPC, 14-38 root, RPC, 14-16 RPC, 14-16 cell-relative name, RPC, 14-17 certificate of identity, 29-5 See also ticket-granting ticket character set, 15-2 compatibility evaluation, 15-5, 15-23 evaluation, 15-27 interoperability, 15-1 local, 15-4 characters, 17-14, 17-22 client, 18-1 and server components, 20-1 application thread, RPC, 14-2 authentication information, RPC, 14-1 binding h
OSF DCE Application Development Guide—Core Components programming language, 11-8 compilers generating nonreentrant code, 8-11 generating reentrant code, 8-11 compiling, ACF, 18-2 complex types, 17-65 concurrency control, RPC, 14-6 condition variable, 7-9 to 7-11 attributes, 7-7 diagram of, 7-10 figure of, 7-11 signaling, 8-13 configuring a new server remotely, 2-19 conformance in dimensions other than the first, 17-34 code example, 17-34, 17-35 conformant and varying array, 17-33 conformant array, 17-33 con
Index 18-24, 18-29 cs_rtag attribute, 15-10, 18-5, 18-24, 18-29 cs_stag attribute, 15-10, 18-5, 18-24, 18-29 cs_tag_rtn attribute, 15-10, 15-14, 18-4, 18-25, 18-29 customized handles, 17-58 D data encryption mechanisms, 23-5 thread-specific, 7-12 Data Encryption Standard. See DES DCE authorization protocol, 24-1 host daemon (dced), 2-2 host services, 2-1 Threads Exceptions, table of, 9-8 Threads signal handling, 8-7 XPG4 routines, 3-9 dce/utc.
OSF DCE Application Development Guide—Core Components dynamic buffer encoding, 16-47 dynamic endpoint, 12-11 E editor, ACL, 31-2 enable_allocate attribute, 18-4, 18-15, 18-29 enabling memory, 17-49 enabling services of a server, 2-23 encapsulated unions, 17-26 encode attribute, 18-3, 18-4, 18-18, 18-29 encoding and decoding of data, 5-4 encryption mechanisms, 23-5 endpoint attribute, 17-6, 17-9 map, 16-36 mapper service, 2-1, 2-3 register operation, 13-8, 14-41 role of within server address, 12-4 unregiste
Index F failures, 16-6, 18-5 See also status attributes, 18-4 fault_status attribute, 11-25, 18-4, 18-9, 18-29 FIFO (First in, First out) scheduling, 7-5 file extension, ACF, 18-2 IDL, 20-2 name, ACF, 18-2 reading/writing with jacket routines, 8-2 filter, 33-5 subject identity, 33-6 FINALLY statement, 9-3, 9-7, 9-8 first_is attribute, 17-6, 17-39, 17-48 fixed array, 17-33 fixed buffer encoding, 16-47 float type, 17-22 floating-point numbers, 17-22 fork( ), calling, 8-4 freeing backing store memory, 5-7 fre
OSF DCE Application Development Guide—Core Components fixed, 17-33 open, 17-33 varying, 17-33 array attributes, 17-25 attributes, 17-5 to 17-65 basic data types, 17-21 boolean type, 17-22 byte type, 17-22 case sensitivity, 17-4 comments, 17-4 const declaration, 17-13 constant declarations, 17-13 constructed type specifiers, 17-17 constructed types, 17-24 customized handles, 17-58 data types, 17-4 declarations, 17-4 encoding services, 5-4 encoding services handles, 16-48 enumerations, 17-29 file, 20-2 gramma
Index header, 17-5 exception-returning. See exception-returning interface handle, RPC use of, 13-8 header, 18-3 interface See also RPC password management facility, 22-10 registry database, 27-3 RPC identifier, 14-20 RPC specification, 13-6 RPC UUIDs, 11-10 security server, 22-6 security services and facilities, 22-7 to 22-10 UNIX security, 22-10 UUID, 11-12 RPC definition of, 11-10 RPC use of, 12-6 Interface Definition Language.
OSF DCE Application Development Guide—Core Components M major version number, 12-4, 12-6 making backing store headers, 5-8 manager, RPC, 12-14 manager interface, ACL, 31-5 managing several objects, 5-1 mapping string-to-UUID, 32-1 marshalling, RPC, 11-5 masks, ACL entry types, 24-6 max_is attribute, 17-6, 17-37 maybe attribute, 17-6, 17-18, 17-19 maybe semantics, 12-12 memory advanced management support, 17-50 allocating, 16-1, 17-49, 18-15 disabling, 17-49 enabling, 17-49 freeing, 16-1, 17-49, 18-15 heap
Index nil UUID, RPC, 12-6 nocode attribute, 18-3, 18-12, 18-29 nonencapsulated union, 17-28 code example, 17-29 nonreentrant code, 8-11 nonreentrant software, 6-4, 8-10, 8-11 using global lock to avoid, 8-10 nonterminating signals, 8-6 nonthreaded libraries, 8-9 NSI attribute, 14-25 code sets, 15-17 attributes, 14-28 RPC, 14-14 binding attribute, 14-14 CDS ACL permissions, 13-9 directory service entries, 14-14 profile, 14-14 server entry, 14-14 directory service handle, 14-25 directory service names, 14-23
OSF DCE Application Development Guide—Core Components sec_pwd_mgmt_setup( ), 35-2 sec_rgy_acct_passwd(), 35-3 path, for NSI searches, 14-22 PCS, 15-2 per-message security, 23-4 pickling of data, 5-4 pipelining software model, 6-3 pipes, 17-29 to 17-32 out, 16-30 pointer levels, 17-46 pointers, 17-42 to 17-48, 17-59 array attributes on, 17-47 in function results, 17-47 opaque, 17-59 pointer_default attribute, 17-6, 17-11, 17-42, 17-47 port, 17-9 Portable Character Set (PCS), 15-2 POSIX sigaction service, 8-8
Index namespace, 15-5 registry, 27-1, 27-2, 27-6 database, 23-2 database accounts, 27-5 database calls and interfaces, 27-3 extending, 28-1 server, 27-1 service, 14-8 See also security server relative time, 19-3, 19-4 remote control of servers, 2-17 management of endpoints, 2-2 of objects, 2-2 of servers, 2-2 of services, 2-2 serviceability interface, 4-39 remote procedure call, 11-1 See also RPC represent_as attribute, 18-4, 18-5, 18-13, 18-29 request buffer, 16-40 RERAISE statement, 9-2 resource model, 14
OSF DCE Application Development Guide—Core Components contexts, and delegation, 25-4 DTS dependencies, 22-11 for peer-to-peer applications, 22-2 risks, 22-2 server, 22-6 and cells, 23-3 interfaces, 22-6 service namespaces, 22-11 RPC principal names, 14-24 services and authenticated RPC, 22-3 services and GSSAPI, 22-3 UNIX versus DCE, 22-2 validation service, 2-1, 2-24 sending and receiving messages on sockets, 8-2 server, 11-1, 18-1 application thread, 14-2 binding handle, 12-5 binding information, 12-5 con
Index mutual authentication, 23-26 swapping client memory, 17-50 switch_is attribute, 17-20, 17-25 synchronization methods, 7-12 synchronization objects, 7-9, 8-12 mutex, 7-7 race conditions, 8-12 synchronous programming techniques, 8-9 synchronous signals, 8-6 system exceptions, 16-7 system profile, 14-38 T tag-setting routine, 15-14 ACF attribute, 15-10 TDF, 19-2 terminating, threads, 7-2, 8-7 terminating signals, 8-6 TGT.
OSF DCE Application Development Guide—Core Components U W undefining jackets, 8-3 unexport operation, 13-2 union, nonencapsulated, 17-28 union type, 17-26 unions, 17-26 unique attribute, 17-16 to 17-20, 17-25, 17-42 unique pointers, 17-44 example, 17-46 universal code set, 15-16, 15-27 universal unique identifier, 11-10 UNIX security interfaces, 22-10 services, 8-1 to 8-2 signals, 8-5 to 8-9 installing signal handlers for, 8-7 UNIX signals, table of, 8-7 unmarshalling, RPC, 11-5 unsigned integer types, 1