background image

eSNMP API Routines
str2oid

str2oid

Converts a null-terminated string

OID

in dot notation to an

OID

structure. The

str2oid

routine does not allocate an

OID

structure.

Format

oid *str2oid ( oid *oid,

char *);

Arguments

oid

The value to be inserted as data into the VARBIND structure. For more

information about OID length and values, see Chapter 3.

s

A null string or empty string returns an OID structure that has one element of
zero.

Description

The routine dynamically allocates the buffer and inserts its pointer into the

OID

structure passed in the call. The caller must explicitly free this buffer. The

OID

can have a maximum of 128 elements.

Return Values

null

An error occurred. Otherwise, the pointer to the

OID

structure (its first argument) is returned.

Example

include <esnmp.h>
OID abc;
if (stroid (&abc, "1.2.5.4.3.6") == NULL

DPRINTF((WARNING, "It did not work...\n");

5–38 eSNMP API Routines

Summary of Contents for Compaq TCP/IP Services for OpenVMS

Page 1: ...Update Information This manual supersedes the DIGITAL TCP IP Services for OpenVMS eSNMP Programming and Reference Version 5 0 Software Version Compaq TCP IP Services for OpenVMS Version 5 1 Operating...

Page 2: ...uter Software Computer Software Documentation and Technical Data for Commercial Items are licensed to the U S Government under vendor s standard commercial license Compaq shall not be liable for techn...

Page 3: ...of MIB II 2 5 2 2 1 MIB II Implemented Groups 2 6 2 2 2 Restrictions to MIB II Implementation 2 6 3 Creating a Subagent Using the eSNMP API 3 1 Creating a MIB Specification 3 1 3 2 The Structure of Ma...

Page 4: ...n SNMP Trap Service 4 12 4 2 2 3 Trap Receiver Examples 4 13 5 eSNMP API Routines 5 1 Interface Routines 5 1 esnmp_init 5 2 esnmp_register 5 3 esnmp_unregister 5 6 esnmp_register2 5 7 esnmp_unregister...

Page 5: ...2 Modifying the Subagent Timeout 6 1 6 3 Log Files 6 2 Index Figures 1 1 SNMP Architecture 1 2 1 2 eSNMP Data Flow 1 3 3 1 MIB II in SMI Tree Structure 3 3 Tables 1 TCP IP Services Documentation viii...

Page 6: ......

Page 7: ...ut installing configuring and starting this product Intended Audience This manual is for experienced OpenVMS and UNIX system managers and assumes a working knowledge of TCP IP networking TCP IP termin...

Page 8: ...TCP IP Services layered application product DIGITAL TCP IP Services for OpenVMS User s Guide This manual describes how to use the applications available with TCP IP Services such as remote file opera...

Page 9: ...ction of the different IPv6 addresses and how to configure TCP IP Services to access the 6bone network For additional information about Compaq OpenVMS products and services access the Compaq website a...

Page 10: ...icate that you must enclose choices in parentheses if you specify more than one In command format descriptions brackets indicate optional choices You can choose one or more items or no items Do not ty...

Page 11: ...g elements keywords the names of independently compiled external functions and files syntax summaries and references to variables or identifiers introduced in an example A hyphen at the end of a comma...

Page 12: ......

Page 13: ...ng interface API tools used to build additional subagents startup and shutdown procedures and text based configuration files This chapter provides an overview of the Compaq implementation of eSNMP Top...

Page 14: ...ese MIBs are described in Chapter 2 The SNMP ASN 1 library used by the master agent to interpret ASN 1 messages The eSNMP API the application programming interface that provides routines for programmi...

Page 15: ...e The process of communication for a request is illustrated with dashed lines and includes the following steps 1 The network management station NMS sometimes called the client originates SNMP requests...

Page 16: ...master agent using the port that was assigned when the subagent registered the MIB When they are idle subagents periodically send a message to port 705 to ensure that the master agent is still runnin...

Page 17: ...mand procedure that stops the master agent and subagents TCPIP SNMP_SYSHUTDOWN COM SYS STARTUP Command procedure initiated by TCPIP SNMP_ SHUTDOWN COM Provided for site specific customization such as...

Page 18: ...C and H Source code for chess example Contains detailed documentation that explains how the code functions TCPIP CHESS_SUBAGENT EXE Functioning chess example image TCPIP ESNMP OLB Object library file...

Page 19: ...owing utilities TCPIP SNMP_REQUEST EXE a MIB browser that allows you to retrieve and update objects from the MIBs TCPIP SNMP_TRPSND EXE a trap sender that generates traps messages that require no resp...

Page 20: ...o be recompiled The circumstances under which recoding or recompiling are required are described in Section 1 7 1 1 7 1 Using Existing SNMP Version 1 MIB Modules Existing SNMP Version 1 MIB subagent e...

Page 21: ...I without the need to relink Some images linked against the current version of TCP IP Services may run under Versions 4 1 and 4 2 but this backward compatibility is not supported and may not work in f...

Page 22: ......

Page 23: ...ides a general RFC description and a specific OpenVMS description for each implemented object Table 2 1 Host Resources MIB Objects Object Name RFC Description OpenVMS Description hrSystemUptime The am...

Page 24: ...The total number of blocks on a device displayed by the SHOW DEVICE FULL command hrStorageUsed The allocated amount of storage in this entry in hrStorageAllocationUnits The total number of used blocks...

Page 25: ...locks displayed by the SHOW DEVICE FULL command hrSWRunIndex A unique value for each software product running on the host Process ID hrSWRunPath A description of the location where this software was l...

Page 26: ...rminal device begins with _FT Data items in the hrDeviceTable group have the following restrictions hrDeviceID is always null OID 0 0 hrDeviceErrors is coded as follows Code Condition warning 3 Error...

Page 27: ...tead hexadecimal value 00 00 01 01 00 00 00 00 January 1 0000 applies hrProcessorFrwID OID prefix 1 3 6 1 2 1 25 3 3 1 1 is not implemented on OpenVMS VAX On this type of system it returns standard nu...

Page 28: ...ansmission group 2 2 2 Restrictions to MIB II Implementation SNMP requests are not implemented for the following MIB II objects ipRouteMetric1 ipRouteMetric5 tcpMaxConn SNMP set requests are not imple...

Page 29: ...refix 1 3 6 1 2 1 1 9 1 2 that may show different sysORUpTime 1 3 6 1 2 1 1 9 1 4 The snmp_request program translates the value received in hundredths of a second to the following dropping any fractio...

Page 30: ......

Page 31: ...at the network manager needs to examine and manipulate Each resource that a MIB manages is represented by an object After gathering the data the developer uses Abstract Syntax Notation 1 ASN 1 to spec...

Page 32: ...d the OID naming structure used in SNMP If not refer to RFC 1902 Structure of Management Information for Version 2 of the Simple Network Management Protocol SNMP Version 2 The information in SNMP is s...

Page 33: ...mation Figure 3 1 MIB II in SMI Tree Structure VM 0721A AI iso 1 org 3 dod 6 internet 1 directory 1 mgmt 2 mib2 1 system 1 interfaces 2 at 3 ip 4 icmp 5 tcp 6 udp 7 egp 8 transmission 10 snmp 11 exper...

Page 34: ...eByWhite 1 3 6 1 4 1 36 2 15 2 99 5 1 2 moveByBlack 1 3 6 1 4 1 36 2 15 2 99 5 1 3 moveStatus 1 3 6 1 4 1 36 2 15 2 99 5 1 4 chessTraps 1 3 6 1 4 1 36 2 15 2 99 6 moveTrap 1 3 6 1 4 1 36 2 15 2 99 6 1...

Page 35: ...l Organization for Standardization ISO Instead of creating ASN 1 files yourself you can create MY files from existing ASCII files for example from RFCs by using the MIB converter facility provided wit...

Page 36: ...s example files using the PRINT_TREE qualifier MIBCOMP RFC1442 MY CHESS_MIB MY chess PRINT_TREE Processing RFC1442 MY Processing CHESS_MIB MY Dump of objects in lexical order This file created by prog...

Page 37: ...ed on OpenVMS for compatibility with UNIX developed procedures For information about using these utilities refer to the Compaq Tru64 UNIX Network Programmer s Guide 3 3 2 2 Object Tables The MIBCOMP c...

Page 38: ...Enumeration Definitions Section The third section of the subtree_TBL H file contains enumeration definitions for those integer MIB variables that are defined with enumerated values as follows define D...

Page 39: ...lized in the subtree_TBL C module You must write method routines for each prototype that is defined as follows extern int mib group get METHOD method extern int mib group set METHOD method For example...

Page 40: ...access object tables or MIB variables directly It only maintains a registry of subtrees When a request for a particular MIB variable arrives it is processed as shown in the following steps where the M...

Page 41: ...ointer to the array of objects in the object table It is indexed by the I_xxxx definitions found in the subtree_TBL H file object_oid objects The index of the last object in the object_TBL file This i...

Page 42: ...IBRARY TCPIP LIB OLB LIBRARY Alternatively you can link your subagent with the eSNMP API shareable image TCPIP ESNMP_SHR EXE The resulting executable image is smaller and can be run without relinking...

Page 43: ...Include symbols for the detached processes that are running custom images Use the same process names specified in TCPIP EXTENSION_MIB_ RUN COM Modify the IF and THEN statements to include the new symb...

Page 44: ......

Page 45: ...request PDUs to an agent and displays the agent s response To run the MIB browser follow these steps 1 Define a foreign command for the program snmp_request SYS SYSTEM TCPIP SNMP_REQUEST Alternativel...

Page 46: ...cribed in Section 4 1 3 value The value to which to set the contents of the OID This parameter is used for set requests For Set requests you can specify more than one group of the following variable n...

Page 47: ...ion or SNMP version and command combination Specify a positive integer for the value max_ignores If you specify a negative value it will be converted to an unsigned positive integer If you specify 0 n...

Page 48: ...of mib view These examples assume that OID 1 3 6 1 6 3 1 1 6 1 0 is the last OID supported on the target host The target host is running an SNMP Version 2 agent The statement end of mib view refers t...

Page 49: ...P version to use for sending the PDU The versions are 2c or 1 default Not case sensitive You can specify the flag without a space v2c and v1 If request_type is getbulk the version defaults to SNMP Ver...

Page 50: ...d address 0 0 0 0 The address_list community is type Read and Write with write access for the host on which the snmp_request program is running The location has been specified as shown in the followin...

Page 51: ...on 255 300 OpenVMS V7 1 Digital TCP IP Services for OpenVMS 1 3 6 1 2 1 1 2 0 1 3 6 1 4 1 36 2 15 13 7 1 1 3 6 1 2 1 2 2 1 1 1 1 1 3 6 1 2 1 2 2 1 2 1 LO IP Interface LO0 OpenVMS Adapter none Loopback...

Page 52: ...ies the correct type for the variable and all the conditions for enabling Set requests are met on the server snmp_request marley dec com address_list _ set 1 3 6 1 2 1 1 4 0 D Richard Blaine 1 3 6 1 2...

Page 53: ...1 Entering Commands for the Trap Sender Program The trap sender program lets you send SNMP Version 1 and SNMP Version 2 trap messages You should use this program only when you want to test the client...

Page 54: ...thenticationFailure 5 egpNeighborLoss 6 enterpriseSpecific For SNMP Version 2 when the v2c flag is specified this parameter must contain a valid OID or 0 as the value of snmpTrapOID specific trap For...

Page 55: ...psnd command The remainder is the display received when running the trap receiver program snmp_traprcv without flags included 1 The following example generates a trap that originated on the localhost...

Page 56: ...formatted dump of the received packet p port Specifies the port number on the local host on which to listen for trap messages The default is 162 tcp Listens on the TCP port instead of the UDP default...

Page 57: ...rivilege snmp_traprcv No snmp trap service entry using default port 162 bind permission denied 2 The example supplied from a nonprivileged account requests trap information in hexadecimal dump format...

Page 58: ......

Page 59: ...ommunication with the master agent esnmp_register Requests local registration of a MIB subtree esnmp_unregister Cancels local registration of a MIB subtree esnmp_register2 Requests cluster registratio...

Page 60: ...e must be registered again You should attempt to create a unique subagent identifier perhaps using the program name argv 0 and additional descriptive text The master agent does not open communications...

Page 61: ...0 If the value is 0 the default timeout is 3 seconds Compaq recommends that you use the default For information about modifying the default subagent timeout value refer to Section 6 2 priority The reg...

Page 62: ...subtree OID 1 3 6 1 2 1 4 21 1 These MIBs are registered at priority 1 Any subagent that registers at a higher priority greater than 1 overrides these registrations A request for IpRouteIfIndex OID 1...

Page 63: ...esnmp_register status esnmp_register ipRouteEntry_subtree RESPONSE_TIMEOUT REGISTRATION_PRIORITY if status ESNMP_LIB_OK printf Could not queue the ipRouteEntry n printf subtree for registration n eSNM...

Page 64: ...btree anymore You can later reregister a MIB subtree if needed by calling the esnmp_register routine Return Values SNMP_LIB_OK The esnmp_unregister routine has completed successfully ESNMP_LIB_BAD_REG...

Page 65: ...emitted by the MIBCOMP command priority The registration priority The entry with the largest number has the highest priority The range is 1 to 255 The subagent that has registered a MIB subtree with...

Page 66: ...STATE_ PENDING The registration is currently held locally while waiting for connection to the master agent ESNMP_REG_STATE_SENT The registration was sent to the master agent ESNMP_REG_STATE_DONE The r...

Page 67: ...t can also register MIB subtrees that overlap the OID range of MIB subtrees that it previously registered or the OID ranges of MIB subtrees registered by other subagents For example consider the two s...

Page 68: ...tatic ESNMP_REG esnmp_reg_for_ip2egp retain this structure for a subsequent call to esnmp_unregister2 initialize the ESNMP_REG structure memset esnmp_reg_for_ip2egp 0 sizeof ESNMP_REG esnmp_reg_for_ip...

Page 69: ...a MIB subtree if needed by calling the esnmp_register2 routine Return Values ESNMP_LIB_OK The routine completed successfully ESNMP_LIB_BAD_REG The MIB subtree was not registered ESNMP_LIB_LOST_ CONNE...

Page 70: ...ments agent_cap_id A pointer to an object identifier that represents an authoritative agent capabilities identifier This value is used for the sysORID object in the sysORTable for the managed node age...

Page 71: ...inter to an object identifier that represents an authoritative agent capabilities identifier This value is used for the sysORID object in the sysORTable for the managed node Description This routine i...

Page 72: ...iate method routines are called as defined by the developer of the subagent Return Values ESNMP_LIB_OK The esnmp_poll routine completed successfully ESNMP_LIB_BAD_REG The master agent failed in a prev...

Page 73: ...nded to cause the master agent to reply immediately The response should be processed by calling the esnmp_poll routine If a response is not received within the timeout period the application code shou...

Page 74: ...er agent is not running traps are queued and sent when communication is possible The trap message is actually sent to the master agent after it responds to the esnmp_init routine This occurs with ever...

Page 75: ...escription Subagents must call this routine when terminating so that the master agent can update its MIB registry quickly and so that resources used by eSNMP on behalf of the subagent can be released...

Page 76: ...nto eSNMP TimeTicks The function returns the value that sysUpTime held when the passed timestamp was now This routine can be used as a TimeTicks data type the time since the eSNMP master agent started...

Page 77: ...e s method routine is then called Therefore a method routine is called to service a single MIB variable Since a single method routine can handle a number of MIB variables the same method routine may b...

Page 78: ...a repeating VARBIND This number increments from 1 to max_repetitions and is 0 zero for nonrepeating VARBIND structures max_repetitions The maximum number of repetitions to perform Used for GetBulk onl...

Page 79: ...n is useful for this Description These types of routines call whatever routine is specified for Get operations in the object table identified by the registered subtree This function is pointed to by s...

Page 80: ...at contains the MIB variable s supplied data value and name OID The instance information has already been extracted from the OID and placed in the method row instance field object A pointer to the obj...

Page 81: ...ine builds this array by subtracting the object OID from the requested variable binding OID instance_len The size of the method row instance field context A pointer to be used privately by the method...

Page 82: ...ocessing _set Routines This following is the sequence of operations performed for _set routines 1 Every variable binding is parsed and its object is located in the object table A METHOD structure is c...

Page 83: ...erform the Set request during the COMMIT phase The method row context field is private to the method routine libesnmp does not use it A typical use is to store the address of an emitted structure that...

Page 84: ...that might have been allocated and stored in method row context and method row save fields and so on The function return status value is ignored for the CLEANUP phase 5 2 2 Method Routine Applications...

Page 85: ...Section 5 2 3 for information on data value representation Return the correct status value as follows ESNMP_MTHD_noError The routine completed successfully or no errors were found ESNMP_MTHD_noSuchIns...

Page 86: ...ct the instance elements from an incoming OID on a request Use the instance2oid function to combine the instance elements with the MIB variable s base OID to set the VARBIND structure s name field whe...

Page 87: ...NMP_TYPE_TimeTicks varbind value ul field The 32 bit timeticks type values are stored in the VARBIND structure as an unsigned integer Use the o_integer function to insert an unsigned value into the VA...

Page 88: ...OID s prefix clone_oid Makes a copy of an OID free_oid Frees a buffer clone_buf Duplicates a buffer mem2oct Converts a string to an oct structure cmp_oct Compares two octets clone_oct Makes a copy of...

Page 89: ...he real type as defined in the object structure must be one of the following otherwise an error is returned ESNMP_TYPE_Integer32 32 bit integer ESNMP_TYPE_Counter32 32 bit counter unsigned ESNMP_TYPE_...

Page 90: ...NetToMediaEntry_type definition VARBIND vb method varbind OBJECT object method object ipNetToMediaEntry_type data assume buffer and structure member assignments occur here switch arg case I_atIfIndex...

Page 91: ...RBIND structure value The value to be inserted into the VARBIND structure The real type as defined in the object structure must be one of the following otherwise an error is returned ESNMP_TYPE_OCTET_...

Page 92: ...ointer to the OBJECT structure for the MIB variable associated with the OID in the VARBIND structure oid The value to be inserted into the VARBIND structure as data For more information about OID leng...

Page 93: ...he MIB variable associated with the OID in the VARBIND structure ptr The pointer to the buffer containing data to be inserted into the VARBIND structure as data len The length of the data in buffer po...

Page 94: ...efinition VARBIND vb method varbind OBJECT object method object ipNetToMediaEntry_type data assume buffer and structure member assignments occur here switch arg case I_atPhysAddress return o_string vb...

Page 95: ...inter to the OBJECT structure for the MIB variable associated with the OID in the VARBIND structure value The 8 byte value to be inserted into the VARBIND structure passed as an array of two integers...

Page 96: ...r 3 s A null string or empty string returns an OID structure that has one element of zero Description The routine dynamically allocates the buffer and inserts its pointer into the OID structure passed...

Page 97: ...ption An OID can have up to 128 elements A full sized OID can require a large buffer Return Values The return value points to its first argument Example include esnmp h define SOMETHING_BIG 1024 OID a...

Page 98: ...to construct the new OID len The number of elements in the instance array Description The instance array may be created by oid2instance or constructed from key values as a result of a GetNext command...

Page 99: ...in unsigned int instance 6 Construct the outgoing OID in a GETNEXT Instance is N 1 A A A A where A s are IP address instance 0 data ipNetToMediaIfIndex instance 1 1 for i 0 i 4 i instance i 2 unsigned...

Page 100: ...ements in the instance array Description The instance values are the elements of an OID beyond those that identify the MIB variable These elements identify a specific instance of a MIB value If there...

Page 101: ...unsigned int instance 6 in a GET operation Expected Instance is N 1 A A A A where A s are IP address instLength oid2instance incoming object instance 6 if instLength 6 return ESNMP_MTHD_noSuchInstanc...

Page 102: ...results in an ipaddr value of zero For an exact match such as Get there must be exactly four elements ipAddr A pointer indicating where to return the IP address value This routine is in network byte...

Page 103: ...ddress instLength oid2instance incoming object instance 6 if instLength 6 inst2ip instance 2 4 ip_addr TRUE 0 iface int instance 0 else return ESNMP_MTHD_noSuchInstance 2 The following example shows a...

Page 104: ...the key Convert the A A A A portion by calling the inst2ip routine passing it length 1 for the length and the carry returned from the conversion of the B B B B portion The most significant element n i...

Page 105: ...element by element comparison from the most significant element element 0 to the least significant element If all other elements are equal the OID with the least number of elements is considered less...

Page 106: ...If all elements of the prefix OID match exactly with corresponding elements of the OID q structure it is considered an even match if the OID q structure contains additional elements The OID q structu...

Page 107: ...OID structure that is to receive the new OID values and call this routine Any previous value in the new OID structure is freed using the free_oid routine and the new values are dynamically allocated...

Page 108: ...lements buffer attached to the structure Format void free_oid oid oid Description This routine frees the buffer pointed to by the OID elements field and zeros the field and the NELEM structure Example...

Page 109: ...e is always allocated at the end and is filled with zeros If the length is less than zero the duplicate buffer length is set to zero A buffer pointer is always returned unless there is a malloc error...

Page 110: ...locates the buffer and inserts its pointer into the oct structure The caller must explicitly free this buffer This routine does not allocate an oct structure and does not free data previously pointed...

Page 111: ...f all bytes are equal the lengths are compared An octet with a null pointer is considered the same as a zero length octet Return Values 1 The string pointed to by the first oct is less than the second...

Page 112: ...r copies the data and updates the oct structure with the buffer s address and length The caller must free this buffer The previous value of the buffer on the new oct structure is freed prior to the ne...

Page 113: ...amically allocated buffer to which the oct structure points and zeros the pointer and length on the oct structure If the oct structure is already null this routine does nothing If the buffer attached...

Page 114: ...structure points Format void free_varbind_data varbind vb Description This routine performs a free_oid vb name operation If indicated by the vb type field it then frees the vb value data using either...

Page 115: ...et cannot be handled also implies ERROR This is the default TRACE Used when tracing all packets also implies ERROR and WARNING null This parameter is not used by OpenVMS It is supplied for compatibili...

Page 116: ...rt WARNING Used when a packet cannot be handled this also implies ERROR TRACE Used when tracing all packets this also implies ERROR and WARNING Format int is_debug_level int type Return Values TRUE Th...

Page 117: ...ions without the ESNMP_LOG macro For example define ESNMP_LOG level x if is_debug_level level esnmp_log level esnmp_logs x __LINE__ __FILE__ Where x is a text string for example a printf statement lev...

Page 118: ...routine you must set the debug level to TRACE Output is sent to the specified file Format _ _print_varbind VARBIND vb int indent Arguments vb The pointer to the VARBIND structure to be displayed If th...

Page 119: ...on 6 1 Format set_select_limit char progname Arguments progname The subagent name This argument is valid with DPI versions only With AgentX the argument is NULL because subagents do not get names Retu...

Page 120: ...outine should be called from the main during program initialization It needs to be called only once Format _ _set_progname char prog Arguments prog The program name as taken from argv 0 or some other...

Page 121: ...e from the second application of the set This routine should be called only after the _ _set_progname routine has been called You can use this to restore the most recent program name only Format _ _re...

Page 122: ...o extract only the file name and file extension Format _ _parse_progname file specification Arguments file specification The full file specification for the subagent Example include esnmp h static cha...

Page 123: ...n sockets that are used by the subagent for communicating with the master agent Format esnmp_cleanup Example include esnmp h int rc ESNMP_LIB_OK rc esnmp_cleanup Return Values ESNMP_LIB_NOTOK There wa...

Page 124: ......

Page 125: ...IMIT to modify the number of times a 1 error value can be returned from a select call The valid TCPIP SNMP_SELECT_ERROR_LIMIT values range from 1 to less than 232 01 default 100 When defining the erro...

Page 126: ...ent TCPIP OS_MIBS LOG for the MIB II TCPIP HR_MIB LOG for the Host Resources MIB Output redirected from SYS ERROR is logged to the following files TCPIP ESNMP ERR for the master agent TCPIP OS_MIBS ER...

Page 127: ...ERROR For the master agent and standard subagents the logging level is WARNING Log files for these processes include messages for WARNING and ERROR events The chess example does not have a default log...

Page 128: ......

Page 129: ...ne 5 3 esnmp_sysuptime interface routine 5 18 esnmp_term interface routine 5 17 esnmp_trap interface routine 5 16 esnmp_uncapabilities interface routine 5 13 esnmp_unregister2 interface routine 5 11 e...

Page 130: ...P __parse_progname support routine 5 64 __print_varbind support routine 5 60 Problems See Troubleshooting features R __restore_progname support routine 5 63 RFCs 1155 2 7 3 1 3 2 4 6 1213 2 5 1514 2...

Page 131: ...g 4 9 Troubleshooting features 6 1 U UNIX utilities 3 7 W Writing subagents compiling 3 5 creating source files 3 5 including in startup and shutdown 3 12 linking and building 3 11 object tables 3 7 u...

Page 132: ......

Reviews: