代码拉取完成,页面将自动刷新
/************************************************************************************************
* Copyright (c) 2006-2009 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *
* Universita' Campus BioMedico - Italy *
* *
* This program 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 2 of the License, or (at your option) any later version. *
* *
* This program 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 this *
* program; if not, write to the: *
* Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, *
* MA 02111-1307, USA. *
* *
* -------------------------------------------------------------------------------------------- *
* Project: Capwap *
* *
* Authors : Matteo Latini (mtylty@gmail.com)
* Donato Capitella (d.capitella@gmail.com)
*
************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#ifdef DMALLOC
#include "../dmalloc-5.5.0/dmalloc.h"
#endif
#include "CWWTP.h"
#include "CWVendorPayloads.h"
#include "WUM.h"
CWBool CWParseUCIPayload(CWProtocolMessage * msgPtr, CWVendorUciValues ** payloadPtr)
{
int argsLen;
CWVendorUciValues *uciPayload = NULL;
CW_CREATE_OBJECT_ERR(uciPayload, CWVendorUciValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);
);
uciPayload->command = (unsigned char)CWProtocolRetrieve8(msgPtr);
uciPayload->response = NULL;
argsLen = (unsigned int)CWProtocolRetrieve32(msgPtr);
if (argsLen != 0) {
CW_CREATE_STRING_ERR(uciPayload->commandArgs, argsLen,
return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);
);
uciPayload->commandArgs = CWProtocolRetrieveStr(msgPtr, argsLen);
} else
uciPayload->commandArgs = NULL;
*payloadPtr = uciPayload;
CWLog("Parsed UCI Vendor Payload...");
return CW_TRUE;
}
CWBool CWParseWUMPayload(CWProtocolMessage * msgPtr, CWVendorWumValues ** payloadPtr)
{
CWVendorWumValues *wumPayload = NULL;
CW_CREATE_OBJECT_ERR(wumPayload, CWVendorWumValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);
);
wumPayload->type = (unsigned char)CWProtocolRetrieve8(msgPtr);
/*
* According to the type of the message, retrive additional fields
*/
if (wumPayload->type == WTP_UPDATE_REQUEST) {
wumPayload->_major_v_ = (unsigned char)CWProtocolRetrieve8(msgPtr);
wumPayload->_minor_v_ = (unsigned char)CWProtocolRetrieve8(msgPtr);
wumPayload->_revision_v_ = (unsigned char)CWProtocolRetrieve8(msgPtr);
wumPayload->_pack_size_ = (unsigned int)CWProtocolRetrieve32(msgPtr);
} else if (wumPayload->type == WTP_CUP_FRAGMENT) {
wumPayload->_seq_num_ = (unsigned int)CWProtocolRetrieve32(msgPtr);
wumPayload->_cup_fragment_size_ = (unsigned int)CWProtocolRetrieve32(msgPtr);
wumPayload->_cup_ = CWProtocolRetrieveRawBytes(msgPtr, wumPayload->_cup_fragment_size_);
}
*payloadPtr = wumPayload;
CWLog("Parsed WUM Vendor Payload...");
return CW_TRUE;
}
CWBool CWParseVendorPayload(CWProtocolMessage * msgPtr, int len, CWProtocolVendorSpecificValues * valPtr)
{
CWVendorUciValues *uciPtr;
CWVendorWumValues *wumPtr;
/*...we choose which payload was used (in this case only
uci configuration payloads are used) */
valPtr->vendorPayloadType = (unsigned short)CWProtocolRetrieve16(msgPtr);
switch (valPtr->vendorPayloadType) {
case CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_UCI:
if (!(CWParseUCIPayload(msgPtr, &uciPtr))) {
CW_FREE_OBJECT(uciPtr->commandArgs);
CW_FREE_OBJECT(uciPtr->response);
CW_FREE_OBJECT(uciPtr);
return CW_FALSE; // will be handled by the caller
}
valPtr->payload = (void *)uciPtr;
break;
case CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_WUM:
if (!(CWParseWUMPayload(msgPtr, &wumPtr))) {
CW_FREE_OBJECT(wumPtr);
return CW_FALSE; // will be handled by the caller
}
valPtr->payload = (void *)wumPtr;
break;
default:
return CW_FALSE; // will be handled by the caller
}
return CW_TRUE;
}
/************************************************************************
* WTP Update System
************************************************************************/
/* Update System States */
#define WUM_STATE_WAIT 0 /* waiting for WTP_UPDATE_REQUESTs */
#define WUM_STATE_BUSY 1 /* busy receiving CUP fragments */
#define WUM_STATE_READY 2 /* ready to start the update procedure */
struct WUMState {
unsigned char state; /* one of the above states */
FILE *cupTmp; /* pointer to the cup file */
int cupSize; /* size of the cup file */
int total_fragments; /* number of fragments of the cup file */
int received_fragments; /* number of fragments already received */
};
struct WUMState wumState = {
.state = WUM_STATE_WAIT,
.cupTmp = NULL,
.cupSize = 0,
.total_fragments = 0,
.received_fragments = 0
};
#define CUP_TMP_FILE "/tmp/wtp.cup"
#define WUA_BIN "WUA"
/*
* WUMPrepareTmpFile
*
* After a WTP_UPDATE_REQUEST, calling this function prepares the update system
* to accept CUP fragments and reassemble them into a temp file. If something goes
* wrong, it returns CW_FALSE; otherwise it returns CW_TRUE, the wumState changes
* to BUSY and we are ready to store the fragments we've received.
*/
CWBool WUMPrepareForUpdate(int size)
{
if (wumState.state != WUM_STATE_WAIT) {
CWLog("Can't start a new update session; the previous one isn't completed yet.\n");
return CW_FALSE;
}
wumState.cupTmp = fopen(CUP_TMP_FILE, "w");
if (wumState.cupTmp == NULL) {
CWLog("Can't open temp file %s for writing.\n", CUP_TMP_FILE);
return CW_FALSE;
}
wumState.cupSize = size;
wumState.total_fragments = size / CUP_FRAGMENT_SIZE;
if (size % CUP_FRAGMENT_SIZE > 0)
wumState.total_fragments++;
wumState.received_fragments = 0;
wumState.state = WUM_STATE_BUSY;
return CW_TRUE;
}
/*
* When in the BUSY State, this function is used to read and store the
* fragments that compose the update package (CUP) into a temp file.
*/
CWBool WUMStoreFragment(CWVendorWumValues * wumValues)
{
int offset, toWrite;
if (wumState.state != WUM_STATE_BUSY) {
CWLog("Received an update fragment, but no update session has been initialized yet.\n");
return CW_FALSE;
}
if (wumValues->_seq_num_ > wumState.total_fragments) {
CWLog("Received an update fragment with invalid sequence number.\n");
return CW_FALSE;
}
offset = wumValues->_seq_num_ * CUP_FRAGMENT_SIZE;
if (fseek(wumState.cupTmp, offset, SEEK_SET) != 0) {
CWLog("Can't seek required offset in CUP tmp file.\n");
return CW_FALSE;
}
toWrite = wumValues->_cup_fragment_size_;
if (fwrite(wumValues->_cup_, 1, toWrite, wumState.cupTmp) != toWrite) {
CWLog("Error while writing CUP tmp file.\n");
return CW_FALSE;
}
CW_FREE_OBJECT(wumValues->_cup_);
wumState.received_fragments++;
return CW_TRUE;
}
/*
* Tells if all fragments of an update have been received and reassembled.
*/
CWBool WUMIsComplete()
{
if (wumState.state != WUM_STATE_BUSY) {
return CW_FALSE;
}
if (wumState.total_fragments > wumState.received_fragments)
return CW_FALSE;
return CW_TRUE;
}
/*
* Close the temp file and goes back to the READY State.
*/
CWBool WUMCloseFile()
{
fclose(wumState.cupTmp);
wumState.cupTmp = NULL;
wumState.state = WUM_STATE_READY;
return CW_TRUE;
}
/*
* Cancel an Update.
*/
CWBool WUMCancel()
{
wumState.state = WUM_STATE_WAIT;
if (wumState.cupTmp)
fclose(wumState.cupTmp);
wumState.cupTmp = NULL;
remove(CUP_TMP_FILE);
return CW_TRUE;
}
/*
* CWWTPCheckVersion - checks if we are already updated.
*/
CWBool CWWTPCheckVersion(CWVendorWumValues * wumPayload)
{
int ret = CW_FALSE;
if (wumPayload->_major_v_ > WTP_VERSION_MAJOR)
ret = CW_TRUE;
else if (wumPayload->_major_v_ == WTP_VERSION_MAJOR) {
if (wumPayload->_minor_v_ > WTP_VERSION_MINOR)
ret = CW_TRUE;
else if (wumPayload->_minor_v_ == WTP_VERSION_MINOR) {
if (wumPayload->_revision_v_ > WTP_VERSION_REVISION)
ret = CW_TRUE;
}
}
return ret;
}
CWBool StartWUA()
{
int pid, fd;
struct flock fl;
/* The following lock in set just for synchronization purposes */
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = getpid();
fd = open(WTP_LOCK_FILE, O_CREAT | O_WRONLY, S_IRWXU);
fcntl(fd, F_SETLKW, &fl); /* F_GETLK, F_SETLK, F_SETLKW */
pid = fork();
if (pid == 0) {
execl(WUA_BIN, WUA_BIN, CUP_TMP_FILE, NULL);
exit(EXIT_FAILURE);
} else if (pid < 0) {
CWLog("Can't fork!");
close(fd);
return CW_FALSE;
}
return CW_TRUE;
}
/*
* Returns CW_TRUE if the required space is available on the
* filesystem where the /tmp dir is mounted.
*/
CWBool check_free_space(int bytes)
{
struct statvfs diskStat;
if (statvfs("/tmp", &diskStat) != 0) {
CWLog("Can't stat filesystem!\n");
return CW_FALSE;
}
if (diskStat.f_bsize * diskStat.f_bfree > bytes)
return CW_TRUE;
return CW_FALSE;
}
CWBool CWWTPSaveWUMValues(CWVendorWumValues * wumPayload, CWProtocolResultCode * resultCode)
{
/* guards on input values */
if (wumPayload == NULL) {
return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
}
*resultCode = CW_PROTOCOL_SUCCESS;
switch (wumPayload->type) {
case WTP_VERSION_REQUEST:
wumPayload->type = WTP_VERSION_RESPONSE;
wumPayload->_major_v_ = WTP_VERSION_MAJOR;
wumPayload->_minor_v_ = WTP_VERSION_MINOR;
wumPayload->_revision_v_ = WTP_VERSION_REVISION;
break;
case WTP_UPDATE_REQUEST:
/* Check if update can be performed */
CWLog("Received Update Request - Version %d.%d.%d",
wumPayload->_major_v_, wumPayload->_minor_v_, wumPayload->_revision_v_);
wumPayload->type = WTP_UPDATE_RESPONSE;
if (!CWWTPCheckVersion(wumPayload)) {
CWLog("WTP already up to date.\n");
*resultCode = CW_PROTOCOL_FAILURE;
} else if (!check_free_space(wumPayload->_pack_size_)) {
CWLog("No disk space available.\n");
*resultCode = CW_PROTOCOL_FAILURE;
} else if (WUMPrepareForUpdate(wumPayload->_pack_size_) == CW_FALSE) {
*resultCode = CW_PROTOCOL_FAILURE;
}
break;
case WTP_CUP_FRAGMENT:
wumPayload->type = WTP_CUP_ACK;
if (!WUMStoreFragment(wumPayload)) {
*resultCode = CW_PROTOCOL_FAILURE;
}
/* if this is the last fragment, close temp file and
* pass to the READY state. */
if (WUMIsComplete()) {
WUMCloseFile();
}
break;
case WTP_COMMIT_UPDATE:
wumPayload->type = WTP_COMMIT_ACK;
/* Check if we are in the correct state */
if (wumState.state != WUM_STATE_READY) {
*resultCode = CW_PROTOCOL_FAILURE;
}
/* Start the Update Agent */
StartWUA();
/* Remember to exit after sending the WTP_COMMIT_ACK */
WTPExitOnUpdateCommit = CW_TRUE;
break;
case WTP_CANCEL_UPDATE_REQUEST:
wumPayload->type = WTP_CANCEL_UPDATE_RESPONSE;
if (wumState.state == WUM_STATE_BUSY) {
/* Accepting fragments */
WUMCloseFile();
if (!remove(CUP_TMP_FILE)) {
CWLog("Error while removing cup tmp file.");
}
} else if (wumState.state == WUM_STATE_READY) {
if (!remove(CUP_TMP_FILE)) {
CWLog("Error while removing cup tmp file.");
}
}
wumState.state = WUM_STATE_WAIT;
}
CWLog("Saved WUM Vendor Payload...");
return CW_TRUE;
}
CWBool CWWTPSaveUCIValues(CWVendorUciValues * uciPayload, CWProtocolResultCode * resultCode)
{
if (uciPayload == NULL) {
return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
}
*resultCode = CW_PROTOCOL_SUCCESS;
struct sockaddr_in serv_addr;
int sendSock, slen = sizeof(serv_addr), responseSize, responseCode;
unsigned int ArgsSize, response = 0, ArgsSizeNet;
char *bufferMessage;
if ((sendSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
CWLog("[CWSaveUCIValues]: Error on creation of socket.");
return CWErrorRaise(CW_ERROR_GENERAL, NULL);
}
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(UCI_SERVER_PORT);
if (inet_aton("127.0.0.1", &serv_addr.sin_addr) == 0) {
CWLog("[CWSaveUCIValues]: Error on aton function.");
close(sendSock);
return CWErrorRaise(CW_ERROR_GENERAL, NULL);
}
if (uciPayload->commandArgs == NULL)
ArgsSize = 0;
else
ArgsSize = strlen(uciPayload->commandArgs);
if ((bufferMessage = malloc(ArgsSize + sizeof(unsigned char) + sizeof(unsigned int))) != NULL) {
memcpy(bufferMessage, &(uciPayload->command), sizeof(unsigned char)); /* First Field */
ArgsSizeNet = htonl(ArgsSize);
memcpy(bufferMessage + sizeof(unsigned char), &ArgsSizeNet, sizeof(unsigned int)); /* Second Field */
if (uciPayload->commandArgs != NULL)
memcpy(bufferMessage + (sizeof(unsigned char) + sizeof(unsigned int)), uciPayload->commandArgs, ArgsSize); /* Third Field */
/*Send conf request to uci daemon */
if (sendto(sendSock, bufferMessage, sizeof(unsigned char), 0, (struct sockaddr *)&serv_addr, slen) < 0) {
CWLog("[CWSaveUCIValues]: Error on sendto function.");
close(sendSock);
CW_FREE_OBJECT(bufferMessage);
return CWErrorRaise(CW_ERROR_GENERAL, NULL);
}
if (recvfrom
(sendSock, &response, sizeof(unsigned int), 0, (struct sockaddr *)&serv_addr,
(socklen_t *) & slen) < 0) {
CWLog("[CWSaveUCIValues]: Error on recvfrom function.");
close(sendSock);
CW_FREE_OBJECT(bufferMessage);
return CWErrorRaise(CW_ERROR_GENERAL, NULL);
}
if (!ntohl(response)) {
CWLog("[CWSaveUCIValues]: Error on recvfrom function.");
close(sendSock);
CW_FREE_OBJECT(bufferMessage);
return CWErrorRaise(CW_ERROR_GENERAL, NULL);
}
if (sendto
(sendSock, bufferMessage + sizeof(unsigned char), sizeof(unsigned int), 0,
(struct sockaddr *)&serv_addr, slen) < 0) {
CWLog("[CWSaveUCIValues]: Error on sendto function.");
close(sendSock);
CW_FREE_OBJECT(bufferMessage);
return CWErrorRaise(CW_ERROR_GENERAL, NULL);
}
if (recvfrom
(sendSock, &response, sizeof(unsigned int), 0, (struct sockaddr *)&serv_addr,
(socklen_t *) & slen) < 0) {
CWLog("[CWSaveUCIValues]: Error on recvfrom function.");
close(sendSock);
CW_FREE_OBJECT(bufferMessage);
return CWErrorRaise(CW_ERROR_GENERAL, NULL);
}
if (!ntohl(response)) {
CWLog("[CWSaveUCIValues]: Error on recvfrom function.");
close(sendSock);
CW_FREE_OBJECT(bufferMessage);
return CWErrorRaise(CW_ERROR_GENERAL, NULL);
}
if (ArgsSize > 0) {
if (sendto
(sendSock, bufferMessage + sizeof(unsigned char) + sizeof(unsigned int), ArgsSize, 0,
(struct sockaddr *)&serv_addr, slen) < 0) {
CWLog("[CWSaveUCIValues]: Error on sendto function.");
close(sendSock);
CW_FREE_OBJECT(bufferMessage);
return CWErrorRaise(CW_ERROR_GENERAL, NULL);
}
if (recvfrom
(sendSock, &response, sizeof(unsigned int), 0, (struct sockaddr *)&serv_addr,
(socklen_t *) & slen) < 0) {
CWLog("[CWSaveUCIValues]: Error on recvfrom function.");
close(sendSock);
CW_FREE_OBJECT(bufferMessage);
return CWErrorRaise(CW_ERROR_GENERAL, NULL);
}
if (!ntohl(response)) {
CWLog("[CWSaveUCIValues]: Error on recvfrom function.");
close(sendSock);
CW_FREE_OBJECT(bufferMessage);
return CWErrorRaise(CW_ERROR_GENERAL, NULL);
}
}
} else {
CWLog("[CWSaveUCIValues]: Error on malloc function.");
close(sendSock);
CW_FREE_OBJECT(bufferMessage);
return CWErrorRaise(CW_ERROR_GENERAL, NULL);
}
/*Receive result code from uci daemon */
if (recvfrom
(sendSock, &responseCode, sizeof(unsigned int), 0, (struct sockaddr *)&serv_addr,
(socklen_t *) & slen) < 0) {
CWLog("[CWSaveUCIValues]: Error on recvfrom function.");
close(sendSock);
CW_FREE_OBJECT(bufferMessage);
return CWErrorRaise(CW_ERROR_GENERAL, NULL);
}
response = htonl(1);
if (sendto(sendSock, &response, sizeof(unsigned int), 0, (struct sockaddr *)&serv_addr, slen) < 0) {
CWLog("[CWSaveUCIValues]: Error on sendto function.");
close(sendSock);
CW_FREE_OBJECT(bufferMessage);
return CWErrorRaise(CW_ERROR_GENERAL, NULL);
}
responseCode = ntohl(responseCode);
if (responseCode != 0)
/*If we have an error */
*resultCode = CW_PROTOCOL_FAILURE;
else {
/*OK, that's a go... receive response string (if we have it) */
/*Receive response length from uci daemon */
if (recvfrom
(sendSock, &responseSize, sizeof(unsigned int), 0, (struct sockaddr *)&serv_addr,
(socklen_t *) & slen) < 0) {
CWLog("[CWSaveUCIValues]: Error on recvfrom function.");
close(sendSock);
CW_FREE_OBJECT(bufferMessage);
return CWErrorRaise(CW_ERROR_GENERAL, NULL);
}
if (sendto(sendSock, &response, sizeof(unsigned int), 0, (struct sockaddr *)&serv_addr, slen) < 0) {
CWLog("[CWSaveUCIValues]: Error on sendto function.");
close(sendSock);
CW_FREE_OBJECT(bufferMessage);
return CWErrorRaise(CW_ERROR_GENERAL, NULL);
}
responseSize = ntohl(responseSize);
if (responseSize > 0) {
CW_FREE_OBJECT(bufferMessage);
/*Fill buffer for response */
if ((bufferMessage = malloc(responseSize * sizeof(unsigned char))) != NULL) {
/*Receive from uci daemon the response string */
if (recvfrom
(sendSock, bufferMessage, sizeof(unsigned char) * responseSize, 0,
(struct sockaddr *)&serv_addr, (socklen_t *) & slen) < 0) {
CWLog("[CWSaveUCIValues]: Error on recvfrom function.");
close(sendSock);
CW_FREE_OBJECT(bufferMessage);
return CWErrorRaise(CW_ERROR_GENERAL, NULL);
}
if (sendto
(sendSock, &response, sizeof(unsigned int), 0, (struct sockaddr *)&serv_addr,
slen) < 0) {
CWLog("[CWSaveUCIValues]: Error on sendto function.");
close(sendSock);
CW_FREE_OBJECT(bufferMessage);
return CWErrorRaise(CW_ERROR_GENERAL, NULL);
}
/*Copy the buffer in the uci payload structure */
CW_CREATE_STRING_ERR(uciPayload->response, responseSize,
return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);
);
memcpy(uciPayload->response, bufferMessage, responseSize);
uciPayload->response[responseSize] = '\0';
} else {
CWLog("[CWSaveUCIValues]: Error on malloc function.");
close(sendSock);
return CWErrorRaise(CW_ERROR_GENERAL, NULL);
}
} else {
/*If response is empty, set it to NULL (needed after, when the response is built) */
uciPayload->response = NULL;
}
}
CWLog("Saved UCI Vendor Payload...");
close(sendSock);
CW_FREE_OBJECT(bufferMessage);
return CW_TRUE;
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。