View Javadoc
1   package org.metricshub.ipmi.core.coding.payload.lan;
2   
3   /*-
4    * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
5    * IPMI Java Client
6    * ჻჻჻჻჻჻
7    * Copyright 2023 Verax Systems, MetricsHub
8    * ჻჻჻჻჻჻
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   *
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   *
19   * You should have received a copy of the GNU General Lesser Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
23   */
24  
25  import org.metricshub.ipmi.core.coding.commands.CommandCodes;
26  import org.metricshub.ipmi.core.common.TypeConverter;
27  
28  /**
29   * A wrapper class for IPMB LAN message
30   */
31  public class IpmiLanRequest extends IpmiLanMessage {
32  
33  	/** The network function is a 6-bit field (IPMI 2.0 section 5.1). */
34  	private static final int MAX_NETWORK_FUNCTION_CODE = 0x3f;
35  
36  	/**
37  	 * Builds IpmiLanRequest addressed at LUN 0.
38  	 *
39  	 * @param networkFunction
40  	 *        - command specific {@link NetworkFunction}
41  	 * @param commandCode
42  	 *        - command specific {@link CommandCodes}
43  	 * @param requestData
44  	 *        - command specific payload
45  	 * @param sequenceNumber
46  	 *        - used to match request and response - must be in range [0-63]
47  	 */
48  	public IpmiLanRequest(NetworkFunction networkFunction, byte commandCode, byte[] requestData, byte sequenceNumber) {
49  		this(networkFunction, commandCode, requestData, sequenceNumber, TypeConverter.intToByte(0));
50  	}
51  
52  	/**
53  	 * Builds IpmiLanRequest.
54  	 *
55  	 * @param networkFunction
56  	 *        - command specific {@link NetworkFunction}
57  	 * @param commandCode
58  	 *        - command specific {@link CommandCodes}
59  	 * @param requestData
60  	 *        - command specific payload
61  	 * @param sequenceNumber
62  	 *        - used to match request and response - must be in range [0-63]
63  	 * @param lun
64  	 *        - target Logical Unit Number. Must be in range [0-3].
65  	 */
66  	public IpmiLanRequest(NetworkFunction networkFunction, byte commandCode, byte[] requestData, byte sequenceNumber,
67  			byte lun) {
68  		this(networkFunction.getCode(), commandCode, requestData, sequenceNumber, lun);
69  	}
70  
71  	/**
72  	 * Builds IpmiLanRequest addressed at LUN 0, under a network function given by its code, which may be one
73  	 * {@link NetworkFunction} does not list: Transport (0Ch), Group Extension (2Ch: DCMI, PICMG), OEM/Group (2Eh),
74  	 * controller-specific OEM (30h-3Eh), IPMI 2.0 table 5-1.
75  	 *
76  	 * @param networkFunctionCode
77  	 *        - the network function code of the request, 00h to 3Fh
78  	 * @param commandCode
79  	 *        - the command code
80  	 * @param requestData
81  	 *        - command specific payload, null for none
82  	 * @param sequenceNumber
83  	 *        - used to match request and response - must be in range [0-63]
84  	 * @throws IllegalArgumentException when the code does not fit in 6 bits
85  	 */
86  	public IpmiLanRequest(int networkFunctionCode, byte commandCode, byte[] requestData, byte sequenceNumber) {
87  		this(networkFunctionCode, commandCode, requestData, sequenceNumber, TypeConverter.intToByte(0));
88  	}
89  
90  	private IpmiLanRequest(int networkFunctionCode, byte commandCode, byte[] requestData, byte sequenceNumber, byte lun) {
91  		if (networkFunctionCode < 0 || networkFunctionCode > MAX_NETWORK_FUNCTION_CODE) {
92  			throw new IllegalArgumentException("Invalid network function code: " + networkFunctionCode);
93  		}
94  		if (lun < 0 || lun > 3) {
95  			throw new IllegalArgumentException("Invalid LUN");
96  		}
97  		setResponderAddress(IpmiLanConstants.BMC_ADDRESS);
98  		setNetworkFunctionCode(TypeConverter.intToByte(networkFunctionCode));
99  		setResponderLogicalUnitNumber(TypeConverter.intToByte(lun));
100 		setRequesterAddress(IpmiLanConstants.REMOTE_CONSOLE_ADDRESS);
101 		setRequesterLogicalUnitNumber(TypeConverter.intToByte(0));
102 		setSequenceNumber(sequenceNumber);
103 		setData(requestData);
104 		setCommand(commandCode);
105 	}
106 
107 	@Override
108 	public int getPayloadLength() {
109 		int length = 7;
110 
111 		if (getData() != null) {
112 			length += getData().length;
113 		}
114 		return length;
115 	}
116 
117 	@Override
118 	public byte[] getPayloadData() {
119 		byte[] message = new byte[getPayloadLength()];
120 
121 		message[0] = getResponderAddress();
122 		message[1] = TypeConverter.intToByte((getNetworkFunctionCode() << 2) | getResponderLogicalUnitNumber());
123 		message[2] = getChecksum1(message);
124 		message[3] = getRequesterAddress();
125 		message[4] = TypeConverter.intToByte(((getSequenceNumber() & 0x3f) << 2) | getRequesterLogicalUnitNumber()); // rqSeq/rqLUN
126 																																																									// (IPMI
127 																																																									// 2.0
128 																																																									// figure
129 																																																									// 13-4)
130 		message[5] = getCommand();
131 
132 		if (getData() != null) {
133 			System.arraycopy(getData(), 0, message, 6, getData().length);
134 		}
135 
136 		message[message.length - 1] = getChecksum2(message);
137 
138 		return message;
139 	}
140 
141 }