⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 icmp-socket.c

📁 Serveez是一个服务器框架
💻 C
📖 第 1 页 / 共 2 页
字号:
#endif /* ENABLE_DEBUG */  return ICMP_ERROR;}/* * Default reader for ICMP sockets. The sender is stored within  * @code{sock->remote_addr} and @code{sock->remote_port} afterwards. */intsvz_icmp_read_socket (svz_socket_t *sock){  int num_read;  socklen_t len;  struct sockaddr_in sender;  int trunc;  len = sizeof (struct sockaddr_in);  /* Receive data. */  if (!(sock->flags & SOCK_FLAG_CONNECTED))    {      num_read = recvfrom (sock->sock_desc, svz_icmp_buffer, 			   sizeof (svz_icmp_buffer), 0, 			   (struct sockaddr *) &sender, &len);    }  else    {      num_read = recv (sock->sock_desc, svz_icmp_buffer, 		       sizeof (svz_icmp_buffer), 0);    }  /* Valid packet data arrived. */  if (num_read > 0)    {#if 0      svz_hexdump (stdout, "icmp packet received", sock->sock_desc,		   svz_icmp_buffer, num_read, 0);#endif      sock->last_recv = time (NULL);      if (!(sock->flags & SOCK_FLAG_FIXED))        {	  sock->remote_addr = sender.sin_addr.s_addr;	}#if ENABLE_DEBUG      svz_log (LOG_DEBUG, "icmp: recv%s: %s (%u bytes)\n",	       sock->flags & SOCK_FLAG_CONNECTED ? "" : "from",	       svz_inet_ntoa (sock->remote_addr), num_read);#endif /* ENABLE_DEBUG */      /*        * Check the ICMP packet and put the packet load only into the       * receive buffer of the socket structure.       */      trunc = svz_icmp_check_packet (sock, (svz_uint8_t *) svz_icmp_buffer, 				     num_read);      if (trunc >= 0)	{	  num_read -= trunc;	  if (num_read > sock->recv_buffer_size - sock->recv_buffer_fill)	    {	      svz_log (LOG_ERROR, 		       "receive buffer overflow on icmp socket %d\n",		       sock->sock_desc);	      return -1;	    }  	  memcpy (sock->recv_buffer + sock->recv_buffer_fill,		  svz_icmp_buffer + trunc, num_read);	  sock->recv_buffer_fill += num_read;	  /* Check access lists. */	  if (svz_sock_check_access (sock, sock) < 0)	    return 0;	  if (sock->check_request)	    sock->check_request (sock);	}      else if (trunc == ICMP_DISCONNECT)	{	  return -1;	}    }  /* Some error occurred. */  else    {      svz_log (LOG_ERROR, "icmp: recv%s: %s\n", 	       sock->flags & SOCK_FLAG_CONNECTED ? "" : "from", NET_ERROR);      if (svz_errno != SOCK_UNAVAILABLE)	return -1;    }  return 0;}/* * The default ICMP write callback is called whenever the socket  * descriptor has been @code{select()}'ed or @code{poll()}'ed to be ready for  * sending. */intsvz_icmp_write_socket (svz_socket_t *sock){  int num_written;  unsigned do_write;  char *p;  socklen_t len;  struct sockaddr_in receiver;  /* Return here if there is nothing to do. */  if (sock->send_buffer_fill <= 0)    return 0;  len = sizeof (struct sockaddr_in);  receiver.sin_family = AF_INET;  /* Get destination address and data length from send buffer. */  p = sock->send_buffer;  memcpy (&do_write, p, sizeof (do_write));  p += sizeof (do_write);  memcpy (&receiver.sin_addr.s_addr, p, sizeof (sock->remote_addr));  p += sizeof (sock->remote_addr);  memcpy (&receiver.sin_port, p, sizeof (sock->remote_port));  p += sizeof (sock->remote_port);  assert ((int) do_write <= sock->send_buffer_fill);  /* If socket is `connect ()'ed use `send ()' instead of `sendto ()'. */  if (!(sock->flags & SOCK_FLAG_CONNECTED))    {      num_written = sendto (sock->sock_desc, p,			    do_write - (p - sock->send_buffer),			    0, (struct sockaddr *) &receiver, len);    }  else    {      num_written = send (sock->sock_desc, p,			  do_write - (p - sock->send_buffer), 0);    }  /* Some error occurred while sending. */  if (num_written < 0)    {      svz_log (LOG_ERROR, "icmp: send%s: %s\n", 	       sock->flags & SOCK_FLAG_CONNECTED ? "" : "to", NET_ERROR);      if (svz_errno == SOCK_UNAVAILABLE)        num_written = 0;    }  /* Packet data could be transmitted. */  else    {      sock->last_send = time (NULL);      if ((unsigned) sock->send_buffer_fill > do_write)        {          memmove (sock->send_buffer,                    sock->send_buffer + do_write,                   sock->send_buffer_fill - do_write);        }      sock->send_buffer_fill -= do_write;    }#if ENABLE_DEBUG  svz_log (LOG_DEBUG, "icmp: send%s: %s (%u bytes)\n",	   sock->flags & SOCK_FLAG_CONNECTED ? "" : "to",	   svz_inet_ntoa (receiver.sin_addr.s_addr),	   do_write - (p - sock->send_buffer));#endif /* ENABLE_DEBUG */  return num_written < 0 ? -1 : 0;}/* * If you are calling this function we will send an empty ICMP packet * signaling that this connection is going down soon. */intsvz_icmp_send_control (svz_socket_t *sock, svz_uint8_t type){  static char *buffer = svz_icmp_buffer;  svz_icmp_header_t hdr;  unsigned len;  int ret = 0;  len = sizeof (len);  memcpy (&buffer[len], &sock->remote_addr, sizeof (sock->remote_addr));  len += sizeof (sock->remote_addr);  memcpy (&buffer[len], &sock->remote_port, sizeof (sock->remote_port));  len += sizeof (sock->remote_port);  hdr.type = sock->itype;  hdr.code = type;  hdr.checksum = svz_raw_ip_checksum (NULL, 0);  hdr.ident = (unsigned short) (getpid () + sock->id);  hdr.sequence = sock->send_seq;  hdr.port = sock->remote_port;  memcpy (&buffer[len], svz_icmp_put_header (&hdr), ICMP_HEADER_SIZE);  len += ICMP_HEADER_SIZE;  memcpy (buffer, &len, sizeof (len));  if ((ret = svz_sock_write (sock, buffer, len)) == -1)    {      sock->flags |= SOCK_FLAG_KILLED;    }  return ret;}/* * Send a given buffer @var{buf} with length @var{length} via this ICMP  * socket. If the length argument supersedes the maximum ICMP message * size the buffer is split into smaller packets. */intsvz_icmp_write (svz_socket_t *sock, char *buf, int length){  static char *buffer = svz_icmp_buffer;  svz_icmp_header_t hdr;  unsigned len, size;  int ret = 0;  /* Return if the socket has already been killed. */  if (sock->flags & SOCK_FLAG_KILLED)    return 0;  while (length)    {      /*        * Put the data length and destination address in front        * of each packet.        */      len = sizeof (len);      memcpy (&buffer[len], &sock->remote_addr, sizeof (sock->remote_addr));      len += sizeof (sock->remote_addr);      memcpy (&buffer[len], &sock->remote_port, sizeof (sock->remote_port));      len += sizeof (sock->remote_port);      if ((size = length) > ICMP_MSG_SIZE)	size = ICMP_MSG_SIZE;      /* Create ICMP header and put it in front of packet load. */      hdr.type = sock->itype;      hdr.code = ICMP_SERVEEZ_DATA;      hdr.checksum = svz_raw_ip_checksum ((svz_uint8_t *) buf, size);      hdr.ident = (unsigned short) (getpid () + sock->id);      hdr.sequence = sock->send_seq++;      hdr.port = sock->remote_port;      memcpy (&buffer[len], svz_icmp_put_header (&hdr), ICMP_HEADER_SIZE);      len += ICMP_HEADER_SIZE;      /* Copy the given buffer. */      memcpy (&buffer[len], buf, size);      len += size;      /* Put chunk length to buffer. */      memcpy (buffer, &len, sizeof (len));      buf += size;      length -= size;      /* Actually send the data or put it into the send buffer queue. */      if ((ret = svz_sock_write (sock, buffer, len)) == -1)        {          sock->flags |= SOCK_FLAG_KILLED;          break;        }    }  return ret;}/* * Put a formatted string to the icmp socket @var{sock}. Packet length and * destination address are additionally saved to the send buffer. The * destination is taken from @code{sock->remote_addr}. Furthermore a valid * icmp header is stored in front of the actual packet data. */intsvz_icmp_printf (svz_socket_t *sock, const char *fmt, ...){  va_list args;  static char buffer[VSNPRINTF_BUF_SIZE];  unsigned len;  /* return if there is nothing to do */  if (sock->flags & SOCK_FLAG_KILLED)    return 0;  /* save actual packet load */  va_start (args, fmt);  len = svz_vsnprintf (buffer, VSNPRINTF_BUF_SIZE, fmt, args);  va_end (args);    return svz_icmp_write (sock, buffer, len);}/* * Default @code{check_request()} callback for ICMP sockets. */intsvz_icmp_check_request (svz_socket_t *sock){  int n;  svz_server_t *server;  if (sock->data == NULL && sock->handle_request == NULL)    return -1;  /*    * If there is a valid `handle_request' callback (dedicated icmp    * connection) call it. This kind of behaviour is due to a socket    * creation via 'icmp_connect' (s.b.) and setting up a static    * `handle_request' callback.   */  if (sock->handle_request)    {      if (sock->handle_request (sock, sock->recv_buffer,                                sock->recv_buffer_fill))        return -1;      sock->recv_buffer_fill = 0;      return 0;    }  /* Go through all icmp servers on this server socket. */  svz_array_foreach (sock->data, server, n)    {      sock->cfg = server->cfg;            if (server->handle_request)        {          if (!server->handle_request (sock, sock->recv_buffer,                                       sock->recv_buffer_fill))            {              sock->recv_buffer_fill = 0;              break;            }        }    }  /* Check if any server processed this packet. */  if (sock->recv_buffer_fill)    {#if ENABLE_DEBUG      svz_log (LOG_DEBUG, "rejecting icmp packet on socket %d\n",	       sock->sock_desc);#endif      sock->recv_buffer_fill = 0;    }  sock->cfg = NULL;  return 0;}/* * This function creates an ICMP socket for receiving and sending. * Return @code{NULL} on errors, otherwise an enqueued socket structure. */svz_socket_t *svz_icmp_connect (unsigned long host, unsigned short port,		  unsigned char type){  SOCKET sockfd;  svz_socket_t *sock;  /* Create a client socket. */  if ((sockfd = svz_socket_create (PROTO_ICMP)) == (SOCKET) -1)      return NULL;  /* Try to connect to the server. Does it make sense for ICMP ? */  if (svz_socket_connect (sockfd, host, port) == -1)     return NULL;  /* Create socket structure and enqueue it. */  if ((sock = svz_sock_alloc ()) == NULL)    {      closesocket (sockfd);      return NULL;    }  svz_sock_resize_buffers (sock, ICMP_BUF_SIZE, ICMP_BUF_SIZE);  svz_sock_unique_id (sock);  sock->sock_desc = sockfd;  sock->flags |= (SOCK_FLAG_SOCK | SOCK_FLAG_CONNECTED | SOCK_FLAG_FIXED);  sock->itype = type;  svz_sock_enqueue (sock);  svz_sock_intern_connection_info (sock);  /* Put foreign address here. */  sock->remote_addr = host;  sock->remote_port = (unsigned short) sock->id;  sock->read_socket = svz_icmp_read_socket;  sock->write_socket = svz_icmp_write_socket;  sock->check_request = svz_icmp_check_request;  /* Finally send a connection message. */  svz_icmp_send_control (sock, ICMP_SERVEEZ_CONNECT);  svz_sock_connections++;  return sock;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -