OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ovsdb_client_ssl.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <boost/bind.hpp>
6 #include <base/logging.h>
7 
8 #include <oper/agent_sandesh.h>
9 #include <ovsdb_types.h>
10 #include <ovsdb_client_ssl.h>
12 
14 
20 
21 OvsdbClientSsl::OvsdbClientSsl(Agent *agent, IpAddress tor_ip, int tor_port,
22  IpAddress tsn_ip, int keepalive_interval,
23  int ha_stale_route_interval,
24  const std::string &ssl_cert,
25  const std::string &ssl_privkey,
26  const std::string &ssl_cacert,
27  OvsPeerManager *manager) :
28  SslServer(agent->event_manager(), boost::asio::ssl::context::tlsv1_server),
29  OvsdbClient(manager, keepalive_interval, ha_stale_route_interval),
30  agent_(agent), ssl_server_port_(tor_port), tsn_ip_(tsn_ip.to_v4()),
31  shutdown_(false) {
32  // Get SSL context from base class and update
33  boost::asio::ssl::context *ctx = context();
34  boost::system::error_code ec;
35 
36  // Verify peer to have a valid certificate
37  ctx->set_verify_mode((boost::asio::ssl::verify_peer |
38  boost::asio::ssl::verify_fail_if_no_peer_cert), ec);
39  assert(ec.value() == 0);
40 
41  ctx->use_certificate_chain_file(ssl_cert, ec);
42  if (ec.value() != 0) {
43  LOG(ERROR, "Error : " << ec.message() << ", while using cert file : "
44  << ssl_cert);
45  exit(EINVAL);
46  }
47 
48  ctx->use_private_key_file(ssl_privkey, boost::asio::ssl::context::pem, ec);
49  if (ec.value() != 0) {
50  LOG(ERROR, "Error : " << ec.message() << ", while using privkey file : "
51  << ssl_privkey);
52  exit(EINVAL);
53  }
54 
55  ctx->load_verify_file(ssl_cacert, ec);
56  if (ec.value() != 0) {
57  LOG(ERROR, "Error : " << ec.message() << ", while using cacert file : "
58  << ssl_cacert);
59  exit(EINVAL);
60  }
61 }
62 
64 }
65 
69 }
70 
73  this, socket);
74  session->set_observer(boost::bind(&OvsdbClientSsl::OnSessionEvent,
75  this, _1, _2));
76  return session;
77 }
78 
80  TcpSession::Event event) {
81  OvsdbClientSslSession *ssl = static_cast<OvsdbClientSslSession *>(session);
82  ssl->EnqueueEvent(event);
83 }
84 
85 const std::string OvsdbClientSsl::protocol() {
86  return "PSSL";
87 }
88 
89 const std::string OvsdbClientSsl::server() {
90  return LocalEndpoint().address().to_string();
91 }
92 
94  return LocalEndpoint().port();
95 }
96 
98  return tsn_ip_;
99 }
100 
102  if (shutdown_)
103  return;
104  shutdown_ = true;
105  OvsdbClientSslSession *ssl =
106  static_cast<OvsdbClientSslSession *>(NextSession(NULL));
107  while (ssl != NULL) {
108  if (!ssl->IsClosed()) {
109  ssl->TriggerClose();
110  }
111  ssl = static_cast<OvsdbClientSslSession *>(NextSession(ssl));
112  }
113 }
114 
116  SessionKey key(ip, port);
117  SessionMap::iterator it;
118  if (port != 0) {
119  it = session_map_.find(key);
120  } else {
121  it = session_map_.upper_bound(key);
122  }
123  if (it != session_map_.end() && it->first.first == ip) {
124  return it->second;
125  }
126  return NULL;
127 }
128 
130  SessionMap::iterator it;
131  if (session == NULL) {
132  it = session_map_.begin();
133  } else {
134  OvsdbClientSslSession *ssl =
135  static_cast<OvsdbClientSslSession *>(session);
136  SessionKey key(ssl->remote_endpoint().address().to_v4(),
137  ssl->remote_endpoint().port());
138  it = session_map_.upper_bound(key);
139  }
140  if (it != session_map_.end()) {
141  return it->second;
142  }
143  return NULL;
144 }
145 
146 void OvsdbClientSsl::AddSessionInfo(SandeshOvsdbClient &client) {
147  SandeshOvsdbClientSession session;
148  std::vector<SandeshOvsdbClientSession> session_list;
149  OvsdbClientSslSession *ssl = static_cast<OvsdbClientSslSession *>(NextSession(NULL));
150  while (ssl != NULL) {
151  ssl->AddSessionInfo(session);
152  session_list.push_back(session);
153  ssl = static_cast<OvsdbClientSslSession *>(NextSession(ssl));
154  }
155  client.set_sessions(session_list);
156 }
157 
158 // AcceptSession callback from SSLserver, to accept a session
160  if (shutdown_) {
161  // don't accept session while shutting down
162  return false;
163  }
164  return true;
165 }
166 
168  OvsPeerManager *manager, OvsdbClientSsl *server, SslSocket *sock,
169  bool async_ready) : OvsdbClientSession(agent, manager),
170  SslSession(server, sock, async_ready), status_("Init") {
171 
173  boost::bind(&OvsdbClientSslSession::RecvMsg, this, _1, _2));
174 
175  // Process session events in KSync workqueue task context,
177  agent->task_scheduler()->GetTaskId("Agent::KSync"), 0,
178  boost::bind(&OvsdbClientSslSession::ProcessSessionEvent, this, _1));
179  session_event_queue_->set_name("OVSDB ssl session event queue");
180 }
181 
183  delete reader_;
185  delete session_event_queue_;
186 }
187 
189  reader_->OnRead(buffer);
190 }
191 
192 void OvsdbClientSslSession::SendMsg(u_int8_t *buf, std::size_t len) {
193  OVSDB_PKT_TRACE(Trace, "Sending: " + std::string((char *)buf, len));
194  Send(buf, len, NULL);
195 }
196 
197 bool OvsdbClientSslSession::RecvMsg(const u_int8_t *buf, std::size_t len) {
198  OVSDB_PKT_TRACE(Trace, "Received: " + std::string((const char*)buf, len));
199  MessageProcess(buf, len);
200  return true;
201 }
202 
204  OvsdbClientSsl *ovs_server = static_cast<OvsdbClientSsl *>(server());
205  return ovs_server->keepalive_interval();
206 }
207 
208 const boost::system::error_code &
210  return close_reason();
211 }
212 
214  OvsdbClientSsl *ovs_server = static_cast<OvsdbClientSsl *>(server());
215  return ovs_server->connection_table();
216 }
217 
219  OvsdbClientSsl *ovs_server = static_cast<OvsdbClientSsl *>(server());
220  return ovs_server->ksync_obj_manager();
221 }
222 
224  OvsdbClientSsl *ovs_server = static_cast<OvsdbClientSsl *>(server());
225  return ovs_server->tsn_ip();
226 }
227 
229  OvsdbClientSsl *ovs_server = static_cast<OvsdbClientSsl *>(server());
230  ovs_server->DeleteSession(this);
231 }
232 
234  // Close the session and return
235  Close();
236 
237  // SSL session will not notify event for self closed session
238  // generate explicit event
240 }
241 
243  return remote_endpoint().address().to_v4();
244 }
245 
247  return remote_endpoint().port();
248 }
249 
251  boost::system::error_code ec;
252  switch (ovs_event.event) {
253  case TcpSession::CLOSE:
254  {
255  OvsdbClientSsl *ovs_server =
256  static_cast<OvsdbClientSsl *>(server());
257  boost::asio::ip::tcp::endpoint ep = remote_endpoint();
258  OvsdbClientSsl::SessionKey key(ep.address().to_v4(), ep.port());
259  ovs_server->session_map_.erase(key);
260 
261  OnClose();
262  }
263  break;
264  case TcpSession::ACCEPT:
265  {
266  OvsdbClientSsl *ovs_server =
267  static_cast<OvsdbClientSsl *>(server());
268  boost::asio::ip::tcp::endpoint ep = remote_endpoint();
269  OvsdbClientSsl::SessionKey key(ep.address().to_v4(), ep.port());
270  std::pair<OvsdbClientSsl::SessionMap::iterator, bool> ret =
271  ovs_server->session_map_.insert
272  (std::pair<OvsdbClientSsl::SessionKey,
273  OvsdbClientSslSession *>(key, this));
274  // assert if entry already exists
275  assert(ret.second == true);
276  }
277  set_status("Established");
278  OnEstablish();
279  break;
280  default:
281  assert(false);
282  break;
283  }
284  return true;
285 }
286 
288  OvsdbSessionEvent ovs_event;
289  ovs_event.event = event;
290  session_event_queue_->Enqueue(ovs_event);
291 }
292 
void Close()
Definition: tcp_session.cc:354
boost::asio::const_buffer Buffer
Definition: tcp_session.h:64
virtual void DeleteSession(TcpSession *session)
Definition: tcp_server.cc:197
void SendMsg(u_int8_t *buf, std::size_t len)
void Shutdown(bool delete_entries=true)
Definition: queue_task.h:152
friend class OvsdbClientSslSession
KSyncObjectManager * ksync_obj_manager()
boost::asio::ip::address IpAddress
Definition: address.h:13
OvsdbClientSession * FindSession(Ip4Address ip, uint16_t port)
boost::asio::ssl::context * context()
Definition: ssl_server.cc:41
void RegisterConnectionTable(Agent *agent)
Definition: ovsdb_client.cc:36
const boost::system::error_code & close_reason() const
Definition: tcp_session.h:145
OvsdbClientSslSession(Agent *agent, OvsPeerManager *manager, OvsdbClientSsl *server, SslSocket *sock, bool async_ready=true)
std::pair< Ip4Address, uint16_t > SessionKey
virtual bool Send(const uint8_t *data, size_t size, size_t *sent)
Definition: tcp_session.cc:428
boost::asio::ssl::stream< boost::asio::ip::tcp::socket > SslSocket
Definition: ssl_session.h:18
const std::string server()
virtual Ip4Address remote_ip() const
int GetTaskId(const std::string &name)
Definition: task.cc:856
Endpoint LocalEndpoint() const
Definition: tcp_server.cc:306
OvsdbClientSession * NextSession(OvsdbClientSession *session)
const std::string protocol()
void set_observer(EventObserver observer)
Definition: tcp_session.cc:218
virtual void OnRead(Buffer buffer)
void AddSessionInfo(SandeshOvsdbClient &client)
TaskScheduler * task_scheduler() const
Definition: agent.h:1120
#define OVSDB_PKT_TRACE(obj,...)
virtual void OnRead(Buffer buffer)
Definition: tcp_session.cc:671
void set_status(std::string status)
Definition: agent.h:358
bool AcceptSession(TcpSession *session)
ConnectionStateTable * connection_table()
boost::asio::ssl::stream< boost::asio::ip::tcp::socket > SslSocket
Definition: ssl_server.h:16
int keepalive_interval() const
Definition: ovsdb_client.cc:48
void AddSessionInfo(SandeshOvsdbClientSession &session)
Definition: trace.h:220
const boost::system::error_code & ovsdb_close_reason() const
OvsdbClientTcpSessionReader * reader_
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
bool IsClosed() const
Definition: tcp_session.h:125
bool ProcessSessionEvent(OvsdbSessionEvent event)
WorkQueue< OvsdbSessionEvent > * session_event_queue_
virtual SslSession * AllocSession(SslSocket *socket)
ConnectionStateTable * connection_table()
Definition: ovsdb_client.cc:40
TcpServer * server()
Definition: tcp_session.h:88
Endpoint remote_endpoint() const
Definition: tcp_session.h:135
void OnSessionEvent(TcpSession *session, TcpSession::Event event)
void MessageProcess(const u_int8_t *buf, std::size_t len)
#define LOG(_Level, _Msg)
Definition: logging.h:33
virtual bool Initialize(unsigned short port)
Definition: tcp_server.cc:59
virtual uint16_t remote_port() const
OvsPeerManager * peer_manager_
Definition: ovsdb_client.h:64
KSyncObjectManager * ksync_obj_manager()
Definition: ovsdb_client.cc:44
bool Enqueue(QueueEntryT entry)
Definition: queue_task.h:248
bool RecvMsg(const u_int8_t *buf, std::size_t len)
void EnqueueEvent(TcpSession::Event event)
void set_name(const std::string &name)
Definition: queue_task.h:307