Ejemplo n.º 1
0
static void tb_dump_port(struct tb *tb, struct tb_regs_port_header *port)
{
	tb_info(tb,
		" Port %d: %x:%x (Revision: %d, TB Version: %d, Type: %s (%#x))\n",
		port->port_number, port->vendor_id, port->device_id,
		port->revision, port->thunderbolt_version, tb_port_type(port),
		port->type);
	tb_info(tb, "  Max hop id (in/out): %d/%d\n",
		port->max_in_hop_id, port->max_out_hop_id);
	tb_info(tb, "  Max counters: %d\n", port->max_counters);
	tb_info(tb, "  NFC Credits: %#x\n", port->nfc_credits);
}
Ejemplo n.º 2
0
static void tb_dump_switch(struct tb *tb, struct tb_regs_switch_header *sw)
{
	tb_info(tb,
		" Switch: %x:%x (Revision: %d, TB Version: %d)\n",
		sw->vendor_id, sw->device_id, sw->revision,
		sw->thunderbolt_version);
	tb_info(tb, "  Max Port Number: %d\n", sw->max_port_number);
	tb_info(tb, "  Config:\n");
	tb_info(tb,
		"   Upstream Port Number: %d Depth: %d Route String: %#llx Enabled: %d, PlugEventsDelay: %dms\n",
		sw->upstream_port_number, sw->depth,
		(((u64) sw->route_hi) << 32) | sw->route_lo,
		sw->enabled, sw->plug_events_delay);
	tb_info(tb,
		"   unknown1: %#x unknown4: %#x\n",
		sw->__unknown1, sw->__unknown4);
}
Ejemplo n.º 3
0
/**
 * reset_switch() - reconfigure route, enable and send TB_CFG_PKG_RESET
 *
 * Return: Returns 0 on success or an error code on failure.
 */
int tb_switch_reset(struct tb *tb, u64 route)
{
	struct tb_cfg_result res;
	struct tb_regs_switch_header header = {
		header.route_hi = route >> 32,
		header.route_lo = route,
		header.enabled = true,
	};
	tb_info(tb, "resetting switch at %llx\n", route);
	res.err = tb_cfg_write(tb->ctl, ((u32 *) &header) + 2, route,
			0, 2, 2, 2);
	if (res.err)
		return res.err;
	res = tb_cfg_reset(tb->ctl, route, TB_CFG_DEFAULT_TIMEOUT);
	if (res.err > 0)
		return -EIO;
	return res.err;
}
Ejemplo n.º 4
0
/**
 * tb_switch_alloc() - allocate and initialize a switch
 *
 * Return: Returns a NULL on failure.
 */
struct tb_switch *tb_switch_alloc(struct tb *tb, u64 route)
{
	int i;
	int cap;
	struct tb_switch *sw;
	int upstream_port = tb_cfg_get_upstream_port(tb->ctl, route);
	if (upstream_port < 0)
		return NULL;

	sw = kzalloc(sizeof(*sw), GFP_KERNEL);
	if (!sw)
		return NULL;

	sw->tb = tb;
	if (tb_cfg_read(tb->ctl, &sw->config, route, 0, TB_CFG_SWITCH, 0, 5))
		goto err;
	tb_info(tb,
		"initializing Switch at %#llx (depth: %d, up port: %d)\n",
		route, tb_route_length(route), upstream_port);
	tb_info(tb, "old switch config:\n");
	tb_dump_switch(tb, &sw->config);

	/* configure switch */
	sw->config.upstream_port_number = upstream_port;
	sw->config.depth = tb_route_length(route);
	sw->config.route_lo = route;
	sw->config.route_hi = route >> 32;
	sw->config.enabled = 1;
	/* from here on we may use the tb_sw_* functions & macros */

	if (sw->config.vendor_id != 0x8086)
		tb_sw_warn(sw, "unknown switch vendor id %#x\n",
			   sw->config.vendor_id);

	if (sw->config.device_id != PCI_DEVICE_ID_INTEL_LIGHT_RIDGE &&
	    sw->config.device_id != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C &&
	    sw->config.device_id != PCI_DEVICE_ID_INTEL_PORT_RIDGE &&
	    sw->config.device_id != PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_BRIDGE &&
	    sw->config.device_id != PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_BRIDGE)
		tb_sw_warn(sw, "unsupported switch device id %#x\n",
			   sw->config.device_id);

	/* upload configuration */
	if (tb_sw_write(sw, 1 + (u32 *) &sw->config, TB_CFG_SWITCH, 1, 3))
		goto err;

	/* initialize ports */
	sw->ports = kcalloc(sw->config.max_port_number + 1, sizeof(*sw->ports),
				GFP_KERNEL);
	if (!sw->ports)
		goto err;

	for (i = 0; i <= sw->config.max_port_number; i++) {
		/* minimum setup for tb_find_cap and tb_drom_read to work */
		sw->ports[i].sw = sw;
		sw->ports[i].port = i;
	}

	cap = tb_find_cap(&sw->ports[0], TB_CFG_SWITCH, TB_CAP_PLUG_EVENTS);
	if (cap < 0) {
		tb_sw_warn(sw, "cannot find TB_CAP_PLUG_EVENTS aborting\n");
		goto err;
	}
	sw->cap_plug_events = cap;

	/* read drom */
	if (tb_drom_read(sw))
		tb_sw_warn(sw, "tb_eeprom_read_rom failed, continuing\n");
	tb_sw_info(sw, "uid: %#llx\n", sw->uid);

	for (i = 0; i <= sw->config.max_port_number; i++) {
		if (sw->ports[i].disabled) {
			tb_port_info(&sw->ports[i], "disabled by eeprom\n");
			continue;
		}
		if (tb_init_port(&sw->ports[i]))
			goto err;
	}

	/* TODO: I2C, IECS, link controller */

	if (tb_plug_events_active(sw, true))
		goto err;

	return sw;
err:
	kfree(sw->ports);
	kfree(sw->drom);
	kfree(sw);
	return NULL;
}
Ejemplo n.º 5
0
/** read on a Socket_t using timeout and retries values as set in object.
 * \ingroup Socket
 * Target Socket_t must have been fully initialised by tb_Connect or tb_initServer. Read result is appended in 'msg' String_t.  
 *
 * @return number of read bytes, or -1 if error.
 * Example:
 * \code
 * ...
 * String_t S = tb_String(NULL);
 * Socket_t So = tb_Socket(TB_TCP_UX, "/tmp/my_unix_sock", 0);
 * tb_Connect(So, 1, 1);
 * int rc;
 *
 * while(( rc = tb_readSock(So, S, 1024)) > 0);
 * switch( rc ) {
 * case -1: // error occurs
 * case  0: // read reached eof (or timed out)
 * ...
 * \endcode
 * S will contains a concatened string of all 1024's buffers read 
 *
 * other Examples : 
 * see test/srv_test.c , test/socket_test.c in build tree
 *
 * \remarks ERROR:
 * in case of error tb_errno will be set to :
 * - TB_ERR_INVALID_OBJECT : So not a TB_SOCKET
 * - TB_ERR_BAD : msg is not a TB_STRING
 * 
 * @see tb_Socket, tb_writeSock, tb_writeSockBin, tb_readSockLine
*/
int tb_readSock(Socket_t S, tb_Object_t Msg, int maxlen) {
  fd_set set ;
  struct timeval tps ;
  int rc, retval = 0;
	sock_members_t So;
	char buff[maxlen+1];

	no_error;

	if(! TB_VALID(S,   TB_SOCKET)) {
		set_tb_errno(TB_ERR_INVALID_TB_OBJECT);
		return TB_ERR;
	}

	if(! TB_VALID(Msg, TB_STRING) && ! TB_VALID(Msg, TB_RAW)) {
		set_tb_errno(TB_ERR_BAD);
		return TB_ERR;
	}

#ifdef WITH_XTI
	if( XSock(S)->addr_family   == TB_X25 ) {
		return tb_readSock_X25(S, Msg, maxlen);
	}
#endif


 
	So = XSock(S);


	if( So->buffer != NULL && tb_getSize(So->buffer) >0) {
		int n;
		n = TB_MIN( (maxlen), (tb_getSize(So->buffer)));
		tb_notice("readSock: already %d bytes in buffer\n", tb_getSize(So->buffer));
		if( n ) {
			if( tb_isA(Msg) == TB_STRING) {
				tb_StrnAdd(Msg, n, -1, "%S", So->buffer);
			} else {
			tb_RawAdd(Msg, n, -1, S2sz(So->buffer));
			}
			tb_StrDel(So->buffer, 0, n);
			if( n == maxlen) {
				return n;
			} else {
				maxlen -= n;
				retval = n;
			}
		}
	} 

	restart_r_select:

  FD_ZERO(&set);
  FD_SET(So->sock, &set);
  tb_getSockTO(S, &(tps.tv_sec), &(tps.tv_usec));

  rc = select(So->sock+1, &set, NULL, NULL, &tps);
  switch (rc)
    {
    case -1:
			if( errno == EINTR ) goto restart_r_select;
      tb_warn("tb_readSock[%d]: select failed (%s)\n", 
							 So->sock, strerror(errno)); 
      // invalid fd ==> we're disconnected
      if( errno == EBADF ) So->status = TB_DISCONNECTED;
			set_tb_errno(TB_ERR_DISCONNECTED);
      retval = TB_ERR;
      break; 
    case 0:
      /* Time out */
      tb_notice("tb_readSock[%d]: select timed out\n", So->sock); 
      So->status = TB_TIMEDOUT;
      retval = TB_KO;
			break ;
    default:
			if( ! FD_ISSET(So->sock, &set)) {
				tb_notice("tb_readSock[%d]: select rc=%d but fd is not ready\n", 
									So->sock, rc); 
				retval = TB_KO;
				break ;
			}
		restart_r_read:
#ifdef WITH_SSL
			if( So->ssl ) {
				tb_info("SSL_read: try to read %d bytes\n", maxlen);
				rc = SSL_read(XSsl(S)->cx, buff, maxlen);
				switch (SSL_get_error(XSsl(S)->cx,rc)) {
				case SSL_ERROR_NONE:
					buff[rc] = 0;
					tb_StrAdd(Msg, -1, "%s", buff);
					if( rc < maxlen ) {
						tb_info("SSL_read: got only %d/%d\n", rc, maxlen);
						maxlen -= rc;
						goto restart_r_select;
					}
					return rc;
				case SSL_ERROR_SYSCALL:
					if( errno ) {
						tb_warn("tb_readSock[%d(SSL)]: read error (%s)\n",
										 So->sock, strerror(errno));
					}
					/* fall through */
				case SSL_ERROR_WANT_WRITE:
				case SSL_ERROR_WANT_READ:
				case SSL_ERROR_WANT_X509_LOOKUP:
				case SSL_ERROR_ZERO_RETURN:
				case SSL_ERROR_SSL:
					ERR_print_errors_fp(stderr);
					return TB_ERR;
				}
			} else {
				set_nonblock_flag(So->sock, 1);
				rc = read(So->sock, buff, maxlen);
				set_nonblock_flag(So->sock, 0);
			}
#else
			set_nonblock_flag(So->sock, 1);
			rc = read(So->sock, buff, maxlen);
			set_nonblock_flag(So->sock, 0);
#endif			

      switch( rc ) {
      case -1:
				if( errno == EINTR ) goto restart_r_read;
				if( errno != EWOULDBLOCK ) {
					tb_error("tb_readSock[%d]: read error (%s)\n", So->sock, strerror(errno));
					retval = TB_ERR;
					So->status = TB_DISCONNECTED;
					break;
				}
      case 0:  // eof
				*buff = 0;
      default:
				retval += rc;
				tb_RawAdd(Msg, rc, -1, buff); 
				break ;
      }
      break;
    }
  return retval;
}
Ejemplo n.º 6
0
int tb_connectSSL( Socket_t S ) {
  BIO* sbio=NULL,* dbio;
	int l;
	sock_ssl_t m = XSsl(S);

	tb_info("tb_connectSSL in\n");

  /* Ordinarily, just decorate the SSL connection with the socket file
   * descriptor.  But for super-cool shazaam debugging, build your
   * own socket BIO, decorate it with a BIO debugging callback, and
   * presto, see a dump of the bytes as they fly.  See ssl/ssl_lib.c
   * for details.  
   */
  if (tb_errorlevel <= TB_NOTICE) { 
    SSL_set_fd(m->cx, tb_getSockFD(S));
	} else {
    if (!(sbio=BIO_new_socket(tb_getSockFD(S),BIO_NOCLOSE))) {
      tb_warn("tb_connectSSL: Cannot create new socket BIO\n");
      ERR_print_errors_fp(stderr);
      goto err;
    }
    SSL_set_bio(m->cx,sbio,sbio);
    m->cx->debug=1;
    dbio=BIO_new_fp(stdout,BIO_NOCLOSE);
    BIO_set_callback(sbio,(void *)bio_dump_cb);
    BIO_set_callback_arg(sbio,dbio);
  }
	tb_info("ssl cx linked to socket\n");

  /* Initialize the state of the connection so the first i/o operation
   * knows to do the SSL connect.  Strictly speaking, this not necessary,
   * as this code goes ahead and calls SSL_connect() anyway (so I can 
   * put the connect tracing stuff in one handy spot).  But look closely
   * in ssl/s_client.c for a call to SSL_connect.  You won't find one.
   */
  SSL_set_connect_state(m->cx);
	//	SSL_CTX_set_session_cache_mode(XSSL(S)->ctx, SSL_SESS_CACHE_CLIENT);
	if(m->session != NULL ) {
		if(! SSL_set_session(m->cx, m->session)) {
			ERR_print_errors_fp(stderr);
		}
		tb_notice("tb_ConnectSSL: got a session to reuse ! (%X)\n", m->session);
	}


  /* Now that we've finally finished customizing the context and the
   * connection, go ahead and see if it works.  This function call 
   * invokes all the SSL connection handshake and key exchange logic,
   * (which is why there's so much to report on after it completes).
   */

 retry_connect:
  l = SSL_connect(m->cx);

	tb_info("ssl connect returns: %d\n", l);

  switch (SSL_get_error(m->cx,l)) { 
  case SSL_ERROR_NONE:
    break;
  case SSL_ERROR_SYSCALL:
    if ((l != 0) && errno)  tb_warn("tb_connectSSL: Write errno=%d\n", errno);
    goto err;
    break;
    /* fall through */
  case SSL_ERROR_WANT_WRITE:
		tb_info("SSL_ERROR_WANT_WRITE\n");
		goto retry_connect;
  case SSL_ERROR_WANT_READ:
		tb_info("SSL_ERROR_WANT_READ\n");
		goto retry_connect;
  case SSL_ERROR_WANT_X509_LOOKUP:
		tb_info("SSL_ERROR_WANT_X509_LOOKUP\n");
		goto retry_connect;
  case SSL_ERROR_ZERO_RETURN:
		tb_info("SSL_ERROR_ZERO_RETURN\n");
  case SSL_ERROR_SSL:
		tb_info("SSL_ERROR_SSL\n");
  default:
    ERR_print_errors_fp(stderr);
    goto err;
    break;
  }


	tb_info("connected\n");

	if(m->session == NULL ) {
		m->session = SSL_get_session(m->cx); //fixme: will leak !
		tb_notice("save session for later reuse (%X)\n", m->session);
		
	}

  /* Report on what happened now that we've successfully connected. */
  if (tb_errorlevel >= TB_NOTICE) ssl_barf_out(S);
  
	tb_info("tb_connectSSL out\n");

	return TB_OK;
 err:
	tb_info("tb_connectSSL err out\n");
	tb_Clear(S);
	return TB_ERR;
}
Ejemplo n.º 7
0
retcode_t tb_initSSL(Socket_t    S, 
										 enum ssl_mode  mode,       // SSL_CLIENT | SSL_SERVER
										 ssl_meth_t  method,     // SSL1 | SSL2 | SSL3 | TLS1
										 char      * CA_path,
										 char      * CA_file,
										 char      * cert,
										 char      * pwd,
										 char      * cipher) {
	SSL_METHOD * meth;
	sock_ssl_t m;

	tb_info("tb_initSSL in\n");

	if(!TB_VALID(S, TB_SOCKET)) {
		set_tb_errno(TB_ERR_INVALID_TB_OBJECT);
		return TB_ERR;
	}
	if(XSock(S)->ssl != NULL ) {
		tb_warn("tb_initSSL: Socket_t allready SSL initialized\n");
		set_tb_errno(TB_ERR_ALLREADY);
		return TB_ERR;
	}

	m = tb_xcalloc(1, sizeof(struct sock_ssl));
	XSock(S)->ssl = m;
	m->ssl_method = method;

	m->mode = method;


	if( CA_path ) m->CA_path = tb_xstrdup(CA_path);
	if( CA_file ) m->CA_file = tb_xstrdup(CA_file);
	if( cert ) 		m->cert    = tb_xstrdup(cert);
	if( pwd ) 		m->pwd     = tb_xstrdup(pwd);		
	if( cipher ) 	m->cipher  = tb_xstrdup(cipher);
	

	__tb_init_SSL_once();

	switch (m->ssl_method) {
  case 1:
		meth = (mode == SSL_CLIENT) ? SSLv23_client_method() : SSLv23_server_method();
    break;
  case 2:
		meth = (mode == SSL_CLIENT) ? SSLv2_client_method() : SSLv2_server_method();
    break;
  case 3:
		meth = (mode == SSL_CLIENT) ? SSLv3_client_method() : SSLv3_server_method();
    break;
  case 4:
		meth = (mode == SSL_CLIENT) ? TLSv1_client_method() : TLSv1_server_method();
    break;
	default:
		meth = NULL;
		goto err;
  }


	if (!(m->ctx = SSL_CTX_new(meth))) {
    tb_warn("tb_initSSL: Cannot create new SSL context\n");
    ERR_print_errors_fp(stderr);
		XSock(S)->status = TB_BROKEN;
		return TB_ERR; 
  }

	if(tb_errorlevel == TB_DEBUG) SSL_CTX_set_info_callback(m->ctx,info_cb);

  if(m->pwd) {
		SSL_CTX_set_default_passwd_cb(m->ctx, pass_cb);
		SSL_CTX_set_default_passwd_cb_userdata(m->ctx, S);
	}
	

	if(m->cert ) {
		if(SSL_CTX_use_certificate_file(m->ctx, m->cert, SSL_FILETYPE_PEM) <= 0) {
			ERR_print_errors_fp(stderr);
			goto err;
		}
		if (SSL_CTX_use_PrivateKey_file(m->ctx, m->cert, SSL_FILETYPE_PEM) <= 0) {
			tb_error("tb_initSSL: Unable to get private key from '%s'\n", 
							 m->cert);
			ERR_print_errors_fp(stderr);
			goto err;
		}
		tb_info("privkey loaded\n");		
		if (!SSL_CTX_check_private_key(m->ctx)) {
			tb_error("tb_initSSL: Private key does not match the certificate public key\n");
			goto err;
		}
		tb_info("tb_initSSL: privkey validated\n");
		tb_info("tb_initSSL: certificate loaded\n");
	}

	if(mode == SSL_CLIENT) {
		SSL_CTX_set_session_cache_mode(m->ctx, SSL_SESS_CACHE_CLIENT);
	} else {
		SSL_CTX_set_session_cache_mode(m->ctx, SSL_SESS_CACHE_SERVER);
		SSL_CTX_set_session_id_context(m->ctx,  "try this one", 12);
	}

  if(m->CA_file || m->CA_path) {
		tb_info("tb_initSSL: loading CAs ...\n");
    if(!SSL_CTX_load_verify_locations(m->ctx, m->CA_file, m->CA_path)) {
			XSock(S)->status = TB_BROKEN;
      tb_warn("tb_initSSL: Cannot load verify locations %s and %s\n",
              m->CA_file, m->CA_path);
      ERR_print_errors_fp(stderr);
			goto err;
    }
		tb_info("tb_initSSL: CA  <%s/%s> loaded\n", m->CA_path, m->CA_file);
		SSL_CTX_set_verify(m->ctx, SSL_VERIFY_PEER, verify_cb);
		SSL_CTX_set_default_verify_paths(m->ctx);
  }

 /* Create and configure SSL connection. */

  if (!(m->cx = (SSL *)SSL_new(m->ctx))) {
    tb_warn("tb_initSSL: Cannot create new SSL context\n");
    ERR_print_errors_fp(stderr);
		goto err;
  }
	tb_info("tb_initSSL: ssl ctx initialized\n");

  /* Use OpenSSL ciphers -v to see the cipher strings and their SSL
   * versions, key exchange, authentication, encryption, and message
   * digest algorithms, and key length restrictions.  See the OpenSSL
   * for the syntax to combine ciphers, e.g. !SSLv2:RC4-MD5:RC4-SHA.
   * If you don't specify anything, you get the same as "DEFAULT", which
   * means "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP".
   */
  if(m->cipher) {
    if(!SSL_CTX_set_cipher_list(m->ctx, m->cipher)) {
      tb_warn("tb_inittSSL: Cannot use cipher list %s\n", m->cipher);
			goto err;
    }
		tb_info("tb_initSSL: cipher set to <%s>\n", m->cipher);
	}


	tb_info("tb_initSSL out\n");
	return TB_OK;

 err:
	// fixme: context not totally freed (CA_path, pwd ...)
	SSL_CTX_free(m->ctx);
	m->ctx = NULL;
	XSock(S)->status = TB_BROKEN;
	return TB_ERR;
}