Old files... not needed in VM.
FossilOrigin-Name: ae77e76307684aa415352aaa4ecd53339a0d98a939464526441f7e741080aaa4
This commit is contained in:
parent
0a19326a7c
commit
182e460add
@ -1,265 +0,0 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Processing of incomming messaages.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "conn.h"
|
||||
#include "capwap.h"
|
||||
#include "capwap_items.h"
|
||||
|
||||
#include "sock.h"
|
||||
#include "action.h"
|
||||
#include "cw_log.h"
|
||||
#include "dbg.h"
|
||||
|
||||
|
||||
|
||||
int conn_send_msg(struct conn *conn, uint8_t * rawmsg);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Init response message header
|
||||
*/
|
||||
void cw_init_response(struct conn *conn, uint8_t * req)
|
||||
{
|
||||
uint8_t *buffer = conn->resp_buffer;
|
||||
int shbytes = cw_get_hdr_msg_offset(req);
|
||||
int dhbytes;
|
||||
memcpy(buffer, req, shbytes);
|
||||
cw_set_hdr_hlen(buffer, 2);
|
||||
cw_set_hdr_flags(buffer, CW_FLAG_HDR_M, 1);
|
||||
dhbytes = cw_get_hdr_msg_offset(buffer);
|
||||
|
||||
uint8_t *msgptr = req + shbytes;
|
||||
uint8_t *dmsgptr = buffer + dhbytes;
|
||||
|
||||
cw_set_msg_type(dmsgptr, cw_get_msg_type(msgptr) + 1);
|
||||
cw_set_msg_seqnum(dmsgptr, cw_get_msg_seqnum(msgptr));
|
||||
cw_set_msg_flags(dmsgptr, 0);
|
||||
}
|
||||
|
||||
void cw_init_request(struct conn *conn, int msg_id)
|
||||
{
|
||||
uint8_t *buffer = conn->req_buffer;
|
||||
|
||||
cw_put_dword(buffer + 0, 0);
|
||||
|
||||
/* unencrypted */
|
||||
cw_put_hdr_preamble(CAPWAP_VERSION<<8 | 0);
|
||||
|
||||
cw_put_dword(buffer + 4, 0);
|
||||
cw_set_hdr_preamble(buffer, 0);
|
||||
cw_set_hdr_hlen(buffer, 2);
|
||||
cw_set_hdr_wbid(buffer, 1);
|
||||
cw_set_hdr_rid(buffer, 0);
|
||||
uint8_t *msgptr = cw_get_hdr_msg_offset(buffer) + buffer;
|
||||
cw_set_msg_type(msgptr, msg_id);
|
||||
cw_set_msg_flags(msgptr, 0);
|
||||
cw_set_msg_elems_len(msgptr, 0);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* send a response
|
||||
*/
|
||||
int cw_send_response(struct conn *conn, uint8_t * rawmsg, int len)
|
||||
{
|
||||
cw_init_response(conn, rawmsg);
|
||||
if (cw_put_msg(conn, conn->resp_buffer) == -1)
|
||||
return 0;
|
||||
conn_send_msg(conn, conn->resp_buffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Special case error message, which is sent when an unexpected messages
|
||||
* was received or somethin else happened.
|
||||
* @param conn conection
|
||||
* @param rawmsg the received request message, which the response belongs to
|
||||
* @pqram result_code result code to send
|
||||
* @return 1
|
||||
*/
|
||||
int cw_send_error_response(struct conn *conn, uint8_t * rawmsg, uint32_t result_code)
|
||||
{
|
||||
cw_init_response(conn, rawmsg);
|
||||
|
||||
uint8_t *out = conn->resp_buffer;
|
||||
|
||||
uint8_t *dst = cw_get_hdr_msg_elems_ptr(out);
|
||||
int l = cw_put_elem_result_code(dst, result_code);
|
||||
|
||||
cw_set_msg_elems_len(out + cw_get_hdr_msg_offset(out), l);
|
||||
|
||||
conn_send_msg(conn, conn->resp_buffer);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int cw_process_msg(struct conn *conn, uint8_t * rawmsg, int len)
|
||||
{
|
||||
struct cw_action_in as, *af, *afm;
|
||||
|
||||
uint8_t *msg_ptr = rawmsg + cw_get_hdr_msg_offset(rawmsg);
|
||||
|
||||
int elems_len = cw_get_msg_elems_len(msg_ptr);
|
||||
/*
|
||||
if (8+elems_len != len){
|
||||
cw_dbg(DBG_MSG_ERR,"Discarding message from %s, msgelems len=%d, data len=%d, (strict capwap) ",
|
||||
sock_addr2str(&conn->addr),elems_len,len-8);
|
||||
|
||||
if (conn_is_strict_capwap(conn)){
|
||||
cw_dbg(DBG_MSG_ERR,"Discarding message from %s, msgelems len=%d, data len=%d, (strict capwap) ",
|
||||
sock_addr2str(&conn->addr),elems_len,len-8);
|
||||
return 0;
|
||||
}
|
||||
if (8+elems_len < len){
|
||||
cw_dbg(DBG_CW_RFC,"Packet from from %s has %d bytes extra data.",
|
||||
sock_addr2str(&conn->addr),len-8-elems_len);
|
||||
elems_len=len-8;
|
||||
}
|
||||
|
||||
if (8+elems_len > len){
|
||||
cw_dbg(DBG_CW_RFC,"Packet from from %s hass msgelems len of %d bytes but has only %d bytes of data, truncating.",
|
||||
sock_addr2str(&conn->addr),elems_len,len-8);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* prepare struct for search operation */
|
||||
as.capwap_state = conn->capwap_state;
|
||||
as.msg_id = cw_get_msg_id(msg_ptr);
|
||||
as.vendor_id = 0;
|
||||
as.elem_id = 0;
|
||||
as.proto = 0;
|
||||
|
||||
|
||||
/* Search for state/message combination */
|
||||
afm = cw_actionlist_in_get(conn->actions->in, &as);
|
||||
|
||||
if (!afm) {
|
||||
/* Throw away unexpected response messages */
|
||||
if (!(as.msg_id & 1)) {
|
||||
cw_dbg(DBG_MSG_ERR,
|
||||
"Message type %d (%s) unexpected/illigal in %s State, discarding.",
|
||||
as.msg_id, cw_strmsg(as.msg_id),
|
||||
cw_strstate(conn->capwap_state));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Request message not found in current state, check if we know
|
||||
anything else about this message type */
|
||||
const char *str = cw_strheap_get(conn->actions->strmsg, as.msg_id);
|
||||
int result_code = 0;
|
||||
if (str) {
|
||||
/* Message found, but it was in wrong state */
|
||||
cw_dbg(DBG_MSG_ERR,
|
||||
"Message type %d (%s) not allowed in %s State.", as.msg_id,
|
||||
cw_strmsg(as.msg_id), cw_strstate(as.capwap_state));
|
||||
result_code = CW_RESULT_MSG_INVALID_IN_CURRENT_STATE;
|
||||
} else {
|
||||
/* Message is unknown */
|
||||
cw_dbg(DBG_MSG_ERR, "Message type %d (%s) unknown.",
|
||||
as.msg_id, cw_strmsg(as.msg_id),
|
||||
cw_strstate(as.capwap_state));
|
||||
result_code = CW_RESULT_MSG_UNRECOGNIZED;
|
||||
|
||||
}
|
||||
cw_send_error_response(conn, rawmsg, result_code);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Execute start processor for message */
|
||||
if (afm->start) {
|
||||
afm->start(conn, afm, rawmsg, len);
|
||||
}
|
||||
|
||||
uint8_t *elems_ptr = cw_get_msg_elems_ptr(msg_ptr);
|
||||
uint8_t *elem;
|
||||
|
||||
/* avltree to bag the found mandatory elements */
|
||||
conn->mand = intavltree_create();
|
||||
|
||||
/* iterate through message elements */
|
||||
cw_foreach_elem(elem, elems_ptr, elems_len) {
|
||||
|
||||
as.elem_id = cw_get_elem_id(elem);
|
||||
int elem_len = cw_get_elem_len(elem);
|
||||
|
||||
cw_dbg_elem(conn, as.msg_id, as.elem_id, cw_get_elem_data(elem),
|
||||
elem_len);
|
||||
|
||||
|
||||
af = cw_actionlist_in_get(conn->actions->in, &as);
|
||||
|
||||
if (!af) {
|
||||
cw_dbg(DBG_ELEM_ERR, "Element %d not allowed in msg %d (%s)",
|
||||
as.elem_id, as.msg_id, cw_strmsg(as.msg_id));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (af->mand) {
|
||||
/* add found mandatory message element
|
||||
to mand list */
|
||||
intavltree_add(conn->mand, af->item_id);
|
||||
}
|
||||
|
||||
if (af->start) {
|
||||
af->start(conn, af, cw_get_elem_data(elem), elem_len);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int result_code = 0;
|
||||
if (afm->end) {
|
||||
result_code = afm->end(conn, afm, rawmsg, len);
|
||||
}
|
||||
|
||||
/* if we've got a request message, we always have to send a response message */
|
||||
if (as.msg_id & 1) {
|
||||
if (result_code > 0) {
|
||||
/* the end method gave us an result code, so
|
||||
send an error message */
|
||||
cw_send_error_response(conn, rawmsg, result_code);
|
||||
} else {
|
||||
/* regular response message */
|
||||
cw_send_response(conn, rawmsg, len);
|
||||
}
|
||||
}
|
||||
|
||||
intavltree_destroy(conn->mand);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "cwmsg.h"
|
||||
|
||||
|
||||
void cwmsg_addelem(struct cwmsg *msg,int type,const uint8_t*elem,int len)
|
||||
{
|
||||
uint32_t val = type<<16|len;
|
||||
*((uint32_t*)(msg->msgelems+msg->pos))=htonl(val);
|
||||
memcpy(msg->msgelems+4+msg->pos,elem,len);
|
||||
msg->pos+=4+len;
|
||||
}
|
||||
|
@ -1,92 +0,0 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Implementation of cwmsg_addelem_ac_descriptor.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "capwap.h"
|
||||
#include "wtpinfo.h"
|
||||
|
||||
|
||||
static int add_subelem(uint8_t * buffer,int type, uint32_t vendor,bstr_t version)
|
||||
{
|
||||
|
||||
*((uint32_t*)buffer) = htonl(vendor);
|
||||
*((uint32_t*)(buffer+4)) = htonl( (type<<16) | bstr_len(version));
|
||||
|
||||
memcpy(buffer+8,bstr_data(version),bstr_len(version));
|
||||
|
||||
return 8+bstr_len(version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an ac descriptor message element.
|
||||
* @param msg pointer to the message
|
||||
* @param acinfo acinfo structure where data is taken from
|
||||
* @param wtpinfo WTP which whants the AC descriptor
|
||||
*/
|
||||
void cwmsg_addelem_ac_descriptor(struct cwmsg *msg,struct ac_info * acinfo,struct wtpinfo *wtpinfo)
|
||||
{
|
||||
uint8_t buffer[600];
|
||||
uint8_t * acd = buffer;
|
||||
|
||||
*((uint32_t*)(acd))=htonl((acinfo->stations<<16) | (acinfo->limit));
|
||||
*((uint32_t*)(acd+4))=htonl((acinfo->active_wtps<<16) | acinfo->max_wtps);
|
||||
*((uint32_t*)(acd+8))=htonl((acinfo->security<<24) | (acinfo->rmac<<16) | acinfo->dtls_policy );
|
||||
|
||||
|
||||
int len = 12;
|
||||
|
||||
switch (msg->capwap_mode){
|
||||
case CWMODE_CISCO:
|
||||
{
|
||||
|
||||
/* If no cisco software version is set, take software version
|
||||
from WTP */
|
||||
bstr_t c_version;
|
||||
if (!acinfo->cisco_software_version)
|
||||
c_version = wtpinfo->software_version;
|
||||
else
|
||||
c_version = acinfo->cisco_software_version;
|
||||
|
||||
/* If we don't have a WTP software version, use normal software
|
||||
version, not cisco software version */
|
||||
if (!c_version)
|
||||
c_version=acinfo->software_version;
|
||||
|
||||
/* It seems to be very important, that the software version sub-elemnt is
|
||||
sent first. If not, the Cisco WTP gets confused and thinks the AP has
|
||||
version 0.0.0.0. Tested with an 8.0.110.0 image on a LAP 1131a */
|
||||
|
||||
len+=add_subelem(buffer+len,1,CW_VENDOR_ID_CISCO,c_version);
|
||||
len+=add_subelem(buffer+len,0,CW_VENDOR_ID_CISCO,acinfo->cisco_hardware_version);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
len+=add_subelem(buffer+len,5,0,acinfo->software_version);
|
||||
len+=add_subelem(buffer+len,4,0,acinfo->hardware_version);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
cwmsg_addelem(msg,CW_ELEM_AC_DESCRIPTOR,acd,len);
|
||||
}
|
||||
|
@ -1,65 +0,0 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "capwap.h"
|
||||
#include "bstr.h"
|
||||
|
||||
|
||||
static inline int wtpdesc_addsubelem(uint8_t * dst,uint8_t type,uint32_t vendorid,bstr_t str)
|
||||
{
|
||||
int l;
|
||||
*((uint32_t*)(dst))=htonl(vendorid);
|
||||
l = bstr_len(str);
|
||||
*((uint32_t*)(dst+4))=htonl((type<<16)|l);
|
||||
memcpy(dst+8,bstr_data(str),l);
|
||||
return l+8;
|
||||
}
|
||||
|
||||
void cwmsg_addelem_wtp_descriptor(struct cwmsg * cwmsg, struct wtpinfo * wtpinfo)
|
||||
{
|
||||
uint8_t d[1024];
|
||||
int len=0;
|
||||
|
||||
/* radios info */
|
||||
*(d)= wtpinfo->max_radios;
|
||||
*(d+1)=wtpinfo->radios_in_use;
|
||||
len=2;
|
||||
|
||||
switch (cwmsg->capwap_mode){
|
||||
case CWMODE_CISCO:
|
||||
/* encryption capabilities */
|
||||
*((uint16_t*)(d+len))=htons(wtpinfo->encryption_cap);
|
||||
len+=2;
|
||||
break;
|
||||
default:
|
||||
/* number of encryption elemnts */
|
||||
*(d+len)=0;
|
||||
len += 1;
|
||||
/* encryption elements */
|
||||
|
||||
|
||||
/* *(d+len)=CWTH_WBID_IEEE80211;
|
||||
uint16_t val = 0;
|
||||
*((uint16_t*)(d+len+1))=htons(val);
|
||||
len+=3;
|
||||
*/
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* hardware version subelem*/
|
||||
len+=wtpdesc_addsubelem(d+len,CW_SUBELEM_WTP_HARDWARE_VERSION,
|
||||
wtpinfo->hardware_vendor_id,wtpinfo->hardware_version);
|
||||
|
||||
/* software version subelem*/
|
||||
len+=wtpdesc_addsubelem(d+len,CW_SUBELEM_WTP_SOFTWARE_VERSION,
|
||||
wtpinfo->software_vendor_id,wtpinfo->software_version);
|
||||
|
||||
/* bootloader version subelem*/
|
||||
len+=wtpdesc_addsubelem(d+len,CW_SUBELEM_WTP_BOOTLOADER_VERSION,
|
||||
wtpinfo->bootloader_vendor_id,wtpinfo->bootloader_version);
|
||||
|
||||
cwmsg_addelem(cwmsg,CW_ELEM_WTP_DESCRIPTOR,d,len);
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "capwap.h"
|
||||
|
||||
#include "cwmsg.h"
|
||||
|
||||
|
||||
int mtu = 564;
|
||||
|
||||
int __old_cwmsg_send(struct cwmsg * cwmsg, int seqnum, int rid, struct conn * conn)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
/* second dword of message control header */
|
||||
//orig val = (seqnum<<24)|((cwmsg->pos+3)<<8);
|
||||
val = (seqnum<<24)|((cwmsg->pos)<<8);
|
||||
|
||||
*((uint32_t*)(cwmsg->ctrlhdr+4))=htonl(val);
|
||||
|
||||
|
||||
|
||||
// int msglen = cwmsg->ctrlhdr-cwmsg->buffer+cwmsg->pos;
|
||||
int msglen = cwmsg->pos+8;
|
||||
|
||||
uint8_t * ptr = cwmsg->buffer;
|
||||
int fragoffset = 0;
|
||||
int hlen = cwmsg->hlen*4;
|
||||
|
||||
|
||||
|
||||
int preamble = CW_VERSION | 0;
|
||||
|
||||
|
||||
int wbid=CWTH_WBID_IEEE80211;
|
||||
int packetlen = msglen+hlen;
|
||||
|
||||
while (packetlen>mtu){
|
||||
val = (preamble << 24) | ((hlen/4)<<19) | (rid<<14) |(wbid<<9) |
|
||||
/*CWTH_FLAGS_T | */
|
||||
CWTH_FLAGS_F |
|
||||
cwmsg->flags;
|
||||
*((uint32_t*)ptr)=htonl(val);
|
||||
|
||||
val = conn->fragid<<16 | fragoffset<<3;
|
||||
*((uint32_t*)(ptr+8))=htonl(val);
|
||||
|
||||
// printf("Offset = %d\n",fragoffset);
|
||||
|
||||
conn_send_packet(conn,ptr,mtu);
|
||||
|
||||
ptr +=mtu-hlen;
|
||||
fragoffset+=(mtu-hlen)/8;
|
||||
|
||||
packetlen-=mtu-hlen;
|
||||
// printf("Packelen=%d\n",packetlen);
|
||||
|
||||
}
|
||||
|
||||
val = (preamble << 24) | ((hlen/4)<<19) | (rid<<14) |(wbid<<9) |
|
||||
/*CWTH_FLAGS_T|*/ cwmsg->flags;
|
||||
|
||||
if (fragoffset)
|
||||
val |= CWTH_FLAGS_F | CWTH_FLAGS_L;
|
||||
|
||||
|
||||
// printf("Setting first byte %08X\n",val);
|
||||
*((uint32_t*)ptr)=htonl(val);
|
||||
|
||||
|
||||
val = conn->fragid<<16 | fragoffset<<3;
|
||||
*((uint32_t*)(ptr+4))=htonl(val);
|
||||
|
||||
return conn_send_packet(conn,cwmsg->buffer,msglen-fragoffset*8+hlen);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
This file is part of libcapwap.
|
||||
|
||||
libcapwap is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
libcapwap is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "cwmsg.h"
|
||||
|
||||
void cwmsg_vaddelem(struct cwmsg *msg,int type, ...)
|
||||
{
|
||||
va_list vl;
|
||||
va_start(vl,type);
|
||||
int len=0;
|
||||
|
||||
uint8_t *data;
|
||||
while ( ( data = va_arg(vl,uint8_t*)) != 0 ){
|
||||
int l=va_arg(vl,int);
|
||||
memcpy(msg->msgelems+4+msg->pos+len,data,l);
|
||||
len+=l;
|
||||
}
|
||||
|
||||
|
||||
uint32_t val = type<<16|len;
|
||||
*((uint32_t*)(msg->msgelems+msg->pos))=htonl(val);
|
||||
msg->pos+=4+len;
|
||||
va_end(vl);
|
||||
}
|
Loading…
Reference in New Issue
Block a user