Cheap Chinese Camera - Part 3

So, I wanted to extract the running file system from the device. After som fiddling around I realised that the only file-transfer or pipe-tool (like netcat/socat) that existed was wget, and it only supported plain HTTP, not HTTPS.

So I found this static ARMv6 build of well known busybox, that included full sets of tools. So I used it to spawn a temporary FTP-service that I could use to download the filesystem.

# flash partition
cd /npc

# download from http host on local server
wget http://some.local.host/busybox

# make runnable
chmod +x busybox

# create symlink for ftpd
ln -sf busybox ftpd

# run service
./busybox tcpsvd -vE 0.0.0.0 21 /npc/ftpd /

Files

Complete rootfs with mtdblock-partitions (except mtd4 that is /rom)
escam_q1_rootfs.tar.gz (23M)

OpenELEC/Kodi storage on NFS

  1. Do a normal install, boot up the system and enable ssh access.
  2. Create the file /storage/.config/systemd/storage-kodi.mount with the following contents:

    [Unit]
    Description=Kodi NFS Storage
    Requires=network-online.service
    After=network-online.service
    Before=kodi.service
    [Mount]
    What=192.168.1.3:/export/openelec/kodi
    Where=/storage/kodi
    Options=udp,nolock
    Type=nfs
    [Install]
    WantedBy=multi-user.target
    

  3. Enable the job

    systemctl enable storage-kodi.mount

  4. Stop the current running Kodi

    systemctl stop kodi

  5. Mount and move current data, then create symlink

    mkdir /storage/kodi
    mount -t nfs 192.168.1.3:/export/openelec/kodi /storage/kodi
    cp -vr /storage/.kodi/* /storage/kodi/
    rm -rf /storage/.kodi
    ln -sf /storage/kodi /storage/.kodi
    

  6. Start Kodi

    systemctl start kodi

Cheap Chinese Camera - Part 2

So I got this tip that a firmware release actually has telnetd enabled.

Since I already know how the camera checks for new firmware updates, I just spoofed the "latest version" request and tried to trick it into downloading the 22.00.16 release that had telnet enabled.

It worked like a charm and it now runs 22.00.16 and yes, telnetd is indeed enabled. Login with username root and no password.

dmesg

[    0.000000] Booting Linux on physical CPU 0
[    0.000000] Linux version 3.4.43-gk (user15@ubuntu) (gcc version 4.6.1 (crosstool-NG 1.18.0) ) #59 PREEMPT Wed Oct 25 00:10:50 PDT 2006
[    0.000000] CPU: ARMv6-compatible processor [410fb767] revision 7 (ARMv7), cr=00c5387d
[    0.000000] CPU: VIPT aliasing data cache, VIPT aliasing instruction cache
[    0.000000] Machine: Goke GK7102 RB_JXH42 board V2.00
[    0.000000] Memory policy: ECC disabled, Data cache writeback
[    0.000000] AHB: 0x90000000  0xf2000000  -- 0x1000000
[    0.000000] APB: 0xa0000000  0xf3000000  -- 0x1000000
[    0.000000] PPM: 0xc0000000  0xc0000000  -- 0x200000
[    0.000000] BSB: 0xc2800000  0xf5000000  -- 0x200000
[    0.000000] DSP: 0xc2a00000  0xf6000000  -- 0x1600000
[    0.000000] hal version = 20151223 
[    0.000000] On node 0 totalpages: 9728
[    0.000000] free_area_init_node: node 0, pgdat 8045c430, node_mem_map 80493000
[    0.000000]   Normal zone: 76 pages used for memmap
[    0.000000]   Normal zone: 0 pages reserved
[    0.000000]   Normal zone: 9652 pages, LIFO batch:1
[    0.000000] pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
[    0.000000] pcpu-alloc: [0] 0 
[    0.000000] Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 9652
[    0.000000] Kernel command line: console=ttySGK0,115200 noinitrd mem=38M rw mtdparts=gk7101_flash:256K(boot),64K(bootenv),2560K(kernel),7168K(rootfs),1024K(rom),5312K(APP) rootfstype=squashfs root=/dev/mtdblock3 init=linuxrc ip=192.168.1.229:192.168.1.225:192.168.1.1:255.255.255.0:"gk7101":eth0 mac=3C:97:0E:22:E1:14 phytype=0
[    0.000000] PID hash table entries: 256 (order: -2, 1024 bytes)
[    0.000000] Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
[    0.000000] Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
[    0.000000] Memory: 38MB = 38MB total
[    0.000000] Memory: 33832k/33832k available, 5080k reserved, 0K highmem
[    0.000000] Virtual kernel memory layout:
[    0.000000]     vector  : 0xffff0000 - 0xffff1000   (   4 kB)
[    0.000000]     fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
[    0.000000]     DMA     : 0xff600000 - 0xffe00000   (   8 MB)
[    0.000000]     vmalloc : 0x82800000 - 0xff000000   (1992 MB)
[    0.000000]     lowmem  : 0x80000000 - 0x82600000   (  38 MB)
[    0.000000]     modules : 0x7f000000 - 0x80000000   (  16 MB)
[    0.000000]       .text : 0x80008000 - 0x80413000   (4140 kB)
[    0.000000]       .init : 0x80413000 - 0x80433000   ( 128 kB)
[    0.000000]       .data : 0x80434000 - 0x8045cd00   ( 164 kB)
[    0.000000]        .bss : 0x8045cd24 - 0x8048edf8   ( 201 kB)
[    0.000000] NR_IRQS:128
[    0.000000] >> gk7101 init irq vic1...
[    0.000000] >> gk7101 init irq vic2...
[    0.000000] gk7101 init vic...
[    0.000000] mach gk7101 init timer...
[    0.000000] sched_clock: 32 bits at 100 Hz, resolution 10000000ns, wraps every 4294967286ms
[    0.000000] Console: colour dummy device 80x30
[    0.000000] console [ttySGK0] enabled
[    0.010000] Calibrating delay loop... 597.60 BogoMIPS (lpj=2988032)
[    0.070000] pid_max: default: 32768 minimum: 301
[    0.070000] Mount-cache hash table entries: 512
[    0.080000] CPU: Testing write buffer coherency: ok
[    0.090000] Setting up static identity map for 0xc0542e30 - 0xc0542e68
[    0.100000] NET: Registered protocol family 16
[    0.110000] gk7101 init timer...
[    0.110000] Init HW timer for DSP communication
[    0.120000] gk7101 init gpio...
[    0.120000] gpiochip_add: registered GPIOs 0 to 63 on device: gk7101-gpio0
[    0.130000] gpio map init...
[    0.130000] create proc dir
[    0.140000] gk7101 register devices 8
[    0.140000] gk7101 register I2C
[    0.280000] bio: create slab  at 0
[    0.290000] spi spi.0: gk7101 SPI Controller 0 created 
[    0.290000] spi spi.0: master is unqueued, this is deprecated
[    0.300000] usbcore: registered new interface driver usbfs
[    0.310000] usbcore: registered new interface driver hub
[    0.310000] usbcore: registered new device driver usb
[    0.320000] i2c regbase: 0xf3003000 
[    0.320000] i2c i2c.0: i2c irq:registers 9
[    0.330000] i2c i2c.0: GK7101 I2C[0] adapter[i2c-0] probed!
[    0.340000] FS-Cache: Loaded
[    0.340000] CacheFiles: Loaded
[    0.350000] cfg80211: Calling CRDA to update world regulatory domain
[    0.360000] gk7101-sd gk7101-sd.0: Slot0 req_size=0x00010000, segs=16, seg_size=0x00010000
[    0.390000] gk7101-sd gk7101-sd.0: GK7101 SD/MMC[0] has 1 slots @ 46000000Hz, [0x09e130b0:0x00000000]
[    0.400000] NET: Registered protocol family 2
[    0.400000] IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
[    0.410000] TCP established hash table entries: 2048 (order: 2, 16384 bytes)
[    0.420000] TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
[    0.430000] TCP: Hash tables configured (established 2048 bind 2048)
[    0.440000] TCP: reno registered
[    0.440000] UDP hash table entries: 256 (order: 0, 4096 bytes)
[    0.450000] UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
[    0.450000] NET: Registered protocol family 1
[    0.460000] RPC: Registered named UNIX socket transport module.
[    0.470000] RPC: Registered udp transport module.
[    0.470000] RPC: Registered tcp transport module.
[    0.480000] RPC: Registered tcp NFSv4.1 backchannel transport module.
[    0.490000] mdma init...
[    0.490000] mdma request irq: 54 
[    0.500000] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[    0.500000] NFS: Registering the id_resolver key type
[    0.510000] jffs2: version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
[    0.520000] msgmni has been set to 66
[    0.530000] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 253)
[    0.540000] io scheduler noop registered
[    0.540000] io scheduler deadline registered
[    0.550000] io scheduler cfq registered (default)
[    0.550000] Serial: gk7101_uart driver
[    0.550000] serial_gk7101_probe: entry
[    0.550000] uart.0: ttySGK0 at MMIO 0xa0005000 (irq = 31) is a gk7101uart
[    0.560000] serial_gk7101_probe: succeed!
[    0.560000] serial_gk7101_probe: entry
[    0.560000] uart.1: ttySGK1 at MMIO 0xa001f000 (irq = 15) is a gk7101uart
[    0.570000] serial_gk7101_probe: succeed!
[    0.570000] serial_gk7101_probe: entry
[    0.570000] uart.2: ttySGK2 at MMIO 0xa001e000 (irq = 27) is a gk7101uart
[    0.580000] serial_gk7101_probe: succeed!
[    0.590000] brd: module loaded
[    0.590000] loop: module loaded
[    0.600000] adc initialized (10:11)
[    0.600000] slram: not enough parameters.
[    0.610000] speed_mod is 0
[    0.610000] support 4X mode read:0xe520f1ff
[    0.620000] gk7101_flash gk7101_flash.0: MX25L12845 (16384 Kbytes)
[    0.620000] 6 cmdlinepart partitions found on MTD device gk7101_flash
[    0.630000] Creating 6 MTD partitions on "gk7101_flash":
[    0.640000] 0x000000000000-0x000000040000 : "boot"
[    0.640000] 0x000000040000-0x000000050000 : "bootenv"
[    0.650000] 0x000000050000-0x0000002d0000 : "kernel"
[    0.660000] 0x0000002d0000-0x0000009d0000 : "rootfs"
[    0.660000] 0x0000009d0000-0x000000ad0000 : "rom"
[    0.670000] 0x000000ad0000-0x000001000000 : "APP"
[    0.680000] GKETH_init
[    0.680000] [GKETH_drv_probe] eth_base = 0xf200e000
[    0.690000] mii id = 0 
[    0.690000] ###### PHY Reset.1.0.2
[    0.810000] mdiobus_register: PHY[0] whose id 0x00000000 
[    0.810000] goke MII Bus: probed
[    0.820000] gk7101-eth gk7101-eth.0: MAC Address[3e:97:0e:22:e1:14].
[    0.830000] usbcore: registered new interface driver cdc_wdm
[    0.830000] usbcore: registered new interface driver libusual
[    0.840000] musb-hdrc: version 6.0, ?dma?, otg (peripheral+host)
[    0.850000] musb phy Begin initial sequence ...
[    1.090000] gk7101 musb init end...
[    1.100000] musb-hdrc: ConfigData=0x03 (UTMI-16, SoftConn)
[    1.100000] musb-hdrc: MHDRC RTL version 2.0 
[    1.100000] musb-hdrc musb-hdrc: MUSB HDRC host driver
[    1.100000] musb-hdrc musb-hdrc: new USB bus registered, assigned bus number 1
[    1.110000] vm : ffde0000, phy : c21a0000
[    1.110000] dma_buf alloc ok!
[    1.120000] hub 1-0:1.0: USB hub found
[    1.120000] hub 1-0:1.0: 1 port detected
[    1.130000] musb-hdrc musb-hdrc: USB Host mode controller at f0006000 using PIO, IRQ 26
[    1.140000] platform add gk7101 musb...
[    1.140000] mousedev: PS/2 mouse device common for all mice
[    1.150000] input: GKInput as /devices/virtual/input/input0
[    1.150000] evbug: Connected device: input0 (GKInput at gk7101/input0)
[    1.150000] Protocol NEC[0]
[    1.160000] ir request irq: 62 
[    1.160000] IR Host Controller probed!
[    1.170000] gk7101 rtc init...
[    1.170000] rtc base: 0xf2080000 
[    1.170000] os read tm: t=0 
[    1.180000] gk7101-rtc: dev (254:0)
[    1.180000] gk7101-rtc gk7101-rtc: rtc core: registered gk7101-rtc as rtc0
[    1.180000] i2c /dev entries driver
[    1.190000] gk7101_wdt: GK7101 Watchdog Timer, (c) 2014 Goke Microelectronics
[    1.200000] [gk7101_wdt_init]: init
[    1.200000] [gk7101_wdt_probe]: probe
[    1.200000] [gk7101_wdt_probe]: probe mapped wdt_base=f3006000
[    1.210000] watchdog inactive, reset disabled, irq disabled
[    1.220000] IPv4 over IPv4 tunneling driver
[    1.220000] gre: GRE over IPv4 demultiplexor driver
[    1.230000] ip_gre: GRE over IPv4 tunneling driver
[    1.240000] TCP: cubic registered
[    1.240000] Initializing XFRM netlink socket
[    1.250000] NET: Registered protocol family 10
[    1.250000] IPv6 over IPv4 tunneling driver
[    1.260000] NET: Registered protocol family 17
[    1.270000] NET: Registered protocol family 15
[    1.270000] lib80211: common routines for IEEE802.11 drivers
[    1.280000] lib80211_crypt: registered algorithm 'NULL'
[    1.280000] Registering the dns_resolver key type
[    1.280000] VFP support v0.3: implementor 41 architecture 1 part 20 variant b rev 5
[    1.290000] os read tm: t=0 
[    1.300000] gk7101-rtc gk7101-rtc: setting system clock to 1970-01-01 00:00:00 UTC (0)
[    1.310000] net eth0: ###### GKETH_start_hw
[    1.310000] net eth0: DMA Error: Check PHY.
[    1.320000] eth open error
[    1.320000] net eth0: ###### GKETH_phy_stop
[    1.320000] IP-Config: Failed to open eth0
[    1.330000] IP-Config: Device `eth0' not found
[    1.340000] VFS: Mounted root (squashfs filesystem) readonly on device 31:3.
[    1.350000] Freeing init memory: 128K
[    1.590000] usb 1-1: new high-speed USB device number 2 using musb-hdrc
[    6.430000] gk_vi_init
[    6.450000]  request_irq...24 ok-- video_sync
[    6.470000]  request_irq...59 ok-- video_frame_last_pixel
[    6.470000]  request_irq...61 ok-- video_frame
[    6.490000]  gk7101_is_valid_gpio_irq...
[    6.650000] crypto initialized (10:11)
Media driver version (gcc version 4.6.1 (crosstool-NG 1.18.0) (uClibc)) v1.1.2 #svn r8850 Wed Jul 6 17:44:23 CST 2016
[    6.860000] Init software HR timer for DSP communication
[    9.600000] rtusb init rt2870 --->
[    9.630000] 
[    9.630000] 
[    9.630000] === pAd = 82a82000, size = 1581168 ===
[    9.630000] 
[    9.650000] <-- RTMPAllocTxRxRingMemory, Status=0
[    9.650000] <-- RTMPAllocAdapterBlock, Status=0
[    9.670000] RTMP_COM_IoctlHandle():pAd->BulkOutEpAddr=0x8
[    9.670000] RTMP_COM_IoctlHandle():pAd->BulkOutEpAddr=0x4
[    9.690000] RTMP_COM_IoctlHandle():pAd->BulkOutEpAddr=0x5
[    9.690000] RTMP_COM_IoctlHandle():pAd->BulkOutEpAddr=0x6
[    9.710000] RTMP_COM_IoctlHandle():pAd->BulkOutEpAddr=0x7
[    9.710000] RTMP_COM_IoctlHandle():pAd->BulkOutEpAddr=0x9
[    9.720000] STA Driver version-JEDI.MP1.mt7601u.v1.5
[    9.730000] Compile time-Jul 26 2006,19:39:19
[    9.730000] ==>WaitForAsicReady MAC_CSR0=0x76010500
[    9.740000] ==>WaitForAsicReady MAC_CSR0=0x76010500
[    9.740000] NVM is EFUSE
[    9.750000] Endpoint(8) is for In-band Command
[    9.750000] Endpoint(4) is for WMM0 AC0
[    9.770000] Endpoint(5) is for WMM0 AC1
[    9.770000] Endpoint(6) is for WMM0 AC2
[    9.770000] Endpoint(7) is for WMM0 AC3
[    9.780000] Endpoint(9) is for WMM1 AC0
[    9.780000] Endpoint(84) is for Data-In
[    9.790000] Endpoint(85) is for Command Rsp
[    9.790000] 80211> RFICType = 3
[    9.800000] NumOfChan ===> 58
[    9.800000] 80211> Number of channel = 0x44
[    9.810000] 80211> Number of rate = 12
[    9.810000] 80211> CurTxPower = 0 dBm
[    9.820000] 80211> TxStream = 0
[    9.820000] crda> requlation requestion by core: 00
[    9.840000] 80211> CFG80211_Register
[    9.840000] MSC msc_proc_create: 82a82000
[    9.880000] usbcore: registered new interface driver rt2870
[   14.560000] sensor board reset...
[   14.940000] jxh42 sensor addr is 0x60, ID is 0xa042
[   14.980000] jxh42 sensor version is 0x81
[   15.000000] sensor board reset...
[   15.910000] net eth0: ###### GKETH_start_hw
[   15.910000] net eth0: DMA Error: Check PHY.
[   15.940000] eth open error
[   15.940000] net eth0: ###### GKETH_phy_stop
[   15.940000] ================> UP : RTMP_SEM_EVENT_WAIT(STA)
[   15.960000] 1. LDO_CTR0(6c) = a6478d, PMU_OCLEVEL 6
[   15.960000] 2. LDO_CTR0(6c) = a6478d, PMU_OCLEVEL 6
[   15.980000] ==>WaitForAsicReady MAC_CSR0=0x76010500
[   15.990000] RTMP_TimerListAdd: add timer obj 82baa764!
[   16.000000] RTMP_TimerListAdd: add timer obj 82baa794!
[   16.010000] RTMP_TimerListAdd: add timer obj 82baa7c4!
[   16.010000] RTMP_TimerListAdd: add timer obj 82baa734!
[   16.020000] RTMP_TimerListAdd: add timer obj 82baa6a4!
[   16.030000] RTMP_TimerListAdd: add timer obj 82baa6d4!
[   16.030000] RTMP_TimerListAdd: add timer obj 82b3ecdc!
[   16.040000] RTMP_TimerListAdd: add timer obj 82b2b5d0!
[   16.050000] RTMP_TimerListAdd: add timer obj 82b2b604!
[   16.050000] RTMP_TimerListAdd: add timer obj 82b3ed7c!
[   16.090000] RTMP_TimerListAdd: add timer obj 82b2df80!
[   16.090000] RTMP_TimerListAdd: add timer obj 82b2d7c0!
[   16.100000] RTMP_TimerListAdd: add timer obj 82b2df4c!
[   16.100000] RTMP_TimerListAdd: add timer obj 82b2e29c!
[   16.110000] RTMP_TimerListAdd: add timer obj 82b2dfb4!
[   16.120000] RTMP_TimerListAdd: add timer obj 82b2dfe8!
[   16.120000] RTMP_TimerListAdd: add timer obj 82b2e01c!
[   16.130000] RTMP_TimerListAdd: add timer obj 82a8640c!
[   16.140000] RTMP_TimerListAdd: add timer obj 82a85c4c!
[   16.140000] RTMP_TimerListAdd: add timer obj 82a863d8!
[   16.150000] RTMP_TimerListAdd: add timer obj 82a86728!
[   16.160000] RTMP_TimerListAdd: add timer obj 82a8665c!
[   16.160000] RTMP_TimerListAdd: add timer obj 82abd684!
[   16.170000] RTMP_TimerListAdd: add timer obj 82abcec4!
[   16.190000] RTMP_TimerListAdd: add timer obj 82abd650!
[   16.190000] RTMP_TimerListAdd: add timer obj 82abd9a0!
[   16.220000] RTMP_TimerListAdd: add timer obj 82abd6b8!
[   16.220000] RTMP_TimerListAdd: add timer obj 82abd6ec!
[   16.230000] RTMP_TimerListAdd: add timer obj 82abd720!
[   16.230000] RTMP_TimerListAdd: add timer obj 82b3ec7c!
[   16.240000] RTMP_TimerListAdd: add timer obj 82b3ed4c!
[   16.250000] RTMP_TimerListAdd: add timer obj 82c01d20!
[   16.250000] RTMP_TimerListAdd: add timer obj 82c01d50!
[   16.260000] RTMP_TimerListAdd: add timer obj 82c01d80!
[   16.270000] RTMP_TimerListAdd: add timer obj 82c01db0!
[   16.270000] RTMP_TimerListAdd: add timer obj 82c01de0!
[   16.280000] RTMP_TimerListAdd: add timer obj 82c01e14!
[   16.290000] RTMP_TimerListAdd: add timer obj 82baa704!
[   16.290000] RTMP_TimerListAdd: add timer obj 82b2a5ec!
[   16.300000] RTMP_TimerListAdd: add timer obj 82b2a5bc!
[   16.340000] RTMP_TimerListAdd: add timer obj 82b2a58c!
[   16.340000] RTMP_TimerListAdd: add timer obj 82b3ecac!
[   16.360000] P2pGroupTabInit .
[ 16.360000] P2pScanChannelDefault <=== count = 3, Channels are 1, 6,11 separately
[ 16.380000] P2pCfgInit:: [ 16.380000] ==>WaitForAsicReady MAC_CSR0=0x76010500 [ 17.040000] cfg_mode=9 [ 17.040000] cfg_mode=9 [ 17.070000] wmode_band_equal(): Band Equal! [ 17.070000] Key1Str is Invalid key length(0) or Type(0) [ 17.100000] Key2Str is Invalid key length(0) or Type(0) [ 17.100000] Key3Str is Invalid key length(0) or Type(0) [ 17.130000] Key4Str is Invalid key length(0) or Type(0) [ 17.130000] ###### Force at HT20 (BW_20) mode !!! ######## [ 17.190000] 1. Phy Mode = 14 [ 17.190000] 2. Phy Mode = 14 [ 17.190000] NVM is Efuse and its size =1d[1e0-1fc] [ 17.230000] ERROR!!! MT7601 E2PROM: WRONG VERSION 0xc, should be 9 [ 17.300000] 3. Phy Mode = 14 [ 17.300000] AntCfgInit: primary/secondary ant 0/1 [ 17.530000] ---> InitFrequencyCalibration [ 17.530000] InitFrequencyCalibrationMode:Unknow mode = 3 [ 17.550000] InitFrequencyCalibration: frequency offset in the EEPROM = 109(0x6d) [ 17.550000] <--- InitFrequencyCalibration [ 17.570000] RTMPSetPhyMode: channel is out of range, use first channel=1 [ 17.580000] MCS Set = ff 00 00 00 01 [ 17.610000] <==== STA : rt28xx_init, Status=0 [ 17.650000] 80211> re-init bands... [ 17.650000] 80211> RFICType = 1 [ 17.700000] NumOfChan ===> 14 [ 17.700000] 80211> Number of channel = 0x44 [ 17.700000] 80211> Number of rate = 12 [ 17.750000] 80211> CurTxPower = 0 dBm [ 17.750000] 80211> TxStream = 1 [ 17.760000] 0x1300 = 00064300 [ 17.760000] RTMPDrvOpen(1):Check if PDMA is idle! [ 17.800000] RTMPDrvOpen(2):Check if PDMA is idle! [ 17.800000] <================ UP : RTMP_SEM_EVENT_UP(STA) [ 21.590000] sensor board reset... [ 23.490000] ==>rt_ioctl_siwfreq::SIOCSIWFREQ(Channel=13) [ 23.590000] PeerBeaconAtJoinAction(): HT-CtrlChannel=13, CentralChannel=>13 [ 23.590000] PeerBeaconAtJoinAction(): Set CentralChannel=13 [ 23.680000] jxh42_set_video_mode errorCode = 00000000! [ 24.310000] win_height:0 win_width:0 [ 24.310000] win_height:0 win_width:0 [ 25.180000] RTMP_TimerListAdd: add timer obj 82bfa518! [ 25.200000] Rcv Wcid(1) AddBAReq [ 25.210000] Start Seq = 00000004 [ 25.220000] RTMP_TimerListAdd: add timer obj 82bfc528! [ 28.520000] wlan0: no IPv6 routers present [ 29.030000] RTMP_TimerListAdd: add timer obj 82bfa558! [ 43.720000] FrequencyCalibration:MT7601 receive OFDM beacon. [ 53.800000] FrequencyCalibration:MT7601 receive OFDM beacon.

mount

rootfs on / type rootfs (rw)
/dev/root on / type squashfs (ro,relatime)
proc on /proc type proc (rw,relatime)
tmpfs on /dev type tmpfs (rw,relatime)
tmpfs on /tmp type tmpfs (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
devpts on /dev/pts type devpts (rw,relatime,mode=600,ptmxmode=000)
/dev/ram0 on /mnt/ramdisk type tmpfs (rw,relatime)
/dev/ram0 on /etc type tmpfs (rw,relatime)
/dev/ram0 on /tmp type tmpfs (rw,relatime)
/dev/mtdblock4 on /rom type jffs2 (rw,relatime)
/dev/mtdblock5 on /npc type jffs2 (rw,relatime)

# cat /proc/cpuinfo
Processor       : ARMv6-compatible processor rev 7 (v6l)
BogoMIPS        : 597.60
Features        : swp half fastmult vfp edsp java tls 
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xb76
CPU revision    : 7

Hardware        : Goke GK7102 RB_JXH42 board V2.00
Revision        : 0000
Serial          : 0000000000000000

# cat /proc/mtd 
dev:    size   erasesize  name
mtd0: 00040000 00010000 "boot"
mtd1: 00010000 00010000 "bootenv"
mtd2: 00280000 00010000 "kernel"
mtd3: 00700000 00010000 "rootfs"
mtd4: 00100000 00010000 "rom"
mtd5: 00530000 00010000 "APP"

Debian on ReadyNAS Duo v2

Before the purchase I found this older teardown and HowTo, that proved that it was fully possible at least. However it was quite dated and targeted against an older Debian release. I browsed the installer files of Debian Jessie (8) and tried figure out how to apply same installation method but with a new release.

However, After a first trial install of Jessie, I noticed that the kernel (3.16.0) lacks some features (Real time clock, full Marvell CESA support etc.) I did a new test install with the upcoming Stretch (9.0) with a updated 4.9.0 kernel, and now everything seems to work.

  1. Setup a TFTP service on a host of your choice.

  2. You need to establish a bootloader serial console just as in the HowTo mentioned earlier. Beware, It's 3.3V TTL level serial.

  3. Debian unfortunally doesn't provide a ReadyNAS Duo v2 kernel image that works with the old Netgear uBoot, so we have to package our own. Grab the default kernel and the Device-Tree binary for the machine. Then stack the Device-Tree binary after the kernel image file to a new combined file.

    wget http://ftp.se.debian.org/debian/dists/stretch/main/installer-armel/current/images/kirkwood/netboot/vmlinuz-4.9.0-1-marvell
    wget http://ftp.se.debian.org/debian/dists/stretch/main/installer-armel/current/images/kirkwood/device-tree/kirkwood-netgear_readynas_duo_v2.dtb
    cat vmlinuz-4.9.0-1-marvell kirkwood-netgear_readynas_duo_v2.dtb >> vmlinuz-dtb
    

  4. Convert the vmlinuz-dtb image to a uboot image with mkimage

    mkimage -A arm -O linux -T kernel -C none -a 0x8000 -e 0x8000 -n "Debian RND2 kernel" -d vmlinuz-dtb /srv/tftp/uImage-rnd2
    

  5. I then used the installer-initrd for the Sheevaplug ESATA witch is very smilar and should work fine for the install.

    wget http://ftp.se.debian.org/debian/dists/stretch/main/installer-armel/current/images/kirkwood/netboot/marvell/sheevaplug-esata/uInitrd
    mv uInitrd /srv/tftp/uInitrd
    

  6. Bring up the bootloader console (just hit any key at startup) and do the following.

    setenv autoload no
    dhcp
    set serverip 192.168.1.3
    tftpboot 1200000 uImage-rnd2
    tftpboot 2000000 uInitrd
    set bootargs console=ttyS0,115200 earlyprintk
    bootm 0x1200000 0x2000000
    

  7. You should now end up in a Debian installer. Just follow the installer as any normal install. When you are about to finish (The question of "Go back"/"Continue"), Go back and Execute shell. The chroot to the installation target.

    mount --bind /dev /target/dev
    mount -t proc none /target/proc
    mount -t sysfs none /target/sys
    chroot /target /bin/bash
    apt-get install flash-kernel
    

  8. Use the following machine configuration in /etc/flashkernel/db

    Machine: NETGEAR ReadyNAS Duo v2
    DTB-Id: kirkwood-netgear_readynas_duo_v2.dtb
    DTB-Append: yes
    Mtd-Kernel: uImage
    Mtd-Initrd: minirootfs
    U-Boot-Kernel-Address: 0x08000
    U-Boot-Initrd-Address: 0x0
    Required-Packages: u-boot-tools
    Bootloader-Sets-Incorrect-Root: yes
    
    This basically tells whenever there is a new kernel or initrd, you should also append the DTB and create uBoot compatible images, then write those to the MTD/NAND partitions uImage and minirootfs (see dmesg or /proc/mtd) We will not alter the original MTD/NAND layout, thus no need to change uBoot environment parameters, since we have plenty of space for kernel and initrd. As long as we don't touch the 0x000000000000-0x0000001a0000 region in NAND/Flash, we can always use uBoot to load & flash new data and images. If unsure, check dmesg or cat /proc/mtd to make sure that the MTD partition layout is correctly detected. If the bootloader area is overwritten then the device is "bricked" and can only be restored with lower level JTAG of the Marvell SoC.

  9. Install kernel and build new initrd

    apt-get install linux-image-marvell
    mkinitramfs -u
    

  10. When done and you see that the kernel and initrd is written to NAND, exit out to install program again and reboot system. It should look like this:

update-initramfs: Generating /boot/initrd.img-4.9.0-1-marvell

Using DTB: kirkwood-netgear_readynas_duo_v2.dtb
Installing /usr/lib/linux-image-4.9.0-1-marvell/kirkwood-netgear_readynas_duo_v2.dtb into /boot/dtbs/4.9.0-1-marvell/kirkwood-netgear_readynas_duo_v2.dtb
Taking backup of kirkwood-netgear_readynas_duo_v2.dtb.
Installing new kirkwood-netgear_readynas_duo_v2.dtb.
Installing /usr/lib/linux-image-4.9.0-1-marvell/kirkwood-netgear_readynas_duo_v2.dtb into /boot/dtbs/4.9.0-1-marvell/kirkwood-netgear_readynas_duo_v2.dtb
Taking backup of kirkwood-netgear_readynas_duo_v2.dtb.
Installing new kirkwood-netgear_readynas_duo_v2.dtb.
flash-kernel: installing version 4.9.0-1-marvell
flash-kernel: appending /usr/lib/linux-image-4.9.0-1-marvell/kirkwood-netgear_readynas_duo_v2.dtb to kernel
Generating kernel u-boot image... done.
Erasing 128 Kibyte @ 7f631f5c00000064 -- 48 % complete 
Writing data to block 0 at offset 0x0
...8<...
Writing data to block 15 at offset 0x1e0000
done.
Generating initramfs u-boot image... done.
Erasing 128 Kibyte @ 7f5d0f5c00000064 -- 128 % complete 
Writing data to block 0 at offset 0x0
...8<...
Writing data to block 43 at offset 0x560000
done.

The system is fully capable to run BorgBackup and actually performs a decent ~60Mbps SSH traffic with some tweaks. To take advantage of the Marvell CESA cryptographic accelerator, use the following configuration in /etc/ssh/sshd_config

# Custom ciphers to use marvell_cesa
Ciphers             aes128-cbc,aes192-cbc,aes256-cbc,3des-cbc
MACs                hmac-sha1,hmac-md5

You also need to specify this in you client configuration (~/.ssh/config)

G762 fan driver

arno@natisbad.org have also done some great work to make the G762 fan driver chip. This is unfortunally missing from the standard Debian kernel image. I didn't feel like recompiling a custom kernel, so I've just extracted the the module from a kernel build a did.

You can find it here:
http://files.adamwesterberg.se/linux/netgear_rnd2/stretch/modules/

Put it under /lib/modules/4.9.0-1-marvell/kernel/drivers/hwmon/ and run depmod -a, then add it to /etc/modules

Further explanation

The stock MTD/NAND layout looks like this:

Creating 5 MTD partitions on "nand_mtd":
0x000000000000-0x000000180000 : "u-boot"
0x000000180000-0x0000001a0000 : "u-boot-env"
0x000000200000-0x000000800000 : "uImage"             ~6M
0x000000800000-0x000001800000 : "minirootfs"         ~16M
0x000001800000-0x000008000000 : "jffs2"              ~10M

The bootcmd parameter of uBoot says:

nand read.e 0x1200000 0x200000 0x600000
nand read.e 0x2000000 0x800000 0x1000000
bootm 0x1200000 0x2000000

You see the connection? :)

References

Cheap Chinese camera teardown

Specifications

It does however, have som decent specifications

  • 1280x720p h.264 video over RTSP
  • 802.11bgn single chain wireless
  • Microphone & speaker
  • microSD/TF slot
  • Some ONVIF compatibility
  • Solenoid IR-cut filter for night/day-vision
  • Infrared LEDs for night

Hardware

The SoC is quite a beast.

Then there is some OP-amps for speaker/microphone and voltage regulation.

Software

This is were the total meltdown is, as usual. The camera is discovered and controlled by an obscure unknown UDP protocol of some kind. It has to register to a Chinese cloud service called Cloudlinks then you have to use a very dodgy Android/iOS application called Yoosee to manage the registered devices. The Yoosee app is also used to configure the WiFi via a quite innovative "transmit by sound" technique.

The authentication also doesn't make sense and is probably very insecure.

Fortunately, it's accessible via RTSP with the URL rtsp://camera-ip:554/onvif1. And it will work fine without Internet-access. It also has a ONVIF SOAP interface on TCP port 5000, but it's quite unusable.

Reverse engineering

The real software author of the camera seems to be GWellTimes and the software product seems to be is named NPC, and the actual product might be this one.

The camera tries to contact the following servers on UDP/51700 or UDP/51880, then it uses more random UDP ports. It actually looks like some kind of tunnel. After I configured mine, I firewalled it for internet-access.

60.205.107.59       (Aliyun Computing Co., LTD)
104.250.144.74      (GorillaServers, Inc. (GORIL-3))
85.195.88.14        (Jeff King, jeff9023@gmail.com)
220.231.142.84      (Shenzhen Runxun Data Communication Co. Ltd.)
114.67.48.145       (Vcloud, Beijing Internet Harbor Technology Co.,Ltd)
183.202.215.187     (China Mobile Communications Corporation?)

It also tried to check for updated on some servers

http://upg.cloudlinks.cn/upg/22/00/latestversion.asp?ID=XXXXXX&MAC=XXXXXX&SEID=XXXXXXX&MVS=22.00.00.10&SubType=0

If it gets a response that there is a higher software available, it fetches it

http://upg.cloudlinks.cn/upg/22/00/npcupg_22.00.00.14.bin

The file it downloads seems to be some kind of firmware at first, consisting of a JFFS2 filesystem and a binary ending

$ binwalk npcupg_22.00.00.14.bin
DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
32            0x20            JFFS2 filesystem, little endian
3054100       0x2E9A14        ELF, 32-bit LSB executable, ARM, version 1 (SYSV)

If we unpack the JFFS2 filesystem, we can see that it's only a form av upgrade package, since it lacks kernel and a ordinary linux root filesystem. Probably it's only targeted to a flash partition for OEM customization. It seems to support various camera sensors. The config/*.xml contains video encoding settings.

Main application seems to be npc (4M), and gwellipc (997K) for more basic functions.

└── fs_1
    ├── boot.sh
    ├── config
    │   ├── image_ar0130.xml
    │   ├── image_h42.xml
    │   ├── image_sc1135.xml
    │   ├── image_sc2135.xml
    │   ├── video_ar0130.xml
    │   ├── video_h42.xml
    │   ├── video_sc1135_bak.xml
    │   ├── video_sc1135.xml
    │   └── video_sc2135.xml
    ├── config-鱼眼-20161124.rar
    ├── dhcp.script
    ├── gwellipc
    ├── language
    │   ├── cf
    │   │   └── PushMesg.txt
    │   ├── ch
    │   │   └── PushMesg.txt
    │   └── en
    │       └── PushMesg.txt
    ├── minihttpd.conf
    ├── npc
    ├── patch
    │   ├── ar0130.ko
    │   ├── dsa.ko
    │   ├── gpioi2c1.ko
    │   ├── gpioi2c.ko
    │   ├── hi_gpio.ko
    │   ├── jxh42.ko
    │   ├── motor_drv.ko
    │   ├── sc1035.ko
    │   ├── sc1135.ko
    │   ├── sc1145.ko
    │   └── sc2135.ko
    ├── readme.txt
    ├── sensors
    │   ├── ar0130.bin
    │   ├── jxh42.bin
    │   ├── sc1035.bin
    │   ├── sc1135.bin
    │   ├── sc1145.bin
    │   └── sc2135.bin
    ├── sound
    │   ├── alarm_1.amr
    │   ├── alarm_2.amr
    │   ├── alarm_3.amr
    │   ├── alarm_4.amr
    │   ├── alarm_5.amr
    │   ├── alarm_6.amr
    │   ├── alarm.amr
    │   ├── beingcalled.amr
    │   ├── calling.amr
    │   ├── ch
    │   │   ├── wifi_ap_mode.amr
    │   │   └── wifi_sta_mode.amr
    │   ├── clear.amr
    │   ├── di.amr
    │   ├── DoorBell.amr
    │   ├── en
    │   │   ├── wifi_ap_mode1.amr
    │   │   ├── wifi_ap_mode.amr
    │   │   ├── wifi_sta_mode1.amr
    │   │   └── wifi_sta_mode.amr
    │   ├── key_press.amr
    │   ├── numbers_ch
    │   │   ├── 0.amr
    │   │   ├── 1.amr
    │   │   ├── 2.amr
    │   │   ├── 3.amr
    │   │   ├── 4.amr
    │   │   ├── 5.amr
    │   │   ├── 6.amr
    │   │   ├── 7.amr
    │   │   ├── 8.amr
    │   │   └── 9.amr
    │   ├── Reset_ch.amr
    │   ├── Reset_en.amr
    │   ├── set.amr
    │   ├── set_fail.amr
    │   ├── set_ok.amr
    │   ├── Unlock.amr
    │   ├── WifiLink_ch
    │   │   ├── LinkFail_again_ch.amr
    │   │   ├── Linking_ch.amr
    │   │   ├── LinkOk_ch.amr
    │   │   └── WaitLink_ch.amr
    │   └── WifiLink_en
    │       ├── LinkFail_again_en.amr
    │       ├── Linking_en.amr
    │       ├── LinkOk_en.amr
    │       └── WaitLink_en.amr
    ├── upgfile_ok
    └── version.txt

14 directories, 81 files

The strings of the binary data at 0x2E9A14 also reveals some interesting lines.

$ strings endbinarydata.bin 
/mnt/disc1/flash_erase
/patch/bin/flash_erase
/mnt/disc1/flashcp
/patch/bin/flashcp
/dev/mtd5
reboot -f

Probably a upgrade program in some way, that writes the JFFS2 to to mtd5 partition maybe?

Drawbacks

  • Initial configuration needs to be done via Yoosee app, and needs online cloud registration to activate.
  • No simple web interface, only configurable by app or Windows "CMS" software
  • Video only, no JPEG stills
  • Video bitrate/quality is not possible to configure, usually about ~1-2Mbps.
  • Doesn't care about NTP options via DHCP - seems to sync tome via UDP cloud tunnel.
  • No complete firmware files available anywhere

I will in time try to get root access to the device, and see if i can change the video encoding bitrate and if it's possible to output (M)JPEG via the built in web server.

MQTT in Splunk

The sensor network consist of various Arduino-based nodes. Both AVR and ESP8622-based, using 433Mhz modules or WiFi in the later case.

I also have made a mobile micro-dashboard (not Splunk related) public for accessing when I'm not at home. It's a simple JQuery-made thing that fetches a JSON file held in memory, that contains the latest values sent via the MQTT network. If a value is older than 1 hour a red warning triangle will show to indicate that the value might not be updated.

Sorry for the Swedish. It says Kitchen, Fridge, Freezer, Balcony and Basement.

IPsec VPN - RouterOS and FreeBSD

FreeBSD suggests using Racoon as the IKE daemon, and I buy that recommendation since RouterOS also uses racoon internally (hint: look at the ipsec,debug)

But this "simple"-tunnel method of RouterOS it a bit tricky to replicate on a default racoon setup. In this example I will use a IP-in-IP tunnel (also called ipencap) and has IP Protocol 4 (IP/4), but using a GRE (IP/47) should also be fine.

  • Route-based tunnel - not Proxy/Policy-based
  • Using IP-in-IP tunnel type ("ipencap" / IP Protocol 4)
  • Site A tunnel endpoint - 192.168.254.1/32
  • Site A local network - 192.168.1.0/24
  • Site B tunnel endpoint - 192.168.254.2/32
  • Site B local network - 192.168.2.0/24

SITE_A_IP and SITE_B_IP is the corresponding public IP-addresses. This howto doesn't cover any required firewall openings.

This is what I found out and works.

Site A - RouterOS

1. Setup tunnel interface on RouterOS, and setup a linknet

/interface ipip
add name=tun1 ipsec-secret=XXXXXXXXXX local-address=SITE_A_IP remote-address=SITE_B_IP
/ip address
add address=192.168.254.1/30 interface=tun1
/ip route
add dst-address=192.168.2.0/24 gateway=192.168.254.2

You're done on RouterOS.

Site B - FreeBSD

1. Setup tunnel interface and services on your FreeBSD (or similar system)

/etc/rc.conf:

cloned_interfaces="gif0"
ifconfig_gif0="inet 192.168.254.2 192.168.254.1 netmask 255.255.255.255 tunnel SITE_B_IP SITE_A_IP"
racoon_enable="YES"
ipsec_enable="YES"
ipsec_file="/usr/local/etc/racoon/setkey.conf"

gateway_enable="YES"
static_routes="net1"
route_net1="-net 192.168.1.0/24 192.168.250.1"

2. Configuration for racoon. Please note the "address SITE_B_IP 4 address SITE_A_IP 4" where the 4 is for ipencap (IP/4) tunnel packets.

/usr/local/etc/racoon/racoon.conf:

path pre_shared_key "/usr/local/etc/racoon/psk.txt";
log notify;

listen {
    isakmp          SITE_B_IP [500];
}

remote SITE_A_IP [500] {
    exchange_mode       main;
    proposal_check      obey;

    # phase 1
    proposal {
        encryption_algorithm    aes 128;
        hash_algorithm          sha1;
        authentication_method   pre_shared_key;
        lifetime time           3600 secs;
        dh_group                2;
    }
}

# phase 2
sainfo (address SITE_B_IP 4 address SITE_A_IP 4) {
    pfs_group                       2;
    lifetime                        time 3600 sec;
    encryption_algorithm            aes 128;
    authentication_algorithm        hmac_sha256, hmac_sha1;
    compression_algorithm           deflate;
}

3. This one is tricky, the IPsec kernel policy configuration. This tells the kernel IP-stack - that traffic from SITE_B_IP to (out) SITE_A_IP that is of type ipencap (IP/4) shall be of encrypted with IPsec transport type ESP. The next line is for the opposite direction.

/usr/local/etc/racoon/setkey.conf:

flush;
spdflush;
spdadd SITE_B_IP SITE_A_IP ipencap -P out ipsec esp/transport/SITE_B_IP-SITE_A_IP/require;
spdadd SITE_A_IP SITE_B_IP ipencap -P in ipsec esp/transport/SITE_A_IP-SITE_B_IP/require;

4. And of course the shared secret.

/usr/local/etc/racoon/psk.txt:

SITE_A_IP    XXXXXXXX

Then of course restart services or do a full reboot.

I prefer route-based tunnels since they work almost like a physical link, and you can use traceroute and standard tools. Your routes decide whats reachable. Policy based tunnels are a bit magic and bypasses standard routing, and I find them hard to troubleshoot.

The theory of operation here is that the tunnel itself gets encrypted, not the specific packets going trough it.

  1. Packet arrives at Site A router. Router makes route lookup and the decision to forward packet to tunnel inteface.
  2. Tunnel encapsulates packet.
  3. Packet then matches Source, Destination and Protocol number defined in IPsec kernel policy (setkey.conf), witch applies the transport encryption.
  4. Encrypted payload leaves router

ifconfig gif0 should display:

gif0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> metric 0 mtu 1280
    options=80000<LINKSTATE>
    tunnel inet SITE_B_IP --> SITE_A_IP
    inet 192.168.254.2 --> 192.168.254.1  netmask 0xffffffff 
    inet6 fe80::a3d9:9ef1:721c:a309%gif0 prefixlen 64 scopeid 0x4 
    nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
    groups: gif

A tcpdump should show the something like:

19:04:14.700751 IP SITE_A_IP > SITE_B_IP: ESP(spi=0x06b57eb9,seq=0x12), length 136
19:04:15.706837 IP SITE_B_IP > SITE_A_IP: ESP(spi=0x02a7da91,seq=0x10), length 136
19:04:15.707011 IP SITE_A_IP > SITE_B_IP: ESP(spi=0x06b57eb9,seq=0x13), length 136
19:04:16.715800 IP SITE_B_IP > SITE_A_IP: ESP(spi=0x02a7da91,seq=0x11), length 136

Good luck!

Splunk at home

Jag har lite diverse temperatur, fuktighetssensorer och annat hemma. Det är egentligen ett annat projekt i sig, men har här om veckan börjat mata Splunk med det.

Jag har inte hittat någon schysst widget än för att visa batterispänning på sensor-noderna bara.

Man kan även suga in progonoser direkt från yo.no via deras XML API.

Ingenting är för nördigt.

OpenWRT as Ad&Tracker blocker

Step 1: Install block-list script

Create a new script named /overlay/update-adblock.sh

#!/bin/ash
dummyhost="0.0.0.0"

echo -n "updating domains list..." wget -q -O- "http://pgl.yoyo.org/adservers/serverlist.php?hostformat=dnsmasq&showintro=0&mimetype=plaintext"|grep address >/var/adblock.domains sed -i s/127.0.0.1/$dummyhost/g /var/adblock.domains echo " done"

echo -n "updating adhosts list..." wget -q -O- http://winhelp2002.mvps.org/hosts.txt|grep "0.0.0.0" >/var/adblock.hosts sed -i -e 's/\r//g' /var/adblock.hosts sed -i -e 's/0.0.0.0/$dummyhost/g' /var/adblock.hosts echo " done"

echo -n "restarting dnsmasq..." /etc/init.d/dnsmasq restart echo " done"

Make it executable

chmod +x /overlay/update-adblock.sh

Force creation of files at boot and create a scheduled run (I'll use 07:23 every Sunday) with crontab -e

@reboot                 touch /var/adblock.domains /var/adblock.hosts
23 7         * * 0         /overlay/update-adblock.sh

Step 2: Add additional config for dnsmasq

Add the following line to /etc/dnsmasq.conf

conf-file=/var/adblock.domains
addn-hosts=/var/adblock.hosts

Make sure that these files exists at boot, or else dnsmasq will fail. Add the following lines to /etc/rc.local

touch /var/adblock.domains
touch /var/adblock.hosts

Step 3: Update and restart dnsmasq

Run the update manually with /overlay/update-adblock.sh

Now all your hosts on your network will be redirected to the dummyhost for the blocked domains and hosts. The lists will also be regulary updated. For further security, block outgoing DNS directly from clients (only allow the router to be source of DNS on your network)

AirPlay on OpenWRT

If you have a OpenWRT-capable router with USB and a USB Soundcard laying around, you can now use it as a AirTunes compatible reciever.

I have built packages for bcrm47xx and ar71xx type SoC's for OpenWRT Barrier Breaker

Atheros AR71xx (for example TP-Link WDR 3xxx/4xxx)
shairport_new_0.08_ar71xx.ipk

Broadcom 47xx (for example Netgear WNR3500L)
shairport_new_0.08_brcm47xx.ipk

Thanks to sm3rt for OpenWRT packaging: https://github.com/sm3rt/OpenWRT-ShairPort

If you are running Linux on your clients, you can always use PulseAudio for network audio streaming.

Update

Shairport and Shairport-sync is now included in OpenWRT 15.05. Just install the packages :)

AMD/ATI 1080p 24Hz DVI fix for XBMC

player.py

import xbmc
import xbmcgui
import subprocess
import os

class MyPlayer(xbmc.Player): def init (self): xbmc.Player.init(self)

def onPlayBackStarted(self): if xbmc.Player().isPlayingVideo(): os.system("~/.xbmc/scripts/scanset.sh &")

player=MyPlayer() VIDEO = 0

while(1): if xbmc.Player().isPlaying(): if xbmc.Player().isPlayingVideo(): VIDEO = 1 else: VIDEO = 0 xbmc.sleep(1000)

Place in ~/.xbmc/scripts/. This also relies on scanset.sh script down below.

#!/bin/bash
sleep 3
echo "running aticonfig underscan-fix"
aticonfig --set-dispattrib=dfp1,positionX:0 >/dev/null
aticonfig --set-dispattrib=dfp1,positionY:0 >/dev/null
aticonfig --set-dispattrib=dfp1,sizeX:1920 >/dev/null
aticonfig --set-dispattrib=dfp1,sizeY:1080 >/dev/null
sleep 1