Escrito por Helio Loureiro
Categoria:

Quem tem filho sabe que não é fácil impor limites.  Especialmente quanto uso de tablets ou smartphones ou até mesmo da TV.  Eu tenho em casa um problema com YouTube que acaba virando a atração principal com um conteúdo bem longe de ser didático.  Tentei até onde podia limitar no "YouTube é das 18 às 20" mas tenho fracassado miseravelmente.

Então resolvi apelar aos meus conhecimento computacionais e ao roteador por onde passa todo o tráfego da casa, e que roda open-wrt.

Criei um sistema básico em shell script que bloqueia tudo que é relacionado com YouTube em horários pré-determinados.  Não ficou bonito, mas funciona.

#! /bin/sh
# save it into /usr/lib/scripts/firewall.sh
# and add into scheduled tasks as
# */5 * * * * /usr/lib/scripts/firewall.sh

hour=`date +%H`
minute=`date +%M`

echo "hour=$hour"
echo "minute=$minute"

status_file=/tmp/firewall_status

blocked_pattern="youtubei.googleapis.com googlevideo.com ytimg-edge-static.l.google.com i.ytimg.com youtube-ui.l.google.com www.youtube.com googleapis.l.google.com youtubei.googleapis.com video-stats.l.google.com ytimg-edge-static.l.google.com"

enable_firewall() {
    echo "Enabling firewall"
    for chain in INPUT FORWARD OUTPUT
        do
        count=1
        for proto in tcp udp
            do
                for blocked in $blocked_pattern
                    do
                    echo iptables -I $chain $count -p $proto -m string --algo bm --string "$blocked" -j DROP
                    iptables -I $chain $count -p $proto -m string --algo bm --string "$blocked" -j DROP
                    count=`expr $count + 1`
                done
        done
        echo iptables -I $chain $count -p udp --sport 443 -j DROP
        iptables -I $chain $count -p udp --sport 443 -j DROP
        count=`expr $count + 1`
        echo iptables -I $chain $count -p udp --dport 443 -j DROP
        iptables -I $chain $count -p udp --dport 443 -j DROP
        count=`expr $count + 1`
    done
}

disable_firewall() {
    echo "Disabling firewall"
    for chain in INPUT FORWARD OUTPUT
        do
        for proto in tcp udp
            do
                for blocked in $blocked_pattern
                    do
                    echo iptables -D $chain -p $proto -m string --algo bm --string "$blocked" -j DROP
                    iptables -D $chain -p $proto -m string --algo bm --string "$blocked" -j DROP
                done
        done
        echo iptables -D $chain -p udp --sport 443 -j DROP
        iptables -D $chain -p udp --sport 443 -j DROP
        echo iptables -D $chain -p udp --dport 443 -j DROP
        iptables -D $chain -p udp --dport 443 -j DROP
    done
}

case $1 in
    start) enable_firewall
           echo -n "enabled" > $status_file
           exit 0;;
    stop) disable_firewall
          echo -n "disabled" > $status_file
          exit 0;;
esac

# possible status
# enabled|disabled

# start
# from 7:55-09:59
time_status=disabled
if [[ $hour -ge 7 && $hour -lt 10 ]]; then
    time_status=enabled
    if [[ $hour -eq 7 ]]; then
        if [[ $minute -lt 55 ]]; then
            time_status=disabled
        else
            time_status=enabled
        fi
    fi
fi

# from 12:00-17:59
if [[ $hour -ge 12 && $hour -lt 18 ]]; then
    time_status=enabled
fi
# from 20:00-21:59
if [[ $hour -ge 20 && $hour -lt 22 ]]; then
    time_status=enabled
fi
echo "time_status=$time_status"

current_status=
if [[ -f "$status_file" ]]; then
    current_status=`cat $status_file`
fi

if [[ $current_status = $time_status ]]; then
    echo "nothing to do"
else
    if [[ $time_status = "enabled" ]];then
        echo "loading firewall rules"
        enable_firewall
    fi
    if [[ $time_status = "disabled" ]];then
        echo "removing firewall rules"
        disable_firewall
    fi
    echo -n $time_status > $status_file
fi

Basta salvar o arquivo em /usr/lib/scripts/firewall.sh e adicionar à crontab do open-wrt.

O código fonte está também publicado no github: https://github.com/helioloureiro/homemadescripts/blob/master/openwrt-firewall-block-youtube.sh

Escrito por Helio Loureiro
Categoria:

Toda história tem um começo, meio e fim.  E esse momento chegou pro encurtador que criei em 14 de novembro de 2010.  Inspirado no miud.in criado pelo Eduardo Maçan e baseado no yourls.org, criei o encurtador pra desafiar o "status quo" da empresa e mostrar que as coisas podiam funcionar de forma fácil e simples.  A vida do encurtador foi legal com vários pontos altos mas ultimamente pude ver que eu era o único usuário costumaz do sistema.  De resto eram só SPAMs e mais SPAMs.  E custo.

O verdadeiro matador do encurtador foi custo.  De algo em torno de 10 dólares em 2010, o custo bateu 70 dólares agora pra renovar.  Alto demais pro pouco uso.  Então decidi juntar o eri.cx ao panteão dos heróis e mitos da Internet e encerrar seu uso.

Foi divertido enquanto durou.

Mas tem um outro lado positivo.  Registrei outro domínio dentro do .br com valor muuuuuito mais acessível: http://hl.eng.br 

É basicamente o eri.cx só que com outro domínio.  Então todas os links encurtados do passado funcionarão no novo.  E com um adicional: CAPTCHA!  Sim, menos SPAMs e mais links encurtados.  E que dure 8 anos do eri.cx ou até mais.  Longa vida ao http://hl.eng.br !

http://hl.eng.br

Escrito por Helio Loureiro
Categoria:

25 anos de alegrias e tristezas.  Felizmente mais alegrias :)

Desses 25 anos, estamos juntos 20 anos.  Acho.  Talvez mais.

Escrito por Helio Loureiro
Categoria:

O herói de antigamente, quando eu comecei com Linux e BSD, era o sysadmin.  Um lobo solitário que cuidava de um ou mais servidores com vários scripts de automação.

Essa figura desapareceu e cedeu lugar à padronização e máquinas virtuais.  E as máquinas virtuais estão cada vez mais dando lugar aos containers.

Então a "arte" de fazer scripts está praticamente morrendo com poucos sysadmins ainda estudando perl, python, awk, etc.  Mas mesmo na criação de containers é possível colocar scripts em prática e de forma proveitosa.  Seriam o sysadmins 3.0.

Nesse sentido precisei criar um container pra rodar alguns programas em Java.  Criei o container baseado no Ubuntu 16.04, que é a versão que tenho no laptop de trabalho e com Maven e Java.  Maven é uma ferramenta de construção de Java parecida com pip no Python, CPAN no Perl, npm no node.js e rebar3 no Erlang.  Ele baixa as dependências nas versões desejadas e compila tudo pra gerar seu arquivo jar.  E também pode ser usado pra criar regras como de unittest.

Mas minha razão pra escrever esse post não é o Maven, que tem muitos outros artigos específicos muito bem escritos.  É sobre o Java.  Eu preciso rodar os meus programas com o JDK da Oracle.   E como automatizar?  Esse é o ponto dos scripts que comentei acima e razão desse artigo, de como usar ainda hoje em dia.  Como o download do JDK da Oracle exige aceitação dos termos de uso, é preciso fazer isso dentro do script (através de cookies).  O resto, é container puro.

O arquivo Dockerfile que criei é esse aqui:

FROM ubuntu:16latest

ENV container docker
ENV DEBIAN_FRONTEND noninteractive

RUN apt-get install -y \
        build-essential \
        lsb-release \
        tar \
        wget \
        unzip \
        sudo \
        git \
        curl \
        createrepo \
        java-package \
        fakeroot \
        maven

RUN apt-get install -y \
        libgtk-3-0 \
        libcairo-gobject2

RUN JAVA_URL=$(curl -sS http://www.oracle.com/technetwork/java/javase/downloads/index.html | \ 
                grep -i href | \
                grep "Download JDK" | \
                head -1 | \
                 tr " " "\n" | \
                grep href | \
                sed "s|.*href=\"\([^\"].*[^\"]\)\".*|\1|" ); \
        JDK_URL=$(curl -sS http://www.oracle.com$JAVA_URL | \
                grep -i "^downloads.*linux.*tar.gz.*" | \
                tr " ," "\n" | \
                grep http | \
                sed "s/.*\(http\)/\1/;s/\"//g" ); \
        curl \
                -SLkO \
                --header "Cookie: oraclelicense=accept-securebackup-cookie" \
                -# \
                $JDK_URL ; \
        linux_java=$(basename $JDK_URL) ; \
        version=$(echo $linux_java | sed "s/.*-\([0-9][^_]*\)_.*/\1/" | cut -d "." -f 1) ; \
        new_name=jdk-${version}-linux-x64.tar.gz ; \
        deb_name=oracle-java${version}-jdk_${version}_amd64.deb; \
        mv $linux_java /home/$new_name

# uid=2000(jenkins) gid=2000(jenkins) groups=2000(jenkins),999(ssh-allowed),130(libvirtd),131(kvm),998(docker)
RUN groupadd -g 2000 jenkins
RUN useradd -g 2000 -u 2000 -m jenkins

RUN su - jenkins -c "yes Y | fakeroot make-jpkg /home/jdk-*-linux-x64.tar.gz" 
RUN dpkg -i /home/jenkins/oracle-java*deb
RUN JAVA_HOME=$(update-java-alternatives -l | grep oracle | tail -1 | awk '{print $NF}') ; \
        JAVA_VERSION=$(update-java-alternatives -l | grep oracle | tail -1 | awk '{print $1}') ; \
        cd $JAVA_HOME; \
        ln -s jre .; \
        update-java-alternatives -s $JAVA_VERSION; \
        update-alternatives --install /usr/bin/java java $JAVA_HOME/bin/java 1; \
        update-alternatives --set java $JAVA_HOME/bin/java

Eu tenho um outro container chamado ubuntu:16latest que é um Ubuntu 16.04 com apt dist-upgrade pra ter a versão mais recente.  Eu geralmente adiciono o usuários jenkins pra poder rodar os containers dentro do jenkins. 

Uma vez feita a configuração, basta construir o container.  Como tenho vários arquivos pra fazer essas construções, eu geralmente salvo como Dockerfile.<distro>_<aplicativo>.  Nesse caso específico salvei num arquivo Dockerfile.ubuntu_java.  Para construir o container então:

docker build -t ubuntu:java -f Dockerfile.ubuntu_java . 

Feito o container e salvo com a tag ubuntu:java, basta somente chamar o container pra rodar seus programas em java ou compilar.

helio@linux:~/DockerBuilds$ docker run -it ubuntu:java java -version 
java version "10.0.1" 2018-04-17 
Java(TM) SE Runtime Environment 18.3 (build 10.0.1+10) 
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.1+10, mixed mode)

Daí pra frente é usar o Java como se estivesse instalado localmente.

Fontes:

1. https://wiki.debian.org/JavaPackage

2. https://www.debian.org/doc/manuals/debian-java-faq/ch5.html

Escrito por Helio Loureiro
Categoria:

Container wall. Christchurch NZ by Bernard Spragg. NZ src: https://flic.kr/p/qkJ7yG

Tive a oportunidade de participar de um curso profissional de containers oferecido dentro da empresa.  Já tive oportunidade de participar de outro curso ministrado pela mesma escola sobre OpenStack numa outra vez.  Material de primeira, laboratório completo e explicações concisas.  Resolvi escrever um pouco pra quem busca algo nesse sentido pra saber se realmente vale a pena.

Meu conhecimento anterior de Dockers veio todo de documentos gerados por comunidade de usuários e pelo próprio site do Docker.  Eu já uso Docker faz alguns anos e com bastante desenvoltura.  Muita coisa que preciso fazer já é em containers.  Durante o curso percebi que realmente não tinha muita novidade.  O uso básico de docker com "run", "images", "tag", etc é exatamente o mesmo.

Uma diferença notável que eu não conhecia foi a referência quanto à OCI, Open Container Iniciative, que tem agora um binário "runc" que substituirá o comando "docker" pra criar uma abstração genérica no manuseio de containers.  Os argumentos são exatamente os mesmo que do "docker".  Então um "docker run -it ubuntu:latest bash"  funciona com um "runc run -it ubuntu:latest bash".  Parte disso é pra facilitar o uso com kubernetes.

Agora sobre kubernetes, eu não conhecia tão a fundo.  Sempre usei um básico do básico do básico com minikube na maioria das vezes.  Já tinha mexido com Jagger pra alguma monitoração de tempo em containers, mas nada como vi no curso.  O laboratório funcionando perfeitamente e com vários exercícios.   Mas várias vezes consultamos a documentação online do kubernetes, ou seja, a documentação já disponível é riquíssima.   Mesmo em alguns pontos o material didático estava bem atrás dos comandos disponíveis no último release de kubernetes. 

E o material do curso?  Sinto mas é um material copyrighted que não pode ser distribuído.  E deixaram isso bem claro.  Mas eu pessoalmente acho que a documentação com tutoriais disponíveis cobrem muito bem tudo que estava descrito ali.

Vale então fazer um curso pago de containers?  Eu diria que depende.  Se tem tempo, é possível aprender tudo sozinho em seu próprio computador.  Mas se tiver uma necessidade mais imediata de resultados, sim cursos serão um bom acelerador nessa direção.

Qualquer que seja sua decisão, keep calm and runc -it run.

Escrito por Helio Loureiro
Categoria:

Escrevi um artigo pro blog "ChurrOps on DevOps" sobre raspresenterpy aṕos uma conversa sobre o assunto no canal do Telegram do grupo "papo de sysadmin".

 

Eu achava que já tinha escrito sobre isso aqui mesmo, mas fiquei surpreso por não ter encontrado nenhuma referência.

raspresenterpy é um programa de display que alterna links pra ser usado pra mostrar mensagens ou telas de monitoramento como do Jenkins.  Fiz até uma apresentação sobre o mesmo numa PyConSE.  O texto que escrevi detalha sobre repositório e como usar o mesmo.

Ele encontra-se com suporte ao raspbian Jessie e python-qt4.  Testei com python-qt5 e já verifiquei que não funciona.  Então deixei no meu backlog pra corrigir e lançar uma versão mais recente.

https://churrops.io/2018/06/08/usando-python-e-raspberrypi-pra-mostrar-varias-telas/

Escrito por Helio Loureiro
Categoria:

Feliz dia da toalha (ou dia do orgulho nerd).  Pegue sua toalha e... não entre em pânico.

Escrito por Helio Loureiro
Categoria:

Já teve problemas com a barra de rolagens (ou scrolls)?  Não?  Pois eu tive por muito tempo.

Como uso KDE, aplicativos baseados em GTK teimam em ignorar os padrões que seleciono e fazem as coisas da forma que querem.  Talvez por isso eu não use Gnome. 

Mas esse problema vem me atormentando desde que foi lançado o GTK3.  Faz o quê?  Uns 5 anos?  As teclas de rolagem estavam com um padrão de que apareciam somente quando o mouse passava por cima.  Irritante.  Não sei quem teve essa ideia, mas eu nunca gostei.  Só que não conseguia mudar.  E eu não dei muita importância ao fato já que no fim conseguia fazer o que precisava e isso era algo pequeno.

E hoje finalmente eu cheguei no ponto de me incomodar e procurar um solução, pois no inkscape é onde esse treco incomoda mais.  Os botões de rolagem ficam se sobrepondo entre o da imagem e da paleta de cores.  Às vezes queria mover, fazia no outro.

E até que não foi algo tão complicado quanto eu esperava.  Como já imaginava, era algo configurável via interface gráfica no caso de estar usando Gnome ou Unity.  Mas pra quem não os têm, via linha de comando basta usar o seguinte: 

gsettings set com.canonical.desktop.interface scrollbar-mode normal

Não gostou e quer voltar ao padrão antigo (por mais que eu não entenda esse tipo de decisão)?

gsettings set com.canonical.desktop.interface scrollbar-mode overlay-auto

É bem simples.  Sofri à toa por besteira.

Escrito por Helio Loureiro
Categoria:

Esses dias estava analisando um código que era parecido com shell script.  Sua função era monitorar as interfaces de rede para, no caso de alteração (nova interface surgindo ou desaparecendo), registrar a mudança de objetos no sistema de dados do opensaf (objetos no IMM pra quem conhece).

Mas o código fazia algo parecido com um shell que a todo healthcheck do AMF (framework do opensaf que é muito semelhante ao systemd e roda determinado programa ou script de tempos em tempos) fazia uma busca com o comando "ip link addr list" e comparava com o que estava  armazenado no IMM.  Algo como:

def healthcheckCallback(self, invocation, compName, healthcheckKey):
		        saAmfResponse(self.check_macs,
				      invocation, eSaAisErrorT.SA_AIS_OK)

def check_macs(self):
macs = []
for line in self.get_link_list().split("\n"):
if not re.search("link/ether", line): continue
# [ 'link/ether', '52:54:00:c3:5d:88', 'brd', 'ff:ff:ff:ff:ff:ff']
mac.append(line.split()[1])
imm_obj = self.get_from_imm()
if imm_obj != macs:
self.update_imm(mac)

def get_link_list(self):
linux_command = "ip link list"
return self.run_shell(linux_command)

Essa é uma forma bastante simplificada pra tentar visualizar como tudo funciona.  Eu propositalmente tirei comentários extras e deixei mais limpo apenas para poder comentar aqui. 

  • Agora explicando o que cada método faz ali:
  • healthcheckCallback(): esse é  o método que eu registrei junto ao AMF pra que seja chamado de tempos e tempos e rode a função check_macs().  Não vou entrar em detalhes dos outros parâmetros pois são inerentes em como o AMF funciona junto ao OpenSAF.  Deixei o link pra o exemplo de uma implementação completa ao final do artigo.
  • check_macs(): é uma função que pega uma listagem em formato array do comando "ip link list" e armazena os MAC, endereço de camada 2 da placa de rede.
  • get_link_list(): apenas pra deixar mais legível a parte que busca e monta o array de informações de rede de um sistema Linux.  O método run_shell() é apenas um subprocess.check_output() de forma mais legível (e por isso omiti essa parte do código).

Como a chamada pra buscar os dados junto ao IMM no OpenSAF tem muitas linhas, eu só deixei um get_from_imm() que retornará um array de mac registrados anteriormente.  Se esse valor for diferente do coletado, então é chamado o método update_imm() com os macs que devem estar lá.

Funciona?  Sim, funciona.  Mas... se não houve nenhuma mudança nas interfaces de rede (como a subida de uma interface de VIP ou mesmo um container em docker), por quê eu preciso rodar o get_link_list()? 

Entendeu qual foi meu ponto?

O código em si consiste em rodar o monitoramente separado numa thread.  Toda vez que o código detecta uma mudança (na verdade o kernel sinaliza isso), ele altera uma variável que o programa lê durante o healthcheck.  Algo como:

def check_macs(self):
if self.network_changed is False: return

Assim bem simples.  Teve mudança? network_changed vira um True.

Linux tem mecanismos pra detectar uma mudanças na interfaces de rede.  Por quê não usar?  E foi o que fiz.

Criei um método chamado monitor_link() que é iniciado junto com programa no método initialize(), que é parte de como o AMF faz as chamadas de callback:

self.thread = threading.Thread(target=self.monitor_link, args=())
self.thread.start()

E como funciona o monitor_link()?  Aqui tenho de pedir desculpas antecipadamente que enquanto o código utiliza menos CPU e memória que chamar um shell script, o tamanho e complexidade é bastante grande.  No fim troquei 2 linhas de código por umas 35 linhas.  Na verdade eu praticamente escrevi o código por trás do "ip link".  Mas o resultado ficou independente desse comando e mesmo de utilizar um shell externo pra buscar o resultado.

A primeira coisa é criar um socket do tipo AF_NETLINK.  Em seguida fazer um bind() num ID aleatório e monitorar com RTMGRP_LINK.

def monitor_link(self):
    # Create the netlink socket and bind to RTMGRP_LINK,
    s = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, socket.NETLINK_ROUTE)
    s.bind((os.getpid(), RTMGRP_LINK))

pra gerar o código aleatório que é um inteiro, usei os.getpid() pra usar o PID do próprio programa.

Em seguida é iniciado um loop com select() em cima do descritor do socket pra leitura.  Quando aparecer algum dado, daí sim a informação é lida.

rlist, wlist, xlist = select.select([s.fileno()], [], [], 1)

O que vem a seguir são quebras da sequência de bits até chegar no ponto é possível ver o tipo de mensagem que chegou do select().  Se o tipo de mensagem for NOOP de algo nulo, apenas continue monitorando no select().  Se vier algum ERROR, pare o programa.  Se vier mensagem e não for do tipo NEWLINK pra um link novo ou mudança de MAC, também continue aguardando no select().

if msg_type == NLMSG_NOOP: continue
elif msg_type == NLMSG_ERROR: break
elif msg_type != RTM_NEWLINK: continue

Por fim uma iteração nos dados pra buscar o tipo.  Se o dado for do tipo IFLA_IFNAME, que é uma nova interface ou mudança de nome, ou IFLA_ADDRESS, que é MAC e endereço IP, muda a flag de network_changed pra True. 

rta_type == IFLA_IFNAME or rta_type == IFLA_ADDRESS:

E é isso.  O código completo segue abaixo.

def monitor_link(self):
    # Create the netlink socket and bind to RTMGRP_LINK,
    s = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, socket.NETLINK_ROUTE)
    s.bind((os.getpid(), RTMGRP_LINK))

    while self.terminating is False:
        rlist, wlist, xlist = select.select([s.fileno()], [], [], 1)
if self.network_changed is True: continue if self.terminating is True: return
try: data = os.read(rlist[0], 65535) except: continue msg_len, msg_type, flags, seq, pid = struct.unpack("=LHHLL", data[:16]) if msg_type == NLMSG_NOOP: continue elif msg_type == NLMSG_ERROR: break elif msg_type != RTM_NEWLINK: continue data = data[16:] family, _, if_type, index, flags, change = struct.unpack("=BBHiII", data[:16]) remaining = msg_len - 32 data = data[16:] while remaining: rta_len, rta_type = struct.unpack("=HH", data[:4]) if rta_len < 4: break rta_data = data[4:rta_len] increment = (rta_len + 4 - 1) & ~(4 - 1) data = data[increment:] remaining -= increment if rta_type == IFLA_IFNAME or rta_type == IFLA_ADDRESS: self.network_changed = True

Encontrei essa implementação no Stack Overflow buscando informação do código em C.  Foi uma grande ajuda e deixou meu programa muito mais coerente com o que eu realmente queria.

Ficou muito maior?  Ficou.  Mas também ficou muito mais 1337 :)

Mais:

[1] Exemplo de uso de python com AMF no OpenSAF: https://sourceforge.net/p/opensaf/staging/ci/default/tree/python/samples/amf_demo

[2] Projeto OpenSAF: https://sourceforge.net/projects/opensaf/

[3] Implementação original desse código: https://stackoverflow.com/questions/44299342/netlink-interface-listener-in-python

Escrito por Helio Loureiro
Categoria:

Tenho escrito pouco aqui, e já passei do prazo de fazer uma retrospectiva de 2017.  Mas antes tarde do que nunca.

Ao invés de escrever, resolvi aderir ao momento multimídia do mundo e fazer em vídeo.  O primeiro é um vídeo de fotos e vídeos meus que peguei direto no Google, no storage onde estão conectados meu smartphone e meu tablet.

O segundo é da coleção de snapshots que o raspberrypi tira a cada 15 minutos da janela de casa. Dá pra ver que no começo e no fim fica bem escuro, enquanto que no meio é mais claro (dias mais curtos no inverno e mais longos no verão).

 

Escrito por Helio Loureiro
Categoria:

Eu gosto de usar os kernels mais recentes e compilar minhas próprias versões.  Às vezes adiciono patches pra melhorar resposta de temporeal, às vezes um suporte pra AUFS no docker.

Atualmente estou com o 4.14-rc2, um pouco antigo nesse momento mas que me deu um uptime de 25 dias sem problemas até agora.

Linux elxaf7qtt32 4.14.0-rc2-helio #12 SMP PREEMPT Fri Sep 29 13:50:19 CEST 2017 x86_64 x86_64 x86_64 OSI/Linux

(é... troquei GNU/Linux por OSI/Linux... por diversão e usando sed na saída do uname)

E descobri que o VirtualBox versão 5.2 simplesmente não consegue rodar o comando /sbin/vboxconfig.  Olhando o erro um pouco mais de perto pelo log:

 

  gcc -Wp,-MD,/tmp/vbox.0/linux/.SUPR0IdcClient-linux.o.d  -nostdinc -isystem /usr/lib/gcc/x86_64-linux-gnu/5/include -I./arch/x86/include -I./arch/x86/include/generated  -I./include -
I./arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/kconfig.h -D__KERNEL__ -Wall -Wundef -Wstrict-prototyp
es -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -Werror-implicit-function-declaration -Wno-format-security -std=gnu89 -fno-PIE -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -
mno-avx -m64 -falign-jumps=1 -falign-loops=1 -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary=3 -mskip-rax-setup -mtune=generic -mno-red-zone -mcmodel=kernel -funit-at-a-time -
DCONFIG_X86_X32_ABI -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -DCONFIG_AS_CFI_SECTIONS=1 -DCONFIG_AS_FXSAVEQ=1 -DCONFIG_AS_SSSE3=1 -DCONFIG_AS_CRC32=1 -DCONFIG_AS_AVX=1 -DCONFIG
_AS_AVX2=1 -DCONFIG_AS_AVX512=1 -DCONFIG_AS_SHA1_NI=1 -DCONFIG_AS_SHA256_NI=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -fno-delete-null-pointer-checks -O2 --param=allow-
store-data-races=0 -DCC_HAVE_ASM_GOTO -Wframe-larger-than=1024 -fstack-protector-strong -Wno-unused-but-set-variable -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-var-tracki
ng-assignments -g -gdwarf-4 -pg -mfentry -DCC_USING_FENTRY -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -fconserve-stack -Werror=implicit-int -Werror=strict-pro
totypes -Werror=date-time -Werror=incompatible-pointer-types -Werror=designated-init -include /tmp/vbox.0/include/VBox/SUPDrvMangling.h -fno-pie -I/lib/modules/4.14.0-rc2-helio/build/i
nclude -I/tmp/vbox.0/ -I/tmp/vbox.0/include -I/tmp/vbox.0/r0drv/linux -D__KERNEL__ -DMODULE -DRT_OS_LINUX -DIN_RING0 -DIN_RT_R0 -DIN_SUP_R0 -DVBOX -DRT_WITH_VBOX -DVBOX_WITH_HARDENING 
-Wno-declaration-after-statement -DRT_ARCH_AMD64 -DVBOX_WITH_64_BITS_GUESTS  -DMODULE  -DKBUILD_BASENAME='"SUPR0IdcClient_linux"'  -DKBUILD_MODNAME='"vboxnetflt"' -c -o /tmp/vbox.0/lin
ux/.tmp_SUPR0IdcClient-linux.o /tmp/vbox.0/linux/SUPR0IdcClient-linux.c
  if [ "-pg" = "-pg" ]; then if [ /tmp/vbox.0/SUPR0IdcClient.o != "scripts/mod/empty.o" ]; then ./scripts/recordmcount  "/tmp/vbox.0/SUPR0IdcClient.o"; fi; fi;
(cat /dev/null;   echo kernel//tmp/vbox.0/vboxnetflt.ko;) > /tmp/vbox.0/modules.order
  if [ "-pg" = "-pg" ]; then if [ /tmp/vbox.0/linux/SUPR0IdcClient-linux.o != "scripts/mod/empty.o" ]; then ./scripts/recordmcount  "/tmp/vbox.0/linux/SUPR0IdcClient-linux.o"; fi; fi;
  if [ "-pg" = "-pg" ]; then if [ /tmp/vbox.0/VBoxNetFlt.o != "scripts/mod/empty.o" ]; then ./scripts/recordmcount  "/tmp/vbox.0/VBoxNetFlt.o"; fi; fi;
/tmp/vbox.0/linux/VBoxNetFlt-linux.c: In function ‘vboxNetFltLinuxSkBufFromSG’:
/tmp/vbox.0/linux/VBoxNetFlt-linux.c:741:24: error: ‘SKB_GSO_UDP’ undeclared (first use in this function)
             fGsoType = SKB_GSO_UDP;
                        ^
/tmp/vbox.0/linux/VBoxNetFlt-linux.c:741:24: note: each undeclared identifier is reported only once for each function it appears in
In file included from /tmp/vbox.0/include/iprt/types.h:29:0,
                 from /tmp/vbox.0/r0drv/linux/the-linux-kernel.h:34,
                 from /tmp/vbox.0/linux/VBoxNetFlt-linux.c:24:
/tmp/vbox.0/linux/VBoxNetFlt-linux.c: In function ‘vboxNetFltLinuxCanForwardAsGso’:
/tmp/vbox.0/linux/VBoxNetFlt-linux.c:1276:53: error: ‘SKB_GSO_UDP’ undeclared (first use in this function)
     if (RT_UNLIKELY( skb_shinfo(pSkb)->gso_type & ~(SKB_GSO_UDP | SKB_GSO_DODGY | SKB_GSO_TCPV6 | SKB_GSO_TCPV4) ))
                                                     ^
/tmp/vbox.0/include/iprt/cdefs.h:1616:53: note: in definition of macro ‘RT_UNLIKELY’
 #  define RT_UNLIKELY(expr)     __builtin_expect(!!(expr), 0)
                                                     ^
/tmp/vbox.0/linux/VBoxNetFlt-linux.c: In function ‘vboxNetFltLinuxForwardToIntNetInner’:
/tmp/vbox.0/linux/VBoxNetFlt-linux.c:1526:47: error: ‘SKB_GSO_UDP’ undeclared (first use in this function)
         if (   (skb_shinfo(pBuf)->gso_type & (SKB_GSO_UDP | SKB_GSO_TCPV6 | SKB_GSO_TCPV4))
                                               ^
scripts/Makefile.build:311: recipe for target '/tmp/vbox.0/linux/VBoxNetFlt-linux.o' failed
make[2]: *** [/tmp/vbox.0/linux/VBoxNetFlt-linux.o] Error 1
Makefile:1498: recipe for target '_module_/tmp/vbox.0' failed
make[1]: *** [_module_/tmp/vbox.0] Error 2
/tmp/vbox.0/Makefile.include.footer:97: recipe for target 'vboxnetflt' failed

Foi algo relacionado com a variável SKB_GSO_UDP, que parece não existir no kernel mais recente ou no VirtualBox.

Buscando pelo termo pude encontrar que realmente existe uma diferença entre ambos um patch precisa ser aplicado, descrito aqui:

Fonte: https://gist.github.com/herbmillerjr/039c129e9c25b047b906e19ad1f23a59

diff --git a/work/vboxnetflt/linux/VBoxNetFlt-linux.c b/work/vboxnetflt/linux/VBoxNetFlt-linux.c
index f824654..b61d82c 100644
--- work/vboxnetflt/linux/VBoxNetFlt-linux.c
+++ work/vboxnetflt/linux/VBoxNetFlt-linux.c
@@ -126,6 +126,10 @@ typedef struct VBOXNETFLTNOTIFIER *PVBOXNETFLTNOTIFIER;
 # endif
 #endif

+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
+#define SKB_GSO_UDP 0
+#endif
+
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 20, 0)
 # define VBOX_HAVE_SKB_VLAN
 #else
diff --git a/work/vboxpci/linux/VBoxPci-linux.c b/work/vboxpci/linux/VBoxPci-linux.c
index 2dbf47f..e361ef3 100644
--- work/vboxpci/linux/VBoxPci-linux.c
+++ work/vboxpci/linux/VBoxPci-linux.c
@@ -353,12 +353,16 @@ static void  vboxPciFileClose(struct file* file)
 static int vboxPciFileWrite(struct file* file, unsigned long long offset, unsigned char* data, unsigned int size)
 {
     int          ret;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
+    ret = kernel_write(file, data, size, &offset);
+#else
     mm_segment_t fs_save;

     fs_save = get_fs();
     set_fs(get_ds());
     ret = vfs_write(file, data, size, &offset);
     set_fs(fs_save);
+#endif
     if (ret < 0)
         printk(KERN_DEBUG "vboxPciFileWrite: error %d\n", ret);

Mas como minha versão de VirtualBox não era exatamente a mesma que essa descrita, acabei fazendo o patch manualmente, que adiciona a variável SKB_GSO_UDP ao VirtualBox caso seja um kernel 4.14.0 ou superior.  Os arquivos para serem modificados no Ubuntu (e possivelmente Debian) são:

  • /usr/share/virtualbox/src/vboxhost/vboxnetflt/linux/VBoxNetFlt-linux.c
  • /usr/share/virtualbox/src/vboxhost/vboxpci/linux/VBoxPci-linux.c

depois basta rodar novamente como root o comando /sbin/vboxconfig para criar os módulos de kernel necessários pro funcionamento do VirtualBox.

SKB_GSO_UDP

SKB: SocKet Buffer

GSO: Generic Segmentation Offloading

UDP: User Datagram Protocol

Não tenho idéia do que isso faz exatamente mas parece ser uma chamada de um pacote UDP encapsulado.

 

Escrito por Helio Loureiro
Categoria:

Sobre o tema de carreira, que parece ter despertado um certo interesse, eu participe a convite do Ivan da gravação de dois episódios do OpenCast no canal Tecnologia Aberta sobre o assunto.  Estávamos eu, Og Maciel, Bruno Rocha, Elyézer Rezende e Tiago Salem, além do próprio Ivan.

Foi um bom bate papo sobre a área de desenvolvimento e inclusive perspectivas de trabalho no exterior.

Opencast #72 - Carreira de Desenvolvedor de Software Livre - parte 1

Opencast #75 - Carreira de Desenvolvedor de Software Livre - parte 2

Unix Load On - RELEASE-170101

E falando ainda de carreira no exterior, eu, Rodolpho Eckhardt, Christiano Linuxmen and Lucas Judocka gravamos no Unix Load On um programa contando como foi nossa experiência pra trabalhar fora, as dificuldades encontradas, socialização, língua e como é a vida atualmente, além de oportunidades no próprio Brasil.  Tudo sob uma perspectiva em relação ao software livre.

Escrito por Helio Loureiro
Categoria:

Não Facebook, nem Google+, nem Twitter e muito menos o Diaspora.  A grande rede social do momento parece mesmo ser o Telegram*.

O Telegram é o novo IRC, ou IRC 2.0.  Um mundo sem fronteiras e controle exercido por moderadores.  Não sei se a sensação é apenas para mim, mas boa parte das conversas de grupos parece que migraram pro Telegram.  De forma fluida e em geral bem descontraída.  É possível criar stickers (adesivos), o que torna a coisa muito engraçada, fazer gifs animados (eu já tenho os meus), e até mesmo bots.  O Telegram trouxe aquela alegria hacker de fazer um monte de coisas que não servem pra nada mas que fazem uma rede crescer.  Lembra o começo do Twitter, quando não tinha a limitação de uso da API e tudo era possível.

Mas o Telegram não é um sistema com indexação.  Então é difícil saber qual grupo participar.  Existem iniciativas pra listar os grupos no github ou um grupo que lista outros grupos de TI, mas em geral a coisa funciona no boca-à-boca.

Existem grupos privados, que são acessíveis somente por convite, e grupos abertos (super grupos) que agora permite até 10.000 pessoas, vários moderadores e níveis diferentes de poder a cada moderador.  E, claro, ainda é possível usar o Telegram da mesma forma que se usa o Whatsapp para mensagens individuais e mesmo chamadas de voz.

Os grupos que participo e recomendo são:

  • Canais e grupos de TI: https://t.me/grupos_ti - Grupo que lista ou tentar listar os demais grupos relacionados com TI.
  • Linux Brasil: https://t.me/linux_brasil - Grupo de discussão de Linux, software livre e coisas completamente aleatórias.  Tem várias discussões políticas também mas é possível sobreviver.
  • Debian Brasil:https://t.me/debian_br - Grupo de discussão sobre Debian**.
  • PyCoding pt-br: https://t.me/PyCoding - Grupo de discussão sobre programação em Python.
  • PyBR #rlz: https://t.me/pythonbr - Grupo mais generalista sobre Python e atividades dentro da comunidade Python Brasil como eventos.
  • SecurityCast: https://t.me/seccast - Grupo de conversas sobre o podcast (ou seria webcast) securitycast com assuntos sobre segurança e criptografia.
  • DockerBR: https://t.me/dockerbr - Grupo sobre Docker.
  • Valhacke, a capital do Telegram: https://t.me/hackncast - Grupo de conversas completamente sem sentido com várias pessoas de vários podcasts como o hack n' cast (original do grupo), Castálio, opencast, etc.  Assunto vai rapidamente sobre ransomwares pra pokemons sem muita cerimônia.  Adoro.
  • UltraOSI: https://t.me/ultraOSI - Da descrição do grupo, "Não seja um iGNUrante,seja um revoluzuero. "Blob!" é a nossa musica oficial: https://ftp.openbsd.org/pub/OpenBSD/songs/song39.mp3 Teste o seu nível de fofosismo e osismo: /fofometro@Stallnoman_Bot".  Muito bom pra dar boas risadas e descontrair.
  • LaTeX BR: https://t.me/latexbr - Grupo pra quem mexe com \latex.
  • UbuntuBR: https://t.me/ulboficial - Grupo de usuários Ubuntu.
  • GNUGRAF: https://t.me/grupoGNUGRAF - Grupo de discussão sobre ferramentas de arte gráfica em software livre.  Vai desde editoração gráfica à fotografia.
  • Shell Script (#! /bin/bash): https://t.me/shellbr - Grupo de dúvidas e discussões sobre shell script.  E tem uns posts simplesmente lindos sobre REGEX.
  • LibreOfficeBR: https://t.me/libreofficebr - Grupo de usuários de LibreOffice.  São discutidas questões sobre fórmulas em planilhas, apresentações, etc.  Bem interessante pra quem usa bastante a suíte de escritório e precisa fugir do "trivial com molho".
  • OsProgramadores: https://t.me/osprogramadores - Grupo para interessados em aprender ou afiar seus conhecimentos em programação.  Muito bom para quem gosta de software craftmanship.
  • Papo de sysadmin: https://t.me/papodesysadmin - Grupo de discussão e dicas pra quem trabalha ou trabalhou como sysadmin ou devops.
  • FreeBSD: https://telegram.me/joinchat/CYyDAUFhgLG8UJfPJrjTUg - Esse é o único grupo que ainda não é um super grupo (por isso não tem url própria), mas é um grupo legal pra falar não só de FreeBSD mas de todas as variantes da família BSD.

 Eu participo de muitos outros grupos, mas esses são os principais.  Sinta-se à vontade para entrar e participar.  Seja pelo app no smartphone ou tablet, ou seja pela web.

[*] Nota: claro que essa percepção pode ser parte da bolha social que cada um participa (ou viés cognitivo).

[**] Update: como o grupo de Debian tava muita xaropada, ainda com o Kretcheu como administrador, eu acabei fazendo um fork e criando outro grupo.  Vou sobreviver a essa grande perda.