Discuta este tópico no fórum

Se este conteúdo te ajudou, deixe um presente!

domingo, 28 de abril de 2013

OpenWRT: Passo a passo da solução de um bug no kernel

Este post será mais um relato do que tenho feito nos últimos dias em relação a um bug muito estranho mas também poderá passar o caminho das pedras se alguém quiser se aventurar mais abaixo neste mundo Linux.

Um problema que encontrei após a configuração do HD externo pela USB foi que algumas partições não apareciam. Meu disco era grande e tinha este formato:

  • sda: disco de 1.5TB
    • sda1: partição primária NTFS de 60GB
    • sda2: partição estendida com o restante do disco
      • sda5: partição lógica ext4 com 1TB
      • sda6: partição lógica swap de 4GB
      • sda7: partição lógica ext4 com 60GB

Se não conhece o básico da estrutura da tabela de partições da MBR, o que é uma partição primária, estendida e lógica, wikipedia é sua amiga.

Nada muito anormal e nunca tive problemas durante anos de uso do disco. Porém, ao conectar no OpenWRT, a partição sda6 e sda7 não apareciam. Cumé? Como em geral acontece, os logs dão uma dica. Esta é a mensagem do kernel:

[  173.870000] sd 1:0:0:0: [sdb] No Caching mode page present
[  173.870000] sd 1:0:0:0: [sdb] Assuming drive cache: write through

[  180.330000]  sdb: sdb1 sdb2 < sdb5 >

[  180.340000] sdb: partition table partially beyond EOD, enabling native capacity

[  180.350000] sd 1:0:0:0: [sdb] No Caching mode page present
[  180.360000] sd 1:0:0:0: [sdb] Assuming drive cache: write through
[  180.370000]  sdb: sdb1 sdb2 < sdb5 >
[  180.370000] sdb: partition table partially beyond EOD, truncated
[  180.380000] sd 1:0:0:0: [sdb] No Caching mode page present
[  180.390000] sd 1:0:0:0: [sdb] Assuming drive cache: write through
[  180.400000] sd 1:0:0:0: [sdb] Attached SCSI disk
Bem, o que era possível entender era que, por algum motivo, o Linux no OpenWRT estava achando que uma partição estava além do fim do disco (EOD). Ele tentava ativar uma "native capacity", que não resolvia, e depois truncava o disco. No final de contas, eu ficava com as partições até a sda5.

Agora vem a beleza do software livre: eu tenho o fonte :-) Fazendo uma busca textual simples pela mensagem, eu encontrei este trecho de código:
linux-3.3.8/block/partition-generic.c:

int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
{
(...)
    state = check_partition(disk, bdev))
(...)
    /*
     * If any partition code tried to read beyond EOD, try
     * unlocking native capacity even if partition table is
     * successfully read as we could be missing some partitions.
     */
    if (state->access_beyond_eod) {
        printk(KERN_WARNING
               "%s: partition table partially beyond EOD, ",
               disk->disk_name);
        if (disk_unlock_native_capacity(disk))
            goto rescan;
    }
(...)
}
Bem, alguma coisa no check_partition(disk, bdev) estava marcando o estado state->access_beyond_eod e gerando a mensagem. Buscando pelo texto access_beyond_eod, achei que ele somente era definido por este código:
linux-3.3.8/block/partitions/check.h:
static inline void *read_part_sector(struct parsed_partitions *state,
                     sector_t n, Sector *p)
{
    if (n >= get_capacity(state->bdev->bd_disk)) {
        state->access_beyond_eod = true;
        return NULL;
    }

    return read_dev_sector(state->bdev, n, p);
}
Pelo código, somente será marcado access_beyond_eod se o setor lido for maior que o tamanho do disco. Agora, quem está errado? O setor? O tamanho do disco? O tamanho do disco parecia estar correto pois ele era apresentado corretamente nas mensagens de kernel e no arquivo /proc/partitions. Deve ser o setor então. Mas ele está errado no disco ou tratado incorretamente?

Para sanar a primeira dúvida, com ajuda da santa wikipedia, fiz um script para interpretar as tabelas de partição na MBR e na partição estendida. Neste ponto, tentando isolar o problema, já tinha apagado as partições 6 e 7, criado uma nova 6 com 1MB, reduzido a partição 1 e criado uma partição 3 entre as partições primárias 1 e 2. Nada disto alterou o resultado. O script mostrou estas informações:
Checking /dev/sdb...

Checking /dev/sdb1...present
Primary Entry: 0001010007FEFFFF3F000000C1676007
Start(CHS): (010100)
End  (CHS): (FEFFFF)
Code      : 07
Start(LBA): 63 (3F000000)
Size(sect): 123758529 sectors, 63364 Mbytes (C1676007)
Checking /dev/sdb2...present
Primary Entry: 00FEFFFF0FFEFFFF1A5E8007E62913A7
Start(CHS): (FEFFFF)
End  (CHS): (FEFFFF)
Code      : 0F
Start(LBA): 125853210 (1A5E8007)
Size(sect): 2803050982 sectors, 1435162 Mbytes (E62913A7)
Extended partition detected! Reading logical partitions...
Checking /dev/sdb5...present

Primary Entry: 00FEFFFF83FEFFFF3F0000002C140080
Active? no
Start(CHS): (FEFFFF)
End  (CHS): (FEFFFF)
Code      : 83
Start(LBA): 63 (3F000000)
Size(sect): 2147488812 sectors, 1099514 Mbytes (2C140080)
Secondary Entry: 00FEFFFF05FEFFFF6B1400807B150000
Next ERB(LBA): 2147488875 (6B140080)
Size(sect): 5499 sectors, 2 Mbytes (7B150000)
Checking /dev/sdb6...present

Primary Entry: 00FEFFFF83FEFFFF7B0D000000080000
Active? no
Start(CHS): (FEFFFF)
End  (CHS): (FEFFFF)
Code      : 83
Start(LBA): 3451 (7B0D0000)
Size(sect): 2048 sectors, 1 Mbytes (00080000)
Secondary Entry: 00000000000000000000000000000000
This is the last logical partition!


Checking /dev/sdb3...present
Primary Entry: 00FEFFFF82FEFFFF0068600700F01F00
Start(CHS): (FEFFFF)
End  (CHS): (FEFFFF)
Code      : 82
Start(LBA): 123758592 (00686007)
Size(sect): 2093056 sectors, 1071 Mbytes (00F01F00)
Checking /dev/sdb4...not present
Em resumo, por encontrar todas as partições, e com o tamanho correto, o disco estava íntegro. Era problema na leitura ou interpretação dos dados pelo kernel. Seria bem mais fácil o disco estar errado... Neste ponto, eu abri um bug para o OpenWRT mas continuei a investigar por conta própria.

O passo seguinte é adicionar mais informações de debug de dentro do kernel. A maneira mais simples é adicionar alguns "printk" (printf do kernel) em pontos estratégicos. Mas primeiro, é necessário encontrar estes pontos.

Meu disco, por ser menor que 2TB, ainda usa tabela de partições MS-DOS. Como o problema ocorre a partir da segunda partição lógica, o código deve estar na parte que lê os dados da partição estendida. O código é este:
linux-3.3.8/block/partitions/msdos.c
static void parse_extended(struct parsed_partitions *state,
                sector_t first_sector, sector_t first_size)
    this_sector = first_sector;

    while (1) {
(...)
        data = read_part_sector(state, this_sector, &sect);
(...)

        p = (struct partition *) (data + 0x1be);
(...)

        for (i=0; i<4; i++, p++)
            if (nr_sects(p) && is_extended_partition(p))
                break;
(...)
         this_sector = first_sector + start_sect(p) * sector_size
                   }
(...)
}
Olha a função read_part_sector que pode marcar access_beyond_eod ali no começo! Para conseguir entender o código, é necessário conhecer a estrutura das partições estendidas. Em resumo, a partição estendida possui uma tabela de partição própria (ERB), onde a primeira entrada descreve a primeira partição lógica e a segunda entrada aponta para a próxima tabela de partição. Voltando as aulas de estrutura de dados, é uma lista ligada/encadeada. Eu coloquei printk ao longo de toda esta função para descobrir o que não estava legal. A parte estranha foi justamente esta última, que soma a posição relativa da próxima tabela de partição com o início da partição estendida:

[   98.230000] parse_extended: sector_size = 1

[   98.230000] parse_extended: start_sect(p) = 2147488875
[   98.230000] parse_extended: start_sect(p)*sector_size = 2147488875
[   98.240000] parse_extended: first_sector = 125853210
[   98.250000] parse_extended: first_sector + start_sect(p) * sector_size = this_sector = 18446744071687926405
O que?! 2147488875 + 125853210 = 18446744071687926405 ?? O que aconteceu com  2273342085? Agora que tinha algo mais palpável, mandei diretamente para a lista de desenvolvimento do OpenWRT. Com ajuda de outros desenvolvedores, descobrimos o problema.

Em primeiro lugar, um pouco de contextualização. Todas as variáveis na expressão problemática são do tipo sector_t, que para meu caso é representado por um u64 (valor inteiro sem sinal de 64 bits). Não deveria ter problemas para as grandezas envolvidas pois vai até 18446744073709551615. Além disto, os setores em uma partição MS-DOS são representados por inteiros sem sinal de 32-bit. Então o 64-bit estão sobrando. Por que o problema? Olhando o binário da resposta correta, 2273342085, e a errada, podemos ver uma coisa em comum:

2273342085(b10)           = 0000000000000000000000 1000101011000000111110(b2)
18446744071687926405(b10) = 1111111111111111111111 1000101011000000111110(b2)

Os bits mais significativos ficaram todos 1 quando o correto seria 0. Uma possível causa deste monte de '1' é de um resultado da conversão de um inteiro com sinal 32-bit para 64-bit. Voltando a aula de análise numérica (wikipedia para relembrar?), os números inteiros com sinal serão negativos quando o primeiro bit for 1. Porém, não é simplesmente colocar um bit na frente. O sistema mais usado atualmente é o complemento para dois. O número negativo é a negação dos bits do mesmo número positivo, mas deslocando em um para não ter zero positivo e negativo. O que importa para este problema é que, para converter um número para outro igual com mais bits, basta completar os bits mais significativos com o valor do primeiro bit. A tabela seguinte mostra exemplo desta conversão de 4-bit para 8-bit:

Decimal
4-bit
8-bit
+3
0011
00000011
+2
0010
00000010
+1
0001
00000001
0
0000
00000000
−1
1111
11111111
−2
1110
11111110
−3
1101
11111101


E o mesmo vale de 32-bit para 64-bit. Como o primeiro bit de 2273342085 é 1, se este fosse um número negativo, ao converter para 64-bit, todos seus primeiros bits serão 1. Mas eu não tinha falado que as variáveis daquela expressão problemática são sem sinal? O compilador se perdeu? Só uma forma de dizer isto: olhando o assembly gerado.

Recompilando o kernel com informações de debug ativadas, é possível extrair o assembly em conjunto com o código em C. A arquitetura do roteador é MIPS. Enfim as aulas de assembly da faculdade com o MIPS servem para alguma coisa! O resultado é este:

this_sector = first_sector + start_sect(p) * sector_size;
 344:   02e00013        mtlo    s7
 348:   00052a00        sll     a1,a1,0x8
 34c:   00031c00        sll     v1,v1,0x10
 350:   00a31825        or      v1,a1,v1
 354:   90850008        lbu     a1,8(a0)
 358:   9084000b        lbu     a0,11(a0)
 35c:   02c00011        mthi    s6
 360:   00651825        or      v1,v1,a1
 364:   00042600        sll     a0,a0,0x18
 368:   00641825        or      v1,v1,a0
 36c:   70720000        madd    v1,s2
 370:   00005812        mflo    t3
 374:   afab004c        sw      t3,76(sp)
 378:   00005010        mfhi    t2
 37c:   afaa0048        sw      t2,72(sp)
A parte que importa está em destaque. A instrução madd é a soma entre dois números inteiros com sinal. O correto deveria ser maddu. Então o compilador acha que isto é um inteiro com sinal? Beleza, compilador com bug, joga fora e pega outro.... não é tão simples assim. Não existe outro compilador que possa ser usado além do gcc para compilar o kernel (llvm está quase lá, mas não para MIPS). Será mesmo problema do compilador? Pode ser, mas pode também ter alguma ajuda do código. Voltando a linha problemática, fora as variáveis locais, existe uma chamada externa para start_sect. Este é o código:
linux-3.3.8/block/partitions/msdos.c:
static inline sector_t start_sect(struct partition *p)
{
    return (sector_t)get_unaligned_le32(&p->start_sect);
}
Ele pega a posição do setor inicial na lista de entradas da tabela de partição, que representa em um número 32-bit, com formato big endian, na mesma ordem usada em protocolos de rede. Este buffer de 4 bytes é passado para a função get_unaligned_le32, que converte para o formato de número 32-bit na ordem da máquina. A implementação desta função depende de cada arquitetura. Em processadores x86, existe uma instrução do processador para fazer isto. Para MIPS, é feiro por código:
linux-3.3.8/include/linux/unaligned/le_byteshift.h:
static inline u32 __get_unaligned_le32(const u8 *p)
{
    return p[0] |p[1] << 8 | p[2] << 16 | p[3] << 24;
}
O código é simples: ele pega cada um dos 4 bytes do buffer 32-bit, desloca cada um para a sua posição correta usando o operador left shift e junta tudo com o operador ou. E qual o problema disto? Existe um não aparente. A especificação C99 define que:


   The integer promotions are performed on each of the operands. The type of the result is
   that of the promoted left operand. If the value of the right operand is negative or is
   greater than or equal to the width of the promoted left operand, the behavior is undefined.

Então, se o lado esquerdo possuir menos ou o mesmo número de bits deslocados pelo lado direito do operador, o comportamento não é definido, que em miúdos quer dizer, se você fizer isto, não sei o que vai acontecer. Nisto, o compilador se perdeu e, por algum motivo, ignorou o fato das variáveis serem sem sinal. Pode ser que ele ainda estivesse considerando operações para variáveis sem sinal 8-bit, onde não importa muito se você está usando um operador 32-bit com ou sem sinal. A solução é ligeiramente simples: converter o tipo do lado esquerdo antes de aplicar o operador. Fica assim:
linux-3.3.8/include/linux/unaligned/le_byteshift.h:
static inline u32 __get_unaligned_le32(const u8 *p)
{
    return p[0] | (u32)p[1] << 8 | (u32)p[2] << 16 | (u32)p[3] << 24;
}

E o código assembly indica que o compilador, agora, assume que aquela soma é entre variáveis sem sinal:

 this_sector = first_sector + start_sect(p) * sector_size;
 344:   02e00013        mtlo    s7
 348:   00052a00        sll     a1,a1,0x8
 34c:   00031c00        sll     v1,v1,0x10
 350:   00a31825        or      v1,a1,v1
 354:   90850008        lbu     a1,8(a0)
 358:   9084000b        lbu     a0,11(a0)
 35c:   02c00011        mthi    s6
 360:   00651825        or      v1,v1,a1
 364:   00042600        sll     a0,a0,0x18
 368:   00641825        or      v1,v1,a0
 36c:   70720001        maddu   v1,s2
 370:   00005812        mflo    t3
 374:   afab004c        sw      t3,76(sp)
 378:   00005010        mfhi    t2
 37c:   afaa0048        sw      t2,72(sp)
Note que a instrução mudou de madd para maddu. Provavelmente foram alteradas outras instruções no código mas ao menos agora sei que o compilador está tratando como número sem sinal.

Adicionado o patch ao kernel, recompilando a imagem e instalando, volto a ter acesso a todas as partições do disco!

Acredito que este problema ainda era desconhecido por ser raro juntar uma arquitetura vulnerável ao problema com ao menos uma partição lógica iniciada além do setor 4294967296 (ou 1 TB) na partição. O mundo x86 não é afetado pois a função __get_unaligned_le32 é implementada diretamente por uma instrução do processador.


Agora falta apenas submeter oficialmente o patch para o Openwrt e para o kernel oficial. Enfim, a culpa era do kernel Linux e compilador, não diretamente do OpenWRT.

Até a próxima!

sexta-feira, 19 de abril de 2013

OpenWRT: Torrent diretamente no roteador.

Mais um artigo da série sobre o OpenWRT.

conectamos um HD no roteador e compartilhamos na rede. Falta somente arrumar uma aplicação para encher todo este espaço em disco. E para isto, nada melhor que o torrents.

O BitTorrent, ou Torrent para os mais íntimos, é um protocolo de compartilhamento de arquivos peer-to-peer. A principal característica é que todos que estão baixando também fornecem este conteúdo. Assim, retira-se o gargalo dos downloads de uma única fonte. Bem, o importante é que é uma ótima ferramenta para baixar arquivos grandes como os arquivos do Ubuntu, LibreOffice e outras coisas.

Existe algumas alternativas de cliente BitTorrent no OpenWRT, mas vou me limitar ao Transmission por ser leve, integrado ao ambiente e com a possibilidade de administração remota facilitada. Como de praxe, precisam ser instalados os pacotes do programa:

Outro problema que pode ocorrer com os torrents é a falta de memória. Se seu equipamento possuir 64MB ou mais, em geral, deve funcionar sem problemas. Caso contrário, pode ser necessário utilizar uma partição ou arquivo em disco externo como swap. Se aparecer interessados, eu faço um post sobre isto. Acompanhe as mensagens de kernel do sistema por alertas de processos mortos por falta de memória.

O primeiro a ser instalado é o daemon. Ele será o programa que ficará rodando e baixando seus arquivos. Os demais serão formas de acessá-lo.
opkg update

opkg install transmission-daemon
Uma das primeiras interfaces é a versão CLI (console). Com ela, você poderá acompanhar e configurar seus torrents conectando no roteador pelo SSH e rodando o programa. 
opkg install transmission-cli
Existe também uma versão WEB, equivalente à versão gráfica, mas operável de um navegador.
opkg install transmission-web
E uma das mais interessantes é a possibilidade de rodar um cliente Transmission no seu computador e ele controlar os Torrents no seu roteador. Para isto, instale:
opkg install transmission-remote
A configuração é toda feita no arquivo /etc/config/transmission. E uma forma facilitada de configurá-lo é por um módulo da interface web Luci. Neste caso, precisa instalar mais um pacote:
opkg install luci-app-transmission
Recomendo o uso da interface, apesar da tradução pt_BR ainda estar desatualizada. Tomara que seja feita a sincronia das traduções antes de sair a próxima versão estável do OpenWRT. As partes mais importantes, configuradas na web ou no arquivo, são ativação do serviço, o diretório para downloads e o de configuração. Observe que o usuário que rodar o programa deve ter permissão de escrita nestes diretórios. Se for usar a interface web ou remota, existe uma lista de endereços permitidos que pode necessitar de ajuste. Dispare o serviço pela web ou linha de comando:
/etc/init.d/transmission enable
/etc/init.d/transmission start
É bom olhar os logs para ver se não ocorreu algum problema:
logread | grep transmission
Para gerenciar seus torrents, você pode usar:
  • a interface web pelo endereço http://roteador:9091/
  • a partir de uma conexão SSH, a interface CLI, pelo comando transmission-cli
  • um cliente transmission no seu computador apontando para host roteador, porta 9091. Neste caso, as opções de clientes são variadas.
Trocando "roteador" pelo nome ou endereço do seu roteador. Se o endereço do roteador não foi alterado, ele será o 192.168.1.1.


Depois de ter uma instalação básica funcional, volte as configurações e observe se existe algo interessante para ser ajustado. A opção de diretório de arquivos incompletos pode ser interessante se a sua intenção é montar um mediabox.

Apesar de já ser possível baixar arquivos com esta configuração, você terá melhores resultados se os parceiros também conseguirem conectar no seu cliente. Eles tentarão conectar na porta definida pela opção "peer_port". É necessário liberar esta porta no firewall.
Em geral, você irá habilitar a porta definida na opção "peer_port", vinda de qualquer lugar da wan e para qualquer endereço do roteador. Talvez você também queira desligar a proteção de "syn_flood" no firewall pois volume "normal" de conexões em torrents vai além dos limites desta proteção. Ah, e por usar o IP WAN do roteador, que em geral é um IP válido na internet, pode esquecer a necessidade dos encaminhamentos de porta.

Atualização em 13/03/2016: se estiver utilizando o SQM ou outro QoS inteligente, é bom configurar o peer-socket-tos para "low-cost". Assim ele sabe que não deve dar prioridade ao torrent. No pior dos casos, configurar esta opção não terá efeito ;-).

Com o transmission no roteador, você poderá continuar a baixar seus arquivos por dias e com um consumo de energia muitas vezes menor do que um computador tradicional. Ainda, após terminar seus downloads e depois de disponibilizar uma boa proporção dos arquivos, você pode deixar o serviço transmission desligado e dar uma folga ao HD. Isto vai aumentar a sua vida útil.

Let's share!

Bom compartilhamento para vocês.

sábado, 6 de abril de 2013

OpenWRT: Compartilhando seu HD na rede pelo roteador(NAS)

A porta USB no roteador o torna muito versátil. Um dos usos mais interessantes é transformá-lo em um NAS (Network Attached Storage) ou, em suma, um "HD na rede". Para tal, vamos precisar de um roteador com porta USB, uma unidade de armazenamento USB e espaço em disco para instalar o servidor de arquivos.


Depois de conectar um HD externo e, talvez, aumentar o espaço do disco do OpenWRT para poder instalar mais coisas, vamos a instalação do servidor de arquivos. O servidor de arquivos padrão para o Linux é o Samba. Apesar de ser uma implementação do protocolo "padrão" da Microsoft para troca de arquivos em rede, é o que temos de melhor para troca de arquivos mesmo entre duas máquinas Linux. Se o cliente for um Windows®, nem se fala.

Já existe um pacote pronto do samba para o OpenWRT. Basta instalar o pacote samba36-server e, opcionalmente, luci-app-samba, e você terá tudo que precisa para o servidor. Você pode usar tanto a interface WEB como a linha de comando para a instalação:
opkg update
opkg install samba36-server
A configuração do samba pode ser feita com as opções do arquivo smb.conf ou, de forma mais limitada, pela infraestrutura do OpenWRT, no arquivo "/etc/config/samba" . Vou me limitar ao segundo caso pois atenderá a maioria dos usuários. Quanto ao primeiro, não seria diferente de um sistema Linux padrão. Preferencialmente altere o arquivo "/etc/samba/smb.conf.template" pois a configuração final será obtida juntando as informações deste arquivo com o que for configurado em "/etc/config/samba". O pacote luci-app-samba, opcional, fornece uma página na interface WEB Luci que possibilita a configuração básica do samba ou a edição do arquivo "smb.conf.template" sem precisar saber usar o vim.

Na inteface WEB, assim como no arquivo de configuração, é bom definir o nome e o grupo de trabalho do seu roteador. Os diretórios compartilhados são criados em um item sambashare ou em "Diretórios Compartilhados" na interface Luci. Caso a segurança não seja preocupação, ative a opção "permitir convidados" ou "guest_ok". Assim, não será necessário fornecer um usuário e senha para conectar no roteador. A opção "somente leitura" vai no mesmo sentido. Só lembrando que, por padrão, usuário sem senha assume o usuário unix nobody e este precisa ter permissão de leitura ou escrita ou diretório para poder acessar ou escrever nos diretórios. Se a segurança não for importante, dê acesso completo a todos os usuários:
chmod a+rw /mnt/sd??
Onde o /mnt/sd?? é o local onde seu disco está montado no sistema. Só lembre que ao liberar o acesso sem senha e com permissão de escrita a todos, seus arquivos estarão acessíveis a qualquer usuário que tenha acesso a sua rede local. Isto inclui as suas visitas que conectam no seu wireless. Por padrão, o acesso externo (pela internet) ao samba está bloqueado no firewall. Não recomendaria a abertura deste servidor para a internet e, se for feito, por favor, não usem acesso de convidados.

Para colocar o servidor de arquivos em uso, habilite o serviço e inicie:
/etc/init.d/samba enable
/etc/init.d/samba start
E teste a partir de um computador. No windows, o caminho será \\<nome ou ip do roteador\<compartilhamento> e nas interfaces gráficas do Linux, em geral, smb://<nome ou ip do roteador/<compartilhamento>. Ex:
  • \\roteador\fotos ou smb://roteador/fotos
  • \\192.168.1.1\documentos ou smb://192.168.1.1/documentos
Se seu desejo é o uso somente com usuário convidado, sem senha, este artigo termina aqui para você. Para os mais preocupados com segurança, pode-se criar contas no OpenWRT para cada usuário. O processo é o mesmo de um sistema Linux. Infelizmente, por padrão, não tem os comandos para facilitar esta tarefa. Portanto, para criar usuários, adicione linhas como esta ao arquivo /etc/passwd:
newuser:*:1000:65534:new user name:/var:/bin/false
O newuser é o login do usuário. O número 1000 é o identificador. Deve ser único entre os usuários e preferencialmente acima de 1000. "new user name" é o nome completo, sem muito uso no OpenWRT. "/var" é o home e "/bin/false" o shell. Se ele não for conectar por SSH com este usuário no roteador, pode ficar como está. O caminho do home, "/var", pode ser interessante mudar se for habilitada a opção "homes" ou "compartilhas os homes dos usuários" na configuração do samba. Assim, quando ele se autenticar, será criado dinamicamente um diretório compartilhado com o nome do usuário para este caminho. É necessário definir uma senha para este usuário no samba utilizando o comando smbpasswd. Na primeira vez, é preciso criar o usuário nos bancos de dados do samba.
smbpasswd -a usuário
O mesmo comando pode ser usado para trocar a senha, mas sem o "-a".

Com isto temos mais uma função, um NAS, consolidado no roteador. Com um NAS e um servidor DLNA, você terá um MediaBox. Com o NAS e um cliente Torrent, um SeedBox. E por que não ambos? E por que não mais coisas? Isto fica para outro post. Até mais.