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

📄 smbproto.c

📁 Sanos Operating System Kernel ----------------------------- Sanos is an OS kernel for use in PC base
💻 C
📖 第 1 页 / 共 2 页
字号:
  if (rc < 0) return rc;

  return 0;
}

int smb_connect_tree(struct smb_share *share)
{
  struct smb *smb;
  int rc;
  char *p;
  char buf[SMB_NAMELEN];

  // Connect to share
  smb = smb_init(share, 1);
  smb->params.req.connect.andx.cmd = 0xFF;
  smb->params.req.connect.password_length = strlen(share->server->password) + 1;

  p = buf;
  p = addstrz(p, share->server->password);
  p = addstrz(p, share->sharename);
  p = addstrz(p, SMB_SERVICE_DISK);

  rc = smb_request(share, smb, SMB_COM_TREE_CONNECT_ANDX, 4, buf, p - buf, 0);
  if (rc < 0) return rc;

  share->tid = smb->tid;
  share->mounttime = time(0);

  return 0;
}

int smb_disconnect_tree(struct smb_share *share)
{
  struct smb *smb;

  // Disconnect from share
  smb = smb_init(share, 1);
  smb_request(share, smb, SMB_COM_TREE_DISCONNECT, 0, NULL, 0, 0);
  share->tid = 0xFFFF;

  return 0;
}

int smb_connect(struct smb_share *share)
{
  struct smb_server *server = share->server;
  struct smb *smb;
  struct sockaddr_in sin;
  int rc;
  unsigned short max_mpx_count;
  char *p;
  char buf[SMB_NAMELEN];

  // Connect to SMB server on port 445
  rc = socket(AF_INET, SOCK_STREAM, IPPROTO_IP, &server->sock);
  if (rc < 0) return rc;

  memset(&sin, 0, sizeof(sin));
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = server->ipaddr.addr;
  sin.sin_port = htons(445);
  
  rc = connect(server->sock, (struct sockaddr *) &sin, sizeof(sin));
  if (rc < 0) goto error;

  // Negotiate protocol version
  smb = smb_init(share, 1);
  rc = smb_request(share, smb, SMB_COM_NEGOTIATE, 0, "\002NT LM 0.12", 12, 0); 
  if (rc < 0) goto error;

  if (smb->params.rsp.negotiate.dialect_index == 0xFFFF) 
  {
    rc = -EREMOTEIO;
    goto error;
  }

  server->tzofs = smb->params.rsp.negotiate.server_timezone * 60;
  server->server_caps = smb->params.rsp.negotiate.capabilities;
  server->max_buffer_size = smb->params.rsp.negotiate.max_buffer_size;
  max_mpx_count = smb->params.rsp.negotiate.max_mpx_count;

  // Setup session
  smb = smb_init(share, 1);
  smb->params.req.setup.andx.cmd = 0xFF;
  smb->params.req.setup.max_buffer_size = (unsigned short) SMB_MAX_BUFFER;
  smb->params.req.setup.max_mpx_count = max_mpx_count;
  smb->params.req.setup.ansi_password_length = strlen(server->password) + 1;
  smb->params.req.setup.unicode_password_length = 0;
  smb->params.req.setup.capabilities = SMB_CAP_NT_SMBS;

  p = buf;
  p = addstrz(p, server->password);
  p = addstrz(p, server->username);
  p = addstrz(p, server->domain);
  p = addstrz(p, SMB_CLIENT_OS);
  p = addstrz(p, SMB_CLIENT_LANMAN);

  rc = smb_request(share, smb, SMB_COM_SESSION_SETUP_ANDX, 13, buf, p - buf, 0); 
  if (rc < 0) goto error;

  server->uid = smb->uid;

  return 0;

error:
  if (server->sock)
  {
    closesocket(server->sock);
    server->sock = NULL;
  }

  return rc;
}

int smb_disconnect(struct smb_share *share)
{
  struct smb_server *server = share->server;
  struct smb *smb;

  if (server->sock)
  {
    // Logoff server
    if (server->uid != 0xFFFF)
    {
      smb = smb_init(share, 1);
      smb->params.andx.cmd = 0xFF;
      smb_request(share, smb, SMB_COM_LOGOFF_ANDX, 2, NULL, 0, 0);
      server->uid = 0xFFFF;
    }

    // Close socket
    closesocket(server->sock);
    server->sock = NULL;
  }

  return 0;
}

int smb_get_connection(struct smb_share *share, struct ip_addr *ipaddr, char *domain, char *username, char *password)
{
  struct smb_server *server;
  int rc;

  // Try to find existing connection to server
  server = servers;
  while (server)
  {
    if (ip_addr_cmp(&server->ipaddr, ipaddr))
    {
      // Add share to server
      share->server = server;
      share->next = server->shares;
      server->shares = share;
      server->refcnt++;

      return 0;
    }

    server = server->next;
  }

  // Allocate new server block
  server = (struct smb_server *) kmalloc(sizeof(struct smb_server));
  if (!server) return -ENOMEM;
  memset(server, 0, sizeof(struct smb_server));

  server->ipaddr = *ipaddr;
  strcpy(server->domain, domain); 
  strcpy(server->username, username); 
  strcpy(server->password, password);
  server->uid = 0xFFFF;
  init_mutex(&server->lock, 0);

  // Add share to server
  share->tid = 0xFFFF;
  share->server = server;
  share->next = server->shares;
  server->shares = share;
  server->refcnt++;

  // Connect to server
  rc = smb_connect(share);
  if (rc < 0)
  {
    share->server = NULL;
    kfree(server);
    return rc;
  }

  // Add server to server list
  server->next = servers;
  servers = server;

  return 0;
}

int smb_release_connection(struct smb_share *share)
{
  struct smb_server *server = share->server;

  if (!server) return 0;

  if (--server->refcnt > 0)
  {
    // Remove share from server list
    if (server->shares == share)
      server->shares = share->next;
    else
    {
      struct smb_share *s;

      for (s = server->shares; s != NULL; s = s->next)
      {
	if (s->next == share)
	{
	  s->next = share->next;
	  break;
	}
      }
    }

    share->server = NULL;
    return 0;
  }

  // Disconnect from server
  smb_disconnect(share);

  // Remove server block
  if (servers == server)
   servers = server->next;
  else
  {
    struct smb_server *s;

    for (s = servers; s != NULL; s = s->next)
    {
      if (s->next == server)
      {
	s->next = server->next;
	break;
      }
    }
  }

  kfree(server);
  share->server = NULL;

  return 0;
}

int smb_check_connection(struct smb_share *share)
{
  struct smb_server *server = share->server;
  int rc;

  if (!server->sock)
  {
    // Create new connection to server
    rc = smb_connect(share);
    if (rc < 0) return rc;
  }

  if (share->tid == 0xFFFF)
  {
    // Reconnect share
    rc = smb_connect_tree(share);
    if (rc < 0) return rc;
  }

  return 0;
}

int smb_reconnect(struct smb_share *share)
{
  struct smb_server *server = share->server;
  struct smb_share *s;
  int rc;

  s = server->shares;
  while (s)
  {
    s->tid = 0xFFFF;
    s = s->next;
  }
  server->uid = 0xFFFF;

  if (server->sock) smb_disconnect(share);

  rc = smb_connect(share);
  if (rc < 0) return rc;

  rc = smb_connect_tree(share);
  if (rc < 0) return rc;

  return 0;
}

⌨️ 快捷键说明

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