📄 comm.c
字号:
header.message); xdrrec_endofrecord(&connection->xdrs, 1); return(-1); } if (err == NDMP_NO_ERR && connection->msginfo.handler->xdr_reply && reply) { if (!(*connection->msginfo.handler->xdr_reply)(&connection->xdrs, reply)) { Error(LOG_ERR, "sending message 0x%x: encoding reply body.\n", header.message); xdrrec_endofrecord(&connection->xdrs, 1); return(-1); } } xdrrec_endofrecord(&connection->xdrs, 1); return(0);}voidndmpFreeMessage(NdmpConnection connectionHandle){ Connection* connection = (Connection *)connectionHandle; Debug(DBG_CAT_COMM|DBG_FOC_FLOW, "ndmpFreeMessage: message:0x%x\n", connection->msginfo.hdr.message); if (connection->msginfo.handler == 0 || connection->msginfo.body == 0) return; connection->xdrs.x_op = XDR_FREE; if (connection->msginfo.hdr.message_type == NDMP_MESSAGE_REQUEST) { if (connection->msginfo.handler->xdr_request) (*connection->msginfo.handler->xdr_request)(&connection->xdrs, connection->msginfo.body); } else { if (connection->msginfo.handler->xdr_reply) (*connection->msginfo.handler->xdr_reply)(&connection->xdrs, connection->msginfo.body); } (void)free((void*)connection->msginfo.body); connection->msginfo.body = 0;}/* * ndmpGetFd * * Returns the connection file descriptor. * * Parameters: * connectionHandle (input) - connection handle * * Returns: * >=0 - file descriptor. * -1 - connection not open. */intndmpGetFd(NdmpConnection connectionHandle){ return(((Connection *)connectionHandle)->sock);}/* * ndmpSetClientData * * This function provides a means for the library client to provide * a pointer to some user data structure that is retrievable by * each message handler via ndmpGetClientData. * * Parameters: * connectionHandle (input) - connection handle. * clientData (input) - user data pointer. * * Returns: * void */voidndmpSetClientData(NdmpConnection connectionHandle, void* clientData){ ((Connection *)connectionHandle)->clientData = clientData;}/* * ndmpGetClientData * * This function provides a means for the library client to provide * a pointer to some user data structure that is retrievable by * each message handler via ndmpGetClientData. * * Parameters: * connectionHandle (input) - connection handle. * * Returns: * client data pointer. */void*ndmpGetClientData(NdmpConnection connectionHandle){ return(((Connection *)connectionHandle)->clientData);}/* * ndmpSetVersion * Sets the NDMP protocol version to be used on the connection. * * Parameters: * connectionHandle (input) - connection handle. * version (input) - protocol version. * * Returns: * void */voidndmpSetVersion(NdmpConnection connectionHandle, u_short version){ ((Connection *)connectionHandle)->version = version;}/* * ndmpGetVersion * Gets the NDMP protocol version in use on the connection. * * Parameters: * connectionHandle (input) - connection handle. * version (input) - protocol version. * * Returns: * void */u_shortndmpGetVersion(NdmpConnection connectionHandle){ return(((Connection *)connectionHandle)->version);}/* * ndmpSetAuthorized * Mark the connection as either having been authorized or not. * * Parameters: * connectionHandle (input) - connection handle. * authorized (input) - TRUE or FALSE. * * Returns: * void */voidndmpSetAuthorized(NdmpConnection connectionHandle, bool_t authorized){ ((Connection *)connectionHandle)->authorized = authorized;}u_longlong_tquadToLongLong(ndmp_u_quad quad){ u_longlong_t ull; ull = ((u_longlong_t)quad.high << 32) + quad.low; return(ull);}ndmp_u_quadlongLongToQuad(u_longlong_t ull){ ndmp_u_quad quad; quad.high = (u_long)(ull >> 32); quad.low = (u_long)ull; return(quad);}/* * ndmpCreateMD5Digest * Creates an MD5 digest * * Parameters: * digest (output) - location to store digest. Must be at least 16 bytes. * password (input) - password string. * challenge (input) - 64 bytes of challenge data. * * Returns: * void */voidndmpCreateMD5Digest(char* digest, char* password, char* challenge){ MD5_CTX context; char md5Buf[128]; memset((void*)md5Buf, 0, sizeof(md5Buf)); memcpy((void*)&md5Buf[0], password, strlen(password)); memcpy((void*)&md5Buf[128-strlen(password)], password, strlen(password)); memcpy((void*)&md5Buf[128-strlen(password)-64], challenge, 64); MD5Init(&context); MD5Update(&context, md5Buf, sizeof(md5Buf)); MD5Final(digest, &context);}/************** private functions ****************************************//* * ndmp_readit * * Low level read routine called by the xdrrec library. * * Parameters: * connection (input) - connection pointer. * buf (input) - location to store received data. * len (input) - max number of bytes to read. * * Returns: * >0 - number of bytes received. * -1 - error. */static intndmp_readit(void* connectionHandle, caddr_t buf, int len){ Connection *connection = (Connection *)connectionHandle; Debug(DBG_CAT_COMM|DBG_FOC_DETAIL, "ndmp_readit: len:%d\n", len); len = read(connection->sock, buf, len); if (len <= 0) { /* Connection has been closed. */ connection->eof = TRUE; return(-1); } return(len);}/* * ndmp_writeit * * Low level write routine called by the xdrrec library. * * Parameters: * connection (input) - connection pointer. * buf (input) - location to store received data. * len (input) - max number of bytes to read. * * Returns: * >0 - number of bytes sent. * -1 - error. */static intndmp_writeit(void* connectionHandle, caddr_t buf, int len){ Connection *connection = (Connection *)connectionHandle; register int n; register int cnt; Debug(DBG_CAT_COMM|DBG_FOC_DETAIL, "ndmp_writeit: len:%d\n", len); for(cnt = len; cnt > 0; cnt -= n, buf += n) { if ((n = write(connection->sock, buf, cnt)) < 0) { connection->eof = TRUE; return (-1); } } return(len);}/* * ndmp_recv_msg * * Read the next message. * * Parameters: * connection (input) - connection pointer. * msg (output) - received message. * * Returns: * 0 - Message successfully received. * error number - Message related error. * -1 - Error decoding the message header. */static intndmp_recv_msg(Connection* connection){ bool_t (*xdr_func)(XDR*, ...) = 0; Debug(DBG_CAT_COMM|DBG_FOC_FLOW, "ndmp_recv_msg\n"); /* Decode the header. */ connection->xdrs.x_op = XDR_DECODE; xdrrec_skiprecord(&connection->xdrs); if (!xdr_ndmp_header(&connection->xdrs, &connection->msginfo.hdr)) { return(-1); } /* Lookup info necessary for processing this message. */ if ((connection->msginfo.handler = ndmp_get_handler(connection, connection->msginfo.hdr.message)) == 0) { Error(LOG_ERR, "message 0x%x not supported.\n", connection->msginfo.hdr.message); return(NDMP_NOT_SUPPORTED_ERR); } connection->msginfo.body = 0; if (connection->msginfo.hdr.error != NDMP_NO_ERR) return(0); /* Determine body type */ if (connection->msginfo.hdr.message_type == NDMP_MESSAGE_REQUEST) { if (connection->msginfo.handler->auth_required && !connection->authorized) { Error(LOG_ERR, "processing request 0x%x: connection not authorized.\n", connection->msginfo.hdr.message); return(NDMP_NOT_AUTHORIZED_ERR); } if (connection->msginfo.handler->sizeof_request > 0) { xdr_func = connection->msginfo.handler->xdr_request; if (xdr_func == 0) { Error(LOG_ERR, "processing request 0x%x: no xdr function in handler table.\n", connection->msginfo.hdr.message); return(NDMP_NOT_SUPPORTED_ERR); } connection->msginfo.body = (void *)malloc(connection->msginfo.handler->sizeof_request); if (connection->msginfo.body == 0) { Error(LOG_ERR, "processing request 0x%x: system call (malloc): %s\n", connection->msginfo.hdr.message, strerror(errno)); return(NDMP_NO_MEM_ERR); } memset(connection->msginfo.body, 0, connection->msginfo.handler->sizeof_request); } } else { if (connection->msginfo.handler->sizeof_reply > 0) { xdr_func = connection->msginfo.handler->xdr_reply; if (xdr_func == 0) { Error(LOG_ERR, "processing reply 0x%x: no xdr function in handler table.\n", connection->msginfo.hdr.message); return(NDMP_NOT_SUPPORTED_ERR); } connection->msginfo.body = (void *)malloc(connection->msginfo.handler->sizeof_reply); if (connection->msginfo.body == 0) { Error(LOG_ERR, "processing reply 0x%x: system call (malloc): %s\n", connection->msginfo.hdr.message, strerror(errno)); return(NDMP_NO_MEM_ERR); } memset(connection->msginfo.body, 0, connection->msginfo.handler->sizeof_reply); } } /* Decode message arguments if needed */ if (xdr_func) { if (!(*xdr_func)(&connection->xdrs, connection->msginfo.body)) { Error(LOG_ERR, "processing message 0x%x: error decoding arguments.\n", connection->msginfo.hdr.message); free(connection->msginfo.body); connection->msginfo.body = 0; return(NDMP_XDR_DECODE_ERR); } } return(0);}/* * ndmp_process_messages * * Reads the next message into the stream buffer. * Processes messages until the stream buffer is empty. * * This function processes all data in the stream buffer before returning. * This allows functions like poll() to be used to determine when new * messages have arrived. If only some of the messages in the stream buffer * were processed and then poll was called, poll() could block waiting for * a message that had already been received and read into the stream buffer. * * This function processes both request and reply messages. * Request messages are dispatched using the appropriate function from the * message handling table. * Only one reply messages may be pending receipt at a time. * A reply message, if received, is placed in connection->msginfo * before returning to the caller. * Errors are reported if a reply is received but not expected or if * more than one reply message is received * * Parameters: * connection (input) - connection pointer. * reply_expected (output) - TRUE - a reply message is expected. * FALSE - no reply message is expected and * an error will be reported if a reply * is received. * * Returns: * 2 - 1 or messages successfully processed, error processing reply message. * 1 - 1 or messages successfully processed, reply seen. * 0 - 1 or more messages successfully processed, no reply seen. * -1 - error; connection no longer established. * * Notes: * If the peer is generating a large number of requests, a caller * looking for a reply will be blocked while the requests are handled. * This is because this function does not return until the stream * buffer is empty. * Code needs to be added to allow a return if the stream buffer * is not empty but there is data available on the socket. This will * prevent poll() from blocking and prevent a caller looking for a reply * from getting blocked by a bunch of requests. */static intndmp_process_messages(Connection* connection, bool_t reply_expected){ MsgInfo reply_msginfo; bool_t reply_read = FALSE; bool_t reply_error = FALSE; int err; Debug(DBG_CAT_COMM|DBG_FOC_DETAIL, "ndmp_process_messages: reply_expected:%s\n", reply_expected == TRUE ? "TRUE" : "FALSE"); memset((void *)&reply_msginfo, 0, sizeof(MsgInfo)); do { memset((void *)&connection->msginfo, 0, sizeof(MsgInfo)); if ((err = ndmp_recv_msg(connection)) != NDMP_NO_ERR) { if (connection->eof) { Debug(DBG_CAT_COMM|DBG_FOC_FLOW, "ndmp_process_messages: detected eof\n"); return(-1); } if (err < 1) { Debug(DBG_CAT_COMM|DBG_FOC_DETAIL, "ndmp_process_messages: error decoding header\n"); /* * Error occurred decoding the header. * Don't send a reply since we don't know the message * or if the message was even a request message. * * To be safe, assume that the message was a reply * if a reply was expected. Need to do this to prevent * hanging ndmpSendRequest() waiting for a reply. * Don't set reply_read so that the reply will be * processed if it received later. */ if (reply_read == FALSE) reply_error = TRUE; continue; } if (connection->msginfo.hdr.message_type != NDMP_MESSAGE_REQUEST) { Debug(DBG_CAT_COMM|DBG_FOC_FLOW, "ndmp_process_messages: received reply: 0x%x\n", connection->msginfo.hdr.message); if (reply_expected == 0 || reply_read == TRUE) Error(LOG_ERR, "unexpected reply message: 0x%x.\n", connection->msginfo.hdr.message); ndmpFreeMessage((NdmpConnection)connection); if (reply_read == FALSE) { reply_read = TRUE; reply_error = TRUE; } continue; } Debug(DBG_CAT_COMM|DBG_FOC_FLOW, "ndmp_process_messages: received request: 0x%x\n", connection->msginfo.hdr.message); ndmpSendReply((NdmpConnection)connection, err, 0); ndmpFreeMessage((NdmpConnection)connection); continue; } if (connection->msginfo.hdr.message_type != NDMP_MESSAGE_REQUEST) { Debug(DBG_CAT_COMM|DBG_FOC_FLOW, "ndmp_process_messages: received reply: 0x%x\n", connection->msginfo.hdr.message); if (reply_expected == 0 || reply_read == TRUE) { Error(LOG_ERR, "unexpected reply message: 0x%x.\n", connection->msginfo.hdr.message); ndmpFreeMessage((NdmpConnection)connection); continue; } reply_read = TRUE; reply_msginfo = connection->msginfo; continue; } Debug(DBG_CAT_COMM|DBG_FOC_FLOW, "ndmp_process_messages: received request: 0x%x\n", connection->msginfo.hdr.message); /* * The following needed to catch an improperly constructed * handler table or to deal with an NDMP client that is not * conforming to the negotiated protocol version. */ if (connection->msginfo.handler->func == 0) { Error(LOG_ERR, "No handler for message 0x%x\n", connection->msginfo.hdr.message); ndmpSendReply((NdmpConnection)connection, NDMP_NOT_SUPPORTED_ERR, 0); ndmpFreeMessage((NdmpConnection)connection); continue; } /* * Call the handler function. * The handler will send any necessary reply. */ (*connection->msginfo.handler->func)(connection, connection->msginfo.body); ndmpFreeMessage((NdmpConnection)connection); } while (xdrrec_eof(&connection->xdrs) == FALSE && connection->eof == FALSE); Debug(DBG_CAT_COMM|DBG_FOC_DETAIL, "ndmp_process_messages: no more messages in stream buffer\n"); if (connection->eof == TRUE) { if (reply_msginfo.body) free(reply_msginfo.body); return(-1); } if (reply_error) { if (reply_msginfo.body) free(reply_msginfo.body); return(2); } if (reply_read) { connection->msginfo = reply_msginfo; return(1); } return(0);}/* * ndmp_get_handler * * Return the handler info for the specified NDMP message. * * Parameters: * message (input) - message number. * * Returns: * 0 - message not found. * pointer to handler info. */static NdmpMsgHandler*ndmp_get_handler(Connection* connection, ndmp_message message){ NdmpMsgHandler *handler; for (handler = connection->msgHandlerTbl; handler->message != 0; handler++) { if (handler->message == message && handler->version == connection->version) return(handler); } return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -