1    	// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2    	// vim: ts=8 sw=2 smarttab
3    	/*
4    	 * Ceph - scalable distributed file system
5    	 *
6    	 * Copyright (C) 2011 New Dream Network
7    	 *
8    	 * This is free software; you can redistribute it and/or
9    	 * modify it under the terms of the GNU Lesser General Public
10   	 * License version 2.1, as published by the Free Software
11   	 * Foundation.  See file COPYING.
12   	 *
13   	 */
14   	
15   	#include <arpa/inet.h>
16   	#include <fcntl.h>
17   	#include <sys/socket.h>
18   	#include <sys/un.h>
19   	
20   	#include "common/admin_socket.h"
21   	#include "common/errno.h"
22   	#include "common/safe_io.h"
23   	#include "common/admin_socket_client.h"
24   	
25   	#include "include/compat.h"
26   	#include "include/sock_compat.h"
27   	
28   	using std::ostringstream;
29   	
30   	const char* get_rand_socket_path()
31   	{
32   	  static char *g_socket_path = NULL;
33   	
34   	  if (g_socket_path == NULL) {
35   	    char buf[512];
36   	    const char *tdir = getenv("TMPDIR");
37   	    if (tdir == NULL) {
38   	      tdir = "/tmp";
39   	    }
40   	    snprintf(buf, sizeof(((struct sockaddr_un*)0)->sun_path),
41   		     "%s/perfcounters_test_socket.%ld.%ld",
42   		     tdir, (long int)getpid(), time(NULL));
43   	    g_socket_path = (char*)strdup(buf);
44   	  }
45   	  return g_socket_path;
46   	}
47   	
48   	static std::string asok_connect(const std::string &path, int *fd)
49   	{
(1) Event open_fn: Returning handle opened by "socket_cloexec". [details]
(2) Event assign: Assigning: "socket_fd" = "socket_cloexec(1, SOCK_STREAM, 0)".
Also see events: [noescape][noescape][noescape][assign]
50   	  int socket_fd = socket_cloexec(PF_UNIX, SOCK_STREAM, 0);
(3) Event cond_false: Condition "socket_fd < 0", taking false branch.
51   	  if(socket_fd < 0) {
52   	    int err = errno;
53   	    ostringstream oss;
54   	    oss << "socket(PF_UNIX, SOCK_STREAM, 0) failed: " << cpp_strerror(err);
55   	    return oss.str();
(4) Event if_end: End of if statement.
56   	  }
57   	
58   	  struct sockaddr_un address;
59   	  memset(&address, 0, sizeof(struct sockaddr_un));
60   	  address.sun_family = AF_UNIX;
61   	  snprintf(address.sun_path, sizeof(address.sun_path), "%s", path.c_str());
62   	
(5) Event noescape: Resource "socket_fd" is not freed or pointed-to in function "connect".
(6) Event cond_false: Condition "connect(socket_fd, (sockaddr *)&address, 110U /* sizeof (sockaddr_un) */) != 0", taking false branch.
Also see events: [open_fn][assign][noescape][noescape][assign]
63   	  if (::connect(socket_fd, (struct sockaddr *) &address, 
64   		sizeof(struct sockaddr_un)) != 0) {
65   	    int err = errno;
66   	    ostringstream oss;
67   	    oss << "connect(" << socket_fd << ") failed: " << cpp_strerror(err);
68   	    close(socket_fd);
69   	    return oss.str();
(7) Event if_end: End of if statement.
70   	  }
71   	
72   	  struct timeval timer;
73   	  timer.tv_sec = 5;
74   	  timer.tv_usec = 0;
(8) Event noescape: Resource "socket_fd" is not freed or pointed-to in function "setsockopt".
(9) Event cond_false: Condition "setsockopt(socket_fd, 1, 20, &timer, 16U /* sizeof (timer) */)", taking false branch.
Also see events: [open_fn][assign][noescape][noescape][assign]
75   	  if (::setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &timer, sizeof(timer))) {
76   	    int err = errno;
77   	    ostringstream oss;
78   	    oss << "setsockopt(" << socket_fd << ", SO_RCVTIMEO) failed: "
79   		<< cpp_strerror(err);
80   	    close(socket_fd);
81   	    return oss.str();
(10) Event if_end: End of if statement.
82   	  }
83   	  timer.tv_sec = 5;
84   	  timer.tv_usec = 0;
(11) Event noescape: Resource "socket_fd" is not freed or pointed-to in function "setsockopt".
(12) Event cond_false: Condition "setsockopt(socket_fd, 1, 21, &timer, 16U /* sizeof (timer) */)", taking false branch.
Also see events: [open_fn][assign][noescape][noescape][assign]
85   	  if (::setsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, &timer, sizeof(timer))) {
86   	    int err = errno;
87   	    ostringstream oss;
88   	    oss << "setsockopt(" << socket_fd << ", SO_SNDTIMEO) failed: "
89   		<< cpp_strerror(err);
90   	    close(socket_fd);
91   	    return oss.str();
(13) Event if_end: End of if statement.
92   	  }
93   	
(14) Event assign: Assigning: "*fd" = "socket_fd".
Also see events: [open_fn][assign][noescape][noescape][noescape]
94   	  *fd = socket_fd;
95   	  return "";
96   	}
97   	
98   	static std::string asok_request(int socket_fd, std::string request)
99   	{
100  	  ssize_t res = safe_write(socket_fd, request.c_str(), request.length() + 1);
101  	  if (res < 0) {
102  	    int err = res;
103  	    ostringstream oss;
104  	    oss << "safe_write(" << socket_fd << ") failed to write request code: "
105  		<< cpp_strerror(err);
106  	    return oss.str();
107  	  }
108  	  return "";
109  	}
110  	
111  	AdminSocketClient::
112  	AdminSocketClient(const std::string &path)
113  	  : m_path(path)
114  	{
115  	}
116  	
117  	std::string AdminSocketClient::ping(bool *ok)
118  	{
119  	  std::string version;
120  	  std::string result = do_request("{\"prefix\":\"0\"}", &version);
121  	  *ok = result == "" && version.length() == 1;
122  	  return result;
123  	}
124  	
125  	std::string AdminSocketClient::do_request(std::string request, std::string *result)
126  	{
127  	  int socket_fd = 0, res;
128  	  std::string buffer;
129  	  uint32_t message_size_raw, message_size;
130  	
(1) Event open_arg: "asok_connect" opens handle stored into "socket_fd". [details]
Also see events: [leaked_handle]
131  	  std::string err = asok_connect(m_path, &socket_fd);
(2) Event cond_true: Condition "!err.empty()", taking true branch.
132  	  if (!err.empty()) {
(3) Event goto: Jumping to label "out".
133  	    goto out;
134  	  }
135  	  err = asok_request(socket_fd, request);
136  	  if (!err.empty()) {
137  	    goto done;
138  	  }
139  	  res = safe_read_exact(socket_fd, &message_size_raw,
140  					sizeof(message_size_raw));
141  	  if (res < 0) {
142  	    int e = res;
143  	    ostringstream oss;
144  	    oss << "safe_read(" << socket_fd << ") failed to read message size: "
145  		<< cpp_strerror(e);
146  	    err = oss.str();
147  	    goto done;
148  	  }
149  	  message_size = ntohl(message_size_raw);
150  	  buffer.resize(message_size, 0);
151  	  res = safe_read_exact(socket_fd, &buffer[0], message_size);
152  	  if (res < 0) {
153  	    int e = res;
154  	    ostringstream oss;
155  	    oss << "safe_read(" << socket_fd << ") failed: " << cpp_strerror(e);
156  	    err = oss.str();
157  	    goto done;
158  	  }
159  	  //printf("MESSAGE FROM SERVER: %s\n", buffer.c_str());
160  	  std::swap(*result, buffer);
161  	done:
162  	  close(socket_fd);
(4) Event label: Reached label "out".
163  	 out:
(5) Event leaked_handle: Handle variable "socket_fd" going out of scope leaks the handle.
Also see events: [open_arg]
164  	  return err;
165  	}
166