1 1.1 christos /* 2 1.1 christos * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy) 3 1.1 christos * Copyright (c) 2005 - 2008 CACE Technologies, Davis (California) 4 1.1 christos * All rights reserved. 5 1.1 christos * 6 1.1 christos * Redistribution and use in source and binary forms, with or without 7 1.1 christos * modification, are permitted provided that the following conditions 8 1.1 christos * are met: 9 1.1 christos * 10 1.1 christos * 1. Redistributions of source code must retain the above copyright 11 1.1 christos * notice, this list of conditions and the following disclaimer. 12 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 christos * notice, this list of conditions and the following disclaimer in the 14 1.1 christos * documentation and/or other materials provided with the distribution. 15 1.1 christos * 3. Neither the name of the Politecnico di Torino, CACE Technologies 16 1.1 christos * nor the names of its contributors may be used to endorse or promote 17 1.1 christos * products derived from this software without specific prior written 18 1.1 christos * permission. 19 1.1 christos * 20 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 1.1 christos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 1.1 christos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 1.1 christos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 1.1 christos * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 1.1 christos * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 1.1 christos * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 1.1 christos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 1.1 christos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 1.1 christos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 1.1 christos * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 1.1 christos * 32 1.1 christos */ 33 1.1 christos 34 1.1 christos #include <config.h> 35 1.1 christos 36 1.1 christos #include <string.h> /* for strlen(), ... */ 37 1.1 christos #include <stdlib.h> /* for malloc(), free(), ... */ 38 1.1 christos #include <stdarg.h> /* for functions with variable number of arguments */ 39 1.1 christos #include <errno.h> /* for the errno variable */ 40 1.1 christos #include "sockutils.h" 41 1.1 christos #include "rpcap-protocol.h" 42 1.1 christos #include <pcap/pcap.h> 43 1.1 christos 44 1.2 christos #include "portability.h" 45 1.2 christos 46 1.1 christos /* 47 1.1 christos * This file contains functions used both by the rpcap client and the 48 1.1 christos * rpcap daemon. 49 1.1 christos */ 50 1.1 christos 51 1.1 christos /* 52 1.1 christos * This function sends a RPCAP error to our peer. 53 1.1 christos * 54 1.1 christos * It has to be called when the main program detects an error. 55 1.1 christos * It will send to our peer the 'buffer' specified by the user. 56 1.1 christos * This function *does not* request a RPCAP CLOSE connection. A CLOSE 57 1.1 christos * command must be sent explicitly by the program, since we do not know 58 1.1 christos * whether the error can be recovered in some way or if it is a 59 1.1 christos * non-recoverable one. 60 1.1 christos * 61 1.1 christos * \param sock: the socket we are currently using. 62 1.1 christos * 63 1.2 christos * \param ssl: if compiled with openssl, the optional ssl handler to use with the above socket. 64 1.2 christos * 65 1.1 christos * \param ver: the protocol version we want to put in the reply. 66 1.1 christos * 67 1.1 christos * \param errcode: a integer which tells the other party the type of error 68 1.1 christos * we had. 69 1.1 christos * 70 1.1 christos * \param error: an user-allocated (and '0' terminated) buffer that contains 71 1.1 christos * the error description that has to be transmitted to our peer. The 72 1.1 christos * error message cannot be longer than PCAP_ERRBUF_SIZE. 73 1.1 christos * 74 1.1 christos * \param errbuf: a pointer to a user-allocated buffer (of size 75 1.1 christos * PCAP_ERRBUF_SIZE) that will contain the error message (in case there 76 1.1 christos * is one). It could be network problem. 77 1.1 christos * 78 1.1 christos * \return '0' if everything is fine, '-1' if some errors occurred. The 79 1.1 christos * error message is returned in the 'errbuf' variable. 80 1.1 christos */ 81 1.1 christos int 82 1.3 christos rpcap_senderror(PCAP_SOCKET sock, SSL *ssl, uint8 ver, unsigned short errcode, const char *error, char *errbuf) 83 1.1 christos { 84 1.1 christos char sendbuf[RPCAP_NETBUF_SIZE]; /* temporary buffer in which data to be sent is buffered */ 85 1.1 christos int sendbufidx = 0; /* index which keeps the number of bytes currently buffered */ 86 1.1 christos uint16 length; 87 1.1 christos 88 1.1 christos length = (uint16)strlen(error); 89 1.1 christos 90 1.1 christos if (length > PCAP_ERRBUF_SIZE) 91 1.1 christos length = PCAP_ERRBUF_SIZE; 92 1.1 christos 93 1.1 christos rpcap_createhdr((struct rpcap_header *) sendbuf, ver, RPCAP_MSG_ERROR, errcode, length); 94 1.1 christos 95 1.1 christos if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, 96 1.1 christos RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE)) 97 1.1 christos return -1; 98 1.1 christos 99 1.1 christos if (sock_bufferize(error, length, sendbuf, &sendbufidx, 100 1.1 christos RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE)) 101 1.1 christos return -1; 102 1.1 christos 103 1.2 christos if (sock_send(sock, ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) < 0) 104 1.1 christos return -1; 105 1.1 christos 106 1.1 christos return 0; 107 1.1 christos } 108 1.1 christos 109 1.1 christos /* 110 1.1 christos * This function fills in a structure of type rpcap_header. 111 1.1 christos * 112 1.1 christos * It is provided just because the creation of an rpcap header is a common 113 1.1 christos * task. It accepts all the values that appears into an rpcap_header, and 114 1.1 christos * it puts them in place using the proper hton() calls. 115 1.1 christos * 116 1.1 christos * \param header: a pointer to a user-allocated buffer which will contain 117 1.1 christos * the serialized header, ready to be sent on the network. 118 1.1 christos * 119 1.1 christos * \param ver: a value (in the host byte order) which will be placed into the 120 1.1 christos * header.ver field and that represents the protocol version number of the 121 1.1 christos * current message. 122 1.1 christos * 123 1.1 christos * \param type: a value (in the host byte order) which will be placed into the 124 1.1 christos * header.type field and that represents the type of the current message. 125 1.1 christos * 126 1.1 christos * \param value: a value (in the host byte order) which will be placed into 127 1.1 christos * the header.value field and that has a message-dependent meaning. 128 1.1 christos * 129 1.1 christos * \param length: a value (in the host by order) which will be placed into 130 1.1 christos * the header.length field, representing the payload length of the message. 131 1.1 christos * 132 1.1 christos * \return Nothing. The serialized header is returned into the 'header' 133 1.1 christos * variable. 134 1.1 christos */ 135 1.1 christos void 136 1.1 christos rpcap_createhdr(struct rpcap_header *header, uint8 ver, uint8 type, uint16 value, uint32 length) 137 1.1 christos { 138 1.1 christos memset(header, 0, sizeof(struct rpcap_header)); 139 1.1 christos 140 1.1 christos header->ver = ver; 141 1.1 christos header->type = type; 142 1.1 christos header->value = htons(value); 143 1.1 christos header->plen = htonl(length); 144 1.1 christos } 145 1.1 christos 146 1.1 christos /* 147 1.1 christos * Convert a message type to a string containing the type name. 148 1.1 christos */ 149 1.1 christos static const char *requests[] = 150 1.1 christos { 151 1.1 christos NULL, /* not a valid message type */ 152 1.1 christos "RPCAP_MSG_ERROR", 153 1.1 christos "RPCAP_MSG_FINDALLIF_REQ", 154 1.1 christos "RPCAP_MSG_OPEN_REQ", 155 1.1 christos "RPCAP_MSG_STARTCAP_REQ", 156 1.1 christos "RPCAP_MSG_UPDATEFILTER_REQ", 157 1.1 christos "RPCAP_MSG_CLOSE", 158 1.1 christos "RPCAP_MSG_PACKET", 159 1.1 christos "RPCAP_MSG_AUTH_REQ", 160 1.1 christos "RPCAP_MSG_STATS_REQ", 161 1.1 christos "RPCAP_MSG_ENDCAP_REQ", 162 1.1 christos "RPCAP_MSG_SETSAMPLING_REQ", 163 1.1 christos }; 164 1.1 christos #define NUM_REQ_TYPES (sizeof requests / sizeof requests[0]) 165 1.1 christos 166 1.1 christos static const char *replies[] = 167 1.1 christos { 168 1.1 christos NULL, 169 1.1 christos NULL, /* this would be a reply to RPCAP_MSG_ERROR */ 170 1.1 christos "RPCAP_MSG_FINDALLIF_REPLY", 171 1.1 christos "RPCAP_MSG_OPEN_REPLY", 172 1.1 christos "RPCAP_MSG_STARTCAP_REPLY", 173 1.1 christos "RPCAP_MSG_UPDATEFILTER_REPLY", 174 1.1 christos NULL, /* this would be a reply to RPCAP_MSG_CLOSE */ 175 1.1 christos NULL, /* this would be a reply to RPCAP_MSG_PACKET */ 176 1.1 christos "RPCAP_MSG_AUTH_REPLY", 177 1.1 christos "RPCAP_MSG_STATS_REPLY", 178 1.1 christos "RPCAP_MSG_ENDCAP_REPLY", 179 1.1 christos "RPCAP_MSG_SETSAMPLING_REPLY", 180 1.1 christos }; 181 1.1 christos #define NUM_REPLY_TYPES (sizeof replies / sizeof replies[0]) 182 1.1 christos 183 1.1 christos const char * 184 1.1 christos rpcap_msg_type_string(uint8 type) 185 1.1 christos { 186 1.1 christos if (type & RPCAP_MSG_IS_REPLY) { 187 1.1 christos type &= ~RPCAP_MSG_IS_REPLY; 188 1.1 christos if (type >= NUM_REPLY_TYPES) 189 1.1 christos return NULL; 190 1.1 christos return replies[type]; 191 1.1 christos } else { 192 1.1 christos if (type >= NUM_REQ_TYPES) 193 1.1 christos return NULL; 194 1.1 christos return requests[type]; 195 1.1 christos } 196 1.1 christos } 197