1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 static char *hex_table
= "0123456789ABCDEF";
23 * Dump up to the first 1024 bytes on an AJP Message
25 * @param pool pool to allocate from
26 * @param msg AJP Message to dump
27 * @param err error string to display
28 * @return dump message
30 char * ajp_msg_dump(apr_pool_t
*pool
, ajp_msg_t
*msg
, char *err
)
38 apr_size_t len
= msg
->len
;
40 /* Display only first 1024 bytes */
43 rv
= apr_palloc(pool
, bl
);
45 "ajp_msg_dump(): %s pos=%" APR_SIZE_T_FMT
46 " len=%" APR_SIZE_T_FMT
" max=%" APR_SIZE_T_FMT
"\n",
47 err
, msg
->pos
, msg
->len
, msg
->max_size
);
50 for (i
= 0; i
< len
; i
+= 16) {
53 for (j
= 0; j
< 16; j
++) {
56 *current
++ = hex_table
[x
>> 4];
57 *current
++ = hex_table
[x
& 0x0f];
63 for (j
= 0; j
< 16; j
++) {
66 if (x
> 0x20 && x
< 0x7F) {
76 "ajp_msg_dump(): %.4lx %s\n",
77 (unsigned long)i
, line
);
88 * Check a new AJP Message by looking at signature and return its size
90 * @param msg AJP Message to check
91 * @param len Pointer to returned len
92 * @return APR_SUCCESS or error
94 apr_status_t
ajp_msg_check_header(ajp_msg_t
*msg
, apr_size_t
*len
)
96 apr_byte_t
*head
= msg
->buf
;
99 if (!((head
[0] == 0x41 && head
[1] == 0x42) ||
100 (head
[0] == 0x12 && head
[1] == 0x34))) {
102 ap_log_error(APLOG_MARK
, APLOG_ERR
, 0, NULL
,
103 "ajp_check_msg_header() got bad signature %02x%02x",
106 return AJP_EBAD_SIGNATURE
;
109 msglen
= ((head
[2] & 0xff) << 8);
110 msglen
+= (head
[3] & 0xFF);
112 if (msglen
> msg
->max_size
) {
113 ap_log_error(APLOG_MARK
, APLOG_ERR
, 0, NULL
,
114 "ajp_check_msg_header() incoming message is "
115 "too big %" APR_SIZE_T_FMT
", max is %" APR_SIZE_T_FMT
,
116 msglen
, msg
->max_size
);
120 msg
->len
= msglen
+ AJP_HEADER_LEN
;
121 msg
->pos
= AJP_HEADER_LEN
;
128 * Reset an AJP Message
130 * @param msg AJP Message to reset
131 * @return APR_SUCCESS or error
133 apr_status_t
ajp_msg_reset(ajp_msg_t
*msg
)
135 msg
->len
= AJP_HEADER_LEN
;
136 msg
->pos
= AJP_HEADER_LEN
;
142 * Reuse an AJP Message
144 * @param msg AJP Message to reuse
145 * @return APR_SUCCESS or error
147 apr_status_t
ajp_msg_reuse(ajp_msg_t
*msg
)
153 max_size
= msg
->max_size
;
154 memset(msg
, 0, sizeof(ajp_msg_t
));
156 msg
->max_size
= max_size
;
157 msg
->header_len
= AJP_HEADER_LEN
;
163 * Mark the end of an AJP Message
165 * @param msg AJP Message to end
166 * @return APR_SUCCESS or error
168 apr_status_t
ajp_msg_end(ajp_msg_t
*msg
)
170 apr_size_t len
= msg
->len
- AJP_HEADER_LEN
;
172 if (msg
->server_side
) {
181 msg
->buf
[2] = (apr_byte_t
)((len
>> 8) & 0xFF);
182 msg
->buf
[3] = (apr_byte_t
)(len
& 0xFF);
187 static APR_INLINE
int ajp_log_overflow(ajp_msg_t
*msg
, const char *context
)
189 ap_log_error(APLOG_MARK
, APLOG_ERR
, 0, NULL
,
190 "%s(): BufferOverflowException %" APR_SIZE_T_FMT
192 context
, msg
->pos
, msg
->len
);
193 return AJP_EOVERFLOW
;
197 * Add an unsigned 32bits value to AJP Message
199 * @param msg AJP Message to get value from
200 * @param value value to add to AJP Message
201 * @return APR_SUCCESS or error
203 apr_status_t
ajp_msg_append_uint32(ajp_msg_t
*msg
, apr_uint32_t value
)
205 apr_size_t len
= msg
->len
;
207 if ((len
+ 4) > msg
->max_size
) {
208 return ajp_log_overflow(msg
, "ajp_msg_append_uint32");
211 msg
->buf
[len
] = (apr_byte_t
)((value
>> 24) & 0xFF);
212 msg
->buf
[len
+ 1] = (apr_byte_t
)((value
>> 16) & 0xFF);
213 msg
->buf
[len
+ 2] = (apr_byte_t
)((value
>> 8) & 0xFF);
214 msg
->buf
[len
+ 3] = (apr_byte_t
)(value
& 0xFF);
222 * Add an unsigned 16bits value to AJP Message
224 * @param msg AJP Message to get value from
225 * @param value value to add to AJP Message
226 * @return APR_SUCCESS or error
228 apr_status_t
ajp_msg_append_uint16(ajp_msg_t
*msg
, apr_uint16_t value
)
230 apr_size_t len
= msg
->len
;
232 if ((len
+ 2) > msg
->max_size
) {
233 return ajp_log_overflow(msg
, "ajp_msg_append_uint16");
236 msg
->buf
[len
] = (apr_byte_t
)((value
>> 8) & 0xFF);
237 msg
->buf
[len
+ 1] = (apr_byte_t
)(value
& 0xFF);
245 * Add an unsigned 8bits value to AJP Message
247 * @param msg AJP Message to get value from
248 * @param value value to add to AJP Message
249 * @return APR_SUCCESS or error
251 apr_status_t
ajp_msg_append_uint8(ajp_msg_t
*msg
, apr_byte_t value
)
253 apr_size_t len
= msg
->len
;
255 if ((len
+ 1) > msg
->max_size
) {
256 return ajp_log_overflow(msg
, "ajp_msg_append_uint8");
259 msg
->buf
[len
] = value
;
266 * Add a String in AJP message, and transform the String in ASCII
267 * if convert is set and we're on an EBCDIC machine
269 * @param msg AJP Message to get value from
270 * @param value Pointer to String
271 * @param convert When set told to convert String to ASCII
272 * @return APR_SUCCESS or error
274 apr_status_t
ajp_msg_append_string_ex(ajp_msg_t
*msg
, const char *value
,
280 return(ajp_msg_append_uint16(msg
, 0xFFFF));
284 if ((msg
->len
+ len
+ 3) > msg
->max_size
) {
285 return ajp_log_overflow(msg
, "ajp_msg_append_cvt_string");
288 /* ignore error - we checked once */
289 ajp_msg_append_uint16(msg
, (apr_uint16_t
)len
);
291 /* We checked for space !! */
292 memcpy(msg
->buf
+ msg
->len
, value
, len
+ 1); /* including \0 */
294 if (convert
) /* convert from EBCDIC if needed */
295 ap_xlate_proto_to_ascii((char *)msg
->buf
+ msg
->len
, len
+ 1);
303 * Add a Byte array to AJP Message
305 * @param msg AJP Message to get value from
306 * @param value Pointer to Byte array
307 * @param valuelen Byte array len
308 * @return APR_SUCCESS or error
310 apr_status_t
ajp_msg_append_bytes(ajp_msg_t
*msg
, const apr_byte_t
*value
,
314 return APR_SUCCESS
; /* Shouldn't we indicate an error ? */
317 if ((msg
->len
+ valuelen
) > msg
->max_size
) {
318 return ajp_log_overflow(msg
, "ajp_msg_append_bytes");
321 /* We checked for space !! */
322 memcpy(msg
->buf
+ msg
->len
, value
, valuelen
);
323 msg
->len
+= valuelen
;
329 * Get a 32bits unsigned value from AJP Message
331 * @param msg AJP Message to get value from
332 * @param rvalue Pointer where value will be returned
333 * @return APR_SUCCESS or error
335 apr_status_t
ajp_msg_get_uint32(ajp_msg_t
*msg
, apr_uint32_t
*rvalue
)
339 if ((msg
->pos
+ 3) > msg
->len
) {
340 return ajp_log_overflow(msg
, "ajp_msg_get_uint32");
343 value
= ((msg
->buf
[(msg
->pos
++)] & 0xFF) << 24);
344 value
|= ((msg
->buf
[(msg
->pos
++)] & 0xFF) << 16);
345 value
|= ((msg
->buf
[(msg
->pos
++)] & 0xFF) << 8);
346 value
|= ((msg
->buf
[(msg
->pos
++)] & 0xFF));
354 * Get a 16bits unsigned value from AJP Message
356 * @param msg AJP Message to get value from
357 * @param rvalue Pointer where value will be returned
358 * @return APR_SUCCESS or error
360 apr_status_t
ajp_msg_get_uint16(ajp_msg_t
*msg
, apr_uint16_t
*rvalue
)
364 if ((msg
->pos
+ 1) > msg
->len
) {
365 return ajp_log_overflow(msg
, "ajp_msg_get_uint16");
368 value
= ((msg
->buf
[(msg
->pos
++)] & 0xFF) << 8);
369 value
+= ((msg
->buf
[(msg
->pos
++)] & 0xFF));
376 * Peek a 16bits unsigned value from AJP Message, position in message
379 * @param msg AJP Message to get value from
380 * @param rvalue Pointer where value will be returned
381 * @return APR_SUCCESS or error
383 apr_status_t
ajp_msg_peek_uint16(ajp_msg_t
*msg
, apr_uint16_t
*rvalue
)
387 if ((msg
->pos
+ 1) > msg
->len
) {
388 return ajp_log_overflow(msg
, "ajp_msg_peek_uint16");
391 value
= ((msg
->buf
[(msg
->pos
)] & 0xFF) << 8);
392 value
+= ((msg
->buf
[(msg
->pos
+ 1)] & 0xFF));
399 * Peek a 8bits unsigned value from AJP Message, position in message
402 * @param msg AJP Message to get value from
403 * @param rvalue Pointer where value will be returned
404 * @return APR_SUCCESS or error
406 apr_status_t
ajp_msg_peek_uint8(ajp_msg_t
*msg
, apr_byte_t
*rvalue
)
408 if (msg
->pos
> msg
->len
) {
409 return ajp_log_overflow(msg
, "ajp_msg_peek_uint8");
412 *rvalue
= msg
->buf
[msg
->pos
];
417 * Get a 8bits unsigned value from AJP Message
419 * @param msg AJP Message to get value from
420 * @param rvalue Pointer where value will be returned
421 * @return APR_SUCCESS or error
423 apr_status_t
ajp_msg_get_uint8(ajp_msg_t
*msg
, apr_byte_t
*rvalue
)
426 if (msg
->pos
> msg
->len
) {
427 return ajp_log_overflow(msg
, "ajp_msg_get_uint8");
430 *rvalue
= msg
->buf
[msg
->pos
++];
436 * Get a String value from AJP Message
438 * @param msg AJP Message to get value from
439 * @param rvalue Pointer where value will be returned
440 * @return APR_SUCCESS or error
442 apr_status_t
ajp_msg_get_string(ajp_msg_t
*msg
, const char **rvalue
)
448 status
= ajp_msg_get_uint16(msg
, &size
);
451 if ((status
!= APR_SUCCESS
) || (size
+ start
> msg
->max_size
)) {
452 return ajp_log_overflow(msg
, "ajp_msg_get_string");
455 msg
->pos
+= (apr_size_t
)size
;
456 msg
->pos
++; /* a String in AJP is NULL terminated */
458 *rvalue
= (const char *)(msg
->buf
+ start
);
464 * Get a Byte array from AJP Message
466 * @param msg AJP Message to get value from
467 * @param rvalue Pointer where value will be returned
468 * @param rvalueLen Pointer where Byte array len will be returned
469 * @return APR_SUCCESS or error
471 apr_status_t
ajp_msg_get_bytes(ajp_msg_t
*msg
, apr_byte_t
**rvalue
,
472 apr_size_t
*rvalue_len
)
478 status
= ajp_msg_get_uint16(msg
, &size
);
479 /* save the current position */
482 if ((status
!= APR_SUCCESS
) || (size
+ start
> msg
->max_size
)) {
483 return ajp_log_overflow(msg
, "ajp_msg_get_bytes");
485 msg
->pos
+= (apr_size_t
)size
; /* only bytes, no trailer */
487 *rvalue
= msg
->buf
+ start
;
495 * Create an AJP Message from pool
497 * @param pool memory pool to allocate AJP message from
498 * @param size size of the buffer to create
499 * @param rmsg Pointer to newly created AJP message
500 * @return APR_SUCCESS or error
502 apr_status_t
ajp_msg_create(apr_pool_t
*pool
, apr_size_t size
, ajp_msg_t
**rmsg
)
504 ajp_msg_t
*msg
= (ajp_msg_t
*)apr_pcalloc(pool
, sizeof(ajp_msg_t
));
507 ap_log_error(APLOG_MARK
, APLOG_ERR
, 0, NULL
,
508 "ajp_msg_create(): can't allocate AJP message memory");
512 msg
->server_side
= 0;
514 msg
->buf
= (apr_byte_t
*)apr_palloc(pool
, size
);
516 /* XXX: This should never happen
517 * In case if the OS cannont allocate 8K of data
518 * we are in serious trouble
519 * No need to check the alloc return value, cause the
520 * core dump is probably the best solution anyhow.
522 if (msg
->buf
== NULL
) {
523 ap_log_error(APLOG_MARK
, APLOG_ERR
, 0, NULL
,
524 "ajp_msg_create(): can't allocate AJP message memory");
529 msg
->header_len
= AJP_HEADER_LEN
;
530 msg
->max_size
= size
;
537 * Recopy an AJP Message to another
539 * @param smsg source AJP message
540 * @param dmsg destination AJP message
541 * @return APR_SUCCESS or error
543 apr_status_t
ajp_msg_copy(ajp_msg_t
*smsg
, ajp_msg_t
*dmsg
)
546 ap_log_error(APLOG_MARK
, APLOG_ERR
, 0, NULL
,
547 "ajp_msg_copy(): destination msg is null");
551 if (smsg
->len
> smsg
->max_size
) {
552 ap_log_error(APLOG_MARK
, APLOG_ERR
, 0, NULL
,
553 "ajp_msg_copy(): destination buffer too "
554 "small %" APR_SIZE_T_FMT
", max size is %" APR_SIZE_T_FMT
,
555 smsg
->len
, smsg
->max_size
);
559 memcpy(dmsg
->buf
, smsg
->buf
, smsg
->len
);
560 dmsg
->len
= smsg
->len
;
561 dmsg
->pos
= smsg
->pos
;
568 * Serialize in an AJP Message a PING command
570 * +-----------------------+
571 * | PING CMD (1 byte) |
572 * +-----------------------+
574 * @param smsg AJP message to put serialized message
575 * @return APR_SUCCESS or error
577 apr_status_t
ajp_msg_serialize_ping(ajp_msg_t
*msg
)
582 if ((rc
= ajp_msg_append_uint8(msg
, CMD_AJP13_PING
)) != APR_SUCCESS
)
589 * Serialize in an AJP Message a CPING command
591 * +-----------------------+
592 * | CPING CMD (1 byte) |
593 * +-----------------------+
595 * @param smsg AJP message to put serialized message
596 * @return APR_SUCCESS or error
598 apr_status_t
ajp_msg_serialize_cping(ajp_msg_t
*msg
)
603 if ((rc
= ajp_msg_append_uint8(msg
, CMD_AJP13_CPING
)) != APR_SUCCESS
)